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