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 if (IS_ENABLED(CONFIG_IEEE802154_L2_PKT_INCL_FCS) && len > 0) {
344 /* append CRC-16/CCITT */
345 uint16_t crc = 0;
346
347 crc = crc16_ccitt(0, sdu, len);
348 sdu[len++] = crc;
349 sdu[len++] = crc >> 8;
350 }
351
352 LOG_DBG("Received: len = %u, rssi = %d status = %u",
353 len, rssi, status);
354
355 pkt = net_pkt_rx_alloc_with_buffer(
356 drv_data->iface, len, AF_UNSPEC, 0, K_NO_WAIT);
357 if (!pkt) {
358 LOG_WRN("Cannot allocate packet");
359 continue;
360 }
361
362 if (net_pkt_write(pkt, sdu, len)) {
363 LOG_WRN("Cannot write packet");
364 net_pkt_unref(pkt);
365 continue;
366 }
367
368 drv_data->rx_entry[i].status = DATA_ENTRY_PENDING;
369
370 /* TODO: Determine LQI in PROP mode. */
371 net_pkt_set_ieee802154_lqi(pkt, 0xff);
372 net_pkt_set_ieee802154_rssi_dbm(pkt,
373 rssi == CC13XX_CC26XX_INVALID_RSSI
374 ? IEEE802154_MAC_RSSI_DBM_UNDEFINED
375 : rssi);
376
377 if (ieee802154_handle_ack(drv_data->iface, pkt) == NET_OK) {
378 net_pkt_unref(pkt);
379 continue;
380 }
381
382 if (net_recv_data(drv_data->iface, pkt)) {
383 LOG_WRN("Packet dropped");
384 net_pkt_unref(pkt);
385 }
386
387 } else if (drv_data->rx_entry[i].status ==
388 DATA_ENTRY_UNFINISHED) {
389 LOG_WRN("Frame not finished");
390 drv_data->rx_entry[i].status = DATA_ENTRY_PENDING;
391 }
392 }
393 }
394
cmd_prop_rx_adv_callback(RF_Handle h,RF_CmdHandle ch,RF_EventMask e)395 static void cmd_prop_rx_adv_callback(RF_Handle h, RF_CmdHandle ch,
396 RF_EventMask e)
397 {
398 const struct device *const dev = DEVICE_DT_INST_GET(0);
399 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
400 RF_Op *op = RF_getCmdOp(h, ch);
401
402 LOG_DBG("ch: %u cmd: %04x st: %04x e: 0x%" PRIx64, ch,
403 op->commandNo, op->status, e);
404
405 /* If PROP_ERROR_RXBUF is returned, then RF_EventRxEntryDone is never
406 * triggered. So finished buffers need to be cleaned up even on this
407 * status.
408 */
409 if (e & RF_EventRxEntryDone || op->status == PROP_ERROR_RXBUF) {
410 drv_rx_done(drv_data);
411 }
412
413 if (op->status == PROP_ERROR_RXBUF
414 || op->status == PROP_ERROR_RXFULL
415 || op->status == PROP_ERROR_RXOVF) {
416 LOG_DBG("RX Error %x", op->status);
417
418 /* Restart RX */
419 if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) {
420 return;
421 }
422
423 (void)drv_start_rx(dev);
424 k_sem_give(&drv_data->lock);
425 }
426 }
427
client_error_callback(RF_Handle h,RF_CmdHandle ch,RF_EventMask e)428 static void client_error_callback(RF_Handle h, RF_CmdHandle ch,
429 RF_EventMask e)
430 {
431 ARG_UNUSED(h);
432 ARG_UNUSED(ch);
433 LOG_ERR("client error: 0x%" PRIx64, e);
434 }
435
client_event_callback(RF_Handle h,RF_ClientEvent event,void * arg)436 static void client_event_callback(RF_Handle h, RF_ClientEvent event,
437 void *arg)
438 {
439 ARG_UNUSED(h);
440 LOG_DBG("event: %d arg: %p", event, arg);
441 }
442
443 static enum ieee802154_hw_caps
ieee802154_cc13xx_cc26xx_subg_get_capabilities(const struct device * dev)444 ieee802154_cc13xx_cc26xx_subg_get_capabilities(const struct device *dev)
445 {
446 /* TODO: enable IEEE802154_HW_FILTER */
447 return IEEE802154_HW_FCS;
448 }
449
ieee802154_cc13xx_cc26xx_subg_cca(const struct device * dev)450 static int ieee802154_cc13xx_cc26xx_subg_cca(const struct device *dev)
451 {
452 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
453 bool was_rx_on = false;
454 RF_EventMask events;
455 int ret;
456
457 if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) {
458 return -EWOULDBLOCK;
459 }
460
461 if (!drv_data->is_up) {
462 ret = -ENETDOWN;
463 goto out;
464 }
465
466 drv_data->cmd_prop_cs.status = IDLE;
467
468 was_rx_on = drv_data->cmd_prop_rx_adv.status == ACTIVE;
469 if (was_rx_on) {
470 ret = drv_stop_rx(dev);
471 if (ret) {
472 ret = -EIO;
473 goto out;
474 }
475 }
476
477 events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_prop_cs, RF_PriorityNormal,
478 NULL, 0);
479 if (events != RF_EventLastCmdDone) {
480 LOG_DBG("Failed to request CCA: 0x%" PRIx64, events);
481 ret = -EIO;
482 goto out;
483 }
484
485 switch (drv_data->cmd_prop_cs.status) {
486 case PROP_DONE_IDLE:
487 /* Do not re-enable RX when the channel is idle as
488 * this usually means we want to TX directly after
489 * and cannot afford any extra latency.
490 */
491 ret = 0;
492 break;
493 case PROP_DONE_BUSY:
494 case PROP_DONE_BUSYTIMEOUT:
495 ret = -EBUSY;
496 break;
497 default:
498 ret = -EIO;
499 }
500
501 out:
502 /* Re-enable RX if we found it on initially
503 * and the channel is busy (or another error
504 * occurred) as this usually means we back off
505 * and want to be able to receive packets in
506 * the meantime.
507 */
508 if (ret && was_rx_on) {
509 drv_start_rx(dev);
510 }
511
512 k_sem_give(&drv_data->lock);
513 return ret;
514 }
515
516 /* This method must be called with the lock held. */
drv_start_rx(const struct device * dev)517 static int drv_start_rx(const struct device *dev)
518 {
519 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
520 RF_CmdHandle cmd_handle;
521
522 if (drv_data->cmd_prop_rx_adv.status == ACTIVE) {
523 return -EALREADY;
524 }
525
526 #ifdef CONFIG_ASSERT
527 if (CONFIG_ASSERT_LEVEL > 0) {
528 /* ensure that all RX buffers are initialized and pending. */
529 for (int i = 0; i < CC13XX_CC26XX_NUM_RX_BUF; i++) {
530 __ASSERT_NO_MSG(drv_data->rx_entry[i].pNextEntry != NULL);
531 __ASSERT_NO_MSG(drv_data->rx_entry[i].status == DATA_ENTRY_PENDING);
532 }
533 }
534 #endif
535
536 drv_data->cmd_prop_rx_adv.status = IDLE;
537 cmd_handle = RF_postCmd(drv_data->rf_handle,
538 (RF_Op *)&drv_data->cmd_prop_rx_adv, RF_PriorityNormal,
539 cmd_prop_rx_adv_callback, RF_EventRxEntryDone);
540 if (cmd_handle < 0) {
541 LOG_DBG("Failed to post RX command (%d)", cmd_handle);
542 return -EIO;
543 }
544
545 drv_data->rx_cmd_handle = cmd_handle;
546
547 return 0;
548 }
549
550 /* This method must be called with the lock held. */
drv_stop_rx(const struct device * dev)551 static int drv_stop_rx(const struct device *dev)
552 {
553 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
554 RF_Stat status;
555
556 if (drv_data->cmd_prop_rx_adv.status != ACTIVE) {
557 return -EALREADY;
558 }
559
560 /* Stop RX without aborting ongoing reception of packets. */
561 status = RF_cancelCmd(drv_data->rf_handle, drv_data->rx_cmd_handle, RF_ABORT_GRACEFULLY);
562 switch (status) {
563 case RF_StatSuccess:
564 case RF_StatCmdEnded:
565 return 0;
566 default:
567 return -EIO;
568 }
569 }
570
ieee802154_cc13xx_cc26xx_subg_set_channel(const struct device * dev,uint16_t channel)571 static int ieee802154_cc13xx_cc26xx_subg_set_channel(
572 const struct device *dev, uint16_t channel)
573 {
574 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
575 uint16_t freq, fract;
576 RF_EventMask events;
577 bool was_rx_on;
578 int ret;
579
580 ret = drv_channel_frequency(channel, &freq, &fract);
581 if (ret < 0) {
582 return ret;
583 }
584
585 if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) {
586 return -EWOULDBLOCK;
587 }
588
589 was_rx_on = drv_data->cmd_prop_rx_adv.status == ACTIVE;
590 if (was_rx_on) {
591 ret = drv_stop_rx(dev);
592 if (ret) {
593 ret = -EIO;
594 goto out;
595 }
596 }
597
598 /* Set the frequency */
599 drv_data->cmd_fs.status = IDLE;
600 drv_data->cmd_fs.frequency = freq;
601 drv_data->cmd_fs.fractFreq = fract;
602 events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_fs,
603 RF_PriorityNormal, NULL, 0);
604 if (events != RF_EventLastCmdDone || drv_data->cmd_fs.status != DONE_OK) {
605 LOG_DBG("Failed to set frequency: 0x%" PRIx64, events);
606 ret = -EIO;
607 }
608
609 out:
610 if (was_rx_on) {
611 /* Re-enable RX if we found it on initially. */
612 (void)drv_start_rx(dev);
613 } else if (!drv_data->is_up) {
614 ret = drv_power_down(dev);
615 }
616
617 k_sem_give(&drv_data->lock);
618
619 return ret;
620 }
621
622 static int
ieee802154_cc13xx_cc26xx_subg_filter(const struct device * dev,bool set,enum ieee802154_filter_type type,const struct ieee802154_filter * filter)623 ieee802154_cc13xx_cc26xx_subg_filter(const struct device *dev, bool set,
624 enum ieee802154_filter_type type,
625 const struct ieee802154_filter *filter)
626 {
627 ARG_UNUSED(dev);
628 ARG_UNUSED(set);
629 ARG_UNUSED(type);
630 ARG_UNUSED(filter);
631 return -ENOTSUP;
632 }
633
ieee802154_cc13xx_cc26xx_subg_set_txpower(const struct device * dev,int16_t dbm)634 static int ieee802154_cc13xx_cc26xx_subg_set_txpower(
635 const struct device *dev, int16_t dbm)
636 {
637 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
638 RF_TxPowerTable_Value power_table_value;
639 RF_Stat status;
640 int ret = 0;
641
642 power_table_value = RF_TxPowerTable_findValue(
643 (RF_TxPowerTable_Entry *)ieee802154_cc13xx_subg_power_table, dbm);
644 if (power_table_value.rawValue == RF_TxPowerTable_INVALID_VALUE) {
645 LOG_DBG("RF_TxPowerTable_findValue() failed");
646 return -EINVAL;
647 }
648
649 /* No need for locking: rf_handle is immutable after initialization. */
650 status = RF_setTxPower(drv_data->rf_handle, power_table_value);
651 if (status != RF_StatSuccess) {
652 LOG_DBG("RF_setTxPower() failed: %d", status);
653 return -EIO;
654 }
655
656 if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) {
657 return -EWOULDBLOCK;
658 }
659
660 if (!drv_data->is_up) {
661 ret = drv_power_down(dev);
662 }
663
664 k_sem_give(&drv_data->lock);
665
666 return ret;
667 }
668
669 /* 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)670 static int ieee802154_cc13xx_cc26xx_subg_tx(const struct device *dev,
671 enum ieee802154_tx_mode mode,
672 struct net_pkt *pkt,
673 struct net_buf *buf)
674 {
675 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
676 RF_EventMask events;
677 int ret = 0;
678
679 if (buf->len > (CC13XX_CC26XX_TX_BUF_SIZE - IEEE802154_PHY_SUN_FSK_PHR_LEN)) {
680 return -EINVAL;
681 }
682
683 if (mode != IEEE802154_TX_MODE_DIRECT) {
684 /* For backwards compatibility we only log an error but do not bail. */
685 NET_ERR("TX mode %d not supported - sending directly instead.", mode);
686 }
687
688 if (k_sem_take(&drv_data->lock, K_FOREVER)) {
689 return -EIO;
690 }
691
692 if (!drv_data->is_up) {
693 ret = -ENETDOWN;
694 goto out;
695 }
696
697 if (drv_data->cmd_prop_rx_adv.status == ACTIVE) {
698 ret = drv_stop_rx(dev);
699 if (ret) {
700 ret = -EIO;
701 goto out;
702 }
703 }
704
705 /* Complete the SUN FSK PHY header, see IEEE 802.15.4, section 19.2.4. */
706 drv_data->tx_data[0] = buf->len + IEEE802154_FCS_LENGTH;
707
708 /* Set TX data
709 *
710 * TODO: Zero-copy TX, see discussion in #49775.
711 */
712 memcpy(&drv_data->tx_data[IEEE802154_PHY_SUN_FSK_PHR_LEN], buf->data, buf->len);
713 drv_data->cmd_prop_tx_adv.pktLen = buf->len + IEEE802154_PHY_SUN_FSK_PHR_LEN;
714
715 drv_data->cmd_prop_tx_adv.status = IDLE;
716 events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_prop_tx_adv,
717 RF_PriorityNormal, cmd_prop_tx_adv_callback, RF_EventLastCmdDone);
718 if ((events & RF_EventLastCmdDone) == 0) {
719 LOG_DBG("Failed to run command (%" PRIx64 ")", events);
720 ret = -EIO;
721 goto out;
722 }
723
724 if (drv_data->cmd_prop_tx_adv.status != PROP_DONE_OK) {
725 LOG_DBG("Transmit failed (0x%x)", drv_data->cmd_prop_tx_adv.status);
726 ret = -EIO;
727 }
728
729 out:
730 (void)drv_start_rx(dev);
731
732 k_sem_give(&drv_data->lock);
733 return ret;
734 }
735
736 /* driver-allocated attribute memory - constant across all driver instances */
737 IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 0, 10);
738
ieee802154_cc13xx_cc26xx_subg_attr_get(const struct device * dev,enum ieee802154_attr attr,struct ieee802154_attr_value * value)739 static int ieee802154_cc13xx_cc26xx_subg_attr_get(const struct device *dev,
740 enum ieee802154_attr attr,
741 struct ieee802154_attr_value *value)
742 {
743 ARG_UNUSED(dev);
744
745 /* We claim channel page nine with channel page zero channel range to
746 * ensure SUN-FSK timing, see the TODO in
747 * ieee802154_cc13xx_cc26xx_subg_channel_to_frequency().
748 */
749 return ieee802154_attr_get_channel_page_and_range(
750 attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_NINE_SUN_PREDEFINED,
751 &drv_attr.phy_supported_channels, value);
752 }
753
ieee802154_cc13xx_cc26xx_subg_start(const struct device * dev)754 static int ieee802154_cc13xx_cc26xx_subg_start(const struct device *dev)
755 {
756 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
757 int ret;
758
759 if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) {
760 return -EIO;
761 }
762
763 if (drv_data->is_up) {
764 ret = -EALREADY;
765 goto out;
766 }
767
768 ret = drv_start_rx(dev);
769 if (ret) {
770 goto out;
771 }
772
773 drv_data->is_up = true;
774
775 out:
776 k_sem_give(&drv_data->lock);
777 return ret;
778 }
779
780 /* Aborts all radio commands in the RF queue. Requires the lock to be held. */
drv_abort_commands(const struct device * dev)781 static int drv_abort_commands(const struct device *dev)
782 {
783 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
784 RF_Stat status;
785
786 status = RF_flushCmd(drv_data->rf_handle, RF_CMDHANDLE_FLUSH_ALL, 0);
787 if (!(status == RF_StatCmdDoneSuccess
788 || status == RF_StatSuccess
789 || status == RF_StatRadioInactiveError
790 || status == RF_StatInvalidParamsError)) {
791 LOG_DBG("Failed to abort radio operations (%d)", status);
792 return -EIO;
793 }
794
795 return 0;
796 }
797
798 /**
799 * Stops the sub-GHz interface and yields the radio (tells RF module to power
800 * down).
801 */
ieee802154_cc13xx_cc26xx_subg_stop_if(const struct device * dev)802 static int ieee802154_cc13xx_cc26xx_subg_stop_if(const struct device *dev)
803 {
804 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
805 int ret;
806
807 if (k_sem_take(&drv_data->lock, LOCK_TIMEOUT)) {
808 return -EIO;
809 }
810
811 if (!drv_data->is_up) {
812 ret = -EALREADY;
813 goto out;
814 }
815
816 ret = drv_abort_commands(dev);
817 if (ret) {
818 goto out;
819 }
820
821 ret = drv_power_down(dev);
822 if (ret) {
823 goto out;
824 }
825
826 drv_data->is_up = false;
827
828 out:
829 k_sem_give(&drv_data->lock);
830 return ret;
831 }
832
833 static int
ieee802154_cc13xx_cc26xx_subg_configure(const struct device * dev,enum ieee802154_config_type type,const struct ieee802154_config * config)834 ieee802154_cc13xx_cc26xx_subg_configure(const struct device *dev,
835 enum ieee802154_config_type type,
836 const struct ieee802154_config *config)
837 {
838 return -ENOTSUP;
839 }
840
drv_setup_rx_buffers(struct ieee802154_cc13xx_cc26xx_subg_data * drv_data)841 static void drv_setup_rx_buffers(struct ieee802154_cc13xx_cc26xx_subg_data *drv_data)
842 {
843 /* No need to zero buffers as they are zeroed on initialization and no
844 * need for locking as initialization is done with exclusive access.
845 */
846
847 for (size_t i = 0; i < CC13XX_CC26XX_NUM_RX_BUF; ++i) {
848 if (i < CC13XX_CC26XX_NUM_RX_BUF - 1) {
849 drv_data->rx_entry[i].pNextEntry =
850 (uint8_t *) &drv_data->rx_entry[i + 1];
851 } else {
852 drv_data->rx_entry[i].pNextEntry =
853 (uint8_t *) &drv_data->rx_entry[0];
854 }
855
856 drv_data->rx_entry[i].config.type = DATA_ENTRY_TYPE_PTR;
857 drv_data->rx_entry[i].config.lenSz = 1;
858 drv_data->rx_entry[i].length = sizeof(drv_data->rx_data[0]);
859 drv_data->rx_entry[i].pData = drv_data->rx_data[i];
860 }
861
862 drv_data->rx_queue.pCurrEntry = (uint8_t *)&drv_data->rx_entry[0];
863 drv_data->rx_queue.pLastEntry = NULL;
864 }
865
drv_setup_tx_buffer(struct ieee802154_cc13xx_cc26xx_subg_data * drv_data)866 static void drv_setup_tx_buffer(struct ieee802154_cc13xx_cc26xx_subg_data *drv_data)
867 {
868 /* No need to zero buffers as they are zeroed on initialization and no
869 * need for locking as initialization is done with exclusive access.
870 */
871
872 /* Part of the SUN FSK PHY header, see IEEE 802.15.4, section 19.2.4. */
873 drv_data->tx_data[1] = BIT(3) | /* FCS Type: 2-octet FCS */
874 BIT(4); /* DW: Enable Data Whitening */
875
876 drv_data->cmd_prop_tx_adv.pPkt = drv_data->tx_data;
877 }
878
drv_data_init(struct ieee802154_cc13xx_cc26xx_subg_data * drv_data)879 static void drv_data_init(struct ieee802154_cc13xx_cc26xx_subg_data *drv_data)
880 {
881 uint8_t *mac;
882
883 /* TODO: Do multi-protocol devices need more than one IEEE MAC? */
884 if (sys_read32(CCFG_BASE + CCFG_O_IEEE_MAC_0) != 0xFFFFFFFF &&
885 sys_read32(CCFG_BASE + CCFG_O_IEEE_MAC_1) != 0xFFFFFFFF) {
886 mac = (uint8_t *)(CCFG_BASE + CCFG_O_IEEE_MAC_0);
887 } else {
888 mac = (uint8_t *)(FCFG1_BASE + FCFG1_O_MAC_15_4_0);
889 }
890
891 sys_memcpy_swap(&drv_data->mac, mac, sizeof(drv_data->mac));
892
893 /* Setup circular RX queue (TRM 25.3.2.7) */
894 drv_setup_rx_buffers(drv_data);
895
896 /* Setup TX buffer (TRM 25.10.2.1.1, table 25-171) */
897 drv_setup_tx_buffer(drv_data);
898
899 k_sem_init(&drv_data->lock, 1, 1);
900 }
901
ieee802154_cc13xx_cc26xx_subg_iface_init(struct net_if * iface)902 static void ieee802154_cc13xx_cc26xx_subg_iface_init(struct net_if *iface)
903 {
904 const struct device *dev = net_if_get_device(iface);
905 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
906
907 net_if_set_link_addr(iface, drv_data->mac, sizeof(drv_data->mac),
908 NET_LINK_IEEE802154);
909
910 drv_data->iface = iface;
911
912 ieee802154_init(iface);
913 }
914
915 static const struct ieee802154_radio_api
916 ieee802154_cc13xx_cc26xx_subg_radio_api = {
917 .iface_api.init = ieee802154_cc13xx_cc26xx_subg_iface_init,
918
919 .get_capabilities = ieee802154_cc13xx_cc26xx_subg_get_capabilities,
920 .cca = ieee802154_cc13xx_cc26xx_subg_cca,
921 .set_channel = ieee802154_cc13xx_cc26xx_subg_set_channel,
922 .filter = ieee802154_cc13xx_cc26xx_subg_filter,
923 .set_txpower = ieee802154_cc13xx_cc26xx_subg_set_txpower,
924 .tx = ieee802154_cc13xx_cc26xx_subg_tx,
925 .start = ieee802154_cc13xx_cc26xx_subg_start,
926 .stop = ieee802154_cc13xx_cc26xx_subg_stop_if,
927 .configure = ieee802154_cc13xx_cc26xx_subg_configure,
928 .attr_get = ieee802154_cc13xx_cc26xx_subg_attr_get,
929 };
930
ieee802154_cc13xx_cc26xx_subg_init(const struct device * dev)931 static int ieee802154_cc13xx_cc26xx_subg_init(const struct device *dev)
932 {
933 struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data;
934 uint16_t freq, fract;
935 RF_Params rf_params;
936 RF_EventMask events;
937
938 /* No need for locking - initialization is exclusive. */
939
940 /* Initialize driver data */
941 drv_data_init(drv_data);
942
943 /* Setup radio */
944 RF_Params_init(&rf_params);
945 rf_params.pErrCb = client_error_callback;
946 rf_params.pClientEventCb = client_event_callback;
947
948 drv_data->rf_handle = RF_open(&drv_data->rf_object,
949 &rf_mode, (RF_RadioSetup *)&ieee802154_cc13xx_subg_radio_div_setup,
950 &rf_params);
951 if (drv_data->rf_handle == NULL) {
952 LOG_ERR("RF_open() failed");
953 return -EIO;
954 }
955
956 /* Run CMD_FS for channel 0 to place a valid CMD_FS command in the
957 * driver's internal state which it requires for proper operation.
958 */
959 (void)drv_channel_frequency(0, &freq, &fract);
960 drv_data->cmd_fs.status = IDLE;
961 drv_data->cmd_fs.frequency = freq;
962 drv_data->cmd_fs.fractFreq = fract;
963 events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_fs,
964 RF_PriorityNormal, NULL, 0);
965 if (events != RF_EventLastCmdDone || drv_data->cmd_fs.status != DONE_OK) {
966 LOG_ERR("Failed to set frequency: 0x%" PRIx64, events);
967 return -EIO;
968 }
969
970 return drv_power_down(dev);
971 }
972
973 static struct ieee802154_cc13xx_cc26xx_subg_data ieee802154_cc13xx_cc26xx_subg_data = {
974 /* Common Radio Commands */
975 .cmd_fs = {
976 .commandNo = CMD_FS,
977 .condition.rule = COND_NEVER,
978 },
979
980 .cmd_prop_rx_adv = {
981 .commandNo = CMD_PROP_RX_ADV,
982 .condition.rule = COND_NEVER,
983 .pktConf = {
984 .bRepeatOk = true,
985 .bRepeatNok = true,
986 .bUseCrc = true,
987 .filterOp = true,
988 },
989 .rxConf = {
990 .bAutoFlushIgnored = true,
991 .bAutoFlushCrcErr = true,
992 .bAppendRssi = true,
993 .bAppendStatus = true,
994 },
995 /* Last preamble byte and SFD for uncoded 2-FSK SUN PHY, phySunFskSfd = 0,
996 * see IEEE 802.15.4, section 19.2.3.2, table 19-2.
997 */
998 .syncWord0 = 0x55904E,
999 .maxPktLen = IEEE802154_MAX_PHY_PACKET_SIZE,
1000 /* PHR field format, see IEEE 802.15.4, section 19.2.4 */
1001 .hdrConf = {
1002 .numHdrBits = 16,
1003 .numLenBits = 11,
1004 },
1005 .lenOffset = -4,
1006 .endTrigger.triggerType = TRIG_NEVER,
1007 .pQueue = &ieee802154_cc13xx_cc26xx_subg_data.rx_queue,
1008 .pOutput =
1009 (uint8_t *) &ieee802154_cc13xx_cc26xx_subg_data
1010 .cmd_prop_rx_adv_output,
1011 },
1012
1013 .cmd_prop_cs = {
1014 .commandNo = CMD_PROP_CS,
1015 .condition.rule = COND_NEVER,
1016 .csConf = {
1017 /* CCA Mode 1: Energy above threshold, see section 10.2.8.
1018 * CC13/26xx SubG does not support correlation mode.
1019 */
1020 .bEnaRssi = true,
1021 /* Abort as soon as any energy above the ED threshold is detected. */
1022 .busyOp = true,
1023 /* Continue sensing until the timeout is reached. */
1024 .idleOp = false,
1025 },
1026 .rssiThr = CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_CS_THRESHOLD,
1027 .csEndTrigger.triggerType = TRIG_REL_START,
1028 /* see IEEE 802.15.4, section 11.3, table 11-1 and section 10.2.8 */
1029 .csEndTime = RF_convertUsToRatTicks(
1030 IEEE802154_PHY_A_CCA_TIME *
1031 (IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_NS /
1032 NSEC_PER_USEC)
1033 ),
1034 },
1035
1036 .cmd_prop_tx_adv = {
1037 .commandNo = CMD_PROP_TX_ADV,
1038 .startTrigger.triggerType = TRIG_NOW,
1039 .startTrigger.pastTrig = true,
1040 .condition.rule = COND_NEVER,
1041 .pktConf.bUseCrc = true,
1042 /* PHR field format, see IEEE 802.15.4, section 19.2.4 */
1043 .numHdrBits = 16,
1044 .preTrigger.triggerType =
1045 TRIG_REL_START, /* workaround for CC13_RF_ROM_FW_CPE--BUG00016 */
1046 .preTrigger.pastTrig = true,
1047 /* Last preamble byte and SFD for uncoded 2-FSK SUN PHY, phySunFskSfd = 0,
1048 * see IEEE 802.15.4, section 19.2.3.2, table 19-2.
1049 */
1050 .syncWord = 0x55904E,
1051 },
1052 };
1053
1054 #if defined(CONFIG_NET_L2_IEEE802154)
1055 NET_DEVICE_DT_INST_DEFINE(0, ieee802154_cc13xx_cc26xx_subg_init, NULL,
1056 &ieee802154_cc13xx_cc26xx_subg_data, NULL,
1057 CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_INIT_PRIO,
1058 &ieee802154_cc13xx_cc26xx_subg_radio_api,
1059 IEEE802154_L2, NET_L2_GET_CTX_TYPE(IEEE802154_L2),
1060 IEEE802154_MTU);
1061 #else
1062 DEVICE_DT_INST_DEFINE(0, ieee802154_cc13xx_cc26xx_subg_init, NULL,
1063 &ieee802154_cc13xx_cc26xx_subg_data, NULL, POST_KERNEL,
1064 CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_INIT_PRIO,
1065 &ieee802154_cc13xx_cc26xx_subg_radio_api);
1066 #endif
1067