drivers: dmamux_stm32: compile time dmamux channels initialization

Move dmamux_stm32_channels struct from device data to device
configuration and initialize the dmamux channel - dma channel
assignment during build time,
as this association is hardwired in all known series.
The information is taken from dma_offset and dma_requests device tree
properties. The current implementation is valid for series with either
a single or two dma peripherals and a single dmamux peripheral.
Both dmas can independently enabled.
As the driver uses multi-instance DT_INST_DEFINE, also macros for a
second dmamux are are added that should allow easier extension to a
second dmamux instance.

Signed-off-by: Thomas Stranger <thomas.stranger@outlook.com>
This commit is contained in:
Thomas Stranger 2021-01-11 15:22:06 +01:00 committed by Ioannis Glaropoulos
parent f463bcaa9d
commit 49b490161d
2 changed files with 69 additions and 40 deletions

View file

@ -30,7 +30,6 @@ int dmamux_stm32_configure(const struct device *dev, uint32_t id,
struct dma_config *config)
{
/* device is the dmamux, id is the dmamux channel from 0 */
struct dmamux_stm32_data *data = dev->data;
const struct dmamux_stm32_config *dev_config = dev->config;
/*
@ -61,8 +60,8 @@ int dmamux_stm32_configure(const struct device *dev, uint32_t id,
* 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) {
if (dma_stm32_configure(dev_config->mux_channels[id].dev_dma,
dev_config->mux_channels[id].dma_id, config) != 0) {
LOG_ERR("cannot configure the dmamux.");
return -EINVAL;
}
@ -79,7 +78,6 @@ int dmamux_stm32_configure(const struct device *dev, uint32_t id,
int dmamux_stm32_start(const struct device *dev, uint32_t id)
{
const struct dmamux_stm32_config *dev_config = dev->config;
struct dmamux_stm32_data *data = dev->data;
/* check if this channel is valid */
if (id >= dev_config->channel_nb) {
@ -87,8 +85,8 @@ int dmamux_stm32_start(const struct device *dev, uint32_t id)
return -EINVAL;
}
if (dma_stm32_start(data->mux_channels[id].dev_dma,
data->mux_channels[id].dma_id) != 0) {
if (dma_stm32_start(dev_config->mux_channels[id].dev_dma,
dev_config->mux_channels[id].dma_id) != 0) {
LOG_ERR("cannot start the dmamux channel %d.", id);
return -EINVAL;
}
@ -99,7 +97,6 @@ int dmamux_stm32_start(const struct device *dev, uint32_t id)
int dmamux_stm32_stop(const struct device *dev, uint32_t id)
{
const struct dmamux_stm32_config *dev_config = dev->config;
struct dmamux_stm32_data *data = dev->data;
/* check if this channel is valid */
if (id >= dev_config->channel_nb) {
@ -107,8 +104,8 @@ int dmamux_stm32_stop(const struct device *dev, uint32_t id)
return -EINVAL;
}
if (dma_stm32_stop(data->mux_channels[id].dev_dma,
data->mux_channels[id].dma_id) != 0) {
if (dma_stm32_stop(dev_config->mux_channels[id].dev_dma,
dev_config->mux_channels[id].dma_id) != 0) {
LOG_ERR("cannot stop the dmamux channel %d.", id);
return -EINVAL;
}
@ -120,7 +117,6 @@ int dmamux_stm32_reload(const struct device *dev, uint32_t id,
uint32_t src, uint32_t dst, size_t size)
{
const struct dmamux_stm32_config *dev_config = dev->config;
struct dmamux_stm32_data *data = dev->data;
/* check if this channel is valid */
if (id >= dev_config->channel_nb) {
@ -128,8 +124,8 @@ int dmamux_stm32_reload(const struct device *dev, uint32_t id,
return -EINVAL;
}
if (dma_stm32_reload(data->mux_channels[id].dev_dma,
data->mux_channels[id].dma_id,
if (dma_stm32_reload(dev_config->mux_channels[id].dev_dma,
dev_config->mux_channels[id].dma_id,
src, dst, size) != 0) {
LOG_ERR("cannot reload the dmamux channel %d.", id);
return -EINVAL;
@ -142,7 +138,6 @@ int dmamux_stm32_get_status(const struct device *dev, uint32_t id,
struct dma_status *stat)
{
const struct dmamux_stm32_config *dev_config = dev->config;
struct dmamux_stm32_data *data = dev->data;
/* check if this channel is valid */
if (id >= dev_config->channel_nb) {
@ -150,8 +145,8 @@ int dmamux_stm32_get_status(const struct device *dev, uint32_t id,
return -EINVAL;
}
if (dma_stm32_get_status(data->mux_channels[id].dev_dma,
data->mux_channels[id].dma_id, stat) != 0) {
if (dma_stm32_get_status(dev_config->mux_channels[id].dev_dma,
dev_config->mux_channels[id].dma_id, stat) != 0) {
LOG_ERR("cannot get the status of dmamux channel %d.", id);
return -EINVAL;
}
@ -161,7 +156,6 @@ int dmamux_stm32_get_status(const struct device *dev, uint32_t id,
static int dmamux_stm32_init(const struct device *dev)
{
struct dmamux_stm32_data *data = dev->data;
const struct dmamux_stm32_config *config = dev->config;
const struct device *clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
@ -171,24 +165,17 @@ static int dmamux_stm32_init(const struct device *dev)
return -EIO;
}
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;
}
/* DMAs assigned to DMAMUX channels at build time might not be ready. */
#if DT_NODE_HAS_STATUS(DT_NODELABEL(dma1), okay)
if (device_is_ready(DEVICE_DT_GET(DT_NODELABEL(dma1))) == false) {
return -ENODEV;
}
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(dma2), okay)
if (device_is_ready(DEVICE_DT_GET(DT_NODELABEL(dma2))) == false) {
return -ENODEV;
}
#endif
return 0;
}
@ -201,7 +188,53 @@ static const struct dma_driver_api dma_funcs = {
.get_status = dmamux_stm32_get_status,
};
/*
* Each dmamux channel is hardwired to one dma controlers dma channel.
* DMAMUX_CHANNEL_INIT_X macros resolve this mapping at build time for each
* dmamux channel using the dma dt properties dma_offset and dma_requests,
* such that it can be stored in dmamux_stm32_channels_X configuration.
* The Macros to get the corresponding dma device binding and dma channel
* for a given dmamux channel, are currently valid for series having
* 1 dmamux and 1 or 2 dmas.
*/
#define DMA_1_BEGIN_DMAMUX_CHANNEL DT_PROP_OR(DT_NODELABEL(dma1), dma_offset, 0)
#define DMA_1_END_DMAMUX_CHANNEL (DMA_1_BEGIN_DMAMUX_CHANNEL + \
DT_PROP_OR(DT_NODELABEL(dma1), dma_requests, 0))
#define DEV_DMA1 COND_CODE_1(DT_NODE_HAS_STATUS(DT_NODELABEL(dma1), okay), \
DEVICE_DT_GET(DT_NODELABEL(dma1)), NULL)
#define DMA_2_BEGIN_DMAMUX_CHANNEL DT_PROP_OR(DT_NODELABEL(dma2), dma_offset, 0)
#define DMA_2_END_DMAMUX_CHANNEL (DMA_2_BEGIN_DMAMUX_CHANNEL + \
DT_PROP_OR(DT_NODELABEL(dma2), dma_requests, 0))
#define DEV_DMA2 COND_CODE_1(DT_NODE_HAS_STATUS(DT_NODELABEL(dma2), okay), \
DEVICE_DT_GET(DT_NODELABEL(dma2)), NULL)
#define DEV_DMA_BINDING(mux_channel) \
((mux_channel < DMA_1_END_DMAMUX_CHANNEL) ? DEV_DMA1 : DEV_DMA2)
#define DMA_CHANNEL(mux_channel) \
((mux_channel < DMA_1_END_DMAMUX_CHANNEL) ? \
(mux_channel + 1) : (mux_channel - DMA_2_BEGIN_DMAMUX_CHANNEL + 1))
/*
* No series implements more than 1 dmamux yet, dummy define added for easier
* future extension.
*/
#define INIT_DMAMUX_0_CHANNEL(x, ...) \
{ .dev_dma = DEV_DMA_BINDING(x), .dma_id = DMA_CHANNEL(x), },
#define INIT_DMAMUX_1_CHANNEL(x, ...) \
{ .dev_dma = 0, .dma_id = 0, },
#define DMAMUX_CHANNELS_INIT_0(count) \
UTIL_LISTIFY(count, INIT_DMAMUX_0_CHANNEL)
#define DMAMUX_CHANNELS_INIT_1(count) \
UTIL_LISTIFY(count, INIT_DMAMUX_1_CHANNEL)
#define DMAMUX_INIT(index) \
static const struct dmamux_stm32_channel \
dmamux_stm32_channels_##index[DT_INST_PROP(index, dma_channels)] = { \
DMAMUX_CHANNELS_INIT_##index(DT_INST_PROP(index, dma_channels))\
}; \
\
const struct dmamux_stm32_config dmamux_stm32_config_##index = { \
.pclken = { .bus = DT_INST_CLOCKS_CELL(index, bus), \
@ -210,15 +243,11 @@ const struct dmamux_stm32_config dmamux_stm32_config_##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_channel \
dmamux_stm32_channels_##index[DT_INST_PROP(index, dma_channels)]; \
\
static struct dmamux_stm32_data dmamux_stm32_data_##index = { \
.mux_channels = dmamux_stm32_channels_##index, \
}; \
\
static struct dmamux_stm32_data dmamux_stm32_data_##index; \
\
DEVICE_DT_INST_DEFINE(index, \
&dmamux_stm32_init, \
device_pm_control_nop, \

View file

@ -15,7 +15,6 @@ struct dmamux_stm32_channel {
/* 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, uint32_t id,
int error_code);
@ -28,6 +27,7 @@ struct dmamux_stm32_config {
uint8_t channel_nb; /* total nb of channels */
uint8_t gen_nb; /* total nb of Request generator */
uint8_t req_nb; /* total nb of Peripheral Request inputs */
const struct dmamux_stm32_channel *mux_channels;
};
uint32_t table_ll_channel[] = {