Commit 6d5cdc17 authored by Gerson Fernando Budke's avatar Gerson Fernando Budke Committed by Martí Bolívar
Browse files

drivers: ieee802154: rf2xx: Add support to Sub-Giga



Add support to at86rf212[b] sub-giga devices. This work enables use of
pages 0, 2 and 5 in accordance with IEEE-802.15.4/2003/2006/2011. The
proprietary speeds can be object of future work.

Note: It is recommended that user define a power table for better
performance, low emissions and to save power. A reference power table
can be found in the datasheet and should be used for tests only and
not on a final product.

Signed-off-by: default avatarGerson Fernando Budke <nandojve@gmail.com>
parent 65960c4d
Loading
Loading
Loading
Loading
+143 −23
Original line number Diff line number Diff line
@@ -134,6 +134,26 @@ static void rf2xx_trx_set_rx_state(const struct device *dev)
	rf2xx_trx_set_state(dev, RF2XX_TRX_PHY_STATE_CMD_RX_AACK_ON);
}

static void rf2xx_set_rssi_base(const struct device *dev, uint16_t channel)
{
	struct rf2xx_context *ctx = dev->data;
	int8_t base;

	if (ctx->cc_page == RF2XX_TRX_CC_PAGE_0) {
		base = channel == 0
				? RF2XX_RSSI_BPSK_20
				: RF2XX_RSSI_BPSK_40;
	} else if (ctx->cc_page == RF2XX_TRX_CC_PAGE_2) {
		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;
}

static void rf2xx_trx_rx(const struct device *dev)
{
	struct rf2xx_context *ctx = dev->data;
@@ -334,31 +354,100 @@ static inline uint8_t *get_mac(const struct device *dev)

static enum ieee802154_hw_caps rf2xx_get_capabilities(const struct device *dev)
{
	ARG_UNUSED(dev);
	struct rf2xx_context *ctx = dev->data;

	LOG_DBG("HW Caps");

	return IEEE802154_HW_FCS |
	       IEEE802154_HW_PROMISC |
	       IEEE802154_HW_FILTER |
	       IEEE802154_HW_CSMA |
	       IEEE802154_HW_TX_RX_ACK |
	       IEEE802154_HW_2_4_GHZ;
	       (ctx->trx_model == RF2XX_TRX_MODEL_212
				? IEEE802154_HW_SUB_GHZ
				: IEEE802154_HW_2_4_GHZ);
}

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;

	if (ctx->cc_page == RF2XX_TRX_CC_PAGE_0) {
		cc_mask = channel == 0
				   ? RF2XX_CC_BPSK_20
				   : RF2XX_CC_BPSK_40;
	} else if (ctx->cc_page == RF2XX_TRX_CC_PAGE_2) {
		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;
}
static int rf2xx_configure_trx_path(const struct device *dev)
{
	struct rf2xx_context *ctx = dev->data;
	uint8_t reg;
	uint8_t gc_tx_offset;

	if (ctx->cc_page == RF2XX_TRX_CC_PAGE_0) {
		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;
}

static int rf2xx_cca(const struct device *dev)
{
	ARG_UNUSED(dev);

	LOG_DBG("CCA");

	return 0;
}

static int rf2xx_set_channel(const struct device *dev, uint16_t channel)
{
	struct rf2xx_context *ctx = dev->data;
	uint8_t reg;

	LOG_DBG("Set Channel %d", channel);

	if (ctx->trx_model == RF2XX_TRX_MODEL_212) {
		if ((ctx->cc_page == RF2XX_TRX_CC_PAGE_0
		     && ctx->cc_page == RF2XX_TRX_CC_PAGE_2)
		    && channel > 10) {
			LOG_ERR("Unsupported channel %u", channel);
			return -EINVAL;
		}
		if (ctx->cc_page == RF2XX_TRX_CC_PAGE_5 && channel > 3) {
			LOG_ERR("Unsupported channel %u", channel);
			return -EINVAL;
		}

		rf2xx_configure_sub_channel(dev, channel);
		rf2xx_configure_trx_path(dev);
		rf2xx_set_rssi_base(dev, channel);
	} else {
		if (channel < 11 || channel > 26) {
			LOG_ERR("Unsupported channel %u", channel);
			return -EINVAL;
		}
	}

	reg = rf2xx_iface_reg_read(dev, RF2XX_PHY_CC_CCA_REG) & ~0x1f;
	rf2xx_iface_reg_write(dev, RF2XX_PHY_CC_CCA_REG, reg | channel);
@@ -555,6 +644,8 @@ static int rf2xx_tx(const struct device *dev,
	struct rf2xx_context *ctx = dev->data;
	int response = 0;

	LOG_DBG("TX");

	if (ctx->tx_mode != mode) {
		switch (mode) {
		case IEEE802154_TX_MODE_DIRECT:
@@ -629,6 +720,8 @@ static int rf2xx_start(const struct device *dev)
{
	const struct rf2xx_config *conf = dev->config;

	LOG_DBG("Start");

	rf2xx_trx_set_state(dev, RF2XX_TRX_PHY_STATE_CMD_TRX_OFF);
	rf2xx_iface_reg_read(dev, RF2XX_IRQ_STATUS_REG);
	gpio_pin_interrupt_configure_dt(&conf->irq_gpio,
@@ -642,6 +735,8 @@ static int rf2xx_stop(const struct device *dev)
{
	const struct rf2xx_config *conf = dev->config;

	LOG_DBG("Stop");

	gpio_pin_interrupt_configure_dt(&conf->irq_gpio, GPIO_INT_DISABLE);
	rf2xx_trx_set_state(dev, RF2XX_TRX_PHY_STATE_CMD_TRX_OFF);
	rf2xx_iface_reg_read(dev, RF2XX_IRQ_STATUS_REG);
@@ -697,6 +792,8 @@ int rf2xx_configure(const struct device *dev,
{
	int ret = -EINVAL;

	LOG_DBG("Configure %d", type);

	switch (type) {
	case IEEE802154_CONFIG_AUTO_ACK_FPB:
	case IEEE802154_CONFIG_ACK_FPB:
@@ -718,6 +815,13 @@ int rf2xx_configure(const struct device *dev,
	return ret;
}

uint16_t rf2xx_get_subgiga_channel_count(const struct device *dev)
{
	struct rf2xx_context *ctx = dev->data;

	return ctx->cc_page == RF2XX_TRX_CC_PAGE_5 ? 4 : 11;
}

static int power_on_and_setup(const struct device *dev)
{
	const struct rf2xx_config *conf = dev->config;
@@ -745,19 +849,19 @@ static int power_on_and_setup(const struct device *dev)
	 *  233-Rev-A (Version 0x01) (Warning)
	 *  233-Rev-B (Version 0x02)
	 */
	if (ctx->trx_model != RF2XX_TRX_MODEL_231 &&
	    ctx->trx_model != RF2XX_TRX_MODEL_232 &&
	    ctx->trx_model != RF2XX_TRX_MODEL_233) {
	if (ctx->trx_model <= RF2XX_TRX_MODEL_230) {
		LOG_DBG("Invalid or not supported transceiver");
		return -ENODEV;
	}

	if (ctx->trx_version < 0x02) {
	if (ctx->trx_model == RF2XX_TRX_MODEL_233 && ctx->trx_version == 0x01) {
		LOG_DBG("Transceiver is old and unstable release");
	}

	/* Set RSSI base */
	if (ctx->trx_model == RF2XX_TRX_MODEL_233) {
	if (ctx->trx_model == RF2XX_TRX_MODEL_212) {
		ctx->trx_rssi_base = -100;
	} else if (ctx->trx_model == RF2XX_TRX_MODEL_233) {
		ctx->trx_rssi_base = -94;
	} else if (ctx->trx_model == RF2XX_TRX_MODEL_231) {
		ctx->trx_rssi_base = -91;
@@ -765,6 +869,10 @@ static int power_on_and_setup(const struct device *dev)
		ctx->trx_rssi_base = -90;
	}

	/* Disable All Features of TRX_CTRL_0 */
	config = 0;
	rf2xx_iface_reg_write(dev, RF2XX_TRX_CTRL_0_REG, config);

	/* Configure PHY behaviour */
	config = (1 << RF2XX_TX_AUTO_CRC_ON) |
		 (3 << RF2XX_SPI_CMD_MODE) |
@@ -777,6 +885,11 @@ static int power_on_and_setup(const struct device *dev)
	}
	rf2xx_iface_reg_write(dev, RF2XX_TRX_CTRL_2_REG, config);

	if (ctx->trx_model == RF2XX_TRX_MODEL_212) {
		rf2xx_configure_trx_path(dev);
		rf2xx_iface_reg_write(dev, RF2XX_CC_CTRL_1_REG, 0);
	}

	ctx->tx_mode = IEEE802154_TX_MODE_CSMA_CA;

	/* Configure INT behaviour */
@@ -784,7 +897,8 @@ static int power_on_and_setup(const struct device *dev)
		 (1 << RF2XX_TRX_END);
	rf2xx_iface_reg_write(dev, RF2XX_IRQ_MASK_REG, config);

	gpio_init_callback(&ctx->irq_cb, trx_isr_handler, BIT(conf->irq_gpio.pin));
	gpio_init_callback(&ctx->irq_cb, trx_isr_handler,
			   BIT(conf->irq_gpio.pin));
	gpio_add_callback(conf->irq_gpio.port, &ctx->irq_cb);

	return 0;
@@ -887,6 +1001,8 @@ static int rf2xx_init(const struct device *dev)
		return -EIO;
	}

	LOG_DBG("RADIO configured");

	k_thread_create(&ctx->trx_thread,
			ctx->trx_stack,
			CONFIG_IEEE802154_RF2XX_RX_STACK_SIZE,
@@ -898,6 +1014,8 @@ static int rf2xx_init(const struct device *dev)
		 "rf2xx_trx [%d]", conf->inst);
	k_thread_name_set(&ctx->trx_thread, thread_name);

	LOG_DBG("Thread OK");

	return 0;
}

@@ -926,6 +1044,7 @@ static struct ieee802154_radio_api rf2xx_radio_api = {
	.start			= rf2xx_start,
	.stop			= rf2xx_stop,
	.configure		= rf2xx_configure,
	.get_subg_channel_count	= rf2xx_get_subgiga_channel_count,
};

#if !defined(CONFIG_IEEE802154_RAW_MODE)
@@ -973,7 +1092,8 @@ static struct ieee802154_radio_api rf2xx_radio_api = {

#define IEEE802154_RF2XX_DEVICE_DATA(n)                                 \
	static struct rf2xx_context rf2xx_ctx_data_##n = {              \
		.mac_addr = DRV_INST_LOCAL_MAC_ADDRESS(n)               \
		.mac_addr = { DRV_INST_LOCAL_MAC_ADDRESS(n) },          \
		.cc_page = DT_INST_ENUM_IDX_OR(n, channel_page, 0),	\
	}

#define IEEE802154_RF2XX_RAW_DEVICE_INIT(n)	   \
+7 −0
Original line number Diff line number Diff line
@@ -74,6 +74,12 @@ enum rf2xx_trx_model_t {
	RF2XX_TRX_MODEL_233     = 0x0B,
};

enum rf2xx_trx_channel_page_t {
	RF2XX_TRX_CC_PAGE_0     = 0x00,
	RF2XX_TRX_CC_PAGE_2     = 0x02,
	RF2XX_TRX_CC_PAGE_5     = 0x05,
};

struct rf2xx_config {
	struct gpio_dt_spec irq_gpio;
	struct gpio_dt_spec reset_gpio;
@@ -106,6 +112,7 @@ struct rf2xx_context {
	struct k_sem trx_tx_sync;

	enum rf2xx_trx_model_t trx_model;
	enum rf2xx_trx_channel_page_t cc_page;
	enum rf2xx_trx_state_trac_t trx_trac;

	enum ieee802154_tx_mode tx_mode;
+13 −0
Original line number Diff line number Diff line
@@ -24,6 +24,12 @@
#define RF2XX_MAX_PSDU_LENGTH               127
#define RX2XX_MAX_FRAME_SIZE                132

#define RF2XX_RSSI_BPSK_20                  -100
#define RF2XX_RSSI_BPSK_40                  -99
#define RF2XX_RSSI_OQPSK_SIN_RC_100         -98
#define RF2XX_RSSI_OQPSK_SIN_250            -97
#define RF2XX_RSSI_OQPSK_RC_250             -97

/*- Types ------------------------------------------------------------------*/
#define RF2XX_TRX_STATUS_REG                0x01
#define RF2XX_TRX_STATE_REG                 0x02
@@ -148,6 +154,12 @@
#define RF2XX_BPSK_OQPSK                    3
#define RF2XX_SUB_MODE                      2
#define RF2XX_OQPSK_DATA_RATE               0
#define RF2XX_SUB_CHANNEL_MASK              0x3F
#define RF2XX_CC_BPSK_20                    0x00
#define RF2XX_CC_BPSK_40                    0x04
#define RF2XX_CC_OQPSK_SIN_RC_100           0x08
#define RF2XX_CC_OQPSK_SIN_250              0x0C
#define RF2XX_CC_OQPSK_RC_250               0x1C

/* ANT_DIV */
#define RF2XX_ANT_SEL                       7
@@ -201,6 +213,7 @@
#define RF2XX_PA_CHIP_LT                    6
#define RF2XX_F_SHIFT_MODE                  2
#define RF2XX_GC_TX_OFFS                    0
#define RF2XX_GC_TX_OFFS_MASK               3

/* XAH_CTRL_1 */
#define RF2XX_ARET_TX_TS_EN                 7
+17 −0
Original line number Diff line number Diff line
@@ -39,6 +39,23 @@ properties:
        Specifies the MAC address that was assigned to the network
        device

    channel-page:
      type: int
      enum:
        - 0
        - 2
        - 5
      description: |
        Selects Channel Page accordingly with IEEE 802.15.4 standard. The Page 0
        is used in both Sub-Giga and 2.4GHz. It allows select channels 0-10 in
        Sub-Giga band (0: BPSK-20, 1-10: BPSK-40) and 11-26 in 2.4GHz band
        (11-26: O-QPSK-250). Channel 2 is for Sub-Giga and selects
        (0: OQPSK-SIN-RC-100, 1-10: OQPSK-SIN-250). Channel 5 is for Sub-Giga
        (JAPAN) and selects (0-3: OQPSK-RC-250) .
          0: Page 0 - BPSK-20 [0], BPSK-40 [1-10], O-QPSK-250 [11-26].
          2: Page 2 - OQPSK-SIN-RC-100 [0], OQPSK-SIN-250 [1-10].
          5: Page 5 - OQPSK-RC-250 [0-3].

    tx-pwr-table:
      type: uint8-array
      default: [ 0x00 ]