[PATCH] spi: atmel-quadspi: balance runtime PM and pclk across system sleep
Karl Mehltretter
kmehltretter at gmail.com
Tue Sep 22 18:29:50 PDT 2026
On the controllers with a generic clock (SAMA7G5, SAMA7D65, SAM9X7 and
LAN969x), atmel_qspi_suspend() takes a runtime PM reference and returns
without dropping it or suspending the device. It disables the peripheral
clock directly. atmel_qspi_resume() only prepares the peripheral clock
and then reinitializes the controller with that clock still off.
On a SAM9X75 Curiosity board, the tested standby and mem resumes
failed:
atmel_qspi f0014000.spi: PM: failed to resume: error -110
spi-nor spi0.0: resume() failed
Reading the flash afterwards returned no data. The runtime usage count
grew by one with each cycle, and the second suspend disabled the
peripheral clock again:
WARNING: drivers/clk/clk.c:1257 at clk_core_disable+0x6c/0xcc
qspi_clk already disabled
Use the same runtime PM sequence as the other variants. Suspend disables
the controller and forces a runtime suspend. Resume forces a runtime
resume, which enables the peripheral clock, before it runs the init
callback, and drops the reference afterwards. With this change the
tested resumes succeed on the board in both modes, the controller
returns to runtime suspend, and the flash reads back.
Fixes: 5af42209a4d2 ("spi: atmel-quadspi: Add support for sama7g5 QSPI")
Reported-by: Sashiko <sashiko-bot at kernel.org>
Closes: https://sashiko.dev/#/patchset/20260709112006.390742-1-robert.marko%40sartura.hr?part=3
Cc: stable at vger.kernel.org
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <kmehltretter at gmail.com>
---
A/B tested on a SAM9X75 Curiosity board, two real suspend cycles each
in standby and mem, woken by the RTC, with a read of the on-board
SST26VF064B after every resume:
without patch with patch
resume error -110 ok
runtime status / usage active / 1, then 2 suspended / 0
second suspend WARNING, qspi_clk clean
already disabled
flash read no data matches
pm_test=devices gives the same result. QEMU's sam9x75-curiosity model
shows the same runtime PM and clock state. Its OSPI does not depend on
pclk, so there reads succeed in both cases.
Not tested: SAMA7G5, SAMA7D65 and LAN969x.
Unrelated to this patch: with and without it, each tested OSPI flash
read on SAM9X75 printed "BUG: sleeping function called from invalid
context" from at_xdmac_issue_pending().
drivers/spi/atmel-quadspi.c | 24 +++++++++++++-----------
1 file changed, 13 insertions(+), 11 deletions(-)
diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
index ec19fa0180f00..96ed734b56218 100644
--- a/drivers/spi/atmel-quadspi.c
+++ b/drivers/spi/atmel-quadspi.c
@@ -1590,12 +1590,14 @@ static int atmel_qspi_suspend(struct device *dev)
if (aq->caps->has_gclk) {
ret = atmel_qspi_sama7g5_suspend(aq);
- clk_disable_unprepare(aq->pclk);
- return ret;
+ if (ret) {
+ pm_runtime_put_autosuspend(dev);
+ return ret;
+ }
+ } else {
+ atmel_qspi_write(QSPI_CR_QSPIDIS, aq, QSPI_CR);
}
- atmel_qspi_write(QSPI_CR_QSPIDIS, aq, QSPI_CR);
-
pm_runtime_mark_last_busy(dev);
pm_runtime_force_suspend(dev);
@@ -1621,20 +1623,20 @@ static int atmel_qspi_resume(struct device *dev)
return ret;
}
- if (aq->caps->has_gclk)
- return aq->caps->init(aq);
-
ret = pm_runtime_force_resume(dev);
if (ret < 0)
return ret;
- atmel_qspi_init(aq);
-
- atmel_qspi_write(aq->scr, aq, QSPI_SCR);
+ if (aq->caps->has_gclk) {
+ ret = aq->caps->init(aq);
+ } else {
+ atmel_qspi_init(aq);
+ atmel_qspi_write(aq->scr, aq, QSPI_SCR);
+ }
pm_runtime_put_autosuspend(dev);
- return 0;
+ return ret;
}
static int atmel_qspi_runtime_suspend(struct device *dev)
--
2.53.0
More information about the linux-arm-kernel
mailing list