drivers: mbox: fix nxp mbox data read channel

This commit repairs reading of data from other
channels than 0.

Refactors irq handler outside of DT define.

Trigger registered callback only when proper flag is set.

Signed-off-by: Tomas Galbicka <tomas.galbicka@nxp.com>
This commit is contained in:
Tomas Galbicka 2024-01-12 15:43:30 +01:00 committed by Fabio Baltieri
parent 5fd3f658ff
commit a689228eb8

View file

@ -1,4 +1,8 @@
/* /*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*
* Wrapper of the i.MX Message Unit driver into Zephyr's MBOX model. * Wrapper of the i.MX Message Unit driver into Zephyr's MBOX model.
*/ */
@ -19,14 +23,14 @@ LOG_MODULE_REGISTER(nxp_mbox_imx_mu);
struct nxp_imx_mu_data { struct nxp_imx_mu_data {
mbox_callback_t cb[MU_MAX_CHANNELS]; mbox_callback_t cb[MU_MAX_CHANNELS];
void *user_data[MU_MAX_CHANNELS]; void *user_data[MU_MAX_CHANNELS];
uint32_t received_data;
}; };
struct nxp_imx_mu_config { struct nxp_imx_mu_config {
MU_Type *base; MU_Type *base;
}; };
static int nxp_imx_mu_send(const struct device *dev, uint32_t channel, static int nxp_imx_mu_send(const struct device *dev, uint32_t channel, const struct mbox_msg *msg)
const struct mbox_msg *msg)
{ {
uint32_t __aligned(4) data32; uint32_t __aligned(4) data32;
const struct nxp_imx_mu_config *cfg = dev->config; const struct nxp_imx_mu_config *cfg = dev->config;
@ -37,8 +41,7 @@ static int nxp_imx_mu_send(const struct device *dev, uint32_t channel,
/* Signalling mode. */ /* Signalling mode. */
if (msg == NULL) { if (msg == NULL) {
return MU_TriggerInterrupts( return MU_TriggerInterrupts(cfg->base, kMU_GenInt0InterruptTrigger >> channel);
cfg->base, kMU_GenInt0InterruptTrigger >> channel);
} }
/* Data transfer mode. */ /* Data transfer mode. */
@ -80,8 +83,7 @@ static uint32_t nxp_imx_mu_max_channels_get(const struct device *dev)
return MU_MAX_CHANNELS; return MU_MAX_CHANNELS;
} }
static int nxp_imx_mu_set_enabled(const struct device *dev, uint32_t channel, static int nxp_imx_mu_set_enabled(const struct device *dev, uint32_t channel, bool enable)
bool enable)
{ {
struct nxp_imx_mu_data *data = dev->data; struct nxp_imx_mu_data *data = dev->data;
const struct nxp_imx_mu_config *cfg = dev->config; const struct nxp_imx_mu_config *cfg = dev->config;
@ -94,14 +96,14 @@ static int nxp_imx_mu_set_enabled(const struct device *dev, uint32_t channel,
if (data->cb[channel] == NULL) { if (data->cb[channel] == NULL) {
LOG_WRN("Enabling channel without a registered callback"); LOG_WRN("Enabling channel without a registered callback");
} }
MU_EnableInterrupts(cfg->base, MU_EnableInterrupts(
kMU_GenInt0InterruptEnable | kMU_GenInt1InterruptEnable | cfg->base, kMU_GenInt0InterruptEnable | kMU_GenInt1InterruptEnable |
kMU_GenInt2InterruptEnable | kMU_GenInt3InterruptEnable | kMU_GenInt2InterruptEnable | kMU_GenInt3InterruptEnable |
kMU_Rx0FullInterruptEnable | kMU_Rx1FullInterruptEnable | kMU_Rx0FullInterruptEnable | kMU_Rx1FullInterruptEnable |
kMU_Rx2FullInterruptEnable | kMU_Rx3FullInterruptEnable); kMU_Rx2FullInterruptEnable | kMU_Rx3FullInterruptEnable);
} else { } else {
MU_DisableInterrupts(cfg->base, MU_DisableInterrupts(
kMU_GenInt0InterruptEnable | kMU_GenInt1InterruptEnable | cfg->base, kMU_GenInt0InterruptEnable | kMU_GenInt1InterruptEnable |
kMU_GenInt2InterruptEnable | kMU_GenInt3InterruptEnable | kMU_GenInt2InterruptEnable | kMU_GenInt3InterruptEnable |
kMU_Rx0FullInterruptEnable | kMU_Rx1FullInterruptEnable | kMU_Rx0FullInterruptEnable | kMU_Rx1FullInterruptEnable |
kMU_Rx2FullInterruptEnable | kMU_Rx3FullInterruptEnable); kMU_Rx2FullInterruptEnable | kMU_Rx3FullInterruptEnable);
@ -118,62 +120,32 @@ static const struct mbox_driver_api nxp_imx_mu_driver_api = {
.set_enabled = nxp_imx_mu_set_enabled, .set_enabled = nxp_imx_mu_set_enabled,
}; };
static void handle_irq(const struct device *dev);
#define MU_INSTANCE_DEFINE(idx) \ #define MU_INSTANCE_DEFINE(idx) \
static struct nxp_imx_mu_data nxp_imx_mu_##idx##_data; \ static struct nxp_imx_mu_data nxp_imx_mu_##idx##_data; \
static struct nxp_imx_mu_config nxp_imx_mu_##idx##_config = { \ const static struct nxp_imx_mu_config nxp_imx_mu_##idx##_config = { \
.base = (MU_Type *)DT_INST_REG_ADDR(idx), \ .base = (MU_Type *)DT_INST_REG_ADDR(idx), \
}; \ }; \
\
void MU_##idx##_IRQHandler(void); \ void MU_##idx##_IRQHandler(void); \
static int nxp_imx_mu_##idx##_init(const struct device *dev) \ static int nxp_imx_mu_##idx##_init(const struct device *dev) \
{ \ { \
ARG_UNUSED(dev); \ ARG_UNUSED(dev); \
MU_Init(nxp_imx_mu_##idx##_config.base); \ MU_Init(nxp_imx_mu_##idx##_config.base); \
IRQ_CONNECT(DT_INST_IRQN(idx), \ IRQ_CONNECT(DT_INST_IRQN(idx), DT_INST_IRQ(idx, priority), MU_##idx##_IRQHandler, \
DT_INST_IRQ(idx, priority), \ NULL, 0); \
MU_##idx##_IRQHandler, \
NULL, \
0); \
irq_enable(DT_INST_IRQN(idx)); \ irq_enable(DT_INST_IRQN(idx)); \
return 0; \ return 0; \
} \ } \
DEVICE_DT_INST_DEFINE(idx, nxp_imx_mu_##idx##_init, NULL, \ DEVICE_DT_INST_DEFINE(idx, nxp_imx_mu_##idx##_init, NULL, &nxp_imx_mu_##idx##_data, \
&nxp_imx_mu_##idx##_data, &nxp_imx_mu_##idx##_config, \ &nxp_imx_mu_##idx##_config, POST_KERNEL, CONFIG_MBOX_INIT_PRIORITY, \
POST_KERNEL, CONFIG_MBOX_INIT_PRIORITY, \
&nxp_imx_mu_driver_api) &nxp_imx_mu_driver_api)
#define MU_IRQ_HANDLER(idx) \ #define MU_IRQ_HANDLER(idx) \
static uint32_t mu_##idx##_received_data; \
void MU_##idx##_IRQHandler(void) \ void MU_##idx##_IRQHandler(void) \
{ \ { \
const struct device *dev = DEVICE_DT_INST_GET(idx); \ const struct device *dev = DEVICE_DT_INST_GET(idx); \
const struct nxp_imx_mu_data *data = dev->data; \ handle_irq(dev); \
const struct nxp_imx_mu_config *config = dev->config; \
struct mbox_msg msg; \
struct mbox_msg *callback_msg_ptr = NULL; \
uint32_t flag = MU_GetStatusFlags(config->base); \
\
for (int i_channel = 0; i_channel < MU_MAX_CHANNELS; i_channel++) { \
if ((flag & (kMU_Rx0FullFlag >> i_channel)) == \
(kMU_Rx0FullFlag >> i_channel)) { \
mu_##idx##_received_data = \
MU_ReceiveMsgNonBlocking(config->base, 0); \
msg.data = (const void *)&mu_##idx##_received_data; \
msg.size = MU_MBOX_SIZE; \
callback_msg_ptr = &msg; \
} else if ((flag & (kMU_GenInt0Flag >> i_channel)) == \
(kMU_GenInt0Flag >> i_channel)) { \
MU_ClearStatusFlags(config->base, \
(kMU_GenInt0Flag >> i_channel)); \
callback_msg_ptr = NULL; \
} \
\
if (data->cb[i_channel]) { \
data->cb[i_channel](dev, i_channel, \
data->user_data[i_channel], \
callback_msg_ptr); \
} \
} \
} }
#define MU_INST(idx) \ #define MU_INST(idx) \
@ -181,3 +153,29 @@ static const struct mbox_driver_api nxp_imx_mu_driver_api = {
MU_IRQ_HANDLER(idx); MU_IRQ_HANDLER(idx);
DT_INST_FOREACH_STATUS_OKAY(MU_INST) DT_INST_FOREACH_STATUS_OKAY(MU_INST)
static void handle_irq(const struct device *dev)
{
struct nxp_imx_mu_data *data = dev->data;
const struct nxp_imx_mu_config *config = dev->config;
const uint32_t flag = MU_GetStatusFlags(config->base);
for (int i_channel = 0; i_channel < MU_MAX_CHANNELS; i_channel++) {
if ((flag & (kMU_Rx0FullFlag >> i_channel)) == (kMU_Rx0FullFlag >> i_channel)) {
data->received_data = MU_ReceiveMsgNonBlocking(config->base, i_channel);
struct mbox_msg msg = {(const void *)&data->received_data, MU_MBOX_SIZE};
if (data->cb[i_channel]) {
data->cb[i_channel](dev, i_channel, data->user_data[i_channel],
&msg);
}
} else if ((flag & (kMU_GenInt0Flag >> i_channel)) ==
(kMU_GenInt0Flag >> i_channel)) {
MU_ClearStatusFlags(config->base, (kMU_GenInt0Flag >> i_channel));
if (data->cb[i_channel]) {
data->cb[i_channel](dev, i_channel, data->user_data[i_channel],
NULL);
}
}
}
}