/* * Copyright (c) 2024 Nordic Semiconductor ASA * SPDX-License-Identifier: Apache-2.0 */ #define DT_DRV_COMPAT nordic_nrf_vevif_local #include #include #include #include #include #define VEVIF_TASKS_NUM DT_INST_PROP(0, nordic_tasks) #define VEVIF_TASKS_MASK DT_INST_PROP(0, nordic_tasks_mask) BUILD_ASSERT(VEVIF_TASKS_NUM <= VPR_TASKS_TRIGGER_MaxCount, "Number of tasks exceeds maximum"); BUILD_ASSERT(VEVIF_TASKS_NUM == DT_NUM_IRQS(DT_DRV_INST(0)), "# IRQs != # tasks"); /* callbacks */ struct mbox_vevif_local_cbs { mbox_callback_t cb[VEVIF_TASKS_NUM]; void *user_data[VEVIF_TASKS_NUM]; uint32_t enabled_mask; }; static struct mbox_vevif_local_cbs cbs; /* IRQ list */ #define VEVIF_IRQN(idx, _) DT_INST_IRQ_BY_IDX(0, idx, irq) static const uint8_t vevif_irqs[VEVIF_TASKS_NUM] = { LISTIFY(DT_NUM_IRQS(DT_DRV_INST(0)), VEVIF_IRQN, (,)) }; static void vevif_local_isr(const void *parameter) { uint8_t id = *(uint8_t *)parameter; nrf_vpr_csr_vevif_tasks_clear(BIT(id)); if (cbs.cb[id] != NULL) { cbs.cb[id](DEVICE_DT_INST_GET(0), id, cbs.user_data[id], NULL); } } static inline bool vevif_local_is_task_valid(uint32_t id) { return (id < VEVIF_TASKS_NUM) && ((VEVIF_TASKS_MASK & BIT(id)) != 0U); } static uint32_t vevif_local_max_channels_get(const struct device *dev) { ARG_UNUSED(dev); return VEVIF_TASKS_NUM; } static int vevif_local_register_callback(const struct device *dev, uint32_t id, mbox_callback_t cb, void *user_data) { ARG_UNUSED(dev); if (!vevif_local_is_task_valid(id)) { return -EINVAL; } cbs.cb[id] = cb; cbs.user_data[id] = user_data; return 0; } static int vevif_local_set_enabled(const struct device *dev, uint32_t id, bool enable) { ARG_UNUSED(dev); if (!vevif_local_is_task_valid(id)) { return -EINVAL; } if (enable) { if ((cbs.enabled_mask & BIT(id)) != 0U) { return -EALREADY; } cbs.enabled_mask |= BIT(id); irq_enable(vevif_irqs[id]); } else { if ((cbs.enabled_mask & BIT(id)) == 0U) { return -EALREADY; } cbs.enabled_mask &= ~BIT(id); irq_disable(vevif_irqs[id]); } return 0; } static const struct mbox_driver_api vevif_local_driver_api = { .max_channels_get = vevif_local_max_channels_get, .register_callback = vevif_local_register_callback, .set_enabled = vevif_local_set_enabled, }; #define VEVIF_IRQ_CONNECT(idx, _) \ IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, idx, irq), DT_INST_IRQ_BY_IDX(0, idx, priority), \ vevif_local_isr, &vevif_irqs[idx], 0) static int vevif_local_init(const struct device *dev) { nrf_vpr_csr_vevif_tasks_clear(NRF_VPR_TASK_TRIGGER_ALL_MASK); LISTIFY(DT_NUM_IRQS(DT_DRV_INST(0)), VEVIF_IRQ_CONNECT, (;)); return 0; } DEVICE_DT_INST_DEFINE(0, vevif_local_init, NULL, NULL, NULL, POST_KERNEL, CONFIG_MBOX_INIT_PRIORITY, &vevif_local_driver_api);