Skip to content

Conversation

bjarki-andreasen
Copy link
Contributor

@bjarki-andreasen bjarki-andreasen commented May 7, 2025

Problem description:

On the nRFH20, some GPIOs are on a power domain. This power domain has to be resumed to use the GPIOs, and resuming them has to be done through IPC, thus, not from ISRs. The current solution just to use the GPIOs is to internally resume the domain from the driver, set/clear the pin, then suspend it again. This is slow and has to be done from thread context.

So, if we use SPI, and the CS is a GPIO on one of these special ports, we can't control the CS GPIO from the SPI ISR.

The solution:

Implement PM_DEVICE_RUNTIME in GPIO driver, so port can be resumed once, from thread, then used from ISR with no IPC calls needed, then suspend port. Additonally, extend SPI driver to resume the port when it is resumed, and suspend once suspended, like a bus. Lastly, extend SPI test suite to support PM_DEVICE_RUNTIME.

Now, if PM_DEVICE_RUNTIME is not used, GPIO power domain is resumed on init, and kept on. if PM_DEVICE_RUNTIME is enabled, user can get the SPI, which gets the GPIO, which gets the GPIO power domain, before the transaction.

This touches the spi_context and spi_loopback test hence why the PR is not isolated to nordic :)

Implement PM_DEVICE_RUNTIME for gpio_nrfx.c

PM is required to request/release the GPD domain if such exists
for a given GPIO instance. Without this, every single API call
will result in a requesting the GPD domain, which makes it slow
and unusable from ISRs, given GPD requires IPC. Now, user can
simply get the GPIO before using it, and put it once done,
calling the APIs from ISR while resumed.

Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
Introduce spi_context_cs_get() and spi_context_cs_put() which shall
be used from drivers to get/put the GPIO port the CS GPIO belongs to
before and after a transaction, in line with the SPI drivers pm
action hook being called.

Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
Implement pm_device_runtime support to spi_loopback test suite.

Specifically:
- call pm_device_runtime_get() on SPI bus before using SPI bus
- call pm_device_runtime_put() once SPI bus is no longer needed.
  This is after transceive has been performed, or after calling
  spi_release_dt() after a transceive has been performed.

This addition has no affect if PM_DEVICE_RUNTIME is not enabled
on a board/test case basis.

Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
@bjarki-andreasen
Copy link
Contributor Author

ping @anangl

Copy link
Member

@anangl anangl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good improvement. One minor comment only.

@@ -402,7 +401,7 @@ static void finish_transaction(const struct device *dev, int error)
spi_context_complete(ctx, dev, error);
dev_data->busy = false;

finalize_spi_transaction(dev, true);
finalize_spi_transaction(dev, (dev_data->ctx.config->operation & SPI_HOLD_ON_CS) > 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes related to pm_device_runtime_put_async() should be done in a separate commit, with some explanation in the commit message.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deal, I already forgot exactly why it was moved here :D

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved to separate commit and added comment to driver

Implement calling spi_context_cs_get_all() and
spi_context_cs_put_all() in line with pm resume/suspend.

Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
In case the SPI transaction has SPI_HOLD_ON_CS set, we need to keep
SPI resumed until spi_release() is called. This is required as we
now need to keep the CS GPIO port resumed until transaction is
complete.

Suspending CS GPIO is not allowed from ISR in some cases (H20 fast
GPIO instance) so we have to defer CS GPIO suspend to some thread
context (put_async or spi_release()).

Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
Add CS GPIO to nrf54h20dk/nrf54h20/cpuapp which is connected to
PORT which is in the "fast domain". The fast domain needs to be
resumed from thread context given it requires IPC communication.

This thus ensures that GPIO can be used with and without
PM_DEVICE_RUNTIME enabled.

Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
Copy link

@bjarki-andreasen
Copy link
Contributor Author

ping @masz-nordic :)

@carlescufi carlescufi assigned masz-nordic and unassigned tbursztyka May 14, 2025
@kartben kartben merged commit 726fd18 into zephyrproject-rtos:main May 14, 2025
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants