1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #define DT_DRV_COMPAT nordic_nrf_vevif_task_rx
7
8 #include <zephyr/devicetree.h>
9 #include <zephyr/drivers/mbox.h>
10
11 #include <hal/nrf_vpr.h>
12 #include <hal/nrf_vpr_csr.h>
13 #include <hal/nrf_vpr_csr_vevif.h>
14
15 #define TASKS_IDX_MIN NRF_VPR_TASKS_TRIGGER_MIN
16 #define TASKS_IDX_MAX NRF_VPR_TASKS_TRIGGER_MAX
17
18 #define VEVIF_TASKS_NUM DT_INST_PROP(0, nordic_tasks)
19 #define VEVIF_TASKS_MASK DT_INST_PROP(0, nordic_tasks_mask)
20
21 BUILD_ASSERT(VEVIF_TASKS_NUM <= VPR_TASKS_TRIGGER_MaxCount, "Number of tasks exceeds maximum");
22 BUILD_ASSERT(VEVIF_TASKS_NUM == DT_NUM_IRQS(DT_DRV_INST(0)), "# IRQs != # tasks");
23
24 /* callbacks */
25 struct mbox_vevif_task_rx_cbs {
26 mbox_callback_t cb[TASKS_IDX_MAX - TASKS_IDX_MIN + 1U];
27 void *user_data[TASKS_IDX_MAX - TASKS_IDX_MIN + 1U];
28 uint32_t enabled_mask;
29 };
30
31 static struct mbox_vevif_task_rx_cbs cbs;
32
33 /* IRQ list */
34 #define VEVIF_IRQN(idx, _) DT_INST_IRQ_BY_IDX(0, idx, irq)
35
36 static const uint8_t vevif_irqs[VEVIF_TASKS_NUM] = {
37 LISTIFY(DT_NUM_IRQS(DT_DRV_INST(0)), VEVIF_IRQN, (,))
38 };
39
vevif_task_rx_isr(const void * parameter)40 static void vevif_task_rx_isr(const void *parameter)
41 {
42 uint8_t channel = *(uint8_t *)parameter;
43 uint8_t idx = channel - TASKS_IDX_MIN;
44
45 nrf_vpr_csr_vevif_tasks_clear(BIT(channel));
46
47 if (cbs.cb[idx] != NULL) {
48 cbs.cb[idx](DEVICE_DT_INST_GET(0), channel, cbs.user_data[idx], NULL);
49 }
50 }
51
vevif_task_rx_is_task_valid(uint32_t id)52 static inline bool vevif_task_rx_is_task_valid(uint32_t id)
53 {
54 return ((id <= TASKS_IDX_MAX) && ((VEVIF_TASKS_MASK & BIT(id)) != 0U));
55 }
56
vevif_task_rx_max_channels_get(const struct device * dev)57 static uint32_t vevif_task_rx_max_channels_get(const struct device *dev)
58 {
59 ARG_UNUSED(dev);
60
61 return VEVIF_TASKS_NUM;
62 }
63
vevif_task_rx_register_callback(const struct device * dev,uint32_t id,mbox_callback_t cb,void * user_data)64 static int vevif_task_rx_register_callback(const struct device *dev, uint32_t id,
65 mbox_callback_t cb, void *user_data)
66 {
67 ARG_UNUSED(dev);
68 uint8_t idx = id - TASKS_IDX_MIN;
69
70 if (!vevif_task_rx_is_task_valid(id)) {
71 return -EINVAL;
72 }
73
74 cbs.cb[idx] = cb;
75 cbs.user_data[idx] = user_data;
76
77 return 0;
78 }
79
vevif_task_rx_set_enabled(const struct device * dev,uint32_t id,bool enable)80 static int vevif_task_rx_set_enabled(const struct device *dev, uint32_t id, bool enable)
81 {
82 ARG_UNUSED(dev);
83 uint8_t idx = id - TASKS_IDX_MIN;
84
85 if (!vevif_task_rx_is_task_valid(id)) {
86 return -EINVAL;
87 }
88
89 if (enable) {
90 if ((cbs.enabled_mask & BIT(id)) != 0U) {
91 return -EALREADY;
92 }
93
94 cbs.enabled_mask |= BIT(id);
95 irq_enable(vevif_irqs[idx]);
96 } else {
97 if ((cbs.enabled_mask & BIT(id)) == 0U) {
98 return -EALREADY;
99 }
100
101 cbs.enabled_mask &= ~BIT(id);
102 irq_disable(vevif_irqs[idx]);
103 }
104
105 return 0;
106 }
107
108 static DEVICE_API(mbox, vevif_task_rx_driver_api) = {
109 .max_channels_get = vevif_task_rx_max_channels_get,
110 .register_callback = vevif_task_rx_register_callback,
111 .set_enabled = vevif_task_rx_set_enabled,
112 };
113
114 #if defined(CONFIG_GEN_SW_ISR_TABLE)
115 #define VEVIF_IRQ_CONNECT(idx, _) \
116 IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, idx, irq), DT_INST_IRQ_BY_IDX(0, idx, priority), \
117 vevif_task_rx_isr, &vevif_irqs[idx], 0)
118 #else
119
120 #define VEVIF_IRQ_FUN(idx, _) \
121 ISR_DIRECT_DECLARE(vevif_task_##idx##_rx_isr) \
122 { \
123 vevif_task_rx_isr(&vevif_irqs[idx]); \
124 return 1; \
125 }
126
127 LISTIFY(DT_NUM_IRQS(DT_DRV_INST(0)), VEVIF_IRQ_FUN, ())
128
129 #define VEVIF_IRQ_CONNECT(idx, _) \
130 IRQ_DIRECT_CONNECT(DT_INST_IRQ_BY_IDX(0, idx, irq), DT_INST_IRQ_BY_IDX(0, idx, priority), \
131 vevif_task_##idx##_rx_isr, 0)
132 #endif
133
vevif_task_rx_init(const struct device * dev)134 static int vevif_task_rx_init(const struct device *dev)
135 {
136 nrf_vpr_csr_vevif_tasks_clear(NRF_VPR_TASK_TRIGGER_ALL_MASK);
137
138 LISTIFY(DT_NUM_IRQS(DT_DRV_INST(0)), VEVIF_IRQ_CONNECT, (;));
139
140 return 0;
141 }
142
143 DEVICE_DT_INST_DEFINE(0, vevif_task_rx_init, NULL, NULL, NULL, POST_KERNEL,
144 CONFIG_MBOX_INIT_PRIORITY, &vevif_task_rx_driver_api);
145