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 	/* Accumulate window widening */
83 	lll->periph.window_widening_prepare_us +=
84 	    lll->periph.window_widening_periodic_us * (p->lazy + 1);
85 	if (lll->periph.window_widening_prepare_us >
86 	    lll->periph.window_widening_max_us) {
87 		lll->periph.window_widening_prepare_us =
88 			lll->periph.window_widening_max_us;
89 	}
90 
91 	/* Invoke common pipeline handling of prepare */
92 	err = lll_prepare(lll_is_abort_cb, lll_conn_abort_cb, prepare_cb, 0, p);
93 	LL_ASSERT(!err || err == -EINPROGRESS);
94 }
95 
init_reset(void)96 static int init_reset(void)
97 {
98 	return 0;
99 }
100 
prepare_cb(struct lll_prepare_param * p)101 static int prepare_cb(struct lll_prepare_param *p)
102 {
103 #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX)
104 	struct lll_df_conn_rx_params *df_rx_params;
105 	struct lll_df_conn_rx_cfg *df_rx_cfg;
106 #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */
107 	uint32_t ticks_at_event;
108 	uint32_t ticks_at_start;
109 	uint16_t event_counter;
110 	uint32_t remainder_us;
111 	uint8_t data_chan_use;
112 	struct lll_conn *lll;
113 	struct ull_hdr *ull;
114 	uint32_t remainder;
115 	uint32_t hcto;
116 	uint32_t ret;
117 
118 	DEBUG_RADIO_START_S(1);
119 
120 	lll = p->param;
121 
122 	/* Check if stopped (on disconnection between prepare and pre-empt)
123 	 */
124 	if (unlikely(lll->handle == 0xFFFF)) {
125 		radio_isr_set(lll_isr_early_abort, lll);
126 		radio_disable();
127 
128 		return 0;
129 	}
130 
131 	/* Reset connection event global variables */
132 	lll_conn_prepare_reset();
133 
134 	/* Calculate the current event latency */
135 	lll->latency_event = lll->latency_prepare + p->lazy;
136 
137 	/* Calculate the current event counter value */
138 	event_counter = lll->event_counter + lll->latency_event;
139 
140 	/* Update event counter to next value */
141 	lll->event_counter = (event_counter + 1);
142 
143 	/* Reset accumulated latencies */
144 	lll->latency_prepare = 0;
145 
146 	if (lll->data_chan_sel) {
147 #if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
148 		data_chan_use = lll_chan_sel_2(event_counter, lll->data_chan_id,
149 					       &lll->data_chan_map[0],
150 					       lll->data_chan_count);
151 #else /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
152 		data_chan_use = 0;
153 		LL_ASSERT(0);
154 #endif /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
155 	} else {
156 		data_chan_use = lll_chan_sel_1(&lll->data_chan_use,
157 					       lll->data_chan_hop,
158 					       lll->latency_event,
159 					       &lll->data_chan_map[0],
160 					       lll->data_chan_count);
161 	}
162 
163 	/* current window widening */
164 	lll->periph.window_widening_event_us +=
165 		lll->periph.window_widening_prepare_us;
166 	lll->periph.window_widening_prepare_us = 0;
167 	if (lll->periph.window_widening_event_us >
168 	    lll->periph.window_widening_max_us) {
169 		lll->periph.window_widening_event_us =
170 			lll->periph.window_widening_max_us;
171 	}
172 
173 	/* current window size */
174 	lll->periph.window_size_event_us +=
175 		lll->periph.window_size_prepare_us;
176 	lll->periph.window_size_prepare_us = 0;
177 
178 	/* Ensure that empty flag reflects the state of the Tx queue, as a
179 	 * peripheral if this is the first connection event and as no prior PDU
180 	 * is transmitted, an incorrect acknowledgment by peer should not
181 	 * dequeue a PDU that has not been transmitted on air.
182 	 */
183 	if (!lll->empty) {
184 		memq_link_t *link;
185 
186 		/* Check for any Tx PDU at the head of the queue */
187 		link = memq_peek(lll->memq_tx.head, lll->memq_tx.tail, NULL);
188 		if (!link) {
189 			/* Update empty flag to reflect that no valid non-empty
190 			 * PDU was transmitted prior to this connection event.
191 			 */
192 			lll->empty = 1U;
193 		}
194 	}
195 
196 	/* Start setting up Radio h/w */
197 	radio_reset();
198 #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
199 	radio_tx_power_set(lll->tx_pwr_lvl);
200 #else
201 	radio_tx_power_set(RADIO_TXP_DEFAULT);
202 #endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
203 
204 	radio_aa_set(lll->access_addr);
205 	radio_crc_configure(PDU_CRC_POLYNOMIAL,
206 				sys_get_le24(lll->crc_init));
207 
208 	lll_chan_set(data_chan_use);
209 
210 	radio_isr_set(lll_conn_isr_rx, lll);
211 
212 	radio_tmr_tifs_set(EVENT_IFS_US);
213 
214 #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX)
215 #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)
216 	enum radio_end_evt_delay_state end_evt_delay;
217 #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
218 
219 #if defined(CONFIG_BT_CTLR_PHY)
220 	if (lll->phy_rx != PHY_CODED) {
221 #else
222 	if (1) {
223 #endif /* CONFIG_BT_CTLR_PHY */
224 		df_rx_cfg = &lll->df_rx_cfg;
225 		df_rx_params = dbuf_latest_get(&df_rx_cfg->hdr, NULL);
226 
227 		if (df_rx_params->is_enabled == true) {
228 			(void)lll_df_conf_cte_rx_enable(df_rx_params->slot_durations,
229 						  df_rx_params->ant_sw_len, df_rx_params->ant_ids,
230 						  data_chan_use, CTE_INFO_IN_S1_BYTE, lll->phy_rx);
231 			lll->df_rx_cfg.chan = data_chan_use;
232 		} else {
233 			lll_df_conf_cte_info_parsing_enable();
234 		}
235 #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)
236 		end_evt_delay = END_EVT_DELAY_ENABLED;
237 	} else {
238 		end_evt_delay = END_EVT_DELAY_DISABLED;
239 #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
240 	}
241 
242 #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)
243 /* Use special API for SOC that requires compensation for PHYEND event delay. */
244 #if defined(CONFIG_BT_CTLR_PHY)
245 	radio_switch_complete_with_delay_compensation_and_tx(lll->phy_rx, 0, lll->phy_tx,
246 							     lll->phy_flags, end_evt_delay);
247 #else /* !CONFIG_BT_CTLR_PHY */
248 	radio_switch_complete_with_delay_compensation_and_tx(0, 0, 0, 0, end_evt_delay);
249 #endif /* !CONFIG_BT_CTLR_PHY */
250 
251 #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
252 #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */
253 
254 	/* Use regular API for cases when:
255 	 * - CTE RX is not enabled,
256 	 * - SOC does not require compensation for PHYEND event delay.
257 	 */
258 	if (!IS_ENABLED(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)) {
259 #if defined(CONFIG_BT_CTLR_PHY)
260 		radio_switch_complete_and_tx(lll->phy_rx, 0, lll->phy_tx, lll->phy_flags);
261 #else /* !CONFIG_BT_CTLR_PHY && !CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
262 		radio_switch_complete_and_tx(0, 0, 0, 0);
263 #endif /* !CONFIG_BT_CTLR_PHY */
264 	}
265 
266 	/* The call can use Radio interface that alternates NRF_RADIO->SHORTS. The register is
267 	 * set by radio_switch_complete_XXX functions, hence any changes done before are cleared.
268 	 */
269 	lll_conn_rx_pkt_set(lll);
270 
271 	ticks_at_event = p->ticks_at_expire;
272 	ull = HDR_LLL2ULL(lll);
273 	ticks_at_event += lll_event_offset_get(ull);
274 
275 	ticks_at_start = ticks_at_event;
276 	ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
277 
278 	remainder = p->remainder;
279 	remainder_us = radio_tmr_start(0, ticks_at_start, remainder);
280 
281 	radio_tmr_aa_capture();
282 	radio_tmr_aa_save(0);
283 
284 	hcto = remainder_us +
285 	       ((EVENT_JITTER_US + EVENT_TICKER_RES_MARGIN_US +
286 		 lll->periph.window_widening_event_us) << 1) +
287 	       lll->periph.window_size_event_us;
288 
289 #if defined(CONFIG_BT_CTLR_PHY)
290 	hcto += radio_rx_ready_delay_get(lll->phy_rx, 1);
291 	hcto += addr_us_get(lll->phy_rx);
292 	hcto += radio_rx_chain_delay_get(lll->phy_rx, 1);
293 #else /* !CONFIG_BT_CTLR_PHY */
294 	hcto += radio_rx_ready_delay_get(0, 0);
295 	hcto += addr_us_get(0);
296 	hcto += radio_rx_chain_delay_get(0, 0);
297 #endif /* !CONFIG_BT_CTLR_PHY */
298 
299 	radio_tmr_hcto_configure(hcto);
300 
301 #if defined(HAL_RADIO_GPIO_HAVE_LNA_PIN)
302 	radio_gpio_lna_setup();
303 
304 #if defined(CONFIG_BT_CTLR_PHY)
305 	radio_gpio_pa_lna_enable(remainder_us +
306 				 radio_rx_ready_delay_get(lll->phy_rx, 1) -
307 				 HAL_RADIO_GPIO_LNA_OFFSET);
308 #else /* !CONFIG_BT_CTLR_PHY */
309 	radio_gpio_pa_lna_enable(remainder_us +
310 				 radio_rx_ready_delay_get(0, 0) -
311 				 HAL_RADIO_GPIO_LNA_OFFSET);
312 #endif /* !CONFIG_BT_CTLR_PHY */
313 #endif /* HAL_RADIO_GPIO_HAVE_LNA_PIN */
314 
315 #if defined(CONFIG_BT_CTLR_PROFILE_ISR) || \
316 	defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
317 	radio_tmr_end_capture();
318 #endif /* CONFIG_BT_CTLR_PROFILE_ISR */
319 
320 #if defined(CONFIG_BT_CTLR_CONN_RSSI)
321 	radio_rssi_measure();
322 #endif /* CONFIG_BT_CTLR_CONN_RSSI */
323 
324 #if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
325 	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
326 	uint32_t overhead;
327 
328 	overhead = lll_preempt_calc(ull, (TICKER_ID_CONN_BASE + lll->handle), ticks_at_event);
329 	/* check if preempt to start has changed */
330 	if (overhead) {
331 		LL_ASSERT_OVERHEAD(overhead);
332 
333 		radio_isr_set(lll_isr_abort, lll);
334 		radio_disable();
335 
336 		return -ECANCELED;
337 	}
338 #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
339 
340 	ret = lll_prepare_done(lll);
341 	LL_ASSERT(!ret);
342 
343 	DEBUG_RADIO_START_S(1);
344 
345 	return 0;
346 }
347