1 /*
2  * Copyright (c) 2024 - 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_PPIB_ENABLED)
37 
38 #include <nrfx_ppib.h>
39 #include <helpers/nrfx_flag32_allocator.h>
40 
41 #define NRFX_LOG_MODULE PPIB
42 #include <nrfx_log.h>
43 
44 #if !defined(__NRFX_DOXYGEN__)
45 
46 #if defined(NRF54L_SERIES) || defined(NRF7120_ENGA_XXAA)
47 
48 #if !defined(NRFX_PPIB_INTERCONNECT_00_10_CHANNELS_USED)
49 /**
50  * Bitmask that defines PPIB00 and PPIB10 channels that are
51  * reserved for use outside of the nrfx library.
52  */
53 #define NRFX_PPIB_INTERCONNECT_00_10_CHANNELS_USED 0UL
54 #endif
55 
56 #if !defined(NRFX_PPIB_INTERCONNECT_01_20_CHANNELS_USED)
57 /**
58  * Bitmask that defines PPIB01 and PPIB20 channels that are
59  * reserved for use outside of the nrfx library.
60  */
61 #define NRFX_PPIB_INTERCONNECT_01_20_CHANNELS_USED 0UL
62 #endif
63 
64 #if !defined(NRFX_PPIB_INTERCONNECT_11_21_CHANNELS_USED)
65 /**
66  * Bitmask that defines PPIB11 and PPIB21 channels that are
67  * reserved for use outside of the nrfx library.
68  */
69 #define NRFX_PPIB_INTERCONNECT_11_21_CHANNELS_USED 0UL
70 #endif
71 
72 #if !defined(NRFX_PPIB_INTERCONNECT_22_30_CHANNELS_USED)
73 /**
74  * Bitmask that defines PPIB022 and PPIB30 channels that are
75  * reserved for use outside of the nrfx library.
76  */
77 #define NRFX_PPIB_INTERCONNECT_22_30_CHANNELS_USED 0UL
78 #endif
79 
80 #endif
81 
82 #if defined(NRF54L20_ENGA_XXAA)
83 
84 #if !defined(NRFX_PPIB_INTERCONNECT_02_03_CHANNELS_USED)
85 /**
86  * Bitmask that defines PPIB022 and PPIB30 channels that are
87  * reserved for use outside of the nrfx library.
88  */
89 #define NRFX_PPIB_INTERCONNECT_02_03_CHANNELS_USED 0UL
90 #endif
91 
92 #if !defined(NRFX_PPIB_INTERCONNECT_04_12_CHANNELS_USED)
93 /**
94  * Bitmask that defines PPIB022 and PPIB30 channels that are
95  * reserved for use outside of the nrfx library.
96  */
97 #define NRFX_PPIB_INTERCONNECT_04_12_CHANNELS_USED 0UL
98 #endif
99 
100 #endif
101 
102 #if defined(HALTIUM_XXAA)
103 
104 #if !defined(NRFX_PPIB_INTERCONNECT_020_030_CHANNELS_USED)
105 /**
106  * Bitmask that defines PPIB020 and PPIB030 channels that are
107  * reserved for use outside of the nrfx library.
108  */
109 #define NRFX_PPIB_INTERCONNECT_020_030_CHANNELS_USED 0UL
110 #endif
111 
112 #endif
113 
114 #endif // !defined(__NRFX_DOXYGEN__)
115 
116 #define PPIB_CHANNELS_NUM(idx)  (NRFX_CONCAT(PPIB, idx, _NTASKSEVENTS_MAX) + 1UL)
117 #define PPIB_CHANNELS_MASK(left, right)                                       \
118     NRFX_BIT_MASK(NRFX_MIN(PPIB_CHANNELS_NUM(left), PPIB_CHANNELS_NUM(right))
119 #define PPIB_CHANNELS_USED(left, right)                                 \
120     NRFX_CONCAT(NRFX_PPIB_INTERCONNECT_, left, _, right, _CHANNELS_USED)
121 #define PPIB_AVAILABLE_CHANNELS_MASK(left, right) \
122     ((uint32_t)(PPIB_CHANNELS_MASK(left, right)) & ~(PPIB_CHANNELS_USED(left, right))))
123 
124 /* Structure holding state of the PPIB instance. */
125 typedef struct
126 {
127     /**< Bitmap representing channels availability. */
128     nrfx_atomic_t allocated_channels;
129     /**< Bitmap representing available channels. */
130     const uint32_t available_channels;
131 } ppib_control_block_t;
132 
133 #define _NRFX_PPIBC_CB_INITIALIZER(left_idx, right_idx)                                         \
134     [NRFX_CONCAT(NRFX_PPIB_INTERCONNECT_, left_idx, _, right_idx, _INST_IDX)] = {               \
135         .allocated_channels = (nrfx_atomic_t)PPIB_AVAILABLE_CHANNELS_MASK(left_idx, right_idx), \
136         .available_channels = PPIB_AVAILABLE_CHANNELS_MASK(left_idx, right_idx),                \
137     },
138 
139 static ppib_control_block_t m_cb[NRFX_PPIB_INTERCONNECT_COUNT] = {
140 #if defined(NRF54L_SERIES) || defined(NRF7120_ENGA_XXAA)
141 #if NRFX_CHECK(NRFX_PPIB00_ENABLED) && NRFX_CHECK(NRFX_PPIB10_ENABLED)
142     _NRFX_PPIBC_CB_INITIALIZER(00, 10)
143 #endif
144 #if NRFX_CHECK(NRFX_PPIB01_ENABLED) && NRFX_CHECK(NRFX_PPIB20_ENABLED)
145     _NRFX_PPIBC_CB_INITIALIZER(01, 20)
146 #endif
147 #if NRFX_CHECK(NRFX_PPIB11_ENABLED) && NRFX_CHECK(NRFX_PPIB21_ENABLED)
148     _NRFX_PPIBC_CB_INITIALIZER(11, 21)
149 #endif
150 #if NRFX_CHECK(NRFX_PPIB22_ENABLED) && NRFX_CHECK(NRFX_PPIB30_ENABLED)
151     _NRFX_PPIBC_CB_INITIALIZER(22, 30)
152 #endif
153 #endif
154 #if defined(NRF54L20_ENGA_XXAA)
155 #if NRFX_CHECK(NRFX_PPIB02_ENABLED) && NRFX_CHECK(NRFX_PPIB03_ENABLED)
156     _NRFX_PPIBC_CB_INITIALIZER(02, 03)
157 #endif
158 #if NRFX_CHECK(NRFX_PPIB04_ENABLED) && NRFX_CHECK(NRFX_PPIB12_ENABLED)
159     _NRFX_PPIBC_CB_INITIALIZER(04, 12)
160 #endif
161 #endif
162 #if defined(HALTIUM_XXAA)
163 #if NRFX_CHECK(NRFX_PPIB020_ENABLED) && NRFX_CHECK(NRFX_PPIB030_ENABLED)
164     _NRFX_PPIBC_CB_INITIALIZER(020, 030)
165 #endif
166 #endif
167 };
168 
nrfx_ppib_free(nrfx_ppib_interconnect_t const * p_instance)169 void nrfx_ppib_free(nrfx_ppib_interconnect_t const * p_instance)
170 {
171     ppib_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
172     uint32_t mask = p_cb->available_channels & ~p_cb->allocated_channels;
173     uint8_t channel_idx = 0;
174 
175     // Clear all channel configurations
176     while (mask)
177     {
178         if (mask & NRFX_BIT(channel_idx))
179         {
180             nrfx_ppib_channel_free(p_instance, channel_idx);
181             mask &= ~NRFX_BIT(channel_idx);
182         }
183         channel_idx++;
184     }
185 }
186 
nrfx_ppib_channel_alloc(nrfx_ppib_interconnect_t const * p_instance,uint8_t * p_channel)187 nrfx_err_t nrfx_ppib_channel_alloc(nrfx_ppib_interconnect_t const * p_instance, uint8_t * p_channel)
188 {
189     ppib_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
190 
191     return nrfx_flag32_alloc(&p_cb->allocated_channels, p_channel);
192 }
193 
nrfx_ppib_channel_free(nrfx_ppib_interconnect_t const * p_instance,uint8_t channel)194 nrfx_err_t nrfx_ppib_channel_free(nrfx_ppib_interconnect_t const * p_instance, uint8_t channel)
195 {
196     ppib_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
197 
198     if ((p_cb->available_channels & NRFX_BIT(channel)) == 0)
199     {
200         return NRFX_ERROR_INVALID_PARAM;
201     }
202 
203     nrf_ppib_subscribe_clear(p_instance->left.p_reg, nrf_ppib_send_task_get(channel));
204     nrf_ppib_subscribe_clear(p_instance->right.p_reg, nrf_ppib_send_task_get(channel));
205     nrf_ppib_publish_clear(p_instance->left.p_reg, nrf_ppib_receive_event_get(channel));
206     nrf_ppib_publish_clear(p_instance->right.p_reg, nrf_ppib_receive_event_get(channel));
207 
208     return nrfx_flag32_free(&p_cb->allocated_channels, channel);
209 }
210 
211 #endif // defined(PPIB_PRESENT)
212