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_event_rx
7
8 #include <zephyr/devicetree.h>
9 #include <zephyr/drivers/mbox.h>
10
11 #include <haly/nrfy_vpr.h>
12
13 #define EVENTS_IDX_MIN NRF_VPR_EVENTS_TRIGGERED_MIN
14 #define EVENTS_IDX_MAX NRF_VPR_EVENTS_TRIGGERED_MAX
15
16 #if defined(CONFIG_MBOX_NRF_VEVIF_EVENT_USE_54L_ERRATA_16)
17 #define VEVIF_54L_EVENT_IDX 20
18 BUILD_ASSERT(DT_INST_PROP(0, nordic_events) == 1);
19 BUILD_ASSERT(DT_INST_PROP(0, nordic_events_mask) & BIT(VEVIF_54L_EVENT_IDX));
20 #endif
21
22 /* callbacks */
23 struct mbox_vevif_event_rx_cbs {
24 mbox_callback_t cb[EVENTS_IDX_MAX - EVENTS_IDX_MIN + 1U];
25 void *user_data[EVENTS_IDX_MAX - EVENTS_IDX_MIN + 1U];
26 uint32_t enabled_mask;
27 };
28
29 struct mbox_vevif_event_rx_conf {
30 NRF_VPR_Type *vpr;
31 uint32_t events_mask;
32 uint8_t events;
33 void (*irq_connect)(void);
34 };
35
trigger_callback(const struct device * dev,struct mbox_vevif_event_rx_cbs * cbs,uint8_t id)36 static void trigger_callback(const struct device *dev, struct mbox_vevif_event_rx_cbs *cbs,
37 uint8_t id)
38 {
39 uint8_t idx = id - EVENTS_IDX_MIN;
40
41 if ((cbs->enabled_mask & BIT(id)) && (cbs->cb[idx] != NULL)) {
42 cbs->cb[idx](dev, id, cbs->user_data[idx], NULL);
43 }
44 }
45
vevif_event_rx_isr(const void * device)46 static void vevif_event_rx_isr(const void *device)
47 {
48 const struct device *dev = (struct device *)device;
49 struct mbox_vevif_event_rx_cbs *cbs = dev->data;
50
51 #if !defined(CONFIG_MBOX_NRF_VEVIF_EVENT_USE_54L_ERRATA_16)
52 const struct mbox_vevif_event_rx_conf *config = dev->config;
53
54 for (uint8_t id = EVENTS_IDX_MIN; id < EVENTS_IDX_MAX + 1U; id++) {
55 nrf_vpr_event_t event = nrfy_vpr_triggered_event_get(id);
56 if (nrfy_vpr_event_check(config->vpr, event)) {
57 nrfy_vpr_event_clear(config->vpr, event);
58 trigger_callback(dev, cbs, id);
59 }
60 }
61 #else
62 trigger_callback(dev, cbs, VEVIF_54L_EVENT_IDX);
63 #endif
64 }
65
vevif_event_rx_event_is_valid(uint32_t events_mask,uint32_t id)66 static inline bool vevif_event_rx_event_is_valid(uint32_t events_mask, uint32_t id)
67 {
68 return ((id <= EVENTS_IDX_MAX) && ((events_mask & BIT(id)) != 0U));
69 }
70
vevif_event_rx_max_channels_get(const struct device * dev)71 static uint32_t vevif_event_rx_max_channels_get(const struct device *dev)
72 {
73 const struct mbox_vevif_event_rx_conf *config = dev->config;
74
75 return config->events;
76 }
77
vevif_event_rx_register_callback(const struct device * dev,uint32_t id,mbox_callback_t cb,void * user_data)78 static int vevif_event_rx_register_callback(const struct device *dev, uint32_t id,
79 mbox_callback_t cb, void *user_data)
80 {
81 const struct mbox_vevif_event_rx_conf *config = dev->config;
82 struct mbox_vevif_event_rx_cbs *cbs = dev->data;
83 uint8_t idx = id - EVENTS_IDX_MIN;
84
85 if (!vevif_event_rx_event_is_valid(config->events_mask, id)) {
86 return -EINVAL;
87 }
88
89 cbs->cb[idx] = cb;
90 cbs->user_data[idx] = user_data;
91
92 return 0;
93 }
94
vevif_event_rx_set_enabled(const struct device * dev,uint32_t id,bool enable)95 static int vevif_event_rx_set_enabled(const struct device *dev, uint32_t id, bool enable)
96 {
97 const struct mbox_vevif_event_rx_conf *config = dev->config;
98 struct mbox_vevif_event_rx_cbs *cbs = dev->data;
99
100 if (!vevif_event_rx_event_is_valid(config->events_mask, id)) {
101 return -EINVAL;
102 }
103
104 if (enable) {
105 if ((cbs->enabled_mask & BIT(id)) != 0U) {
106 return -EALREADY;
107 }
108
109 cbs->enabled_mask |= BIT(id);
110 nrfy_vpr_int_enable(config->vpr, BIT(id));
111 } else {
112 if ((cbs->enabled_mask & BIT(id)) == 0U) {
113 return -EALREADY;
114 }
115
116 cbs->enabled_mask &= ~BIT(id);
117 nrfy_vpr_int_disable(config->vpr, BIT(id));
118 }
119
120 return 0;
121 }
122
123 static DEVICE_API(mbox, vevif_event_rx_driver_api) = {
124 .max_channels_get = vevif_event_rx_max_channels_get,
125 .register_callback = vevif_event_rx_register_callback,
126 .set_enabled = vevif_event_rx_set_enabled,
127 };
128
vevif_event_rx_init(const struct device * dev)129 static int vevif_event_rx_init(const struct device *dev)
130 {
131 const struct mbox_vevif_event_rx_conf *config = dev->config;
132
133 config->irq_connect();
134
135 return 0;
136 }
137
138 #define VEVIF_EVENT_RX_DEFINE(inst) \
139 BUILD_ASSERT(DT_INST_PROP(inst, nordic_events) <= NRF_VPR_EVENTS_TRIGGERED_COUNT, \
140 "Number of events exceeds maximum"); \
141 \
142 static void irq_connect##inst(void) \
143 { \
144 IRQ_CONNECT(DT_IRQN(DT_DRV_INST(inst)), DT_IRQ(DT_DRV_INST(inst), priority), \
145 vevif_event_rx_isr, (const void *)DEVICE_DT_GET(DT_DRV_INST(inst)), \
146 0); \
147 irq_enable(DT_IRQN(DT_DRV_INST(inst))); \
148 }; \
149 \
150 static struct mbox_vevif_event_rx_cbs data##inst = { \
151 .enabled_mask = 0, \
152 }; \
153 static const struct mbox_vevif_event_rx_conf conf##inst = { \
154 .vpr = (NRF_VPR_Type *)DT_REG_ADDR(DT_INST_PARENT(inst)), \
155 .events = DT_INST_PROP(inst, nordic_events), \
156 .events_mask = DT_INST_PROP(inst, nordic_events_mask), \
157 .irq_connect = irq_connect##inst, \
158 }; \
159 \
160 DEVICE_DT_INST_DEFINE(inst, vevif_event_rx_init, NULL, &data##inst, &conf##inst, \
161 POST_KERNEL, CONFIG_MBOX_INIT_PRIORITY, &vevif_event_rx_driver_api);
162
163 DT_INST_FOREACH_STATUS_OKAY(VEVIF_EVENT_RX_DEFINE)
164