[PATCH 3/3] media: mali-c55: Keep ISP powered while IRQ wake is armed
From: Linus Walleij
Date: Tue Sep 29 2026 - 08:08:51 EST
System suspend enables IRQ wake and then calls pm_runtime_force_suspend().
For an active ISP this asserts its resets and disables its clocks, so it
can no longer generate frame interrupts. An already runtime-suspended ISP
is left powered off as well.
Take a runtime PM reference before arming IRQ wake and retain it until
resume. This powers up an idle ISP and keeps an active ISP's configuration
intact. Release the reference if arming wake fails, and use the PM wake
policy in both suspend and resume to balance the reference. Continue to
use forced runtime suspend and resume when wake is disabled.
Use the forced power-down path for hibernation freeze and power-off even
when wake is enabled. Capture must not remain active while a hibernation
image is created.
Wake events require a configured stream and an input source that
remains operational during system sleep.
The internal TPG shares the ISP's power state. External sensor and
receiver drivers will need their own system-sleep wake support.
Assisted-by: LLM
Signed-off-by: Linus Walleij <linusw@xxxxxxxxxx>
---
.../media/platform/arm/mali-c55/mali-c55-core.c | 38 ++++++++++++++--------
1 file changed, 25 insertions(+), 13 deletions(-)
diff --git a/drivers/media/platform/arm/mali-c55/mali-c55-core.c b/drivers/media/platform/arm/mali-c55/mali-c55-core.c
index 07267b79801b..2629bb3aa628 100644
--- a/drivers/media/platform/arm/mali-c55/mali-c55-core.c
+++ b/drivers/media/platform/arm/mali-c55/mali-c55-core.c
@@ -756,31 +756,43 @@ static int __maybe_unused mali_c55_suspend(struct device *dev)
struct mali_c55 *mali_c55 = dev_get_drvdata(dev);
int ret;
- if (device_may_wakeup(dev)) {
- ret = enable_irq_wake(mali_c55->irqnum);
- if (ret)
- return ret;
- }
+ if (!device_may_wakeup(dev))
+ return pm_runtime_force_suspend(dev);
- ret = pm_runtime_force_suspend(dev);
- if (ret && device_may_wakeup(dev))
- disable_irq_wake(mali_c55->irqnum);
+ /* Keep the ISP clocked and out of reset while it can wake the system. */
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
+ return ret;
- return ret;
+ ret = enable_irq_wake(mali_c55->irqnum);
+ if (ret) {
+ pm_runtime_put_autosuspend(dev);
+ return ret;
+ }
+
+ return 0;
}
static int __maybe_unused mali_c55_resume(struct device *dev)
{
struct mali_c55 *mali_c55 = dev_get_drvdata(dev);
- if (device_may_wakeup(dev))
- disable_irq_wake(mali_c55->irqnum);
+ if (!device_may_wakeup(dev))
+ return pm_runtime_force_resume(dev);
- return pm_runtime_force_resume(dev);
+ disable_irq_wake(mali_c55->irqnum);
+ pm_runtime_put_autosuspend(dev);
+
+ return 0;
}
static const struct dev_pm_ops mali_c55_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(mali_c55_suspend, mali_c55_resume)
+ .suspend = pm_sleep_ptr(mali_c55_suspend),
+ .resume = pm_sleep_ptr(mali_c55_resume),
+ .freeze = pm_sleep_ptr(pm_runtime_force_suspend),
+ .thaw = pm_sleep_ptr(pm_runtime_force_resume),
+ .poweroff = pm_sleep_ptr(pm_runtime_force_suspend),
+ .restore = pm_sleep_ptr(pm_runtime_force_resume),
SET_RUNTIME_PM_OPS(mali_c55_runtime_suspend, mali_c55_runtime_resume,
NULL)
};
--
2.55.0