Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 41 additions & 17 deletions drivers/dma/dma_silabs_siwx91x.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <zephyr/drivers/dma.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/logging/log.h>
#include <zephyr/pm/device.h>
#include <zephyr/types.h>
#include "rsi_rom_udma.h"
#include "rsi_rom_udma_wrapper.h"
Expand Down Expand Up @@ -560,8 +561,7 @@ bool siwx91x_dma_chan_filter(const struct device *dev, int channel, void *filter
}
}

/* Function to initialize DMA peripheral */
static int siwx91x_dma_init(const struct device *dev)
static int dma_siwx91x_pm_action(const struct device *dev, enum pm_device_action action)
{
const struct dma_siwx91x_config *cfg = dev->config;
struct dma_siwx91x_data *data = dev->data;
Expand All @@ -573,27 +573,48 @@ static int siwx91x_dma_init(const struct device *dev)
};
int ret;

ret = clock_control_on(cfg->clock_dev, cfg->clock_subsys);
if (ret) {
return ret;
}
switch (action) {
case PM_DEVICE_ACTION_RESUME:
break;
case PM_DEVICE_ACTION_SUSPEND:
break;
case PM_DEVICE_ACTION_TURN_ON:
ret = clock_control_on(cfg->clock_dev, cfg->clock_subsys);
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to turn this clock in PM_DEVICE_ACTION_TURN_ON, or this can be done later in PM_DEVICE_ACTION_RESUME?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it was discussed to place it here

if (ret < 0 && ret != -EALREADY) {
return ret;
}

udma_handle = UDMAx_Initialize(&udma_resources, udma_resources.desc, NULL,
(uint32_t *)&data->udma_handle);
if (udma_handle != &data->udma_handle) {
return -EINVAL;
}
udma_handle = UDMAx_Initialize(&udma_resources, udma_resources.desc, NULL,
(uint32_t *)&data->udma_handle);
Copy link
Contributor

@jerome-pouiller jerome-pouiller Sep 5, 2025

Choose a reason for hiding this comment

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

Do you think UDMAx_Initialize() should be called on PM_DEVICE_ACTION_RESUME or on PM_DEVICE_ACTION_TURN_ON?

I believe Device runtime PM will only play with PM_DEVICE_ACTION_SUSPEND. PM_DEVICE_ACTION_SUSPEND may stop the clocks and the regulator but I believe it will retains the registers.

I assume System Managed PM (or power domains) won't retains the registers but it will call PM_DEVICE_ACTION_TURN_OFF and PM_DEVICE_ACTION_TURN_ON. So, UDMAx_Initialize() should be only done in PM_DEVICE_ACTION_TURN_ON.

@Martinhoff-maker, @asmellby, can you confirm my understanding?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

addressed

if (udma_handle != &data->udma_handle) {
return -EINVAL;
}

/* Connect the DMA interrupt */
cfg->irq_configure();
cfg->irq_configure();

if (UDMAx_DMAEnable(&udma_resources, udma_handle) != 0) {
return -EBUSY;
if (UDMAx_DMAEnable(&udma_resources, udma_handle) != 0) {
return -EBUSY;
}
break;
case PM_DEVICE_ACTION_TURN_OFF:
ret = clock_control_off(cfg->clock_dev, cfg->clock_subsys);
if (ret < 0 && ret != -EALREADY) {
return ret;
}
break;
default:
return -ENOTSUP;
}

return 0;
}

/* Function to initialize DMA peripheral */
static int siwx91x_dma_init(const struct device *dev)
{
return pm_device_driver_init(dev, dma_siwx91x_pm_action);
}

static void siwx91x_dma_isr(const struct device *dev)
{
const struct dma_siwx91x_config *cfg = dev->config;
Expand Down Expand Up @@ -701,7 +722,10 @@ static DEVICE_API(dma, siwx91x_dma_api) = {
(siwx91x_dma_chan_desc##inst)), \
.irq_configure = siwx91x_dma_irq_configure_##inst, \
}; \
DEVICE_DT_INST_DEFINE(inst, siwx91x_dma_init, NULL, &dma_data_##inst, &dma_cfg_##inst, \
POST_KERNEL, CONFIG_DMA_INIT_PRIORITY, &siwx91x_dma_api);
PM_DEVICE_DT_INST_DEFINE(inst, dma_siwx91x_pm_action); \
DEVICE_DT_INST_DEFINE(inst, siwx91x_dma_init, PM_DEVICE_DT_INST_GET(inst), \
&dma_data_##inst, &dma_cfg_##inst, POST_KERNEL, \
CONFIG_DMA_INIT_PRIORITY, \
&siwx91x_dma_api);

DT_INST_FOREACH_STATUS_OKAY(SIWX91X_DMA_INIT)
2 changes: 2 additions & 0 deletions dts/arm/silabs/siwg917.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@
clocks = <&clock0 SIWX91X_CLK_DMA0>;
#dma-cells = <1>;
dma-channels = <32>;
power-domains = <&siwx91x_soc_pd>;
zephyr,pm-device-runtime-auto;
status = "disabled";
};

Expand Down