1 /*
2 * Copyright (c) 2020 Friedt Professional Engineering Services, Inc
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT ti_cc13xx_cc26xx_ieee802154_subghz
8
9 #define LOG_LEVEL CONFIG_IEEE802154_DRIVER_LOG_LEVEL
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_REGISTER(ieee802154_cc13xx_cc26xx_subg);
12
13 #include <errno.h>
14 #include <string.h>
15
16 #include <zephyr/device.h>
17 #include <zephyr/net/ieee802154.h>
18 #include <zephyr/net/ieee802154_radio.h>
19 #include <zephyr/net/net_pkt.h>
20 #include <zephyr/random/random.h>
21 #include <zephyr/sys/byteorder.h>
22 #include <zephyr/sys/crc.h>
23 #include <zephyr/sys/sys_io.h>
24
25 #include <driverlib/rf_mailbox.h>
26 #include <driverlib/rf_prop_mailbox.h>
27 #include <driverlib/rfc.h>
28 #include <inc/hw_ccfg.h>
29 #include <inc/hw_fcfg1.h>
30 #include <rf_patches/rf_patch_cpe_multi_protocol.h>
31
32 #include <ti/drivers/rf/RF.h>
33
34 #include "ieee802154_cc13xx_cc26xx_subg.h"
35
36 static int drv_start_rx(const struct device *dev);
37 static int drv_stop_rx(const struct device *dev);
38
39 #ifndef CMD_PROP_RADIO_DIV_SETUP_PA
40 /* workaround for older HAL TI SDK (less than 4.40) */
41 #define CMD_PROP_RADIO_DIV_SETUP_PA CMD_PROP_RADIO_DIV_SETUP
42 #endif
43
44 #if defined(CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_CUSTOM_RADIO_SETUP)
45 /* User-defined CMD_PROP_RADIO_DIV_SETUP structures */
46 #if defined(CONFIG_SOC_CC1352R)
47 extern volatile rfc_CMD_PROP_RADIO_DIV_SETUP_t ieee802154_cc13xx_subg_radio_div_setup;
48 #elif defined(CONFIG_SOC_CC1352P) || defined(CONFIG_SOC_CC1352P7)
49 extern volatile rfc_CMD_PROP_RADIO_DIV_SETUP_PA_t ieee802154_cc13xx_subg_radio_div_setup;
50 #endif /* CONFIG_SOC_CC1352x, extern RADIO_DIV_SETUP */
51 #else
52
53 #if defined(CONFIG_SOC_CC1352R)
54 /* Radio register overrides for CC13x2R (note: CC26x2 does not support sub-GHz radio)
55 * from SmartRF Studio (200kbps, 50kHz deviation, 2-GFSK, 311.8kHz Rx BW),
56 * approximates SUN FSK PHY, 915 MHz band, operating mode #3.
57 */
58 static uint32_t ieee802154_cc13xx_overrides_sub_ghz[] = {
59 /* DC/DC regulator: In Tx, use DCDCCTL5[3:0]=0x7 (DITHER_EN=0 and IPEAK=7). */
60 (uint32_t)0x00F788D3,
61 /* Set RF_FSCA.ANADIV.DIV_SEL_BIAS = 1. Bits [0:16, 24, 30] are don't care.. */
62 (uint32_t)0x4001405D,
63 /* Set RF_FSCA.ANADIV.DIV_SEL_BIAS = 1. Bits [0:16, 24, 30] are don't care.. */
64 (uint32_t)0x08141131,
65 /* Tx: Configure PA ramp time, PACTL2.RC=0x3 (in ADI0, set PACTL2[4:3]=0x3) */
66 ADI_2HALFREG_OVERRIDE(0, 16, 0x8, 0x8, 17, 0x1, 0x1),
67 /* Tx: Configure PA ramping, set wait time before turning off
68 * (0x1A ticks of 16/24 us = 17.3 us).
69 */
70 HW_REG_OVERRIDE(0x6028, 0x001A),
71 /* Rx: Set AGC reference level to 0x16 (default: 0x2E) */
72 HW_REG_OVERRIDE(0x609C, 0x0016),
73 /* Rx: Set RSSI offset to adjust reported RSSI by -1 dB (default: -2),
74 * trimmed for external bias and differential configuration
75 */
76 (uint32_t)0x000188A3,
77 /* Rx: Set anti-aliasing filter bandwidth to 0x8 (in ADI0, set IFAMPCTL3[7:4]=0x8) */
78 ADI_HALFREG_OVERRIDE(0, 61, 0xF, 0x8),
79 /* Tx: Set PA trim to max to maximize its output power (in ADI0, set PACTL0=0xF8) */
80 ADI_REG_OVERRIDE(0, 12, 0xF8),
81 (uint32_t)0xFFFFFFFF
82 };
83
84 /* Radio values for CC13X2P */
85 #elif defined(CONFIG_SOC_CC1352P) || defined(CONFIG_SOC_CC1352P7)
86 /* CC1352P overrides from SmartRF Studio (200kbps, 50kHz deviation, 2-GFSK, 311.8kHz Rx BW) */
87 static uint32_t ieee802154_cc13xx_overrides_sub_ghz[] = {
88 /* Tx: Configure PA ramp time, PACTL2.RC=0x3 (in ADI0, set PACTL2[4:3]=0x1) */
89 ADI_2HALFREG_OVERRIDE(0, 16, 0x8, 0x8, 17, 0x1, 0x0),
90 /* Rx: Set AGC reference level to 0x16 (default: 0x2E) */
91 HW_REG_OVERRIDE(0x609C, 0x0016),
92 /* Rx: Set RSSI offset to adjust reported RSSI by -1 dB (default: -2),
93 * trimmed for external bias and differential configuration.
94 */
95 (uint32_t)0x000188A3,
96 /* Rx: Set anti-aliasing filter bandwidth to 0x6 (in ADI0, set IFAMPCTL3[7:4]=0x8) */
97 ADI_HALFREG_OVERRIDE(0, 61, 0xF, 0x8),
98 /* override_prop_common_sub1g.xml */
99 /* Set RF_FSCA.ANADIV.DIV_SEL_BIAS = 1. Bits [0:16, 24, 30] are don't care.. */
100 (uint32_t)0x4001405D,
101 /* Set RF_FSCA.ANADIV.DIV_SEL_BIAS = 1. Bits [0:16, 24, 30] are don't care.. */
102 (uint32_t)0x08141131,
103 /* override_prop_common.xml */
104 /* DC/DC regulator: In Tx with 14 dBm PA setting, use DCDCCTL5[3:0]=0xF */
105 /* (DITHER_EN=1 and IPEAK=7). In Rx, use default settings. */
106 (uint32_t)0x00F788D3,
107 (uint32_t)0xFFFFFFFF
108 };
109 static uint32_t rf_prop_overrides_tx_std[] = {
110 /* The TX Power element should always be the first in the list */
111 TX_STD_POWER_OVERRIDE(0x013F),
112 /* The ANADIV radio parameter based on the LO divider (0) and front-end (0) settings */
113 (uint32_t)0x11310703,
114 /* override_phy_tx_pa_ramp_genfsk_std.xml */
115 /* Tx: Configure PA ramping, set wait time before turning off */
116 /* (0x1A ticks of 16/24 us = 17.3 us). */
117 HW_REG_OVERRIDE(0x6028, 0x001A),
118 /* Set TXRX pin to 0 in RX and high impedance in idle/TX. */
119 HW_REG_OVERRIDE(0x60A8, 0x0401),
120 (uint32_t)0xFFFFFFFF
121 };
122 static uint32_t rf_prop_overrides_tx_20[] = {
123 /* The TX Power element should always be the first in the list */
124 TX20_POWER_OVERRIDE(0x001B8ED2),
125 /* The ANADIV radio parameter based on the LO divider (0) and front-end (0) settings */
126 (uint32_t)0x11C10703,
127 /* override_phy_tx_pa_ramp_genfsk_hpa.xml */
128 /* Tx: Configure PA ramping, set wait time before turning off */
129 /* (0x1F ticks of 16/24 us = 20.3 us). */
130 HW_REG_OVERRIDE(0x6028, 0x001F),
131 /* Set TXRX pin to 0 in RX/TX and high impedance in idle. */
132 HW_REG_OVERRIDE(0x60A8, 0x0001),
133 (uint32_t)0xFFFFFFFF
134 };
135
136 #else
137 #error "unsupported CC13xx SoC"
138 #endif /* CONFIG_SOC_CC1352x */
139
140 /* Radio setup command for CC13xx */
141 #if defined(CONFIG_SOC_CC1352R)
142 static volatile rfc_CMD_PROP_RADIO_DIV_SETUP_t ieee802154_cc13xx_subg_radio_div_setup = {
143 .commandNo = CMD_PROP_RADIO_DIV_SETUP,
144 #elif defined(CONFIG_SOC_CC1352P) || defined(CONFIG_SOC_CC1352P7)
145 static volatile rfc_CMD_PROP_RADIO_DIV_SETUP_PA_t ieee802154_cc13xx_subg_radio_div_setup = {
146 .commandNo = CMD_PROP_RADIO_DIV_SETUP_PA,
147 #endif /* CONFIG_SOC_CC1352x */
148 .condition.rule = COND_NEVER,
149 .modulation = {
150 .modType = 1, /* 2-GFSK - non-standard modulation */
151 .deviation = 200, /* +/- 200*250 = 50kHz deviation (modulation index 0.5) */
152 },
153 .symbolRate = {
154 .preScale = 15,
155 .rateWord = 131072, /* 200 kBit, see TRM, section 25.10.5.2, formula 15 */
156 },
157 .rxBw = 0x59, /* 310.8 kHz RX bandwidth, see TRM, section 25.10.5.2, table 25-183 */
158 .preamConf.nPreamBytes = 7, /* phyFskPreambleLength = 7 + 1, also see nSwBits below */
159 .formatConf = {
160 .nSwBits = 24, /* 24-bit (1 byte preamble + 16 bit SFD) */
161 .bMsbFirst = true,
162 .whitenMode = 7, /* Determine whitening and CRC from PHY header */
163 },
164 .config.biasMode = true, /* Rely on an external antenna biasing network. */
165 .txPower = 0x013f, /* 14 dBm, see TRM 25.3.3.2.16 */
166 .centerFreq = 906, /* Set channel page zero, channel 1 by default, see IEEE 802.15.4,
167 * section 10.1.3.3.
168 * TODO: Use compliant SUN PHY frequencies from channel page 9.
169 */
170 .intFreq = 0x8000, /* Use default intermediate frequency. */
171 .loDivider = 5,
172 .pRegOverride = ieee802154_cc13xx_overrides_sub_ghz,
173 #if defined(CONFIG_SOC_CC1352P) || defined(CONFIG_SOC_CC1352P7)
174 .pRegOverrideTxStd = rf_prop_overrides_tx_std,
175 .pRegOverrideTx20 = rf_prop_overrides_tx_20,
176 #endif /* CONFIG_SOC_CC1352P, CONFIG_SOC_CC1352P7 */
177 };
178
179 #endif /* CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_CUSTOM_RADIO_SETUP */
180
181 /* Sub GHz power tables */
182 #if defined(CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_CUSTOM_POWER_TABLE)
183 extern RF_TxPowerTable_Entry ieee802154_cc13xx_subg_power_table[];
184
185 #elif defined(CONFIG_SOC_CC1352R)
186 static const RF_TxPowerTable_Entry ieee802154_cc13xx_subg_power_table[] = {
187 { -20, RF_TxPowerTable_DEFAULT_PA_ENTRY(0, 3, 0, 2) },
188 { -15, RF_TxPowerTable_DEFAULT_PA_ENTRY(1, 3, 0, 3) },
189 { -10, RF_TxPowerTable_DEFAULT_PA_ENTRY(2, 3, 0, 5) },
190 { -5, RF_TxPowerTable_DEFAULT_PA_ENTRY(4, 3, 0, 5) },
191 { 0, RF_TxPowerTable_DEFAULT_PA_ENTRY(8, 3, 0, 8) },
192 { 1, RF_TxPowerTable_DEFAULT_PA_ENTRY(9, 3, 0, 9) },
193 { 2, RF_TxPowerTable_DEFAULT_PA_ENTRY(10, 3, 0, 9) },
194 { 3, RF_TxPowerTable_DEFAULT_PA_ENTRY(11, 3, 0, 10) },
195 { 4, RF_TxPowerTable_DEFAULT_PA_ENTRY(13, 3, 0, 11) },
196 { 5, RF_TxPowerTable_DEFAULT_PA_ENTRY(14, 3, 0, 14) },
197 { 6, RF_TxPowerTable_DEFAULT_PA_ENTRY(17, 3, 0, 16) },
198 { 7, RF_TxPowerTable_DEFAULT_PA_ENTRY(20, 3, 0, 19) },
199 { 8, RF_TxPowerTable_DEFAULT_PA_ENTRY(24, 3, 0, 22) },
200 { 9, RF_TxPowerTable_DEFAULT_PA_ENTRY(28, 3, 0, 31) },
201 { 10, RF_TxPowerTable_DEFAULT_PA_ENTRY(18, 2, 0, 31) },
202 { 11, RF_TxPowerTable_DEFAULT_PA_ENTRY(26, 2, 0, 51) },
203 { 12, RF_TxPowerTable_DEFAULT_PA_ENTRY(16, 0, 0, 82) },
204 { 13, RF_TxPowerTable_DEFAULT_PA_ENTRY(36, 0, 0, 89) },
205 #ifdef CONFIG_CC13X2_CC26X2_BOOST_MODE
206 { 14, RF_TxPowerTable_DEFAULT_PA_ENTRY(63, 0, 1, 0) },
207 #endif
208 RF_TxPowerTable_TERMINATION_ENTRY
209 };
210 #elif defined(CONFIG_SOC_CC1352P) || defined(CONFIG_SOC_CC1352P7)
211 /* Sub GHz power table */
212 static const RF_TxPowerTable_Entry ieee802154_cc13xx_subg_power_table[] = {
213 { -20, RF_TxPowerTable_DEFAULT_PA_ENTRY(0, 3, 0, 2) },
214 { -15, RF_TxPowerTable_DEFAULT_PA_ENTRY(1, 3, 0, 3) },
215 { -10, RF_TxPowerTable_DEFAULT_PA_ENTRY(2, 3, 0, 5) },
216 { -5, RF_TxPowerTable_DEFAULT_PA_ENTRY(4, 3, 0, 5) },
217 { 0, RF_TxPowerTable_DEFAULT_PA_ENTRY(8, 3, 0, 8) },
218 { 1, RF_TxPowerTable_DEFAULT_PA_ENTRY(9, 3, 0, 9) },
219 { 2, RF_TxPowerTable_DEFAULT_PA_ENTRY(10, 3, 0, 9) },
220 { 3, RF_TxPowerTable_DEFAULT_PA_ENTRY(11, 3, 0, 10) },
221 { 4, RF_TxPowerTable_DEFAULT_PA_ENTRY(13, 3, 0, 11) },
222 { 5, RF_TxPowerTable_DEFAULT_PA_ENTRY(14, 3, 0, 14) },
223 { 6, RF_TxPowerTable_DEFAULT_PA_ENTRY(17, 3, 0, 16) },
224 { 7, RF_TxPowerTable_DEFAULT_PA_ENTRY(20, 3, 0, 19) },
225 { 8, RF_TxPowerTable_DEFAULT_PA_ENTRY(24, 3, 0, 22) },
226 { 9, RF_TxPowerTable_DEFAULT_PA_ENTRY(28, 3, 0, 31) },
227 { 10, RF_TxPowerTable_DEFAULT_PA_ENTRY(18, 2, 0, 31) },
228 { 11, RF_TxPowerTable_DEFAULT_PA_ENTRY(26, 2, 0, 51) },
229 { 12, RF_TxPowerTable_DEFAULT_PA_ENTRY(16, 0, 0, 82) },
230 { 13, RF_TxPowerTable_DEFAULT_PA_ENTRY(36, 0, 0, 89) },
231 #ifdef CONFIG_CC13X2_CC26X2_BOOST_MODE
232 { 14, RF_TxPowerTable_DEFAULT_PA_ENTRY(63, 0, 1, 0) },
233 #endif
234 { 15, RF_TxPowerTable_HIGH_PA_ENTRY(18, 0, 0, 36, 0) },
235 { 16, RF_TxPowerTable_HIGH_PA_ENTRY(24, 0, 0, 43, 0) },
236 { 17, RF_TxPowerTable_HIGH_PA_ENTRY(28, 0, 0, 51, 2) },
237 { 18, RF_TxPowerTable_HIGH_PA_ENTRY(34, 0, 0, 64, 4) },
238 { 19, RF_TxPowerTable_HIGH_PA_ENTRY(15, 3, 0, 36, 4) },
239 { 20, RF_TxPowerTable_HIGH_PA_ENTRY(18, 3, 0, 71, 27) },
240 RF_TxPowerTable_TERMINATION_ENTRY
241 };
242 #endif /* CONFIG_SOC_CC1352x power table */
243
244 #define LOCK_TIMEOUT (k_is_in_isr() ? K_NO_WAIT : K_FOREVER)
245
246 /** RF patches to use (note: RF core keeps a pointer to this, so no stack). */
247 static RF_Mode rf_mode = {
248 .rfMode = RF_MODE_MULTIPLE,
249 .cpePatchFxn = &rf_patch_cpe_multi_protocol,
250 };
251
drv_channel_frequency(uint16_t channel,uint16_t * frequency,uint16_t * fractFreq)252 static inline int drv_channel_frequency(uint16_t channel, uint16_t *frequency, uint16_t *fractFreq)
253 {
254 __ASSERT_NO_MSG(frequency != NULL);
255 __ASSERT_NO_MSG(fractFreq != NULL);
256
257 /* See IEEE 802.15.4-2020, section 10.1.3.3. */
258 if (channel == 0) {
259 *frequency = 868;
260 /*
261 * uint16_t fractional part of 868.3 MHz
262 * equivalent to (0.3 * 1000 * BIT(16)) / 1000, rounded up
263 */
264 *fractFreq = 0x4ccd;
265 } else if (channel <= 10) {
266 *frequency = 906 + 2 * (channel - 1);
267 *fractFreq = 0;
268 } else {
269 *frequency = 0;
270 *fractFreq = 0;
271 return channel <= 26 ? -ENOTSUP : -EINVAL;
272 }
273
274 /* TODO: This incorrectly mixes up legacy BPSK SubGHz PHY channel page
275 * zero frequency calculation with SUN FSK operating mode #3 PHY radio
276 * settings.
277 *
278 * The correct channel frequency calculation for this PHY is on channel page 9,
279 * using the formula ChanCenterFreq = ChanCenterFreq0 + channel * ChanSpacing.
280 *
281 * Assuming operating mode #3, the parameters for some frequently used bands
282 * on this channel page are:
283 * 863 MHz: ChanSpacing 0.2, TotalNumChan 35, ChanCenterFreq0 863.1
284 * 915 MHz: ChanSpacing 0.4, TotalNumChan 64, ChanCenterFreq0 902.4
285 *
286 * See IEEE 802.15.4, section 10.1.3.9.
287 *
288 * Setting the PHY, channel page, band and operating mode requires additional
289 * radio configuration settings.
290 *
291 * Making derived MAC/PHY PIB attributes available to L2 requires an additional
292 * attribute getter, see
293 * https://github.com/zephyrproject-rtos/zephyr/issues/50336#issuecomment-1251122582.
294 *
295 * We resolve this bug right now by basing all timing on SUN FSK
296 * parameters while maintaining the channel/channel page assignment of a
297 * BPSK PHY.
298 */
299
300 return 0;
301 }
302
drv_power_down(const struct device * const dev)303 static inline int drv_power_down(const struct device *const dev)
304 {
305 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
306
307 (void)RF_yield(drv_data->rf_handle);
308
309 return 0;
310 }
311
cmd_prop_tx_adv_callback(RF_Handle h,RF_CmdHandle ch,RF_EventMask e)312 static void cmd_prop_tx_adv_callback(RF_Handle h, RF_CmdHandle ch,
313 RF_EventMask e)
314 {
315 const struct device *const dev = DEVICE_DT_INST_GET(0);
316 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
317 RF_Op *op = RF_getCmdOp(h, ch);
318
319 /* No need for locking as the RX status is volatile and there's no race. */
320 LOG_DBG("ch: %u cmd: %04x cs st: %04x tx st: %04x e: 0x%" PRIx64, ch,
321 op->commandNo, op->status, drv_data->cmd_prop_tx_adv.status, e);
322 }
323
drv_rx_done(struct ieee802154_cc13xx_cc26xx_subg_data * drv_data)324 static void drv_rx_done(struct ieee802154_cc13xx_cc26xx_subg_data *drv_data)
325 {
326 int8_t rssi, status;
327 struct net_pkt *pkt;
328 uint8_t len;
329 uint8_t *sdu;
330
331 /* No need for locking as only immutable data is accessed from drv_data.
332 * The rx queue itself (entries and data) are managed and protected
333 * internally by TI's RF driver.
334 */
335
336 for (int i = 0; i < CC13XX_CC26XX_NUM_RX_BUF; i++) {
337 if (drv_data->rx_entry[i].status == DATA_ENTRY_FINISHED) {
338 len = drv_data->rx_data[i][0];
339 sdu = drv_data->rx_data[i] + 1;
340 status = drv_data->rx_data[i][len--];
341 rssi = drv_data->rx_data[i][len--];
342
343 /* TODO: Configure firmware to include CRC in raw mode. */
344 if (IS_ENABLED(CONFIG_IEEE802154_RAW_MODE) && len > 0) {
345 /* append CRC-16/CCITT */
346 uint16_t crc = 0;
347
348 crc = crc16_ccitt(0, sdu, len);
349 sdu[len++] = crc;
350 sdu[len++] = crc >> 8;
351 }
352
353 LOG_DBG("Received: len = %u, rssi = %d status = %u",
354 len, rssi, status);
355
356 pkt = net_pkt_rx_alloc_with_buffer(
357 drv_data->iface, len, AF_UNSPEC, 0, K_NO_WAIT);
358 if (!pkt) {
359 LOG_WRN("Cannot allocate packet");
360 continue;
361 }
362
363 if (net_pkt_write(pkt, sdu, len)) {
364 LOG_WRN("Cannot write packet");
365 net_pkt_unref(pkt);
366 continue;
367 }
368
369 drv_data->rx_entry[i].status = DATA_ENTRY_PENDING;
370
371 /* TODO: Determine LQI in PROP mode. */
372 net_pkt_set_ieee802154_lqi(pkt, 0xff);
373 net_pkt_set_ieee802154_rssi_dbm(pkt,
374 rssi == CC13XX_CC26XX_INVALID_RSSI
375 ? IEEE802154_MAC_RSSI_DBM_UNDEFINED
376 : rssi);
377
378 if (ieee802154_handle_ack(drv_data->iface, pkt) == NET_OK) {
379 net_pkt_unref(pkt);
380 continue;
381 }
382
383 if (net_recv_data(drv_data->iface, pkt)) {
384 LOG_WRN("Packet dropped");
385 net_pkt_unref(pkt);
386 }
387
388 } else if (drv_data->rx_entry[i].status ==
389 DATA_ENTRY_UNFINISHED) {
390 LOG_WRN("Frame not finished");
391 drv_data->rx_entry[i].status = DATA_ENTRY_PENDING;
392 }
393 }
394 }
395
cmd_prop_rx_adv_callback(RF_Handle h,RF_CmdHandle ch,RF_EventMask e)396 static void cmd_prop_rx_adv_callback(RF_Handle h, RF_CmdHandle ch,
397 RF_EventMask e)
398 {
399 const struct device *const dev = DEVICE_DT_INST_GET(0);
400 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
401 RF_Op *op = RF_getCmdOp(h, ch);
402
403 LOG_DBG("ch: %u cmd: %04x st: %04x e: 0x%" PRIx64, ch,
404 op->commandNo, op->status, e);
405
406 /* If PROP_ERROR_RXBUF is returned, then RF_EventRxEntryDone is never
407 * triggered. So finished buffers need to be cleaned up even on this
408 * status.
409 */
410 if (e & RF_EventRxEntryDone || op->status == PROP_ERROR_RXBUF) {
411 drv_rx_done(drv_data);
412 }
413
414 if (op->status == PROP_ERROR_RXBUF
415 || op->status == PROP_ERROR_RXFULL
416 || op->status == PROP_ERROR_RXOVF) {
417 LOG_DBG("RX Error %x", op->status);
418
419 /* Restart RX */
420 if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) {
421 return;
422 }
423
424 (void)drv_start_rx(dev);
425 k_sem_give(&drv_data->lock);
426 }
427 }
428
client_error_callback(RF_Handle h,RF_CmdHandle ch,RF_EventMask e)429 static void client_error_callback(RF_Handle h, RF_CmdHandle ch,
430 RF_EventMask e)
431 {
432 ARG_UNUSED(h);
433 ARG_UNUSED(ch);
434 LOG_ERR("client error: 0x%" PRIx64, e);
435 }
436
client_event_callback(RF_Handle h,RF_ClientEvent event,void * arg)437 static void client_event_callback(RF_Handle h, RF_ClientEvent event,
438 void *arg)
439 {
440 ARG_UNUSED(h);
441 LOG_DBG("event: %d arg: %p", event, arg);
442 }
443
444 static enum ieee802154_hw_caps
ieee802154_cc13xx_cc26xx_subg_get_capabilities(const struct device * dev)445 ieee802154_cc13xx_cc26xx_subg_get_capabilities(const struct device *dev)
446 {
447 /* TODO: enable IEEE802154_HW_FILTER */
448 return IEEE802154_HW_FCS;
449 }
450
ieee802154_cc13xx_cc26xx_subg_cca(const struct device * dev)451 static int ieee802154_cc13xx_cc26xx_subg_cca(const struct device *dev)
452 {
453 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
454 bool was_rx_on = false;
455 RF_EventMask events;
456 int ret;
457
458 if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) {
459 return -EWOULDBLOCK;
460 }
461
462 if (!drv_data->is_up) {
463 ret = -ENETDOWN;
464 goto out;
465 }
466
467 drv_data->cmd_prop_cs.status = IDLE;
468
469 was_rx_on = drv_data->cmd_prop_rx_adv.status == ACTIVE;
470 if (was_rx_on) {
471 ret = drv_stop_rx(dev);
472 if (ret) {
473 ret = -EIO;
474 goto out;
475 }
476 }
477
478 events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_prop_cs, RF_PriorityNormal,
479 NULL, 0);
480 if (events != RF_EventLastCmdDone) {
481 LOG_DBG("Failed to request CCA: 0x%" PRIx64, events);
482 ret = -EIO;
483 goto out;
484 }
485
486 switch (drv_data->cmd_prop_cs.status) {
487 case PROP_DONE_IDLE:
488 /* Do not re-enable RX when the channel is idle as
489 * this usually means we want to TX directly after
490 * and cannot afford any extra latency.
491 */
492 ret = 0;
493 break;
494 case PROP_DONE_BUSY:
495 case PROP_DONE_BUSYTIMEOUT:
496 ret = -EBUSY;
497 break;
498 default:
499 ret = -EIO;
500 }
501
502 out:
503 /* Re-enable RX if we found it on initially
504 * and the channel is busy (or another error
505 * occurred) as this usually means we back off
506 * and want to be able to receive packets in
507 * the meantime.
508 */
509 if (ret && was_rx_on) {
510 drv_start_rx(dev);
511 }
512
513 k_sem_give(&drv_data->lock);
514 return ret;
515 }
516
517 /* This method must be called with the lock held. */
drv_start_rx(const struct device * dev)518 static int drv_start_rx(const struct device *dev)
519 {
520 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
521 RF_CmdHandle cmd_handle;
522
523 if (drv_data->cmd_prop_rx_adv.status == ACTIVE) {
524 return -EALREADY;
525 }
526
527 #ifdef CONFIG_ASSERT
528 if (CONFIG_ASSERT_LEVEL > 0) {
529 /* ensure that all RX buffers are initialized and pending. */
530 for (int i = 0; i < CC13XX_CC26XX_NUM_RX_BUF; i++) {
531 __ASSERT_NO_MSG(drv_data->rx_entry[i].pNextEntry != NULL);
532 __ASSERT_NO_MSG(drv_data->rx_entry[i].status == DATA_ENTRY_PENDING);
533 }
534 }
535 #endif
536
537 drv_data->cmd_prop_rx_adv.status = IDLE;
538 cmd_handle = RF_postCmd(drv_data->rf_handle,
539 (RF_Op *)&drv_data->cmd_prop_rx_adv, RF_PriorityNormal,
540 cmd_prop_rx_adv_callback, RF_EventRxEntryDone);
541 if (cmd_handle < 0) {
542 LOG_DBG("Failed to post RX command (%d)", cmd_handle);
543 return -EIO;
544 }
545
546 drv_data->rx_cmd_handle = cmd_handle;
547
548 return 0;
549 }
550
551 /* This method must be called with the lock held. */
drv_stop_rx(const struct device * dev)552 static int drv_stop_rx(const struct device *dev)
553 {
554 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
555 RF_Stat status;
556
557 if (drv_data->cmd_prop_rx_adv.status != ACTIVE) {
558 return -EALREADY;
559 }
560
561 /* Stop RX without aborting ongoing reception of packets. */
562 status = RF_cancelCmd(drv_data->rf_handle, drv_data->rx_cmd_handle, RF_ABORT_GRACEFULLY);
563 switch (status) {
564 case RF_StatSuccess:
565 case RF_StatCmdEnded:
566 return 0;
567 default:
568 return -EIO;
569 }
570 }
571
ieee802154_cc13xx_cc26xx_subg_set_channel(const struct device * dev,uint16_t channel)572 static int ieee802154_cc13xx_cc26xx_subg_set_channel(
573 const struct device *dev, uint16_t channel)
574 {
575 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
576 uint16_t freq, fract;
577 RF_EventMask events;
578 bool was_rx_on;
579 int ret;
580
581 ret = drv_channel_frequency(channel, &freq, &fract);
582 if (ret < 0) {
583 return ret;
584 }
585
586 if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) {
587 return -EWOULDBLOCK;
588 }
589
590 was_rx_on = drv_data->cmd_prop_rx_adv.status == ACTIVE;
591 if (was_rx_on) {
592 ret = drv_stop_rx(dev);
593 if (ret) {
594 ret = -EIO;
595 goto out;
596 }
597 }
598
599 /* Set the frequency */
600 drv_data->cmd_fs.status = IDLE;
601 drv_data->cmd_fs.frequency = freq;
602 drv_data->cmd_fs.fractFreq = fract;
603 events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_fs,
604 RF_PriorityNormal, NULL, 0);
605 if (events != RF_EventLastCmdDone || drv_data->cmd_fs.status != DONE_OK) {
606 LOG_DBG("Failed to set frequency: 0x%" PRIx64, events);
607 ret = -EIO;
608 }
609
610 out:
611 if (was_rx_on) {
612 /* Re-enable RX if we found it on initially. */
613 (void)drv_start_rx(dev);
614 } else if (!drv_data->is_up) {
615 ret = drv_power_down(dev);
616 }
617
618 k_sem_give(&drv_data->lock);
619
620 return ret;
621 }
622
623 static int
ieee802154_cc13xx_cc26xx_subg_filter(const struct device * dev,bool set,enum ieee802154_filter_type type,const struct ieee802154_filter * filter)624 ieee802154_cc13xx_cc26xx_subg_filter(const struct device *dev, bool set,
625 enum ieee802154_filter_type type,
626 const struct ieee802154_filter *filter)
627 {
628 ARG_UNUSED(dev);
629 ARG_UNUSED(set);
630 ARG_UNUSED(type);
631 ARG_UNUSED(filter);
632 return -ENOTSUP;
633 }
634
ieee802154_cc13xx_cc26xx_subg_set_txpower(const struct device * dev,int16_t dbm)635 static int ieee802154_cc13xx_cc26xx_subg_set_txpower(
636 const struct device *dev, int16_t dbm)
637 {
638 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
639 RF_TxPowerTable_Value power_table_value;
640 RF_Stat status;
641 int ret = 0;
642
643 power_table_value = RF_TxPowerTable_findValue(
644 (RF_TxPowerTable_Entry *)ieee802154_cc13xx_subg_power_table, dbm);
645 if (power_table_value.rawValue == RF_TxPowerTable_INVALID_VALUE) {
646 LOG_DBG("RF_TxPowerTable_findValue() failed");
647 return -EINVAL;
648 }
649
650 /* No need for locking: rf_handle is immutable after initialization. */
651 status = RF_setTxPower(drv_data->rf_handle, power_table_value);
652 if (status != RF_StatSuccess) {
653 LOG_DBG("RF_setTxPower() failed: %d", status);
654 return -EIO;
655 }
656
657 if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) {
658 return -EWOULDBLOCK;
659 }
660
661 if (!drv_data->is_up) {
662 ret = drv_power_down(dev);
663 }
664
665 k_sem_give(&drv_data->lock);
666
667 return ret;
668 }
669
670 /* See IEEE 802.15.4 section 6.7.1 and TRM section 25.5.4.3 */
ieee802154_cc13xx_cc26xx_subg_tx(const struct device * dev,enum ieee802154_tx_mode mode,struct net_pkt * pkt,struct net_buf * buf)671 static int ieee802154_cc13xx_cc26xx_subg_tx(const struct device *dev,
672 enum ieee802154_tx_mode mode,
673 struct net_pkt *pkt,
674 struct net_buf *buf)
675 {
676 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
677 RF_EventMask events;
678 int ret = 0;
679
680 if (buf->len > (CC13XX_CC26XX_TX_BUF_SIZE - IEEE802154_PHY_SUN_FSK_PHR_LEN)) {
681 return -EINVAL;
682 }
683
684 if (mode != IEEE802154_TX_MODE_DIRECT) {
685 /* For backwards compatibility we only log an error but do not bail. */
686 NET_ERR("TX mode %d not supported - sending directly instead.", mode);
687 }
688
689 if (k_sem_take(&drv_data->lock, K_FOREVER)) {
690 return -EIO;
691 }
692
693 if (!drv_data->is_up) {
694 ret = -ENETDOWN;
695 goto out;
696 }
697
698 if (drv_data->cmd_prop_rx_adv.status == ACTIVE) {
699 ret = drv_stop_rx(dev);
700 if (ret) {
701 ret = -EIO;
702 goto out;
703 }
704 }
705
706 /* Complete the SUN FSK PHY header, see IEEE 802.15.4, section 19.2.4. */
707 drv_data->tx_data[0] = buf->len + IEEE802154_FCS_LENGTH;
708
709 /* Set TX data
710 *
711 * TODO: Zero-copy TX, see discussion in #49775.
712 */
713 memcpy(&drv_data->tx_data[IEEE802154_PHY_SUN_FSK_PHR_LEN], buf->data, buf->len);
714 drv_data->cmd_prop_tx_adv.pktLen = buf->len + IEEE802154_PHY_SUN_FSK_PHR_LEN;
715
716 drv_data->cmd_prop_tx_adv.status = IDLE;
717 events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_prop_tx_adv,
718 RF_PriorityNormal, cmd_prop_tx_adv_callback, RF_EventLastCmdDone);
719 if ((events & RF_EventLastCmdDone) == 0) {
720 LOG_DBG("Failed to run command (%" PRIx64 ")", events);
721 ret = -EIO;
722 goto out;
723 }
724
725 if (drv_data->cmd_prop_tx_adv.status != PROP_DONE_OK) {
726 LOG_DBG("Transmit failed (0x%x)", drv_data->cmd_prop_tx_adv.status);
727 ret = -EIO;
728 }
729
730 out:
731 (void)drv_start_rx(dev);
732
733 k_sem_give(&drv_data->lock);
734 return ret;
735 }
736
737 /* driver-allocated attribute memory - constant across all driver instances */
738 IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 0, 10);
739
ieee802154_cc13xx_cc26xx_subg_attr_get(const struct device * dev,enum ieee802154_attr attr,struct ieee802154_attr_value * value)740 static int ieee802154_cc13xx_cc26xx_subg_attr_get(const struct device *dev,
741 enum ieee802154_attr attr,
742 struct ieee802154_attr_value *value)
743 {
744 ARG_UNUSED(dev);
745
746 /* We claim channel page nine with channel page zero channel range to
747 * ensure SUN-FSK timing, see the TODO in
748 * ieee802154_cc13xx_cc26xx_subg_channel_to_frequency().
749 */
750 return ieee802154_attr_get_channel_page_and_range(
751 attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_NINE_SUN_PREDEFINED,
752 &drv_attr.phy_supported_channels, value);
753 }
754
ieee802154_cc13xx_cc26xx_subg_start(const struct device * dev)755 static int ieee802154_cc13xx_cc26xx_subg_start(const struct device *dev)
756 {
757 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
758 int ret;
759
760 if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) {
761 return -EIO;
762 }
763
764 if (drv_data->is_up) {
765 ret = -EALREADY;
766 goto out;
767 }
768
769 ret = drv_start_rx(dev);
770 if (ret) {
771 goto out;
772 }
773
774 drv_data->is_up = true;
775
776 out:
777 k_sem_give(&drv_data->lock);
778 return ret;
779 }
780
781 /* Aborts all radio commands in the RF queue. Requires the lock to be held. */
drv_abort_commands(const struct device * dev)782 static int drv_abort_commands(const struct device *dev)
783 {
784 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
785 RF_Stat status;
786
787 status = RF_flushCmd(drv_data->rf_handle, RF_CMDHANDLE_FLUSH_ALL, 0);
788 if (!(status == RF_StatCmdDoneSuccess
789 || status == RF_StatSuccess
790 || status == RF_StatRadioInactiveError
791 || status == RF_StatInvalidParamsError)) {
792 LOG_DBG("Failed to abort radio operations (%d)", status);
793 return -EIO;
794 }
795
796 return 0;
797 }
798
799 /**
800 * Stops the sub-GHz interface and yields the radio (tells RF module to power
801 * down).
802 */
ieee802154_cc13xx_cc26xx_subg_stop_if(const struct device * dev)803 static int ieee802154_cc13xx_cc26xx_subg_stop_if(const struct device *dev)
804 {
805 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
806 int ret;
807
808 if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) {
809 return -EIO;
810 }
811
812 if (!drv_data->is_up) {
813 ret = -EALREADY;
814 goto out;
815 }
816
817 ret = drv_abort_commands(dev);
818 if (ret) {
819 goto out;
820 }
821
822 ret = drv_power_down(dev);
823 if (ret) {
824 goto out;
825 }
826
827 drv_data->is_up = false;
828
829 out:
830 k_sem_give(&drv_data->lock);
831 return ret;
832 }
833
834 static int
ieee802154_cc13xx_cc26xx_subg_configure(const struct device * dev,enum ieee802154_config_type type,const struct ieee802154_config * config)835 ieee802154_cc13xx_cc26xx_subg_configure(const struct device *dev,
836 enum ieee802154_config_type type,
837 const struct ieee802154_config *config)
838 {
839 return -ENOTSUP;
840 }
841
drv_setup_rx_buffers(struct ieee802154_cc13xx_cc26xx_subg_data * drv_data)842 static void drv_setup_rx_buffers(struct ieee802154_cc13xx_cc26xx_subg_data *drv_data)
843 {
844 /* No need to zero buffers as they are zeroed on initialization and no
845 * need for locking as initialization is done with exclusive access.
846 */
847
848 for (size_t i = 0; i < CC13XX_CC26XX_NUM_RX_BUF; ++i) {
849 if (i < CC13XX_CC26XX_NUM_RX_BUF - 1) {
850 drv_data->rx_entry[i].pNextEntry =
851 (uint8_t *) &drv_data->rx_entry[i + 1];
852 } else {
853 drv_data->rx_entry[i].pNextEntry =
854 (uint8_t *) &drv_data->rx_entry[0];
855 }
856
857 drv_data->rx_entry[i].config.type = DATA_ENTRY_TYPE_PTR;
858 drv_data->rx_entry[i].config.lenSz = 1;
859 drv_data->rx_entry[i].length = sizeof(drv_data->rx_data[0]);
860 drv_data->rx_entry[i].pData = drv_data->rx_data[i];
861 }
862
863 drv_data->rx_queue.pCurrEntry = (uint8_t *)&drv_data->rx_entry[0];
864 drv_data->rx_queue.pLastEntry = NULL;
865 }
866
drv_setup_tx_buffer(struct ieee802154_cc13xx_cc26xx_subg_data * drv_data)867 static void drv_setup_tx_buffer(struct ieee802154_cc13xx_cc26xx_subg_data *drv_data)
868 {
869 /* No need to zero buffers as they are zeroed on initialization and no
870 * need for locking as initialization is done with exclusive access.
871 */
872
873 /* Part of the SUN FSK PHY header, see IEEE 802.15.4, section 19.2.4. */
874 drv_data->tx_data[1] = BIT(3) | /* FCS Type: 2-octet FCS */
875 BIT(4); /* DW: Enable Data Whitening */
876
877 drv_data->cmd_prop_tx_adv.pPkt = drv_data->tx_data;
878 }
879
drv_data_init(struct ieee802154_cc13xx_cc26xx_subg_data * drv_data)880 static void drv_data_init(struct ieee802154_cc13xx_cc26xx_subg_data *drv_data)
881 {
882 uint8_t *mac;
883
884 /* TODO: Do multi-protocol devices need more than one IEEE MAC? */
885 if (sys_read32(CCFG_BASE + CCFG_O_IEEE_MAC_0) != 0xFFFFFFFF &&
886 sys_read32(CCFG_BASE + CCFG_O_IEEE_MAC_1) != 0xFFFFFFFF) {
887 mac = (uint8_t *)(CCFG_BASE + CCFG_O_IEEE_MAC_0);
888 } else {
889 mac = (uint8_t *)(FCFG1_BASE + FCFG1_O_MAC_15_4_0);
890 }
891
892 sys_memcpy_swap(&drv_data->mac, mac, sizeof(drv_data->mac));
893
894 /* Setup circular RX queue (TRM 25.3.2.7) */
895 drv_setup_rx_buffers(drv_data);
896
897 /* Setup TX buffer (TRM 25.10.2.1.1, table 25-171) */
898 drv_setup_tx_buffer(drv_data);
899
900 k_sem_init(&drv_data->lock, 1, 1);
901 }
902
ieee802154_cc13xx_cc26xx_subg_iface_init(struct net_if * iface)903 static void ieee802154_cc13xx_cc26xx_subg_iface_init(struct net_if *iface)
904 {
905 const struct device *dev = net_if_get_device(iface);
906 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
907
908 net_if_set_link_addr(iface, drv_data->mac, sizeof(drv_data->mac),
909 NET_LINK_IEEE802154);
910
911 drv_data->iface = iface;
912
913 ieee802154_init(iface);
914 }
915
916 static const struct ieee802154_radio_api
917 ieee802154_cc13xx_cc26xx_subg_radio_api = {
918 .iface_api.init = ieee802154_cc13xx_cc26xx_subg_iface_init,
919
920 .get_capabilities = ieee802154_cc13xx_cc26xx_subg_get_capabilities,
921 .cca = ieee802154_cc13xx_cc26xx_subg_cca,
922 .set_channel = ieee802154_cc13xx_cc26xx_subg_set_channel,
923 .filter = ieee802154_cc13xx_cc26xx_subg_filter,
924 .set_txpower = ieee802154_cc13xx_cc26xx_subg_set_txpower,
925 .tx = ieee802154_cc13xx_cc26xx_subg_tx,
926 .start = ieee802154_cc13xx_cc26xx_subg_start,
927 .stop = ieee802154_cc13xx_cc26xx_subg_stop_if,
928 .configure = ieee802154_cc13xx_cc26xx_subg_configure,
929 .attr_get = ieee802154_cc13xx_cc26xx_subg_attr_get,
930 };
931
ieee802154_cc13xx_cc26xx_subg_init(const struct device * dev)932 static int ieee802154_cc13xx_cc26xx_subg_init(const struct device *dev)
933 {
934 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
935 uint16_t freq, fract;
936 RF_Params rf_params;
937 RF_EventMask events;
938
939 /* No need for locking - initialization is exclusive. */
940
941 /* Initialize driver data */
942 drv_data_init(drv_data);
943
944 /* Setup radio */
945 RF_Params_init(&rf_params);
946 rf_params.pErrCb = client_error_callback;
947 rf_params.pClientEventCb = client_event_callback;
948
949 drv_data->rf_handle = RF_open(&drv_data->rf_object,
950 &rf_mode, (RF_RadioSetup *)&ieee802154_cc13xx_subg_radio_div_setup,
951 &rf_params);
952 if (drv_data->rf_handle == NULL) {
953 LOG_ERR("RF_open() failed");
954 return -EIO;
955 }
956
957 /* Run CMD_FS for channel 0 to place a valid CMD_FS command in the
958 * driver's internal state which it requires for proper operation.
959 */
960 (void)drv_channel_frequency(0, &freq, &fract);
961 drv_data->cmd_fs.status = IDLE;
962 drv_data->cmd_fs.frequency = freq;
963 drv_data->cmd_fs.fractFreq = fract;
964 events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_fs,
965 RF_PriorityNormal, NULL, 0);
966 if (events != RF_EventLastCmdDone || drv_data->cmd_fs.status != DONE_OK) {
967 LOG_ERR("Failed to set frequency: 0x%" PRIx64, events);
968 return -EIO;
969 }
970
971 return drv_power_down(dev);
972 }
973
974 static struct ieee802154_cc13xx_cc26xx_subg_data ieee802154_cc13xx_cc26xx_subg_data = {
975 /* Common Radio Commands */
976 .cmd_fs = {
977 .commandNo = CMD_FS,
978 .condition.rule = COND_NEVER,
979 },
980
981 .cmd_prop_rx_adv = {
982 .commandNo = CMD_PROP_RX_ADV,
983 .condition.rule = COND_NEVER,
984 .pktConf = {
985 .bRepeatOk = true,
986 .bRepeatNok = true,
987 .bUseCrc = true,
988 .filterOp = true,
989 },
990 .rxConf = {
991 .bAutoFlushIgnored = true,
992 .bAutoFlushCrcErr = true,
993 .bAppendRssi = true,
994 .bAppendStatus = true,
995 },
996 /* Last preamble byte and SFD for uncoded 2-FSK SUN PHY, phySunFskSfd = 0,
997 * see IEEE 802.15.4, section 19.2.3.2, table 19-2.
998 */
999 .syncWord0 = 0x55904E,
1000 .maxPktLen = IEEE802154_MAX_PHY_PACKET_SIZE,
1001 /* PHR field format, see IEEE 802.15.4, section 19.2.4 */
1002 .hdrConf = {
1003 .numHdrBits = 16,
1004 .numLenBits = 11,
1005 },
1006 .lenOffset = -4,
1007 .endTrigger.triggerType = TRIG_NEVER,
1008 .pQueue = &ieee802154_cc13xx_cc26xx_subg_data.rx_queue,
1009 .pOutput =
1010 (uint8_t *) &ieee802154_cc13xx_cc26xx_subg_data
1011 .cmd_prop_rx_adv_output,
1012 },
1013
1014 .cmd_prop_cs = {
1015 .commandNo = CMD_PROP_CS,
1016 .condition.rule = COND_NEVER,
1017 .csConf = {
1018 /* CCA Mode 1: Energy above threshold, see section 10.2.8.
1019 * CC13/26xx SubG does not support correlation mode.
1020 */
1021 .bEnaRssi = true,
1022 /* Abort as soon as any energy above the ED threshold is detected. */
1023 .busyOp = true,
1024 /* Continue sensing until the timeout is reached. */
1025 .idleOp = false,
1026 },
1027 .rssiThr = CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_CS_THRESHOLD,
1028 .csEndTrigger.triggerType = TRIG_REL_START,
1029 /* see IEEE 802.15.4, section 11.3, table 11-1 and section 10.2.8 */
1030 .csEndTime = RF_convertUsToRatTicks(
1031 IEEE802154_PHY_A_CCA_TIME *
1032 (IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_NS /
1033 NSEC_PER_USEC)
1034 ),
1035 },
1036
1037 .cmd_prop_tx_adv = {
1038 .commandNo = CMD_PROP_TX_ADV,
1039 .startTrigger.triggerType = TRIG_NOW,
1040 .startTrigger.pastTrig = true,
1041 .condition.rule = COND_NEVER,
1042 .pktConf.bUseCrc = true,
1043 /* PHR field format, see IEEE 802.15.4, section 19.2.4 */
1044 .numHdrBits = 16,
1045 .preTrigger.triggerType =
1046 TRIG_REL_START, /* workaround for CC13_RF_ROM_FW_CPE--BUG00016 */
1047 .preTrigger.pastTrig = true,
1048 /* Last preamble byte and SFD for uncoded 2-FSK SUN PHY, phySunFskSfd = 0,
1049 * see IEEE 802.15.4, section 19.2.3.2, table 19-2.
1050 */
1051 .syncWord = 0x55904E,
1052 },
1053 };
1054
1055 #if defined(CONFIG_NET_L2_IEEE802154)
1056 NET_DEVICE_DT_INST_DEFINE(0, ieee802154_cc13xx_cc26xx_subg_init, NULL,
1057 &ieee802154_cc13xx_cc26xx_subg_data, NULL,
1058 CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_INIT_PRIO,
1059 &ieee802154_cc13xx_cc26xx_subg_radio_api,
1060 IEEE802154_L2, NET_L2_GET_CTX_TYPE(IEEE802154_L2),
1061 IEEE802154_MTU);
1062 #else
1063 DEVICE_DT_INST_DEFINE(0, ieee802154_cc13xx_cc26xx_subg_init, NULL,
1064 &ieee802154_cc13xx_cc26xx_subg_data, NULL, POST_KERNEL,
1065 CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_INIT_PRIO,
1066 &ieee802154_cc13xx_cc26xx_subg_radio_api);
1067 #endif
1068