1 /*
2 * Copyright (c) 2018 - 2020 Nordic Semiconductor ASA
3 * Copyright (c) 2018 Ioannis Glaropoulos
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #if defined(CONFIG_BT_CTLR_PHY_CODED)
9 /* The 2 adjacent TIMER EVENTS_COMPARE event offsets used for implementing
10 * SW_SWITCH_TIMER-based auto-switch for TIFS, when receiving in LE Coded PHY.
11 * 'index' must be 0 or 1.
12 */
13 #define SW_SWITCH_TIMER_S2_EVTS_COMP(index) \
14 (SW_SWITCH_TIMER_EVTS_COMP_S2_BASE + (index))
15
16 /* Wire the SW SWITCH TIMER EVENTS_COMPARE[<cc_offset>] event
17 * to RADIO TASKS_TXEN/RXEN task.
18 */
19 #define HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI(index) \
20 (HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI_BASE + (index))
21
22 static inline void hal_radio_sw_switch_coded_config_clear(uint8_t ppi_en,
23 uint8_t ppi_dis, uint8_t cc_s2, uint8_t group_index);
24 #endif
25
hal_radio_nrf_ppi_channels_enable(uint32_t mask)26 static inline void hal_radio_nrf_ppi_channels_enable(uint32_t mask)
27 {
28 nrf_ppi_channels_enable(NRF_PPI, mask);
29 }
30
hal_radio_nrf_ppi_channels_disable(uint32_t mask)31 static inline void hal_radio_nrf_ppi_channels_disable(uint32_t mask)
32 {
33 nrf_ppi_channels_disable(NRF_PPI, mask);
34 }
35
36 /*******************************************************************************
37 * Enable Radio on Event Timer tick:
38 * wire the EVENT_TIMER EVENTS_COMPARE[0] event to RADIO TASKS_TXEN/RXEN task.
39 *
40 * Use the pre-programmed PPI channels if possible (if TIMER0 is used as the
41 * EVENT_TIMER).
42 */
43 #if (EVENT_TIMER_ID == 0)
44
hal_radio_enable_on_tick_ppi_config_and_enable(uint8_t trx)45 static inline void hal_radio_enable_on_tick_ppi_config_and_enable(uint8_t trx)
46 {
47 /* No need to configure anything for the pre-programmed channels.
48 * Just enable and disable them accordingly.
49 */
50 if (trx) {
51 nrf_ppi_channels_enable(NRF_PPI,
52 BIT(HAL_RADIO_ENABLE_TX_ON_TICK_PPI));
53 } else {
54 nrf_ppi_channels_enable(NRF_PPI,
55 BIT(HAL_RADIO_ENABLE_RX_ON_TICK_PPI));
56 }
57 }
58
59 #else
60
hal_radio_enable_on_tick_ppi_config_and_enable(uint8_t trx)61 static inline void hal_radio_enable_on_tick_ppi_config_and_enable(uint8_t trx)
62 {
63 if (trx) {
64 nrf_ppi_channel_endpoint_setup(NRF_PPI,
65 HAL_RADIO_ENABLE_TX_ON_TICK_PPI,
66 (uint32_t)&(EVENT_TIMER->EVENTS_COMPARE[0]),
67 (uint32_t)&(NRF_RADIO->TASKS_TXEN));
68
69 #if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
70 NRF_PPI->CHG[SW_SWITCH_SINGLE_TIMER_TASK_GROUP_IDX] =
71 BIT(HAL_RADIO_ENABLE_TX_ON_TICK_PPI);
72
73 nrf_ppi_fork_endpoint_setup(NRF_PPI,
74 HAL_RADIO_ENABLE_TX_ON_TICK_PPI,
75 (uint32_t)&(NRF_PPI->TASKS_CHG[SW_SWITCH_SINGLE_TIMER_TASK_GROUP_IDX].DIS));
76 #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
77
78 nrf_ppi_channels_enable(NRF_PPI,
79 BIT(HAL_RADIO_ENABLE_TX_ON_TICK_PPI));
80 } else {
81 nrf_ppi_channel_endpoint_setup(NRF_PPI,
82 HAL_RADIO_ENABLE_RX_ON_TICK_PPI,
83 (uint32_t)&(EVENT_TIMER->EVENTS_COMPARE[0]),
84 (uint32_t)&(NRF_RADIO->TASKS_RXEN));
85
86 #if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
87 NRF_PPI->CHG[SW_SWITCH_SINGLE_TIMER_TASK_GROUP_IDX] =
88 BIT(HAL_RADIO_ENABLE_RX_ON_TICK_PPI);
89
90 nrf_ppi_fork_endpoint_setup(NRF_PPI,
91 HAL_RADIO_ENABLE_RX_ON_TICK_PPI,
92 (uint32_t)&(NRF_PPI->TASKS_CHG[SW_SWITCH_SINGLE_TIMER_TASK_GROUP_IDX].DIS));
93 #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
94
95 nrf_ppi_channels_enable(NRF_PPI,
96 BIT(HAL_RADIO_ENABLE_RX_ON_TICK_PPI));
97 }
98 }
99
100 #endif /* (EVENT_TIMER_ID == 0) */
101
102 /*******************************************************************************
103 * Capture event timer on Address reception:
104 * wire the RADIO EVENTS_ADDRESS event to the
105 * EVENT_TIMER TASKS_CAPTURE[<address timer>] task.
106 *
107 * Use the pre-programmed PPI channel if possible (if TIMER0 is used as the
108 * EVENT_TIMER).
109 */
110 #if (EVENT_TIMER_ID == 0)
111
hal_radio_recv_timeout_cancel_ppi_config(void)112 static inline void hal_radio_recv_timeout_cancel_ppi_config(void)
113 {
114 /* No need to configure anything for the pre-programmed channel. */
115 }
116
117 #else
118
hal_radio_recv_timeout_cancel_ppi_config(void)119 static inline void hal_radio_recv_timeout_cancel_ppi_config(void)
120 {
121 nrf_ppi_channel_endpoint_setup(
122 NRF_PPI,
123 HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI,
124 (uint32_t)&(NRF_RADIO->EVENTS_ADDRESS),
125 (uint32_t)&(EVENT_TIMER->TASKS_CAPTURE[1]));
126 }
127
128 #endif /* (EVENT_TIMER_ID == 0) */
129
130 /*******************************************************************************
131 * Disable Radio on HCTO:
132 * wire the EVENT_TIMER EVENTS_COMPARE[<HCTO timer>] event
133 * to the RADIO TASKS_DISABLE task.
134 *
135 * Use the pre-programmed PPI channel if possible (if TIMER0 is used as the
136 * EVENT_TIMER).
137 */
138 #if (EVENT_TIMER_ID == 0)
139
hal_radio_disable_on_hcto_ppi_config(void)140 static inline void hal_radio_disable_on_hcto_ppi_config(void)
141 {
142 /* No need to configure anything for the pre-programmed channel. */
143 }
144
145 #else
146
hal_radio_disable_on_hcto_ppi_config(void)147 static inline void hal_radio_disable_on_hcto_ppi_config(void)
148 {
149 nrf_ppi_channel_endpoint_setup(
150 NRF_PPI,
151 HAL_RADIO_DISABLE_ON_HCTO_PPI,
152 (uint32_t)&(EVENT_TIMER->EVENTS_COMPARE[1]),
153 (uint32_t)&(NRF_RADIO->TASKS_DISABLE));
154 }
155
156 #endif /* (EVENT_TIMER_ID == 0) */
157
158 /*******************************************************************************
159 * Capture event timer on Radio end:
160 * wire the RADIO EVENTS_END event to the
161 * EVENT_TIMER TASKS_CAPTURE[<radio end timer>] task.
162 *
163 * Use the pre-programmed PPI channel if possible (if TIMER0 is used as the
164 * EVENT_TIMER).
165 */
166 #if (EVENT_TIMER_ID == 0)
167
hal_radio_end_time_capture_ppi_config(void)168 static inline void hal_radio_end_time_capture_ppi_config(void)
169 {
170 /* No need to configure anything for the pre-programmed channel. */
171 }
172
173 #else
174
hal_radio_end_time_capture_ppi_config(void)175 static inline void hal_radio_end_time_capture_ppi_config(void)
176 {
177 nrf_ppi_channel_endpoint_setup(
178 NRF_PPI,
179 HAL_RADIO_END_TIME_CAPTURE_PPI,
180 (uint32_t)&(NRF_RADIO->NRF_RADIO_TRX_END_EVENT),
181 (uint32_t)&(EVENT_TIMER->TASKS_CAPTURE[2]));
182 }
183
184 #endif /* (EVENT_TIMER_ID == 0) */
185
186 /*******************************************************************************
187 * Start event timer on RTC tick:
188 * wire the RTC0 EVENTS_COMPARE[2] event to EVENT_TIMER TASKS_START task.
189 */
hal_event_timer_start_ppi_config(void)190 static inline void hal_event_timer_start_ppi_config(void)
191 {
192 nrf_ppi_channel_endpoint_setup(
193 NRF_PPI,
194 HAL_EVENT_TIMER_START_PPI,
195 (uint32_t)&(NRF_RTC0->EVENTS_COMPARE[2]),
196 (uint32_t)&(EVENT_TIMER->TASKS_START));
197 }
198
199 /*******************************************************************************
200 * Capture event timer on Radio ready:
201 * wire the RADIO EVENTS_READY event to the
202 * EVENT_TIMER TASKS_CAPTURE[<radio ready timer>] task.
203 */
hal_radio_ready_time_capture_ppi_config(void)204 static inline void hal_radio_ready_time_capture_ppi_config(void)
205 {
206 nrf_ppi_channel_endpoint_setup(
207 NRF_PPI,
208 HAL_RADIO_READY_TIME_CAPTURE_PPI,
209 (uint32_t)&(NRF_RADIO->EVENTS_READY),
210 (uint32_t)&(EVENT_TIMER->TASKS_CAPTURE[0]));
211 }
212
213 /*******************************************************************************
214 * Trigger encryption task upon address reception:
215 * wire the RADIO EVENTS_ADDRESS event to the CCM TASKS_CRYPT task.
216 *
217 * PPI channel 25 is pre-programmed with the following fixed settings:
218 * EEP: RADIO->EVENTS_ADDRESS
219 * TEP: CCM->TASKS_CRYPT
220 */
hal_trigger_crypt_ppi_config(void)221 static inline void hal_trigger_crypt_ppi_config(void)
222 {
223 /* No need to configure anything for the pre-programmed channel. */
224 }
225
226 /*******************************************************************************
227 * Disable trigger encryption task
228 */
hal_trigger_crypt_ppi_disable(void)229 static inline void hal_trigger_crypt_ppi_disable(void)
230 {
231 /* No need to disable anything as ppi channel will be disabled in a
232 * separate disable ppi call by the caller of this function.
233 */
234 }
235
236 #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX)
237 /*******************************************************************************
238 * Trigger encryption task on Bit counter match:
239 * wire the RADIO EVENTS_BCMATCH event to the CCM TASKS_CRYPT task.
240 *
241 * PPI channel HAL_TRIGGER_CRYPT_DELAY_PPI is also used for HAL_TRIGGER-
242 * _RATEOVERRIDE_PPI.
243 * Make sure the same PPI is not configured for both events at once.
244 *
245 * EEP: RADIO->EVENTS_BCMATCH
246 * TEP: CCM->TASKS_CRYPT
247 */
hal_trigger_crypt_by_bcmatch_ppi_config(void)248 static inline void hal_trigger_crypt_by_bcmatch_ppi_config(void)
249 {
250 /* Configure Bit counter to trigger EVENTS_BCMATCH for CCM_TASKS_CRYPT-
251 * _DELAY_BITS bit. This is a time required for Radio to store
252 * received data in memory before the CCM TASKS_CRYPT starts. This
253 * makes CCM to do not read the memory before Radio stores received
254 * data.
255 */
256 nrf_ppi_channel_endpoint_setup(NRF_PPI, HAL_TRIGGER_CRYPT_DELAY_PPI,
257 (uint32_t)&(NRF_RADIO->EVENTS_BCMATCH),
258 (uint32_t)&(NRF_CCM->TASKS_CRYPT));
259 }
260 #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */
261
262 /*******************************************************************************
263 * Trigger automatic address resolution on Bit counter match:
264 * wire the RADIO EVENTS_BCMATCH event to the AAR TASKS_START task.
265 *
266 * PPI channel 23 is pre-programmed with the following fixed settings:
267 * EEP: RADIO->EVENTS_BCMATCH
268 * TEP: AAR->TASKS_START
269 */
hal_trigger_aar_ppi_config(void)270 static inline void hal_trigger_aar_ppi_config(void)
271 {
272 /* No need to configure anything for the pre-programmed channel. */
273 }
274
275 /*******************************************************************************
276 * Trigger Radio Rate override upon Rateboost event.
277 */
278 #if defined(CONFIG_BT_CTLR_PHY_CODED) && defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED)
hal_trigger_rateoverride_ppi_config(void)279 static inline void hal_trigger_rateoverride_ppi_config(void)
280 {
281 nrf_ppi_channel_endpoint_setup(
282 NRF_PPI,
283 HAL_TRIGGER_RATEOVERRIDE_PPI,
284 (uint32_t)&(NRF_RADIO->EVENTS_RATEBOOST),
285 (uint32_t)&(NRF_CCM->TASKS_RATEOVERRIDE));
286 }
287 #endif /* CONFIG_BT_CTLR_PHY_CODED && CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
288
289 /******************************************************************************/
290 #if !defined(CONFIG_BT_CTLR_TIFS_HW)
291 /* PPI setup used for SW-based auto-switching during TIFS. */
292
293 #if !defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
294
295 /* Clear SW-switch timer on packet end:
296 * wire the RADIO EVENTS_END event to SW_SWITCH_TIMER TASKS_CLEAR task.
297 *
298 * Note: this PPI is not needed if we use a single TIMER instance in radio.c
299 */
300
hal_sw_switch_timer_clear_ppi_config(void)301 static inline void hal_sw_switch_timer_clear_ppi_config(void)
302 {
303 nrf_ppi_channel_endpoint_setup(
304 NRF_PPI,
305 HAL_SW_SWITCH_TIMER_CLEAR_PPI,
306 (uint32_t)&(NRF_RADIO->NRF_RADIO_TRX_END_EVENT),
307 (uint32_t)&(SW_SWITCH_TIMER->TASKS_CLEAR));
308 }
309
310 #else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
311
312 /* Clear event timer (sw-switch timer) on Radio end:
313 * wire the RADIO EVENTS_END event to the
314 * EVENT_TIMER TASKS_CLEAR task.
315 *
316 * Note: in nRF52X this PPI channel is forked for both capturing and clearing
317 * timer on RADIO EVENTS_END.
318 */
319
hal_sw_switch_timer_clear_ppi_config(void)320 static inline void hal_sw_switch_timer_clear_ppi_config(void)
321 {
322 nrf_ppi_fork_endpoint_setup(
323 NRF_PPI,
324 HAL_RADIO_END_TIME_CAPTURE_PPI,
325 (uint32_t)&(SW_SWITCH_TIMER->TASKS_CLEAR));
326 }
327
328 #endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
329
330 /* The 2 adjacent PPI groups used for implementing SW_SWITCH_TIMER-based
331 * auto-switch for TIFS. 'index' must be 0 or 1.
332 */
333 #define SW_SWITCH_TIMER_TASK_GROUP(index) \
334 (SW_SWITCH_TIMER_TASK_GROUP_BASE + (index))
335
336 /* The 2 adjacent TIMER EVENTS_COMPARE event offsets used for implementing
337 * SW_SWITCH_TIMER-based auto-switch for TIFS. 'index' must be 0 or 1.
338 */
339 #define SW_SWITCH_TIMER_EVTS_COMP(index) \
340 (SW_SWITCH_TIMER_EVTS_COMP_BASE + (index))
341
342 /* Wire a SW SWITCH TIMER EVENTS_COMPARE[<cc_offset>] event
343 * to a PPI GROUP TASK DISABLE task (PPI group with index <index>).
344 * 2 adjacent PPIs (9 & 10) and 2 adjacent PPI groups are used for this wiring;
345 * <index> must be 0 or 1. <offset> must be a valid TIMER CC register offset.
346 */
347 /* Because nRF52805 has limited number of programmable PPI channels,
348 * tIFS Trx SW switching on this SoC can be used only when pre-programmed
349 * PPI channels are also in use, i.e. when TIMER0 is the event timer.
350 */
351 #if (EVENT_TIMER_ID != 0) && defined(CONFIG_SOC_NRF52805)
352 #error "tIFS Trx SW switch can be used on this SoC only with TIMER0 as the event timer"
353 #endif
354
355 #define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(index) \
356 (HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_BASE + (index))
357 #define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(cc_offset) \
358 ((uint32_t)&(SW_SWITCH_TIMER->EVENTS_COMPARE[cc_offset]))
359 #define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(index) \
360 ((uint32_t)&(NRF_PPI->TASKS_CHG[SW_SWITCH_TIMER_TASK_GROUP(index)].DIS))
361
362 /* Wire the RADIO EVENTS_END or EVENTS_PHYEND event to one of the PPI GROUP
363 * TASK ENABLE task. 2 adjacent PPI groups are used for this wiring.
364 * 'index' must be 0 or 1.
365 */
366 #define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT \
367 ((uint32_t)&(NRF_RADIO->NRF_RADIO_TRX_END_EVENT))
368 #define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_TASK(index) \
369 ((uint32_t)&(NRF_PPI->TASKS_CHG[SW_SWITCH_TIMER_TASK_GROUP(index)].EN))
370
371 /*Enable Radio at specific time-stamp:
372 * wire the SW SWITCH TIMER EVENTS_COMPARE[<cc_offset>] event
373 * to RADIO TASKS_TXEN/RXEN task.
374 * 2 adjacent PPIs (12 & 13) are used for this wiring; <index> must be 0 or 1.
375 * <offset> must be a valid TIMER CC register offset.
376 */
377 #define HAL_SW_SWITCH_RADIO_ENABLE_PPI(index) \
378 (HAL_SW_SWITCH_RADIO_ENABLE_PPI_BASE + (index))
379 #define HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(cc_offset) \
380 ((uint32_t)&(SW_SWITCH_TIMER->EVENTS_COMPARE[cc_offset]))
381 #define HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX \
382 ((uint32_t)&(NRF_RADIO->TASKS_TXEN))
383 #define HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_RX \
384 ((uint32_t)&(NRF_RADIO->TASKS_RXEN))
385
hal_radio_sw_switch_setup(uint8_t ppi_group_index)386 static inline void hal_radio_sw_switch_setup(uint8_t ppi_group_index)
387 {
388 /* Set up software switch mechanism for next Radio switch. */
389
390 /* Wire RADIO END event to PPI Group[<index>] enable task,
391 * over PPI[<HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI>]
392 */
393 nrf_ppi_channel_endpoint_setup(
394 NRF_PPI,
395 HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI,
396 HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT,
397 HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_TASK(ppi_group_index));
398 }
399
hal_radio_txen_on_sw_switch(uint8_t compare_reg_index,uint8_t radio_enable_ppi)400 static inline void hal_radio_txen_on_sw_switch(uint8_t compare_reg_index, uint8_t radio_enable_ppi)
401 {
402 /* Wire SW Switch timer event <compare_reg> to the
403 * PPI[<radio_enable_ppi>] for enabling Radio. Do
404 * not wire the task; it is done by the caller of
405 * the function depending on the desired direction
406 * (TX/RX).
407 */
408 nrf_ppi_event_endpoint_setup(NRF_PPI, radio_enable_ppi,
409 HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(compare_reg_index));
410
411 nrf_ppi_task_endpoint_setup(NRF_PPI, radio_enable_ppi,
412 HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX);
413 }
414
hal_radio_b2b_txen_on_sw_switch(uint8_t compare_reg_index,uint8_t radio_enable_ppi)415 static inline void hal_radio_b2b_txen_on_sw_switch(uint8_t compare_reg_index,
416 uint8_t radio_enable_ppi)
417 {
418 /* NOTE: As independent PPI are used to trigger the Radio Tx task,
419 * double buffers implementation works for sw_switch using PPIs,
420 * simply reuse the hal_radio_txen_on_sw_switch() function to set
421 * the next PPIs task to be Radio Tx enable.
422 */
423 hal_radio_txen_on_sw_switch(compare_reg_index, radio_enable_ppi);
424 }
425
hal_radio_rxen_on_sw_switch(uint8_t compare_reg_index,uint8_t radio_enable_ppi)426 static inline void hal_radio_rxen_on_sw_switch(uint8_t compare_reg_index, uint8_t radio_enable_ppi)
427 {
428 /* Wire SW Switch timer event <compare_reg> to the
429 * PPI[<radio_enable_ppi>] for enabling Radio. Do
430 * not wire the task; it is done by the caller of
431 * the function depending on the desired direction
432 * (TX/RX).
433 */
434 nrf_ppi_event_endpoint_setup(NRF_PPI, radio_enable_ppi,
435 HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(compare_reg_index));
436
437 nrf_ppi_task_endpoint_setup(NRF_PPI, radio_enable_ppi,
438 HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_RX);
439 }
440
hal_radio_b2b_rxen_on_sw_switch(uint8_t compare_reg_index,uint8_t radio_enable_ppi)441 static inline void hal_radio_b2b_rxen_on_sw_switch(uint8_t compare_reg_index,
442 uint8_t radio_enable_ppi)
443 {
444 /* NOTE: As independent PPI are used to trigger the Radio Tx task,
445 * double buffers implementation works for sw_switch using PPIs,
446 * simply reuse the hal_radio_txen_on_sw_switch() function to set
447 * the next PPIs task to be Radio Tx enable.
448 */
449 hal_radio_rxen_on_sw_switch(compare_reg_index, radio_enable_ppi);
450 }
451
hal_radio_sw_switch_disable(void)452 static inline void hal_radio_sw_switch_disable(void)
453 {
454 /* Disable the following PPI channels that implement SW Switch:
455 * - Clearing SW SWITCH TIMER on RADIO END event
456 * - Enabling SW SWITCH PPI Group on RADIO END event
457 */
458 nrf_ppi_channels_disable(
459 NRF_PPI,
460 BIT(HAL_SW_SWITCH_TIMER_CLEAR_PPI) |
461 BIT(HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI));
462
463 /* Invalidation of subscription of S2 timer Compare used when
464 * RXing on LE Coded PHY is not needed, as other DPPI subscription
465 * is disable on each sw_switch call already.
466 */
467 }
468
hal_radio_sw_switch_b2b_tx_disable(uint8_t compare_reg_index)469 static inline void hal_radio_sw_switch_b2b_tx_disable(uint8_t compare_reg_index)
470 {
471 hal_radio_sw_switch_disable();
472 }
473
hal_radio_sw_switch_b2b_rx_disable(uint8_t compare_reg_index)474 static inline void hal_radio_sw_switch_b2b_rx_disable(uint8_t compare_reg_index)
475 {
476 hal_radio_sw_switch_disable();
477 }
478
hal_radio_sw_switch_cleanup(void)479 static inline void hal_radio_sw_switch_cleanup(void)
480 {
481 hal_radio_sw_switch_disable();
482 nrf_ppi_group_disable(NRF_PPI, SW_SWITCH_TIMER_TASK_GROUP(0));
483 nrf_ppi_group_disable(NRF_PPI, SW_SWITCH_TIMER_TASK_GROUP(1));
484 }
485
486 #if defined(CONFIG_BT_CTLR_PHY_CODED) && \
487 defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED)
488 /* Cancel the SW switch timer running considering S8 timing:
489 * wire the RADIO EVENTS_RATEBOOST event to SW_SWITCH_TIMER TASKS_CAPTURE task.
490 */
491 #define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_EVT \
492 ((uint32_t)&(NRF_RADIO->EVENTS_RATEBOOST))
493 #define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_TASK(index) \
494 ((uint32_t)&(SW_SWITCH_TIMER->TASKS_CAPTURE[index]))
495
hal_radio_sw_switch_coded_tx_config_set(uint8_t ppi_en,uint8_t ppi_dis,uint8_t cc_s2,uint8_t group_index)496 static inline void hal_radio_sw_switch_coded_tx_config_set(uint8_t ppi_en,
497 uint8_t ppi_dis, uint8_t cc_s2, uint8_t group_index)
498 {
499 nrf_ppi_event_endpoint_setup(NRF_PPI, ppi_en,
500 HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(cc_s2));
501
502 nrf_ppi_task_endpoint_setup(NRF_PPI, ppi_en,
503 HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX);
504
505 /* Wire the Group task disable
506 * to the S2 EVENTS_COMPARE.
507 */
508 nrf_ppi_event_endpoint_setup(NRF_PPI, ppi_dis,
509 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(cc_s2));
510
511 nrf_ppi_task_endpoint_setup(NRF_PPI, ppi_dis,
512 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(group_index));
513
514 /* Capture CC to cancel the timer that has assumed
515 * S8 reception, if packet will be received in S2.
516 */
517 nrf_ppi_event_endpoint_setup(NRF_PPI, HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI,
518 HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_EVT);
519 nrf_ppi_task_endpoint_setup(NRF_PPI, HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI,
520 HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_TASK(cc_s2));
521
522 nrf_ppi_channels_enable(
523 NRF_PPI,
524 BIT(HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI));
525
526 /* Note: below code is not absolutely needed, as other DPPI subscription
527 * is disable on each sw_switch call already.
528 */
529 if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED) && false) {
530 /* We need to clear the other group S2 PPI */
531 group_index = (group_index + 1) & 0x01;
532 hal_radio_sw_switch_coded_config_clear(
533 HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI(group_index),
534 0U, 0U, 0U);
535 }
536 }
537
hal_radio_sw_switch_coded_config_clear(uint8_t ppi_en,uint8_t ppi_dis,uint8_t cc_s2,uint8_t group_index)538 static inline void hal_radio_sw_switch_coded_config_clear(uint8_t ppi_en,
539 uint8_t ppi_dis, uint8_t cc_s2, uint8_t group_index)
540 {
541 /* Invalidate PPI used when RXing on LE Coded PHY. */
542 nrf_ppi_event_endpoint_setup(NRF_PPI, ppi_en, 0);
543 nrf_ppi_task_endpoint_setup(NRF_PPI, ppi_en, 0);
544 }
545
hal_radio_sw_switch_disable_group_clear(uint8_t ppi_dis,uint8_t cc_reg,uint8_t group_index)546 static inline void hal_radio_sw_switch_disable_group_clear(uint8_t ppi_dis, uint8_t cc_reg,
547 uint8_t group_index)
548 {
549 /* Wire the Group task disable to the default EVENTS_COMPARE. */
550 nrf_ppi_event_endpoint_setup(NRF_PPI, ppi_dis,
551 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(cc_reg));
552 nrf_ppi_task_endpoint_setup(NRF_PPI, ppi_dis,
553 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(group_index));
554 }
555
556 #else
557
hal_radio_group_task_disable_ppi_setup(void)558 static inline void hal_radio_group_task_disable_ppi_setup(void)
559 {
560 /* Wire SW SWITCH TIMER EVENTS COMPARE event <cc index-0> to
561 * PPI Group TASK [<index-0>] DISABLE task, over PPI<index-0>.
562 */
563 nrf_ppi_channel_endpoint_setup(
564 NRF_PPI,
565 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0),
566 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(
567 SW_SWITCH_TIMER_EVTS_COMP(0)),
568 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(0));
569
570 /* Wire SW SWITCH TIMER event <compare index-1> to
571 * PPI Group[<index-1>] Disable Task, over PPI<index-1>.
572 */
573 nrf_ppi_channel_endpoint_setup(
574 NRF_PPI,
575 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1),
576 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(
577 SW_SWITCH_TIMER_EVTS_COMP(1)),
578 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(1));
579 }
580 #endif /* CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
581
582 #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)
583 /* The 2 adjacent TIMER EVENTS_COMPARE event offsets used for implementing PHYEND delay compensation
584 * for SW_SWITCH_TIMER-based TIFS auto-switch. 'index' must be 0 or 1.
585 */
586 #define SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_EVTS_COMP(index) \
587 (SW_SWITCH_TIMER_EVTS_COMP_PHYEND_DELAY_COMPENSATION_BASE + (index))
588 /* Wire the SW SWITCH PHYEND delay compensation TIMER EVENTS_COMPARE[<cc_offset>] event to software
589 * switch TIMER0->CLEAR task.
590 */
591 #define HAL_SW_SWITCH_RADIO_ENABLE_PHYEND_DELAY_COMPENSATION_PPI(index) \
592 (HAL_SW_SWITCH_RADIO_ENABLE_PHYEND_DELAY_COMPENSATION_PPI_BASE + (index))
593
594 /* Cancel the SW switch timer running considering PHYEND delay compensation timing:
595 * wire the RADIO EVENTS_CTEPRESENT event to SW_SWITCH_TIMER TASKS_CAPTURE task.
596 */
597 #define HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI_EVT \
598 ((uint32_t)&(NRF_RADIO->EVENTS_CTEPRESENT))
599 #define HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI_TASK(index) \
600 ((uint32_t)&(SW_SWITCH_TIMER->TASKS_CAPTURE[index]))
601
602 /**
603 * @brief Setup additional EVENTS_COMPARE to compensate EVENTS_PHYEND delay.
604 *
605 * When EVENTS_PHYEND event is used to mark actual end of PDU, CTEINLINE is enabled but received
606 * PDU does not include CTE after CRC, the EVENTS_PHYEND will be generated with a short delay.
607 * That influences maintenance of TISF by software switch. To compensate the delay additional
608 * EVENTS_COMPARE events is set with TIFS value subtracted by the delay. This EVENT_COMPARE
609 * event will timeout before regular EVENTS_COMPARE and start radio switching procedure.
610 * In case there is a CTEInfo in the received PDU, an EVENTS_CTEPRESENT will be generated by
611 * Radio peripheral. The EVENTS_CTEPRESENT event is wired to cancel EVENTS_COMPARE setup for
612 * handling delayed EVENTS_PHYEND.
613 *
614 * Disable of the group of PPIs responsible for handling of software based switch is done by
615 * timeout of regular EVENTS_PHYEND event. The EVENTS_PHYEND delay is short enough (16 us) that
616 * it can use the same PPI to trigger disable the group for timeout for both EVENTS_COMPAREs.
617 * In case the EVENTS_COMPARE for delayed EVENTS_PHYEND event timesout, the group will be disabled
618 * within the Radio TX rampup period.
619 *
620 * @param radio_enable_ppi Index of PPI to wire EVENTS_PHYEND event to Radio enable TX task.
621 * @param phyend_delay_cc Index of EVENTS_COMPARE event to be set for delayed EVENTS_PHYEND event
622 */
623 static inline void
hal_radio_sw_switch_phyend_delay_compensation_config_set(uint8_t radio_enable_ppi,uint8_t phyend_delay_cc)624 hal_radio_sw_switch_phyend_delay_compensation_config_set(uint8_t radio_enable_ppi,
625 uint8_t phyend_delay_cc)
626 {
627 /* Wire EVENTS_COMPARE[<phyend_delay_cc_offs>] event to Radio TASKS_TXEN */
628 nrf_ppi_event_endpoint_setup(NRF_PPI, radio_enable_ppi,
629 HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(phyend_delay_cc));
630
631 nrf_ppi_task_endpoint_setup(NRF_PPI, radio_enable_ppi,
632 HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX);
633
634 /* Wire Radio CTEPRESENT event to cancel EVENTS_COMPARE[<cc_offs>] timer */
635 nrf_ppi_event_endpoint_setup(NRF_PPI,
636 HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI,
637 HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI_EVT);
638 nrf_ppi_task_endpoint_setup(NRF_PPI,
639 HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI,
640 HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI_TASK(phyend_delay_cc));
641
642 /* Enable CTEPRESENT event to disable EVENTS_COMPARE[<cc_offs>] PPI channel */
643 nrf_ppi_channels_enable(NRF_PPI,
644 BIT(HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI));
645 }
646
647 /**
648 * @brief Clear additional EVENTS_COMAPRE responsible for compensation EVENTS_PHYEND delay.
649 *
650 * Disables PPI responsible for cancel of EVENTS_COMPARE set for delayed EVENTS_PHYEND.
651 * Removes wireing of delayed EVENTS_COMPARE event to enable Radio TX task.
652 *
653 * @param radio_enable_ppi Index of PPI to wire EVENTS_PHYEND event to Radio enable TX task.
654 * @param phyend_delay_cc Not used in context of nRF52 SOCs
655 */
656 static inline void
hal_radio_sw_switch_phyend_delay_compensation_config_clear(uint8_t radio_enable_ppi,uint8_t phyend_delay_cc)657 hal_radio_sw_switch_phyend_delay_compensation_config_clear(uint8_t radio_enable_ppi,
658 uint8_t phyend_delay_cc)
659 {
660 /* Invalidate PPI used when */
661 nrf_ppi_event_endpoint_setup(NRF_PPI, radio_enable_ppi, NRF_PPI_NONE);
662 nrf_ppi_task_endpoint_setup(NRF_PPI, radio_enable_ppi, NRF_PPI_NONE);
663
664 /* Disable CTEPRESENT event to disable EVENTS_COMPARE[<phyend_delay_cc_offs>] PPI channel */
665 nrf_ppi_channels_disable(NRF_PPI,
666 BIT(HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI));
667 }
668 #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
669
hal_radio_sw_switch_ppi_group_setup(void)670 static inline void hal_radio_sw_switch_ppi_group_setup(void)
671 {
672 /* Include the appropriate PPI channels in the two PPI Groups. */
673 #if !defined(CONFIG_BT_CTLR_PHY_CODED) || \
674 !defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED)
675 NRF_PPI->CHG[SW_SWITCH_TIMER_TASK_GROUP(0)] =
676 BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0)) |
677 #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)
678 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PHYEND_DELAY_COMPENSATION_PPI(0)) |
679 #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
680 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(0));
681 NRF_PPI->CHG[SW_SWITCH_TIMER_TASK_GROUP(1)] =
682 BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1)) |
683 #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)
684 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PHYEND_DELAY_COMPENSATION_PPI(1)) |
685 #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
686 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(1));
687 #else
688 NRF_PPI->CHG[SW_SWITCH_TIMER_TASK_GROUP(0)] =
689 BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0)) |
690 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(0)) |
691 BIT(HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI(0));
692 NRF_PPI->CHG[SW_SWITCH_TIMER_TASK_GROUP(1)] =
693 BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1)) |
694 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(1)) |
695 BIT(HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI(1));
696 #endif /* CONFIG_BT_CTLR_PHY_CODED && CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
697 }
698
699 #endif /* !CONFIG_BT_CTLR_TIFS_HW */
700