[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20190128161306.27805-12-ben.whitten@lairdtech.com>
Date: Mon, 28 Jan 2019 16:13:05 +0000
From: Ben Whitten <ben.whitten@...il.com>
To: afaerber@...e.de
Cc: linux-lpwan@...ts.infradead.org,
Ben Whitten <ben.whitten@...rdtech.com>,
"David S. Miller" <davem@...emloft.net>, netdev@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: [PATCH lora-next 11/11] net: lora: sx130x: add patch to register fields
The SX130x chips require a number of constant adjustments and patches.
We add the fields for the registers which require patches, add patch
values then add a helper to patch fields. Removing one TODO.
Signed-off-by: Ben Whitten <ben.whitten@...rdtech.com>
---
drivers/net/lora/sx130x.c | 131 +++++++++++++++++++++++++++++++++++++-
drivers/net/lora/sx130x.h | 75 ++++++++++++++++++++++
2 files changed, 205 insertions(+), 1 deletion(-)
diff --git a/drivers/net/lora/sx130x.c b/drivers/net/lora/sx130x.c
index 428e82b4ccb8..6e3b42de98a0 100644
--- a/drivers/net/lora/sx130x.c
+++ b/drivers/net/lora/sx130x.c
@@ -27,6 +27,63 @@
#include "sx130x.h"
+struct sx130x_fields_sequence {
+ enum sx130x_fields field;
+ u8 val;
+};
+
+static const struct sx130x_fields_sequence sx130x_regmap_fields_patch[] = {
+ /* I/Q path setup */
+ {F_RSSI_BB_FILTER_ALPHA, 6},
+ {F_RSSI_DEC_FILTER_ALPHA, 7},
+ {F_RSSI_CHANN_FILTER_ALPHA, 7},
+ {F_RSSI_BB_DEFAULT_VALUE, 23},
+ {F_RSSI_DEC_DEFAULT_VALUE, 85},
+ {F_RSSI_CHANN_DEFAULT_VALUE, 66},
+ {F_DEC_GAIN_OFFSET, 7},
+ {F_CHAN_GAIN_OFFSET, 6},
+
+ /* LoRa 'multi' demodulator setup */
+ {F_SNR_AVG_CST, 3},
+ {F_FRAME_SYNCH_PEAK1_POS, 3}, // Public LoRa network
+ {F_FRAME_SYNCH_PEAK2_POS, 4}, // Public LoRa network
+
+ /* LoRa standalone 'MBWSSF' demodulator setup */
+ {F_MBWSSF_FRAME_SYNCH_PEAK1_POS, 3}, // Public LoRa network
+ {F_MBWSSF_FRAME_SYNCH_PEAK2_POS, 4}, // Public LoRa network
+
+ /* Improvement of ref clock freq error tolerance */
+ {F_ADJUST_MODEM_START_OFFSET_RDX4L, 1},
+ {F_ADJUST_MODEM_START_OFFSET_SF12_RDX4L, (4094 & 0xFF)},
+ {F_ADJUST_MODEM_START_OFFSET_SF12_RDX4H, (4094 >> 8)},
+ {F_CORR_MAC_GAIN, 7},
+
+ /* FSK datapath setup */
+ {F_FSK_RX_INVERT, 1},
+ {F_FSK_MODEM_INVERT_IQ, 1},
+
+ /* FSK demodulator setup */
+ {F_FSK_RSSI_LENGTH, 4},
+ {F_FSK_PKT_MODE, 1},
+ {F_FSK_CRC_EN, 1},
+ {F_FSK_DCFREE_ENC, 2},
+ {F_FSK_ERROR_OSR_TOL, 10},
+ {F_FSK_PKT_LENGTH, 255},
+ {F_FSK_PATTERN_TIMEOUT_CFGL, 128},
+
+ /* TX general parameters */
+ {F_TX_START_DELAYL, (TX_START_DELAY_DEFAULT & 0xFF)},
+ {F_TX_START_DELAYH, (TX_START_DELAY_DEFAULT >> 8)},
+
+ /* TX LoRa */
+ {F_TX_SWAP_IQ, 1},
+ {F_TX_FRAME_SYNCH_PEAK1_POS, 3}, // Public LoRa network
+ {F_TX_FRAME_SYNCH_PEAK2_POS, 4}, // Public LoRa network
+
+ /* TX FSK */
+ {F_FSK_TX_GAUSSIAN_SELECT_BT, 2},
+};
+
static const struct reg_field sx130x_regmap_fields[] = {
/* PAGE */
[F_SOFT_RESET] = REG_FIELD(SX1301_PAGE, 7, 7),
@@ -54,6 +111,59 @@ static const struct reg_field sx130x_regmap_fields[] = {
[F_TX_TRIG_IMMEDIATE] = REG_FIELD(SX1301_TX_TRIG, 0, 0),
[F_TX_TRIG_DELAYED] = REG_FIELD(SX1301_TX_TRIG, 1, 1),
[F_TX_TRIG_GPS] = REG_FIELD(SX1301_TX_TRIG, 2, 2),
+
+ /* RSSI_X_FILTER_ALPHA */
+ [F_RSSI_BB_FILTER_ALPHA] = REG_FIELD(SX1301_RSSI_BB_FILTER_ALPHA, 0, 4),
+ [F_RSSI_DEC_FILTER_ALPHA] = REG_FIELD(SX1301_RSSI_DEC_FILTER_ALPHA, 0, 4),
+ [F_RSSI_CHANN_FILTER_ALPHA] = REG_FIELD(SX1301_RSSI_CHANN_FILTER_ALPHA, 0, 4),
+ /* RSSI_X_DEFAULT_VALUE */
+ [F_RSSI_BB_DEFAULT_VALUE] = REG_FIELD(SX1301_RSSI_BB_DEFAULT_VALUE, 0, 7),
+ [F_RSSI_DEC_DEFAULT_VALUE] = REG_FIELD(SX1301_RSSI_DEC_DEFAULT_VALUE, 0, 7),
+ [F_RSSI_CHANN_DEFAULT_VALUE] = REG_FIELD(SX1301_RSSI_CHANN_DEFAULT_VALUE, 0, 7),
+ /* GAIN_OFFSET */
+ [F_DEC_GAIN_OFFSET] = REG_FIELD(SX1301_GAIN_OFFSET, 0, 3),
+ [F_CHAN_GAIN_OFFSET] = REG_FIELD(SX1301_GAIN_OFFSET, 4, 7),
+
+ [F_SNR_AVG_CST] = REG_FIELD(SX1301_MISC_CFG1, 4, 5),
+ [F_FRAME_SYNCH_PEAK1_POS] = REG_FIELD(SX1301_FRAME_SYNCH, 0, 3),
+ [F_FRAME_SYNCH_PEAK2_POS] = REG_FIELD(SX1301_FRAME_SYNCH, 4, 7),
+
+ [F_MBWSSF_FRAME_SYNCH_PEAK1_POS] = REG_FIELD(SX1301_BHSYNCPOS, 0, 3),
+ [F_MBWSSF_FRAME_SYNCH_PEAK2_POS] = REG_FIELD(SX1301_BHSYNCPOS, 4, 7),
+
+ [F_ADJUST_MODEM_START_OFFSET_RDX4L] =
+ REG_FIELD(SX1301_MODEM_START_RDX4L, 0, 7), // 12 bits
+ [F_ADJUST_MODEM_START_OFFSET_RDX4H] =
+ REG_FIELD(SX1301_MODEM_START_RDX4H, 0, 3),
+ [F_ADJUST_MODEM_START_OFFSET_SF12_RDX4L] =
+ REG_FIELD(SX1301_MODEM_START_SF12_RDX4L, 0, 7), // 12 bits
+ [F_ADJUST_MODEM_START_OFFSET_SF12_RDX4H] =
+ REG_FIELD(SX1301_MODEM_START_SF12_RDX4H, 0, 3),
+ [F_CORR_MAC_GAIN] = REG_FIELD(SX1301_CORR_CFG, 4, 6),
+
+ [F_FSK_RSSI_LENGTH] = REG_FIELD(SX1301_FSK_CFG1, 3, 5),
+ [F_FSK_RX_INVERT] = REG_FIELD(SX1301_FSK_CFG1, 6, 6),
+ [F_FSK_PKT_MODE] = REG_FIELD(SX1301_FSK_CFG1, 7, 7),
+
+ [F_FSK_MODEM_INVERT_IQ] = REG_FIELD(SX1301_IQCFG, 5, 5),
+
+ [F_FSK_CRC_EN] = REG_FIELD(SX1301_FSK_CFG2, 3, 3),
+ [F_FSK_DCFREE_ENC] = REG_FIELD(SX1301_FSK_CFG2, 4, 5),
+ [F_FSK_ERROR_OSR_TOL] = REG_FIELD(SX1301_FSK_ERROR_OSR_TOL, 0, 4),
+ [F_FSK_PKT_LENGTH] = REG_FIELD(SX1301_FSK_PKT_LENGTH, 0, 7),
+ [F_FSK_PATTERN_TIMEOUT_CFGL] =
+ REG_FIELD(SX1301_FSK_PATTERN_TIMEOUT_CFGL, 0, 7), // 10 bits
+ [F_FSK_PATTERN_TIMEOUT_CFGH] =
+ REG_FIELD(SX1301_FSK_PATTERN_TIMEOUT_CFGH, 0, 1),
+
+ [F_TX_START_DELAYL] = REG_FIELD(SX1301_TX_START_DELAYL, 0, 7), // 16 bit
+ [F_TX_START_DELAYH] = REG_FIELD(SX1301_TX_START_DELAYH, 0, 7),
+
+ [F_TX_SWAP_IQ] = REG_FIELD(SX1301_TX_CFG2, 7, 7),
+ [F_TX_FRAME_SYNCH_PEAK1_POS] = REG_FIELD(SX1301_TX_FRAME_SYNCH, 0, 3),
+ [F_TX_FRAME_SYNCH_PEAK2_POS] = REG_FIELD(SX1301_TX_FRAME_SYNCH, 4, 7),
+
+ [F_FSK_TX_GAUSSIAN_SELECT_BT] = REG_FIELD(SX1301_FSK_TX, 1, 2),
};
struct sx130x_tx_header {
@@ -263,6 +373,23 @@ static int sx130x_soft_reset(struct sx130x_priv *priv)
return 0;
}
+static int sx130x_fields_patch(struct sx130x_priv *priv)
+{
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(sx130x_regmap_fields_patch); i++) {
+ ret = sx130x_field_force_write(priv, sx130x_regmap_fields_patch[i].field,
+ sx130x_regmap_fields_patch[i].val);
+ if (ret) {
+ dev_err(priv->dev,
+ "Failed to patch regmap field: %d\n", i);
+ break;
+ }
+ }
+
+ return ret;
+}
+
static int sx130x_agc_ram_read(struct sx130x_priv *priv, u8 addr, unsigned int *val)
{
int ret;
@@ -881,7 +1008,9 @@ static int sx130x_loradev_open(struct net_device *netdev)
if (ret)
goto err_calibrate;
- /* TODO Load constant adjustments, patches */
+ ret = sx130x_fields_patch(priv);
+ if (ret)
+ return ret;
/* TODO Frequency time drift */
diff --git a/drivers/net/lora/sx130x.h b/drivers/net/lora/sx130x.h
index 38f1b58b2165..121c8a35b5c3 100644
--- a/drivers/net/lora/sx130x.h
+++ b/drivers/net/lora/sx130x.h
@@ -29,6 +29,9 @@
#define SX1301_PA_GAIN_OFFSET 6
#define SX1301_DAC_GAIN_OFFSET 4
+/* Calibrated value for 500KHz BW and notch filter disabled */
+#define TX_START_DELAY_DEFAULT 1497
+
/* Page independent */
#define SX1301_PAGE 0x00
#define SX1301_VER 0x01
@@ -49,12 +52,39 @@
#define SX1301_PAGE_BASE(n) (SX1301_VIRT_BASE + (SX1301_PAGE_LEN * n))
/* Page 0 */
+#define SX1301_IQCFG (SX1301_PAGE_BASE(0) + 0x21)
#define SX1301_CHRS (SX1301_PAGE_BASE(0) + 0x23)
+#define SX1301_CORR_CFG (SX1301_PAGE_BASE(0) + 0x4E)
+#define SX1301_MODEM_START_RDX4L (SX1301_PAGE_BASE(0) + 0x51)
+#define SX1301_MODEM_START_RDX4H (SX1301_PAGE_BASE(0) + 0x52)
+#define SX1301_MODEM_START_SF12_RDX4L (SX1301_PAGE_BASE(0) + 0x53)
+#define SX1301_MODEM_START_SF12_RDX4H (SX1301_PAGE_BASE(0) + 0x54)
+#define SX1301_FRAME_SYNCH (SX1301_PAGE_BASE(0) + 0x5F)
+#define SX1301_MISC_CFG1 (SX1301_PAGE_BASE(0) + 0x63)
+#define SX1301_GAIN_OFFSET (SX1301_PAGE_BASE(0) + 0x68)
#define SX1301_FORCE_CTRL (SX1301_PAGE_BASE(0) + 0x69)
#define SX1301_MCU_CTRL (SX1301_PAGE_BASE(0) + 0x6A)
+#define SX1301_RSSI_BB_DEFAULT_VALUE (SX1301_PAGE_BASE(0) + 0x6C)
+#define SX1301_RSSI_DEC_DEFAULT_VALUE (SX1301_PAGE_BASE(0) + 0x6D)
+#define SX1301_RSSI_CHANN_DEFAULT_VALUE (SX1301_PAGE_BASE(0) + 0x6E)
+#define SX1301_RSSI_BB_FILTER_ALPHA (SX1301_PAGE_BASE(0) + 0x6F)
+#define SX1301_RSSI_DEC_FILTER_ALPHA (SX1301_PAGE_BASE(0) + 0x70)
+#define SX1301_RSSI_CHANN_FILTER_ALPHA (SX1301_PAGE_BASE(0) + 0x71)
/* Page 1 */
#define SX1301_TX_TRIG (SX1301_PAGE_BASE(1) + 0x21)
+#define SX1301_TX_START_DELAYL (SX1301_PAGE_BASE(1) + 0x22)
+#define SX1301_TX_START_DELAYH (SX1301_PAGE_BASE(1) + 0x23)
+#define SX1301_TX_FRAME_SYNCH (SX1301_PAGE_BASE(1) + 0x24)
+#define SX1301_TX_CFG2 (SX1301_PAGE_BASE(1) + 0x2A)
+#define SX1301_BHSYNCPOS (SX1301_PAGE_BASE(1) + 0x2E)
+#define SX1301_FSK_CFG1 (SX1301_PAGE_BASE(1) + 0x3F)
+#define SX1301_FSK_CFG2 (SX1301_PAGE_BASE(1) + 0x40)
+#define SX1301_FSK_ERROR_OSR_TOL (SX1301_PAGE_BASE(1) + 0x41)
+#define SX1301_FSK_PKT_LENGTH (SX1301_PAGE_BASE(1) + 0x4C)
+#define SX1301_FSK_TX (SX1301_PAGE_BASE(1) + 0x4D)
+#define SX1301_FSK_PATTERN_TIMEOUT_CFGL (SX1301_PAGE_BASE(1) + 0x53)
+#define SX1301_FSK_PATTERN_TIMEOUT_CFGH (SX1301_PAGE_BASE(1) + 0x54)
/* Page 2 */
#define SX1301_RADIO_A_SPI_DATA (SX1301_PAGE_BASE(2) + 0x21)
@@ -98,6 +128,51 @@ enum sx130x_fields {
F_TX_TRIG_IMMEDIATE,
F_TX_TRIG_DELAYED,
F_TX_TRIG_GPS,
+
+ F_RSSI_BB_FILTER_ALPHA,
+ F_RSSI_DEC_FILTER_ALPHA,
+ F_RSSI_CHANN_FILTER_ALPHA,
+
+ F_RSSI_BB_DEFAULT_VALUE,
+ F_RSSI_DEC_DEFAULT_VALUE,
+ F_RSSI_CHANN_DEFAULT_VALUE,
+
+ F_DEC_GAIN_OFFSET,
+ F_CHAN_GAIN_OFFSET,
+
+ F_SNR_AVG_CST,
+ F_FRAME_SYNCH_PEAK1_POS,
+ F_FRAME_SYNCH_PEAK2_POS,
+
+ F_MBWSSF_FRAME_SYNCH_PEAK1_POS,
+ F_MBWSSF_FRAME_SYNCH_PEAK2_POS,
+
+ F_ADJUST_MODEM_START_OFFSET_RDX4L,
+ F_ADJUST_MODEM_START_OFFSET_RDX4H,
+ F_ADJUST_MODEM_START_OFFSET_SF12_RDX4L,
+ F_ADJUST_MODEM_START_OFFSET_SF12_RDX4H,
+ F_CORR_MAC_GAIN,
+
+ F_FSK_RX_INVERT,
+ F_FSK_MODEM_INVERT_IQ,
+
+ F_FSK_RSSI_LENGTH,
+ F_FSK_PKT_MODE,
+ F_FSK_CRC_EN,
+ F_FSK_DCFREE_ENC,
+ F_FSK_ERROR_OSR_TOL,
+ F_FSK_PKT_LENGTH,
+ F_FSK_PATTERN_TIMEOUT_CFGL,
+ F_FSK_PATTERN_TIMEOUT_CFGH,
+
+ F_TX_START_DELAYL,
+ F_TX_START_DELAYH,
+
+ F_TX_SWAP_IQ,
+ F_TX_FRAME_SYNCH_PEAK1_POS,
+ F_TX_FRAME_SYNCH_PEAK2_POS,
+
+ F_FSK_TX_GAUSSIAN_SELECT_BT,
};
struct regmap *sx130x_get_regmap(struct device *dev);
--
2.17.1
Powered by blists - more mailing lists