drivers: dma: Enable dma and dmamux on stm32
This patch prepares the dma and introduces the dmamux on soc series which supports this feature for memory/periph transfers. Signed-off-by: Francois Ramu <francois.ramu@st.com>
This commit is contained in:
parent
5d57404c54
commit
41df1c9380
6 changed files with 462 additions and 5 deletions
|
@ -6,6 +6,7 @@ zephyr_library_sources_ifdef(CONFIG_DMA_SAM_XDMAC dma_sam_xdmac.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_DMA_STM32 dma_stm32.c)
|
zephyr_library_sources_ifdef(CONFIG_DMA_STM32 dma_stm32.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_DMA_STM32_V1 dma_stm32_v1.c)
|
zephyr_library_sources_ifdef(CONFIG_DMA_STM32_V1 dma_stm32_v1.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_DMA_STM32_V2 dma_stm32_v2.c)
|
zephyr_library_sources_ifdef(CONFIG_DMA_STM32_V2 dma_stm32_v2.c)
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_DMAMUX_STM32 dmamux_stm32.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_DMA_DW dma_dw.c)
|
zephyr_library_sources_ifdef(CONFIG_DMA_DW dma_dw.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_DMA_NIOS2_MSGDMA dma_nios2_msgdma.c)
|
zephyr_library_sources_ifdef(CONFIG_DMA_NIOS2_MSGDMA dma_nios2_msgdma.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_DMA_SAM0 dma_sam0.c)
|
zephyr_library_sources_ifdef(CONFIG_DMA_SAM0 dma_sam0.c)
|
||||||
|
|
|
@ -22,9 +22,16 @@ config DMA_STM32_V1
|
||||||
|
|
||||||
config DMA_STM32_V2
|
config DMA_STM32_V2
|
||||||
bool
|
bool
|
||||||
depends on SOC_SERIES_STM32F0X || SOC_SERIES_STM32F1X || SOC_SERIES_STM32F3X || SOC_SERIES_STM32L0X || SOC_SERIES_STM32L4X
|
depends on SOC_SERIES_STM32F0X || SOC_SERIES_STM32F1X || SOC_SERIES_STM32F3X || SOC_SERIES_STM32L0X || SOC_SERIES_STM32L4X || SOC_SERIES_STM32WBX
|
||||||
select USE_STM32_LL_DMA
|
select USE_STM32_LL_DMA
|
||||||
help
|
help
|
||||||
Enable DMA support on F0/F1/F3/L0/L4 series SoCs.
|
Enable DMA support on F0/F1/F3/L0/L4/WB series SoCs.
|
||||||
|
|
||||||
|
config DMAMUX_STM32
|
||||||
|
bool
|
||||||
|
depends on DMA_STM32_V2
|
||||||
|
depends on SOC_STM32L4R5XX || SOC_SERIES_STM32WBX
|
||||||
|
help
|
||||||
|
Enable DMAMUX support on L4R/WB series SoCs.
|
||||||
|
|
||||||
endif # DMA_STM32
|
endif # DMA_STM32
|
||||||
|
|
|
@ -78,24 +78,46 @@ static void dma_stm32_irq_handler(void *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
stream = &data->streams[id];
|
stream = &data->streams[id];
|
||||||
stream->busy = false;
|
|
||||||
|
if (!IS_ENABLED(CONFIG_DMAMUX_STM32)) {
|
||||||
|
stream->busy = false;
|
||||||
|
}
|
||||||
|
|
||||||
/* the dma stream id is in range from STREAM_OFFSET..<dma-requests> */
|
/* the dma stream id is in range from STREAM_OFFSET..<dma-requests> */
|
||||||
if (func_ll_is_active_tc[id](dma)) {
|
if (func_ll_is_active_tc[id](dma)) {
|
||||||
func_ll_clear_tc[id](dma);
|
func_ll_clear_tc[id](dma);
|
||||||
|
|
||||||
|
#ifdef CONFIG_DMAMUX_STM32
|
||||||
|
stream->busy = false;
|
||||||
|
/* the callback function expects the dmamux channel nb */
|
||||||
|
stream->dma_callback(stream->callback_arg,
|
||||||
|
stream->mux_channel, 0);
|
||||||
|
#else
|
||||||
stream->dma_callback(stream->callback_arg, id + STREAM_OFFSET,
|
stream->dma_callback(stream->callback_arg, id + STREAM_OFFSET,
|
||||||
0);
|
0);
|
||||||
|
#endif /* CONFIG_DMAMUX_STM32 */
|
||||||
} else if (stm32_dma_is_unexpected_irq_happened(dma, id)) {
|
} else if (stm32_dma_is_unexpected_irq_happened(dma, id)) {
|
||||||
LOG_ERR("Unexpected irq happened.");
|
LOG_ERR("Unexpected irq happened.");
|
||||||
|
|
||||||
|
#ifdef CONFIG_DMAMUX_STM32
|
||||||
|
stream->dma_callback(stream->callback_arg,
|
||||||
|
stream->mux_channel, -EIO);
|
||||||
|
#else
|
||||||
stream->dma_callback(stream->callback_arg, id + STREAM_OFFSET,
|
stream->dma_callback(stream->callback_arg, id + STREAM_OFFSET,
|
||||||
-EIO);
|
-EIO);
|
||||||
|
#endif /* CONFIG_DMAMUX_STM32 */
|
||||||
} else {
|
} else {
|
||||||
LOG_ERR("Transfer Error.");
|
LOG_ERR("Transfer Error.");
|
||||||
dma_stm32_dump_stream_irq(dev, id);
|
dma_stm32_dump_stream_irq(dev, id);
|
||||||
dma_stm32_clear_stream_irq(dev, id);
|
dma_stm32_clear_stream_irq(dev, id);
|
||||||
|
|
||||||
|
#ifdef CONFIG_DMAMUX_STM32
|
||||||
|
stream->dma_callback(stream->callback_arg,
|
||||||
|
stream->mux_channel, -EIO);
|
||||||
|
#else
|
||||||
stream->dma_callback(stream->callback_arg, id + STREAM_OFFSET,
|
stream->dma_callback(stream->callback_arg, id + STREAM_OFFSET,
|
||||||
-EIO);
|
-EIO);
|
||||||
|
#endif /* CONFIG_DMAMUX_STM32 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,8 +232,13 @@ static int dma_stm32_get_periph_increment(enum dma_addr_adj increment,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DMAMUX_STM32
|
||||||
|
int dma_stm32_configure(struct device *dev, u32_t id,
|
||||||
|
struct dma_config *config)
|
||||||
|
#else
|
||||||
static int dma_stm32_configure(struct device *dev, u32_t id,
|
static int dma_stm32_configure(struct device *dev, u32_t id,
|
||||||
struct dma_config *config)
|
struct dma_config *config)
|
||||||
|
#endif /* CONFIG_DMAMUX_STM32 */
|
||||||
{
|
{
|
||||||
struct dma_stm32_data *data = dev->driver_data;
|
struct dma_stm32_data *data = dev->driver_data;
|
||||||
struct dma_stm32_stream *stream = &data->streams[id - STREAM_OFFSET];
|
struct dma_stm32_stream *stream = &data->streams[id - STREAM_OFFSET];
|
||||||
|
@ -399,9 +426,10 @@ static int dma_stm32_configure(struct device *dev, u32_t id,
|
||||||
DMA_InitStruct.NbData = config->head_block->block_size /
|
DMA_InitStruct.NbData = config->head_block->block_size /
|
||||||
config->dest_data_size;
|
config->dest_data_size;
|
||||||
}
|
}
|
||||||
#if defined(CONFIG_DMA_STM32_V2)
|
|
||||||
|
#if defined(CONFIG_DMA_STM32_V2) || defined(CONFIG_DMAMUX_STM32)
|
||||||
/*
|
/*
|
||||||
* the with dma V2,
|
* the with dma V2 and dma mux,
|
||||||
* the request ID is stored in the dma_slot
|
* the request ID is stored in the dma_slot
|
||||||
*/
|
*/
|
||||||
DMA_InitStruct.PeriphRequest = config->dma_slot;
|
DMA_InitStruct.PeriphRequest = config->dma_slot;
|
||||||
|
@ -441,8 +469,13 @@ static int dma_stm32_disable_stream(DMA_TypeDef *dma, u32_t id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DMAMUX_STM32
|
||||||
|
int dma_stm32_reload(struct device *dev, u32_t id,
|
||||||
|
u32_t src, u32_t dst, size_t size)
|
||||||
|
#else
|
||||||
static int dma_stm32_reload(struct device *dev, u32_t id,
|
static int dma_stm32_reload(struct device *dev, u32_t id,
|
||||||
u32_t src, u32_t dst, size_t size)
|
u32_t src, u32_t dst, size_t size)
|
||||||
|
#endif /* CONFIG_DMAMUX_STM32 */
|
||||||
{
|
{
|
||||||
const struct dma_stm32_config *config = dev->config->config_info;
|
const struct dma_stm32_config *config = dev->config->config_info;
|
||||||
DMA_TypeDef *dma = (DMA_TypeDef *)(config->base);
|
DMA_TypeDef *dma = (DMA_TypeDef *)(config->base);
|
||||||
|
@ -485,7 +518,11 @@ static int dma_stm32_reload(struct device *dev, u32_t id,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DMAMUX_STM32
|
||||||
|
int dma_stm32_start(struct device *dev, u32_t id)
|
||||||
|
#else
|
||||||
static int dma_stm32_start(struct device *dev, u32_t id)
|
static int dma_stm32_start(struct device *dev, u32_t id)
|
||||||
|
#endif /* CONFIG_DMAMUX_STM32 */
|
||||||
{
|
{
|
||||||
const struct dma_stm32_config *config = dev->config->config_info;
|
const struct dma_stm32_config *config = dev->config->config_info;
|
||||||
DMA_TypeDef *dma = (DMA_TypeDef *)(config->base);
|
DMA_TypeDef *dma = (DMA_TypeDef *)(config->base);
|
||||||
|
@ -506,7 +543,11 @@ static int dma_stm32_start(struct device *dev, u32_t id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DMAMUX_STM32
|
||||||
|
int dma_stm32_stop(struct device *dev, u32_t id)
|
||||||
|
#else
|
||||||
static int dma_stm32_stop(struct device *dev, u32_t id)
|
static int dma_stm32_stop(struct device *dev, u32_t id)
|
||||||
|
#endif /* CONFIG_DMAMUX_STM32 */
|
||||||
{
|
{
|
||||||
struct dma_stm32_data *data = dev->driver_data;
|
struct dma_stm32_data *data = dev->driver_data;
|
||||||
struct dma_stm32_stream *stream = &data->streams[id - STREAM_OFFSET];
|
struct dma_stm32_stream *stream = &data->streams[id - STREAM_OFFSET];
|
||||||
|
@ -521,7 +562,10 @@ static int dma_stm32_stop(struct device *dev, u32_t id)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_DMAMUX_STM32
|
||||||
LL_DMA_DisableIT_TC(dma, table_ll_stream[id]);
|
LL_DMA_DisableIT_TC(dma, table_ll_stream[id]);
|
||||||
|
#endif /* CONFIG_DMAMUX_STM32 */
|
||||||
|
|
||||||
#if defined(CONFIG_DMA_STM32_V1)
|
#if defined(CONFIG_DMA_STM32_V1)
|
||||||
stm32_dma_disable_fifo_irq(dma, id);
|
stm32_dma_disable_fifo_irq(dma, id);
|
||||||
#endif
|
#endif
|
||||||
|
@ -560,8 +604,17 @@ static int dma_stm32_init(struct device *dev)
|
||||||
}
|
}
|
||||||
memset(data->streams, 0, size_stream);
|
memset(data->streams, 0, size_stream);
|
||||||
|
|
||||||
|
#ifdef CONFIG_DMAMUX_STM32
|
||||||
|
int offset = ((dev == device_get_binding((const char *)"DMA_1"))
|
||||||
|
? 0 : data->max_streams);
|
||||||
|
#endif /* CONFIG_DMAMUX_STM32 */
|
||||||
|
|
||||||
for (int i = 0; i < data->max_streams; i++) {
|
for (int i = 0; i < data->max_streams; i++) {
|
||||||
data->streams[i].busy = false;
|
data->streams[i].busy = false;
|
||||||
|
#ifdef CONFIG_DMAMUX_STM32
|
||||||
|
/* each further stream->mux_channel is fixed here */
|
||||||
|
data->streams[i].mux_channel = i + offset;
|
||||||
|
#endif /* CONFIG_DMAMUX_STM32 */
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
|
|
||||||
struct dma_stm32_stream {
|
struct dma_stm32_stream {
|
||||||
u32_t direction;
|
u32_t direction;
|
||||||
|
#ifdef CONFIG_DMAMUX_STM32
|
||||||
|
int mux_channel; /* stores the dmamux channel */
|
||||||
|
#endif /* CONFIG_DMAMUX_STM32 */
|
||||||
bool source_periph;
|
bool source_periph;
|
||||||
bool busy;
|
bool busy;
|
||||||
u32_t src_size;
|
u32_t src_size;
|
||||||
|
@ -71,4 +74,14 @@ u32_t stm32_dma_get_mburst(struct dma_config *config, bool source_periph);
|
||||||
u32_t stm32_dma_get_pburst(struct dma_config *config, bool source_periph);
|
u32_t stm32_dma_get_pburst(struct dma_config *config, bool source_periph);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_DMAMUX_STM32
|
||||||
|
/* dma_stm32_ api functions are exported to the dmamux_stm32 */
|
||||||
|
int dma_stm32_configure(struct device *dev, u32_t id,
|
||||||
|
struct dma_config *config);
|
||||||
|
int dma_stm32_reload(struct device *dev, u32_t id,
|
||||||
|
u32_t src, u32_t dst, size_t size);
|
||||||
|
int dma_stm32_start(struct device *dev, u32_t id);
|
||||||
|
int dma_stm32_stop(struct device *dev, u32_t id);
|
||||||
|
#endif /* CONFIG_DMAMUX_STM32 */
|
||||||
|
|
||||||
#endif /* DMA_STM32_H_*/
|
#endif /* DMA_STM32_H_*/
|
||||||
|
|
217
drivers/dma/dmamux_stm32.c
Normal file
217
drivers/dma/dmamux_stm32.c
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 STMicroelectronics
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Common part of DMAMUX drivers for stm32.
|
||||||
|
* @note api functions named dmamux_stm32_
|
||||||
|
* are calling the dma_stm32 corresponding function
|
||||||
|
* implemented in dma_stm32.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <soc.h>
|
||||||
|
#include <init.h>
|
||||||
|
#include <drivers/dma.h>
|
||||||
|
#include <drivers/clock_control.h>
|
||||||
|
#include <drivers/clock_control/stm32_clock_control.h>
|
||||||
|
|
||||||
|
#include "dmamux_stm32.h"
|
||||||
|
#include "dma_stm32.h"
|
||||||
|
|
||||||
|
#include <logging/log.h>
|
||||||
|
LOG_MODULE_REGISTER(dmamux_stm32, CONFIG_DMA_LOG_LEVEL);
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT st_stm32_dmamux
|
||||||
|
|
||||||
|
int dmamux_stm32_configure(struct device *dev, u32_t id,
|
||||||
|
struct dma_config *config)
|
||||||
|
{
|
||||||
|
/* device is the dmamux, id is the dmamux channel from 0 */
|
||||||
|
struct dmamux_stm32_data *data = dev->driver_data;
|
||||||
|
const struct dmamux_stm32_config *dev_config =
|
||||||
|
dev->config->config_info;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* request line ID for this mux channel is stored
|
||||||
|
* in the dma_slot parameter
|
||||||
|
*/
|
||||||
|
int request_id = config->dma_slot;
|
||||||
|
|
||||||
|
if (request_id >= dev_config->req_nb + dev_config->gen_nb) {
|
||||||
|
LOG_ERR("request ID %d is too big.", request_id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if this channel is valid */
|
||||||
|
if (id >= dev_config->channel_nb) {
|
||||||
|
LOG_ERR("channel ID %d is too big.", id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Also configures the corresponding dma channel
|
||||||
|
* instance is given by the dev_dma
|
||||||
|
* stream is given by the index i
|
||||||
|
* config is directly this dma_config
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This dmamux channel 'id' is now used for this peripheral request
|
||||||
|
* It gives this mux request ID to the dma through the config.dma_slot
|
||||||
|
*/
|
||||||
|
if (dma_stm32_configure(data->mux_channels[id].dev_dma,
|
||||||
|
data->mux_channels[id].dma_id, config) != 0) {
|
||||||
|
LOG_ERR("cannot configure the dmamux.");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the Request Line ID to this dmamux channel i */
|
||||||
|
DMAMUX_Channel_TypeDef *dmamux =
|
||||||
|
(DMAMUX_Channel_TypeDef *)dev_config->base;
|
||||||
|
|
||||||
|
LL_DMAMUX_SetRequestID(dmamux, id, request_id);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dmamux_stm32_start(struct device *dev, u32_t id)
|
||||||
|
{
|
||||||
|
const struct dmamux_stm32_config *dev_config =
|
||||||
|
dev->config->config_info;
|
||||||
|
struct dmamux_stm32_data *data = dev->driver_data;
|
||||||
|
|
||||||
|
/* check if this channel is valid */
|
||||||
|
if (id >= dev_config->channel_nb) {
|
||||||
|
LOG_ERR("channel ID %d is too big.", id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dma_stm32_start(data->mux_channels[id].dev_dma,
|
||||||
|
data->mux_channels[id].dma_id) != 0) {
|
||||||
|
LOG_ERR("cannot start the dmamux channel %d.", id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dmamux_stm32_stop(struct device *dev, u32_t id)
|
||||||
|
{
|
||||||
|
const struct dmamux_stm32_config *dev_config =
|
||||||
|
dev->config->config_info;
|
||||||
|
struct dmamux_stm32_data *data = dev->driver_data;
|
||||||
|
|
||||||
|
/* check if this channel is valid */
|
||||||
|
if (id >= dev_config->channel_nb) {
|
||||||
|
LOG_ERR("channel ID %d is too big.", id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dma_stm32_stop(data->mux_channels[id].dev_dma,
|
||||||
|
data->mux_channels[id].dma_id) != 0) {
|
||||||
|
LOG_ERR("cannot stop the dmamux channel %d.", id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dmamux_stm32_reload(struct device *dev, u32_t id,
|
||||||
|
u32_t src, u32_t dst, size_t size)
|
||||||
|
{
|
||||||
|
const struct dmamux_stm32_config *dev_config =
|
||||||
|
dev->config->config_info;
|
||||||
|
struct dmamux_stm32_data *data = dev->driver_data;
|
||||||
|
|
||||||
|
/* check if this channel is valid */
|
||||||
|
if (id >= dev_config->channel_nb) {
|
||||||
|
LOG_ERR("channel ID %d is too big.", id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dma_stm32_reload(data->mux_channels[id].dev_dma,
|
||||||
|
data->mux_channels[id].dma_id,
|
||||||
|
src, dst, size) != 0) {
|
||||||
|
LOG_ERR("cannot reload the dmamux channel %d.", id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dmamux_stm32_init(struct device *dev)
|
||||||
|
{
|
||||||
|
struct dmamux_stm32_data *data = dev->driver_data;
|
||||||
|
const struct dmamux_stm32_config *config =
|
||||||
|
dev->config->config_info;
|
||||||
|
struct device *clk =
|
||||||
|
device_get_binding(STM32_CLOCK_CONTROL_NAME);
|
||||||
|
|
||||||
|
if (clock_control_on(clk,
|
||||||
|
(clock_control_subsys_t *) &config->pclken) != 0) {
|
||||||
|
LOG_ERR("clock op failed\n");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
int size_stream =
|
||||||
|
sizeof(struct dmamux_stm32_channel) * config->channel_nb;
|
||||||
|
data->mux_channels = k_malloc(size_stream);
|
||||||
|
if (!data->mux_channels) {
|
||||||
|
LOG_ERR("HEAP_MEM_POOL_SIZE is too small");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < config->channel_nb; i++) {
|
||||||
|
/*
|
||||||
|
* associates the dmamux channel
|
||||||
|
* to the corresponding dma stream
|
||||||
|
*/
|
||||||
|
if (i < config->channel_nb / 2) {
|
||||||
|
data->mux_channels[i].dev_dma =
|
||||||
|
device_get_binding((const char *)"DMA_1");
|
||||||
|
/* dma 1 channels from 1 to N */
|
||||||
|
data->mux_channels[i].dma_id = i + 1;
|
||||||
|
} else {
|
||||||
|
data->mux_channels[i].dev_dma =
|
||||||
|
device_get_binding((const char *)"DMA_2");
|
||||||
|
data->mux_channels[i].dma_id =
|
||||||
|
/* dma 2 channels from 1 to N */
|
||||||
|
i - config->channel_nb / 2 + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dma_driver_api dma_funcs = {
|
||||||
|
.reload = dmamux_stm32_reload,
|
||||||
|
.config = dmamux_stm32_configure,
|
||||||
|
.start = dmamux_stm32_start,
|
||||||
|
.stop = dmamux_stm32_stop,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DMAMUX_INIT(index) \
|
||||||
|
\
|
||||||
|
const struct dmamux_stm32_config dmamux_stm32_config_##index = {\
|
||||||
|
.pclken = { .bus = DT_INST_CLOCKS_CELL(index, bus), \
|
||||||
|
.enr = DT_INST_CLOCKS_CELL(index, bits) }, \
|
||||||
|
.base = DT_INST_REG_ADDR(index), \
|
||||||
|
.channel_nb = DT_INST_PROP(index, dma_channels), \
|
||||||
|
.gen_nb = DT_INST_PROP(index, dma_generators), \
|
||||||
|
.req_nb = DT_INST_PROP(index, dma_requests), \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
static struct dmamux_stm32_data dmamux_stm32_data_##index = { \
|
||||||
|
.mux_channels = NULL, \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
DEVICE_AND_API_INIT(dmamux_##index, DT_INST_LABEL(index), \
|
||||||
|
&dmamux_stm32_init, \
|
||||||
|
&dmamux_stm32_data_##index, &dmamux_stm32_config_##index,\
|
||||||
|
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,\
|
||||||
|
&dma_funcs)
|
||||||
|
|
||||||
|
#if DT_HAS_DRV_INST(0)
|
||||||
|
DMAMUX_INIT(0);
|
||||||
|
#endif /* DT_HAS_DRV_INST(0) */
|
166
drivers/dma/dmamux_stm32.h
Normal file
166
drivers/dma/dmamux_stm32.h
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 STMicroelectronics
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DMAMUX_STM32_H_
|
||||||
|
#define DMAMUX_STM32_H_
|
||||||
|
|
||||||
|
/* this is the configuration of one dmamux channel */
|
||||||
|
struct dmamux_stm32_channel {
|
||||||
|
struct device *dev_dma; /* pointer to the associated dma instance */
|
||||||
|
u8_t dma_id; /* ref of the associated dma stream for this instance */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* the table of all the dmamux channel */
|
||||||
|
struct dmamux_stm32_data {
|
||||||
|
struct dmamux_stm32_channel *mux_channels;
|
||||||
|
void *callback_arg;
|
||||||
|
void (*dmamux_callback)(void *arg, u32_t id,
|
||||||
|
int error_code);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* this is the configuration of the dmamux IP */
|
||||||
|
struct dmamux_stm32_config {
|
||||||
|
struct stm32_pclken pclken;
|
||||||
|
u32_t base;
|
||||||
|
u8_t channel_nb; /* total nb of channels */
|
||||||
|
u8_t gen_nb; /* total nb of Request generator */
|
||||||
|
u8_t req_nb; /* total nb of Peripheral Request inputs */
|
||||||
|
};
|
||||||
|
|
||||||
|
u32_t table_ll_channel[] = {
|
||||||
|
LL_DMAMUX_CHANNEL_0,
|
||||||
|
LL_DMAMUX_CHANNEL_1,
|
||||||
|
LL_DMAMUX_CHANNEL_2,
|
||||||
|
LL_DMAMUX_CHANNEL_3,
|
||||||
|
LL_DMAMUX_CHANNEL_4,
|
||||||
|
#if defined(LL_DMAMUX_CHANNEL_5)
|
||||||
|
LL_DMAMUX_CHANNEL_5,
|
||||||
|
#endif /* LL_DMAMUX_CHANNEL_5 */
|
||||||
|
#if defined(LL_DMAMUX_CHANNEL_6)
|
||||||
|
LL_DMAMUX_CHANNEL_6,
|
||||||
|
#endif /* LL_DMAMUX_CHANNEL_6 */
|
||||||
|
#if defined(LL_DMAMUX_CHANNEL_7)
|
||||||
|
LL_DMAMUX_CHANNEL_7,
|
||||||
|
#endif /* LL_DMAMUX_CHANNEL_7 */
|
||||||
|
#if defined(LL_DMAMUX_CHANNEL_8)
|
||||||
|
LL_DMAMUX_CHANNEL_8,
|
||||||
|
#endif /* LL_DMAMUX_CHANNEL_8 */
|
||||||
|
#if defined(LL_DMAMUX_CHANNEL_9)
|
||||||
|
LL_DMAMUX_CHANNEL_9,
|
||||||
|
#endif /* LL_DMAMUX_CHANNEL_9 */
|
||||||
|
#if defined(LL_DMAMUX_CHANNEL_10)
|
||||||
|
LL_DMAMUX_CHANNEL_10,
|
||||||
|
#endif /* LL_DMAMUX_CHANNEL_10 */
|
||||||
|
#if defined(LL_DMAMUX_CHANNEL_11)
|
||||||
|
LL_DMAMUX_CHANNEL_11,
|
||||||
|
#endif /* LL_DMAMUX_CHANNEL_11 */
|
||||||
|
#if defined(LL_DMAMUX_CHANNEL_12)
|
||||||
|
LL_DMAMUX_CHANNEL_12,
|
||||||
|
#endif /* LL_DMAMUX_CHANNEL_12 */
|
||||||
|
#if defined(LL_DMAMUX_CHANNEL_13)
|
||||||
|
LL_DMAMUX_CHANNEL_13,
|
||||||
|
#endif /* LL_DMAMUX_CHANNEL_13 */
|
||||||
|
#if defined(LL_DMAMUX_CHANNEL_14)
|
||||||
|
LL_DMAMUX_CHANNEL_14,
|
||||||
|
#endif /* LL_DMAMUX_CHANNEL_14 */
|
||||||
|
#if defined(LL_DMAMUX_CHANNEL_15)
|
||||||
|
LL_DMAMUX_CHANNEL_15,
|
||||||
|
#endif /* LL_DMAMUX_CHANNEL_15 */
|
||||||
|
};
|
||||||
|
|
||||||
|
u32_t (*func_ll_is_active_so[])(DMAMUX_Channel_TypeDef *DMAMUXx) = {
|
||||||
|
LL_DMAMUX_IsActiveFlag_SO0,
|
||||||
|
LL_DMAMUX_IsActiveFlag_SO1,
|
||||||
|
LL_DMAMUX_IsActiveFlag_SO2,
|
||||||
|
LL_DMAMUX_IsActiveFlag_SO3,
|
||||||
|
LL_DMAMUX_IsActiveFlag_SO4,
|
||||||
|
LL_DMAMUX_IsActiveFlag_SO5,
|
||||||
|
#if defined(DMAMUX_CSR_SOF6)
|
||||||
|
LL_DMAMUX_IsActiveFlag_SO6,
|
||||||
|
#endif /* DMAMUX_CSR_SOF6 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF7)
|
||||||
|
LL_DMAMUX_IsActiveFlag_SO7,
|
||||||
|
#endif /* DMAMUX_CSR_SOF7 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF8)
|
||||||
|
LL_DMAMUX_IsActiveFlag_SO8,
|
||||||
|
#endif /* DMAMUX_CSR_SOF8 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF9)
|
||||||
|
LL_DMAMUX_IsActiveFlag_SO9,
|
||||||
|
#endif /* DMAMUX_CSR_SOF9 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF10)
|
||||||
|
LL_DMAMUX_IsActiveFlag_SO10,
|
||||||
|
#endif /* DMAMUX_CSR_SOF10 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF11)
|
||||||
|
LL_DMAMUX_IsActiveFlag_SO11,
|
||||||
|
#endif /* DMAMUX_CSR_SOF11 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF12)
|
||||||
|
LL_DMAMUX_IsActiveFlag_SO12,
|
||||||
|
#endif /* DMAMUX_CSR_SOF12 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF130)
|
||||||
|
LL_DMAMUX_IsActiveFlag_SO13,
|
||||||
|
#endif /* DMAMUX_CSR_SOF130 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF14)
|
||||||
|
LL_DMAMUX_IsActiveFlag_SO14,
|
||||||
|
#endif /* DMAMUX_CSR_SOF14 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF15)
|
||||||
|
LL_DMAMUX_IsActiveFlag_SO15,
|
||||||
|
#endif /* DMAMUX_CSR_SOF15 */
|
||||||
|
};
|
||||||
|
|
||||||
|
void (*func_ll_clear_so[])(DMAMUX_Channel_TypeDef *DMAMUXx) = {
|
||||||
|
LL_DMAMUX_ClearFlag_SO0,
|
||||||
|
LL_DMAMUX_ClearFlag_SO1,
|
||||||
|
LL_DMAMUX_ClearFlag_SO2,
|
||||||
|
LL_DMAMUX_ClearFlag_SO3,
|
||||||
|
LL_DMAMUX_ClearFlag_SO4,
|
||||||
|
LL_DMAMUX_ClearFlag_SO5,
|
||||||
|
#if defined(DMAMUX_CSR_SOF6)
|
||||||
|
LL_DMAMUX_ClearFlag_SO6,
|
||||||
|
#endif /* DMAMUX_CSR_SOF6 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF7)
|
||||||
|
LL_DMAMUX_ClearFlag_SO7,
|
||||||
|
#endif /* DMAMUX_CSR_SOF7 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF8)
|
||||||
|
LL_DMAMUX_ClearFlag_SO8,
|
||||||
|
#endif /* DMAMUX_CSR_SOF8 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF9)
|
||||||
|
LL_DMAMUX_ClearFlag_SO9,
|
||||||
|
#endif /* DMAMUX_CSR_SOF9 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF10)
|
||||||
|
LL_DMAMUX_ClearFlag_SO10,
|
||||||
|
#endif /* DMAMUX_CSR_SOF10 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF11)
|
||||||
|
LL_DMAMUX_ClearFlag_SO11,
|
||||||
|
#endif /* DMAMUX_CSR_SOF11 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF12)
|
||||||
|
LL_DMAMUX_ClearFlag_SO12,
|
||||||
|
#endif /* DMAMUX_CSR_SOF12 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF13)
|
||||||
|
LL_DMAMUX_ClearFlag_SO13,
|
||||||
|
#endif /* DMAMUX_CSR_SOF13 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF14)
|
||||||
|
LL_DMAMUX_ClearFlag_SO14,
|
||||||
|
#endif /* DMAMUX_CSR_SOF145 */
|
||||||
|
#if defined(DMAMUX_CSR_SOF15)
|
||||||
|
LL_DMAMUX_ClearFlag_SO15,
|
||||||
|
#endif /* DMAMUX_CSR_SOF15 */
|
||||||
|
};
|
||||||
|
|
||||||
|
u32_t (*func_ll_is_active_rgo[])(DMAMUX_Channel_TypeDef *DMAMUXx) = {
|
||||||
|
LL_DMAMUX_IsActiveFlag_RGO0,
|
||||||
|
LL_DMAMUX_IsActiveFlag_RGO1,
|
||||||
|
LL_DMAMUX_IsActiveFlag_RGO2,
|
||||||
|
LL_DMAMUX_IsActiveFlag_RGO3,
|
||||||
|
};
|
||||||
|
|
||||||
|
void (*func_ll_clear_rgo[])(DMAMUX_Channel_TypeDef *DMAMUXx) = {
|
||||||
|
LL_DMAMUX_ClearFlag_RGO0,
|
||||||
|
LL_DMAMUX_ClearFlag_RGO1,
|
||||||
|
LL_DMAMUX_ClearFlag_RGO2,
|
||||||
|
LL_DMAMUX_ClearFlag_RGO3,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* DMAMUX_STM32_H_*/
|
Loading…
Add table
Add a link
Reference in a new issue