1 /*
2 * Copyright (c) 2019 Brett Witherspoon
3 * Copyright (c) 2020 Friedt Professional Engineering Services, Inc
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #define DT_DRV_COMPAT ti_cc13xx_cc26xx_ieee802154
9
10 #define LOG_LEVEL CONFIG_IEEE802154_DRIVER_LOG_LEVEL
11 #include <zephyr/logging/log.h>
12 LOG_MODULE_REGISTER(ieee802154_cc13xx_cc26xx);
13
14 #include <zephyr/device.h>
15 #include <errno.h>
16 #include <zephyr/sys/byteorder.h>
17 #include <zephyr/net/ieee802154_radio.h>
18 #include <zephyr/net/ieee802154.h>
19 #include <zephyr/net/net_pkt.h>
20 #include <zephyr/random/random.h>
21 #include <string.h>
22 #include <zephyr/sys/sys_io.h>
23
24 #include <driverlib/rf_ieee_mailbox.h>
25 #include <driverlib/rfc.h>
26 #include <inc/hw_ccfg.h>
27 #include <inc/hw_fcfg1.h>
28 #include <rf_patches/rf_patch_cpe_multi_protocol.h>
29
30 #include <ti/drivers/rf/RF.h>
31
32 #include "ieee802154_cc13xx_cc26xx.h"
33
34 #if defined(CONFIG_NET_L2_OPENTHREAD)
35 #include <zephyr/net/openthread.h>
36 #endif
37
38 /* Overrides from SmartRF Studio 7 2.13.0 */
39 static uint32_t overrides[] = {
40 /* DC/DC regulator: In Tx, use DCDCCTL5[3:0]=0x3 (DITHER_EN=0 and IPEAK=3). */
41 0x00F388D3,
42 /* Rx: Set LNA bias current offset to +15 to saturate trim to max (default: 0) */
43 0x000F8883,
44 0xFFFFFFFF
45 };
46
47 /* 2.4 GHz power table */
48 static const RF_TxPowerTable_Entry txPowerTable_2_4[] = {
49 {-20, RF_TxPowerTable_DEFAULT_PA_ENTRY(6, 3, 0, 2)},
50 {-15, RF_TxPowerTable_DEFAULT_PA_ENTRY(10, 3, 0, 3)},
51 {-10, RF_TxPowerTable_DEFAULT_PA_ENTRY(15, 3, 0, 5)},
52 {-5, RF_TxPowerTable_DEFAULT_PA_ENTRY(22, 3, 0, 9)},
53 {0, RF_TxPowerTable_DEFAULT_PA_ENTRY(19, 1, 0, 20)},
54 {1, RF_TxPowerTable_DEFAULT_PA_ENTRY(22, 1, 0, 20)},
55 {2, RF_TxPowerTable_DEFAULT_PA_ENTRY(25, 1, 0, 25)},
56 {3, RF_TxPowerTable_DEFAULT_PA_ENTRY(29, 1, 0, 28)},
57 {4, RF_TxPowerTable_DEFAULT_PA_ENTRY(35, 1, 0, 39)},
58 {5, RF_TxPowerTable_DEFAULT_PA_ENTRY(23, 0, 0, 57)},
59 RF_TxPowerTable_TERMINATION_ENTRY,
60 };
61
62 static void ieee802154_cc13xx_cc26xx_rx_done(
63 struct ieee802154_cc13xx_cc26xx_data *drv_data);
64 static int ieee802154_cc13xx_cc26xx_stop(const struct device *dev);
65
66 /* TODO remove when rf driver bugfix is pulled in */
update_saved_cmdhandle(RF_CmdHandle ch,RF_CmdHandle * saved)67 static void update_saved_cmdhandle(RF_CmdHandle ch, RF_CmdHandle *saved)
68 {
69 *saved = MAX(ch, *saved);
70 }
71
72 /* This is really the TX callback, because CSMA and TX are chained */
cmd_ieee_csma_callback(RF_Handle h,RF_CmdHandle ch,RF_EventMask e)73 static void cmd_ieee_csma_callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
74 {
75 ARG_UNUSED(h);
76
77 const struct device *const dev = DEVICE_DT_INST_GET(0);
78 struct ieee802154_cc13xx_cc26xx_data *drv_data = dev->data;
79
80 update_saved_cmdhandle(ch, (RF_CmdHandle *) &drv_data->saved_cmdhandle);
81
82 LOG_DBG("e: 0x%" PRIx64, e);
83
84 if (e & RF_EventInternalError) {
85 LOG_ERR("Internal error");
86 }
87 }
88
cmd_ieee_rx_callback(RF_Handle h,RF_CmdHandle ch,RF_EventMask e)89 static void cmd_ieee_rx_callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
90 {
91 ARG_UNUSED(h);
92
93 const struct device *const dev = DEVICE_DT_INST_GET(0);
94 struct ieee802154_cc13xx_cc26xx_data *drv_data = dev->data;
95
96 update_saved_cmdhandle(ch, (RF_CmdHandle *) &drv_data->saved_cmdhandle);
97
98 LOG_DBG("e: 0x%" PRIx64, e);
99
100 if (e & RF_EventRxBufFull) {
101 LOG_WRN("RX buffer is full");
102 }
103
104 if (e & RF_EventInternalError) {
105 LOG_ERR("Internal error");
106 }
107
108 if (e & RF_EventRxEntryDone) {
109 ieee802154_cc13xx_cc26xx_rx_done(drv_data);
110 }
111 }
112
client_error_callback(RF_Handle h,RF_CmdHandle ch,RF_EventMask e)113 static void client_error_callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
114 {
115 ARG_UNUSED(h);
116 ARG_UNUSED(ch);
117 LOG_DBG("e: 0x%" PRIx64, e);
118 }
119
client_event_callback(RF_Handle h,RF_ClientEvent event,void * arg)120 static void client_event_callback(RF_Handle h, RF_ClientEvent event, void *arg)
121 {
122 ARG_UNUSED(h);
123 LOG_DBG("event: %d arg: %p", event, arg);
124 }
125
126 static enum ieee802154_hw_caps
ieee802154_cc13xx_cc26xx_get_capabilities(const struct device * dev)127 ieee802154_cc13xx_cc26xx_get_capabilities(const struct device *dev)
128 {
129 return IEEE802154_HW_FCS | IEEE802154_HW_FILTER |
130 IEEE802154_HW_RX_TX_ACK | IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_CSMA |
131 IEEE802154_HW_RETRANSMISSION;
132 }
133
ieee802154_cc13xx_cc26xx_cca(const struct device * dev)134 static int ieee802154_cc13xx_cc26xx_cca(const struct device *dev)
135 {
136 struct ieee802154_cc13xx_cc26xx_data *drv_data = dev->data;
137 RF_Stat status;
138
139 status = RF_runImmediateCmd(drv_data->rf_handle,
140 (uint32_t *)&drv_data->cmd_ieee_cca_req);
141 if (status != RF_StatSuccess) {
142 LOG_ERR("Failed to request CCA (0x%x)", status);
143 return -EIO;
144 }
145
146 switch (drv_data->cmd_ieee_cca_req.ccaInfo.ccaState) {
147 case 0:
148 return 0;
149 case 1:
150 return -EBUSY;
151 default:
152 return -EIO;
153 }
154 }
155
ieee802154_cc13xx_cc26xx_channel_to_frequency(uint16_t channel,uint16_t * frequency,uint16_t * fractFreq)156 static inline int ieee802154_cc13xx_cc26xx_channel_to_frequency(
157 uint16_t channel, uint16_t *frequency, uint16_t *fractFreq)
158 {
159 __ASSERT_NO_MSG(frequency != NULL);
160 __ASSERT_NO_MSG(fractFreq != NULL);
161
162 /* See IEEE 802.15.4-2020, section 10.1.3.3. */
163 if (channel >= 11 && channel <= 26) {
164 *frequency = 2405 + 5 * (channel - 11);
165 *fractFreq = 0;
166 return 0;
167 } else {
168 /* TODO: Support sub-GHz for CC13xx rather than having separate drivers */
169 *frequency = 0;
170 *fractFreq = 0;
171 return channel < 11 ? -ENOTSUP : -EINVAL;
172 }
173 }
174
ieee802154_cc13xx_cc26xx_set_channel(const struct device * dev,uint16_t channel)175 static int ieee802154_cc13xx_cc26xx_set_channel(const struct device *dev,
176 uint16_t channel)
177 {
178 int ret;
179 RF_CmdHandle cmd_handle;
180 RF_EventMask reason;
181 uint16_t freq, fract;
182 struct ieee802154_cc13xx_cc26xx_data *drv_data = dev->data;
183
184 ret = ieee802154_cc13xx_cc26xx_channel_to_frequency(channel, &freq, &fract);
185 if (ret < 0) {
186 return ret;
187 }
188
189 /* Abort FG and BG processes */
190 if (ieee802154_cc13xx_cc26xx_stop(dev) < 0) {
191 ret = -EIO;
192 goto out;
193 }
194
195 /* Block TX while changing channel */
196 k_mutex_lock(&drv_data->tx_mutex, K_FOREVER);
197
198 /* Set the frequency */
199 drv_data->cmd_fs.status = IDLE;
200 drv_data->cmd_fs.frequency = freq;
201 drv_data->cmd_fs.fractFreq = fract;
202 reason = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_fs,
203 RF_PriorityNormal, NULL, 0);
204 if (reason != RF_EventLastCmdDone) {
205 LOG_ERR("Failed to set frequency: 0x%" PRIx64, reason);
206 ret = -EIO;
207 goto out;
208 }
209
210 /* Run BG receive process on requested channel */
211 drv_data->cmd_ieee_rx.status = IDLE;
212 drv_data->cmd_ieee_rx.channel = channel;
213 cmd_handle = RF_postCmd(drv_data->rf_handle,
214 (RF_Op *)&drv_data->cmd_ieee_rx, RF_PriorityNormal,
215 cmd_ieee_rx_callback, RF_EventRxEntryDone);
216 if (cmd_handle < 0) {
217 LOG_ERR("Failed to post RX command (%d)", cmd_handle);
218 ret = -EIO;
219 goto out;
220 }
221
222 ret = 0;
223
224 out:
225 k_mutex_unlock(&drv_data->tx_mutex);
226 return ret;
227 }
228
229 /* TODO remove when rf driver bugfix is pulled in */
ieee802154_cc13xx_cc26xx_reset_channel(const struct device * dev)230 static int ieee802154_cc13xx_cc26xx_reset_channel(
231 const struct device *dev)
232 {
233 uint8_t channel;
234 struct ieee802154_cc13xx_cc26xx_data *drv_data = dev->data;
235
236 /* extract the channel from cmd_ieee_rx */
237 channel = drv_data->cmd_ieee_rx.channel;
238
239 __ASSERT_NO_MSG(11 <= channel && channel <= 26);
240
241 LOG_DBG("re-setting channel to %u", channel);
242
243 return ieee802154_cc13xx_cc26xx_set_channel(dev, channel);
244 }
245
246 static int
ieee802154_cc13xx_cc26xx_filter(const struct device * dev,bool set,enum ieee802154_filter_type type,const struct ieee802154_filter * filter)247 ieee802154_cc13xx_cc26xx_filter(const struct device *dev, bool set,
248 enum ieee802154_filter_type type,
249 const struct ieee802154_filter *filter)
250 {
251 struct ieee802154_cc13xx_cc26xx_data *drv_data = dev->data;
252
253 if (!set) {
254 return -ENOTSUP;
255 }
256
257 if (type == IEEE802154_FILTER_TYPE_IEEE_ADDR) {
258 memcpy((uint8_t *)&drv_data->cmd_ieee_rx.localExtAddr,
259 filter->ieee_addr,
260 sizeof(drv_data->cmd_ieee_rx.localExtAddr));
261 } else if (type == IEEE802154_FILTER_TYPE_SHORT_ADDR) {
262 drv_data->cmd_ieee_rx.localShortAddr = filter->short_addr;
263 } else if (type == IEEE802154_FILTER_TYPE_PAN_ID) {
264 drv_data->cmd_ieee_rx.localPanID = filter->pan_id;
265 } else {
266 return -ENOTSUP;
267 }
268
269 return 0;
270 }
271
ieee802154_cc13xx_cc26xx_set_txpower(const struct device * dev,int16_t dbm)272 static int ieee802154_cc13xx_cc26xx_set_txpower(const struct device *dev,
273 int16_t dbm)
274 {
275 RF_Stat status;
276 const RF_TxPowerTable_Entry *table;
277 struct ieee802154_cc13xx_cc26xx_data *drv_data = dev->data;
278
279 /* TODO Support sub-GHz for CC13xx */
280 table = txPowerTable_2_4;
281
282 RF_TxPowerTable_Value power_table_value = RF_TxPowerTable_findValue(
283 (RF_TxPowerTable_Entry *)table, dbm);
284 if (power_table_value.rawValue == RF_TxPowerTable_INVALID_VALUE) {
285 LOG_ERR("RF_TxPowerTable_findValue() failed");
286 return -EINVAL;
287 }
288
289 status = RF_setTxPower(drv_data->rf_handle, power_table_value);
290 if (status != RF_StatSuccess) {
291 LOG_ERR("RF_setTxPower() failed: %d", status);
292 return -EIO;
293 }
294
295 return 0;
296 }
297
298 /* See IEEE 802.15.4 section 6.2.5.1 and TRM section 25.5.4.3 */
ieee802154_cc13xx_cc26xx_tx(const struct device * dev,enum ieee802154_tx_mode mode,struct net_pkt * pkt,struct net_buf * frag)299 static int ieee802154_cc13xx_cc26xx_tx(const struct device *dev,
300 enum ieee802154_tx_mode mode,
301 struct net_pkt *pkt,
302 struct net_buf *frag)
303 {
304 int r;
305 RF_EventMask reason;
306 RF_ScheduleCmdParams sched_params = {
307 .allowDelay = true,
308 };
309 struct ieee802154_cc13xx_cc26xx_data *drv_data = dev->data;
310 bool ack = ieee802154_is_ar_flag_set(frag);
311 int retry = CONFIG_IEEE802154_CC13XX_CC26XX_RADIO_TX_RETRIES;
312
313 if (mode != IEEE802154_TX_MODE_CSMA_CA) {
314 NET_ERR("TX mode %d not supported", mode);
315 return -ENOTSUP;
316 }
317
318 k_mutex_lock(&drv_data->tx_mutex, K_FOREVER);
319
320 /* Workaround for Issue #29418 where the driver stalls after
321 * wrapping around RF command handle 4096. This change
322 * effectively empties the RF command queue every ~4 minutes
323 * but otherwise causes the system to incur little overhead.
324 * A subsequent SimpleLink SDK release should resolve the issue.
325 */
326 if (drv_data->saved_cmdhandle >= BIT(12) - 5) {
327 r = ieee802154_cc13xx_cc26xx_reset_channel(dev);
328 if (r < 0) {
329 goto out;
330 }
331 drv_data->saved_cmdhandle = -1;
332 }
333
334 do {
335
336 drv_data->cmd_ieee_csma.status = IDLE;
337 drv_data->cmd_ieee_csma.randomState = sys_rand32_get();
338
339 drv_data->cmd_ieee_tx.status = IDLE;
340 drv_data->cmd_ieee_tx.payloadLen = frag->len;
341 drv_data->cmd_ieee_tx.pPayload = frag->data;
342 drv_data->cmd_ieee_tx.condition.rule =
343 ack ? COND_STOP_ON_FALSE : COND_NEVER;
344
345 if (ack) {
346 drv_data->cmd_ieee_rx_ack.status = IDLE;
347 drv_data->cmd_ieee_rx_ack.seqNo = frag->data[2];
348 }
349
350 reason = RF_runScheduleCmd(drv_data->rf_handle,
351 (RF_Op *)&drv_data->cmd_ieee_csma, &sched_params,
352 cmd_ieee_csma_callback,
353 RF_EventLastFGCmdDone | RF_EventLastCmdDone);
354 if ((reason & (RF_EventLastFGCmdDone | RF_EventLastCmdDone))
355 == 0) {
356 LOG_DBG("Failed to run command (0x%" PRIx64 ")",
357 reason);
358 continue;
359 }
360
361 if (drv_data->cmd_ieee_csma.status != IEEE_DONE_OK) {
362 /* TODO: According to IEEE 802.15.4 CSMA/CA failure
363 * fails TX immediately and should not trigger
364 * attempt (which is reserved for ACK timeouts).
365 */
366 LOG_DBG("Channel access failure (0x%x)",
367 drv_data->cmd_ieee_csma.status);
368 continue;
369 }
370
371 if (drv_data->cmd_ieee_tx.status != IEEE_DONE_OK) {
372 /* TODO: According to IEEE 802.15.4 transmission failure
373 * fails TX immediately and should not trigger
374 * attempt (which is reserved for ACK timeouts).
375 */
376 LOG_DBG("Transmit failed (0x%x)",
377 drv_data->cmd_ieee_tx.status);
378 continue;
379 }
380
381 if (!ack || drv_data->cmd_ieee_rx_ack.status == IEEE_DONE_ACK ||
382 drv_data->cmd_ieee_rx_ack.status == IEEE_DONE_ACKPEND) {
383 r = 0;
384 goto out;
385 }
386
387 LOG_DBG("No acknowledgment (0x%x)",
388 drv_data->cmd_ieee_rx_ack.status);
389 } while (retry-- > 0);
390
391 LOG_DBG("Failed to TX");
392 r = -EIO;
393
394 out:
395 k_mutex_unlock(&drv_data->tx_mutex);
396 return r;
397 }
398
ieee802154_cc13xx_cc26xx_rx_done(struct ieee802154_cc13xx_cc26xx_data * drv_data)399 static void ieee802154_cc13xx_cc26xx_rx_done(
400 struct ieee802154_cc13xx_cc26xx_data *drv_data)
401 {
402 struct net_pkt *pkt;
403 uint8_t len, seq, corr, lqi;
404 int8_t rssi;
405 uint8_t *sdu;
406
407 for (int i = 0; i < CC13XX_CC26XX_NUM_RX_BUF; i++) {
408 if (drv_data->rx_entry[i].status == DATA_ENTRY_FINISHED) {
409 /* rx_data contains length, psdu, fcs, rssi, corr */
410 len = drv_data->rx_data[i][0];
411 sdu = drv_data->rx_data[i] + 1;
412 seq = drv_data->rx_data[i][3];
413 corr = drv_data->rx_data[i][len--] & 0x3F;
414 rssi = drv_data->rx_data[i][len--];
415
416 if (!IS_ENABLED(CONFIG_IEEE802154_L2_PKT_INCL_FCS)) {
417 len -= 2;
418 }
419
420 /* scale 6-bit corr to 8-bit lqi */
421 lqi = corr << 2;
422
423 LOG_DBG("Received: len = %u, seq = %u, rssi = %d, lqi = %u",
424 len, seq, rssi, lqi);
425
426 pkt = net_pkt_rx_alloc_with_buffer(
427 drv_data->iface, len, AF_UNSPEC, 0, K_NO_WAIT);
428 if (!pkt) {
429 LOG_WRN("Cannot allocate packet");
430 continue;
431 }
432
433 if (net_pkt_write(pkt, sdu, len)) {
434 LOG_WRN("Cannot write packet");
435 net_pkt_unref(pkt);
436 continue;
437 }
438
439 drv_data->rx_entry[i].status = DATA_ENTRY_PENDING;
440
441 net_pkt_set_ieee802154_lqi(pkt, lqi);
442 net_pkt_set_ieee802154_rssi_dbm(pkt,
443 rssi == CC13XX_CC26XX_INVALID_RSSI
444 ? IEEE802154_MAC_RSSI_DBM_UNDEFINED
445 : rssi);
446
447 if (net_recv_data(drv_data->iface, pkt)) {
448 LOG_WRN("Packet dropped");
449 net_pkt_unref(pkt);
450 }
451
452 } else if (drv_data->rx_entry[i].status ==
453 DATA_ENTRY_UNFINISHED) {
454 LOG_WRN("Frame not finished");
455 drv_data->rx_entry[i].status = DATA_ENTRY_PENDING;
456 }
457 }
458 }
459
ieee802154_cc13xx_cc26xx_start(const struct device * dev)460 static int ieee802154_cc13xx_cc26xx_start(const struct device *dev)
461 {
462 ARG_UNUSED(dev);
463
464 return 0;
465 }
466
ieee802154_cc13xx_cc26xx_stop(const struct device * dev)467 static int ieee802154_cc13xx_cc26xx_stop(const struct device *dev)
468 {
469 struct ieee802154_cc13xx_cc26xx_data *drv_data = dev->data;
470
471 RF_Stat status;
472
473 status = RF_flushCmd(drv_data->rf_handle, RF_CMDHANDLE_FLUSH_ALL, 0);
474 if (!(status == RF_StatCmdDoneSuccess
475 || status == RF_StatSuccess
476 || status == RF_StatRadioInactiveError
477 || status == RF_StatInvalidParamsError)) {
478 LOG_DBG("Failed to abort radio operations (%d)", status);
479 return -EIO;
480 }
481
482 return 0;
483 }
484
485 /**
486 * Stops the sub-GHz interface and yields the radio (tells RF module to power
487 * down).
488 */
ieee802154_cc13xx_cc26xx_stop_if(const struct device * dev)489 static int ieee802154_cc13xx_cc26xx_stop_if(const struct device *dev)
490 {
491 struct ieee802154_cc13xx_cc26xx_data *drv_data = dev->data;
492 int ret;
493
494 ret = ieee802154_cc13xx_cc26xx_stop(dev);
495 if (ret < 0) {
496 return ret;
497 }
498
499 /* power down radio */
500 RF_yield(drv_data->rf_handle);
501 return 0;
502 }
503
504 static int
ieee802154_cc13xx_cc26xx_configure(const struct device * dev,enum ieee802154_config_type type,const struct ieee802154_config * config)505 ieee802154_cc13xx_cc26xx_configure(const struct device *dev,
506 enum ieee802154_config_type type,
507 const struct ieee802154_config *config)
508 {
509 return -ENOTSUP;
510 }
511
512 /* driver-allocated attribute memory - constant across all driver instances */
513 IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26);
514
ieee802154_cc13xx_cc26xx_attr_get(const struct device * dev,enum ieee802154_attr attr,struct ieee802154_attr_value * value)515 static int ieee802154_cc13xx_cc26xx_attr_get(const struct device *dev, enum ieee802154_attr attr,
516 struct ieee802154_attr_value *value)
517 {
518 ARG_UNUSED(dev);
519
520 return ieee802154_attr_get_channel_page_and_range(
521 attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915,
522 &drv_attr.phy_supported_channels, value);
523 }
524
ieee802154_cc13xx_cc26xx_data_init(const struct device * dev)525 static void ieee802154_cc13xx_cc26xx_data_init(const struct device *dev)
526 {
527 struct ieee802154_cc13xx_cc26xx_data *drv_data = dev->data;
528 uint8_t *mac;
529
530 if (sys_read32(CCFG_BASE + CCFG_O_IEEE_MAC_0) != 0xFFFFFFFF &&
531 sys_read32(CCFG_BASE + CCFG_O_IEEE_MAC_1) != 0xFFFFFFFF) {
532 mac = (uint8_t *)(CCFG_BASE + CCFG_O_IEEE_MAC_0);
533 } else {
534 mac = (uint8_t *)(FCFG1_BASE + FCFG1_O_MAC_15_4_0);
535 }
536
537 sys_memcpy_swap(&drv_data->mac, mac, sizeof(drv_data->mac));
538
539 /* Setup circular RX queue (TRM 25.3.2.7) */
540 memset(&drv_data->rx_entry[0], 0, sizeof(drv_data->rx_entry[0]));
541 memset(&drv_data->rx_entry[1], 0, sizeof(drv_data->rx_entry[1]));
542
543 drv_data->rx_entry[0].pNextEntry = (uint8_t *)&drv_data->rx_entry[1];
544 drv_data->rx_entry[0].config.type = DATA_ENTRY_TYPE_PTR;
545 drv_data->rx_entry[0].config.lenSz = 1;
546 drv_data->rx_entry[0].length = sizeof(drv_data->rx_data[0]);
547 drv_data->rx_entry[0].pData = drv_data->rx_data[0];
548
549 drv_data->rx_entry[1].pNextEntry = (uint8_t *)&drv_data->rx_entry[0];
550 drv_data->rx_entry[1].config.type = DATA_ENTRY_TYPE_PTR;
551 drv_data->rx_entry[1].config.lenSz = 1;
552 drv_data->rx_entry[1].length = sizeof(drv_data->rx_data[1]);
553 drv_data->rx_entry[1].pData = drv_data->rx_data[1];
554
555 drv_data->rx_queue.pCurrEntry = (uint8_t *)&drv_data->rx_entry[0];
556 drv_data->rx_queue.pLastEntry = NULL;
557
558 k_mutex_init(&drv_data->tx_mutex);
559 }
560
ieee802154_cc13xx_cc26xx_iface_init(struct net_if * iface)561 static void ieee802154_cc13xx_cc26xx_iface_init(struct net_if *iface)
562 {
563 const struct device *dev = net_if_get_device(iface);
564 struct ieee802154_cc13xx_cc26xx_data *drv_data = dev->data;
565
566 net_if_set_link_addr(iface, drv_data->mac, sizeof(drv_data->mac),
567 NET_LINK_IEEE802154);
568
569 drv_data->iface = iface;
570
571 ieee802154_init(iface);
572 }
573
574 static const struct ieee802154_radio_api ieee802154_cc13xx_cc26xx_radio_api = {
575 .iface_api.init = ieee802154_cc13xx_cc26xx_iface_init,
576
577 .get_capabilities = ieee802154_cc13xx_cc26xx_get_capabilities,
578 .cca = ieee802154_cc13xx_cc26xx_cca,
579 .set_channel = ieee802154_cc13xx_cc26xx_set_channel,
580 .filter = ieee802154_cc13xx_cc26xx_filter,
581 .set_txpower = ieee802154_cc13xx_cc26xx_set_txpower,
582 .tx = ieee802154_cc13xx_cc26xx_tx,
583 .start = ieee802154_cc13xx_cc26xx_start,
584 .stop = ieee802154_cc13xx_cc26xx_stop_if,
585 .configure = ieee802154_cc13xx_cc26xx_configure,
586 .attr_get = ieee802154_cc13xx_cc26xx_attr_get,
587 };
588
589 /** RF patches to use (note: RF core keeps a pointer to this, so no stack). */
590 static RF_Mode rf_mode = {
591 .rfMode = RF_MODE_MULTIPLE,
592 .cpePatchFxn = &rf_patch_cpe_multi_protocol,
593 };
594
ieee802154_cc13xx_cc26xx_init(const struct device * dev)595 static int ieee802154_cc13xx_cc26xx_init(const struct device *dev)
596 {
597 RF_Params rf_params;
598 RF_EventMask reason;
599 struct ieee802154_cc13xx_cc26xx_data *drv_data = dev->data;
600
601 /* Initialize driver data */
602 ieee802154_cc13xx_cc26xx_data_init(dev);
603
604 /* Setup radio */
605 RF_Params_init(&rf_params);
606 rf_params.pErrCb = client_error_callback;
607 rf_params.pClientEventCb = client_event_callback;
608
609 drv_data->rf_handle = RF_open(&drv_data->rf_object,
610 &rf_mode, (RF_RadioSetup *)&drv_data->cmd_radio_setup,
611 &rf_params);
612 if (drv_data->rf_handle == NULL) {
613 LOG_ERR("RF_open() failed");
614 return -EIO;
615 }
616
617 /*
618 * Run CMD_FS with frequency 0 to ensure RF_currClient is not NULL.
619 * RF_currClient is a static variable in the TI RF Driver library.
620 * If this is not done, then even CMD_ABORT fails.
621 */
622 drv_data->cmd_fs.status = IDLE;
623 drv_data->cmd_fs.pNextOp = NULL;
624 drv_data->cmd_fs.condition.rule = COND_NEVER;
625 drv_data->cmd_fs.synthConf.bTxMode = false;
626 drv_data->cmd_fs.frequency = 0;
627 drv_data->cmd_fs.fractFreq = 0;
628
629 reason = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_fs,
630 RF_PriorityNormal, NULL, 0);
631 if (reason != RF_EventLastCmdDone) {
632 LOG_ERR("Failed to set frequency: 0x%" PRIx64, reason);
633 return -EIO;
634 }
635
636 return 0;
637 }
638
639 static struct ieee802154_cc13xx_cc26xx_data ieee802154_cc13xx_cc26xx_data = {
640 .cmd_fs = {
641 .commandNo = CMD_FS,
642 },
643
644 .cmd_ieee_cca_req = {
645 .commandNo = CMD_IEEE_CCA_REQ,
646 },
647
648 .cmd_ieee_rx = {
649 .commandNo = CMD_IEEE_RX,
650 .status = IDLE,
651 .pNextOp = NULL,
652 .startTrigger.triggerType = TRIG_NOW,
653 .condition.rule = COND_NEVER,
654 .channel = 0,
655 .rxConfig = {
656 .bAutoFlushCrc = 1,
657 .bAutoFlushIgn = 1,
658 .bIncludePhyHdr = 0,
659 .bIncludeCrc = 1,
660 .bAppendRssi = 1,
661 .bAppendCorrCrc = 1,
662 .bAppendSrcInd = 0,
663 .bAppendTimestamp = 0
664 },
665 .pRxQ = &ieee802154_cc13xx_cc26xx_data.rx_queue,
666 .pOutput = NULL,
667 .frameFiltOpt = {
668 .frameFiltEn = 1,
669 .frameFiltStop = 0,
670 .autoAckEn = 1,
671 .slottedAckEn = 0,
672 .autoPendEn = 0,
673 .defaultPend = 0,
674 .bPendDataReqOnly = 0,
675 .bPanCoord = 0,
676 .maxFrameVersion = 3,
677 .fcfReservedMask = 0,
678 .modifyFtFilter = 0,
679 .bStrictLenFilter = 1
680 },
681 .frameTypes = {
682 .bAcceptFt0Beacon = 0,
683 .bAcceptFt1Data = 1,
684 .bAcceptFt2Ack = 0,
685 .bAcceptFt3MacCmd = 1,
686 .bAcceptFt4Reserved = 0,
687 .bAcceptFt5Reserved = 0,
688 .bAcceptFt6Reserved = 0,
689 .bAcceptFt7Reserved = 0
690 },
691 .ccaOpt = {
692 #if IEEE802154_PHY_CCA_MODE == 1
693 .ccaEnEnergy = 1,
694 .ccaEnCorr = 0,
695 #elif IEEE802154_PHY_CCA_MODE == 2
696 .ccaEnEnergy = 0,
697 .ccaEnCorr = 1,
698 #elif IEEE802154_PHY_CCA_MODE == 3
699 .ccaEnEnergy = 1,
700 .ccaEnCorr = 1,
701 #else
702 #error "Invalid CCA mode"
703 #endif
704 .ccaEnSync = 1,
705 .ccaSyncOp = 0,
706 .ccaCorrOp = 0,
707 .ccaCorrThr = 3,
708 },
709 /* See IEEE 802.15.4-2006 6.9.9*/
710 .ccaRssiThr = CC13XX_CC26XX_RECEIVER_SENSITIVITY + 10,
711 .numExtEntries = 0x00,
712 .numShortEntries = 0x00,
713 .pExtEntryList = NULL,
714 .pShortEntryList = NULL,
715 .localExtAddr = 0x0000000000000000,
716 .localShortAddr = 0x0000,
717 .localPanID = 0x0000,
718 .endTrigger.triggerType = TRIG_NEVER
719 },
720
721 .cmd_ieee_csma = {
722 .commandNo = CMD_IEEE_CSMA,
723 .status = IDLE,
724 .pNextOp = (rfc_radioOp_t *)&ieee802154_cc13xx_cc26xx_data.cmd_ieee_tx,
725 .startTrigger.triggerType = TRIG_NOW,
726 .condition.rule = COND_STOP_ON_FALSE,
727 .randomState = 0,
728 .macMaxBE =
729 CONFIG_IEEE802154_CC13XX_CC26XX_RADIO_CSMA_CA_MAX_BE,
730 .macMaxCSMABackoffs =
731 CONFIG_IEEE802154_CC13XX_CC26XX_RADIO_CSMA_CA_MAX_BO,
732 .csmaConfig = {
733 /* Initial value of CW for unslotted CSMA */
734 .initCW = 1,
735 /* Unslotted CSMA for non-beacon enabled PAN */
736 .bSlotted = 0,
737 /* RX stays on during CSMA backoffs */
738 .rxOffMode = 0,
739 },
740 .NB = 0,
741 .BE = CONFIG_IEEE802154_CC13XX_CC26XX_RADIO_CSMA_CA_MIN_BE,
742 .remainingPeriods = 0,
743 .endTrigger.triggerType = TRIG_NEVER,
744 },
745
746 .cmd_ieee_tx = {
747 .commandNo = CMD_IEEE_TX,
748 .status = IDLE,
749 .pNextOp = (rfc_radioOp_t *)&ieee802154_cc13xx_cc26xx_data.cmd_ieee_rx_ack,
750 .startTrigger.triggerType = TRIG_NOW,
751 .condition.rule = COND_NEVER,
752 .txOpt = {
753 /* Automatically insert PHY header */
754 .bIncludePhyHdr = 0x0,
755 /* Automatically append CRC */
756 .bIncludeCrc = 0x0,
757 /* Disable long frame testing */
758 .payloadLenMsb = 0x0,
759 },
760 .payloadLen = 0x0,
761 .pPayload = NULL,
762 },
763
764 .cmd_ieee_rx_ack = {
765 .commandNo = CMD_IEEE_RX_ACK,
766 .status = IDLE,
767 .pNextOp = NULL,
768 .startTrigger.triggerType = TRIG_NOW,
769 .condition.rule = COND_NEVER,
770 .seqNo = 0,
771 .endTrigger = {
772 .triggerType = TRIG_REL_START,
773 .pastTrig = 1,
774 },
775 .endTime = IEEE802154_MAC_ACK_WAIT_DURATION *
776 CC13XX_CC26XX_RAT_CYCLES_PER_SECOND /
777 IEEE802154_2450MHZ_OQPSK_SYMBOLS_PER_SECOND,
778 },
779
780 .cmd_radio_setup = {
781 #if defined(CONFIG_SOC_CC1352R) || defined(CONFIG_SOC_CC2652R) || \
782 defined(CONFIG_SOC_CC1352R7) || defined(CONFIG_SOC_CC2652R7)
783 .commandNo = CMD_RADIO_SETUP,
784 #elif defined(CONFIG_SOC_CC1352P) || defined(CONFIG_SOC_CC2652P) || \
785 defined(CONFIG_SOC_CC1352P7) || defined(CONFIG_SOC_CC2652P7)
786 .commandNo = CMD_RADIO_SETUP_PA,
787 #endif /* CONFIG_SOC_CCxx52x */
788 .status = IDLE,
789 .pNextOp = NULL,
790 .startTrigger.triggerType = TRIG_NOW,
791 .condition.rule = COND_NEVER,
792 .mode = 0x01, /* IEEE 802.15.4 */
793 .loDivider = 0x00,
794 .config = {
795 .frontEndMode = 0x0,
796 .biasMode = 0x0,
797 .analogCfgMode = 0x0,
798 .bNoFsPowerUp = 0x0,
799 },
800 .txPower = 0x2853, /* 0 dBm */
801 .pRegOverride = overrides
802 },
803 };
804
805 #if defined(CONFIG_NET_L2_IEEE802154)
806 #define L2 IEEE802154_L2
807 #define L2_CTX_TYPE NET_L2_GET_CTX_TYPE(IEEE802154_L2)
808 #define MTU IEEE802154_MTU
809 #elif defined(CONFIG_NET_L2_OPENTHREAD)
810 #define L2 OPENTHREAD_L2
811 #define L2_CTX_TYPE NET_L2_GET_CTX_TYPE(OPENTHREAD_L2)
812 #define MTU 1280
813 #endif
814
815 #if defined(CONFIG_NET_L2_IEEE802154) || defined(CONFIG_NET_L2_PHY_IEEE802154)
816 NET_DEVICE_DT_INST_DEFINE(0, ieee802154_cc13xx_cc26xx_init, NULL,
817 &ieee802154_cc13xx_cc26xx_data, NULL,
818 CONFIG_IEEE802154_CC13XX_CC26XX_INIT_PRIO,
819 &ieee802154_cc13xx_cc26xx_radio_api, L2,
820 L2_CTX_TYPE, MTU);
821 #else
822 DEVICE_DT_INST_DEFINE(0, ieee802154_cc13xx_cc26xx_init, NULL,
823 &ieee802154_cc13xx_cc26xx_data, NULL, POST_KERNEL,
824 CONFIG_IEEE802154_CC13XX_CC26XX_INIT_PRIO,
825 &ieee802154_cc13xx_cc26xx_radio_api);
826 #endif
827