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