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:
parent
f463bcaa9d
commit
49b490161d
2 changed files with 69 additions and 40 deletions
|
@ -30,7 +30,6 @@ int dmamux_stm32_configure(const struct device *dev, uint32_t id,
|
||||||
struct dma_config *config)
|
struct dma_config *config)
|
||||||
{
|
{
|
||||||
/* device is the dmamux, id is the dmamux channel from 0 */
|
/* 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;
|
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
|
* 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
|
* It gives this mux request ID to the dma through the config.dma_slot
|
||||||
*/
|
*/
|
||||||
if (dma_stm32_configure(data->mux_channels[id].dev_dma,
|
if (dma_stm32_configure(dev_config->mux_channels[id].dev_dma,
|
||||||
data->mux_channels[id].dma_id, config) != 0) {
|
dev_config->mux_channels[id].dma_id, config) != 0) {
|
||||||
LOG_ERR("cannot configure the dmamux.");
|
LOG_ERR("cannot configure the dmamux.");
|
||||||
return -EINVAL;
|
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)
|
int dmamux_stm32_start(const struct device *dev, uint32_t id)
|
||||||
{
|
{
|
||||||
const struct dmamux_stm32_config *dev_config = dev->config;
|
const struct dmamux_stm32_config *dev_config = dev->config;
|
||||||
struct dmamux_stm32_data *data = dev->data;
|
|
||||||
|
|
||||||
/* check if this channel is valid */
|
/* check if this channel is valid */
|
||||||
if (id >= dev_config->channel_nb) {
|
if (id >= dev_config->channel_nb) {
|
||||||
|
@ -87,8 +85,8 @@ int dmamux_stm32_start(const struct device *dev, uint32_t id)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dma_stm32_start(data->mux_channels[id].dev_dma,
|
if (dma_stm32_start(dev_config->mux_channels[id].dev_dma,
|
||||||
data->mux_channels[id].dma_id) != 0) {
|
dev_config->mux_channels[id].dma_id) != 0) {
|
||||||
LOG_ERR("cannot start the dmamux channel %d.", id);
|
LOG_ERR("cannot start the dmamux channel %d.", id);
|
||||||
return -EINVAL;
|
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)
|
int dmamux_stm32_stop(const struct device *dev, uint32_t id)
|
||||||
{
|
{
|
||||||
const struct dmamux_stm32_config *dev_config = dev->config;
|
const struct dmamux_stm32_config *dev_config = dev->config;
|
||||||
struct dmamux_stm32_data *data = dev->data;
|
|
||||||
|
|
||||||
/* check if this channel is valid */
|
/* check if this channel is valid */
|
||||||
if (id >= dev_config->channel_nb) {
|
if (id >= dev_config->channel_nb) {
|
||||||
|
@ -107,8 +104,8 @@ int dmamux_stm32_stop(const struct device *dev, uint32_t id)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dma_stm32_stop(data->mux_channels[id].dev_dma,
|
if (dma_stm32_stop(dev_config->mux_channels[id].dev_dma,
|
||||||
data->mux_channels[id].dma_id) != 0) {
|
dev_config->mux_channels[id].dma_id) != 0) {
|
||||||
LOG_ERR("cannot stop the dmamux channel %d.", id);
|
LOG_ERR("cannot stop the dmamux channel %d.", id);
|
||||||
return -EINVAL;
|
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)
|
uint32_t src, uint32_t dst, size_t size)
|
||||||
{
|
{
|
||||||
const struct dmamux_stm32_config *dev_config = dev->config;
|
const struct dmamux_stm32_config *dev_config = dev->config;
|
||||||
struct dmamux_stm32_data *data = dev->data;
|
|
||||||
|
|
||||||
/* check if this channel is valid */
|
/* check if this channel is valid */
|
||||||
if (id >= dev_config->channel_nb) {
|
if (id >= dev_config->channel_nb) {
|
||||||
|
@ -128,8 +124,8 @@ int dmamux_stm32_reload(const struct device *dev, uint32_t id,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dma_stm32_reload(data->mux_channels[id].dev_dma,
|
if (dma_stm32_reload(dev_config->mux_channels[id].dev_dma,
|
||||||
data->mux_channels[id].dma_id,
|
dev_config->mux_channels[id].dma_id,
|
||||||
src, dst, size) != 0) {
|
src, dst, size) != 0) {
|
||||||
LOG_ERR("cannot reload the dmamux channel %d.", id);
|
LOG_ERR("cannot reload the dmamux channel %d.", id);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -142,7 +138,6 @@ int dmamux_stm32_get_status(const struct device *dev, uint32_t id,
|
||||||
struct dma_status *stat)
|
struct dma_status *stat)
|
||||||
{
|
{
|
||||||
const struct dmamux_stm32_config *dev_config = dev->config;
|
const struct dmamux_stm32_config *dev_config = dev->config;
|
||||||
struct dmamux_stm32_data *data = dev->data;
|
|
||||||
|
|
||||||
/* check if this channel is valid */
|
/* check if this channel is valid */
|
||||||
if (id >= dev_config->channel_nb) {
|
if (id >= dev_config->channel_nb) {
|
||||||
|
@ -150,8 +145,8 @@ int dmamux_stm32_get_status(const struct device *dev, uint32_t id,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dma_stm32_get_status(data->mux_channels[id].dev_dma,
|
if (dma_stm32_get_status(dev_config->mux_channels[id].dev_dma,
|
||||||
data->mux_channels[id].dma_id, stat) != 0) {
|
dev_config->mux_channels[id].dma_id, stat) != 0) {
|
||||||
LOG_ERR("cannot get the status of dmamux channel %d.", id);
|
LOG_ERR("cannot get the status of dmamux channel %d.", id);
|
||||||
return -EINVAL;
|
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)
|
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 dmamux_stm32_config *config = dev->config;
|
||||||
const struct device *clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
|
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;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < config->channel_nb; i++) {
|
/* DMAs assigned to DMAMUX channels at build time might not be ready. */
|
||||||
/*
|
#if DT_NODE_HAS_STATUS(DT_NODELABEL(dma1), okay)
|
||||||
* associates the dmamux channel
|
if (device_is_ready(DEVICE_DT_GET(DT_NODELABEL(dma1))) == false) {
|
||||||
* to the corresponding dma stream
|
return -ENODEV;
|
||||||
*/
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -201,7 +188,53 @@ static const struct dma_driver_api dma_funcs = {
|
||||||
.get_status = dmamux_stm32_get_status,
|
.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) \
|
#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 = { \
|
const struct dmamux_stm32_config dmamux_stm32_config_##index = { \
|
||||||
.pclken = { .bus = DT_INST_CLOCKS_CELL(index, bus), \
|
.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), \
|
.channel_nb = DT_INST_PROP(index, dma_channels), \
|
||||||
.gen_nb = DT_INST_PROP(index, dma_generators), \
|
.gen_nb = DT_INST_PROP(index, dma_generators), \
|
||||||
.req_nb = DT_INST_PROP(index, dma_requests), \
|
.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, \
|
.mux_channels = dmamux_stm32_channels_##index, \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
|
static struct dmamux_stm32_data dmamux_stm32_data_##index; \
|
||||||
|
\
|
||||||
DEVICE_DT_INST_DEFINE(index, \
|
DEVICE_DT_INST_DEFINE(index, \
|
||||||
&dmamux_stm32_init, \
|
&dmamux_stm32_init, \
|
||||||
device_pm_control_nop, \
|
device_pm_control_nop, \
|
||||||
|
|
|
@ -15,7 +15,6 @@ struct dmamux_stm32_channel {
|
||||||
|
|
||||||
/* the table of all the dmamux channel */
|
/* the table of all the dmamux channel */
|
||||||
struct dmamux_stm32_data {
|
struct dmamux_stm32_data {
|
||||||
struct dmamux_stm32_channel *mux_channels;
|
|
||||||
void *callback_arg;
|
void *callback_arg;
|
||||||
void (*dmamux_callback)(void *arg, uint32_t id,
|
void (*dmamux_callback)(void *arg, uint32_t id,
|
||||||
int error_code);
|
int error_code);
|
||||||
|
@ -28,6 +27,7 @@ struct dmamux_stm32_config {
|
||||||
uint8_t channel_nb; /* total nb of channels */
|
uint8_t channel_nb; /* total nb of channels */
|
||||||
uint8_t gen_nb; /* total nb of Request generator */
|
uint8_t gen_nb; /* total nb of Request generator */
|
||||||
uint8_t req_nb; /* total nb of Peripheral Request inputs */
|
uint8_t req_nb; /* total nb of Peripheral Request inputs */
|
||||||
|
const struct dmamux_stm32_channel *mux_channels;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t table_ll_channel[] = {
|
uint32_t table_ll_channel[] = {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue