1 /*
2 * Copyright (c) 2021 - 2025, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <nrfx.h>
35
36 #if NRFX_CHECK(NRFX_BELLBOARD_ENABLED)
37
38 #include <nrfx_bellboard.h>
39 #include <nrf_bitmask.h>
40
41 #define NRFX_LOG_MODULE BELLBOARD
42 #include <nrfx_log.h>
43
44 typedef struct
45 {
46 nrfx_bellboard_event_handler_t handler;
47 void * context;
48 uint32_t int_pend;
49 uint8_t int_idx;
50 nrfx_drv_state_t state;
51 } nrfx_bellboard_cb_t;
52
53 static nrfx_bellboard_cb_t m_cb[NRFX_BELLBOARD_ENABLED_COUNT];
54
nrfx_bellboard_init(nrfx_bellboard_t const * p_instance,uint8_t interrupt_priority,nrfx_bellboard_event_handler_t event_handler,void * p_context)55 nrfx_err_t nrfx_bellboard_init(nrfx_bellboard_t const * p_instance,
56 uint8_t interrupt_priority,
57 nrfx_bellboard_event_handler_t event_handler,
58 void * p_context)
59 {
60 nrfx_bellboard_cb_t * p_cb = &m_cb[p_instance->drv_inst_idx];
61 nrfx_err_t err_code = NRFX_SUCCESS;
62
63 if (p_cb->state == NRFX_DRV_STATE_INITIALIZED)
64 {
65 #if NRFX_API_VER_AT_LEAST(3, 2, 0)
66 err_code = NRFX_ERROR_ALREADY;
67 #else
68 err_code = NRFX_ERROR_INVALID_STATE;
69 #endif
70 NRFX_LOG_WARNING("Function: %s, error code: %s.",
71 __func__,
72 NRFX_LOG_ERROR_STRING_GET(err_code));
73 return err_code;
74 }
75
76 p_cb->state = NRFX_DRV_STATE_INITIALIZED;
77 p_cb->handler = event_handler;
78 p_cb->context = p_context;
79 p_cb->int_idx = p_instance->int_idx;
80
81 nrfy_bellboard_int_init(NRF_BELLBOARD,
82 0,
83 interrupt_priority,
84 false,
85 p_instance->int_idx);
86
87 NRFX_LOG_INFO("Initialized.");
88 return err_code;
89 }
90
nrfx_bellboard_uninit(nrfx_bellboard_t const * p_instance)91 void nrfx_bellboard_uninit(nrfx_bellboard_t const * p_instance)
92 {
93 NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_INITIALIZED);
94
95 nrfy_bellboard_int_uninit(p_instance->int_idx);
96
97 nrfx_bellboard_cb_t * p_cb = &m_cb[p_instance->drv_inst_idx];
98
99 p_cb->handler = NULL;
100 p_cb->int_idx = 0;
101 p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
102 NRFX_LOG_INFO("Uninitialized.");
103 }
104
nrfx_bellboard_init_check(nrfx_bellboard_t const * p_instance)105 bool nrfx_bellboard_init_check(nrfx_bellboard_t const * p_instance)
106 {
107 nrfx_bellboard_cb_t * p_cb = &m_cb[p_instance->drv_inst_idx];
108
109 return (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
110 }
111
nrfx_bellboard_int_enable(nrfx_bellboard_t const * p_instance,uint32_t mask)112 void nrfx_bellboard_int_enable(nrfx_bellboard_t const * p_instance, uint32_t mask)
113 {
114 NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_INITIALIZED);
115
116 nrfy_bellboard_int_enable(NRF_BELLBOARD, p_instance->int_idx, mask);
117 }
118
nrfx_bellboard_int_disable(nrfx_bellboard_t const * p_instance,uint32_t mask)119 void nrfx_bellboard_int_disable(nrfx_bellboard_t const * p_instance, uint32_t mask)
120 {
121 NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_INITIALIZED);
122
123 nrfy_bellboard_int_disable(NRF_BELLBOARD, p_instance->int_idx, mask);
124 }
125
irq_handler(void * unused,nrfx_bellboard_cb_t * p_cb)126 static void irq_handler(void * unused, nrfx_bellboard_cb_t * p_cb)
127 {
128 (void)unused;
129 /* Pending interrupts registers are cleared when event is cleared.
130 * Add current pending interrupts to be processed later.
131 */
132 for (uint8_t i = 0; i < NRFX_BELLBOARD_ENABLED_COUNT; i++)
133 {
134 if (m_cb[i].state == NRFX_DRV_STATE_INITIALIZED)
135 {
136 m_cb[i].int_pend |= nrfy_bellboard_int_pending_get(NRF_BELLBOARD, m_cb[i].int_idx);
137 }
138 }
139
140 uint32_t int_pend = p_cb->int_pend;
141 p_cb->int_pend = 0;
142
143 (void)nrfy_bellboard_events_process(NRF_BELLBOARD, int_pend);
144
145 if (p_cb->handler != NULL)
146 {
147 while (int_pend)
148 {
149 uint8_t event_no = (uint8_t)NRF_CTZ(int_pend);
150 p_cb->handler(event_no, p_cb->context);
151 nrf_bitmask_bit_clear(event_no, &int_pend);
152 }
153 }
154 }
155
156 NRFX_INSTANCE_IRQ_HANDLERS(BELLBOARD, bellboard)
157
158 #endif // NRFX_CHECK(NRFX_BELLBOARD_ENABLED)
159