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
86 changes: 67 additions & 19 deletions drivers/dma/dma_silabs_siwx91x_gpdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include <zephyr/drivers/dma.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/logging/log.h>
#include <zephyr/pm/device.h>
#include <zephyr/pm/policy.h>
#include "rsi_gpdma.h"
#include "rsi_rom_gpdma.h"

Expand Down Expand Up @@ -60,6 +62,16 @@ struct siwx19x_gpdma_data {
uint8_t reload_compatible;
};

static void siwx91x_gpdma_pm_policy_state_lock_get(void)
{
pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES);
}

static void siwx91x_gpdma_pm_policy_state_lock_put(void)
{
pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES);
}

static bool siwx91x_gpdma_is_priority_valid(uint32_t channel_priority)
{
return (channel_priority >= GPDMA_MIN_PRIORITY && channel_priority <= GPDMA_MAX_PRIORITY);
Expand Down Expand Up @@ -360,13 +372,19 @@ static int siwx91x_gpdma_reload(const struct device *dev, uint32_t channel, uint

static int siwx91x_gpdma_start(const struct device *dev, uint32_t channel)
{
const struct siwx91x_gpdma_config *cfg = dev->config;
struct siwx19x_gpdma_data *data = dev->data;

if (channel >= data->dma_ctx.dma_channels) {
return -EINVAL;
}

if (!sys_test_bit((mem_addr_t)&cfg->reg->GLOBAL.DMA_CHNL_ENABLE_REG, channel)) {
siwx91x_gpdma_pm_policy_state_lock_get();
}

if (RSI_GPDMA_DMAChannelTrigger(&data->hal_ctx, channel)) {
siwx91x_gpdma_pm_policy_state_lock_put();
return -EINVAL;
}

Expand All @@ -375,13 +393,18 @@ static int siwx91x_gpdma_start(const struct device *dev, uint32_t channel)

static int siwx91x_gpdma_stop(const struct device *dev, uint32_t channel)
{
const struct siwx91x_gpdma_config *cfg = dev->config;
struct siwx19x_gpdma_data *data = dev->data;
k_spinlock_key_t key;

if (channel >= data->dma_ctx.dma_channels) {
return -EINVAL;
}

if (sys_test_bit((mem_addr_t)&cfg->reg->GLOBAL.DMA_CHNL_ENABLE_REG, channel)) {
siwx91x_gpdma_pm_policy_state_lock_put();
}

if (RSI_GPDMA_AbortChannel(&data->hal_ctx, channel)) {
return -EINVAL;
}
Expand Down Expand Up @@ -428,32 +451,54 @@ bool siwx91x_gpdma_chan_filter(const struct device *dev, int channel, void *filt
}
}

static int siwx91x_gpdma_init(const struct device *dev)
static int gpdma_siwx91x_pm_action(const struct device *dev, enum pm_device_action action)
{
const struct siwx91x_gpdma_config *cfg = dev->config;
struct siwx19x_gpdma_data *data = dev->data;
RSI_GPDMA_INIT_T gpdma_init = {
.pUserData = NULL,
.baseG = (uint32_t)cfg->reg,
.baseC = (uint32_t)cfg->channel_reg,
.sramBase = (uint32_t)data->desc_pool->buffer,
};
RSI_GPDMA_HANDLE_T gpdma_handle;
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: {
RSI_GPDMA_INIT_T gpdma_init = {
.pUserData = NULL,
.baseG = (uint32_t)cfg->reg,
.baseC = (uint32_t)cfg->channel_reg,
.sramBase = (uint32_t)data->desc_pool->buffer,
};
RSI_GPDMA_HANDLE_T gpdma_handle;

ret = clock_control_on(cfg->clock_dev, cfg->clock_subsys);
if (ret < 0 && ret != -EALREADY) {
return ret;
}

gpdma_handle = RSI_GPDMA_Init(&data->hal_ctx, &gpdma_init);
if (gpdma_handle != &data->hal_ctx) {
return -EIO;
gpdma_handle = RSI_GPDMA_Init(&data->hal_ctx, &gpdma_init);
if (gpdma_handle != &data->hal_ctx) {
return -EIO;
}

break;
}
case PM_DEVICE_ACTION_TURN_OFF:
break;
default:
return -ENOTSUP;
}

return 0;
}

static int siwx91x_gpdma_init(const struct device *dev)
{
const struct siwx91x_gpdma_config *cfg = dev->config;

cfg->irq_configure();

return 0;
return pm_device_driver_init(dev, gpdma_siwx91x_pm_action);
}

static void siwx91x_gpdma_isr(const struct device *dev)
Expand All @@ -471,6 +516,7 @@ static void siwx91x_gpdma_isr(const struct device *dev)
if (channel_int_status & abort_mask) {
RSI_GPDMA_AbortChannel(&data->hal_ctx, channel);
cfg->reg->GLOBAL.INTERRUPT_STAT_REG = abort_mask;
siwx91x_gpdma_pm_policy_state_lock_put();
}

if (channel_int_status & desc_fetch_mask) {
Expand All @@ -491,6 +537,7 @@ static void siwx91x_gpdma_isr(const struct device *dev)
data->chan_info[channel].cb(dev, data->chan_info[channel].cb_data, channel,
0);
}
siwx91x_gpdma_pm_policy_state_lock_put();
}
}

Expand Down Expand Up @@ -531,8 +578,9 @@ static DEVICE_API(dma, siwx91x_gpdma_api) = {
.clock_subsys = (clock_control_subsys_t)DT_INST_PHA(inst, clocks, clkid), \
.irq_configure = siwx91x_gpdma_irq_configure_##inst, \
}; \
DEVICE_DT_INST_DEFINE(inst, siwx91x_gpdma_init, NULL, &siwx91x_gpdma_data_##inst, \
&siwx91x_gpdma_cfg_##inst, POST_KERNEL, CONFIG_DMA_INIT_PRIORITY, \
&siwx91x_gpdma_api);
PM_DEVICE_DT_INST_DEFINE(inst, gpdma_siwx91x_pm_action); \
DEVICE_DT_INST_DEFINE(inst, siwx91x_gpdma_init, PM_DEVICE_DT_INST_GET(inst), \
&siwx91x_gpdma_data_##inst, &siwx91x_gpdma_cfg_##inst, POST_KERNEL, \
CONFIG_DMA_INIT_PRIORITY, &siwx91x_gpdma_api);

DT_INST_FOREACH_STATUS_OKAY(SIWX91X_GPDMA_INIT)
2 changes: 2 additions & 0 deletions dts/arm/silabs/siwg917.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,8 @@
silabs,channel-reg-base = <0x21081004>;
silabs,dma-channel-count = <8>;
#dma-cells = <2>;
power-domains = <&siwx91x_soc_pd>;
zephyr,pm-device-runtime-auto;
status = "disabled";
};
};
Expand Down