1313#include <zephyr/drivers/dma.h>
1414#include <zephyr/drivers/clock_control.h>
1515#include <zephyr/logging/log.h>
16+ #include <zephyr/pm/device.h>
17+ #include <zephyr/pm/policy.h>
1618#include <zephyr/types.h>
1719#include "rsi_rom_udma.h"
1820#include "rsi_rom_udma_wrapper.h"
@@ -39,6 +41,7 @@ struct dma_siwx91x_channel_info {
3941 void * cb_data ; /* User callback data */
4042 RSI_UDMA_DESC_T * sg_desc_addr_info ; /* Scatter-Gather table start address */
4143 enum dma_xfer_dir xfer_direction ; /* mem<->mem ot per<->mem */
44+ bool channel_active ; /* Channel active flag */
4245};
4346
4447struct dma_siwx91x_config {
@@ -60,6 +63,16 @@ struct dma_siwx91x_data {
6063 */
6164};
6265
66+ static void siwx91x_dma_pm_policy_state_lock_get (void )
67+ {
68+ pm_policy_state_lock_get (PM_STATE_SUSPEND_TO_IDLE , PM_ALL_SUBSTATES );
69+ }
70+
71+ static void siwx91x_dma_pm_policy_state_lock_put (void )
72+ {
73+ pm_policy_state_lock_put (PM_STATE_SUSPEND_TO_IDLE , PM_ALL_SUBSTATES );
74+ }
75+
6376static enum dma_xfer_dir siwx91x_transfer_direction (uint32_t dir )
6477{
6578 if (dir == MEMORY_TO_MEMORY ) {
@@ -482,7 +495,17 @@ static int siwx91x_dma_start(const struct device *dev, uint32_t channel)
482495 return - EINVAL ;
483496 }
484497
498+ /* Get the power management policy state lock */
499+ if (!data -> zephyr_channel_info [channel ].channel_active ) {
500+ siwx91x_dma_pm_policy_state_lock_get ();
501+ data -> zephyr_channel_info [channel ].channel_active = true;
502+ }
503+
485504 if (RSI_UDMA_ChannelEnable (udma_handle , channel ) != 0 ) {
505+ if (data -> zephyr_channel_info [channel ].channel_active ) {
506+ siwx91x_dma_pm_policy_state_lock_put ();
507+ data -> zephyr_channel_info [channel ].channel_active = false;
508+ }
486509 return - EINVAL ;
487510 }
488511
@@ -510,6 +533,11 @@ static int siwx91x_dma_stop(const struct device *dev, uint32_t channel)
510533 return - EIO ;
511534 }
512535
536+ if (data -> zephyr_channel_info [channel ].channel_active ) {
537+ siwx91x_dma_pm_policy_state_lock_put ();
538+ data -> zephyr_channel_info [channel ].channel_active = false;
539+ }
540+
513541 return 0 ;
514542}
515543
@@ -560,8 +588,7 @@ bool siwx91x_dma_chan_filter(const struct device *dev, int channel, void *filter
560588 }
561589}
562590
563- /* Function to initialize DMA peripheral */
564- static int siwx91x_dma_init (const struct device * dev )
591+ static int dma_siwx91x_pm_action (const struct device * dev , enum pm_device_action action )
565592{
566593 const struct dma_siwx91x_config * cfg = dev -> config ;
567594 struct dma_siwx91x_data * data = dev -> data ;
@@ -573,25 +600,45 @@ static int siwx91x_dma_init(const struct device *dev)
573600 };
574601 int ret ;
575602
576- ret = clock_control_on (cfg -> clock_dev , cfg -> clock_subsys );
577- if (ret ) {
578- return ret ;
579- }
603+ switch (action ) {
604+ case PM_DEVICE_ACTION_RESUME :
605+ break ;
606+ case PM_DEVICE_ACTION_SUSPEND :
607+ break ;
608+ case PM_DEVICE_ACTION_TURN_ON :
609+ ret = clock_control_on (cfg -> clock_dev , cfg -> clock_subsys );
610+ if (ret < 0 && ret != - EALREADY ) {
611+ return ret ;
612+ }
580613
581- udma_handle = UDMAx_Initialize (& udma_resources , udma_resources .desc , NULL ,
582- (uint32_t * )& data -> udma_handle );
583- if (udma_handle != & data -> udma_handle ) {
584- return - EINVAL ;
614+ udma_handle = UDMAx_Initialize (& udma_resources , udma_resources .desc , NULL ,
615+ (uint32_t * )& data -> udma_handle );
616+ if (udma_handle != & data -> udma_handle ) {
617+ return - EINVAL ;
618+ }
619+
620+ if (UDMAx_DMAEnable (& udma_resources , udma_handle ) != 0 ) {
621+ return - EBUSY ;
622+ }
623+ break ;
624+ case PM_DEVICE_ACTION_TURN_OFF :
625+ break ;
626+ default :
627+ return - ENOTSUP ;
585628 }
586629
630+ return 0 ;
631+ }
632+
633+ /* Function to initialize DMA peripheral */
634+ static int siwx91x_dma_init (const struct device * dev )
635+ {
636+ const struct dma_siwx91x_config * cfg = dev -> config ;
637+
587638 /* Connect the DMA interrupt */
588639 cfg -> irq_configure ();
589640
590- if (UDMAx_DMAEnable (& udma_resources , udma_handle ) != 0 ) {
591- return - EBUSY ;
592- }
593-
594- return 0 ;
641+ return pm_device_driver_init (dev , dma_siwx91x_pm_action );
595642}
596643
597644static void siwx91x_dma_isr (const struct device * dev )
@@ -639,6 +686,10 @@ static void siwx91x_dma_isr(const struct device *dev)
639686 dev , data -> zephyr_channel_info [channel ].cb_data , channel , 0 );
640687 }
641688 sys_write32 (BIT (channel ), (mem_addr_t )& cfg -> reg -> UDMA_DONE_STATUS_REG );
689+ if (data -> zephyr_channel_info [channel ].channel_active ) {
690+ siwx91x_dma_pm_policy_state_lock_put ();
691+ data -> zephyr_channel_info [channel ].channel_active = false;
692+ }
642693 } else {
643694 /* Call UDMA ROM IRQ handler. */
644695 ROMAPI_UDMA_WRAPPER_API -> uDMAx_IRQHandler (& udma_resources , udma_resources .desc ,
@@ -701,7 +752,10 @@ static DEVICE_API(dma, siwx91x_dma_api) = {
701752 (siwx91x_dma_chan_desc##inst)), \
702753 .irq_configure = siwx91x_dma_irq_configure_##inst, \
703754 }; \
704- DEVICE_DT_INST_DEFINE(inst, siwx91x_dma_init, NULL, &dma_data_##inst, &dma_cfg_##inst, \
705- POST_KERNEL, CONFIG_DMA_INIT_PRIORITY, &siwx91x_dma_api);
755+ PM_DEVICE_DT_INST_DEFINE(inst, dma_siwx91x_pm_action); \
756+ DEVICE_DT_INST_DEFINE(inst, siwx91x_dma_init, PM_DEVICE_DT_INST_GET(inst), \
757+ &dma_data_##inst, &dma_cfg_##inst, POST_KERNEL, \
758+ CONFIG_DMA_INIT_PRIORITY, \
759+ &siwx91x_dma_api);
706760
707761DT_INST_FOREACH_STATUS_OKAY (SIWX91X_DMA_INIT )
0 commit comments