mcux: Add MCUX IPM driver for lpc and kinetis socs
Add driver for MCUX mailbox which can be used for lpcxpresso54114
and other lpc and kinetis socs.
Origin: Original
Signed-off-by: Stanislav Poboril <stanislav.poboril@nxp.com>
diff --git a/arch/arm/soc/nxp_lpc/lpc54xxx/dts.fixup b/arch/arm/soc/nxp_lpc/lpc54xxx/dts.fixup
index 4e3de15..f9903af 100644
--- a/arch/arm/soc/nxp_lpc/lpc54xxx/dts.fixup
+++ b/arch/arm/soc/nxp_lpc/lpc54xxx/dts.fixup
@@ -17,4 +17,9 @@
#define CONFIG_USART_MCUX_LPC_0_IRQ_PRI NXP_LPC_USART_40086000_IRQ_0_PRIORITY
#define CONFIG_USART_MCUX_LPC_0_NAME NXP_LPC_USART_40086000_LABEL
+#define CONFIG_MAILBOX_MCUX_MAILBOX_0_IRQ NXP_LPC_MAILBOX_4008B000_IRQ_0
+#define CONFIG_MAILBOX_MCUX_MAILBOX_0_IRQ_PRI NXP_LPC_MAILBOX_4008B000_IRQ_0_PRIORITY
+#define CONFIG_MAILBOX_MCUX_MAILBOX_0_NAME NXP_LPC_MAILBOX_4008B000_LABEL
+#define CONFIG_MAILBOX_MCUX_MAILBOX_0_BASE_ADDRESS NXP_LPC_MAILBOX_4008B000_BASE_ADDRESS
+
/* End of SoC Level DTS fixup file */
diff --git a/boards/arm/lpcxpresso54114_m0/lpcxpresso54114_m0.dts b/boards/arm/lpcxpresso54114_m0/lpcxpresso54114_m0.dts
index 33374d5..925fd43 100644
--- a/boards/arm/lpcxpresso54114_m0/lpcxpresso54114_m0.dts
+++ b/boards/arm/lpcxpresso54114_m0/lpcxpresso54114_m0.dts
@@ -14,6 +14,7 @@
aliases {
usart-0 = &usart0;
+ mailbox-0 = &mailbox0;
led0 = &red_led;
led1 = &green_led;
led2 = &blue_led;
@@ -46,3 +47,7 @@
status = "disabled"; /* enable for console, if needed */
current-speed = <115200>;
};
+
+&mailbox0 {
+ status = "ok";
+};
diff --git a/boards/arm/lpcxpresso54114_m4/lpcxpresso54114_m4.dts b/boards/arm/lpcxpresso54114_m4/lpcxpresso54114_m4.dts
index 4a2881d..7f5633c 100644
--- a/boards/arm/lpcxpresso54114_m4/lpcxpresso54114_m4.dts
+++ b/boards/arm/lpcxpresso54114_m4/lpcxpresso54114_m4.dts
@@ -14,6 +14,7 @@
aliases{
usart-0 = &usart0;
+ mailbox-0 = &mailbox0;
led0 = &red_led;
led1 = &green_led;
led2 = &blue_led;
@@ -46,3 +47,7 @@
status = "ok";
current-speed = <115200>;
};
+
+&mailbox0 {
+ status = "ok";
+};
diff --git a/drivers/ipm/CMakeLists.txt b/drivers/ipm/CMakeLists.txt
index bbff9cc..3121e87 100644
--- a/drivers/ipm/CMakeLists.txt
+++ b/drivers/ipm/CMakeLists.txt
@@ -1,5 +1,6 @@
zephyr_library()
+zephyr_library_sources_ifdef(CONFIG_IPM_MCUX ipm_mcux.c)
zephyr_library_sources_ifdef(CONFIG_IPM_QUARK_SE ipm_quark_se.c)
zephyr_library_sources_ifdef(CONFIG_USERSPACE ipm_handlers.c)
diff --git a/drivers/ipm/Kconfig b/drivers/ipm/Kconfig
index 9ff83ff..25d8214 100644
--- a/drivers/ipm/Kconfig
+++ b/drivers/ipm/Kconfig
@@ -22,3 +22,9 @@
Sets up the initial interrupt mask and clears out all
channels. Should be turned on for one CPU only.
+config IPM_MCUX
+ bool "MCUX IPM driver"
+ default n
+ depends on IPM && HAS_MCUX
+ help
+ Driver for MCUX mailbox
diff --git a/drivers/ipm/ipm_mcux.c b/drivers/ipm/ipm_mcux.c
new file mode 100644
index 0000000..95aedee
--- /dev/null
+++ b/drivers/ipm/ipm_mcux.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2017-2018, NXP
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+#include <device.h>
+#include <ipm.h>
+#include <fsl_mailbox.h>
+#include <fsl_clock.h>
+#include <soc.h>
+
+#define MCUX_IPM_DATA_REGS 1
+#define MCUX_IPM_MAX_ID_VAL 0
+
+#if defined(__CM4_CMSIS_VERSION)
+#define MAILBOX_ID_THIS_CPU kMAILBOX_CM4
+#define MAILBOX_ID_OTHER_CPU kMAILBOX_CM0Plus
+#else
+#define MAILBOX_ID_THIS_CPU kMAILBOX_CM0Plus
+#define MAILBOX_ID_OTHER_CPU kMAILBOX_CM4
+#endif
+
+struct mcux_mailbox_config {
+ MAILBOX_Type *base;
+ void (*irq_config_func)(struct device *dev);
+};
+
+struct mcux_mailbox_data {
+ ipm_callback_t callback;
+ void *callback_ctx;
+};
+
+static void mcux_mailbox_isr(void *arg)
+{
+ struct device *dev = arg;
+ struct mcux_mailbox_data *data = dev->driver_data;
+ const struct mcux_mailbox_config *config = dev->config->config_info;
+ mailbox_cpu_id_t cpu_id;
+
+ cpu_id = MAILBOX_ID_THIS_CPU;
+
+ volatile u32_t value = MAILBOX_GetValue(config->base, cpu_id);
+
+ __ASSERT(value, "spurious MAILBOX interrupt");
+
+ /* Clear or the interrupt gets called intermittently */
+ MAILBOX_ClearValueBits(config->base, cpu_id, value);
+
+ if (data->callback) {
+ /* Only one MAILBOX, id is unused and set to 0 */
+ data->callback(data->callback_ctx, 0, &value);
+ }
+ /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F
+ * Store immediate overlapping exception return operation
+ * might vector to incorrect interrupt
+ */
+#if defined __CORTEX_M && (__CORTEX_M == 4U)
+ __DSB();
+#endif
+}
+
+
+static int mcux_mailbox_ipm_send(struct device *d, int wait, u32_t id,
+ const void *data, int size)
+{
+ const struct mcux_mailbox_config *config = d->config->config_info;
+ MAILBOX_Type *base = config->base;
+ u32_t data32[MCUX_IPM_DATA_REGS]; /* Until we change API
+ * to u32_t array
+ */
+ int flags;
+ int i;
+
+ ARG_UNUSED(wait);
+
+ if (id > MCUX_IPM_MAX_ID_VAL) {
+ return -EINVAL;
+ }
+
+ if (size > MCUX_IPM_DATA_REGS * sizeof(u32_t)) {
+ return -EMSGSIZE;
+ }
+
+ flags = irq_lock();
+
+ /* Actual message is passing using 32 bits registers */
+ memcpy(data32, data, size);
+
+ for (i = 0; i < ARRAY_SIZE(data32); ++i) {
+ MAILBOX_SetValueBits(base, MAILBOX_ID_OTHER_CPU, data32[i]);
+ }
+
+ irq_unlock(flags);
+
+ return 0;
+}
+
+
+static int mcux_mailbox_ipm_max_data_size_get(struct device *d)
+{
+ ARG_UNUSED(d);
+ /* Only a single 32-bit register available */
+ return MCUX_IPM_DATA_REGS*sizeof(u32_t);
+}
+
+
+static u32_t mcux_mailbox_ipm_max_id_val_get(struct device *d)
+{
+ ARG_UNUSED(d);
+ /* Only a single instance of MAILBOX available for this platform */
+ return MCUX_IPM_MAX_ID_VAL;
+}
+
+static void mcux_mailbox_ipm_register_callback(struct device *d,
+ ipm_callback_t cb,
+ void *context)
+{
+ struct mcux_mailbox_data *driver_data = d->driver_data;
+
+ driver_data->callback = cb;
+ driver_data->callback_ctx = context;
+}
+
+
+static int mcux_mailbox_ipm_set_enabled(struct device *d, int enable)
+{
+ /* For now: nothing to be done */
+ return 0;
+}
+
+
+static int mcux_mailbox_init(struct device *dev)
+{
+ const struct mcux_mailbox_config *config = dev->config->config_info;
+
+ MAILBOX_Init(config->base);
+ config->irq_config_func(dev);
+ return 0;
+}
+
+static const struct ipm_driver_api mcux_mailbox_driver_api = {
+ .send = mcux_mailbox_ipm_send,
+ .register_callback = mcux_mailbox_ipm_register_callback,
+ .max_data_size_get = mcux_mailbox_ipm_max_data_size_get,
+ .max_id_val_get = mcux_mailbox_ipm_max_id_val_get,
+ .set_enabled = mcux_mailbox_ipm_set_enabled
+};
+
+
+/* Config MAILBOX 0 */
+
+static void mcux_mailbox_config_func_0(struct device *dev);
+
+static const struct mcux_mailbox_config mcux_mailbox_0_config = {
+ .base = (MAILBOX_Type *)CONFIG_MAILBOX_MCUX_MAILBOX_0_BASE_ADDRESS,
+ .irq_config_func = mcux_mailbox_config_func_0,
+};
+
+static struct mcux_mailbox_data mcux_mailbox_0_data;
+
+DEVICE_AND_API_INIT(mailbox_0, CONFIG_MAILBOX_MCUX_MAILBOX_0_NAME,
+ &mcux_mailbox_init,
+ &mcux_mailbox_0_data, &mcux_mailbox_0_config,
+ PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+ &mcux_mailbox_driver_api);
+
+
+static void mcux_mailbox_config_func_0(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_MAILBOX_MCUX_MAILBOX_0_IRQ,
+ CONFIG_MAILBOX_MCUX_MAILBOX_0_IRQ_PRI,
+ mcux_mailbox_isr, DEVICE_GET(mailbox_0), 0);
+
+ irq_enable(CONFIG_MAILBOX_MCUX_MAILBOX_0_IRQ);
+}
diff --git a/dts/arm/nxp/nxp_lpc54xxx.dtsi b/dts/arm/nxp/nxp_lpc54xxx.dtsi
index 388083d..61d6115 100644
--- a/dts/arm/nxp/nxp_lpc54xxx.dtsi
+++ b/dts/arm/nxp/nxp_lpc54xxx.dtsi
@@ -67,6 +67,14 @@
gpio-controller;
#gpio-cells = <2>;
};
+
+ mailbox0:mailbox@4008B000 {
+ compatible = "nxp,lpc-mailbox";
+ reg = <0x4008B000 0xEC>;
+ interrupts = <31 0>;
+ label = "MAILBOX_0";
+ status = "disabled";
+ };
};
};
diff --git a/dts/bindings/arm/nxp,lpc-mailbox.yaml b/dts/bindings/arm/nxp,lpc-mailbox.yaml
new file mode 100644
index 0000000..d2b9dca
--- /dev/null
+++ b/dts/bindings/arm/nxp,lpc-mailbox.yaml
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2017, NXP
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+---
+title: LPC MAILBOX
+id: nxp,lpc-mailbox
+version: 0.1
+
+description: >
+ This binding gives a base representation of the LPC MAILBOX
+
+properties:
+ compatible:
+ type: string
+ category: required
+ description: compatible strings
+ constraint: "nxp,lpc-mailbox"
+
+ reg:
+ type: array
+ description: mmio register space
+ generation: define
+ category: required
+
+ interrupts:
+ type: array
+ category: required
+ description: required interrupts
+ generation: define
+
+ label:
+ type: string
+ category: required
+ description: Human readable string describing the device (used by Zephyr for API name)
+ generation: define
+
+...