Skip to content

Commit 50089c4

Browse files
committed
drivers: dma: dma_mcux_lpc: Add register backup and restore
Add for the case that the registers are not kept in some low power modes. Signed-off-by: Jason Yu <zejiang.yu@nxp.com>
1 parent b6b43f7 commit 50089c4

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

drivers/dma/dma_mcux_lpc.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,28 @@
2929

3030
LOG_MODULE_REGISTER(dma_mcux_lpc, CONFIG_DMA_LOG_LEVEL);
3131

32+
#if CONFIG_PM_DEVICE
33+
/*
34+
* Data structures to backup DMA registers when the
35+
* register content lost in low power modes.
36+
*/
37+
struct dma_backup_reg {
38+
/*
39+
* Backup the control registers.
40+
* Don't need to backup CTRL and SRAMBASE, they
41+
* are configured in function DMA_Init.
42+
*/
43+
uint32_t enableset; /* Register ENABLESET */
44+
uint32_t intenset; /* Register INTENSET */
45+
};
46+
47+
struct dma_ch_backup_reg {
48+
/* Don't need to backup status register CTLSTAT. */
49+
uint32_t cfg; /* Register CFG */
50+
uint32_t xfercfg; /* Register XFERCFG */
51+
};
52+
#endif /* CONFIG_PM_DEVICE */
53+
3254
struct dma_mcux_lpc_config {
3355
DMA_Type *base;
3456
uint32_t otrig_base_address;
@@ -54,6 +76,9 @@ struct channel_data {
5476
uint8_t num_of_descriptors;
5577
bool descriptors_queued;
5678
bool busy;
79+
#if CONFIG_PM_DEVICE
80+
struct dma_ch_backup_reg backup_reg;
81+
#endif /* CONFIG_PM_DEVICE */
5782
};
5883

5984
struct dma_otrig {
@@ -68,6 +93,9 @@ struct dma_mcux_lpc_dma_data {
6893
struct dma_otrig *otrig_array;
6994
int8_t *channel_index;
7095
uint8_t num_channels_used;
96+
#if CONFIG_PM_DEVICE
97+
struct dma_backup_reg backup_reg;
98+
#endif /* CONFIG_PM_DEVICE */
7199
};
72100

73101
struct k_spinlock configuring_otrigs;
@@ -948,6 +976,69 @@ static int dma_mcux_lpc_get_attribute(const struct device *dev, uint32_t type, u
948976
return 0;
949977
}
950978

979+
#if CONFIG_PM_DEVICE
980+
static void dma_mcux_lpc_backup_reg(const struct device *dev)
981+
{
982+
struct dma_mcux_lpc_dma_data *dma_data = dev->data;
983+
const struct dma_mcux_lpc_config *config = dev->config;
984+
struct channel_data *p_channel_data;
985+
uint32_t virtual_channel;
986+
DMA_Type *dma_base = DEV_BASE(dev);
987+
988+
dma_data->backup_reg.enableset = dma_base->COMMON[0].ENABLESET;
989+
dma_data->backup_reg.intenset = dma_base->COMMON[0].INTENSET;
990+
991+
/* Only backup the used channels */
992+
virtual_channel = 0;
993+
for (uint32_t channel = 0; channel < config->num_of_channels; channel++) {
994+
if (dma_data->channel_index[channel] != -1) {
995+
p_channel_data = &dma_data->channel_data[virtual_channel];
996+
997+
p_channel_data->backup_reg.xfercfg = dma_base->CHANNEL[channel].XFERCFG;
998+
p_channel_data->backup_reg.cfg = dma_base->CHANNEL[channel].CFG;
999+
virtual_channel++;
1000+
}
1001+
}
1002+
}
1003+
1004+
static void dma_mcux_lpc_restore_reg(const struct device *dev)
1005+
{
1006+
struct dma_mcux_lpc_dma_data *dma_data = dev->data;
1007+
const struct dma_mcux_lpc_config *config = dev->config;
1008+
struct channel_data *p_channel_data;
1009+
uint32_t virtual_channel;
1010+
DMA_Type *dma_base = DEV_BASE(dev);
1011+
1012+
dma_base->COMMON[0].ENABLESET = dma_data->backup_reg.enableset;
1013+
dma_base->COMMON[0].INTENSET = dma_data->backup_reg.intenset;
1014+
1015+
/* Only backup the used channels */
1016+
virtual_channel = 0;
1017+
for (uint32_t channel = 0; channel < config->num_of_channels; channel++) {
1018+
if (dma_data->channel_index[channel] != -1) {
1019+
p_channel_data = &dma_data->channel_data[virtual_channel];
1020+
1021+
dma_base->CHANNEL[channel].XFERCFG = p_channel_data->backup_reg.xfercfg;
1022+
dma_base->CHANNEL[channel].CFG = p_channel_data->backup_reg.cfg;
1023+
virtual_channel++;
1024+
}
1025+
}
1026+
}
1027+
1028+
#else /* !CONFIG_PM_DEVICE */
1029+
1030+
static inline static void dma_mcux_lpc_backup_reg(const struct device *dev)
1031+
{
1032+
ARG_UNUSED(dev);
1033+
}
1034+
1035+
static inline static void dma_mcux_lpc_restore_reg(const struct device *dev)
1036+
{
1037+
ARG_UNUSED(dev);
1038+
}
1039+
1040+
#endif /* CONFIG_PM_DEVICE */
1041+
9511042
static int dma_mcux_lpc_pm_action(const struct device *dev, enum pm_device_action action)
9521043
{
9531044
switch (action) {
@@ -956,9 +1047,11 @@ static int dma_mcux_lpc_pm_action(const struct device *dev, enum pm_device_actio
9561047
case PM_DEVICE_ACTION_SUSPEND:
9571048
break;
9581049
case PM_DEVICE_ACTION_TURN_OFF:
1050+
dma_mcux_lpc_backup_reg(dev);
9591051
break;
9601052
case PM_DEVICE_ACTION_TURN_ON:
9611053
DMA_Init(DEV_BASE(dev));
1054+
dma_mcux_lpc_restore_reg(dev);
9621055
break;
9631056
default:
9641057
return -ENOTSUP;

0 commit comments

Comments
 (0)