1 /*
2  * Copyright (c) 2016 - 2019 Nordic Semiconductor ASA
3  * Copyright (c) 2016 Vinayak Kariappa Chettimada
4  * Copyright 2019 - 2020 NXP
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <string.h>
10 #include <zephyr/sys/printk.h>
11 #include <zephyr/sys/byteorder.h>
12 #include <zephyr/bluetooth/addr.h>
13 #include <zephyr/toolchain.h>
14 #include <zephyr/irq.h>
15 #include <errno.h>
16 
17 #include "util/mem.h"
18 
19 #include "hal/ccm.h"
20 #include "hal/radio.h"
21 
22 #include "lll/pdu_vendor.h"
23 #include "ll_sw/pdu.h"
24 
25 #include "fsl_xcvr.h"
26 #include "hal/cntr.h"
27 #include "hal/ticker.h"
28 #include "hal/swi.h"
29 #include "fsl_cau3_ble.h"	/* must be after irq.h */
30 
31 #include "common/assert.h"
32 
33 #include <soc.h>
34 #include "hal/debug.h"
35 
36 #define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL
37 #include <zephyr/logging/log.h>
38 LOG_MODULE_REGISTER(bt_openisa_radio);
39 
40 static radio_isr_cb_t isr_cb;
41 static void *isr_cb_param;
42 
43 #define RADIO_AESCCM_HDR_MASK 0xE3 /* AES-CCM: NESN, SN, MD bits masked to 0 */
44 #define RADIO_PDU_LEN_MAX (BIT(8) - 1)
45 #define BYTES_TO_USEC(bytes, bits_per_usec)	\
46 		((bytes) * 8 >> (__builtin_ffs(bits_per_usec) - 1))
47 
48 /* us values */
49 #define MIN_CMD_TIME 10		/* Minimum interval for a delayed radio cmd */
50 #define RX_MARGIN 8
51 #define TX_MARGIN 0
52 #define RX_WTMRK 5		/* (AA + PDU header) - 1 */
53 #define AA_OVHD_1MBPS 27	/* AA playback overhead for 1 Mbps PHY */
54 #define AA_OVHD_2MBPS 10	/* AA playback overhead for 2 Mbps PHY */
55 #define RX_OVHD 32		/* Rx overhead */
56 
57 #define PB_RX 544	/* half of PB (packet buffer) */
58 
59 /* The PDU in packet buffer starts after the Access Address which is 4 octets */
60 #define PB_RX_PDU (PB_RX + 2)	/* Rx PDU offset (in halfwords) in PB */
61 #define PB_TX_PDU 2		/* Tx PDU offset (in halfwords) in packet
62 				 * buffer
63 				 */
64 
65 #define RADIO_ACTIVE_MASK 0x1fff
66 #define RADIO_DISABLE_TMR 4		/* us */
67 
68 /* Delay needed in order to enter Manual DSM.
69  * Must be at least 4 ticks ahead of DSM_TIMER (from RM).
70  */
71 #define DSM_ENTER_DELAY_TICKS 6
72 
73 /* Delay needed in order to exit Manual DSM.
74  * Should be after radio_tmr_start() (2 ticks after lll_clk_on()).
75  * But less that 1.5ms (EVENT_OVERHEAD_XTAL_US) (ULL to LLL time offset).
76  * Must be at least 4 ticks ahead of DSM_TIMER (from RM).
77  */
78 #define DSM_EXIT_DELAY_TICKS 30
79 
80 /* Mask to determine the state of DSM machine */
81 #define MAN_DSM_ON (RSIM_DSM_CONTROL_MAN_DEEP_SLEEP_STATUS_MASK \
82 		| RSIM_DSM_CONTROL_DSM_MAN_READY_MASK \
83 		| RSIM_DSM_CONTROL_MAN_SLEEP_REQUEST_MASK) \
84 
85 static uint32_t dsm_ref; /* DSM reference counter */
86 
87 static uint8_t delayed_radio_start;
88 static uint8_t delayed_trx;
89 static uint32_t delayed_ticks_start;
90 static uint32_t delayed_remainder;
91 static uint8_t delayed_radio_stop;
92 static uint32_t delayed_hcto;
93 
94 static uint32_t rtc_start;
95 static uint32_t rtc_diff_start_us;
96 
97 static uint32_t tmr_aa;		/* AA (Access Address) timestamp saved value */
98 static uint32_t tmr_aa_save;	/* save AA timestamp */
99 static uint32_t tmr_ready;		/* radio ready for Tx/Rx timestamp */
100 static uint32_t tmr_end;		/* Tx/Rx end timestamp saved value */
101 static uint32_t tmr_end_save;	/* save Tx/Rx end timestamp */
102 static uint32_t tmr_tifs;
103 
104 static uint32_t rx_wu;
105 static uint32_t tx_wu;
106 
107 static uint8_t phy_mode;		/* Current PHY mode (DR_1MBPS or DR_2MBPS) */
108 static uint8_t bits_per_usec;	/* This saves the # of bits per usec,
109 				 * depending on the PHY mode
110 				 */
111 static uint8_t phy_aa_ovhd;	/* This saves the AA overhead, depending on the
112 				 * PHY mode
113 				 */
114 
115 static uint32_t isr_tmr_aa;
116 static uint32_t isr_tmr_end;
117 static uint32_t isr_latency;
118 static uint32_t next_wu;
119 static uint32_t next_radio_cmd;
120 
121 static uint32_t radio_trx;
122 static uint32_t force_bad_crc;
123 static uint32_t skip_hcto;
124 
125 static uint8_t *rx_pkt_ptr;
126 static uint32_t payload_max_size;
127 
128 static uint8_t MALIGN(4) _pkt_empty[PDU_EM_LL_SIZE_MAX];
129 static uint8_t MALIGN(4) _pkt_scratch[
130 			((RADIO_PDU_LEN_MAX + 3) > PDU_AC_LL_SIZE_MAX) ?
131 			(RADIO_PDU_LEN_MAX + 3) : PDU_AC_LL_SIZE_MAX];
132 
133 static int8_t rssi;
134 
135 static struct {
136 	union {
137 		uint64_t counter;
138 		uint8_t bytes[CAU3_AES_BLOCK_SIZE - 1 - 2];
139 	} nonce;	/* used by the B0 format but not in-situ */
140 	struct pdu_data *rx_pkt_out;
141 	struct pdu_data *rx_pkt_in;
142 	uint8_t auth_mic_valid;
143 	uint8_t empty_pdu_rxed;
144 } ctx_ccm;
145 
146 #if defined(CONFIG_BT_CTLR_PRIVACY)
147 #define RPA_NO_IRK_MATCH 0xFF	/* No IRK match in AR table */
148 
149 static struct {
150 	uint8_t ar_enable;
151 	uint32_t irk_idx;
152 } radio_ar_ctx = {0U, RPA_NO_IRK_MATCH};
153 #endif /* CONFIG_BT_CTLR_PRIVACY */
154 
tmp_cb(void * param)155 static void tmp_cb(void *param)
156 {
157 	uint32_t tmr = GENFSK->EVENT_TMR & GENFSK_EVENT_TMR_EVENT_TMR_MASK;
158 	uint32_t t2 = GENFSK->T2_CMP & GENFSK_T2_CMP_T2_CMP_MASK;
159 
160 	isr_latency = (tmr - t2) & GENFSK_EVENT_TMR_EVENT_TMR_MASK; /* 24bit */
161 	/* Mark as done */
162 	*(uint32_t *)param = 1;
163 }
164 
get_isr_latency(void)165 static void get_isr_latency(void)
166 {
167 	volatile uint32_t tmp = 0;
168 
169 	radio_isr_set(tmp_cb, (void *)&tmp);
170 
171 	/* Reset TMR to zero */
172 	GENFSK->EVENT_TMR = 0x1000000;
173 
174 	radio_disable();
175 	while (!tmp) {
176 	}
177 	irq_disable(LL_RADIO_IRQn_2nd_lvl);
178 }
179 
180 static uint32_t radio_tmr_start_hlp(uint8_t trx, uint32_t ticks_start, uint32_t remainder);
181 static void radio_tmr_hcto_configure_hlp(uint32_t hcto);
radio_config_after_wake(void)182 static void radio_config_after_wake(void)
183 {
184 	if (!delayed_radio_start) {
185 		delayed_radio_stop = 0;
186 		return;
187 	}
188 
189 	delayed_radio_start = 0;
190 	radio_tmr_start_hlp(delayed_trx, delayed_ticks_start,
191 				delayed_remainder);
192 
193 	if (delayed_radio_stop) {
194 		delayed_radio_stop = 0;
195 
196 		/* Adjust time out as remainder was in radio_tmr_start_hlp() */
197 		delayed_hcto += rtc_diff_start_us;
198 		radio_tmr_hcto_configure_hlp(delayed_hcto);
199 	}
200 }
201 
202 #if defined(CONFIG_BT_CTLR_PRIVACY)
ar_execute(void * pkt)203 static void ar_execute(void *pkt)
204 {
205 	struct pdu_adv *pdu_adv = (struct pdu_adv *)pkt;
206 	bt_addr_t *rpa = (bt_addr_t *)&pdu_adv->payload[0];
207 
208 	/* Perform address resolution when TxAdd=1 and address is resolvable */
209 	if (pdu_adv->tx_addr && BT_ADDR_IS_RPA(rpa)) {
210 		uint32_t *hash, *prand;
211 		status_t status;
212 
213 		/* Use pointers to avoid breaking strict aliasing */
214 		hash = (uint32_t *)(&rpa->val[0]);
215 		prand = (uint32_t *)(&rpa->val[3]);
216 
217 		/* CAUv3 needs hash & prand in le format, right-justified */
218 		status = CAU3_RPAtableSearch(CAU3, (*prand & 0xFFFFFF),
219 					(*hash & 0xFFFFFF),
220 					&radio_ar_ctx.irk_idx,
221 					kCAU3_TaskDoneEvent);
222 		if (status != kStatus_Success) {
223 			radio_ar_ctx.irk_idx = RPA_NO_IRK_MATCH;
224 			LOG_ERR("CAUv3 RPA table search failed %d", status);
225 			return;
226 		}
227 	}
228 
229 	radio_ar_ctx.ar_enable = 0U;
230 }
231 #endif /* CONFIG_BT_CTLR_PRIVACY */
232 
pkt_rx(void)233 static void pkt_rx(void)
234 {
235 	uint32_t len, idx;
236 	uint16_t *rxb = (uint16_t *)rx_pkt_ptr, tmp;
237 	volatile uint16_t *pb = &GENFSK->PACKET_BUFFER[PB_RX_PDU];
238 	volatile const uint32_t *sts = &GENFSK->XCVR_STS;
239 
240 	/* payload length */
241 	len = (GENFSK->XCVR_CTRL & GENFSK_XCVR_CTRL_LENGTH_EXT_MASK) >>
242 			GENFSK_XCVR_CTRL_LENGTH_EXT_SHIFT;
243 
244 	if (len > payload_max_size) {
245 		/* Unexpected size */
246 		force_bad_crc = 1;
247 		next_radio_cmd = 0;
248 		while (*sts & GENFSK_XCVR_STS_RX_IN_PROGRESS_MASK) {
249 		}
250 		return;
251 	}
252 
253 	/* For Data Physical Channel PDU,
254 	 * assume no CTEInfo field, CP=0 => 2 bytes header
255 	 */
256 	/* Add PDU header size */
257 	len += 2;
258 
259 	/* Add to AA time, PDU + CRC time */
260 	isr_tmr_end = isr_tmr_aa + BYTES_TO_USEC(len + 3, bits_per_usec);
261 
262 	/* If not enough time for warmup after we copy the PDU from
263 	 * packet buffer, send delayed command now
264 	 */
265 	if (next_radio_cmd) {
266 		/* Start Rx/Tx in TIFS */
267 		idx = isr_tmr_end + tmr_tifs - next_wu;
268 		GENFSK->XCVR_CTRL = next_radio_cmd;
269 		GENFSK->T1_CMP = GENFSK_T1_CMP_T1_CMP(idx) |
270 				 GENFSK_T1_CMP_T1_CMP_EN(1);
271 		next_radio_cmd = 0;
272 	}
273 
274 	/* Can't rely on data read from packet buffer while in Rx */
275 	/* Wait for Rx to finish */
276 	while (*sts & GENFSK_XCVR_STS_RX_IN_PROGRESS_MASK) {
277 	}
278 
279 	if (ctx_ccm.rx_pkt_out) {
280 		*(uint16_t *)ctx_ccm.rx_pkt_out = pb[0];
281 		if (len < CAU3_BLE_MIC_SIZE) {
282 			ctx_ccm.rx_pkt_out = 0;
283 			ctx_ccm.rx_pkt_in = 0;
284 			ctx_ccm.empty_pdu_rxed = 1;
285 		}
286 	}
287 
288 	/* Copy the PDU */
289 	for (idx = 0; idx < len / 2; idx++) {
290 		rxb[idx] = pb[idx];
291 	}
292 
293 	/* Copy last byte */
294 	if (len & 0x1) {
295 		tmp = pb[len / 2];
296 		rx_pkt_ptr[len - 1] =  ((uint8_t *)&tmp)[0];
297 	}
298 
299 #if defined(CONFIG_BT_CTLR_PRIVACY)
300 	/* Perform address resolution on this Rx */
301 	if (radio_ar_ctx.ar_enable) {
302 		ar_execute(rxb);
303 	}
304 #endif /* CONFIG_BT_CTLR_PRIVACY */
305 
306 	force_bad_crc = 0;
307 }
308 
309 #define IRQ_MASK ~(GENFSK_IRQ_CTRL_T2_IRQ_MASK | \
310 		   GENFSK_IRQ_CTRL_RX_WATERMARK_IRQ_MASK | \
311 		   GENFSK_IRQ_CTRL_TX_IRQ_MASK | \
312 		   GENFSK_IRQ_CTRL_WAKE_IRQ_MASK)
isr_radio(void * arg)313 void isr_radio(void *arg)
314 {
315 	ARG_UNUSED(arg);
316 
317 	uint32_t tmr = GENFSK->EVENT_TMR & GENFSK_EVENT_TMR_EVENT_TMR_MASK;
318 	uint32_t irq = GENFSK->IRQ_CTRL;
319 	uint32_t valid = 0;
320 	/* We need to check for a valid IRQ source.
321 	 * In theory, we could get to this ISR after the IRQ source was cleared.
322 	 * This could happen due to the way LLL interacts with IRQs
323 	 * (radio_isr_set(), radio_disable()) and their propagation path:
324 	 * GENFSK -> INTMUX(does not latch pending source interrupts)
325 	 * INTMUX -> EVENT_UNIT
326 	 */
327 
328 	if (irq & GENFSK_IRQ_CTRL_WAKE_IRQ_MASK) {
329 		/* Clear pending interrupts */
330 		GENFSK->IRQ_CTRL &= 0xffffffff;
331 
332 		/* Disable DSM_TIMER */
333 		RSIM->DSM_CONTROL &= ~RSIM_DSM_CONTROL_DSM_TIMER_EN(1);
334 
335 		radio_config_after_wake();
336 		return;
337 	}
338 
339 	if (irq & GENFSK_IRQ_CTRL_TX_IRQ_MASK) {
340 		valid = 1;
341 		GENFSK->IRQ_CTRL &= (IRQ_MASK | GENFSK_IRQ_CTRL_TX_IRQ_MASK);
342 		GENFSK->T1_CMP &= ~GENFSK_T1_CMP_T1_CMP_EN_MASK;
343 
344 		isr_tmr_end = tmr - isr_latency;
345 		if (tmr_end_save) {
346 			tmr_end = isr_tmr_end;
347 		}
348 		radio_trx = 1;
349 	}
350 
351 	if (irq & GENFSK_IRQ_CTRL_RX_WATERMARK_IRQ_MASK) {
352 		valid = 1;
353 		/* Disable Rx timeout */
354 		/* 0b1010..RX Cancel -- Cancels pending RX events but do not
355 		 *			abort a RX-in-progress
356 		 */
357 		GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0xa);
358 		GENFSK->T2_CMP &= ~GENFSK_T2_CMP_T2_CMP_EN_MASK;
359 
360 		GENFSK->IRQ_CTRL &= (IRQ_MASK |
361 				     GENFSK_IRQ_CTRL_RX_WATERMARK_IRQ_MASK);
362 		GENFSK->T1_CMP &= ~GENFSK_T1_CMP_T1_CMP_EN_MASK;
363 
364 		/* Fix reported AA time */
365 		isr_tmr_aa = GENFSK->TIMESTAMP - phy_aa_ovhd;
366 
367 		if (tmr_aa_save) {
368 			tmr_aa = isr_tmr_aa;
369 		}
370 		/* Copy the PDU as it arrives, calculates Rx end */
371 		pkt_rx();
372 		if (tmr_end_save) {
373 			tmr_end = isr_tmr_end;	/* from pkt_rx() */
374 		}
375 		radio_trx = 1;
376 		rssi = (GENFSK->XCVR_STS & GENFSK_XCVR_STS_RSSI_MASK) >>
377 					GENFSK_XCVR_STS_RSSI_SHIFT;
378 	}
379 
380 	if (irq & GENFSK_IRQ_CTRL_T2_IRQ_MASK) {
381 		valid = 1;
382 		GENFSK->IRQ_CTRL &= (IRQ_MASK | GENFSK_IRQ_CTRL_T2_IRQ_MASK);
383 		/* Disable both comparators */
384 		GENFSK->T1_CMP &= ~GENFSK_T1_CMP_T1_CMP_EN_MASK;
385 		GENFSK->T2_CMP &= ~GENFSK_T2_CMP_T2_CMP_EN_MASK;
386 	}
387 
388 	if (radio_trx && next_radio_cmd) {
389 		/* Start Rx/Tx in TIFS */
390 		tmr = isr_tmr_end + tmr_tifs - next_wu;
391 		GENFSK->XCVR_CTRL = next_radio_cmd;
392 		GENFSK->T1_CMP = GENFSK_T1_CMP_T1_CMP(tmr) |
393 				 GENFSK_T1_CMP_T1_CMP_EN(1);
394 		next_radio_cmd = 0;
395 	}
396 
397 	if (valid) {
398 		isr_cb(isr_cb_param);
399 	}
400 }
401 
radio_isr_set(radio_isr_cb_t cb,void * param)402 void radio_isr_set(radio_isr_cb_t cb, void *param)
403 {
404 	irq_disable(LL_RADIO_IRQn_2nd_lvl);
405 	irq_disable(LL_RADIO_IRQn);
406 
407 	isr_cb_param = param;
408 	isr_cb = cb;
409 
410 	/* Clear pending interrupts */
411 	GENFSK->IRQ_CTRL &= 0xffffffff;
412 	EVENT_UNIT->INTPTPENDCLEAR = (uint32_t)(1U << LL_RADIO_IRQn);
413 
414 	irq_enable(LL_RADIO_IRQn);
415 	irq_enable(LL_RADIO_IRQn_2nd_lvl);
416 }
417 
418 #define DISABLE_HPMCAL
419 
420 #ifdef DISABLE_HPMCAL
421 #define WU_OPTIM            26  /* 34: quite ok, 36 few ok */
422 #define USE_FIXED_HPMCAL    563
423 
hpmcal_disable(void)424 static void hpmcal_disable(void)
425 {
426 #ifdef USE_FIXED_HPMCAL
427 	uint32_t hpmcal = USE_FIXED_HPMCAL;
428 #else
429 	uint32_t hpmcal_vals[40];
430 	uint32_t hpmcal;
431 	int i;
432 
433 	GENFSK->TX_POWER = GENFSK_TX_POWER_TX_POWER(1);
434 
435 	/* TX warm-up at Channel Frequency = 2.44GHz */
436 	for (i = 0; i < ARRAY_SIZE(hpmcal_vals); i++) {
437 		GENFSK->CHANNEL_NUM = 2402 - 2360 + 2 * i;
438 
439 		/* Reset TMR to zero */
440 		GENFSK->EVENT_TMR = 0x1000000;
441 
442 		/* TX Start Now */
443 		GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0x1);
444 
445 		while ((GENFSK->EVENT_TMR & 0xffffff) < 1000)
446 			;
447 
448 		/* Abort All */
449 		GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0xb);
450 
451 		/* Wait for XCVR to become idle. */
452 		while (GENFSK->XCVR_CTRL & GENFSK_XCVR_CTRL_XCVR_BUSY_MASK)
453 			;
454 
455 		hpmcal_vals[i] = (XCVR_PLL_DIG->HPMCAL_CTRL &
456 				XCVR_PLL_DIG_HPMCAL_CTRL_HPM_CAL_FACTOR_MASK) >>
457 				XCVR_PLL_DIG_HPMCAL_CTRL_HPM_CAL_FACTOR_SHIFT;
458 	}
459 
460 	hpmcal = hpmcal_vals[20];
461 #endif
462 
463 	XCVR_PLL_DIG->HPMCAL_CTRL = (XCVR_PLL_DIG->HPMCAL_CTRL &
464 			~XCVR_PLL_DIG_HPMCAL_CTRL_HPM_CAL_FACTOR_MANUAL_MASK) +
465 			XCVR_PLL_DIG_HPMCAL_CTRL_HPM_CAL_FACTOR_MANUAL(hpmcal) +
466 			XCVR_PLL_DIG_HPMCAL_CTRL_HP_CAL_DISABLE_MASK +
467 			0x00000000;
468 
469 	/* Move the sigma_delta_en signal to be 1us after pll_dig_en */
470 	int pll_dig_en  = (XCVR_TSM->TIMING34 &
471 			XCVR_TSM_TIMING34_PLL_DIG_EN_TX_HI_MASK) >>
472 			XCVR_TSM_TIMING34_PLL_DIG_EN_TX_HI_SHIFT;
473 
474 	XCVR_TSM->TIMING38 = (XCVR_TSM->TIMING38 &
475 			~XCVR_TSM_TIMING38_SIGMA_DELTA_EN_TX_HI_MASK) +
476 			XCVR_TSM_TIMING38_SIGMA_DELTA_EN_TX_HI(pll_dig_en+1);
477 			/* sigma_delta_en */
478 
479 	XCVR_TSM->TIMING19   -= B1(WU_OPTIM); /* sy_pd_filter_charge_en */
480 	XCVR_TSM->TIMING24   -= B1(WU_OPTIM); /* sy_divn_cal_en */
481 	XCVR_TSM->TIMING13   -= B1(WU_OPTIM); /* sy_vco_autotune_en */
482 	XCVR_TSM->TIMING17   -= B0(WU_OPTIM); /* sy_lo_tx_buf_en */
483 	XCVR_TSM->TIMING26   -= B0(WU_OPTIM); /* tx_pa_en */
484 	XCVR_TSM->TIMING35   -= B0(WU_OPTIM); /* tx_dig_en */
485 	XCVR_TSM->TIMING14   -= B0(WU_OPTIM); /* sy_pd_cycle_slip_ld_ft_en */
486 
487 	XCVR_TSM->END_OF_SEQ -= B1(WU_OPTIM) + B0(WU_OPTIM);
488 }
489 #endif
490 
radio_setup(void)491 void radio_setup(void)
492 {
493 	XCVR_Reset();
494 
495 #if defined(CONFIG_BT_CTLR_PRIVACY) || defined(CONFIG_BT_CTLR_LE_ENC)
496 	CAU3_Init(CAU3);
497 #endif /* CONFIG_BT_CTLR_PRIVACY || CONFIG_BT_CTLR_LE_ENC */
498 
499 	XCVR_Init(GFSK_BT_0p5_h_0p5, DR_1MBPS);
500 	XCVR_SetXtalTrim(41);
501 
502 #ifdef DISABLE_HPMCAL
503 	hpmcal_disable();
504 #endif
505 
506 	/* Enable Deep Sleep Mode for GENFSK */
507 	XCVR_MISC->XCVR_CTRL |= XCVR_CTRL_XCVR_CTRL_MAN_DSM_SEL(2);
508 
509 	/* Enable the CRC as it is disabled by default after reset */
510 	XCVR_MISC->CRCW_CFG |= XCVR_CTRL_CRCW_CFG_CRCW_EN(1);
511 
512 	/* Assign Radio #0 Interrupt to GENERIC_FSK */
513 	XCVR_MISC->XCVR_CTRL |= XCVR_CTRL_XCVR_CTRL_RADIO0_IRQ_SEL(3);
514 
515 	phy_mode = GENFSK->BITRATE = DR_1MBPS;
516 	bits_per_usec = 1;
517 	phy_aa_ovhd = AA_OVHD_1MBPS;
518 
519 	/*
520 	 * Split the buffer in equal parts: first half for Tx,
521 	 * second half for Rx
522 	 */
523 	GENFSK->PB_PARTITION = GENFSK_PB_PARTITION_PB_PARTITION(PB_RX);
524 
525 	/* Get warmup times. They are used in TIFS calculations */
526 	rx_wu = (XCVR_TSM->END_OF_SEQ & XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_MASK)
527 				>> XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_SHIFT;
528 	tx_wu = (XCVR_TSM->END_OF_SEQ & XCVR_TSM_END_OF_SEQ_END_OF_TX_WU_MASK)
529 				>> XCVR_TSM_END_OF_SEQ_END_OF_TX_WU_SHIFT;
530 
531 	/* IRQ config, clear pending interrupts */
532 	irq_disable(LL_RADIO_IRQn_2nd_lvl);
533 	GENFSK->IRQ_CTRL = 0xffffffff;
534 	GENFSK->IRQ_CTRL = GENFSK_IRQ_CTRL_GENERIC_FSK_IRQ_EN(1) |
535 			   GENFSK_IRQ_CTRL_RX_WATERMARK_IRQ_EN(1) |
536 			   GENFSK_IRQ_CTRL_TX_IRQ_EN(1) |
537 			   GENFSK_IRQ_CTRL_T2_IRQ_EN(1) |
538 			   GENFSK_IRQ_CTRL_WAKE_IRQ_EN(1);
539 
540 	/* Disable Rx recycle */
541 	GENFSK->IRQ_CTRL |= GENFSK_IRQ_CTRL_CRC_IGNORE(1);
542 	GENFSK->WHITEN_SZ_THR |= GENFSK_WHITEN_SZ_THR_REC_BAD_PKT(1);
543 
544 	/* Turn radio on to measure ISR latency */
545 	if (radio_is_off()) {
546 		dsm_ref = 0;
547 		radio_wake();
548 		while (radio_is_off()) {
549 		}
550 	} else {
551 		dsm_ref = 1;
552 	}
553 
554 	get_isr_latency();
555 
556 	/* Turn radio off */
557 	radio_sleep();
558 }
559 
radio_reset(void)560 void radio_reset(void)
561 {
562 	irq_disable(LL_RADIO_IRQn_2nd_lvl);
563 	/* Vega radio is never disabled therefore doesn't require resetting */
564 }
565 
radio_phy_set(uint8_t phy,uint8_t flags)566 void radio_phy_set(uint8_t phy, uint8_t flags)
567 {
568 	int err = 0;
569 	ARG_UNUSED(flags);
570 
571 	/* This function sets one of two modes:
572 	 * - BLE 1 Mbps
573 	 * - BLE 2 Mbps
574 	 * Coded BLE is not supported by VEGA
575 	 */
576 	switch (phy) {
577 	case BIT(0):
578 	default:
579 		if (phy_mode == DR_1MBPS) {
580 			break;
581 		}
582 
583 		err = XCVR_ChangeMode(GFSK_BT_0p5_h_0p5, DR_1MBPS);
584 		if (err) {
585 			LOG_ERR("Failed to change PHY to 1 Mbps");
586 			BT_ASSERT(0);
587 		}
588 
589 		phy_mode = GENFSK->BITRATE = DR_1MBPS;
590 		bits_per_usec = 1;
591 		phy_aa_ovhd = AA_OVHD_1MBPS;
592 
593 		break;
594 
595 	case BIT(1):
596 		if (phy_mode == DR_2MBPS) {
597 			break;
598 		}
599 
600 		err = XCVR_ChangeMode(GFSK_BT_0p5_h_0p5, DR_2MBPS);
601 		if (err) {
602 			LOG_ERR("Failed to change PHY to 2 Mbps");
603 			BT_ASSERT(0);
604 		}
605 
606 		phy_mode = GENFSK->BITRATE = DR_2MBPS;
607 		bits_per_usec = 2;
608 		phy_aa_ovhd = AA_OVHD_2MBPS;
609 
610 		break;
611 	}
612 }
613 
radio_tx_power_set(uint32_t power)614 void radio_tx_power_set(uint32_t power)
615 {
616 	ARG_UNUSED(power);
617 
618 	/* tx_power_level should only have the values 1, 2, 4, 6, ... , 62.
619 	 * Any value odd value (1, 3, ...) is not permitted and will result in
620 	 * undefined behavior.
621 	 * Those value have an associated db level that was not found in the
622 	 * documentation.
623 	 * Because of these inconsistencies for the moment this
624 	 * function sets the power level to a known value.
625 	 */
626 	uint32_t tx_power_level = 62;
627 
628 	GENFSK->TX_POWER = GENFSK_TX_POWER_TX_POWER(tx_power_level);
629 }
630 
radio_tx_power_max_set(void)631 void radio_tx_power_max_set(void)
632 {
633 	printk("%s\n", __func__);
634 }
635 
radio_freq_chan_set(uint32_t chan)636 void radio_freq_chan_set(uint32_t chan)
637 {
638 	/*
639 	 * The channel number for vega radio is computed
640 	 * as 2360 + ch_num [in MHz]
641 	 * The LLL expects the channel number to be computed as 2400 + ch_num.
642 	 * Therefore a compensation of 40 MHz has been provided.
643 	 */
644 	GENFSK->CHANNEL_NUM = GENFSK_CHANNEL_NUM_CHANNEL_NUM(40 + chan);
645 }
646 
647 #define GENFSK_BLE_WHITEN_START			1	/* after H0 */
648 #define GENFSK_BLE_WHITEN_END			1	/* at the end of CRC */
649 #define GENFSK_BLE_WHITEN_POLY_TYPE		0	/* Galois poly type */
650 #define GENFSK_BLE_WHITEN_SIZE			7	/* poly order */
651 #define GENFSK_BLE_WHITEN_POLY			0x04
652 
radio_whiten_iv_set(uint32_t iv)653 void radio_whiten_iv_set(uint32_t iv)
654 {
655 	GENFSK->WHITEN_CFG &= ~(GENFSK_WHITEN_CFG_WHITEN_START_MASK |
656 				GENFSK_WHITEN_CFG_WHITEN_END_MASK |
657 				GENFSK_WHITEN_CFG_WHITEN_B4_CRC_MASK |
658 				GENFSK_WHITEN_CFG_WHITEN_POLY_TYPE_MASK |
659 				GENFSK_WHITEN_CFG_WHITEN_REF_IN_MASK |
660 				GENFSK_WHITEN_CFG_WHITEN_PAYLOAD_REINIT_MASK |
661 				GENFSK_WHITEN_CFG_WHITEN_SIZE_MASK |
662 				GENFSK_WHITEN_CFG_MANCHESTER_EN_MASK |
663 				GENFSK_WHITEN_CFG_MANCHESTER_INV_MASK |
664 				GENFSK_WHITEN_CFG_MANCHESTER_START_MASK |
665 				GENFSK_WHITEN_CFG_WHITEN_INIT_MASK);
666 
667 	GENFSK->WHITEN_CFG |=
668 	    GENFSK_WHITEN_CFG_WHITEN_START(GENFSK_BLE_WHITEN_START) |
669 	    GENFSK_WHITEN_CFG_WHITEN_END(GENFSK_BLE_WHITEN_END) |
670 	    GENFSK_WHITEN_CFG_WHITEN_B4_CRC(0) |
671 	    GENFSK_WHITEN_CFG_WHITEN_POLY_TYPE(GENFSK_BLE_WHITEN_POLY_TYPE) |
672 	    GENFSK_WHITEN_CFG_WHITEN_REF_IN(0) |
673 	    GENFSK_WHITEN_CFG_WHITEN_PAYLOAD_REINIT(0) |
674 	    GENFSK_WHITEN_CFG_WHITEN_SIZE(GENFSK_BLE_WHITEN_SIZE) |
675 	    GENFSK_WHITEN_CFG_MANCHESTER_EN(0) |
676 	    GENFSK_WHITEN_CFG_MANCHESTER_INV(0) |
677 	    GENFSK_WHITEN_CFG_MANCHESTER_START(0) |
678 	    GENFSK_WHITEN_CFG_WHITEN_INIT(iv | 0x40);
679 
680 	GENFSK->WHITEN_POLY =
681 		GENFSK_WHITEN_POLY_WHITEN_POLY(GENFSK_BLE_WHITEN_POLY);
682 
683 	GENFSK->WHITEN_SZ_THR &= ~GENFSK_WHITEN_SZ_THR_WHITEN_SZ_THR_MASK;
684 	GENFSK->WHITEN_SZ_THR |= GENFSK_WHITEN_SZ_THR_WHITEN_SZ_THR(0);
685 }
686 
radio_aa_set(const uint8_t * aa)687 void radio_aa_set(const uint8_t *aa)
688 {
689 	/* Configure Access Address detection using NETWORK ADDRESS 0 */
690 	GENFSK->NTW_ADR_0 = *((uint32_t *)aa);
691 	GENFSK->NTW_ADR_CTRL &= ~(GENFSK_NTW_ADR_CTRL_NTW_ADR0_SZ_MASK |
692 				  GENFSK_NTW_ADR_CTRL_NTW_ADR_THR0_MASK);
693 	GENFSK->NTW_ADR_CTRL |= GENFSK_NTW_ADR_CTRL_NTW_ADR0_SZ(3) |
694 				GENFSK_NTW_ADR_CTRL_NTW_ADR_THR0(0);
695 
696 	GENFSK->NTW_ADR_CTRL |= (uint32_t) ((1 << 0) <<
697 			GENFSK_NTW_ADR_CTRL_NTW_ADR_EN_SHIFT);
698 
699 	/*
700 	 * The Access Address must be written in the packet buffer
701 	 * in front of the PDU
702 	 */
703 	GENFSK->PACKET_BUFFER[0] = (aa[1] << 8) + aa[0];
704 	GENFSK->PACKET_BUFFER[1] = (aa[3] << 8) + aa[2];
705 }
706 
707 #define GENFSK_BLE_CRC_SZ	3 /* 3 bytes */
708 #define GENFSK_BLE_PREAMBLE_SZ	0 /* 1 byte of preamble, depends on PHY type */
709 #define GENFSK_BLE_LEN_BIT_ORD	0 /* LSB */
710 #define GENFSK_BLE_SYNC_ADDR_SZ	3 /* 4 bytes, Access Address */
711 #define GENFSK_BLE_LEN_ADJ_SZ	GENFSK_BLE_CRC_SZ /* adjust length with CRC
712 						   * size
713 						   */
714 #define GENFSK_BLE_H0_SZ	8 /* 8 bits */
715 
radio_pkt_configure(uint8_t bits_len,uint8_t max_len,uint8_t flags)716 void radio_pkt_configure(uint8_t bits_len, uint8_t max_len, uint8_t flags)
717 {
718 	ARG_UNUSED(flags);
719 
720 	payload_max_size = max_len;
721 
722 	GENFSK->XCVR_CFG &= ~GENFSK_XCVR_CFG_PREAMBLE_SZ_MASK;
723 	GENFSK->XCVR_CFG |=
724 		GENFSK_XCVR_CFG_PREAMBLE_SZ(GENFSK_BLE_PREAMBLE_SZ);
725 
726 	GENFSK->PACKET_CFG &= ~(GENFSK_PACKET_CFG_LENGTH_SZ_MASK |
727 			GENFSK_PACKET_CFG_LENGTH_BIT_ORD_MASK |
728 			GENFSK_PACKET_CFG_SYNC_ADDR_SZ_MASK |
729 			GENFSK_PACKET_CFG_LENGTH_ADJ_MASK |
730 			GENFSK_PACKET_CFG_H0_SZ_MASK |
731 			GENFSK_PACKET_CFG_H1_SZ_MASK);
732 
733 	GENFSK->PACKET_CFG |= GENFSK_PACKET_CFG_LENGTH_SZ(bits_len) |
734 		GENFSK_PACKET_CFG_LENGTH_BIT_ORD(GENFSK_BLE_LEN_BIT_ORD) |
735 		GENFSK_PACKET_CFG_SYNC_ADDR_SZ(GENFSK_BLE_SYNC_ADDR_SZ) |
736 		GENFSK_PACKET_CFG_LENGTH_ADJ(GENFSK_BLE_LEN_ADJ_SZ) |
737 		GENFSK_PACKET_CFG_H0_SZ(GENFSK_BLE_H0_SZ) |
738 		GENFSK_PACKET_CFG_H1_SZ((8 - bits_len));
739 
740 	GENFSK->H0_CFG &= ~(GENFSK_H0_CFG_H0_MASK_MASK |
741 			    GENFSK_H0_CFG_H0_MATCH_MASK);
742 	GENFSK->H0_CFG |= GENFSK_H0_CFG_H0_MASK(0) |
743 			  GENFSK_H0_CFG_H0_MATCH(0);
744 
745 	GENFSK->H1_CFG &= ~(GENFSK_H1_CFG_H1_MASK_MASK |
746 			    GENFSK_H1_CFG_H1_MATCH_MASK);
747 	GENFSK->H1_CFG |= GENFSK_H1_CFG_H1_MASK(0) |
748 			  GENFSK_H1_CFG_H1_MATCH(0);
749 
750 	/* set Rx watermark to AA + PDU header */
751 	GENFSK->RX_WATERMARK = GENFSK_RX_WATERMARK_RX_WATERMARK(RX_WTMRK);
752 }
753 
radio_pkt_rx_set(void * rx_packet)754 void radio_pkt_rx_set(void *rx_packet)
755 {
756 	rx_pkt_ptr = rx_packet;
757 }
758 
radio_pkt_tx_set(void * tx_packet)759 void radio_pkt_tx_set(void *tx_packet)
760 {
761 	/*
762 	 * The GENERIC_FSK software must program the TX buffer
763 	 * before commanding a TX operation, and must not access the RAM during
764 	 * the transmission.
765 	 */
766 	uint16_t *pkt = tx_packet;
767 	uint32_t cnt = 0, pkt_len = (((uint8_t *)tx_packet)[1] + 1) / 2 + 1;
768 	volatile uint16_t *pkt_buffer = &GENFSK->PACKET_BUFFER[PB_TX_PDU];
769 
770 	for (; cnt < pkt_len; cnt++) {
771 		pkt_buffer[cnt] = pkt[cnt];
772 	}
773 }
774 
radio_tx_ready_delay_get(uint8_t phy,uint8_t flags)775 uint32_t radio_tx_ready_delay_get(uint8_t phy, uint8_t flags)
776 {
777 	return tx_wu;
778 }
779 
radio_tx_chain_delay_get(uint8_t phy,uint8_t flags)780 uint32_t radio_tx_chain_delay_get(uint8_t phy, uint8_t flags)
781 {
782 	return 0;
783 }
784 
radio_rx_ready_delay_get(uint8_t phy,uint8_t flags)785 uint32_t radio_rx_ready_delay_get(uint8_t phy, uint8_t flags)
786 {
787 	return rx_wu;
788 }
789 
radio_rx_chain_delay_get(uint8_t phy,uint8_t flags)790 uint32_t radio_rx_chain_delay_get(uint8_t phy, uint8_t flags)
791 {
792 	/* RX_WTMRK = AA + PDU header, but AA time is already accounted for */
793 	/* PDU header (assume 2 bytes) => 16us, depends on PHY type */
794 	/* 2 * RX_OVHD = RX_WATERMARK_IRQ time - TIMESTAMP - isr_latency */
795 	/* The rest is Rx margin that for now isn't well defined */
796 	return BYTES_TO_USEC(2, bits_per_usec) + 2 * RX_OVHD +
797 					RX_MARGIN + isr_latency +
798 					RX_OVHD;
799 }
800 
radio_rx_enable(void)801 void radio_rx_enable(void)
802 {
803 	/* Wait for idle state */
804 	while (GENFSK->XCVR_STS & RADIO_ACTIVE_MASK) {
805 	}
806 
807 	/* 0b0101..RX Start Now */
808 	GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0x5);
809 }
810 
radio_tx_enable(void)811 void radio_tx_enable(void)
812 {
813 	/* Wait for idle state */
814 	while (GENFSK->XCVR_STS & RADIO_ACTIVE_MASK) {
815 	}
816 
817 	/* 0b0001..TX Start Now */
818 	GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0x1);
819 }
820 
radio_disable(void)821 void radio_disable(void)
822 {
823 	/* Disable both comparators */
824 	GENFSK->T1_CMP = 0;
825 	GENFSK->T2_CMP = 0;
826 
827 	/*
828 	 * 0b1011..Abort All - Cancels all pending events and abort any
829 	 * sequence-in-progress
830 	 */
831 	GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0xb);
832 
833 	/* Wait for idle state */
834 	while (GENFSK->XCVR_STS & RADIO_ACTIVE_MASK) {
835 	}
836 
837 	/* Clear pending interrupts */
838 	GENFSK->IRQ_CTRL &= 0xffffffff;
839 	EVENT_UNIT->INTPTPENDCLEAR = (uint32_t)(1U << LL_RADIO_IRQn);
840 
841 	next_radio_cmd = 0;
842 	radio_trx = 0;
843 
844 	/* generate T2 interrupt to get into isr_radio() */
845 	uint32_t tmr = GENFSK->EVENT_TMR + RADIO_DISABLE_TMR;
846 
847 	GENFSK->T2_CMP = GENFSK_T2_CMP_T2_CMP(tmr) | GENFSK_T2_CMP_T2_CMP_EN(1);
848 }
849 
radio_status_reset(void)850 void radio_status_reset(void)
851 {
852 	radio_trx = 0;
853 }
854 
radio_is_ready(void)855 uint32_t radio_is_ready(void)
856 {
857 	/* Always false. LLL expects the radio not to be in idle/Tx/Rx state */
858 	return 0;
859 }
860 
radio_is_done(void)861 uint32_t radio_is_done(void)
862 {
863 	return radio_trx;
864 }
865 
radio_has_disabled(void)866 uint32_t radio_has_disabled(void)
867 {
868 	/* Not used */
869 	return 0;
870 }
871 
radio_is_idle(void)872 uint32_t radio_is_idle(void)
873 {
874 	/* Vega radio is never disabled */
875 	return 1;
876 }
877 
878 #define GENFSK_BLE_CRC_START_BYTE	4 /* After Access Address */
879 #define GENFSK_BLE_CRC_BYTE_ORD		0 /* LSB */
880 
radio_crc_configure(uint32_t polynomial,uint32_t iv)881 void radio_crc_configure(uint32_t polynomial, uint32_t iv)
882 {
883 	/* printk("%s poly: %08x, iv: %08x\n", __func__, polynomial, iv); */
884 
885 	GENFSK->CRC_CFG &= ~(GENFSK_CRC_CFG_CRC_SZ_MASK |
886 			     GENFSK_CRC_CFG_CRC_START_BYTE_MASK |
887 			     GENFSK_CRC_CFG_CRC_REF_IN_MASK |
888 			     GENFSK_CRC_CFG_CRC_REF_OUT_MASK |
889 			     GENFSK_CRC_CFG_CRC_BYTE_ORD_MASK);
890 	GENFSK->CRC_CFG |= GENFSK_CRC_CFG_CRC_SZ(GENFSK_BLE_CRC_SZ) |
891 		GENFSK_CRC_CFG_CRC_START_BYTE(GENFSK_BLE_CRC_START_BYTE) |
892 		GENFSK_CRC_CFG_CRC_REF_IN(0) |
893 		GENFSK_CRC_CFG_CRC_REF_OUT(0) |
894 		GENFSK_CRC_CFG_CRC_BYTE_ORD(GENFSK_BLE_CRC_BYTE_ORD);
895 
896 	GENFSK->CRC_INIT = (iv << ((4U - GENFSK_BLE_CRC_SZ) << 3));
897 	GENFSK->CRC_POLY = (polynomial << ((4U - GENFSK_BLE_CRC_SZ) << 3));
898 	GENFSK->CRC_XOR_OUT = 0;
899 
900 	/*
901 	 * Enable CRC in hardware; this is already done at startup but we do it
902 	 * here anyways just to be sure.
903 	 */
904 	GENFSK->XCVR_CFG &= ~GENFSK_XCVR_CFG_SW_CRC_EN_MASK;
905 }
906 
radio_crc_is_valid(void)907 uint32_t radio_crc_is_valid(void)
908 {
909 	if (force_bad_crc) {
910 		return 0;
911 	}
912 
913 	uint32_t radio_crc = (GENFSK->XCVR_STS & GENFSK_XCVR_STS_CRC_VALID_MASK) >>
914 						GENFSK_XCVR_STS_CRC_VALID_SHIFT;
915 	return radio_crc;
916 }
917 
radio_pkt_empty_get(void)918 void *radio_pkt_empty_get(void)
919 {
920 	return _pkt_empty;
921 }
922 
radio_pkt_scratch_get(void)923 void *radio_pkt_scratch_get(void)
924 {
925 	return _pkt_scratch;
926 }
927 
radio_switch_complete_and_rx(uint8_t phy_rx)928 void radio_switch_complete_and_rx(uint8_t phy_rx)
929 {
930 	/*  0b0110..RX Start @ T1 Timer Compare Match (EVENT_TMR = T1_CMP) */
931 	next_radio_cmd = GENFSK_XCVR_CTRL_SEQCMD(0x6);
932 
933 	/* the margin is used to account for any overhead in radio switching */
934 	next_wu = rx_wu + RX_MARGIN;
935 }
936 
radio_switch_complete_and_tx(uint8_t phy_rx,uint8_t flags_rx,uint8_t phy_tx,uint8_t flags_tx)937 void radio_switch_complete_and_tx(uint8_t phy_rx, uint8_t flags_rx, uint8_t phy_tx,
938 				  uint8_t flags_tx)
939 {
940 	/*  0b0010..TX Start @ T1 Timer Compare Match (EVENT_TMR = T1_CMP) */
941 	next_radio_cmd = GENFSK_XCVR_CTRL_SEQCMD(0x2);
942 
943 	/* the margin is used to account for any overhead in radio switching */
944 	next_wu = tx_wu + TX_MARGIN;
945 }
946 
radio_switch_complete_and_disable(void)947 void radio_switch_complete_and_disable(void)
948 {
949 	next_radio_cmd = 0;
950 }
951 
radio_rssi_measure(void)952 void radio_rssi_measure(void)
953 {
954 	rssi = 0;
955 }
956 
radio_rssi_get(void)957 uint32_t radio_rssi_get(void)
958 {
959 	return (uint32_t)-rssi;
960 }
961 
radio_rssi_status_reset(void)962 void radio_rssi_status_reset(void)
963 {
964 }
965 
radio_rssi_is_ready(void)966 uint32_t radio_rssi_is_ready(void)
967 {
968 	return (rssi != 0);
969 }
970 
radio_filter_configure(uint8_t bitmask_enable,uint8_t bitmask_addr_type,uint8_t * bdaddr)971 void radio_filter_configure(uint8_t bitmask_enable, uint8_t bitmask_addr_type,
972 			    uint8_t *bdaddr)
973 {
974 	/* printk("%s\n", __func__); */
975 }
976 
radio_filter_disable(void)977 void radio_filter_disable(void)
978 {
979 	/* Nothing to do here */
980 }
981 
radio_filter_status_reset(void)982 void radio_filter_status_reset(void)
983 {
984 	/* printk("%s\n", __func__); */
985 }
986 
radio_filter_has_match(void)987 uint32_t radio_filter_has_match(void)
988 {
989 	/* printk("%s\n", __func__); */
990 	return 0;
991 }
992 
radio_filter_match_get(void)993 uint32_t radio_filter_match_get(void)
994 {
995 	/* printk("%s\n", __func__); */
996 	return 0;
997 }
998 
radio_bc_configure(uint32_t n)999 void radio_bc_configure(uint32_t n)
1000 {
1001 	printk("%s\n", __func__);
1002 }
1003 
radio_bc_status_reset(void)1004 void radio_bc_status_reset(void)
1005 {
1006 	printk("%s\n", __func__);
1007 }
1008 
radio_bc_has_match(void)1009 uint32_t radio_bc_has_match(void)
1010 {
1011 	printk("%s\n", __func__);
1012 	return 0;
1013 }
1014 
radio_tmr_status_reset(void)1015 void radio_tmr_status_reset(void)
1016 {
1017 	tmr_aa_save = 0;
1018 	tmr_end_save = 0;
1019 }
1020 
radio_tmr_tifs_set(uint32_t tifs)1021 void radio_tmr_tifs_set(uint32_t tifs)
1022 {
1023 	tmr_tifs = tifs;
1024 }
1025 
1026 /* Start the radio after ticks_start (ticks) + remainder (us) time */
radio_tmr_start_hlp(uint8_t trx,uint32_t ticks_start,uint32_t remainder)1027 static uint32_t radio_tmr_start_hlp(uint8_t trx, uint32_t ticks_start, uint32_t remainder)
1028 {
1029 	uint32_t radio_start_now_cmd = 0;
1030 
1031 	/* Disable both comparators */
1032 	GENFSK->T1_CMP = 0;
1033 	GENFSK->T2_CMP = 0;
1034 
1035 	/* Save it for later */
1036 	rtc_start = ticks_start;
1037 
1038 	/* Convert ticks to us and use just EVENT_TMR */
1039 	rtc_diff_start_us = HAL_TICKER_TICKS_TO_US(rtc_start - cntr_cnt_get());
1040 
1041 	skip_hcto = 0;
1042 	if (rtc_diff_start_us > GENFSK_T1_CMP_T1_CMP_MASK) {
1043 		/* ticks_start already passed. Don't start the radio */
1044 		rtc_diff_start_us = 0;
1045 
1046 		/* Ignore time out as well */
1047 		skip_hcto = 1;
1048 		return remainder;
1049 	}
1050 	remainder += rtc_diff_start_us;
1051 
1052 	if (trx) {
1053 		if (remainder <= MIN_CMD_TIME) {
1054 			/* 0b0001..TX Start Now */
1055 			radio_start_now_cmd = GENFSK_XCVR_CTRL_SEQCMD(0x1);
1056 			remainder = 0;
1057 		} else {
1058 			/*
1059 			 * 0b0010..TX Start @ T1 Timer Compare Match
1060 			 *         (EVENT_TMR = T1_CMP)
1061 			 */
1062 			GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0x2);
1063 			GENFSK->T1_CMP = GENFSK_T1_CMP_T1_CMP(remainder);
1064 		}
1065 		tmr_ready = remainder + tx_wu;
1066 	} else {
1067 		if (remainder <= MIN_CMD_TIME) {
1068 			/* 0b0101..RX Start Now */
1069 			radio_start_now_cmd = GENFSK_XCVR_CTRL_SEQCMD(0x5);
1070 			remainder = 0;
1071 		} else {
1072 			/*
1073 			 * 0b0110..RX Start @ T1 Timer Compare Match
1074 			 *         (EVENT_TMR = T1_CMP)
1075 			 */
1076 			GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0x6);
1077 			GENFSK->T1_CMP = GENFSK_T1_CMP_T1_CMP(remainder);
1078 		}
1079 		tmr_ready = remainder + rx_wu;
1080 	}
1081 
1082 	/*
1083 	 * reset EVENT_TMR should be done after ticks_start.
1084 	 * We converted ticks to us, so we reset it now.
1085 	 * All tmr_* times are relative to EVENT_TMR reset.
1086 	 * rtc_diff_start_us is used to adjust them
1087 	 */
1088 	GENFSK->EVENT_TMR = GENFSK_EVENT_TMR_EVENT_TMR_LD(1);
1089 
1090 	if (radio_start_now_cmd) {
1091 		/* trigger Rx/Tx Start Now */
1092 		GENFSK->XCVR_CTRL = radio_start_now_cmd;
1093 	} else {
1094 		/* enable T1_CMP to trigger the SEQCMD */
1095 		GENFSK->T1_CMP |= GENFSK_T1_CMP_T1_CMP_EN(1);
1096 	}
1097 
1098 	return remainder;
1099 }
1100 
radio_tmr_start(uint8_t trx,uint32_t ticks_start,uint32_t remainder)1101 uint32_t radio_tmr_start(uint8_t trx, uint32_t ticks_start, uint32_t remainder)
1102 {
1103 	if ((!(remainder / 1000000UL)) || (remainder & 0x80000000)) {
1104 		ticks_start--;
1105 		remainder += 30517578UL;
1106 	}
1107 	remainder /= 1000000UL;
1108 
1109 	if (radio_is_off()) {
1110 		delayed_radio_start = 1;
1111 		delayed_trx = trx;
1112 		delayed_ticks_start = ticks_start;
1113 		delayed_remainder = remainder;
1114 		return remainder;
1115 	}
1116 
1117 	delayed_radio_start = 0;
1118 	return radio_tmr_start_hlp(trx, ticks_start, remainder);
1119 }
1120 
radio_tmr_start_tick(uint8_t trx,uint32_t tick)1121 uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t tick)
1122 {
1123 	/* Setup compare event with min. 1 us offset */
1124 	uint32_t remainder_us = 1;
1125 
1126 	return radio_tmr_start_hlp(trx, tick, remainder_us);
1127 }
1128 
radio_tmr_start_us(uint8_t trx,uint32_t us)1129 void radio_tmr_start_us(uint8_t trx, uint32_t us)
1130 {
1131 	printk("%s\n", __func__);
1132 }
1133 
radio_tmr_start_now(uint8_t trx)1134 uint32_t radio_tmr_start_now(uint8_t trx)
1135 {
1136 	printk("%s\n", __func__);
1137 	return 0;
1138 }
1139 
radio_tmr_start_get(void)1140 uint32_t radio_tmr_start_get(void)
1141 {
1142 	return rtc_start;
1143 }
1144 
radio_tmr_stop(void)1145 void radio_tmr_stop(void)
1146 {
1147 }
1148 
radio_tmr_hcto_configure_hlp(uint32_t hcto)1149 static void radio_tmr_hcto_configure_hlp(uint32_t hcto)
1150 {
1151 	if (skip_hcto) {
1152 		skip_hcto = 0;
1153 		return;
1154 	}
1155 
1156 	/* 0b1001..RX Stop @ T2 Timer Compare Match (EVENT_TMR = T2_CMP) */
1157 	GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0x9);
1158 	GENFSK->T2_CMP = GENFSK_T2_CMP_T2_CMP(hcto) |
1159 			 GENFSK_T2_CMP_T2_CMP_EN(1);
1160 
1161 }
1162 
1163 /* Header completion time out */
radio_tmr_hcto_configure(uint32_t hcto)1164 void radio_tmr_hcto_configure(uint32_t hcto)
1165 {
1166 	if (delayed_radio_start) {
1167 		delayed_radio_stop = 1;
1168 		delayed_hcto = hcto;
1169 		return;
1170 	}
1171 
1172 	delayed_radio_stop = 0;
1173 	radio_tmr_hcto_configure_hlp(hcto);
1174 }
1175 
radio_tmr_aa_capture(void)1176 void radio_tmr_aa_capture(void)
1177 {
1178 	tmr_aa_save = 1;
1179 }
1180 
radio_tmr_aa_get(void)1181 uint32_t radio_tmr_aa_get(void)
1182 {
1183 	return tmr_aa - rtc_diff_start_us;
1184 }
1185 
1186 static uint32_t radio_tmr_aa;
1187 
radio_tmr_aa_save(uint32_t aa)1188 void radio_tmr_aa_save(uint32_t aa)
1189 {
1190 	radio_tmr_aa = aa;
1191 }
1192 
radio_tmr_aa_restore(void)1193 uint32_t radio_tmr_aa_restore(void)
1194 {
1195 	return radio_tmr_aa;
1196 }
1197 
radio_tmr_ready_get(void)1198 uint32_t radio_tmr_ready_get(void)
1199 {
1200 	return tmr_ready - rtc_diff_start_us;
1201 }
1202 
radio_tmr_end_capture(void)1203 void radio_tmr_end_capture(void)
1204 {
1205 	tmr_end_save = 1;
1206 }
1207 
radio_tmr_end_get(void)1208 uint32_t radio_tmr_end_get(void)
1209 {
1210 	return tmr_end - rtc_diff_start_us;
1211 }
1212 
radio_tmr_tifs_base_get(void)1213 uint32_t radio_tmr_tifs_base_get(void)
1214 {
1215 	return radio_tmr_end_get() + rtc_diff_start_us;
1216 }
1217 
radio_tmr_sample(void)1218 void radio_tmr_sample(void)
1219 {
1220 	printk("%s\n", __func__);
1221 }
1222 
radio_tmr_sample_get(void)1223 uint32_t radio_tmr_sample_get(void)
1224 {
1225 	printk("%s\n", __func__);
1226 	return 0;
1227 }
1228 
radio_ccm_rx_pkt_set_ut(struct ccm * ccm,uint8_t phy,void * pkt)1229 void *radio_ccm_rx_pkt_set_ut(struct ccm *ccm, uint8_t phy, void *pkt)
1230 {
1231 	/* Saved by LL as MSO to LSO in the ccm->key
1232 	 * SK (LSO to MSO)
1233 	 * :0x66:0xC6:0xC2:0x27:0x8E:0x3B:0x8E:0x05
1234 	 * :0x3E:0x7E:0xA3:0x26:0x52:0x1B:0xAD:0x99
1235 	 */
1236 	uint8_t key_local[16] __aligned(4) = {
1237 		0x99, 0xad, 0x1b, 0x52, 0x26, 0xa3, 0x7e, 0x3e,
1238 		0x05, 0x8e, 0x3b, 0x8e, 0x27, 0xc2, 0xc6, 0x66
1239 	};
1240 	void *result;
1241 
1242 	/* ccm.key[16] is stored in MSO format, as retrieved from e function */
1243 	memcpy(ccm->key, key_local, sizeof(key_local));
1244 
1245 	/* Input std sample data, vol 6, part C, ch 1 */
1246 	_pkt_scratch[0] = 0x0f;
1247 	_pkt_scratch[1] = 0x05;
1248 	_pkt_scratch[2] = 0x9f; /* cleartext = 0x06*/
1249 	_pkt_scratch[3] = 0xcd;
1250 	_pkt_scratch[4] = 0xa7;
1251 	_pkt_scratch[5] = 0xf4;
1252 	_pkt_scratch[6] = 0x48;
1253 
1254 	/* IV std sample data, vol 6, part C, ch 1, stored in LL in LSO format
1255 	 * IV (LSO to MSO)      :0x24:0xAB:0xDC:0xBA:0xBE:0xBA:0xAF:0xDE
1256 	 */
1257 	ccm->iv[0] = 0x24;
1258 	ccm->iv[1] = 0xAB;
1259 	ccm->iv[2] = 0xDC;
1260 	ccm->iv[3] = 0xBA;
1261 	ccm->iv[4] = 0xBE;
1262 	ccm->iv[5] = 0xBA;
1263 	ccm->iv[6] = 0xAF;
1264 	ccm->iv[7] = 0xDE;
1265 
1266 	result = radio_ccm_rx_pkt_set(ccm, phy, pkt);
1267 	radio_ccm_is_done();
1268 
1269 	if (ctx_ccm.auth_mic_valid == 1 && ((uint8_t *)pkt)[2] == 0x06) {
1270 		LOG_INF("Passed decrypt\n");
1271 	} else {
1272 		LOG_INF("Failed decrypt\n");
1273 	}
1274 
1275 	return result;
1276 }
1277 
radio_ccm_rx_pkt_set(struct ccm * ccm,uint8_t phy,void * pkt)1278 void *radio_ccm_rx_pkt_set(struct ccm *ccm, uint8_t phy, void *pkt)
1279 {
1280 	uint8_t key_local[16] __aligned(4);
1281 	status_t status;
1282 	cau3_handle_t handle = {
1283 			.keySlot = kCAU3_KeySlot2,
1284 			.taskDone = kCAU3_TaskDonePoll
1285 	};
1286 	ARG_UNUSED(phy);
1287 
1288 	/* ccm.key[16] is stored in MSO format, as retrieved from e function */
1289 	memcpy(key_local, ccm->key, sizeof(key_local));
1290 	ctx_ccm.auth_mic_valid = 0;
1291 	ctx_ccm.empty_pdu_rxed = 0;
1292 	ctx_ccm.rx_pkt_in = (struct pdu_data *)_pkt_scratch;
1293 	ctx_ccm.rx_pkt_out = (struct pdu_data *)pkt;
1294 	ctx_ccm.nonce.counter = ccm->counter;	/* LSO to MSO, counter is LE */
1295 	/* The directionBit set to 1 for Data Physical Chan PDUs sent by
1296 	 * the central and set to 0 for Data Physical Chan PDUs sent by the
1297 	 * peripheral
1298 	 */
1299 	ctx_ccm.nonce.bytes[4] |= ccm->direction << 7;
1300 	memcpy(&ctx_ccm.nonce.bytes[5], ccm->iv, 8); /* LSO to MSO */
1301 
1302 	/* Loads the key into CAU3's DMEM and expands the AES key schedule. */
1303 	status = CAU3_AES_SetKey(CAU3, &handle, key_local, 16);
1304 	if (status != kStatus_Success) {
1305 		LOG_ERR("CAUv3 AES key set failed %d", status);
1306 		return NULL;
1307 	}
1308 
1309 	return _pkt_scratch;
1310 }
1311 
radio_ccm_tx_pkt_set_ut(struct ccm * ccm,void * pkt)1312 void *radio_ccm_tx_pkt_set_ut(struct ccm *ccm, void *pkt)
1313 {
1314 	/* Clear:
1315 	 * 06 1b 17 00 37 36 35 34 33 32 31 30 41 42 43
1316 	 * 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51
1317 	 */
1318 	uint8_t data_in[29] = {
1319 		0x06, 0x1b, 0x17, 0x00, 0x37, 0x36, 0x35, 0x34,
1320 		0x33, 0x32, 0x31, 0x30, 0x41, 0x42, 0x43, 0x44,
1321 		0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
1322 		0x4d, 0x4e, 0x4f, 0x50, 0x51
1323 	};
1324 	/* LL_DATA2:
1325 	 * 06 1f f3 88 81 e7 bd 94 c9 c3 69 b9 a6 68 46
1326 	 * dd 47 86 aa 8c 39 ce 54 0d 0d ae 3a dc df 89 b9 60 88
1327 	 */
1328 	uint8_t data_ref_out[33] = {
1329 		0x06, 0x1f, 0xf3, 0x88, 0x81, 0xe7, 0xbd, 0x94,
1330 		0xc9, 0xc3, 0x69, 0xb9, 0xa6, 0x68, 0x46, 0xdd,
1331 		0x47, 0x86, 0xaa, 0x8c, 0x39, 0xce, 0x54, 0x0d,
1332 		0x0d, 0xae, 0x3a, 0xdc, 0xdf,
1333 		0x89, 0xb9, 0x60, 0x88
1334 	};
1335 	/* Saved by LL as MSO to LSO in the ccm->key
1336 	 * SK (LSO to MSO)
1337 	 * :0x66:0xC6:0xC2:0x27:0x8E:0x3B:0x8E:0x05
1338 	 * :0x3E:0x7E:0xA3:0x26:0x52:0x1B:0xAD:0x99
1339 	 */
1340 	uint8_t key_local[16] __aligned(4) = {
1341 		0x99, 0xad, 0x1b, 0x52, 0x26, 0xa3, 0x7e, 0x3e,
1342 		0x05, 0x8e, 0x3b, 0x8e, 0x27, 0xc2, 0xc6, 0x66
1343 	};
1344 	void *result;
1345 
1346 	/* ccm.key[16] is stored in MSO format, as retrieved from e function */
1347 	memcpy(ccm->key, key_local, sizeof(key_local));
1348 	memcpy(pkt, data_in, sizeof(data_in));
1349 	/* IV std sample data, vol 6, part C, ch 1, stored in LL in LSO format
1350 	 * IV (LSO to MSO)      :0x24:0xAB:0xDC:0xBA:0xBE:0xBA:0xAF:0xDE
1351 	 */
1352 	ccm->iv[0] = 0x24;
1353 	ccm->iv[1] = 0xAB;
1354 	ccm->iv[2] = 0xDC;
1355 	ccm->iv[3] = 0xBA;
1356 	ccm->iv[4] = 0xBE;
1357 	ccm->iv[5] = 0xBA;
1358 	ccm->iv[6] = 0xAF;
1359 	ccm->iv[7] = 0xDE;
1360 	/* 4. Data packet2 (packet 1, S --> M) */
1361 	ccm->counter = 1;
1362 	ccm->direction = 0;
1363 
1364 	result = radio_ccm_tx_pkt_set(ccm, pkt);
1365 
1366 	if (memcmp(result, data_ref_out, sizeof(data_ref_out))) {
1367 		LOG_INF("Failed encrypt\n");
1368 	} else {
1369 		LOG_INF("Passed encrypt\n");
1370 	}
1371 
1372 	return result;
1373 }
1374 
radio_ccm_tx_pkt_set(struct ccm * ccm,void * pkt)1375 void *radio_ccm_tx_pkt_set(struct ccm *ccm, void *pkt)
1376 {
1377 	uint8_t key_local[16] __aligned(4);
1378 	uint8_t aad;
1379 	uint8_t *auth_mic;
1380 	status_t status;
1381 	cau3_handle_t handle = {
1382 			.keySlot = kCAU3_KeySlot2,
1383 			.taskDone = kCAU3_TaskDonePoll
1384 	};
1385 
1386 	/* Test for Empty PDU and bypass encryption */
1387 	if (((struct pdu_data *)pkt)->len == 0) {
1388 		return pkt;
1389 	}
1390 
1391 	/* ccm.key[16] is stored in MSO format, as retrieved from e function */
1392 	memcpy(key_local, ccm->key, sizeof(key_local));
1393 	ctx_ccm.nonce.counter = ccm->counter;	/* LSO to MSO, counter is LE */
1394 	/* The directionBit set to 1 for Data Physical Chan PDUs sent by
1395 	 * the central and set to 0 for Data Physical Chan PDUs sent by the
1396 	 * peripheral
1397 	 */
1398 	ctx_ccm.nonce.bytes[4] |= ccm->direction << 7;
1399 	memcpy(&ctx_ccm.nonce.bytes[5], ccm->iv, 8); /* LSO to MSO */
1400 
1401 	/* Loads the key into CAU3's DMEM and expands the AES key schedule. */
1402 	status = CAU3_AES_SetKey(CAU3, &handle, key_local, 16);
1403 	if (status != kStatus_Success) {
1404 		LOG_ERR("CAUv3 AES key set failed %d", status);
1405 		return NULL;
1406 	}
1407 
1408 	auth_mic = _pkt_scratch + 2 + ((struct pdu_data *)pkt)->len;
1409 	aad = *(uint8_t *)pkt & RADIO_AESCCM_HDR_MASK;
1410 
1411 	status = CAU3_AES_CCM_EncryptTag(CAU3, &handle,
1412 				 (uint8_t *)pkt + 2, ((struct pdu_data *)pkt)->len,
1413 				 _pkt_scratch + 2,
1414 				 ctx_ccm.nonce.bytes, 13,
1415 				 &aad, 1, auth_mic, CAU3_BLE_MIC_SIZE);
1416 	if (status != kStatus_Success) {
1417 		LOG_ERR("CAUv3 AES CCM decrypt failed %d", status);
1418 		return 0;
1419 	}
1420 
1421 	_pkt_scratch[0] = *(uint8_t *)pkt;
1422 	_pkt_scratch[1] = ((struct pdu_data *)pkt)->len + CAU3_BLE_MIC_SIZE;
1423 
1424 	return _pkt_scratch;
1425 }
1426 
radio_ccm_is_done(void)1427 uint32_t radio_ccm_is_done(void)
1428 {
1429 	status_t status;
1430 	uint8_t *auth_mic;
1431 	uint8_t aad;
1432 	cau3_handle_t handle = {
1433 			.keySlot = kCAU3_KeySlot2,
1434 			.taskDone = kCAU3_TaskDonePoll
1435 	};
1436 
1437 	if (ctx_ccm.rx_pkt_in->len > CAU3_BLE_MIC_SIZE) {
1438 		auth_mic = (uint8_t *)ctx_ccm.rx_pkt_in + 2 +
1439 				ctx_ccm.rx_pkt_in->len - CAU3_BLE_MIC_SIZE;
1440 		aad = *(uint8_t *)ctx_ccm.rx_pkt_in & RADIO_AESCCM_HDR_MASK;
1441 		status = CAU3_AES_CCM_DecryptTag(CAU3, &handle,
1442 				(uint8_t *)ctx_ccm.rx_pkt_in + 2,
1443 				(uint8_t *)ctx_ccm.rx_pkt_out + 2,
1444 				ctx_ccm.rx_pkt_in->len - CAU3_BLE_MIC_SIZE,
1445 				ctx_ccm.nonce.bytes, 13,
1446 				&aad, 1, auth_mic, CAU3_BLE_MIC_SIZE);
1447 		if (status != kStatus_Success) {
1448 			LOG_ERR("CAUv3 AES CCM decrypt failed %d", status);
1449 			return 0;
1450 		}
1451 
1452 		ctx_ccm.auth_mic_valid = handle.micPassed;
1453 		ctx_ccm.rx_pkt_out->len -= 4;
1454 
1455 	} else if (ctx_ccm.rx_pkt_in->len == 0) {
1456 		/* Just copy input into output */
1457 		*ctx_ccm.rx_pkt_out = *ctx_ccm.rx_pkt_in;
1458 		ctx_ccm.auth_mic_valid = 1;
1459 		ctx_ccm.empty_pdu_rxed = 1;
1460 	} else {
1461 		return 0;   /* length only allowed 0, not 1,2,3,4 */
1462 	}
1463 
1464 	return 1;
1465 }
1466 
radio_ccm_mic_is_valid(void)1467 uint32_t radio_ccm_mic_is_valid(void)
1468 {
1469 	return ctx_ccm.auth_mic_valid;
1470 }
1471 
radio_ccm_is_available(void)1472 uint32_t radio_ccm_is_available(void)
1473 {
1474 	return ctx_ccm.empty_pdu_rxed;
1475 }
1476 
1477 #if defined(CONFIG_BT_CTLR_PRIVACY)
radio_ar_configure(uint32_t nirk,void * irk)1478 void radio_ar_configure(uint32_t nirk, void *irk)
1479 {
1480 	status_t status;
1481 	uint8_t pirk[16];
1482 
1483 	/* Initialize CAUv3 RPA table */
1484 	status = CAU3_RPAtableInit(CAU3, kCAU3_TaskDoneEvent);
1485 	if (kStatus_Success != status) {
1486 		LOG_ERR("CAUv3 RPA table init failed");
1487 		return;
1488 	}
1489 
1490 	/* CAUv3 RPA table is limited to CONFIG_BT_CTLR_RL_SIZE entries */
1491 	if (nirk > CONFIG_BT_CTLR_RL_SIZE) {
1492 		LOG_WRN("Max CAUv3 RPA table size is %d", CONFIG_BT_CTLR_RL_SIZE);
1493 		nirk = CONFIG_BT_CTLR_RL_SIZE;
1494 	}
1495 
1496 	/* Insert RPA keys(IRK) in table */
1497 	for (int i = 0; i < nirk; i++) {
1498 		/* CAUv3 needs IRK in le format */
1499 		sys_memcpy_swap(pirk, (uint8_t *)irk + i * 16, 16);
1500 		status = CAU3_RPAtableInsertKey(CAU3, (uint32_t *)&pirk,
1501 						kCAU3_TaskDoneEvent);
1502 		if (kStatus_Success != status) {
1503 			LOG_ERR("CAUv3 RPA table insert failed");
1504 			return;
1505 		}
1506 	}
1507 
1508 	/* RPA Table was configured, it can be used for next Rx */
1509 	radio_ar_ctx.ar_enable = 1U;
1510 }
1511 
radio_ar_match_get(void)1512 uint32_t radio_ar_match_get(void)
1513 {
1514 	return radio_ar_ctx.irk_idx;
1515 }
1516 
radio_ar_status_reset(void)1517 void radio_ar_status_reset(void)
1518 {
1519 	radio_ar_ctx.ar_enable = 0U;
1520 	radio_ar_ctx.irk_idx = RPA_NO_IRK_MATCH;
1521 }
1522 
radio_ar_has_match(void)1523 uint32_t radio_ar_has_match(void)
1524 {
1525 	return (radio_ar_ctx.irk_idx != RPA_NO_IRK_MATCH);
1526 }
1527 #endif /* CONFIG_BT_CTLR_PRIVACY */
1528 
radio_sleep(void)1529 uint32_t radio_sleep(void)
1530 {
1531 
1532 	if (dsm_ref == 0) {
1533 		return -EALREADY;
1534 	}
1535 
1536 	uint32_t localref = --dsm_ref;
1537 #if (CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_HIGH_PRIO) && \
1538 	(CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
1539 	/* TODO:
1540 	 * These operations (decrement, check) should be atomic/critical section
1541 	 * since we turn radio on/off from different contexts/ISRs (LLL, radio).
1542 	 * It's fine for now as all the contexts have the same priority and
1543 	 * don't preempt each other.
1544 	 */
1545 #else
1546 #error "Missing atomic operation in radio_sleep()"
1547 #endif
1548 	if (localref == 0) {
1549 
1550 		uint32_t status = (RSIM->DSM_CONTROL & MAN_DSM_ON);
1551 
1552 		if (status) {
1553 			/* Already in sleep mode */
1554 			return 0;
1555 		}
1556 
1557 		/* Disable DSM_TIMER */
1558 		RSIM->DSM_CONTROL &= ~RSIM_DSM_CONTROL_DSM_TIMER_EN(1);
1559 
1560 		/* Get current DSM_TIMER value */
1561 		uint32_t dsm_timer = RSIM->DSM_TIMER;
1562 
1563 		/* Set Sleep time after DSM_ENTER_DELAY */
1564 		RSIM->MAN_SLEEP = RSIM_MAN_SLEEP_MAN_SLEEP_TIME(dsm_timer +
1565 				DSM_ENTER_DELAY_TICKS);
1566 
1567 		/* Set Wake time to max, we use DSM early exit */
1568 		RSIM->MAN_WAKE = RSIM_MAN_WAKE_MAN_WAKE_TIME(dsm_timer - 1);
1569 
1570 		/* MAN wakeup request enable */
1571 		RSIM->DSM_CONTROL |= RSIM_DSM_CONTROL_MAN_WAKEUP_REQUEST_EN(1);
1572 
1573 		/* Enable DSM, sending a sleep request */
1574 		GENFSK->DSM_CTRL |= GENFSK_DSM_CTRL_GEN_SLEEP_REQUEST(1);
1575 
1576 		/* Enable DSM_TIMER */
1577 		RSIM->DSM_CONTROL |= RSIM_DSM_CONTROL_DSM_TIMER_EN(1);
1578 	}
1579 
1580 	return 0;
1581 }
1582 
radio_wake(void)1583 uint32_t radio_wake(void)
1584 {
1585 	uint32_t localref = ++dsm_ref;
1586 #if (CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_HIGH_PRIO) && \
1587 	(CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
1588 	/* TODO:
1589 	 * These operations (increment, check) should be atomic/critical section
1590 	 * since we turn radio on/off from different contexts/ISRs (LLL, radio).
1591 	 * It's fine for now as all the contexts have the same priority and
1592 	 * don't preempt each other.
1593 	 */
1594 #else
1595 #error "Missing atomic operation in radio_wake()"
1596 #endif
1597 	if (localref == 1) {
1598 
1599 		uint32_t status = (RSIM->DSM_CONTROL & MAN_DSM_ON);
1600 
1601 		if (!status) {
1602 			/* Not in sleep mode */
1603 			return 0;
1604 		}
1605 
1606 		/* Get current DSM_TIMER value */
1607 		uint32_t dsm_timer = RSIM->DSM_TIMER;
1608 
1609 		/* Set Wake time after DSM_ENTER_DELAY */
1610 		RSIM->MAN_WAKE = RSIM_MAN_WAKE_MAN_WAKE_TIME(dsm_timer +
1611 				DSM_EXIT_DELAY_TICKS);
1612 	}
1613 
1614 	return 0;
1615 }
1616 
radio_is_off(void)1617 uint32_t radio_is_off(void)
1618 {
1619 	uint32_t status = (RSIM->DSM_CONTROL & MAN_DSM_ON);
1620 
1621 	return status;
1622 }
1623