From 6ead139b4b171fbe494c4a8422e557ce3fc2d414 Mon Sep 17 00:00:00 2001 From: Yicheng Li Date: Tue, 22 Aug 2023 14:55:36 -0700 Subject: [PATCH] mbox: Add NXP MU as a MBOX device Add a MBOX driver wrapper around the NXP MU, simular to the existing wrapper around the NXP S32 MRU. This allows Zephyr IPC to work based on the MU, on a number of NXP boards. Also update the SHA of NXP HAL to enable the Kconfig for this driver. Signed-off-by: Yicheng Li --- .../arm/mimxrt595_evk/mimxrt595_evk_cm33.dts | 4 + drivers/mbox/CMakeLists.txt | 1 + drivers/mbox/Kconfig | 1 + drivers/mbox/Kconfig.nxp_imx | 9 + drivers/mbox/mbox_nxp_imx_mu.c | 179 ++++++++++++++++++ dts/arm/nxp/nxp_rt5xx_common.dtsi | 9 + dts/bindings/mbox/nxp,mbox-imx-mu.yaml | 29 +++ samples/drivers/mbox/CMakeLists.txt | 2 + .../mbox/boards/mimxrt595_evk_cm33.conf | 1 + samples/drivers/mbox/sample.yaml | 5 +- west.yml | 2 +- 11 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 drivers/mbox/Kconfig.nxp_imx create mode 100644 drivers/mbox/mbox_nxp_imx_mu.c create mode 100644 dts/bindings/mbox/nxp,mbox-imx-mu.yaml create mode 100644 samples/drivers/mbox/boards/mimxrt595_evk_cm33.conf diff --git a/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts b/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts index e65106d87d6..f919ba00ea0 100644 --- a/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts +++ b/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts @@ -459,6 +459,10 @@ zephyr_udc0: &usbhs { status = "okay"; }; +&mbox { + status = "okay"; +}; + /* Disable this node if not using USB and need another MPU region */ &sram1 { status = "okay"; diff --git a/drivers/mbox/CMakeLists.txt b/drivers/mbox/CMakeLists.txt index aa39b235522..b81a3bb679f 100644 --- a/drivers/mbox/CMakeLists.txt +++ b/drivers/mbox/CMakeLists.txt @@ -7,4 +7,5 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_USERSPACE mbox_handlers.c) zephyr_library_sources_ifdef(CONFIG_MBOX_NRFX_IPC mbox_nrfx_ipc.c) zephyr_library_sources_ifdef(CONFIG_MBOX_NXP_S32_MRU mbox_nxp_s32_mru.c) +zephyr_library_sources_ifdef(CONFIG_MBOX_NXP_IMX_MU mbox_nxp_imx_mu.c) zephyr_library_sources_ifdef(CONFIG_MBOX_ANDES_PLIC_SW mbox_andes_plic_sw.c) diff --git a/drivers/mbox/Kconfig b/drivers/mbox/Kconfig index a88a84472b4..0668c9aab8b 100644 --- a/drivers/mbox/Kconfig +++ b/drivers/mbox/Kconfig @@ -13,6 +13,7 @@ if MBOX # overridden (by defining symbols in multiple locations) source "drivers/mbox/Kconfig.nrfx" source "drivers/mbox/Kconfig.nxp_s32" +source "drivers/mbox/Kconfig.nxp_imx" source "drivers/mbox/Kconfig.andes" config MBOX_INIT_PRIORITY diff --git a/drivers/mbox/Kconfig.nxp_imx b/drivers/mbox/Kconfig.nxp_imx new file mode 100644 index 00000000000..6822e5dd87c --- /dev/null +++ b/drivers/mbox/Kconfig.nxp_imx @@ -0,0 +1,9 @@ +# Copyright 2022 NXP +# SPDX-License-Identifier: Apache-2.0 + +config MBOX_NXP_IMX_MU + bool "NXP i.MX Message Unit (MU) driver" + default y + depends on DT_HAS_NXP_MBOX_IMX_MU_ENABLED + help + Driver for NXP i.MX Message Unit. diff --git a/drivers/mbox/mbox_nxp_imx_mu.c b/drivers/mbox/mbox_nxp_imx_mu.c new file mode 100644 index 00000000000..3c708b95eca --- /dev/null +++ b/drivers/mbox/mbox_nxp_imx_mu.c @@ -0,0 +1,179 @@ +/* + * Wrapper of the i.MX Message Unit driver into Zephyr's MBOX model. + */ + +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_MBOX_LOG_LEVEL +#include +LOG_MODULE_REGISTER(nxp_mbox_imx_mu); + +#define DT_DRV_COMPAT nxp_mbox_imx_mu + +#define MU_MAX_CHANNELS 4 +#define MU_MBOX_SIZE sizeof(uint32_t) + +struct nxp_imx_mu_data { + mbox_callback_t cb[MU_MAX_CHANNELS]; + void *user_data[MU_MAX_CHANNELS]; +}; + +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) +{ + uint32_t __aligned(4) data32; + const struct nxp_imx_mu_config *cfg = dev->config; + + if (channel >= MU_MAX_CHANNELS) { + return -EINVAL; + } + + /* Signalling mode. */ + if (msg == NULL) { + return MU_TriggerInterrupts( + cfg->base, kMU_GenInt0InterruptTrigger); + } + + /* Data transfer mode. */ + if (msg->size != MU_MBOX_SIZE) { + /* We can only send this many bytes at a time. */ + return -EMSGSIZE; + } + + /* memcpy to avoid issues when msg->data is not word-aligned. */ + memcpy(&data32, msg->data, msg->size); + MU_SendMsg(cfg->base, channel, data32); + return 0; +} + +static int nxp_imx_mu_register_callback(const struct device *dev, uint32_t channel, + mbox_callback_t cb, void *user_data) +{ + struct nxp_imx_mu_data *data = dev->data; + + if (channel >= MU_MAX_CHANNELS) { + return -EINVAL; + } + + data->cb[channel] = cb; + data->user_data[channel] = user_data; + + return 0; +} + +static int nxp_imx_mu_mtu_get(const struct device *dev) +{ + ARG_UNUSED(dev); + return MU_MBOX_SIZE; +} + +static uint32_t nxp_imx_mu_max_channels_get(const struct device *dev) +{ + ARG_UNUSED(dev); + return MU_MAX_CHANNELS; +} + +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; + + if (channel >= MU_MAX_CHANNELS) { + return -EINVAL; + } + + if (enable) { + if (data->cb[channel] == NULL) { + LOG_WRN("Enabling channel without a registered callback"); + } + 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 | + kMU_GenInt2InterruptEnable | kMU_GenInt3InterruptEnable | + kMU_Rx0FullInterruptEnable | kMU_Rx1FullInterruptEnable | + kMU_Rx2FullInterruptEnable | kMU_Rx3FullInterruptEnable); + } + + return 0; +} + +static const struct mbox_driver_api nxp_imx_mu_driver_api = { + .send = nxp_imx_mu_send, + .register_callback = nxp_imx_mu_register_callback, + .mtu_get = nxp_imx_mu_mtu_get, + .max_channels_get = nxp_imx_mu_max_channels_get, + .set_enabled = nxp_imx_mu_set_enabled, +}; + +#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 = { \ + .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_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, \ + &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; \ + int channel = 0; \ + struct mbox_msg msg; \ + struct mbox_msg *callback_msg_ptr = NULL; \ + uint32_t flag = MU_GetStatusFlags(config->base); \ + \ + if ((flag & kMU_Rx0FullFlag) == kMU_Rx0FullFlag) { \ + 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) == kMU_GenInt0Flag) { \ + MU_ClearStatusFlags(config->base, kMU_GenInt0Flag); \ + callback_msg_ptr = NULL; \ + } \ + \ + if (data->cb[channel]) { \ + data->cb[channel](dev, channel, \ + data->user_data[channel], \ + callback_msg_ptr); \ + } \ + } + +#define MU_INST(idx) \ + MU_INSTANCE_DEFINE(idx); \ + MU_IRQ_HANDLER(idx); + +DT_INST_FOREACH_STATUS_OKAY(MU_INST) diff --git a/dts/arm/nxp/nxp_rt5xx_common.dtsi b/dts/arm/nxp/nxp_rt5xx_common.dtsi index 9de7dfba991..5b24777f0c5 100644 --- a/dts/arm/nxp/nxp_rt5xx_common.dtsi +++ b/dts/arm/nxp/nxp_rt5xx_common.dtsi @@ -546,6 +546,15 @@ #address-cells = <3>; #size-cells = <0>; }; + + mbox:mbox@110000 { + compatible = "nxp,mbox-imx-mu"; + reg = <0x110000 0x100>; + interrupts = <34 0>; + rx-channels = <4>; + #mbox-cells = <1>; + status = "disabled"; + }; }; &flexspi { diff --git a/dts/bindings/mbox/nxp,mbox-imx-mu.yaml b/dts/bindings/mbox/nxp,mbox-imx-mu.yaml new file mode 100644 index 00000000000..bc8bb5d6abf --- /dev/null +++ b/dts/bindings/mbox/nxp,mbox-imx-mu.yaml @@ -0,0 +1,29 @@ +description: | + NXP i.MX Message Unit as Zephyr MBOX + +compatible: "nxp,mbox-imx-mu" + +include: [base.yaml, mailbox-controller.yaml] + +properties: + interrupts: + required: true + + rx-channels: + type: int + enum: [1, 2, 3, 4] + description: | + Number of receive channels enabled on this instance. + Setting this value to N, will enable channels 0 to N-1, consecutively. + It should be set by the receiver core coupled with this MU instance. + + For example, if receiver A wants to Rx on channels 0 to 3, then A must + set rx-channels of muA as follows: + + mruA { + rx-channels = <4>; + status = "okay"; + }; + +mbox-cells: + - channel diff --git a/samples/drivers/mbox/CMakeLists.txt b/samples/drivers/mbox/CMakeLists.txt index dd7ab115570..d94fdffbfb1 100644 --- a/samples/drivers/mbox/CMakeLists.txt +++ b/samples/drivers/mbox/CMakeLists.txt @@ -12,6 +12,8 @@ if("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpuapp") set(BOARD_REMOTE "nrf5340dk_nrf5340_cpunet") elseif("${BOARD}" STREQUAL "adp_xc7k_ae350") set(BOARD_REMOTE "adp_xc7k_ae350") +elseif("${BOARD}" STREQUAL "mimxrt595_evk_cm33") + set(BOARD_REMOTE "nrf5340dk_nrf5340_cpunet") else() message(FATAL_ERROR "${BOARD} is not supported for this sample") endif() diff --git a/samples/drivers/mbox/boards/mimxrt595_evk_cm33.conf b/samples/drivers/mbox/boards/mimxrt595_evk_cm33.conf new file mode 100644 index 00000000000..b01ff58e024 --- /dev/null +++ b/samples/drivers/mbox/boards/mimxrt595_evk_cm33.conf @@ -0,0 +1 @@ +CONFIG_MBOX_NXP_IMX_MU=y diff --git a/samples/drivers/mbox/sample.yaml b/samples/drivers/mbox/sample.yaml index 6d1ee5fd235..eb5e5ac1a5d 100644 --- a/samples/drivers/mbox/sample.yaml +++ b/samples/drivers/mbox/sample.yaml @@ -2,7 +2,10 @@ sample: name: MBOX IPC sample tests: sample.drivers.mbox: - platform_allow: nrf5340dk_nrf5340_cpuapp adp_xc7k_ae350 + platform_allow: + - nrf5340dk_nrf5340_cpuapp + - adp_xc7k_ae350 + - mimxrt595_evk_cm33 integration_platforms: - nrf5340dk_nrf5340_cpuapp tags: mbox diff --git a/west.yml b/west.yml index c690b2dd31a..f0005c12d4d 100644 --- a/west.yml +++ b/west.yml @@ -193,7 +193,7 @@ manifest: groups: - hal - name: hal_nxp - revision: 0ef57e8ee40f02f1dce4b4ad666c55885f941703 + revision: 06c956741a81eb0fd3c0c31367c3c177bffaaab8 path: modules/hal/nxp groups: - hal