@@ -14,6 +14,9 @@ LOG_MODULE_REGISTER(spi_cc23x0, CONFIG_SPI_LOG_LEVEL);
14
14
#include <zephyr/drivers/pinctrl.h>
15
15
#include <zephyr/drivers/spi.h>
16
16
#include <zephyr/irq.h>
17
+ #include <zephyr/pm/device.h>
18
+ #include <zephyr/pm/device_runtime.h>
19
+ #include <zephyr/pm/policy.h>
17
20
#include <zephyr/sys/util.h>
18
21
19
22
#include <driverlib/clkctl.h>
@@ -63,6 +66,22 @@ struct spi_cc23x0_data {
63
66
#endif
64
67
};
65
68
69
+ static inline void spi_cc23x0_pm_policy_state_lock_get (void )
70
+ {
71
+ #ifdef CONFIG_PM_DEVICE
72
+ pm_policy_state_lock_get (PM_STATE_RUNTIME_IDLE , PM_ALL_SUBSTATES );
73
+ pm_policy_state_lock_get (PM_STATE_STANDBY , PM_ALL_SUBSTATES );
74
+ #endif
75
+ }
76
+
77
+ static inline void spi_cc23x0_pm_policy_state_lock_put (void )
78
+ {
79
+ #ifdef CONFIG_PM_DEVICE
80
+ pm_policy_state_lock_put (PM_STATE_STANDBY , PM_ALL_SUBSTATES );
81
+ pm_policy_state_lock_put (PM_STATE_RUNTIME_IDLE , PM_ALL_SUBSTATES );
82
+ #endif
83
+ }
84
+
66
85
static void spi_cc23x0_isr (const struct device * dev )
67
86
{
68
87
const struct spi_cc23x0_config * cfg = dev -> config ;
@@ -307,6 +326,8 @@ static int spi_cc23x0_transceive(const struct device *dev,
307
326
};
308
327
#endif
309
328
329
+ spi_cc23x0_pm_policy_state_lock_get ();
330
+
310
331
spi_context_lock (ctx , false, NULL , NULL , config );
311
332
312
333
ret = spi_cc23x0_configure (dev , config );
@@ -339,16 +360,22 @@ static int spi_cc23x0_transceive(const struct device *dev,
339
360
block_cfg_rx .dest_addr_adj = DMA_ADDR_ADJ_INCREMENT ;
340
361
block_cfg_rx .block_size = SPI_CC23_DFS * data -> tx_len_left ;
341
362
342
- ret = dma_config (cfg -> dma_dev , cfg -> dma_channel_tx , & dma_cfg_tx );
363
+ ret = pm_device_runtime_get (cfg -> dma_dev );
343
364
if (ret ) {
344
- LOG_ERR ("Failed to configure DMA TX channel" );
365
+ LOG_ERR ("Failed to resume DMA (%d)" , ret );
345
366
goto int_disable ;
346
367
}
347
368
369
+ ret = dma_config (cfg -> dma_dev , cfg -> dma_channel_tx , & dma_cfg_tx );
370
+ if (ret ) {
371
+ LOG_ERR ("Failed to configure DMA TX channel (%d)" , ret );
372
+ goto dma_suspend ;
373
+ }
374
+
348
375
ret = dma_config (cfg -> dma_dev , cfg -> dma_channel_rx , & dma_cfg_rx );
349
376
if (ret ) {
350
- LOG_ERR ("Failed to configure DMA RX channel" );
351
- goto int_disable ;
377
+ LOG_ERR ("Failed to configure DMA RX channel (%d)" , ret );
378
+ goto dma_suspend ;
352
379
}
353
380
354
381
/* Disable DMA triggers */
@@ -364,14 +391,19 @@ static int spi_cc23x0_transceive(const struct device *dev,
364
391
ret = spi_context_wait_for_completion (& data -> ctx );
365
392
if (ret ) {
366
393
LOG_ERR ("SPI transfer failed (%d)" , ret );
367
- goto int_disable ;
394
+ goto dma_suspend ;
368
395
}
369
396
370
397
spi_context_update_tx (ctx , SPI_CC23_DFS , data -> tx_len_left );
371
398
spi_context_update_rx (ctx , SPI_CC23_DFS , data -> tx_len_left );
372
399
373
400
LOG_DBG ("SPI transfer completed" );
374
401
402
+ dma_suspend :
403
+ ret = pm_device_runtime_put (cfg -> dma_dev );
404
+ if (ret ) {
405
+ LOG_ERR ("Failed to suspend DMA (%d)" , ret );
406
+ }
375
407
int_disable :
376
408
SPIDisableInt (cfg -> base , SPI_CC23_INT_MASK );
377
409
#else
@@ -388,6 +420,7 @@ static int spi_cc23x0_transceive(const struct device *dev,
388
420
389
421
ctx_release :
390
422
spi_context_release (ctx , ret );
423
+ spi_cc23x0_pm_policy_state_lock_put ();
391
424
return ret ;
392
425
}
393
426
@@ -434,6 +467,12 @@ static int spi_cc23x0_init(const struct device *dev)
434
467
LOG_ERR ("DMA not ready" );
435
468
return - ENODEV ;
436
469
}
470
+
471
+ ret = pm_device_runtime_enable (cfg -> dma_dev );
472
+ if (ret ) {
473
+ LOG_ERR ("Failed to enable DMA runtime PM" );
474
+ return ret ;
475
+ }
437
476
#endif
438
477
439
478
ret = spi_context_cs_configure_all (& data -> ctx );
@@ -446,6 +485,29 @@ static int spi_cc23x0_init(const struct device *dev)
446
485
return 0 ;
447
486
}
448
487
488
+ #ifdef CONFIG_PM_DEVICE
489
+
490
+ static int spi_cc23x0_pm_action (const struct device * dev , enum pm_device_action action )
491
+ {
492
+ const struct spi_cc23x0_config * cfg = dev -> config ;
493
+ struct spi_cc23x0_data * data = dev -> data ;
494
+
495
+ switch (action ) {
496
+ case PM_DEVICE_ACTION_SUSPEND :
497
+ SPIDisable (cfg -> base );
498
+ CLKCTLDisable (CLKCTL_BASE , CLKCTL_SPI0 );
499
+ return 0 ;
500
+ case PM_DEVICE_ACTION_RESUME :
501
+ /* Force SPI to be reconfigured at next transfer */
502
+ data -> ctx .config = NULL ;
503
+ return 0 ;
504
+ default :
505
+ return - ENOTSUP ;
506
+ }
507
+ }
508
+
509
+ #endif /* CONFIG_PM_DEVICE */
510
+
449
511
#ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
450
512
#define SPI_CC23X0_DMA_INIT (n ) \
451
513
.dma_dev = DEVICE_DT_GET(TI_CC23X0_DT_INST_DMA_CTLR(n, tx)), \
@@ -459,6 +521,7 @@ static int spi_cc23x0_init(const struct device *dev)
459
521
460
522
#define SPI_CC23X0_INIT (n ) \
461
523
PINCTRL_DT_INST_DEFINE(n); \
524
+ PM_DEVICE_DT_INST_DEFINE(n, spi_cc23x0_pm_action); \
462
525
\
463
526
static void spi_irq_config_func_##n(void) \
464
527
{ \
@@ -484,7 +547,7 @@ static int spi_cc23x0_init(const struct device *dev)
484
547
\
485
548
DEVICE_DT_INST_DEFINE(n, \
486
549
spi_cc23x0_init, \
487
- NULL, \
550
+ PM_DEVICE_DT_INST_GET(n), \
488
551
&spi_cc23x0_data_##n, \
489
552
&spi_cc23x0_config_##n, \
490
553
POST_KERNEL, \
0 commit comments