Skip to content

Commit 11a4257

Browse files
dma: dma_nxp_sdma: support pm runtime operations
Add support for PM runtime operations. Signed-off-by: Laurentiu Mihalcea <[email protected]>
1 parent 598e81e commit 11a4257

File tree

1 file changed

+72
-2
lines changed

1 file changed

+72
-2
lines changed

drivers/dma/dma_nxp_sdma.c

+72-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
#include <zephyr/irq.h>
99
#include <zephyr/cache.h>
1010
#include <zephyr/logging/log.h>
11+
#include <zephyr/pm/device_runtime.h>
12+
#include <zephyr/pm/device.h>
13+
#include <zephyr/drivers/clock_control.h>
1114
#include "fsl_sdma.h"
1215

1316
LOG_MODULE_REGISTER(nxp_sdma);
@@ -23,6 +26,8 @@ AT_NONCACHEABLE_SECTION_ALIGN(static sdma_context_data_t
2326
struct sdma_dev_cfg {
2427
SDMAARM_Type *base;
2528
void (*irq_config)(void);
29+
const struct device *clk_dev;
30+
uint32_t bus_clk_id;
2631
};
2732

2833
struct sdma_channel_data {
@@ -422,9 +427,66 @@ static bool sdma_channel_filter(const struct device *dev, int chan_id, void *par
422427
dev_data->chan[chan_id].event_source = *((int *)param);
423428
dev_data->chan[chan_id].index = chan_id;
424429

430+
if (pm_device_runtime_get(dev) < 0) {
431+
LOG_ERR("failed to runtime get");
432+
return false;
433+
}
434+
425435
return true;
426436
}
427437

438+
static void sdma_channel_release(const struct device *dev, uint32_t chan_id)
439+
{
440+
if (chan_id == 0) {
441+
return;
442+
}
443+
444+
if (chan_id >= FSL_FEATURE_SDMA_MODULE_CHANNEL) {
445+
return;
446+
}
447+
448+
if (pm_device_runtime_put(dev) < 0) {
449+
LOG_ERR("failed to runtime put");
450+
return;
451+
}
452+
}
453+
454+
static int sdma_bus_clk_enable_disable(const struct device *dev, bool enable)
455+
{
456+
const struct sdma_dev_cfg *cfg = dev->config;
457+
458+
if (!cfg->clk_dev) {
459+
return -ENODEV;
460+
}
461+
462+
if (enable) {
463+
return clock_control_on(cfg->clk_dev,
464+
UINT_TO_POINTER(cfg->bus_clk_id));
465+
} else {
466+
return clock_control_off(cfg->clk_dev,
467+
UINT_TO_POINTER(cfg->bus_clk_id));
468+
}
469+
}
470+
471+
__maybe_unused static int sdma_pm_action(const struct device *dev,
472+
enum pm_device_action action)
473+
{
474+
bool enable = true;
475+
476+
switch (action) {
477+
case PM_DEVICE_ACTION_RESUME:
478+
break;
479+
case PM_DEVICE_ACTION_SUSPEND:
480+
enable = false;
481+
break;
482+
case PM_DEVICE_ACTION_TURN_ON:
483+
case PM_DEVICE_ACTION_TURN_OFF:
484+
return 0;
485+
}
486+
487+
return sdma_bus_clk_enable_disable(dev, enable);
488+
}
489+
428490
static DEVICE_API(dma, sdma_api) = {
429491
.reload = dma_nxp_sdma_reload,
430492
.config = dma_nxp_sdma_config,
@@ -435,6 +497,7 @@ static DEVICE_API(dma, sdma_api) = {
435497
.get_status = dma_nxp_sdma_get_status,
436498
.get_attribute = dma_nxp_sdma_get_attribute,
437499
.chan_filter = sdma_channel_filter,
500+
.chan_release = sdma_channel_release,
438501
};
439502

440503
static int dma_nxp_sdma_init(const struct device *dev)
@@ -450,12 +513,13 @@ static int dma_nxp_sdma_init(const struct device *dev)
450513
SDMA_GetDefaultConfig(&defconfig);
451514
defconfig.ratio = kSDMA_ARMClockFreq;
452515

516+
/* this also ungates the bus clock */
453517
SDMA_Init(cfg->base, &defconfig);
454518

455519
/* configure interrupts */
456520
cfg->irq_config();
457521

458-
return 0;
522+
return pm_device_runtime_enable(dev);
459523
}
460524

461525
#define DMA_NXP_SDMA_INIT(inst) \
@@ -468,6 +532,8 @@ static int dma_nxp_sdma_init(const struct device *dev)
468532
static const struct sdma_dev_cfg sdma_cfg_##inst = { \
469533
.base = (SDMAARM_Type *)DT_INST_REG_ADDR(inst), \
470534
.irq_config = dma_nxp_sdma_##inst_irq_config, \
535+
.clk_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(inst)), \
536+
.bus_clk_id = DT_INST_CLOCKS_CELL(inst, name), \
471537
}; \
472538
static void dma_nxp_sdma_##inst_irq_config(void) \
473539
{ \
@@ -476,7 +542,11 @@ static int dma_nxp_sdma_init(const struct device *dev)
476542
dma_nxp_sdma_isr, DEVICE_DT_INST_GET(inst), 0); \
477543
irq_enable(DT_INST_IRQN(inst)); \
478544
} \
479-
DEVICE_DT_INST_DEFINE(inst, &dma_nxp_sdma_init, NULL, \
545+
\
546+
PM_DEVICE_DT_INST_DEFINE(inst, sdma_pm_action); \
547+
\
548+
DEVICE_DT_INST_DEFINE(inst, &dma_nxp_sdma_init, \
549+
PM_DEVICE_DT_INST_GET(inst), \
480550
&sdma_data_##inst, &sdma_cfg_##inst, \
481551
PRE_KERNEL_1, CONFIG_DMA_INIT_PRIORITY, \
482552
&sdma_api); \

0 commit comments

Comments
 (0)