[PATCH] drm/panfrost: Unprepare clocks on system suspend

From: Michał Kopeć

Date: Sat Oct 03 2026 - 15:48:29 EST


With GPU_PM_CLK_DIS, system suspend only disables the GPU clocks, which
leaves them prepared. Some providers power a clock down only in
unprepare: MediaTek PLLs are switched off in mtk_pll_unprepare(). On
MT8188 this keeps MFGPLL running through suspend, and TF-A refuses the
26 MHz-off state because of it:

suspend: bus26m total blocked = 0x40040000

The SoC then only reaches a shallower sleep state, never signals sleep
to the EC, and the EC reports a sleep hang and wakes the system.

Use clk_disable_unprepare() on suspend and clk_prepare_enable() on
resume. Both run in process context, so preparing is allowed.

Fixes: 56e76c017918 ("drm/panfrost: Implement ability to turn on/off GPU clocks in suspend")
Signed-off-by: Michał Kopeć <michal@nozomi.space>
---
drivers/gpu/drm/panfrost/panfrost_device.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c
index 485349faf2511..3f1a8109a79a4 100644
--- a/drivers/gpu/drm/panfrost/panfrost_device.c
+++ b/drivers/gpu/drm/panfrost/panfrost_device.c
@@ -507,12 +507,12 @@ static int panfrost_device_resume(struct device *dev)
}

if (pfdev->comp->pm_features & BIT(GPU_PM_CLK_DIS)) {
- ret = clk_enable(pfdev->clock);
+ ret = clk_prepare_enable(pfdev->clock);
if (ret)
goto err_clk;

if (pfdev->bus_clock) {
- ret = clk_enable(pfdev->bus_clock);
+ ret = clk_prepare_enable(pfdev->bus_clock);
if (ret)
goto err_bus_clk;
}
@@ -526,10 +526,10 @@ static int panfrost_device_resume(struct device *dev)

err_resume:
if (pfdev->comp->pm_features & BIT(GPU_PM_CLK_DIS) && pfdev->bus_clock)
- clk_disable(pfdev->bus_clock);
+ clk_disable_unprepare(pfdev->bus_clock);
err_bus_clk:
if (pfdev->comp->pm_features & BIT(GPU_PM_CLK_DIS))
- clk_disable(pfdev->clock);
+ clk_disable_unprepare(pfdev->clock);
err_clk:
if (pfdev->comp->pm_features & BIT(GPU_PM_VREG_OFF))
dev_pm_opp_set_opp(dev, NULL);
@@ -545,11 +545,15 @@ static int panfrost_device_suspend(struct device *dev)
if (ret)
return ret;

+ /*
+ * Unprepare as well: some clock providers, e.g. MediaTek PLLs, only
+ * power down in unprepare, and a running GPU PLL blocks system sleep.
+ */
if (pfdev->comp->pm_features & BIT(GPU_PM_CLK_DIS)) {
if (pfdev->bus_clock)
- clk_disable(pfdev->bus_clock);
+ clk_disable_unprepare(pfdev->bus_clock);

- clk_disable(pfdev->clock);
+ clk_disable_unprepare(pfdev->clock);
}

if (pfdev->comp->pm_features & BIT(GPU_PM_VREG_OFF))

base-commit: 70456f05d4b6396b22048c4b8cd3cb98ecf9f9e3
--
2.55.0