diff --git a/lora_sx127_rpi4.c b/lora_sx127.c similarity index 97% rename from lora_sx127_rpi4.c rename to lora_sx127.c index f0ed080..3177e7e 100644 --- a/lora_sx127_rpi4.c +++ b/lora_sx127.c @@ -428,6 +428,10 @@ static void sx127x_tx_work(struct work_struct *work) } // reset FIFO address and payload length + ret = sx127x_reg_write(hw, SX127X_REG_FIFO_TX_BASE_ADDR, SX127X_FIFO_TX_BASE_ADDRESS); + if (ret < 0) + goto exit_busy; + ret = sx127x_reg_write(hw, SX127X_REG_FIFO_ADDR_PTR, SX127X_FIFO_TX_BASE_ADDRESS); if (ret < 0) goto exit_busy; @@ -443,32 +447,23 @@ static void sx127x_tx_work(struct work_struct *work) if (ret < 0) goto exit_busy; - ret = sx127x_reg_read(hw, SX127X_REG_OP_MODE, &mode); - if (ret < 0) - goto exit_busy; - - if ((mode & SX127X_MODE_MASK) == SX127X_STANDBY_MODE - || (mode & SX127X_MODE_MASK) == SX127X_RXCONTINUOUS_MODE) - ret = sx127x_mode(hw, SX127X_TX_MODE); - else - hw->delayed_tx_length = size; + hw->delayed_tx_length = size; exit_busy: spin_lock_irqsave(&hw->lock, spin_irq); if (set_busy) hw->busy = false; - if (tx_skb) + if (ret && tx_skb) hw->tx_skb = NULL; spin_unlock_irqrestore(&hw->lock, spin_irq); - if (tx_skb) { -#ifndef SX127X_LEGACY_KERNEL - if (ret) - ieee802154_xmit_error(hw->ieee, tx_skb, ret); - else + if (ret && tx_skb) { +#ifdef SX127X_LEGACY_KERNEL + ieee802154_xmit_complete(hw->ieee, tx_skb, false); +#else + ieee802154_xmit_error(hw->ieee, tx_skb, ret); #endif - ieee802154_xmit_complete(hw->ieee, tx_skb, false); } (void) ret; @@ -480,13 +475,15 @@ static void sx127x_poll_work(struct work_struct *work) bool do_rx = false, was_busy = false; unsigned long spin_irq; struct sx127x *hw = container_of(work, struct sx127x, poll_work); - struct sk_buff *rx_skb = NULL; + struct sk_buff *rx_skb = NULL, *tx_skb = NULL; spin_lock_irqsave(&hw->lock, spin_irq); if (!hw->busy) hw->busy = true; else was_busy = true; + + tx_skb = hw->tx_skb; spin_unlock_irqrestore(&hw->lock, spin_irq); if (was_busy) @@ -496,9 +493,11 @@ static void sx127x_poll_work(struct work_struct *work) goto exit_busy; ack_flags = 0; - + if (read_flags & SX127X_FLAG_TXDONE) ack_flags |= SX127X_FLAG_TXDONE; + else + tx_skb = NULL; if (read_flags & SX127X_FLAG_RXDONE) { do_rx = true; @@ -563,8 +562,13 @@ exit_busy: if (rx_skb) kfree_skb(rx_skb); + if (tx_skb) + ieee802154_xmit_complete(hw->ieee, tx_skb, false); + spin_lock_irqsave(&hw->lock, spin_irq); hw->busy = false; + if (tx_skb) + hw->tx_skb = NULL; spin_unlock_irqrestore(&hw->lock, spin_irq); } @@ -583,7 +587,7 @@ static int sx127x_802154_xmit_async(struct ieee802154_hw *ieee, struct sk_buff * spin_lock_irqsave(&hw->lock, spin_irq); if (!hw->tx_skb) - hw->tx_skb = skb_get(skb); + hw->tx_skb = skb; else ret = -EBUSY; spin_unlock_irqrestore(&hw->lock, spin_irq); @@ -625,6 +629,7 @@ static int sx127x_802154_start(struct ieee802154_hw *ieee) } mod_timer(&hw->poll_timer, jiffies + POLL_JIFFIES); + dev_dbg(regmap_get_device(hw->regmap), "%s\n", __func__); return 0; } @@ -636,6 +641,7 @@ static void sx127x_802154_stop(struct ieee802154_hw *ieee) cancel_work_sync(&hw->poll_work); (void) sx127x_mode(hw, SX127X_SLEEP_MODE); + dev_dbg(regmap_get_device(hw->regmap), "%s\n", __func__); } static int sx127x_802154_set_promiscuous_mode(struct ieee802154_hw *ieee, const bool on) diff --git a/lora_sx127_rpi3.c b/lora_sx127_rpi3.c deleted file mode 100644 index 8200ac7..0000000 --- a/lora_sx127_rpi3.c +++ /dev/null @@ -1,812 +0,0 @@ -/*- - * Copyright (c) 2017 Jian-Hong, Pan - * Copyright (c) 2024 Fabian Montero - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -#define DEBUG - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef F_XOSC -#define F_XOSC 32000000 -#endif -static u32 xosc_frq = F_XOSC; -module_param(xosc_frq, uint, 0000); -MODULE_PARM_DESC(xosc_frq, "Crystal oscillator frequency of the LoRa chip"); - -#define __POW_2_19 0x80000 - -#ifndef SX127X_SPRF -#define SX127X_SPRF 512 -#endif -static u32 sprf = SX127X_SPRF; -module_param(sprf, uint, 0000); -MODULE_PARM_DESC(sprf, "Spreading factor of Chirp Spread Spectrum modulation"); - -#ifndef SX127X_RX_BYTE_TIMEOUT -#define SX127X_RX_BYTE_TIMEOUT 1023 -#endif -static u32 rx_timeout = SX127X_RX_BYTE_TIMEOUT; -module_param(rx_timeout, uint, 0000); -MODULE_PARM_DESC(rx_timeout, "RX time-out value as number of symbols"); - -/* SX127X Registers addresses */ -#define SX127X_REG_FIFO 0x00 -#define SX127X_REG_OP_MODE 0x01 -#define SX127X_REG_FRF_MSB 0x06 -#define SX127X_REG_FRF_MID 0x07 -#define SX127X_REG_FRF_LSB 0x08 -#define SX127X_REG_PA_CONFIG 0x09 -#define SX127X_REG_PA_RAMP 0x0A -#define SX127X_REG_OCP 0x0B -#define SX127X_REG_LNA 0x0C -#define SX127X_REG_FIFO_ADDR_PTR 0x0D -#define SX127X_REG_FIFO_TX_BASE_ADDR 0x0E -#define SX127X_REG_FIFO_RX_BASE_ADDR 0x0F -#define SX127X_REG_FIFO_RX_CURRENT_ADDR 0x10 -#define SX127X_REG_IRQ_FLAGS_MASK 0x11 -#define SX127X_REG_IRQ_FLAGS 0x12 -#define SX127X_REG_RX_NB_BYTES 0x13 -#define SX127X_REG_RX_HEADER_CNT_VALUE_MSB 0x14 -#define SX127X_REG_RX_HEADER_CNT_VALUE_LSB 0x15 -#define SX127X_REG_RX_PACKET_CNT_VALUE_MSB 0x16 -#define SX127X_REG_RX_PACKET_CNT_VALUE_LSB 0x17 -#define SX127X_REG_MODEM_STAT 0x18 -#define SX127X_REG_PKT_SNR_VALUE 0x19 -#define SX127X_REG_PKT_RSSI_VALUE 0x1A -#define SX127X_REG_RSSI_VALUE 0x1B -#define SX127X_REG_HOP_CHANNEL 0x1C -#define SX127X_REG_MODEM_CONFIG1 0x1D -#define SX127X_REG_MODEM_CONFIG2 0x1E -#define SX127X_REG_SYMB_TIMEOUT_LSB 0x1F -#define SX127X_REG_PREAMBLE_MSB 0x20 -#define SX127X_REG_PREAMBLE_LSB 0x21 -#define SX127X_REG_PAYLOAD_LENGTH 0x22 -#define SX127X_REG_MAX_PAYLOAD_LENGTH 0x23 -#define SX127X_REG_HOP_PERIOD 0x24 -#define SX127X_REG_FIFO_RX_BYTE_ADDR 0x25 -#define SX127X_REG_MODEM_CONFIG3 0x26 -#define SX127X_REG_FEI_MSB 0x28 -#define SX127X_REG_FEI_MID 0x29 -#define SX127X_REG_FEI_LSB 0x2A -#define SX127X_REG_RSSI_WIDEBAND 0x2C -#define SX127X_REG_DETECT_OPTIMIZE 0x31 -#define SX127X_REG_INVERT_IRQ 0x33 -#define SX127X_REG_DETECTION_THRESHOLD 0x37 -#define SX127X_REG_SYNC_WORD 0x39 -#define SX127X_REG_VERSION 0x42 -#define SX127X_REG_TCXO 0x4B -#define SX127X_REG_PA_DAC 0x4D -#define SX127X_REG_FORMER_TEMP 0x5B -#define SX127X_REG_AGC_REF 0x61 -#define SX127X_REG_AGC_THRESH1 0x62 -#define SX127X_REG_AGC_THRESH2 0x63 -#define SX127X_REG_AGC_THRESH3 0x64 -#define SX127X_REG_PLL 0x70 -#define SX127X_MAX_REG SX127X_REG_PLL - -/* SX127X's operating states in LoRa mode */ -#define SX127X_MODE_MASK 0x07 -#define SX127X_SLEEP_MODE 0x00 -#define SX127X_STANDBY_MODE 0x01 -#define SX127X_FSTX_MODE 0x02 -#define SX127X_TX_MODE 0x03 -#define SX127X_FSRX_MODE 0x04 -#define SX127X_RXCONTINUOUS_MODE 0x05 -#define SX127X_RXSINGLE_MODE 0x06 -#define SX127X_CAD_MODE 0x07 -#define SX127X_LORA_MODE 0x80 - -/* SX127X_REG_OCP flags */ -#define SX127X_FLAG_OCPON 0x20 - -/* SX127X's IRQ flags in LoRa mode */ -#define SX127X_FLAG_RXTIMEOUT 0x80 -#define SX127X_FLAG_RXDONE 0x40 -#define SX127X_FLAG_PAYLOADCRCERROR 0x20 -#define SX127X_FLAG_VALIDHEADER 0x10 -#define SX127X_FLAG_TXDONE 0x08 -#define SX127X_FLAG_CADDONE 0x04 -#define SX127X_FLAG_FHSSCHANGECHANNEL 0x02 -#define SX127X_FLAG_CADDETECTED 0x01 - -/* SX127X's IRQ flags' mask for output pins in LoRa mode */ -#define SX127X_FLAGMASK_RXTIMEOUT 0x80 -#define SX127X_FLAGMASK_RXDONE 0x40 -#define SX127X_FLAGMASK_PAYLOADCRCERROR 0x20 -#define SX127X_FLAGMASK_VALIDHEADER 0x10 -#define SX127X_FLAGMASK_TXDONE 0x08 -#define SX127X_FLAGMASK_CADDONE 0x04 -#define SX127X_FLAGMASK_FHSSCHANGECHANNEL 0x02 -#define SX127X_FLAGMASK_CADDETECTED 0x01 - -#define SX127X_MODEM_CONFIG1_HEADER_MODE_MASK 0x01 -#define SX127X_MODEM_CONFIG1_HEADER_MODE_EXPLICIT 0x00 -#define SX127X_MODEM_CONFIG1_HEADER_MODE_IMPLICIT 0x01 - -/* SX127X's RX/TX FIFO base address */ -#define SX127X_FIFO_RX_BASE_ADDRESS 0x00 -#define SX127X_FIFO_TX_BASE_ADDRESS 0x80 - -#define POLL_JIFFIES (msecs_to_jiffies(10)) - -struct sx127x { - struct regmap *regmap; - struct ieee802154_hw *ieee; - struct spi_device *spi; - - spinlock_t lock; - bool busy; - struct sk_buff *tx_skb; - size_t delayed_tx_length; - - struct timer_list poll_timer; - struct work_struct poll_work; - struct work_struct tx_work; - - u32 oscillator_freq; -}; - -static int sx127x_reg_read(struct sx127x *hw, unsigned int address, u8 *data) -{ - int ret = regmap_raw_read(hw->regmap, address, data, 1); - if (ret < 0) - dev_err(&hw->spi->dev, "regmap_raw_read(0x%x) failed: %d\n", address, ret); - - return ret; -} - -static int sx127x_reg_write(struct sx127x *hw, unsigned int address, u8 data) -{ - int ret = regmap_raw_write(hw->regmap, address, &data, 1); - if (ret < 0) - dev_err(&hw->spi->dev, "regmap_raw_write(0x%x) failed: %d\n", address, ret); - - return ret; -} - -static int sx127x_mode(struct sx127x *hw, unsigned int mode) -{ - return sx127x_reg_write(hw, SX127X_REG_OP_MODE, SX127X_LORA_MODE | mode); -} - -static int sx127x_set_frequency(struct sx127x *hw, unsigned long frequency) -{ - u8 msb_mid_lsb[3]; - int i; - u64 frf; - - frf = (((u64) frequency) << 19) / hw->oscillator_freq; - for (i = sizeof msb_mid_lsb - 1; i >= 0; --i) { - msb_mid_lsb[i] = (frf & 0xff); - frf >>= 8; - } - - return regmap_raw_write(hw->regmap, SX127X_REG_FRF_MSB, msb_mid_lsb, sizeof msb_mid_lsb); -} - -static int sx127x_get_frequency(struct sx127x *hw, unsigned long *frequency) -{ - u8 msb_mid_lsb[3]; - int i, ret; - u64 frt; - - ret = regmap_raw_read(hw->regmap, SX127X_REG_FRF_MSB, msb_mid_lsb, sizeof msb_mid_lsb); - if (ret < 0) - return ret; - - frt = 0; - for (i = 0; i < sizeof msb_mid_lsb; ++i) - frt = (frt << 8) | msb_mid_lsb[i]; - - *frequency = (frt * hw->oscillator_freq) >> 19; - return 0; -} - -static int sx127x_set_ocp(struct sx127x *hw, u8 current_ma) -{ - u8 ocp_trim; - - /* P. 109 - * - * Trimming of OCP current: - * Imax = 45+5*OcpTrim [mA] if OcpTrim <= 15 (120 mA) / - * Imax = -30+10*OcpTrim [mA] if 15 < OcpTrim <= 27 (130 to - * 240 mA) - * Imax = 240mA for higher settings - * Default Imax = 100mA - */ - if (current_ma <= 45) - ocp_trim = 0; - else if (current_ma <= 120) - ocp_trim = (current_ma - 45) / 5; - else if (current_ma <= 240) - ocp_trim = (current_ma + 30) / 10; - else - ocp_trim = 28; - - return sx127x_reg_write(hw, SX127X_REG_OCP, SX127X_FLAG_OCPON | ocp_trim); -} - -static int sx127x_set_tx_power(struct sx127x *hw, int level) -{ - int ret; - - // PA BOOST - if (level > 17) { - if (level > 20) - level = 20; - - // subtract 3 from level, so 18 - 20 maps to 15 - 17 - level -= 3; - - // High Power +20 dBm Operation (Semtech SX1276/77/78/79 5.4.3.) - ret = sx127x_reg_write(hw, SX127X_REG_PA_DAC, 0x87); - if (ret < 0) - return ret; - - ret = sx127x_set_ocp(hw, 140); - if (ret < 0) - return ret; - } else { - if (level < 2) - level = 2; - - // Default value PA_HF/LF or +17dBm - ret = sx127x_reg_write(hw, SX127X_REG_PA_DAC, 0x84); - if (ret < 0) - return ret; - - ret = sx127x_set_ocp(hw, 100); - if (ret < 0) - return ret; - } - - // PA_CONFIG -#define PA_BOOST 0x80 - return sx127x_reg_write(hw, SX127X_REG_PA_CONFIG, PA_BOOST | (level - 2)); -} - -static int sx127x_init(struct sx127x *hw, u8 *major, u8 *minor) -{ - u8 modem_config1, lna, version; - int ret; - - ret = sx127x_reg_read(hw, SX127X_REG_VERSION, &version); - if (ret < 0) - return ret; - - if (version != 0x12) { - dev_err(&hw->spi->dev, "%s: bad version 0x%02x\n", __func__, version); - return -ENODEV; - } - - *major = (version >> 4) & 0xf; - *minor = (version >> 0) & 0xf; - - ret = sx127x_mode(hw, SX127X_SLEEP_MODE); - if (ret < 0) { - dev_err(&hw->spi->dev, "%s: sx127x_mode() failed: %d\n", __func__, ret); - return ret; - } - - ret = sx127x_reg_write(hw, SX127X_REG_FIFO_RX_BASE_ADDR, SX127X_FIFO_RX_BASE_ADDRESS); - if (ret < 0) - return ret; - - ret = sx127x_reg_write(hw, SX127X_REG_FIFO_TX_BASE_ADDR, SX127X_FIFO_TX_BASE_ADDRESS); - if (ret < 0) - return ret; - - ret = sx127x_reg_read(hw, SX127X_REG_LNA, &lna); - if (ret < 0) - return ret; - - lna |= 0x3; // ???, pero lo hace el sketch - ret = sx127x_reg_write(hw, SX127X_REG_LNA, lna); - if (ret < 0) - return ret; - - ret = sx127x_reg_read(hw, SX127X_REG_MODEM_CONFIG1, &modem_config1); - if (ret < 0) - return ret; - - modem_config1 &= ~SX127X_MODEM_CONFIG1_HEADER_MODE_MASK; - modem_config1 |= SX127X_MODEM_CONFIG1_HEADER_MODE_EXPLICIT; - - ret = sx127x_reg_write(hw, SX127X_REG_MODEM_CONFIG1, modem_config1); - if (ret < 0) - return ret; - - ret = sx127x_reg_write(hw, SX127X_REG_MODEM_CONFIG3, 0x4); - if (ret < 0) - return ret; - - return 0; -} - -static void sx127x_tx_work(struct work_struct *work) -{ - u8 mode; - int ret = 0; - bool set_busy = false; - size_t i, size; - const u8 *buffer; - struct sx127x *hw = container_of(work, struct sx127x, tx_work); - struct sk_buff *tx_skb; - unsigned long spin_irq; - - spin_lock_irqsave(&hw->lock, spin_irq); - - tx_skb = hw->tx_skb; - if (!hw->busy && !hw->delayed_tx_length) { - hw->busy = true; - set_busy = true; - } - - spin_unlock_irqrestore(&hw->lock, spin_irq); - - if (!set_busy) { - ret = -EBUSY; - goto exit_busy; - } else if (!tx_skb) { - ret = -EINVAL; - goto exit_busy; - } - - size = tx_skb->len; - buffer = tx_skb->data; - - if (!size || size > 128) { - ret = -EINVAL; - goto exit_busy; - } - - ret = sx127x_reg_read(hw, SX127X_REG_OP_MODE, &mode); - if (ret < 0) - goto exit_busy; - - if ((mode & SX127X_MODE_MASK) == SX127X_TX_MODE) { - ret = -EBUSY; - goto exit_busy; - } - - // reset FIFO address and payload length - ret = sx127x_reg_write(hw, SX127X_REG_FIFO_ADDR_PTR, SX127X_FIFO_TX_BASE_ADDRESS); - if (ret < 0) - goto exit_busy; - - // write data - for (i = 0; i < size; i++) { - ret = sx127x_reg_write(hw, SX127X_REG_FIFO, buffer[i]); - if (ret < 0) - goto exit_busy; - } - - ret = sx127x_reg_write(hw, SX127X_REG_PAYLOAD_LENGTH, (u8) size); - if (ret < 0) - goto exit_busy; - - ret = sx127x_reg_read(hw, SX127X_REG_OP_MODE, &mode); - if (ret < 0) - goto exit_busy; - - if ((mode & SX127X_MODE_MASK) == SX127X_STANDBY_MODE - || (mode & SX127X_MODE_MASK) == SX127X_RXCONTINUOUS_MODE) - ret = sx127x_mode(hw, SX127X_TX_MODE); - else - hw->delayed_tx_length = size; - -exit_busy: - spin_lock_irqsave(&hw->lock, spin_irq); - if (set_busy) - hw->busy = false; - - if (tx_skb) - hw->tx_skb = NULL; - spin_unlock_irqrestore(&hw->lock, spin_irq); - - if (tx_skb) { -#ifndef SX127X_LEGACY_KERNEL - if (ret) - ieee802154_xmit_error(hw->ieee, tx_skb, ret); - else -#endif - ieee802154_xmit_complete(hw->ieee, tx_skb, false); - } - - (void) ret; -} - -static void sx127x_poll_work(struct work_struct *work) -{ - u8 ack_flags, lqi, mode, read_flags, rx_base, *rx_data, rx_length; - bool do_rx = false, was_busy = false; - unsigned long spin_irq; - struct sx127x *hw = container_of(work, struct sx127x, poll_work); - struct sk_buff *rx_skb = NULL; - - spin_lock_irqsave(&hw->lock, spin_irq); - if (!hw->busy) - hw->busy = true; - else - was_busy = true; - spin_unlock_irqrestore(&hw->lock, spin_irq); - - if (was_busy) - return; - - if (sx127x_reg_read(hw, SX127X_REG_IRQ_FLAGS, &read_flags) < 0) - goto exit_busy; - - ack_flags = 0; - - if (read_flags & SX127X_FLAG_TXDONE) - ack_flags |= SX127X_FLAG_TXDONE; - - if (read_flags & SX127X_FLAG_RXDONE) { - do_rx = true; - ack_flags |= SX127X_FLAG_RXDONE; - - if (read_flags & SX127X_FLAG_VALIDHEADER) - ack_flags |= SX127X_FLAG_VALIDHEADER; - else - do_rx = false; - - if (read_flags & SX127X_FLAG_PAYLOADCRCERROR) { - do_rx = false; - ack_flags |= SX127X_FLAG_PAYLOADCRCERROR; - } - } - - if (do_rx) { - if (sx127x_reg_read(hw, SX127X_REG_FIFO_RX_CURRENT_ADDR, &rx_base) < 0 - || sx127x_reg_read(hw, SX127X_REG_RX_NB_BYTES, &rx_length) < 0) - goto exit_busy; - - if (sx127x_reg_write(hw, SX127X_REG_FIFO_ADDR_PTR, rx_base) < 0) - goto exit_busy; - - rx_skb = dev_alloc_skb(IEEE802154_MTU); - if (!rx_skb) - goto exit_busy; - - rx_data = skb_put(rx_skb, rx_length); - while (rx_length--) - if (sx127x_reg_read(hw, SX127X_REG_FIFO, rx_data++) < 0) - goto exit_busy; - - if (sx127x_reg_write(hw, SX127X_REG_FIFO_RX_BASE_ADDR, SX127X_FIFO_RX_BASE_ADDRESS) < 0) - goto exit_busy; - } - - if (sx127x_reg_write(hw, SX127X_REG_IRQ_FLAGS, ack_flags) < 0) - goto exit_busy; - - if (sx127x_reg_read(hw, SX127X_REG_OP_MODE, &mode) < 0) - goto exit_busy; - - if ((mode & SX127X_MODE_MASK) != SX127X_TX_MODE) { - if (hw->delayed_tx_length) { - sx127x_mode(hw, SX127X_TX_MODE); - hw->delayed_tx_length = 0; - } else if ((mode & SX127X_MODE_MASK) != SX127X_RXCONTINUOUS_MODE) - sx127x_mode(hw, SX127X_RXCONTINUOUS_MODE); - } - - if (rx_skb) { - lqi = 69; //TODO - ieee802154_rx_irqsafe(hw->ieee, rx_skb, lqi); - rx_skb = NULL; // rx_skb ownership transferred to the mac802154 layer - } - -exit_busy: - if (rx_skb) - kfree_skb(rx_skb); - - spin_lock_irqsave(&hw->lock, spin_irq); - hw->busy = false; - spin_unlock_irqrestore(&hw->lock, spin_irq); -} - -static void sx127x_poll_timer(struct timer_list *timer) -{ - struct sx127x *hw = container_of(timer, struct sx127x, poll_timer); - schedule_work(&hw->poll_work); - mod_timer(&hw->poll_timer, jiffies + POLL_JIFFIES); -} - -static int sx127x_802154_xmit_async(struct ieee802154_hw *ieee, struct sk_buff *skb) -{ - int ret = 0; - struct sx127x *hw = ieee->priv; - unsigned long spin_irq; - - spin_lock_irqsave(&hw->lock, spin_irq); - if (!hw->tx_skb) - hw->tx_skb = skb_get(skb); - else - ret = -EBUSY; - spin_unlock_irqrestore(&hw->lock, spin_irq); - - schedule_work(&hw->tx_work); - return ret; -} - -static int sx127x_802154_ed(struct ieee802154_hw *ieee, u8 *level) -{ - struct sx127x *hw = ieee->priv; - (void) hw; - return -ENOSYS; -} - -static int sx127x_802154_set_channel(struct ieee802154_hw *ieee, u8 page, u8 channel) -{ - struct sx127x *hw = ieee->priv; - (void) hw; - return -ENOSYS; -} - -static int sx127x_802154_set_txpower(struct ieee802154_hw *ieee, s32 mbm) -{ - struct sx127x *hw = ieee->priv; - (void) hw; - return -ENOSYS; -} - -static int sx127x_802154_start(struct ieee802154_hw *ieee) -{ - int ret; - struct sx127x *hw = ieee->priv; - - ret = sx127x_mode(hw, SX127X_STANDBY_MODE); - if (ret < 0) { - dev_err(&hw->spi->dev, "%s: sx127x_mode() failed: %d\n", __func__, ret); - return ret; - } - - mod_timer(&hw->poll_timer, jiffies + POLL_JIFFIES); - return 0; -} - -static void sx127x_802154_stop(struct ieee802154_hw *ieee) -{ - struct sx127x *hw = ieee->priv; - - del_timer_sync(&hw->poll_timer); - cancel_work_sync(&hw->poll_work); - - (void) sx127x_mode(hw, SX127X_SLEEP_MODE); -} - -static int sx127x_802154_set_promiscuous_mode(struct ieee802154_hw *ieee, const bool on) -{ - return 0; -} - -static const struct ieee802154_ops sx127x_802154_ops = { - .owner = THIS_MODULE, - .xmit_async = sx127x_802154_xmit_async, - .ed = sx127x_802154_ed, - .set_channel = sx127x_802154_set_channel, - .set_txpower = sx127x_802154_set_txpower, - .start = sx127x_802154_start, - .stop = sx127x_802154_stop, - .set_promiscuous_mode = sx127x_802154_set_promiscuous_mode, -}; - -static bool sx127x_reg_volatile(struct device *dev, unsigned int reg) -{ - return true; -} - -static const struct regmap_config sx127x_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .max_register = SX127X_MAX_REG, - .read_flag_mask = 0x00, - .write_flag_mask = 0x80, - .volatile_reg = sx127x_reg_volatile, -}; - -/* in mbm */ -static const s32 sx127x_tx_powers[] = { - -200, -100, 0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, - 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300}; - -static int sx127x_spi_probe(struct spi_device *spi) -{ - u8 major, minor; - int ret = 0; - struct sx127x *hw; - unsigned long frequency; - struct ieee802154_hw *ieee; - struct device_node *of_node; - - dev_dbg(&spi->dev, "%s hello\n", __func__); - - ieee = ieee802154_alloc_hw(sizeof *hw, &sx127x_802154_ops); - if (!ieee) { - dev_err(&spi->dev, "ieee802154_alloc_hw(): out of memory\n"); - return -ENOMEM; - } - - hw = ieee->priv; - hw->spi = spi; - hw->ieee = ieee; - hw->busy = false; - hw->delayed_tx_length = 0; - spin_lock_init(&hw->lock); - - INIT_WORK(&hw->tx_work, sx127x_tx_work); - INIT_WORK(&hw->poll_work, sx127x_poll_work); - timer_setup(&hw->poll_timer, sx127x_poll_timer, 0); - - hw->regmap = devm_regmap_init_spi(spi, &sx127x_regmap_config); - if (IS_ERR(hw->regmap)) { - dev_err(&spi->dev, "%s: devm_regmap_init_spi() failed: %d\n", __func__, ret); - return PTR_ERR(hw->regmap); - } - - of_node = regmap_get_device(hw->regmap)->of_node; - if (of_property_read_u32(of_node, "clock-frequency", &hw->oscillator_freq)) { - dev_err(&spi->dev, "%s: 'clock-frequency' missing from DT node\n", __func__); - return -EINVAL; - } - - ieee->parent = &spi->dev; - spi_set_drvdata(spi, hw); - - //TODO: pin de reset - - ieee802154_random_extended_addr(&ieee->phy->perm_extended_addr); - - ieee->flags = IEEE802154_HW_TX_OMIT_CKSUM - | IEEE802154_HW_RX_OMIT_CKSUM - | IEEE802154_HW_PROMISCUOUS; - - ieee->phy->flags = WPAN_PHY_FLAG_TXPOWER; - ieee->phy->transmit_power = sx127x_tx_powers[12]; - ieee->phy->supported.tx_powers = sx127x_tx_powers; - ieee->phy->supported.tx_powers_size = ARRAY_SIZE(sx127x_tx_powers); - - /* SX1278 phy channel 11 as default */ - ieee->phy->current_channel = 11; - /* Define channels could be used. */ - ieee->phy->supported.channels[0] = 1 << 11; /*TODO: sx1278_ieee_channel_mask(hw);*/ - - ret = sx127x_init(hw, &major, &minor); - if (ret < 0) { - dev_err(&spi->dev, "%s: sx127x_init() failed: %d\n", __func__, ret); - goto fail_init; - } - - dev_info(&spi->dev, "IEEE 802.15.4 over LoRa SX127x compatible device v%u.%u\n", major, minor); - - // Valor viene del sketch - ret = sx127x_set_frequency(hw, 434000000); - if (ret < 0) { - dev_err(&spi->dev, "%s: sx127x_set_frequency() failed: %d\n", __func__, ret); - goto fail_init; - } - - ret = sx127x_get_frequency(hw, &frequency); - if (ret < 0) { - dev_err(&spi->dev, "%s: sx127x_get_frequency() failed: %d\n", __func__, ret); - goto fail_init; - } - - dev_dbg(&spi->dev, "%s: frequency sanity test: %lu Hz\n", __func__, frequency); - - ret = sx127x_set_tx_power(hw, 17); // 17 dBm - if (ret < 0) { - dev_err(&spi->dev, "%s: sx127x_set_tx_power() failed: %d\n", __func__, ret); - goto fail_init; - } - - ret = ieee802154_register_hw(ieee); - if (ret < 0) - dev_err(&spi->dev, "ieee802154_register_hw() failed: %d\n", ret); - - return ret; - -fail_init: - ieee802154_free_hw(ieee); - return ret; -} - -#ifdef SX127X_LEGACY_KERNEL -static int sx127x_spi_remove(struct spi_device *spi) -#else -static void sx127x_spi_remove(struct spi_device *spi) -#endif -{ - struct sx127x *hw = spi_get_drvdata(spi); - - dev_dbg(&hw->spi->dev, "%s bye\n", __func__); - - ieee802154_unregister_hw(hw->ieee); - ieee802154_free_hw(hw->ieee); - -#ifdef SX127X_LEGACY_KERNEL - return 0; -#endif -} - -static const struct of_device_id sx127x_of_ids[] = { - { .compatible = "semtech,sx1276" }, - { .compatible = "semtech,sx1277" }, - { .compatible = "semtech,sx1278" }, - { .compatible = "semtech,sx1279" }, - {}, -}; -MODULE_DEVICE_TABLE(of, sx127x_of_ids); - -static const struct spi_device_id sx127x_spi_ids[] = { - { .name = "sx1276" }, - { .name = "sx1277" }, - { .name = "sx1278" }, - { .name = "sx1279" }, - {}, -}; -MODULE_DEVICE_TABLE(spi, sx127x_spi_ids); - -static struct spi_driver sx127x_spi_driver = { - .driver = { - .name = "sx127x", - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(sx127x_of_ids), - }, - .probe = sx127x_spi_probe, - .remove = sx127x_spi_remove, - .id_table = sx127x_spi_ids, -}; - -module_spi_driver(sx127x_spi_driver); - -MODULE_AUTHOR("Jian-Hong Pan, "); -MODULE_AUTHOR("Fabian Montero "); -MODULE_DESCRIPTION("Semtech SX127x LoRa PHY driver with IEEE 802.15.4 MAC interface"); -MODULE_LICENSE("GPL"); diff --git a/setup-lora_pi3.c b/setup-lora_pi3.c deleted file mode 100755 index a52c732..0000000 --- a/setup-lora_pi3.c +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -set -e - -modprobe regmap_spi -modprobe mac802154 -insmod /home/loro/LoRo/LoRo/loro.ko -sleep 1 -ip link set down wpan0 -iwpan dev wpan0 set pan_id 0xbeef -ip link add link wpan0 name lowpan0 type lowpan -ip link set up wpan0 -ip link set up lowpan0