| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | /* ieee802154_rf2xx.c - ATMEL RF2XX IEEE 802.15.4 Driver */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-25 11:13:24 -05:00
										 |  |  |  | #define DT_DRV_COMPAT atmel_rf2xx
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2020-01-26 14:57:24 -03:00
										 |  |  |  |  * Copyright (c) 2019-2020 Gerson Fernando Budke | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  |  * | 
					
						
							|  |  |  |  |  * SPDX-License-Identifier: Apache-2.0 | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #define LOG_MODULE_NAME ieee802154_rf2xx
 | 
					
						
							|  |  |  |  | #define LOG_LEVEL CONFIG_IEEE802154_DRIVER_LOG_LEVEL
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-06 10:25:46 +02:00
										 |  |  |  | #include <zephyr/logging/log.h>
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | LOG_MODULE_REGISTER(LOG_MODULE_NAME); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #include <errno.h>
 | 
					
						
							|  |  |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2022-07-27 18:00:25 +02:00
										 |  |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-06 10:25:46 +02:00
										 |  |  |  | #include <zephyr/kernel.h>
 | 
					
						
							|  |  |  |  | #include <zephyr/arch/cpu.h>
 | 
					
						
							|  |  |  |  | #include <zephyr/debug/stack.h>
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-06 10:25:46 +02:00
										 |  |  |  | #include <zephyr/device.h>
 | 
					
						
							|  |  |  |  | #include <zephyr/init.h>
 | 
					
						
							|  |  |  |  | #include <zephyr/net/net_if.h>
 | 
					
						
							|  |  |  |  | #include <zephyr/net/net_pkt.h>
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-06 10:25:46 +02:00
										 |  |  |  | #include <zephyr/sys/byteorder.h>
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2023-10-06 22:38:53 +00:00
										 |  |  |  | #include <zephyr/random/random.h>
 | 
					
						
							| 
									
										
										
										
											2022-05-06 10:25:46 +02:00
										 |  |  |  | #include <zephyr/linker/sections.h>
 | 
					
						
							|  |  |  |  | #include <zephyr/sys/atomic.h>
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-06 10:25:46 +02:00
										 |  |  |  | #include <zephyr/drivers/spi.h>
 | 
					
						
							|  |  |  |  | #include <zephyr/drivers/gpio.h>
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-06 10:25:46 +02:00
										 |  |  |  | #include <zephyr/net/ieee802154_radio.h>
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | #include "ieee802154_rf2xx.h"
 | 
					
						
							|  |  |  |  | #include "ieee802154_rf2xx_regs.h"
 | 
					
						
							|  |  |  |  | #include "ieee802154_rf2xx_iface.h"
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 16:29:45 -02:00
										 |  |  |  | #if defined(CONFIG_NET_L2_OPENTHREAD)
 | 
					
						
							| 
									
										
										
										
											2022-05-06 10:25:46 +02:00
										 |  |  |  | #include <zephyr/net/openthread.h>
 | 
					
						
							| 
									
										
										
										
											2020-01-08 16:29:45 -02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-20 21:55:09 -03:00
										 |  |  |  | #define RF2XX_OT_PSDU_LENGTH              1280
 | 
					
						
							| 
									
										
										
										
											2020-01-08 16:29:45 -02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-20 21:55:09 -03:00
										 |  |  |  | #define RF2XX_ACK_FRAME_LEN               3
 | 
					
						
							|  |  |  |  | #define RF2XX_ACK_FRAME_TYPE              (2 << 0)
 | 
					
						
							|  |  |  |  | #define RF2XX_ACK_FRAME_PENDING_BIT       (1 << 4)
 | 
					
						
							|  |  |  |  | #define RF2XX_FRAME_CTRL_ACK_REQUEST_BIT  (1 << 5)
 | 
					
						
							| 
									
										
										
										
											2020-01-08 16:29:45 -02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-27 11:26:57 -05:00
										 |  |  |  | static uint8_t rf2xx_ack_psdu[RF2XX_ACK_FRAME_LEN] = { 0 }; | 
					
						
							| 
									
										
										
										
											2020-01-08 16:29:45 -02:00
										 |  |  |  | static struct net_buf rf2xx_ack_frame = { | 
					
						
							|  |  |  |  | 	.data  = rf2xx_ack_psdu, | 
					
						
							|  |  |  |  | 	.size  = RF2XX_ACK_FRAME_LEN, | 
					
						
							|  |  |  |  | 	.len   = RF2XX_ACK_FRAME_LEN, | 
					
						
							|  |  |  |  | 	.__buf = rf2xx_ack_psdu, | 
					
						
							| 
									
										
										
										
											2020-03-20 21:55:09 -03:00
										 |  |  |  | 	.frags = NULL, | 
					
						
							| 
									
										
										
										
											2020-01-08 16:29:45 -02:00
										 |  |  |  | }; | 
					
						
							|  |  |  |  | static struct net_pkt rf2xx_ack_pkt = { | 
					
						
							|  |  |  |  | 	.buffer = &rf2xx_ack_frame, | 
					
						
							| 
									
										
										
										
											2022-10-12 18:19:54 +02:00
										 |  |  |  | 	.cb = { | 
					
						
							|  |  |  |  | 		.lqi = 80, | 
					
						
							|  |  |  |  | 		.rssi = -40, | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-08 16:29:45 -02:00
										 |  |  |  | }; | 
					
						
							|  |  |  |  | #endif /* CONFIG_NET_L2_OPENTHREAD */
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | /* Radio Transceiver ISR */ | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static inline void trx_isr_handler(const struct device *port, | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 				   struct gpio_callback *cb, | 
					
						
							| 
									
										
										
										
											2020-05-27 11:26:57 -05:00
										 |  |  |  | 				   uint32_t pins) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	struct rf2xx_context *ctx = CONTAINER_OF(cb, | 
					
						
							|  |  |  |  | 						 struct rf2xx_context, | 
					
						
							|  |  |  |  | 						 irq_cb); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	ARG_UNUSED(port); | 
					
						
							|  |  |  |  | 	ARG_UNUSED(pins); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	k_sem_give(&ctx->trx_isr_lock); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static void rf2xx_trx_set_state(const struct device *dev, | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 				enum rf2xx_trx_state_cmd_t state) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	do { | 
					
						
							|  |  |  |  | 		rf2xx_iface_reg_write(dev, RF2XX_TRX_STATE_REG, | 
					
						
							|  |  |  |  | 				      RF2XX_TRX_PHY_STATE_CMD_FORCE_TRX_OFF); | 
					
						
							|  |  |  |  | 	} while (RF2XX_TRX_PHY_STATUS_TRX_OFF != | 
					
						
							|  |  |  |  | 		 (rf2xx_iface_reg_read(dev, RF2XX_TRX_STATUS_REG) & | 
					
						
							|  |  |  |  | 		  RF2XX_TRX_PHY_STATUS_MASK)); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	do { | 
					
						
							|  |  |  |  | 		rf2xx_iface_reg_write(dev, RF2XX_TRX_STATE_REG, state); | 
					
						
							|  |  |  |  | 	} while (state != | 
					
						
							|  |  |  |  | 		 (rf2xx_iface_reg_read(dev, RF2XX_TRX_STATUS_REG) & | 
					
						
							|  |  |  |  | 		  RF2XX_TRX_PHY_STATUS_MASK)); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static void rf2xx_trx_set_tx_state(const struct device *dev) | 
					
						
							| 
									
										
										
										
											2020-01-26 14:57:24 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-27 11:26:57 -05:00
										 |  |  |  | 	uint8_t status; | 
					
						
							| 
									
										
										
										
											2020-01-26 14:57:24 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/**
 | 
					
						
							|  |  |  |  | 	 * Ensures that RX automatically ACK will be sent when requested. | 
					
						
							|  |  |  |  | 	 * Datasheet: Chapter 7.2.3 RX_AACK_ON – Receive with Automatic ACK | 
					
						
							|  |  |  |  | 	 * Datasheet: Figure 7-13. Timing Example of an RX_AACK Transaction | 
					
						
							|  |  |  |  | 	 * for Slotted Operation. | 
					
						
							| 
									
										
										
										
											2020-03-03 20:47:59 -03:00
										 |  |  |  | 	 * | 
					
						
							|  |  |  |  | 	 * This will create a spin lock that wait transceiver be free from | 
					
						
							|  |  |  |  | 	 * current receive frame process | 
					
						
							| 
									
										
										
										
											2020-01-26 14:57:24 -03:00
										 |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 	do { | 
					
						
							|  |  |  |  | 		status = (rf2xx_iface_reg_read(dev, RF2XX_TRX_STATUS_REG) & | 
					
						
							|  |  |  |  | 			  RF2XX_TRX_PHY_STATUS_MASK); | 
					
						
							|  |  |  |  | 	} while (status == RF2XX_TRX_PHY_STATUS_BUSY_RX_AACK || | 
					
						
							|  |  |  |  | 		 status == RF2XX_TRX_PHY_STATUS_STATE_TRANSITION); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-03 20:47:59 -03:00
										 |  |  |  | 	rf2xx_trx_set_state(dev, RF2XX_TRX_PHY_STATE_CMD_TRX_OFF); | 
					
						
							|  |  |  |  | 	rf2xx_iface_reg_read(dev, RF2XX_IRQ_STATUS_REG); | 
					
						
							| 
									
										
										
										
											2020-01-26 14:57:24 -03:00
										 |  |  |  | 	rf2xx_trx_set_state(dev, RF2XX_TRX_PHY_STATE_CMD_TX_ARET_ON); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static void rf2xx_trx_set_rx_state(const struct device *dev) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	rf2xx_trx_set_state(dev, RF2XX_TRX_PHY_STATE_CMD_TRX_OFF); | 
					
						
							|  |  |  |  | 	rf2xx_iface_reg_read(dev, RF2XX_IRQ_STATUS_REG); | 
					
						
							|  |  |  |  | 	/**
 | 
					
						
							|  |  |  |  | 	 * Set extended RX mode | 
					
						
							|  |  |  |  | 	 * Datasheet: chapter 7.2 Extended Operating Mode | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 	rf2xx_trx_set_state(dev, RF2XX_TRX_PHY_STATE_CMD_RX_AACK_ON); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | static void rf2xx_set_rssi_base(const struct device *dev, uint16_t channel) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	struct rf2xx_context *ctx = dev->data; | 
					
						
							|  |  |  |  | 	int8_t base; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | 	if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915) { | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 		base = channel == 0 | 
					
						
							|  |  |  |  | 				? RF2XX_RSSI_BPSK_20 | 
					
						
							|  |  |  |  | 				: RF2XX_RSSI_BPSK_40; | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | 	} else if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWO_OQPSK_868_915) { | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 		base = channel == 0 | 
					
						
							|  |  |  |  | 				? RF2XX_RSSI_OQPSK_SIN_RC_100 | 
					
						
							|  |  |  |  | 				: RF2XX_RSSI_OQPSK_SIN_250; | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		base = RF2XX_RSSI_OQPSK_RC_250; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	ctx->trx_rssi_base = base; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static void rf2xx_trx_rx(const struct device *dev) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-28 21:23:02 +02:00
										 |  |  |  | 	struct rf2xx_context *ctx = dev->data; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	struct net_pkt *pkt = NULL; | 
					
						
							| 
									
										
										
										
											2020-05-27 11:26:57 -05:00
										 |  |  |  | 	uint8_t rx_buf[RX2XX_MAX_FRAME_SIZE]; | 
					
						
							|  |  |  |  | 	uint8_t pkt_len; | 
					
						
							|  |  |  |  | 	uint8_t frame_len; | 
					
						
							|  |  |  |  | 	uint8_t trac; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * The rf2xx frame buffer can have length > 128 bytes. The | 
					
						
							| 
									
										
										
										
											2022-09-24 13:59:28 +02:00
										 |  |  |  | 	 * net_pkt_rx_alloc_with_buffer allocates max value of 128 bytes. | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	 * | 
					
						
							|  |  |  |  | 	 * This obligate the driver to have rx_buf statically allocated with | 
					
						
							|  |  |  |  | 	 * RX2XX_MAX_FRAME_SIZE. | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2020-01-26 14:57:24 -03:00
										 |  |  |  | 	if (ctx->trx_model != RF2XX_TRX_MODEL_231) { | 
					
						
							|  |  |  |  | 		pkt_len = ctx->rx_phr; | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		rf2xx_iface_frame_read(dev, rx_buf, RX2XX_FRAME_HEADER_SIZE); | 
					
						
							|  |  |  |  | 		pkt_len = rx_buf[RX2XX_FRAME_PHR_INDEX]; | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-24 17:57:28 +02:00
										 |  |  |  | 	if (!ctx->promiscuous && pkt_len < RX2XX_FRAME_MIN_PHR_SIZE) { | 
					
						
							| 
									
										
										
										
											2023-09-24 16:33:10 +02:00
										 |  |  |  | 		LOG_ERR("Invalid RX frame length"); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		return; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	frame_len = RX2XX_FRAME_HEADER_SIZE + pkt_len + | 
					
						
							|  |  |  |  | 		    RX2XX_FRAME_FOOTER_SIZE; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	rf2xx_iface_frame_read(dev, rx_buf, frame_len); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-24 16:33:10 +02:00
										 |  |  |  | 	if (ctx->trx_model != RF2XX_TRX_MODEL_231) { | 
					
						
							|  |  |  |  | 		trac = rx_buf[pkt_len + RX2XX_FRAME_TRAC_INDEX]; | 
					
						
							|  |  |  |  | 		trac = (trac >> RF2XX_RX_TRAC_STATUS) & RF2XX_RX_TRAC_BIT_MASK; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ctx->pkt_ed = rx_buf[pkt_len + RX2XX_FRAME_ED_INDEX]; | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		trac = (rf2xx_iface_reg_read(dev, RF2XX_TRX_STATE_REG) | 
					
						
							|  |  |  |  | 			>> RF2XX_TRAC_STATUS) & RF2XX_TRAC_BIT_MASK; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ctx->pkt_ed = (rf2xx_iface_reg_read(dev, RF2XX_PHY_RSSI_REG) | 
					
						
							|  |  |  |  | 			       >> RF2XX_RSSI) & RF2XX_RSSI_MASK; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	ctx->pkt_lqi = rx_buf[pkt_len + RX2XX_FRAME_LQI_INDEX]; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-24 17:57:28 +02:00
										 |  |  |  | 	if (!ctx->promiscuous && trac == RF2XX_TRX_PHY_STATE_TRAC_INVALID) { | 
					
						
							| 
									
										
										
										
											2023-09-24 16:33:10 +02:00
										 |  |  |  | 		LOG_ERR("Invalid RX frame"); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		return; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-11 14:26:26 +01:00
										 |  |  |  | 	if (!IS_ENABLED(CONFIG_IEEE802154_L2_PKT_INCL_FCS) && pkt_len >= RX2XX_FRAME_FCS_LENGTH) { | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		pkt_len -= RX2XX_FRAME_FCS_LENGTH; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-24 13:59:28 +02:00
										 |  |  |  | 	pkt = net_pkt_rx_alloc_with_buffer(ctx->iface, pkt_len, | 
					
						
							|  |  |  |  | 					   AF_UNSPEC, 0, K_NO_WAIT); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	if (!pkt) { | 
					
						
							| 
									
										
										
										
											2023-09-24 16:33:10 +02:00
										 |  |  |  | 		LOG_ERR("No RX buffer available"); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		return; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	memcpy(pkt->buffer->data, rx_buf + RX2XX_FRAME_HEADER_SIZE, pkt_len); | 
					
						
							|  |  |  |  | 	net_buf_add(pkt->buffer, pkt_len); | 
					
						
							|  |  |  |  | 	net_pkt_set_ieee802154_lqi(pkt, ctx->pkt_lqi); | 
					
						
							| 
									
										
										
										
											2023-06-11 14:32:55 +02:00
										 |  |  |  | 	net_pkt_set_ieee802154_rssi_dbm(pkt, ctx->pkt_ed + ctx->trx_rssi_base); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	LOG_DBG("Caught a packet (%02X) (LQI: %02X, RSSI: %d, ED: %02X)", | 
					
						
							|  |  |  |  | 		pkt_len, ctx->pkt_lqi, ctx->trx_rssi_base + ctx->pkt_ed, | 
					
						
							|  |  |  |  | 		ctx->pkt_ed); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (net_recv_data(ctx->iface, pkt) < 0) { | 
					
						
							| 
									
										
										
										
											2023-09-24 16:33:10 +02:00
										 |  |  |  | 		LOG_DBG("RX Packet dropped by NET stack"); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		net_pkt_unref(pkt); | 
					
						
							|  |  |  |  | 		return; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (LOG_LEVEL >= LOG_LEVEL_DBG) { | 
					
						
							| 
									
										
										
										
											2020-03-12 14:18:42 -07:00
										 |  |  |  | 		log_stack_usage(&ctx->trx_thread); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-03-04 19:11:41 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static void rf2xx_process_rx_frame(const struct device *dev) | 
					
						
							| 
									
										
										
										
											2020-03-04 19:11:41 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-28 21:23:02 +02:00
										 |  |  |  | 	struct rf2xx_context *ctx = dev->data; | 
					
						
							| 
									
										
										
										
											2020-03-04 19:11:41 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-21 19:43:26 -03:00
										 |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * NOTE: In promiscuous mode invalid frames will be processed. | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-26 14:57:24 -03:00
										 |  |  |  | 	if (ctx->trx_model != RF2XX_TRX_MODEL_231) { | 
					
						
							|  |  |  |  | 		rf2xx_trx_rx(dev); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		/* Ensures that automatically ACK will be sent
 | 
					
						
							|  |  |  |  | 		 * when requested | 
					
						
							|  |  |  |  | 		 */ | 
					
						
							|  |  |  |  | 		while (rf2xx_iface_reg_read(dev, RF2XX_TRX_STATUS_REG) == | 
					
						
							|  |  |  |  | 		       RF2XX_TRX_PHY_STATUS_BUSY_RX_AACK) { | 
					
						
							|  |  |  |  | 			; | 
					
						
							| 
									
										
										
										
											2021-03-24 16:39:15 -07:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-01-26 14:57:24 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		/* Set PLL_ON to avoid transceiver receive
 | 
					
						
							|  |  |  |  | 		 * new data until finish reading process | 
					
						
							|  |  |  |  | 		 */ | 
					
						
							|  |  |  |  | 		rf2xx_trx_set_state(dev, RF2XX_TRX_PHY_STATE_CMD_PLL_ON); | 
					
						
							|  |  |  |  | 		rf2xx_trx_rx(dev); | 
					
						
							|  |  |  |  | 		rf2xx_trx_set_state(dev, RF2XX_TRX_PHY_STATE_CMD_RX_AACK_ON); | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-04 19:11:41 -03:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static void rf2xx_process_tx_frame(const struct device *dev) | 
					
						
							| 
									
										
										
										
											2020-03-04 19:11:41 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-28 21:23:02 +02:00
										 |  |  |  | 	struct rf2xx_context *ctx = dev->data; | 
					
						
							| 
									
										
										
										
											2020-03-04 19:11:41 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	ctx->trx_trac = (rf2xx_iface_reg_read(dev, RF2XX_TRX_STATE_REG) >> | 
					
						
							| 
									
										
										
										
											2023-01-31 15:49:56 +02:00
										 |  |  |  | 			 RF2XX_TRAC_STATUS) & RF2XX_TRAC_BIT_MASK; | 
					
						
							| 
									
										
										
										
											2020-03-04 19:11:41 -03:00
										 |  |  |  | 	k_sem_give(&ctx->trx_tx_sync); | 
					
						
							|  |  |  |  | 	rf2xx_trx_set_rx_state(dev); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static void rf2xx_process_trx_end(const struct device *dev) | 
					
						
							| 
									
										
										
										
											2020-03-04 19:11:41 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-27 11:26:57 -05:00
										 |  |  |  | 	uint8_t trx_status = (rf2xx_iface_reg_read(dev, RF2XX_TRX_STATUS_REG) & | 
					
						
							| 
									
										
										
										
											2020-03-03 20:47:59 -03:00
										 |  |  |  | 			   RF2XX_TRX_PHY_STATUS_MASK); | 
					
						
							| 
									
										
										
										
											2020-03-04 19:11:41 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-03 20:47:59 -03:00
										 |  |  |  | 	if (trx_status == RF2XX_TRX_PHY_STATUS_TX_ARET_ON) { | 
					
						
							| 
									
										
										
										
											2020-03-04 19:11:41 -03:00
										 |  |  |  | 		rf2xx_process_tx_frame(dev); | 
					
						
							| 
									
										
										
										
											2020-03-03 20:47:59 -03:00
										 |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		rf2xx_process_rx_frame(dev); | 
					
						
							| 
									
										
										
										
											2020-03-04 19:11:41 -03:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-21 09:35:29 +02:00
										 |  |  |  | static void rf2xx_thread_main(void *p1, void *p2, void *p3) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-09-21 09:35:29 +02:00
										 |  |  |  | 	ARG_UNUSED(p2); | 
					
						
							|  |  |  |  | 	ARG_UNUSED(p3); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	struct rf2xx_context *ctx = p1; | 
					
						
							| 
									
										
										
										
											2020-05-27 11:26:57 -05:00
										 |  |  |  | 	uint8_t isr_status; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	while (true) { | 
					
						
							|  |  |  |  | 		k_sem_take(&ctx->trx_isr_lock, K_FOREVER); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-08 11:31:38 +02:00
										 |  |  |  | 		isr_status = rf2xx_iface_reg_read(ctx->dev, | 
					
						
							|  |  |  |  | 						  RF2XX_IRQ_STATUS_REG); | 
					
						
							| 
									
										
										
										
											2020-03-03 20:47:59 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		/*
 | 
					
						
							|  |  |  |  | 		 *  IRQ_7 (BAT_LOW) Indicates a supply voltage below the | 
					
						
							|  |  |  |  | 		 *    programmed threshold. 9.5.4 | 
					
						
							|  |  |  |  | 		 *  IRQ_6 (TRX_UR) Indicates a Frame Buffer access | 
					
						
							|  |  |  |  | 		 *    violation. 9.3.3 | 
					
						
							|  |  |  |  | 		 *  IRQ_5 (AMI) Indicates address matching. 8.2 | 
					
						
							|  |  |  |  | 		 *  IRQ_4 (CCA_ED_DONE) Multi-functional interrupt: | 
					
						
							|  |  |  |  | 		 *   1. AWAKE_END: 7.1.2.5 | 
					
						
							|  |  |  |  | 		 *      • Indicates finished transition to TRX_OFF state | 
					
						
							|  |  |  |  | 		 *        from P_ON, SLEEP, DEEP_SLEEP, or RESET state. | 
					
						
							|  |  |  |  | 		 *   2. CCA_ED_DONE: 8.5.4 | 
					
						
							|  |  |  |  | 		 *      • Indicates the end of a CCA or ED | 
					
						
							|  |  |  |  | 		 *        measurement. 8.6.4 | 
					
						
							|  |  |  |  | 		 *  IRQ_3 (TRX_END) | 
					
						
							|  |  |  |  | 		 *    RX: Indicates the completion of a frame | 
					
						
							|  |  |  |  | 		 *      reception. 7.1.3 | 
					
						
							|  |  |  |  | 		 *    TX: Indicates the completion of a frame | 
					
						
							|  |  |  |  | 		 *      transmission. 7.1.3 | 
					
						
							|  |  |  |  | 		 *  IRQ_2 (RX_START) Indicates the start of a PSDU | 
					
						
							|  |  |  |  | 		 *    reception; the AT86RF233 state changed to BUSY_RX; | 
					
						
							|  |  |  |  | 		 *    the PHR can be read from Frame Buffer. 7.1.3 | 
					
						
							|  |  |  |  | 		 *  IRQ_1 (PLL_UNLOCK) Indicates PLL unlock. If the radio | 
					
						
							|  |  |  |  | 		 *    transceiver is in BUSY_TX / BUSY_TX_ARET state, the | 
					
						
							|  |  |  |  | 		 *    PA is turned off immediately. 9.7.5 | 
					
						
							|  |  |  |  | 		 *  IRQ_0 (PLL_LOCK) Indicates PLL lock. | 
					
						
							|  |  |  |  | 		 */ | 
					
						
							|  |  |  |  | 		if (isr_status & (1 << RF2XX_RX_START)) { | 
					
						
							| 
									
										
										
										
											2020-01-26 14:57:24 -03:00
										 |  |  |  | 			if (ctx->trx_model != RF2XX_TRX_MODEL_231) { | 
					
						
							| 
									
										
										
										
											2020-07-08 11:31:38 +02:00
										 |  |  |  | 				rf2xx_iface_sram_read(ctx->dev, 0, | 
					
						
							|  |  |  |  | 						      &ctx->rx_phr, 1); | 
					
						
							| 
									
										
										
										
											2020-01-26 14:57:24 -03:00
										 |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2023-01-21 19:55:29 +01:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if (isr_status & (1 << RF2XX_TRX_END)) { | 
					
						
							| 
									
										
										
										
											2020-07-08 11:31:38 +02:00
										 |  |  |  | 			rf2xx_process_trx_end(ctx->dev); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static inline uint8_t *get_mac(const struct device *dev) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-28 20:44:16 +02:00
										 |  |  |  | 	const struct rf2xx_config *conf = dev->config; | 
					
						
							| 
									
										
										
										
											2020-05-28 21:23:02 +02:00
										 |  |  |  | 	struct rf2xx_context *ctx = dev->data; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-03 22:37:13 -03:00
										 |  |  |  | 	if (!conf->has_mac) { | 
					
						
							| 
									
										
										
										
											2024-04-03 11:38:07 +02:00
										 |  |  |  | 		sys_rand_get(ctx->mac_addr, sizeof(ctx->mac_addr)); | 
					
						
							| 
									
										
										
										
											2020-03-03 22:37:13 -03:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * Clear bit 0 to ensure it isn't a multicast address and set | 
					
						
							| 
									
										
										
										
											2020-04-23 23:54:30 -03:00
										 |  |  |  | 	 * bit 1 to indicate address is locally administered and may | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	 * not be globally unique. | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 	ctx->mac_addr[0] = (ctx->mac_addr[0] & ~0x01) | 0x02; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return ctx->mac_addr; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static enum ieee802154_hw_caps rf2xx_get_capabilities(const struct device *dev) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 	LOG_DBG("HW Caps"); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return IEEE802154_HW_FCS | | 
					
						
							|  |  |  |  | 	       IEEE802154_HW_PROMISC | | 
					
						
							|  |  |  |  | 	       IEEE802154_HW_FILTER | | 
					
						
							|  |  |  |  | 	       IEEE802154_HW_CSMA | | 
					
						
							| 
									
										
										
										
											2023-06-03 19:31:31 +02:00
										 |  |  |  | 	       IEEE802154_HW_RETRANSMISSION | | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	       IEEE802154_HW_TX_RX_ACK | | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | 	       IEEE802154_HW_RX_TX_ACK; | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static int rf2xx_configure_sub_channel(const struct device *dev, uint16_t channel) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	struct rf2xx_context *ctx = dev->data; | 
					
						
							|  |  |  |  | 	uint8_t reg; | 
					
						
							|  |  |  |  | 	uint8_t cc_mask; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | 	if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915) { | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 		cc_mask = channel == 0 | 
					
						
							|  |  |  |  | 				   ? RF2XX_CC_BPSK_20 | 
					
						
							|  |  |  |  | 				   : RF2XX_CC_BPSK_40; | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | 	} else if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWO_OQPSK_868_915) { | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 		cc_mask = channel == 0 | 
					
						
							|  |  |  |  | 				   ? RF2XX_CC_OQPSK_SIN_RC_100 | 
					
						
							|  |  |  |  | 				   : RF2XX_CC_OQPSK_SIN_250; | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		cc_mask = RF2XX_CC_OQPSK_RC_250; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	reg = rf2xx_iface_reg_read(dev, RF2XX_TRX_CTRL_2_REG) | 
					
						
							|  |  |  |  | 	    & ~RF2XX_SUB_CHANNEL_MASK; | 
					
						
							|  |  |  |  | 	rf2xx_iface_reg_write(dev, RF2XX_TRX_CTRL_2_REG, reg | cc_mask); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return 0; | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | static int rf2xx_configure_trx_path(const struct device *dev) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	struct rf2xx_context *ctx = dev->data; | 
					
						
							|  |  |  |  | 	uint8_t reg; | 
					
						
							|  |  |  |  | 	uint8_t gc_tx_offset; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | 	if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915) { | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 		gc_tx_offset = 0x03; | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		gc_tx_offset = 0x02; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	reg = rf2xx_iface_reg_read(dev, RF2XX_RF_CTRL_0_REG) | 
					
						
							|  |  |  |  | 	    & ~RF2XX_GC_TX_OFFS_MASK; | 
					
						
							|  |  |  |  | 	rf2xx_iface_reg_write(dev, RF2XX_RF_CTRL_0_REG, reg | gc_tx_offset); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static int rf2xx_cca(const struct device *dev) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	ARG_UNUSED(dev); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 	LOG_DBG("CCA"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	return 0; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static int rf2xx_set_channel(const struct device *dev, uint16_t channel) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 	struct rf2xx_context *ctx = dev->data; | 
					
						
							| 
									
										
										
										
											2020-05-27 11:26:57 -05:00
										 |  |  |  | 	uint8_t reg; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 	LOG_DBG("Set Channel %d", channel); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (ctx->trx_model == RF2XX_TRX_MODEL_212) { | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | 		if ((ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915 | 
					
						
							|  |  |  |  | 		     || ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWO_OQPSK_868_915) | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 		    && channel > 10) { | 
					
						
							|  |  |  |  | 			LOG_ERR("Unsupported channel %u", channel); | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | 			return channel > 26 ? -EINVAL : -ENOTSUP; | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | 		if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_FIVE_OQPSK_780 && | 
					
						
							|  |  |  |  | 		    channel > 3) { | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 			LOG_ERR("Unsupported channel %u", channel); | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | 			return channel > 7 ? -EINVAL : -ENOTSUP; | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		rf2xx_configure_sub_channel(dev, channel); | 
					
						
							|  |  |  |  | 		rf2xx_configure_trx_path(dev); | 
					
						
							|  |  |  |  | 		rf2xx_set_rssi_base(dev, channel); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | 		/* 2.4G O-QPSK, channel page zero */ | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 		if (channel < 11 || channel > 26) { | 
					
						
							|  |  |  |  | 			LOG_ERR("Unsupported channel %u", channel); | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | 			return channel < 11 ? -ENOTSUP : -EINVAL; | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	reg = rf2xx_iface_reg_read(dev, RF2XX_PHY_CC_CCA_REG) & ~0x1f; | 
					
						
							|  |  |  |  | 	rf2xx_iface_reg_write(dev, RF2XX_PHY_CC_CCA_REG, reg | channel); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return 0; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static int rf2xx_set_txpower(const struct device *dev, int16_t dbm) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-07-27 18:00:25 +02:00
										 |  |  |  | 	const struct rf2xx_config *conf = dev->config; | 
					
						
							|  |  |  |  | 	struct rf2xx_context *ctx = dev->data; | 
					
						
							|  |  |  |  | 	float min, max, step; | 
					
						
							|  |  |  |  | 	uint8_t reg; | 
					
						
							|  |  |  |  | 	uint8_t idx; | 
					
						
							|  |  |  |  | 	uint8_t val; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	LOG_DBG("Try set Power to %d", dbm); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/**
 | 
					
						
							|  |  |  |  | 	 * if table size is equal 1 the code assumes a table was not defined. In | 
					
						
							|  |  |  |  | 	 * this case the transceiver PHY_TX_PWR register will be set with value | 
					
						
							|  |  |  |  | 	 * zero. This is a safe value for all variants and represents an output | 
					
						
							|  |  |  |  | 	 * power above 0 dBm. | 
					
						
							|  |  |  |  | 	 * | 
					
						
							|  |  |  |  | 	 * Note: This is a special case too which avoid division by zero when | 
					
						
							|  |  |  |  | 	 * computing the step variable. | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 	if (conf->tx_pwr_table_size == 1) { | 
					
						
							|  |  |  |  | 		rf2xx_iface_reg_write(dev, RF2XX_PHY_TX_PWR_REG, 0); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		return 0; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	min = conf->tx_pwr_min[1]; | 
					
						
							|  |  |  |  | 	if (conf->tx_pwr_min[0] == 0x01) { | 
					
						
							| 
									
										
										
										
											2023-04-25 19:19:18 -07:00
										 |  |  |  | 		min *= -1.0f; | 
					
						
							| 
									
										
										
										
											2022-07-27 18:00:25 +02:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	max = conf->tx_pwr_max[1]; | 
					
						
							|  |  |  |  | 	if (conf->tx_pwr_max[0] == 0x01) { | 
					
						
							| 
									
										
										
										
											2023-04-25 19:19:18 -07:00
										 |  |  |  | 		min *= -1.0f; | 
					
						
							| 
									
										
										
										
											2022-07-27 18:00:25 +02:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 19:19:18 -07:00
										 |  |  |  | 	step = (max - min) / ((float)conf->tx_pwr_table_size - 1.0f); | 
					
						
							| 
									
										
										
										
											2022-07-27 18:00:25 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 19:19:18 -07:00
										 |  |  |  | 	if (step == 0.0f) { | 
					
						
							|  |  |  |  | 		step = 1.0f; | 
					
						
							| 
									
										
										
										
											2022-07-27 18:00:25 +02:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	LOG_DBG("Tx-power values: min %f, max %f, step %f, entries %d", | 
					
						
							| 
									
										
										
										
											2023-04-25 19:19:18 -07:00
										 |  |  |  | 		(double)min, (double)max, (double)step, conf->tx_pwr_table_size); | 
					
						
							| 
									
										
										
										
											2022-07-27 18:00:25 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (dbm < min) { | 
					
						
							|  |  |  |  | 		LOG_INF("TX-power %d dBm below min of %f dBm, using %f dBm", | 
					
						
							| 
									
										
										
										
											2023-04-25 19:19:18 -07:00
										 |  |  |  | 			dbm, (double)min, (double)max); | 
					
						
							| 
									
										
										
										
											2022-07-27 18:00:25 +02:00
										 |  |  |  | 		dbm = min; | 
					
						
							|  |  |  |  | 	} else if (dbm > max) { | 
					
						
							|  |  |  |  | 		LOG_INF("TX-power %d dBm above max of %f dBm, using %f dBm", | 
					
						
							| 
									
										
										
										
											2023-04-25 19:19:18 -07:00
										 |  |  |  | 			dbm, (double)min, (double)max); | 
					
						
							| 
									
										
										
										
											2022-07-27 18:00:25 +02:00
										 |  |  |  | 		dbm = max; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-30 11:40:42 -07:00
										 |  |  |  | 	idx = abs((int) (((float)(dbm - max) / step))); | 
					
						
							| 
									
										
										
										
											2022-07-27 18:00:25 +02:00
										 |  |  |  | 	LOG_DBG("Tx-power idx: %d", idx); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (idx >= conf->tx_pwr_table_size) { | 
					
						
							|  |  |  |  | 		idx = conf->tx_pwr_table_size - 1; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	val = conf->tx_pwr_table[idx]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (ctx->trx_model != RF2XX_TRX_MODEL_212) { | 
					
						
							|  |  |  |  | 		reg = rf2xx_iface_reg_read(dev, RF2XX_PHY_TX_PWR_REG) & 0xf0; | 
					
						
							|  |  |  |  | 		val = reg + (val & 0x0f); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	LOG_DBG("Tx-power normalized: %d dBm, PHY_TX_PWR 0x%02x, idx %d", | 
					
						
							|  |  |  |  | 		dbm, val, idx); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	rf2xx_iface_reg_write(dev, RF2XX_PHY_TX_PWR_REG, val); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return 0; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static int rf2xx_set_ieee_addr(const struct device *dev, bool set, | 
					
						
							| 
									
										
										
										
											2020-05-27 11:26:57 -05:00
										 |  |  |  | 			       const uint8_t *ieee_addr) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-27 11:26:57 -05:00
										 |  |  |  | 	const uint8_t *ptr_to_reg = ieee_addr; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	LOG_DBG("IEEE address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", | 
					
						
							|  |  |  |  | 		ieee_addr[7], ieee_addr[6], ieee_addr[5], ieee_addr[4], | 
					
						
							|  |  |  |  | 		ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0]); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (set) { | 
					
						
							| 
									
										
										
										
											2020-05-27 11:26:57 -05:00
										 |  |  |  | 		for (uint8_t i = 0; i < 8; i++, ptr_to_reg++) { | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 			rf2xx_iface_reg_write(dev, (RF2XX_IEEE_ADDR_0_REG + i), | 
					
						
							|  |  |  |  | 					      *ptr_to_reg); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2020-05-27 11:26:57 -05:00
										 |  |  |  | 		for (uint8_t i = 0; i < 8; i++) { | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 			rf2xx_iface_reg_write(dev, (RF2XX_IEEE_ADDR_0_REG + i), | 
					
						
							|  |  |  |  | 					      0); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return 0; | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-06-08 15:47:32 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static int rf2xx_set_short_addr(const struct device *dev, bool set, | 
					
						
							| 
									
										
										
										
											2020-05-27 11:26:57 -05:00
										 |  |  |  | 				uint16_t short_addr) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-27 11:26:57 -05:00
										 |  |  |  | 	uint8_t short_addr_le[2] = { 0xFF, 0xFF }; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (set) { | 
					
						
							|  |  |  |  | 		sys_put_le16(short_addr, short_addr_le); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	rf2xx_iface_reg_write(dev, RF2XX_SHORT_ADDR_0_REG, short_addr_le[0]); | 
					
						
							|  |  |  |  | 	rf2xx_iface_reg_write(dev, RF2XX_SHORT_ADDR_1_REG, short_addr_le[1]); | 
					
						
							|  |  |  |  | 	rf2xx_iface_reg_write(dev, RF2XX_CSMA_SEED_0_REG, | 
					
						
							|  |  |  |  | 			      short_addr_le[0] + short_addr_le[1]); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	LOG_DBG("Short Address: 0x%02X%02X", short_addr_le[1], | 
					
						
							|  |  |  |  | 		short_addr_le[0]); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return 0; | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-06-08 15:47:32 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static int rf2xx_set_pan_id(const struct device *dev, bool set, | 
					
						
							|  |  |  |  | 			    uint16_t pan_id) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-27 11:26:57 -05:00
										 |  |  |  | 	uint8_t pan_id_le[2] = { 0xFF, 0xFF }; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (set) { | 
					
						
							|  |  |  |  | 		sys_put_le16(pan_id, pan_id_le); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	rf2xx_iface_reg_write(dev, RF2XX_PAN_ID_0_REG, pan_id_le[0]); | 
					
						
							|  |  |  |  | 	rf2xx_iface_reg_write(dev, RF2XX_PAN_ID_1_REG, pan_id_le[1]); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	LOG_DBG("Pan Id: 0x%02X%02X", pan_id_le[1], pan_id_le[0]); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return 0; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static int rf2xx_filter(const struct device *dev, | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 			bool set, enum ieee802154_filter_type type, | 
					
						
							|  |  |  |  | 			const struct ieee802154_filter *filter) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	LOG_DBG("Applying filter %u", type); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (type == IEEE802154_FILTER_TYPE_IEEE_ADDR) { | 
					
						
							|  |  |  |  | 		return rf2xx_set_ieee_addr(dev, set, filter->ieee_addr); | 
					
						
							|  |  |  |  | 	} else if (type == IEEE802154_FILTER_TYPE_SHORT_ADDR) { | 
					
						
							|  |  |  |  | 		return rf2xx_set_short_addr(dev, set, filter->short_addr); | 
					
						
							|  |  |  |  | 	} else if (type == IEEE802154_FILTER_TYPE_PAN_ID) { | 
					
						
							|  |  |  |  | 		return rf2xx_set_pan_id(dev, set, filter->pan_id); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return -ENOTSUP; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 16:29:45 -02:00
										 |  |  |  | #if defined(CONFIG_NET_L2_OPENTHREAD)
 | 
					
						
							| 
									
										
										
										
											2020-03-20 21:55:09 -03:00
										 |  |  |  | static void rf2xx_handle_ack(struct rf2xx_context *ctx, struct net_buf *frag) | 
					
						
							| 
									
										
										
										
											2020-01-08 16:29:45 -02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-20 21:55:09 -03:00
										 |  |  |  | 	if ((frag->data[0] & RF2XX_FRAME_CTRL_ACK_REQUEST_BIT) == 0) { | 
					
						
							|  |  |  |  | 		return; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-17 14:53:01 +01:00
										 |  |  |  | 	rf2xx_ack_psdu[0] = RF2XX_ACK_FRAME_TYPE; | 
					
						
							| 
									
										
										
										
											2020-03-20 21:55:09 -03:00
										 |  |  |  | 	rf2xx_ack_psdu[2] = frag->data[2]; | 
					
						
							| 
									
										
										
										
											2020-01-08 16:29:45 -02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (ctx->trx_trac == RF2XX_TRX_PHY_STATE_TRAC_SUCCESS_DATA_PENDING) { | 
					
						
							| 
									
										
										
										
											2020-03-17 14:53:01 +01:00
										 |  |  |  | 		rf2xx_ack_psdu[0] |= RF2XX_ACK_FRAME_PENDING_BIT; | 
					
						
							| 
									
										
										
										
											2020-01-08 16:29:45 -02:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-20 21:55:09 -03:00
										 |  |  |  | 	net_pkt_cursor_init(&rf2xx_ack_pkt); | 
					
						
							| 
									
										
										
										
											2020-01-08 16:29:45 -02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-02 19:56:49 +02:00
										 |  |  |  | 	if (ieee802154_handle_ack(ctx->iface, &rf2xx_ack_pkt) != NET_OK) { | 
					
						
							| 
									
										
										
										
											2020-01-08 16:29:45 -02:00
										 |  |  |  | 		LOG_INF("ACK packet not handled."); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | #else
 | 
					
						
							|  |  |  |  | 	#define rf2xx_handle_ack(...)
 | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static int rf2xx_tx(const struct device *dev, | 
					
						
							| 
									
										
										
											
												net: ieee802154_radio: Allow to specify TX mode
Even though radio driver can report in its capabilities that it does
support CSMA CA, there's no way in the driver to select how the frame
should be transmitted (with CSMA or without). As layers above radio
driver (Thread, Zigbee) can expect that both TX modes are available, we
need to extend the API to allow either of these modes.
This commits extends the API `tx` function with an extra parameter,
`ieee802154_tx_mode`, which informs the driver how the packet should be
transmitted. Currently, the following modes are specified:
* direct (regular tx, no cca, just how it worked so far),
* CCA before transmission,
* CSMA CA before transmission,
* delayed TX,
* delayed TX with CCA
Assume that radios that reported CSMA CA capability transmit in CSMA CA
mode by default, all others will support direct mode.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
											
										 
											2020-02-28 13:57:49 +01:00
										 |  |  |  | 		    enum ieee802154_tx_mode mode, | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		    struct net_pkt *pkt, | 
					
						
							|  |  |  |  | 		    struct net_buf *frag) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-01-08 16:29:45 -02:00
										 |  |  |  | 	ARG_UNUSED(pkt); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-28 21:23:02 +02:00
										 |  |  |  | 	struct rf2xx_context *ctx = dev->data; | 
					
						
							| 
									
										
										
										
											2020-01-08 16:29:45 -02:00
										 |  |  |  | 	int response = 0; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 	LOG_DBG("TX"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-21 19:02:34 -03:00
										 |  |  |  | 	if (ctx->tx_mode != mode) { | 
					
						
							|  |  |  |  | 		switch (mode) { | 
					
						
							|  |  |  |  | 		case IEEE802154_TX_MODE_DIRECT: | 
					
						
							|  |  |  |  | 			/* skip retries & csma/ca algorithm */ | 
					
						
							|  |  |  |  | 			rf2xx_iface_reg_write(dev, RF2XX_XAH_CTRL_0_REG, 0x0E); | 
					
						
							|  |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		case IEEE802154_TX_MODE_CSMA_CA: | 
					
						
							|  |  |  |  | 			/* backoff maxBE = 5, minBE = 3 */ | 
					
						
							|  |  |  |  | 			rf2xx_iface_reg_write(dev, RF2XX_CSMA_BE_REG, 0x53); | 
					
						
							|  |  |  |  | 			/* max frame retries = 3, csma/ca retries = 4 */ | 
					
						
							|  |  |  |  | 			rf2xx_iface_reg_write(dev, RF2XX_XAH_CTRL_0_REG, 0x38); | 
					
						
							|  |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		case IEEE802154_TX_MODE_CCA: | 
					
						
							| 
									
										
										
										
											2020-11-21 20:21:35 -03:00
										 |  |  |  | 			/* backoff period = 0 */ | 
					
						
							|  |  |  |  | 			rf2xx_iface_reg_write(dev, RF2XX_CSMA_BE_REG, 0x00); | 
					
						
							|  |  |  |  | 			/* no frame retries & no csma/ca retries */ | 
					
						
							|  |  |  |  | 			rf2xx_iface_reg_write(dev, RF2XX_XAH_CTRL_0_REG, 0x00); | 
					
						
							|  |  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2020-11-21 19:02:34 -03:00
										 |  |  |  | 		case IEEE802154_TX_MODE_TXTIME: | 
					
						
							|  |  |  |  | 		case IEEE802154_TX_MODE_TXTIME_CCA: | 
					
						
							|  |  |  |  | 		default: | 
					
						
							|  |  |  |  | 			NET_ERR("TX mode %d not supported", mode); | 
					
						
							|  |  |  |  | 			return -ENOTSUP; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ctx->tx_mode = mode; | 
					
						
							| 
									
										
										
											
												net: ieee802154_radio: Allow to specify TX mode
Even though radio driver can report in its capabilities that it does
support CSMA CA, there's no way in the driver to select how the frame
should be transmitted (with CSMA or without). As layers above radio
driver (Thread, Zigbee) can expect that both TX modes are available, we
need to extend the API to allow either of these modes.
This commits extends the API `tx` function with an extra parameter,
`ieee802154_tx_mode`, which informs the driver how the packet should be
transmitted. Currently, the following modes are specified:
* direct (regular tx, no cca, just how it worked so far),
* CCA before transmission,
* CSMA CA before transmission,
* delayed TX,
* delayed TX with CCA
Assume that radios that reported CSMA CA capability transmit in CSMA CA
mode by default, all others will support direct mode.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
											
										 
											2020-02-28 13:57:49 +01:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-03 20:47:59 -03:00
										 |  |  |  | 	rf2xx_trx_set_tx_state(dev); | 
					
						
							|  |  |  |  | 	rf2xx_iface_reg_read(dev, RF2XX_IRQ_STATUS_REG); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-03 20:47:59 -03:00
										 |  |  |  | 	k_sem_reset(&ctx->trx_tx_sync); | 
					
						
							|  |  |  |  | 	rf2xx_iface_frame_write(dev, frag->data, frag->len); | 
					
						
							|  |  |  |  | 	rf2xx_iface_phy_tx_start(dev); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	k_sem_take(&ctx->trx_tx_sync, K_FOREVER); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	switch (ctx->trx_trac) { | 
					
						
							|  |  |  |  | 	/* Channel is still busy after attempting MAX_CSMA_RETRIES of
 | 
					
						
							|  |  |  |  | 	 * CSMA-CA | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 	case RF2XX_TRX_PHY_STATE_TRAC_CHANNEL_ACCESS_FAILED: | 
					
						
							|  |  |  |  | 		response = -EBUSY; | 
					
						
							|  |  |  |  | 		break; | 
					
						
							|  |  |  |  | 	/* No acknowledgment frames were received during all retry
 | 
					
						
							|  |  |  |  | 	 * attempts | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 	case RF2XX_TRX_PHY_STATE_TRAC_NO_ACK: | 
					
						
							|  |  |  |  | 		response = -EAGAIN; | 
					
						
							|  |  |  |  | 		break; | 
					
						
							|  |  |  |  | 	/* Transaction not yet finished */ | 
					
						
							|  |  |  |  | 	case RF2XX_TRX_PHY_STATE_TRAC_INVALID: | 
					
						
							|  |  |  |  | 		response = -EINTR; | 
					
						
							|  |  |  |  | 		break; | 
					
						
							|  |  |  |  | 	/* RF2XX_TRX_PHY_STATE_TRAC_SUCCESS:
 | 
					
						
							|  |  |  |  | 	 *  The transaction was responded to by a valid ACK, or, if no | 
					
						
							|  |  |  |  | 	 *  ACK is requested, after a successful frame transmission. | 
					
						
							|  |  |  |  | 	 * | 
					
						
							|  |  |  |  | 	 * RF2XX_TRX_PHY_STATE_TRAC_SUCCESS_DATA_PENDING: | 
					
						
							|  |  |  |  | 	 * Equivalent to SUCCESS and indicating that the “Frame | 
					
						
							|  |  |  |  | 	 * Pending” bit (see Section 8.1.2.2) of the received | 
					
						
							|  |  |  |  | 	 * acknowledgment frame was set. | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2020-03-20 21:55:09 -03:00
										 |  |  |  | 		rf2xx_handle_ack(ctx, frag); | 
					
						
							| 
									
										
										
										
											2020-01-08 16:29:45 -02:00
										 |  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return response; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static int rf2xx_start(const struct device *dev) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-28 20:44:16 +02:00
										 |  |  |  | 	const struct rf2xx_config *conf = dev->config; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 	LOG_DBG("Start"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-03 20:47:59 -03:00
										 |  |  |  | 	rf2xx_trx_set_state(dev, RF2XX_TRX_PHY_STATE_CMD_TRX_OFF); | 
					
						
							|  |  |  |  | 	rf2xx_iface_reg_read(dev, RF2XX_IRQ_STATUS_REG); | 
					
						
							| 
									
										
										
										
											2022-02-01 10:11:11 +01:00
										 |  |  |  | 	gpio_pin_interrupt_configure_dt(&conf->irq_gpio, | 
					
						
							|  |  |  |  | 					GPIO_INT_EDGE_TO_ACTIVE); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	rf2xx_trx_set_rx_state(dev); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return 0; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static int rf2xx_stop(const struct device *dev) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-28 20:44:16 +02:00
										 |  |  |  | 	const struct rf2xx_config *conf = dev->config; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 	LOG_DBG("Stop"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-01 10:11:11 +01:00
										 |  |  |  | 	gpio_pin_interrupt_configure_dt(&conf->irq_gpio, GPIO_INT_DISABLE); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	rf2xx_trx_set_state(dev, RF2XX_TRX_PHY_STATE_CMD_TRX_OFF); | 
					
						
							| 
									
										
										
										
											2020-03-03 20:47:59 -03:00
										 |  |  |  | 	rf2xx_iface_reg_read(dev, RF2XX_IRQ_STATUS_REG); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return 0; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-21 20:19:14 -03:00
										 |  |  |  | static int rf2xx_pan_coord_set(const struct device *dev, bool pan_coordinator) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	uint8_t reg; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (pan_coordinator) { | 
					
						
							|  |  |  |  | 		reg = rf2xx_iface_reg_read(dev, RF2XX_CSMA_SEED_1_REG); | 
					
						
							|  |  |  |  | 		reg |= (1 << RF2XX_AACK_I_AM_COORD); | 
					
						
							|  |  |  |  | 		rf2xx_iface_reg_write(dev, RF2XX_CSMA_SEED_1_REG, reg); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		reg = rf2xx_iface_reg_read(dev, RF2XX_CSMA_SEED_1_REG); | 
					
						
							|  |  |  |  | 		reg &= ~(1 << RF2XX_AACK_I_AM_COORD); | 
					
						
							|  |  |  |  | 		rf2xx_iface_reg_write(dev, RF2XX_CSMA_SEED_1_REG, reg); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return 0; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-21 19:43:26 -03:00
										 |  |  |  | static int rf2xx_promiscuous_set(const struct device *dev, bool promiscuous) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-09-24 17:57:28 +02:00
										 |  |  |  | 	struct rf2xx_context *ctx = dev->data; | 
					
						
							| 
									
										
										
										
											2020-11-21 19:43:26 -03:00
										 |  |  |  | 	uint8_t reg; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-24 17:57:28 +02:00
										 |  |  |  | 	ctx->promiscuous = promiscuous; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-21 19:43:26 -03:00
										 |  |  |  | 	if (promiscuous) { | 
					
						
							|  |  |  |  | 		reg = rf2xx_iface_reg_read(dev, RF2XX_XAH_CTRL_1_REG); | 
					
						
							|  |  |  |  | 		reg |= (1 << RF2XX_AACK_PROM_MODE); | 
					
						
							|  |  |  |  | 		rf2xx_iface_reg_write(dev, RF2XX_XAH_CTRL_1_REG, reg); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		reg = rf2xx_iface_reg_read(dev, RF2XX_CSMA_SEED_1_REG); | 
					
						
							|  |  |  |  | 		reg |= (1 << RF2XX_AACK_DIS_ACK); | 
					
						
							|  |  |  |  | 		rf2xx_iface_reg_write(dev, RF2XX_CSMA_SEED_1_REG, reg); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		reg = rf2xx_iface_reg_read(dev, RF2XX_XAH_CTRL_1_REG); | 
					
						
							|  |  |  |  | 		reg &= ~(1 << RF2XX_AACK_PROM_MODE); | 
					
						
							|  |  |  |  | 		rf2xx_iface_reg_write(dev, RF2XX_XAH_CTRL_1_REG, reg); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		reg = rf2xx_iface_reg_read(dev, RF2XX_CSMA_SEED_1_REG); | 
					
						
							|  |  |  |  | 		reg &= ~(1 << RF2XX_AACK_DIS_ACK); | 
					
						
							|  |  |  |  | 		rf2xx_iface_reg_write(dev, RF2XX_CSMA_SEED_1_REG, reg); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return 0; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | int rf2xx_configure(const struct device *dev, | 
					
						
							|  |  |  |  | 		    enum ieee802154_config_type type, | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		    const struct ieee802154_config *config) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-21 19:43:26 -03:00
										 |  |  |  | 	int ret = -EINVAL; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 	LOG_DBG("Configure %d", type); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-21 19:43:26 -03:00
										 |  |  |  | 	switch (type) { | 
					
						
							|  |  |  |  | 	case IEEE802154_CONFIG_AUTO_ACK_FPB: | 
					
						
							|  |  |  |  | 	case IEEE802154_CONFIG_ACK_FPB: | 
					
						
							| 
									
										
										
										
											2020-11-21 20:19:14 -03:00
										 |  |  |  | 		break; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-21 19:43:26 -03:00
										 |  |  |  | 	case IEEE802154_CONFIG_PAN_COORDINATOR: | 
					
						
							| 
									
										
										
										
											2020-11-21 20:19:14 -03:00
										 |  |  |  | 		ret = rf2xx_pan_coord_set(dev, config->pan_coordinator); | 
					
						
							| 
									
										
										
										
											2020-11-21 19:43:26 -03:00
										 |  |  |  | 		break; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	case IEEE802154_CONFIG_PROMISCUOUS: | 
					
						
							|  |  |  |  | 		ret = rf2xx_promiscuous_set(dev, config->promiscuous); | 
					
						
							|  |  |  |  | 		break; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	case IEEE802154_CONFIG_EVENT_HANDLER: | 
					
						
							|  |  |  |  | 	default: | 
					
						
							|  |  |  |  | 		break; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return ret; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | static int rf2xx_attr_get(const struct device *dev, enum ieee802154_attr attr, | 
					
						
							|  |  |  |  | 			   struct ieee802154_attr_value *value) | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	struct rf2xx_context *ctx = dev->data; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | 	switch (attr) { | 
					
						
							|  |  |  |  | 	case IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_PAGES: | 
					
						
							|  |  |  |  | 		value->phy_supported_channel_pages = ctx->cc_page; | 
					
						
							|  |  |  |  | 		return 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	case IEEE802154_ATTR_PHY_SUPPORTED_CHANNEL_RANGES: | 
					
						
							|  |  |  |  | 		value->phy_supported_channels = &ctx->cc_channels; | 
					
						
							|  |  |  |  | 		return 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	default: | 
					
						
							|  |  |  |  | 		return -ENOENT; | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static int power_on_and_setup(const struct device *dev) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-28 20:44:16 +02:00
										 |  |  |  | 	const struct rf2xx_config *conf = dev->config; | 
					
						
							| 
									
										
										
										
											2020-05-28 21:23:02 +02:00
										 |  |  |  | 	struct rf2xx_context *ctx = dev->data; | 
					
						
							| 
									
										
										
										
											2020-05-27 11:26:57 -05:00
										 |  |  |  | 	uint8_t config; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	rf2xx_iface_phy_rst(dev); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* Sync transceiver state */ | 
					
						
							|  |  |  |  | 	do { | 
					
						
							|  |  |  |  | 		rf2xx_iface_reg_write(dev, RF2XX_TRX_STATE_REG, | 
					
						
							|  |  |  |  | 				      RF2XX_TRX_PHY_STATE_CMD_TRX_OFF); | 
					
						
							|  |  |  |  | 	} while (RF2XX_TRX_PHY_STATUS_TRX_OFF != | 
					
						
							|  |  |  |  | 		 (rf2xx_iface_reg_read(dev, RF2XX_TRX_STATUS_REG) & | 
					
						
							|  |  |  |  | 		  RF2XX_TRX_PHY_STATUS_MASK)); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* get device identification */ | 
					
						
							|  |  |  |  | 	ctx->trx_model = rf2xx_iface_reg_read(dev, RF2XX_PART_NUM_REG); | 
					
						
							|  |  |  |  | 	ctx->trx_version = rf2xx_iface_reg_read(dev, RF2XX_VERSION_NUM_REG); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/**
 | 
					
						
							|  |  |  |  | 	 * Valid transceiver are: | 
					
						
							|  |  |  |  | 	 *  231-Rev-A (Version 0x02) | 
					
						
							|  |  |  |  | 	 *  232-Rev-A (Version 0x02) | 
					
						
							|  |  |  |  | 	 *  233-Rev-A (Version 0x01) (Warning) | 
					
						
							|  |  |  |  | 	 *  233-Rev-B (Version 0x02) | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 	if (ctx->trx_model <= RF2XX_TRX_MODEL_230) { | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		LOG_DBG("Invalid or not supported transceiver"); | 
					
						
							|  |  |  |  | 		return -ENODEV; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 	if (ctx->trx_model == RF2XX_TRX_MODEL_233 && ctx->trx_version == 0x01) { | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		LOG_DBG("Transceiver is old and unstable release"); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* Set RSSI base */ | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 	if (ctx->trx_model == RF2XX_TRX_MODEL_212) { | 
					
						
							|  |  |  |  | 		ctx->trx_rssi_base = -100; | 
					
						
							|  |  |  |  | 	} else if (ctx->trx_model == RF2XX_TRX_MODEL_233) { | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		ctx->trx_rssi_base = -94; | 
					
						
							|  |  |  |  | 	} else if (ctx->trx_model == RF2XX_TRX_MODEL_231) { | 
					
						
							|  |  |  |  | 		ctx->trx_rssi_base = -91; | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		ctx->trx_rssi_base = -90; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 	/* Disable All Features of TRX_CTRL_0 */ | 
					
						
							|  |  |  |  | 	config = 0; | 
					
						
							|  |  |  |  | 	rf2xx_iface_reg_write(dev, RF2XX_TRX_CTRL_0_REG, config); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	/* Configure PHY behaviour */ | 
					
						
							|  |  |  |  | 	config = (1 << RF2XX_TX_AUTO_CRC_ON) | | 
					
						
							|  |  |  |  | 		 (3 << RF2XX_SPI_CMD_MODE) | | 
					
						
							|  |  |  |  | 		 (1 << RF2XX_IRQ_MASK_MODE); | 
					
						
							|  |  |  |  | 	rf2xx_iface_reg_write(dev, RF2XX_TRX_CTRL_1_REG, config); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	config = (1 << RF2XX_RX_SAFE_MODE); | 
					
						
							|  |  |  |  | 	if (ctx->trx_model != RF2XX_TRX_MODEL_232) { | 
					
						
							|  |  |  |  | 		config |= (1 << RF2XX_OQPSK_SCRAM_EN); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	rf2xx_iface_reg_write(dev, RF2XX_TRX_CTRL_2_REG, config); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 	if (ctx->trx_model == RF2XX_TRX_MODEL_212) { | 
					
						
							|  |  |  |  | 		rf2xx_configure_trx_path(dev); | 
					
						
							|  |  |  |  | 		rf2xx_iface_reg_write(dev, RF2XX_CC_CTRL_1_REG, 0); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-21 19:02:34 -03:00
										 |  |  |  | 	ctx->tx_mode = IEEE802154_TX_MODE_CSMA_CA; | 
					
						
							| 
									
										
										
										
											2023-09-24 17:57:28 +02:00
										 |  |  |  | 	ctx->promiscuous = false; | 
					
						
							| 
									
										
										
										
											2020-11-21 19:02:34 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	/* Configure INT behaviour */ | 
					
						
							|  |  |  |  | 	config = (1 << RF2XX_RX_START) | | 
					
						
							|  |  |  |  | 		 (1 << RF2XX_TRX_END); | 
					
						
							|  |  |  |  | 	rf2xx_iface_reg_write(dev, RF2XX_IRQ_MASK_REG, config); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 	gpio_init_callback(&ctx->irq_cb, trx_isr_handler, | 
					
						
							|  |  |  |  | 			   BIT(conf->irq_gpio.pin)); | 
					
						
							| 
									
										
										
										
											2023-06-01 20:34:27 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (gpio_add_callback(conf->irq_gpio.port, &ctx->irq_cb) < 0) { | 
					
						
							|  |  |  |  | 		LOG_ERR("Could not set IRQ callback."); | 
					
						
							|  |  |  |  | 		return -ENXIO; | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return 0; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static inline int configure_gpios(const struct device *dev) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-28 20:44:16 +02:00
										 |  |  |  | 	const struct rf2xx_config *conf = dev->config; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* Chip IRQ line */ | 
					
						
							| 
									
										
										
										
											2023-08-26 13:43:58 +10:00
										 |  |  |  | 	if (!gpio_is_ready_dt(&conf->irq_gpio)) { | 
					
						
							| 
									
										
										
										
											2022-02-01 10:11:11 +01:00
										 |  |  |  | 		LOG_ERR("IRQ GPIO device not ready"); | 
					
						
							|  |  |  |  | 		return -ENODEV; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-02-01 10:11:11 +01:00
										 |  |  |  | 	gpio_pin_configure_dt(&conf->irq_gpio, GPIO_INPUT); | 
					
						
							|  |  |  |  | 	gpio_pin_interrupt_configure_dt(&conf->irq_gpio, | 
					
						
							|  |  |  |  | 					GPIO_INT_EDGE_TO_ACTIVE); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* Chip RESET line */ | 
					
						
							| 
									
										
										
										
											2023-08-26 13:43:58 +10:00
										 |  |  |  | 	if (!gpio_is_ready_dt(&conf->reset_gpio)) { | 
					
						
							| 
									
										
										
										
											2022-02-01 10:11:11 +01:00
										 |  |  |  | 		LOG_ERR("RESET GPIO device not ready"); | 
					
						
							|  |  |  |  | 		return -ENODEV; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-02-01 10:11:11 +01:00
										 |  |  |  | 	gpio_pin_configure_dt(&conf->reset_gpio, GPIO_OUTPUT_INACTIVE); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* Chip SLPTR line */ | 
					
						
							| 
									
										
										
										
											2023-08-26 13:43:58 +10:00
										 |  |  |  | 	if (!gpio_is_ready_dt(&conf->slptr_gpio)) { | 
					
						
							| 
									
										
										
										
											2022-02-01 10:11:11 +01:00
										 |  |  |  | 		LOG_ERR("SLPTR GPIO device not ready"); | 
					
						
							|  |  |  |  | 		return -ENODEV; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-02-01 10:11:11 +01:00
										 |  |  |  | 	gpio_pin_configure_dt(&conf->slptr_gpio, GPIO_OUTPUT_INACTIVE); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* Chip DIG2 line (Optional feature) */ | 
					
						
							| 
									
										
										
										
											2022-02-01 10:11:11 +01:00
										 |  |  |  | 	if (conf->dig2_gpio.port != NULL) { | 
					
						
							| 
									
										
										
										
											2023-08-26 13:43:58 +10:00
										 |  |  |  | 		if (!gpio_is_ready_dt(&conf->dig2_gpio)) { | 
					
						
							| 
									
										
										
										
											2022-02-01 10:11:11 +01:00
										 |  |  |  | 			LOG_ERR("DIG2 GPIO device not ready"); | 
					
						
							|  |  |  |  | 			return -ENODEV; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		LOG_INF("Optional instance of %s device activated", | 
					
						
							| 
									
										
										
										
											2022-02-01 10:11:11 +01:00
										 |  |  |  | 			conf->dig2_gpio.port->name); | 
					
						
							|  |  |  |  | 		gpio_pin_configure_dt(&conf->dig2_gpio, GPIO_INPUT); | 
					
						
							|  |  |  |  | 		gpio_pin_interrupt_configure_dt(&conf->dig2_gpio, | 
					
						
							|  |  |  |  | 						GPIO_INT_EDGE_TO_ACTIVE); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* Chip CLKM line (Optional feature) */ | 
					
						
							| 
									
										
										
										
											2022-02-01 10:11:11 +01:00
										 |  |  |  | 	if (conf->clkm_gpio.port != NULL) { | 
					
						
							| 
									
										
										
										
											2023-08-26 13:43:58 +10:00
										 |  |  |  | 		if (!gpio_is_ready_dt(&conf->clkm_gpio)) { | 
					
						
							| 
									
										
										
										
											2022-02-01 10:11:11 +01:00
										 |  |  |  | 			LOG_ERR("CLKM GPIO device not ready"); | 
					
						
							|  |  |  |  | 			return -ENODEV; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		LOG_INF("Optional instance of %s device activated", | 
					
						
							| 
									
										
										
										
											2022-02-01 10:11:11 +01:00
										 |  |  |  | 			conf->clkm_gpio.port->name); | 
					
						
							|  |  |  |  | 		gpio_pin_configure_dt(&conf->clkm_gpio, GPIO_INPUT); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return 0; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static inline int configure_spi(const struct device *dev) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-28 20:44:16 +02:00
										 |  |  |  | 	const struct rf2xx_config *conf = dev->config; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-03 14:49:05 +01:00
										 |  |  |  | 	if (!spi_is_ready_dt(&conf->spi)) { | 
					
						
							| 
									
										
										
										
											2021-10-29 09:11:36 +02:00
										 |  |  |  | 		LOG_ERR("SPI bus %s is not ready", | 
					
						
							|  |  |  |  | 			conf->spi.bus->name); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		return -ENODEV; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return 0; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | static int rf2xx_init(const struct device *dev) | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-28 21:23:02 +02:00
										 |  |  |  | 	struct rf2xx_context *ctx = dev->data; | 
					
						
							| 
									
										
										
										
											2020-05-28 20:44:16 +02:00
										 |  |  |  | 	const struct rf2xx_config *conf = dev->config; | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	char thread_name[20]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	LOG_DBG("\nInitialize RF2XX Transceiver\n"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-08 11:31:38 +02:00
										 |  |  |  | 	ctx->dev = dev; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	k_sem_init(&ctx->trx_tx_sync, 0, 1); | 
					
						
							|  |  |  |  | 	k_sem_init(&ctx->trx_isr_lock, 0, 1); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (configure_gpios(dev) != 0) { | 
					
						
							|  |  |  |  | 		LOG_ERR("Configuring GPIOS failed"); | 
					
						
							|  |  |  |  | 		return -EIO; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (configure_spi(dev) != 0) { | 
					
						
							|  |  |  |  | 		LOG_ERR("Configuring SPI failed"); | 
					
						
							|  |  |  |  | 		return -EIO; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	LOG_DBG("GPIO and SPI configured"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (power_on_and_setup(dev) != 0) { | 
					
						
							|  |  |  |  | 		LOG_ERR("Configuring RF2XX failed"); | 
					
						
							|  |  |  |  | 		return -EIO; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 	LOG_DBG("RADIO configured"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	k_thread_create(&ctx->trx_thread, | 
					
						
							|  |  |  |  | 			ctx->trx_stack, | 
					
						
							|  |  |  |  | 			CONFIG_IEEE802154_RF2XX_RX_STACK_SIZE, | 
					
						
							| 
									
										
										
										
											2023-09-21 09:35:29 +02:00
										 |  |  |  | 			rf2xx_thread_main, | 
					
						
							| 
									
										
										
										
											2020-07-08 11:31:38 +02:00
										 |  |  |  | 			ctx, NULL, NULL, | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 			K_PRIO_COOP(2), 0, K_NO_WAIT); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-26 10:48:53 +02:00
										 |  |  |  | 	snprintk(thread_name, sizeof(thread_name), | 
					
						
							|  |  |  |  | 		 "rf2xx_trx [%d]", conf->inst); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	k_thread_name_set(&ctx->trx_thread, thread_name); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 	LOG_DBG("Thread OK"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	return 0; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static void rf2xx_iface_init(struct net_if *iface) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-04-30 20:33:38 +02:00
										 |  |  |  | 	const struct device *dev = net_if_get_device(iface); | 
					
						
							| 
									
										
										
										
											2020-05-28 21:23:02 +02:00
										 |  |  |  | 	struct rf2xx_context *ctx = dev->data; | 
					
						
							| 
									
										
										
										
											2020-05-27 11:26:57 -05:00
										 |  |  |  | 	uint8_t *mac = get_mac(dev); | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	net_if_set_link_addr(iface, mac, 8, NET_LINK_IEEE802154); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	ctx->iface = iface; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | 	if (ctx->trx_model == RF2XX_TRX_MODEL_212) { | 
					
						
							|  |  |  |  | 		if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915 || | 
					
						
							|  |  |  |  | 		    ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_TWO_OQPSK_868_915) { | 
					
						
							|  |  |  |  | 			ctx->cc_range.from_channel = 0U; | 
					
						
							|  |  |  |  | 			ctx->cc_range.to_channel = 10U; | 
					
						
							|  |  |  |  | 		} else if (ctx->cc_page == IEEE802154_ATTR_PHY_CHANNEL_PAGE_FIVE_OQPSK_780) { | 
					
						
							|  |  |  |  | 			ctx->cc_range.from_channel = 0U; | 
					
						
							|  |  |  |  | 			ctx->cc_range.to_channel = 3U; | 
					
						
							|  |  |  |  | 		} else { | 
					
						
							|  |  |  |  | 			__ASSERT(false, "Unsupported channel page %u.", ctx->cc_page); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		__ASSERT(ctx->cc_page == | 
					
						
							|  |  |  |  | 				 IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915, | 
					
						
							|  |  |  |  | 			 "Unsupported channel page %u.", ctx->cc_page); | 
					
						
							|  |  |  |  | 		ctx->cc_range.from_channel = 11U; | 
					
						
							|  |  |  |  | 		ctx->cc_range.to_channel = 26U; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 	ieee802154_init(iface); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-25 22:16:28 +07:00
										 |  |  |  | static const struct ieee802154_radio_api rf2xx_radio_api = { | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 	.iface_api.init		= rf2xx_iface_init, | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	.get_capabilities	= rf2xx_get_capabilities, | 
					
						
							|  |  |  |  | 	.cca			= rf2xx_cca, | 
					
						
							|  |  |  |  | 	.set_channel		= rf2xx_set_channel, | 
					
						
							|  |  |  |  | 	.filter			= rf2xx_filter, | 
					
						
							|  |  |  |  | 	.set_txpower		= rf2xx_set_txpower, | 
					
						
							|  |  |  |  | 	.tx			= rf2xx_tx, | 
					
						
							|  |  |  |  | 	.start			= rf2xx_start, | 
					
						
							|  |  |  |  | 	.stop			= rf2xx_stop, | 
					
						
							|  |  |  |  | 	.configure		= rf2xx_configure, | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | 	.attr_get		= rf2xx_attr_get, | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #if !defined(CONFIG_IEEE802154_RAW_MODE)
 | 
					
						
							|  |  |  |  |     #if defined(CONFIG_NET_L2_IEEE802154)
 | 
					
						
							|  |  |  |  | 	#define L2 IEEE802154_L2
 | 
					
						
							|  |  |  |  | 	#define L2_CTX_TYPE NET_L2_GET_CTX_TYPE(IEEE802154_L2)
 | 
					
						
							|  |  |  |  | 	#define MTU RF2XX_MAX_PSDU_LENGTH
 | 
					
						
							|  |  |  |  |     #elif defined(CONFIG_NET_L2_OPENTHREAD)
 | 
					
						
							|  |  |  |  | 	#define L2 OPENTHREAD_L2
 | 
					
						
							|  |  |  |  | 	#define L2_CTX_TYPE NET_L2_GET_CTX_TYPE(OPENTHREAD_L2)
 | 
					
						
							|  |  |  |  | 	#define MTU RF2XX_OT_PSDU_LENGTH
 | 
					
						
							|  |  |  |  |     #endif
 | 
					
						
							|  |  |  |  | #endif /* CONFIG_IEEE802154_RAW_MODE */
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-03 22:37:13 -03:00
										 |  |  |  | #define DRV_INST_LOCAL_MAC_ADDRESS(n)					\
 | 
					
						
							|  |  |  |  | 	UTIL_AND(DT_INST_NODE_HAS_PROP(n, local_mac_address),		\ | 
					
						
							|  |  |  |  | 		 UTIL_AND(DT_INST_PROP_LEN(n, local_mac_address) == 8,	\ | 
					
						
							|  |  |  |  | 			  DT_INST_PROP(n, local_mac_address))) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 18:00:25 +02:00
										 |  |  |  | #define IEEE802154_RF2XX_DEVICE_CONFIG(n)				  \
 | 
					
						
							|  |  |  |  | 	BUILD_ASSERT(DT_INST_PROP_LEN(n, tx_pwr_min) == 2,		  \ | 
					
						
							|  |  |  |  | 	"rf2xx: Error TX-PWR-MIN len is different of two");		  \ | 
					
						
							|  |  |  |  | 	BUILD_ASSERT(DT_INST_PROP_LEN(n, tx_pwr_max) == 2,		  \ | 
					
						
							|  |  |  |  | 	"rf2xx: Error TX-PWR-MAX len is different of two");		  \ | 
					
						
							|  |  |  |  | 	BUILD_ASSERT(DT_INST_PROP_LEN(n, tx_pwr_table) != 0,		  \ | 
					
						
							|  |  |  |  | 	"rf2xx: Error TX-PWR-TABLE len must be greater than zero");	  \ | 
					
						
							|  |  |  |  | 	static const uint8_t rf2xx_pwr_table_##n[] =			  \ | 
					
						
							|  |  |  |  | 		DT_INST_PROP_OR(n, tx_pwr_table, 0);			  \ | 
					
						
							|  |  |  |  | 	static const struct rf2xx_config rf2xx_ctx_config_##n = {	  \ | 
					
						
							|  |  |  |  | 		.inst = n,						  \ | 
					
						
							|  |  |  |  | 		.has_mac = DT_INST_NODE_HAS_PROP(n, local_mac_address),   \ | 
					
						
							|  |  |  |  | 		.irq_gpio = GPIO_DT_SPEC_INST_GET(n, irq_gpios),	  \ | 
					
						
							|  |  |  |  | 		.reset_gpio = GPIO_DT_SPEC_INST_GET(n, reset_gpios),	  \ | 
					
						
							|  |  |  |  | 		.slptr_gpio = GPIO_DT_SPEC_INST_GET(n, slptr_gpios),	  \ | 
					
						
							| 
									
										
										
										
											2022-02-01 10:11:11 +01:00
										 |  |  |  | 		.dig2_gpio = GPIO_DT_SPEC_INST_GET_OR(n, dig2_gpios, {}), \ | 
					
						
							|  |  |  |  | 		.clkm_gpio = GPIO_DT_SPEC_INST_GET_OR(n, clkm_gpios, {}), \ | 
					
						
							| 
									
										
										
										
											2022-07-27 18:00:25 +02:00
										 |  |  |  | 		.spi = SPI_DT_SPEC_INST_GET(n, SPI_WORD_SET(8) |	  \ | 
					
						
							| 
									
										
										
										
											2025-07-30 16:01:47 -05:00
										 |  |  |  | 				 SPI_TRANSFER_MSB),			  \ | 
					
						
							| 
									
										
										
										
											2022-07-27 18:00:25 +02:00
										 |  |  |  | 									  \ | 
					
						
							|  |  |  |  | 		.tx_pwr_min = DT_INST_PROP_OR(n, tx_pwr_min, 0),	  \ | 
					
						
							|  |  |  |  | 		.tx_pwr_max = DT_INST_PROP_OR(n, tx_pwr_max, 0),	  \ | 
					
						
							|  |  |  |  | 		.tx_pwr_table = rf2xx_pwr_table_##n,			  \ | 
					
						
							|  |  |  |  | 		.tx_pwr_table_size = DT_INST_PROP_LEN(n, tx_pwr_table),	  \ | 
					
						
							| 
									
										
										
										
											2020-03-03 22:37:13 -03:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-21 20:19:14 -03:00
										 |  |  |  | #define IEEE802154_RF2XX_DEVICE_DATA(n)                                 \
 | 
					
						
							| 
									
										
										
										
											2020-03-03 22:37:13 -03:00
										 |  |  |  | 	static struct rf2xx_context rf2xx_ctx_data_##n = {              \ | 
					
						
							| 
									
										
										
										
											2022-07-27 18:15:57 +02:00
										 |  |  |  | 		.mac_addr = { DRV_INST_LOCAL_MAC_ADDRESS(n) },          \ | 
					
						
							| 
									
										
										
										
											2023-09-02 14:26:44 +02:00
										 |  |  |  | 		.cc_page = BIT(DT_INST_ENUM_IDX_OR(n, channel_page, 0)),\ | 
					
						
							|  |  |  |  | 		.cc_channels = {                                        \ | 
					
						
							|  |  |  |  | 			.ranges = &rf2xx_ctx_data_##n.cc_range,         \ | 
					
						
							|  |  |  |  | 			.num_ranges = 1U,                               \ | 
					
						
							|  |  |  |  | 		}                                                       \ | 
					
						
							| 
									
										
										
										
											2020-03-03 22:37:13 -03:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | #define IEEE802154_RF2XX_RAW_DEVICE_INIT(n)	   \
 | 
					
						
							| 
									
										
										
										
											2020-12-17 12:09:42 -06:00
										 |  |  |  | 	DEVICE_DT_INST_DEFINE(			   \ | 
					
						
							|  |  |  |  | 		n,				   \ | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		&rf2xx_init,			   \ | 
					
						
							| 
									
										
										
										
											2021-04-28 11:05:54 +02:00
										 |  |  |  | 		NULL,				   \ | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		&rf2xx_ctx_data_##n,		   \ | 
					
						
							|  |  |  |  | 		&rf2xx_ctx_config_##n,		   \ | 
					
						
							|  |  |  |  | 		POST_KERNEL,			   \ | 
					
						
							|  |  |  |  | 		CONFIG_IEEE802154_RF2XX_INIT_PRIO, \ | 
					
						
							|  |  |  |  | 		&rf2xx_radio_api) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #define IEEE802154_RF2XX_NET_DEVICE_INIT(n)	   \
 | 
					
						
							| 
									
										
										
										
											2020-12-17 12:09:42 -06:00
										 |  |  |  | 	NET_DEVICE_DT_INST_DEFINE(		   \ | 
					
						
							|  |  |  |  | 		n,				   \ | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		&rf2xx_init,			   \ | 
					
						
							| 
									
										
										
										
											2021-04-28 11:05:54 +02:00
										 |  |  |  | 		NULL,				   \ | 
					
						
							| 
									
										
										
										
											2019-10-24 19:59:35 -03:00
										 |  |  |  | 		&rf2xx_ctx_data_##n,		   \ | 
					
						
							|  |  |  |  | 		&rf2xx_ctx_config_##n,		   \ | 
					
						
							|  |  |  |  | 		CONFIG_IEEE802154_RF2XX_INIT_PRIO, \ | 
					
						
							|  |  |  |  | 		&rf2xx_radio_api,		   \ | 
					
						
							|  |  |  |  | 		L2,				   \ | 
					
						
							|  |  |  |  | 		L2_CTX_TYPE,			   \ | 
					
						
							|  |  |  |  | 		MTU) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 16:06:32 -07:00
										 |  |  |  | #define IEEE802154_RF2XX_INIT(inst)				\
 | 
					
						
							|  |  |  |  | 	IEEE802154_RF2XX_DEVICE_CONFIG(inst);			\ | 
					
						
							|  |  |  |  | 	IEEE802154_RF2XX_DEVICE_DATA(inst);			\ | 
					
						
							|  |  |  |  | 								\ | 
					
						
							|  |  |  |  | 	COND_CODE_1(CONFIG_IEEE802154_RAW_MODE,			\ | 
					
						
							|  |  |  |  | 		    (IEEE802154_RF2XX_RAW_DEVICE_INIT(inst);),	\ | 
					
						
							|  |  |  |  | 		    (IEEE802154_RF2XX_NET_DEVICE_INIT(inst);)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 11:23:07 -07:00
										 |  |  |  | DT_INST_FOREACH_STATUS_OKAY(IEEE802154_RF2XX_INIT) |