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