1 /*
2  * Copyright (c) 2018-2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdint.h>
8 
9 #include <zephyr/toolchain.h>
10 
11 #include <zephyr/sys/util.h>
12 #include <zephyr/sys/byteorder.h>
13 
14 #include "hal/ccm.h"
15 #include "hal/radio.h"
16 #include "hal/ticker.h"
17 
18 #include "util/util.h"
19 #include "util/memq.h"
20 #include "util/dbuf.h"
21 #include "util/util.h"
22 
23 #include "pdu_df.h"
24 #include "pdu_vendor.h"
25 #include "pdu.h"
26 
27 #include "lll.h"
28 #include "lll_vendor.h"
29 #include "lll_clock.h"
30 #include "lll_df_types.h"
31 #include "lll_conn.h"
32 #include "lll_peripheral.h"
33 #include "lll_chan.h"
34 
35 #include "lll_internal.h"
36 #include "lll_df_internal.h"
37 #include "lll_tim_internal.h"
38 
39 #include <soc.h>
40 #include "hal/debug.h"
41 
42 static int init_reset(void);
43 static int prepare_cb(struct lll_prepare_param *p);
44 
lll_periph_init(void)45 int lll_periph_init(void)
46 {
47 	int err;
48 
49 	err = init_reset();
50 	if (err) {
51 		return err;
52 	}
53 
54 	return 0;
55 }
56 
lll_periph_reset(void)57 int lll_periph_reset(void)
58 {
59 	int err;
60 
61 	err = init_reset();
62 	if (err) {
63 		return err;
64 	}
65 
66 	return 0;
67 }
68 
lll_periph_prepare(void * param)69 void lll_periph_prepare(void *param)
70 {
71 	struct lll_prepare_param *p;
72 	struct lll_conn *lll;
73 	int err;
74 
75 	err = lll_hfclock_on();
76 	LL_ASSERT(err >= 0);
77 
78 	p = param;
79 
80 	lll = p->param;
81 
82 	/* Invoke common pipeline handling of prepare */
83 	err = lll_prepare(lll_conn_peripheral_is_abort_cb, lll_conn_abort_cb,
84 			  prepare_cb, 0U, param);
85 	LL_ASSERT(!err || err == -EINPROGRESS);
86 }
87 
init_reset(void)88 static int init_reset(void)
89 {
90 	return 0;
91 }
92 
prepare_cb(struct lll_prepare_param * p)93 static int prepare_cb(struct lll_prepare_param *p)
94 {
95 #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX)
96 	struct lll_df_conn_rx_params *df_rx_params;
97 	struct lll_df_conn_rx_cfg *df_rx_cfg;
98 #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */
99 	uint32_t ticks_at_event;
100 	uint32_t ticks_at_start;
101 	uint16_t event_counter;
102 	uint32_t remainder_us;
103 	uint8_t data_chan_use;
104 	struct lll_conn *lll;
105 	struct ull_hdr *ull;
106 	uint32_t remainder;
107 	uint32_t hcto;
108 	uint32_t ret;
109 
110 	DEBUG_RADIO_START_S(1);
111 
112 	lll = p->param;
113 
114 	/* Check if stopped (on disconnection between prepare and preempt)
115 	 */
116 	if (unlikely(lll->handle == 0xFFFF)) {
117 		radio_isr_set(lll_isr_early_abort, lll);
118 		radio_disable();
119 
120 		return 0;
121 	}
122 
123 	/* Reset connection event global variables */
124 	lll_conn_prepare_reset();
125 
126 	/* Calculate the current event latency */
127 	lll->lazy_prepare = p->lazy;
128 	lll->latency_event = lll->latency_prepare + lll->lazy_prepare;
129 
130 	/* Calculate the current event counter value */
131 	event_counter = lll->event_counter + lll->latency_event;
132 
133 	/* Update event counter to next value */
134 	lll->event_counter = (event_counter + 1);
135 
136 	/* Reset accumulated latencies */
137 	lll->latency_prepare = 0;
138 
139 	if (lll->data_chan_sel) {
140 #if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
141 		data_chan_use = lll_chan_sel_2(event_counter, lll->data_chan_id,
142 					       &lll->data_chan_map[0],
143 					       lll->data_chan_count);
144 #else /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
145 		data_chan_use = 0;
146 		LL_ASSERT(0);
147 #endif /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
148 	} else {
149 		data_chan_use = lll_chan_sel_1(&lll->data_chan_use,
150 					       lll->data_chan_hop,
151 					       lll->latency_event,
152 					       &lll->data_chan_map[0],
153 					       lll->data_chan_count);
154 	}
155 
156 	/* Accumulate window widening */
157 	lll->periph.window_widening_prepare_us +=
158 	    lll->periph.window_widening_periodic_us * (lll->lazy_prepare + 1U);
159 	if (lll->periph.window_widening_prepare_us >
160 	    lll->periph.window_widening_max_us) {
161 		lll->periph.window_widening_prepare_us =
162 			lll->periph.window_widening_max_us;
163 	}
164 
165 	/* current window widening */
166 	lll->periph.window_widening_event_us +=
167 		lll->periph.window_widening_prepare_us;
168 	lll->periph.window_widening_prepare_us = 0;
169 	if (lll->periph.window_widening_event_us >
170 	    lll->periph.window_widening_max_us) {
171 		lll->periph.window_widening_event_us =
172 			lll->periph.window_widening_max_us;
173 	}
174 
175 	/* current window size */
176 	lll->periph.window_size_event_us +=
177 		lll->periph.window_size_prepare_us;
178 	lll->periph.window_size_prepare_us = 0;
179 
180 	/* Ensure that empty flag reflects the state of the Tx queue, as a
181 	 * peripheral if this is the first connection event and as no prior PDU
182 	 * is transmitted, an incorrect acknowledgment by peer should not
183 	 * dequeue a PDU that has not been transmitted on air.
184 	 */
185 	if (!lll->empty) {
186 		memq_link_t *link;
187 
188 		/* Check for any Tx PDU at the head of the queue */
189 		link = memq_peek(lll->memq_tx.head, lll->memq_tx.tail, NULL);
190 		if (!link) {
191 			/* Update empty flag to reflect that no valid non-empty
192 			 * PDU was transmitted prior to this connection event.
193 			 */
194 			lll->empty = 1U;
195 		}
196 	}
197 
198 	/* Start setting up Radio h/w */
199 	radio_reset();
200 #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
201 	radio_tx_power_set(lll->tx_pwr_lvl);
202 #else
203 	radio_tx_power_set(RADIO_TXP_DEFAULT);
204 #endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
205 
206 	radio_aa_set(lll->access_addr);
207 	radio_crc_configure(PDU_CRC_POLYNOMIAL,
208 				sys_get_le24(lll->crc_init));
209 
210 	lll_chan_set(data_chan_use);
211 
212 	radio_isr_set(lll_conn_isr_rx, lll);
213 
214 	radio_tmr_tifs_set(lll->tifs_tx_us);
215 
216 #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX)
217 #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)
218 	enum radio_end_evt_delay_state end_evt_delay;
219 #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
220 
221 #if defined(CONFIG_BT_CTLR_PHY)
222 	if (lll->phy_rx != PHY_CODED) {
223 #else
224 	if (1) {
225 #endif /* CONFIG_BT_CTLR_PHY */
226 		df_rx_cfg = &lll->df_rx_cfg;
227 		df_rx_params = dbuf_latest_get(&df_rx_cfg->hdr, NULL);
228 
229 		if (df_rx_params->is_enabled == true) {
230 			(void)lll_df_conf_cte_rx_enable(df_rx_params->slot_durations,
231 						  df_rx_params->ant_sw_len, df_rx_params->ant_ids,
232 						  data_chan_use, CTE_INFO_IN_S1_BYTE, lll->phy_rx);
233 			lll->df_rx_cfg.chan = data_chan_use;
234 		} else {
235 			lll_df_conf_cte_info_parsing_enable();
236 		}
237 #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)
238 		end_evt_delay = END_EVT_DELAY_ENABLED;
239 	} else {
240 		end_evt_delay = END_EVT_DELAY_DISABLED;
241 #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
242 	}
243 
244 #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)
245 /* Use special API for SOC that requires compensation for PHYEND event delay. */
246 #if defined(CONFIG_BT_CTLR_PHY)
247 	radio_switch_complete_with_delay_compensation_and_tx(lll->phy_rx, 0, lll->phy_tx,
248 							     lll->phy_flags, end_evt_delay);
249 #else /* !CONFIG_BT_CTLR_PHY */
250 	radio_switch_complete_with_delay_compensation_and_tx(0, 0, 0, 0, end_evt_delay);
251 #endif /* !CONFIG_BT_CTLR_PHY */
252 
253 #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
254 #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */
255 
256 	/* Use regular API for cases when:
257 	 * - CTE RX is not enabled,
258 	 * - SOC does not require compensation for PHYEND event delay.
259 	 */
260 	if (!IS_ENABLED(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)) {
261 #if defined(CONFIG_BT_CTLR_PHY)
262 		radio_switch_complete_and_tx(lll->phy_rx, 0, lll->phy_tx, lll->phy_flags);
263 #else /* !CONFIG_BT_CTLR_PHY && !CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
264 		radio_switch_complete_and_tx(0, 0, 0, 0);
265 #endif /* !CONFIG_BT_CTLR_PHY */
266 	}
267 
268 	/* The call can use Radio interface that alternates NRF_RADIO->SHORTS. The register is
269 	 * set by radio_switch_complete_XXX functions, hence any changes done before are cleared.
270 	 */
271 	lll_conn_rx_pkt_set(lll);
272 
273 	ticks_at_event = p->ticks_at_expire;
274 	ull = HDR_LLL2ULL(lll);
275 	ticks_at_event += lll_event_offset_get(ull);
276 
277 	ticks_at_start = ticks_at_event;
278 	ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
279 
280 	remainder = p->remainder;
281 	remainder_us = radio_tmr_start(0, ticks_at_start, remainder);
282 
283 	radio_tmr_aa_capture();
284 	radio_tmr_aa_save(0);
285 
286 	hcto = remainder_us +
287 	       ((EVENT_JITTER_US + EVENT_TICKER_RES_MARGIN_US +
288 		 lll->periph.window_widening_event_us) << 1) +
289 	       lll->periph.window_size_event_us;
290 
291 #if defined(CONFIG_BT_CTLR_PHY)
292 	hcto += radio_rx_ready_delay_get(lll->phy_rx, 1);
293 	hcto += addr_us_get(lll->phy_rx);
294 	hcto += radio_rx_chain_delay_get(lll->phy_rx, 1);
295 #else /* !CONFIG_BT_CTLR_PHY */
296 	hcto += radio_rx_ready_delay_get(0, 0);
297 	hcto += addr_us_get(0);
298 	hcto += radio_rx_chain_delay_get(0, 0);
299 #endif /* !CONFIG_BT_CTLR_PHY */
300 
301 	radio_tmr_hcto_configure(hcto);
302 
303 #if defined(HAL_RADIO_GPIO_HAVE_LNA_PIN)
304 	radio_gpio_lna_setup();
305 
306 #if defined(CONFIG_BT_CTLR_PHY)
307 	radio_gpio_pa_lna_enable(remainder_us +
308 				 radio_rx_ready_delay_get(lll->phy_rx, 1) -
309 				 HAL_RADIO_GPIO_LNA_OFFSET);
310 #else /* !CONFIG_BT_CTLR_PHY */
311 	radio_gpio_pa_lna_enable(remainder_us +
312 				 radio_rx_ready_delay_get(0, 0) -
313 				 HAL_RADIO_GPIO_LNA_OFFSET);
314 #endif /* !CONFIG_BT_CTLR_PHY */
315 #endif /* HAL_RADIO_GPIO_HAVE_LNA_PIN */
316 
317 #if defined(CONFIG_BT_CTLR_PROFILE_ISR) || \
318 	defined(CONFIG_BT_CTLR_TX_DEFER) || \
319 	defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
320 	radio_tmr_end_capture();
321 #endif /* CONFIG_BT_CTLR_PROFILE_ISR ||
322 	* CONFIG_BT_CTLR_TX_DEFER ||
323 	* HAL_RADIO_GPIO_HAVE_PA_PIN
324 	*/
325 
326 #if defined(CONFIG_BT_CTLR_CONN_RSSI)
327 	radio_rssi_measure();
328 #endif /* CONFIG_BT_CTLR_CONN_RSSI */
329 
330 #if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
331 	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
332 	uint32_t overhead;
333 
334 	overhead = lll_preempt_calc(ull, (TICKER_ID_CONN_BASE + lll->handle), ticks_at_event);
335 	/* check if preempt to start has changed */
336 	if (overhead) {
337 		LL_ASSERT_OVERHEAD(overhead);
338 
339 		radio_isr_set(lll_isr_abort, lll);
340 		radio_disable();
341 
342 		return -ECANCELED;
343 	}
344 #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
345 
346 	ret = lll_prepare_done(lll);
347 	LL_ASSERT(!ret);
348 
349 	DEBUG_RADIO_START_S(1);
350 
351 	return 0;
352 }
353