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:
parent
5fd3f658ff
commit
a689228eb8
|
@ -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.
|
||||
*/
|
||||
|
||||
|
@ -19,14 +23,14 @@ LOG_MODULE_REGISTER(nxp_mbox_imx_mu);
|
|||
struct nxp_imx_mu_data {
|
||||
mbox_callback_t cb[MU_MAX_CHANNELS];
|
||||
void *user_data[MU_MAX_CHANNELS];
|
||||
uint32_t received_data;
|
||||
};
|
||||
|
||||
struct nxp_imx_mu_config {
|
||||
MU_Type *base;
|
||||
};
|
||||
|
||||
static int nxp_imx_mu_send(const struct device *dev, uint32_t channel,
|
||||
const struct mbox_msg *msg)
|
||||
static int nxp_imx_mu_send(const struct device *dev, uint32_t channel, const struct mbox_msg *msg)
|
||||
{
|
||||
uint32_t __aligned(4) data32;
|
||||
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. */
|
||||
if (msg == NULL) {
|
||||
return MU_TriggerInterrupts(
|
||||
cfg->base, kMU_GenInt0InterruptTrigger >> channel);
|
||||
return MU_TriggerInterrupts(cfg->base, kMU_GenInt0InterruptTrigger >> channel);
|
||||
}
|
||||
|
||||
/* Data transfer mode. */
|
||||
|
@ -80,8 +83,7 @@ static uint32_t nxp_imx_mu_max_channels_get(const struct device *dev)
|
|||
return MU_MAX_CHANNELS;
|
||||
}
|
||||
|
||||
static int nxp_imx_mu_set_enabled(const struct device *dev, uint32_t channel,
|
||||
bool enable)
|
||||
static int nxp_imx_mu_set_enabled(const struct device *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
struct nxp_imx_mu_data *data = dev->data;
|
||||
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) {
|
||||
LOG_WRN("Enabling channel without a registered callback");
|
||||
}
|
||||
MU_EnableInterrupts(cfg->base,
|
||||
kMU_GenInt0InterruptEnable | kMU_GenInt1InterruptEnable |
|
||||
MU_EnableInterrupts(
|
||||
cfg->base, kMU_GenInt0InterruptEnable | kMU_GenInt1InterruptEnable |
|
||||
kMU_GenInt2InterruptEnable | kMU_GenInt3InterruptEnable |
|
||||
kMU_Rx0FullInterruptEnable | kMU_Rx1FullInterruptEnable |
|
||||
kMU_Rx2FullInterruptEnable | kMU_Rx3FullInterruptEnable);
|
||||
} else {
|
||||
MU_DisableInterrupts(cfg->base,
|
||||
kMU_GenInt0InterruptEnable | kMU_GenInt1InterruptEnable |
|
||||
MU_DisableInterrupts(
|
||||
cfg->base, kMU_GenInt0InterruptEnable | kMU_GenInt1InterruptEnable |
|
||||
kMU_GenInt2InterruptEnable | kMU_GenInt3InterruptEnable |
|
||||
kMU_Rx0FullInterruptEnable | kMU_Rx1FullInterruptEnable |
|
||||
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,
|
||||
};
|
||||
|
||||
static void handle_irq(const struct device *dev);
|
||||
|
||||
#define MU_INSTANCE_DEFINE(idx) \
|
||||
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), \
|
||||
}; \
|
||||
\
|
||||
void MU_##idx##_IRQHandler(void); \
|
||||
static int nxp_imx_mu_##idx##_init(const struct device *dev) \
|
||||
{ \
|
||||
ARG_UNUSED(dev); \
|
||||
MU_Init(nxp_imx_mu_##idx##_config.base); \
|
||||
IRQ_CONNECT(DT_INST_IRQN(idx), \
|
||||
DT_INST_IRQ(idx, priority), \
|
||||
MU_##idx##_IRQHandler, \
|
||||
NULL, \
|
||||
0); \
|
||||
IRQ_CONNECT(DT_INST_IRQN(idx), DT_INST_IRQ(idx, priority), MU_##idx##_IRQHandler, \
|
||||
NULL, 0); \
|
||||
irq_enable(DT_INST_IRQN(idx)); \
|
||||
return 0; \
|
||||
} \
|
||||
DEVICE_DT_INST_DEFINE(idx, nxp_imx_mu_##idx##_init, NULL, \
|
||||
&nxp_imx_mu_##idx##_data, &nxp_imx_mu_##idx##_config, \
|
||||
POST_KERNEL, CONFIG_MBOX_INIT_PRIORITY, \
|
||||
DEVICE_DT_INST_DEFINE(idx, nxp_imx_mu_##idx##_init, NULL, &nxp_imx_mu_##idx##_data, \
|
||||
&nxp_imx_mu_##idx##_config, POST_KERNEL, CONFIG_MBOX_INIT_PRIORITY, \
|
||||
&nxp_imx_mu_driver_api)
|
||||
|
||||
#define MU_IRQ_HANDLER(idx) \
|
||||
static uint32_t mu_##idx##_received_data; \
|
||||
void MU_##idx##_IRQHandler(void) \
|
||||
{ \
|
||||
const struct device *dev = DEVICE_DT_INST_GET(idx); \
|
||||
const struct nxp_imx_mu_data *data = dev->data; \
|
||||
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); \
|
||||
} \
|
||||
} \
|
||||
handle_irq(dev); \
|
||||
}
|
||||
|
||||
#define MU_INST(idx) \
|
||||
|
@ -181,3 +153,29 @@ static const struct mbox_driver_api nxp_imx_mu_driver_api = {
|
|||
MU_IRQ_HANDLER(idx);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue