rk8xx PMIC code uses SYS_OFF_MODE_POWER_OFF_PREPARE instead of SYS_OFF_MODE_POWER_OFF. The later one should be used, but invokes the shutdown handler with interrupts already being turned off. This does not cope well with SPI.
Designs
Child items
...
Show closed items
Linked items
0
Link issues together to show that they're related.
Learn more.
The rk8xx PMIC driver calls regmap_update_bits to shutdown the system, which first reads the current register value, then sets the required shutdown bits in the value that was read and finally writes the new register value. For SPI a custom regmap handler is implemented in rk8xx-spi.
The handler calls spi_sync() for reading / writing to the SPI bus. spi_sync() uses wait_for_completion() internally, which is not allowed in atomic context. We can avoid the read part, by just returning a fixed value at shutdown time. We basically do not care about the other bits if the system shuts down anyways. For writing there also exists spi_async(). Calling that queues the SPI write instruction without waiting for its completions.
The problem is, that the actual sending happens via a worker thread in the next step. But we are very late in the shutdown process and thread scheduling has already been stopped. The system is not supposed to leave the atomic context after this function returns. Thus calling spi_async() results in the register not being written to at all. For spi-mem there is also an internal spi_flush_queue() function, which flushes any async work. But that function effectively results in spi_async being the same as spi_sync and does not help at all.
Right now it seems this requires fundamental changes to the SPI framework, similar to the I2C framework's atomic support.