From: Ben Whitten <ben.whit...@gmail.com>

The AGC software requires loading of a power lookup table on initialisation
prior to transmission.
The fields required are digital, pa, dac, and mixer gain. These values are
typically hardware specific and calibrated for a particular power output at
the card rf port.
The format of the DT binding is <power(s8) dig(u8) pa(u8) dac(u8) mix(u8)>
a valid entry is 5 bytes, a valid table is up to 16 entries.

Signed-off-by: Ben Whitten <ben.whit...@gmail.com>
---
 drivers/net/lora/sx130x.c | 29 +++++++++++++++++++++++++++++
 drivers/net/lora/sx130x.h |  2 ++
 2 files changed, 31 insertions(+)

diff --git a/drivers/net/lora/sx130x.c b/drivers/net/lora/sx130x.c
index 3174fc695d54..70cfb4532b51 100644
--- a/drivers/net/lora/sx130x.c
+++ b/drivers/net/lora/sx130x.c
@@ -51,6 +51,14 @@ static const struct reg_field sx130x_regmap_fields[] = {
                REG_FIELD(SX1301_EMERGENCY_FORCE_HOST_CTRL, 0, 0),
 };
 
+struct sx130x_tx_gain_lut {
+       s8 power;       /* dBm measured at board connector */
+       u8 dig_gain;
+       u8 pa_gain;
+       u8 dac_gain;
+       u8 mix_gain;
+};
+
 struct sx130x_priv {
        struct lora_dev_priv    lora;
        struct device           *dev;
@@ -59,6 +67,8 @@ struct sx130x_priv {
        struct regmap_field     
*regmap_fields[ARRAY_SIZE(sx130x_regmap_fields)];
        struct mutex            io_lock;
        void                    *drvdata;
+       struct sx130x_tx_gain_lut tx_gain_lut[SX1301_TX_GAIN_LUT_MAX];
+       u8 tx_gain_lut_size;
 };
 
 struct regmap *sx130x_get_regmap(struct device *dev)
@@ -589,6 +599,7 @@ int sx130x_early_probe(struct regmap *regmap, struct 
gpio_desc *rst)
        struct device *dev = regmap_get_device(regmap);
        struct net_device *netdev;
        struct sx130x_priv *priv;
+       const u8 *power_lut;
        int ret;
        int i;
 
@@ -620,6 +631,24 @@ int sx130x_early_probe(struct regmap *regmap, struct 
gpio_desc *rst)
                        return ret;
                }
        }
+
+       if (IS_ENABLED(CONFIG_OF)) {
+               power_lut = of_get_property(dev->of_node, "power-lut", &ret);
+               if (power_lut && (ret % 5)) {
+                       dev_err(dev, "Invalid power table\n");
+                       return -EINVAL;
+               } else if (power_lut) {
+                       priv->tx_gain_lut_size = ret / 5;
+                       for (i = 0; i < priv->tx_gain_lut_size; i++) {
+                               priv->tx_gain_lut[i].power = *(power_lut++);
+                               priv->tx_gain_lut[i].dig_gain = *(power_lut++);
+                               priv->tx_gain_lut[i].pa_gain = *(power_lut++) & 
0x03;
+                               priv->tx_gain_lut[i].dac_gain = *(power_lut++) 
& 0x03;
+                               priv->tx_gain_lut[i].mix_gain = *(power_lut++) 
& 0x0F;
+                       }
+               }
+       }
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(sx130x_early_probe);
diff --git a/drivers/net/lora/sx130x.h b/drivers/net/lora/sx130x.h
index abab2ee42512..6330777f4eac 100644
--- a/drivers/net/lora/sx130x.h
+++ b/drivers/net/lora/sx130x.h
@@ -18,6 +18,8 @@
 #define SX1301_MCU_AGC_FW_VERSION 4
 #define SX1301_MCU_AGC_CAL_FW_VERSION 2
 
+#define SX1301_TX_GAIN_LUT_MAX 16
+
 /* Page independent */
 #define SX1301_PAGE     0x00
 #define SX1301_VER      0x01
-- 
2.17.1

Reply via email to