1010#include <zephyr/drivers/gpio.h>
1111#include <soc.h>
1212#include <nrfx_spis.h>
13+ #include <zephyr/pm/device.h>
14+ #include <zephyr/pm/device_runtime.h>
1315
1416#include <zephyr/logging/log.h>
1517#include <zephyr/irq.h>
@@ -175,6 +177,8 @@ static int transceive(const struct device *dev,
175177 const struct spi_buf * rx_buf = rx_bufs ? rx_bufs -> buffers : NULL ;
176178 int error ;
177179
180+ pm_device_runtime_get (dev );
181+
178182 spi_context_lock (& dev_data -> ctx , asynchronous , cb , userdata , spi_cfg );
179183
180184 error = configure (dev , spi_cfg );
@@ -282,7 +286,49 @@ static void event_handler(const nrfx_spis_evt_t *p_event, void *p_context)
282286 if (p_event -> evt_type == NRFX_SPIS_XFER_DONE ) {
283287 spi_context_complete (& dev_data -> ctx , dev_data -> dev ,
284288 p_event -> rx_amount );
289+
290+ pm_device_runtime_put (dev_data -> dev );
291+ }
292+ }
293+
294+ static void spi_nrfx_suspend (const struct device * dev )
295+ {
296+ const struct spi_nrfx_config * dev_config = dev -> config ;
297+
298+ if (dev_config -> wake_gpio .port == NULL ) {
299+ nrf_spis_disable (dev_config -> spis .p_reg );
300+ }
301+
302+ (void )pinctrl_apply_state (dev_config -> pcfg , PINCTRL_STATE_SLEEP );
303+ }
304+
305+ static void spi_nrfx_resume (const struct device * dev )
306+ {
307+ const struct spi_nrfx_config * dev_config = dev -> config ;
308+
309+ (void )pinctrl_apply_state (dev_config -> pcfg , PINCTRL_STATE_DEFAULT );
310+
311+ if (dev_config -> wake_gpio .port == NULL ) {
312+ nrf_spis_enable (dev_config -> spis .p_reg );
313+ }
314+ }
315+
316+ static int spi_nrfx_pm_action (const struct device * dev , enum pm_device_action action )
317+ {
318+ switch (action ) {
319+ case PM_DEVICE_ACTION_SUSPEND :
320+ spi_nrfx_suspend (dev );
321+ return 0 ;
322+
323+ case PM_DEVICE_ACTION_RESUME :
324+ spi_nrfx_resume (dev );
325+ return 0 ;
326+
327+ default :
328+ break ;
285329 }
330+
331+ return - ENOTSUP ;
286332}
287333
288334static int spi_nrfx_init (const struct device * dev )
@@ -308,6 +354,16 @@ static int spi_nrfx_init(const struct device *dev)
308354 return - EBUSY ;
309355 }
310356
357+ /* When the WAKE line is used, the SPIS peripheral is enabled
358+ * only after the master signals that it wants to perform a
359+ * transfer and it is disabled right after the transfer is done.
360+ * Waiting for the WAKE line to go high, what can be done using
361+ * the GPIO PORT event, instead of just waiting for the transfer
362+ * with the SPIS peripheral enabled, significantly reduces idle
363+ * power consumption.
364+ */
365+ nrf_spis_disable (dev_config -> spis .p_reg );
366+
311367 if (dev_config -> wake_gpio .port ) {
312368 if (!gpio_is_ready_dt (& dev_config -> wake_gpio )) {
313369 return - ENODEV ;
@@ -332,21 +388,11 @@ static int spi_nrfx_init(const struct device *dev)
332388 if (err < 0 ) {
333389 return err ;
334390 }
335-
336- /* When the WAKE line is used, the SPIS peripheral is enabled
337- * only after the master signals that it wants to perform a
338- * transfer and it is disabled right after the transfer is done.
339- * Waiting for the WAKE line to go high, what can be done using
340- * the GPIO PORT event, instead of just waiting for the transfer
341- * with the SPIS peripheral enabled, significantly reduces idle
342- * power consumption.
343- */
344- nrf_spis_disable (dev_config -> spis .p_reg );
345391 }
346392
347393 spi_context_unlock_unconditionally (& dev_data -> ctx );
348394
349- return 0 ;
395+ return pm_device_driver_init ( dev , spi_nrfx_pm_action ) ;
350396}
351397
352398/*
@@ -394,9 +440,10 @@ static int spi_nrfx_init(const struct device *dev)
394440 BUILD_ASSERT(!DT_NODE_HAS_PROP(SPIS(idx), wake_gpios) || \
395441 !(DT_GPIO_FLAGS(SPIS(idx), wake_gpios) & GPIO_ACTIVE_LOW),\
396442 "WAKE line must be configured as active high"); \
443+ PM_DEVICE_DT_DEFINE(SPIS(idx), spi_nrfx_pm_action, 1); \
397444 SPI_DEVICE_DT_DEFINE(SPIS(idx), \
398445 spi_nrfx_init, \
399- NULL, \
446+ PM_DEVICE_DT_GET(SPIS(idx)), \
400447 &spi_##idx##_data, \
401448 &spi_##idx##z_config, \
402449 POST_KERNEL, \
0 commit comments