mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-08-03 23:43:35 +00:00
Turn MCX series into families. Reasoning: 1. The MCX SOCs are quite different from each other and having them all under one family in the HWMv2 hierarchy is fruitless because there are so many differences that it is confusing to try to introduce family-level code and configs since they would each only apply to a subset of the series. There is almost nothing that can be shared between all of them. Which is why there are comments in the MCX family files saying not to put anything in them. This is a technical waste. 2. Therefore, turning all of them into families is almost 0 effort and makes sense. It will allow these different types of MCX to be further subdivided into series in the future as the MCX portfolio expands and such division will be necessary as new SOCs within each letter family are released. Signed-off-by: Declan Snyder <declan.snyder@nxp.com>
225 lines
5.5 KiB
C
225 lines
5.5 KiB
C
/*
|
|
* Copyright (c) 2017-2018, 2024 NXP
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#define DT_DRV_COMPAT nxp_lpc_mailbox
|
|
|
|
#include <errno.h>
|
|
#include <zephyr/device.h>
|
|
#include <zephyr/drivers/ipm.h>
|
|
#include <fsl_mailbox.h>
|
|
#include <fsl_clock.h>
|
|
#include <soc.h>
|
|
#include <zephyr/irq.h>
|
|
#include <zephyr/sys/barrier.h>
|
|
#include <zephyr/drivers/reset.h>
|
|
#include <zephyr/sys/util_macro.h>
|
|
|
|
#define MCUX_IPM_DATA_REGS 1
|
|
#define MCUX_IPM_MAX_ID_VAL 0
|
|
|
|
#if (defined(LPC55S69_cm33_core0_SERIES) || defined(LPC55S69_cm33_core1_SERIES) || \
|
|
defined(CONFIG_SOC_FAMILY_MCXN))
|
|
#if (defined(LPC55S69_cm33_core0_SERIES) || defined(MCXN947_cm33_core0_SERIES) || \
|
|
defined(MCXN946_cm33_core0_SERIES) || defined(MCXN547_cm33_core0_SERIES) || \
|
|
defined(MCXN546_cm33_core0_SERIES))
|
|
#define MAILBOX_ID_THIS_CPU kMAILBOX_CM33_Core0
|
|
#define MAILBOX_ID_OTHER_CPU kMAILBOX_CM33_Core1
|
|
#else
|
|
#define MAILBOX_ID_THIS_CPU kMAILBOX_CM33_Core1
|
|
#define MAILBOX_ID_OTHER_CPU kMAILBOX_CM33_Core0
|
|
#endif
|
|
#else
|
|
#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
|
|
#endif
|
|
|
|
#define MAILBOX_USES_RESET COND_CODE_1(DT_ANY_INST_HAS_PROP_STATUS_OKAY(resets), (true), (false))
|
|
|
|
struct mcux_mailbox_config {
|
|
MAILBOX_Type *base;
|
|
void (*irq_config_func)(const struct device *dev);
|
|
const struct reset_dt_spec reset;
|
|
};
|
|
|
|
struct mcux_mailbox_data {
|
|
ipm_callback_t callback;
|
|
void *callback_ctx;
|
|
};
|
|
|
|
static void mcux_mailbox_isr(const struct device *dev)
|
|
{
|
|
struct mcux_mailbox_data *data = dev->data;
|
|
const struct mcux_mailbox_config *config = dev->config;
|
|
mailbox_cpu_id_t cpu_id;
|
|
|
|
cpu_id = MAILBOX_ID_THIS_CPU;
|
|
|
|
volatile uint32_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(dev, 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)
|
|
barrier_dsync_fence_full();
|
|
#endif
|
|
}
|
|
|
|
|
|
static int mcux_mailbox_ipm_send(const struct device *d, int wait,
|
|
uint32_t id,
|
|
const void *data, int size)
|
|
{
|
|
const struct mcux_mailbox_config *config = d->config;
|
|
MAILBOX_Type *base = config->base;
|
|
/* Until we change API to uint32_t array */
|
|
uint32_t data32[MCUX_IPM_DATA_REGS] = {0};
|
|
unsigned int flags;
|
|
int i;
|
|
|
|
ARG_UNUSED(wait);
|
|
|
|
if (id > MCUX_IPM_MAX_ID_VAL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if ((size < 0) || (size > MCUX_IPM_DATA_REGS * sizeof(uint32_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(const struct device *d)
|
|
{
|
|
ARG_UNUSED(d);
|
|
/* Only a single 32-bit register available */
|
|
return MCUX_IPM_DATA_REGS*sizeof(uint32_t);
|
|
}
|
|
|
|
|
|
static uint32_t mcux_mailbox_ipm_max_id_val_get(const 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(const struct device *d,
|
|
ipm_callback_t cb,
|
|
void *context)
|
|
{
|
|
struct mcux_mailbox_data *driver_data = d->data;
|
|
|
|
driver_data->callback = cb;
|
|
driver_data->callback_ctx = context;
|
|
}
|
|
|
|
|
|
static int mcux_mailbox_ipm_set_enabled(const struct device *d, int enable)
|
|
{
|
|
/* For now: nothing to be done */
|
|
return 0;
|
|
}
|
|
|
|
static inline int mcux_mailbox_reset(const struct device *dev)
|
|
{
|
|
const struct mcux_mailbox_config *config = dev->config;
|
|
int ret = 0;
|
|
|
|
/* on some platforms, explicit reset is not needed or possible for the mailbox */
|
|
if (!MAILBOX_USES_RESET) {
|
|
return 0;
|
|
}
|
|
|
|
if (!device_is_ready(config->reset.dev)) {
|
|
ret = -ENODEV;
|
|
} else {
|
|
ret = reset_line_toggle(config->reset.dev, config->reset.id);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int mcux_mailbox_init(const struct device *dev)
|
|
{
|
|
const struct mcux_mailbox_config *config = dev->config;
|
|
int ret = 0;
|
|
|
|
ret = mcux_mailbox_reset(dev);
|
|
if (ret) {
|
|
return ret;
|
|
}
|
|
|
|
MAILBOX_Init(config->base);
|
|
config->irq_config_func(dev);
|
|
return 0;
|
|
}
|
|
|
|
static DEVICE_API(ipm, 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(const struct device *dev);
|
|
|
|
static const struct mcux_mailbox_config mcux_mailbox_0_config = {
|
|
.base = (MAILBOX_Type *)DT_INST_REG_ADDR(0),
|
|
.irq_config_func = mcux_mailbox_config_func_0,
|
|
.reset = RESET_DT_SPEC_INST_GET_OR(0, {0}),
|
|
};
|
|
|
|
static struct mcux_mailbox_data mcux_mailbox_0_data;
|
|
|
|
DEVICE_DT_INST_DEFINE(0,
|
|
&mcux_mailbox_init,
|
|
NULL,
|
|
&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(const struct device *dev)
|
|
{
|
|
IRQ_CONNECT(DT_INST_IRQN(0),
|
|
DT_INST_IRQ(0, priority),
|
|
mcux_mailbox_isr, DEVICE_DT_INST_GET(0), 0);
|
|
|
|
irq_enable(DT_INST_IRQN(0));
|
|
}
|