1 /*
2  * Copyright (c) 2017 - 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_PRS_ENABLED)
37 #include "nrfx_prs.h"
38 
39 #define NRFX_LOG_MODULE PRS
40 #include <nrfx_log.h>
41 
42 #define LOG_FUNCTION_EXIT(level, ret_code)            \
43     NRFX_LOG_##level("Function: %s, error code: %s.", \
44         __func__,                                     \
45         NRFX_LOG_ERROR_STRING_GET(ret_code))
46 
47 
48 typedef struct {
49     nrfx_irq_handler_t handler;
50     bool               acquired;
51 } prs_box_t;
52 
53 #define PRS_BOX_DEFINE(n)                                                    \
54     static prs_box_t m_prs_box_##n = { .handler = NULL, .acquired = false }; \
55     void nrfx_prs_box_##n##_irq_handler(void)                                \
56     {                                                                        \
57         NRFX_ASSERT(m_prs_box_##n.handler);                                  \
58         m_prs_box_##n.handler();                                             \
59     }
60 
61 #if defined(NRFX_PRS_BOX_0_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_0_ENABLED)
62 PRS_BOX_DEFINE(0)
63 #endif
64 #if defined(NRFX_PRS_BOX_1_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_1_ENABLED)
65 PRS_BOX_DEFINE(1)
66 #endif
67 #if defined(NRFX_PRS_BOX_2_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_2_ENABLED)
68 PRS_BOX_DEFINE(2)
69 #endif
70 #if defined(NRFX_PRS_BOX_3_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_3_ENABLED)
71 PRS_BOX_DEFINE(3)
72 #endif
73 #if defined(NRFX_PRS_BOX_4_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_4_ENABLED)
74 PRS_BOX_DEFINE(4)
75 #endif
76 #if defined(NRFX_PRS_BOX_5_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_5_ENABLED)
77 PRS_BOX_DEFINE(5)
78 #endif
79 #if defined(NRFX_PRS_BOX_6_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_6_ENABLED)
80 PRS_BOX_DEFINE(6)
81 #endif
82 #if defined(NRFX_PRS_BOX_7_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_7_ENABLED)
83 PRS_BOX_DEFINE(7)
84 #endif
85 #if defined(NRFX_PRS_BOX_8_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_8_ENABLED)
86 PRS_BOX_DEFINE(8)
87 #endif
88 #if defined(NRFX_PRS_BOX_9_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_9_ENABLED)
89 PRS_BOX_DEFINE(9)
90 #endif
91 
prs_box_get(void const * p_base_addr)92 static prs_box_t * prs_box_get(void const * p_base_addr)
93 {
94 #if !defined(IS_PRS_BOX)
95 #define IS_PRS_BOX(n, p_base_addr)  ((p_base_addr) == NRFX_PRS_BOX_##n##_ADDR)
96 #endif
97 
98 #if defined(NRFX_PRS_BOX_0_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_0_ENABLED)
99     if (IS_PRS_BOX(0, p_base_addr)) { return &m_prs_box_0; }
100     else
101 #endif
102 #if defined(NRFX_PRS_BOX_1_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_1_ENABLED)
103     if (IS_PRS_BOX(1, p_base_addr)) { return &m_prs_box_1; }
104     else
105 #endif
106 #if defined(NRFX_PRS_BOX_2_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_2_ENABLED)
107     if (IS_PRS_BOX(2, p_base_addr)) { return &m_prs_box_2; }
108     else
109 #endif
110 #if defined(NRFX_PRS_BOX_3_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_3_ENABLED)
111     if (IS_PRS_BOX(3, p_base_addr)) { return &m_prs_box_3; }
112     else
113 #endif
114 #if defined(NRFX_PRS_BOX_4_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_4_ENABLED)
115     if (IS_PRS_BOX(4, p_base_addr)) { return &m_prs_box_4; }
116     else
117 #endif
118 #if defined(NRFX_PRS_BOX_5_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_5_ENABLED)
119     if (IS_PRS_BOX(5, p_base_addr)) { return &m_prs_box_5; }
120     else
121 #endif
122 #if defined(NRFX_PRS_BOX_6_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_6_ENABLED)
123     if (IS_PRS_BOX(6, p_base_addr)) { return &m_prs_box_6; }
124     else
125 #endif
126 #if defined(NRFX_PRS_BOX_7_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_7_ENABLED)
127     if (IS_PRS_BOX(7, p_base_addr)) { return &m_prs_box_7; }
128     else
129 #endif
130 #if defined(NRFX_PRS_BOX_8_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_8_ENABLED)
131     if (IS_PRS_BOX(8, p_base_addr)) { return &m_prs_box_8; }
132     else
133 #endif
134 #if defined(NRFX_PRS_BOX_9_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_9_ENABLED)
135     if (IS_PRS_BOX(9, p_base_addr)) { return &m_prs_box_9; }
136     else
137 #endif
138     {
139         return NULL;
140     }
141 }
142 
nrfx_prs_acquire(void const * p_base_addr,nrfx_irq_handler_t irq_handler)143 nrfx_err_t nrfx_prs_acquire(void       const * p_base_addr,
144                             nrfx_irq_handler_t irq_handler)
145 {
146     NRFX_ASSERT(p_base_addr);
147 
148     nrfx_err_t ret_code;
149 
150     prs_box_t * p_box = prs_box_get(p_base_addr);
151     if (p_box != NULL)
152     {
153         bool busy = false;
154 
155         NRFX_CRITICAL_SECTION_ENTER();
156         if (p_box->acquired)
157         {
158             busy = true;
159         }
160         else
161         {
162             p_box->handler  = irq_handler;
163             p_box->acquired = true;
164         }
165         NRFX_CRITICAL_SECTION_EXIT();
166 
167         if (busy)
168         {
169             ret_code = NRFX_ERROR_BUSY;
170             LOG_FUNCTION_EXIT(WARNING, ret_code);
171             return ret_code;
172         }
173     }
174 
175     ret_code = NRFX_SUCCESS;
176     LOG_FUNCTION_EXIT(INFO, ret_code);
177     return ret_code;
178 }
179 
nrfx_prs_release(void const * p_base_addr)180 void nrfx_prs_release(void const * p_base_addr)
181 {
182     NRFX_ASSERT(p_base_addr);
183 
184     prs_box_t * p_box = prs_box_get(p_base_addr);
185     if (p_box != NULL)
186     {
187         p_box->handler  = NULL;
188         p_box->acquired = false;
189     }
190 }
191 
192 
193 #endif // NRFX_CHECK(NRFX_PRS_ENABLED)
194