nrfxlib API 3.4.99
Loading...
Searching...
No Matches
nrf_802154_hw_utils.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 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 Nordic Semiconductor ASA 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
42#ifndef NRF_802154_HW_UTILS_H_
43#define NRF_802154_HW_UTILS_H_
44
45#include <nrfx.h>
46
47#ifdef __STATIC_INLINE__
48#undef __STATIC_INLINE__
49#endif /* __STATIC_INLINE__ */
50
51#ifdef NRF_802154_HW_UTILS_DECLARE_ONLY
52#define __STATIC_INLINE__
53#else /* NRF_802154_HW_UTILS_DECLARE_ONLY */
54#define __STATIC_INLINE__ __STATIC_INLINE
55#endif /* NRF_802154_HW_UTILS_DECLARE_ONLY */
56
57#define RADIO_BASE ((uintptr_t)NRF_RADIO)
58#define FICR_BASE ((uintptr_t)NRF_FICR)
59
60#define FICR_REG_RESET_VALUE 0xFFFFFFFFUL
61#define IS_FICR_REG_SET(_ficr_reg) ((_ficr_reg) != FICR_REG_RESET_VALUE)
62
71#if defined(NRF54LC10A_XXAA) || defined(NRF54LV10A_XXAA)
72#define NRF54L_FIR_4205_ENABLE_WORKAROUND 1
73#else
74#define NRF54L_FIR_4205_ENABLE_WORKAROUND 0
75#endif
76
85__STATIC_INLINE__ uint32_t nrf_802154_hw_offset_read(uintptr_t base_addr, uint32_t offset);
86
94__STATIC_INLINE__ void nrf_802154_hw_offset_write(uintptr_t base_addr,
95 uint32_t offset,
96 uint32_t value);
97
98#ifndef RADIO_POWER_POWER_Msk
102__STATIC_INLINE__ void nrf_802154_hw_reset_radio_tasks_events(void);
103#endif /* RADIO_POWER_POWER_Msk */
104
105#if NRF53_ERRATA_158_ENABLE_WORKAROUND
116__STATIC_INLINE__ void yopan_158_workaround(void);
117#endif /* NRF53_ERRATA_158_ENABLE_WORKAROUND */
118
119#if NRF53_ERRATA_117_ENABLE_WORKAROUND
125__STATIC_INLINE__ void errata_117_apply(void);
126#endif /* NRF53_ERRATA_117_ENABLE_WORKAROUND */
127
128#if NRF54L_ERRATA_6_ENABLE_WORKAROUND
134__STATIC_INLINE__ void mltpan_6_apply(void);
135#endif /* NRF54L_ERRATA_6_ENABLE_WORKAROUND */
136
137#if NRF54L_FIR_4205_ENABLE_WORKAROUND
143__STATIC_INLINE__ void fir_4205_apply(void);
144#endif /* NRF54L_FIR_4205_ENABLE_WORKAROUND */
145
146#if NRF52_CONFIGURATION_254_ENABLE
152__STATIC_INLINE__ void device_config_254_apply_tx(void);
153#endif /* NRF52_CONFIGURATION_254_ENABLE */
154
155#ifndef NRF_802154_HW_UTILS_DECLARE_ONLY
156
157__STATIC_INLINE__ uint32_t nrf_802154_hw_offset_read(uintptr_t base_addr, uint32_t offset)
158{
159 return *(volatile uint32_t *)(base_addr + offset);
160}
161
162__STATIC_INLINE__ void nrf_802154_hw_offset_write(uintptr_t base_addr,
163 uint32_t offset,
164 uint32_t value)
165{
166 volatile uint32_t * p_register_address = (volatile uint32_t *)(base_addr + offset);
167
168 *p_register_address = value;
169}
170
171#ifndef RADIO_POWER_POWER_Msk
172
173__STATIC_INLINE__ void nrf_802154_hw_reset_radio_tasks_events(void)
174{
175 /* SUBSCRIBE registers */
176 nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_TXEN);
177 nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_RXEN);
178 nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_START);
179 nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_STOP);
180 nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_DISABLE);
181 nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_RSSISTART);
182 nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_BCSTART);
183 nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_BCSTOP);
184 nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_EDSTART);
185 nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_EDSTOP);
186 nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_CCASTART);
187 nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_CCASTOP);
188
189 /* EVENT registers */
190 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_READY);
191 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS);
192 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_PAYLOAD);
193 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_END);
194 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_DISABLED);
195 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_DEVMATCH);
196 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_DEVMISS);
197 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_BCMATCH);
198 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CRCOK);
199 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CRCERROR);
200 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_FRAMESTART);
201 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_EDEND);
202 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_EDSTOPPED);
203 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CCAIDLE);
204 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CCABUSY);
205 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CCASTOPPED);
206 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_RATEBOOST);
207 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_TXREADY);
208 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_RXREADY);
209 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_MHRMATCH);
210 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_PHYEND);
211 nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CTEPRESENT);
212
213 /* PUBLISH registers */
214 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_READY);
215 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS);
216 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_PAYLOAD);
217 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_END);
218 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_DISABLED);
219 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_DEVMATCH);
220 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_DEVMISS);
221 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_BCMATCH);
222 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_CRCOK);
223 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_CRCERROR);
224 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_FRAMESTART);
225 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_EDEND);
226 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_EDSTOPPED);
227 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_CCAIDLE);
228 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_CCABUSY);
229 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_CCASTOPPED);
230 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_RATEBOOST);
231 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_TXREADY);
232 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_RXREADY);
233 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_MHRMATCH);
234 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_PHYEND);
235 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_CTEPRESENT);
236
237 /* INTEN registers */
238 nrf_radio_int_disable(NRF_RADIO, 0xFFFFFFFFUL);
239}
240
241#endif /* RADIO_POWER_POWER_Msk */
242
243#if NRF53_ERRATA_158_ENABLE_WORKAROUND
244
246__STATIC_INLINE__ void yopan_158_workaround(void)
247{
248 const uint32_t radio_address_mask = 0xFFFFF000UL;
249 const uint32_t ficr_trim_registers_count = 32UL;
250
251 /* Copy all the trimming values from FICR into the target addresses. Trim until one ADDR
252 is not initialized. */
253 for (uint32_t index = 0; index < ficr_trim_registers_count; index++)
254 {
255 if (((volatile uint32_t *)((volatile uintptr_t)NRF_FICR_NS->TRIMCNF[index].ADDR &
256 (uintptr_t)radio_address_mask) == (uint32_t *)NRF_RADIO))
257 {
258 *((volatile uint32_t *)NRF_FICR_NS->TRIMCNF[index].ADDR) =
259 NRF_FICR_NS->TRIMCNF[index].DATA;
260 }
261 }
262}
263
264#endif /* NRF53_ERRATA_158_ENABLE_WORKAROUND */
265
266#if NRF53_ERRATA_117_ENABLE_WORKAROUND
267
268__STATIC_INLINE__ void errata_117_apply(void)
269{
270#ifndef CONFIG_SOC_SERIES_BSIM_NRFXX
271
272 /* Register at 0x01FF0084. */
273 uint32_t ficr_reg = nrf_802154_hw_offset_read(FICR_BASE, 0x84UL);
274
275 /* Register at 0x41008588. */
276 nrf_802154_hw_offset_write(RADIO_BASE, 0x588UL, ficr_reg);
277
278#endif /* CONFIG_SOC_SERIES_BSIM_NRFXX */
279}
280
281#endif /* NRF53_ERRATA_117_ENABLE_WORKAROUND */
282
283#if NRF54L_ERRATA_6_ENABLE_WORKAROUND
284
285__STATIC_INLINE__ void mltpan_6_apply(void)
286{
287#ifndef CONFIG_SOC_SERIES_BSIM_NRFXX
288
289 /* Apply MLTPAN-6 */
291
292#endif /* CONFIG_SOC_SERIES_BSIM_NRFXX */
293}
294
295#endif /* NRF54L_ERRATA_6_ENABLE_WORKAROUND */
296
297#if NRF54L_FIR_4205_ENABLE_WORKAROUND
298
299__STATIC_INLINE__ void fir_4205_apply(void)
300{
301#ifndef CONFIG_SOC_SERIES_BSIM_NRFXX
302
303 /* Apply FIR-4205. */
304 nrf_802154_hw_offset_write(RADIO_BASE, 0xB40UL, 0x25A4A42DUL);
305
306#endif /* CONFIG_SOC_SERIES_BSIM_NRFXX */
307}
308
309#endif /* NRF54L_FIR_4205_ENABLE_WORKAROUND */
310
311#if NRF52_CONFIGURATION_254_ENABLE
312
318__STATIC_INLINE__ void device_config_254_apply_tx(void)
319{
320 /* Trim values for FTPAN-254 */
321 uint32_t ficr_reg1 = nrf_802154_hw_offset_read(FICR_BASE, 0x0330UL);
322 uint32_t ficr_reg2 = nrf_802154_hw_offset_read(FICR_BASE, 0x0334UL);
323 uint32_t ficr_reg3 = nrf_802154_hw_offset_read(FICR_BASE, 0x0338UL);
324
325 /* Check if the device is fixed by testing every FICR register's value separately. */
326 if (IS_FICR_REG_SET(ficr_reg1))
327 {
328 nrf_802154_hw_offset_write(RADIO_BASE, 0x074cUL, ficr_reg1);
329 }
330
331 if (IS_FICR_REG_SET(ficr_reg2))
332 {
333 nrf_802154_hw_offset_write(RADIO_BASE, 0x0584UL, ficr_reg2);
334 }
335
336 if (IS_FICR_REG_SET(ficr_reg3))
337 {
338 nrf_802154_hw_offset_write(RADIO_BASE, 0x0588UL, ficr_reg3);
339 }
340}
341
342#endif /* NRF52_CONFIGURATION_254_ENABLE */
343
344#endif /* NRF_802154_HW_UTILS_DECLARE_ONLY */
345
346#endif /* NRF_802154_HW_UTILS_H_ */
__STATIC_INLINE void nrf_802154_hw_offset_write(uintptr_t base_addr, uint32_t offset, uint32_t value)
Write to peripheral register at a given offset.
Definition nrf_802154_hw_utils.h:162
#define RADIO_BASE
Definition nrf_802154_hw_utils.h:57
__STATIC_INLINE uint32_t nrf_802154_hw_offset_read(uintptr_t base_addr, uint32_t offset)
Read peripheral register at a given offset.
Definition nrf_802154_hw_utils.h:157
__STATIC_INLINE void nrf_802154_hw_reset_radio_tasks_events(void)
Reset radio PUBLISH, SUBSCRIBE, EVENTS and INTEN registers.
Definition nrf_802154_hw_utils.h:173
#define FICR_BASE
Definition nrf_802154_hw_utils.h:58
#define IS_FICR_REG_SET(_ficr_reg)
Definition nrf_802154_hw_utils.h:61