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