[PATCH lora-next 00/11] net: lora: Get SX130x to transmit lora packets

2019-01-28 Thread Ben Whitten
Hello,

This series adds setup nessesary to transmit lora packets from the
SX1301x, it builds on the comments on the RFC [1] to a point where
the card is capable of sending out a LoRa modulated signal using
transmission paramaters from the LORA socket address.

As patches have been refactored and split up extensivly to bite
sized chunks they do not include individual RFC -> v1, this is
covered in this letter.

The setup involves starting the firmware up inside the card by
providing a LUT of its internal gain values calibrated against
the card output. As this information is hardware specific it
is added as a binding in the DT, with documentation to match.
Binding patch is based off a commit of the basic documentation
under review [2]
Not captured here are commands to set this gain table for use
in devices which do not use DT.

As _stat_xmit cannot sleep we spin the tx function to a work queue
so we can write to the SPI backed regmaps.

As proposed [3] as one way of getting lora packet metadata to
the driver is by using the socket address to encode spreading
factor, coding rate, bandwidth etc. The corresponding translation
is added on the driver side, populating the test transmission with
real values and has been tested to show changing bandwidths.
To perform testing a tx_test [4] was used to show changing
parameters on a spectrum analyser.

We also add patches to the defaults in the SX130x to fill in a TODO
in our initialisation.

Thanks,
Ben Whitten

[1] http://lists.infradead.org/pipermail/linux-lpwan/2018-December/19.html
[2] http://lists.infradead.org/pipermail/linux-lpwan/2019-January/000150.html
[3] 
https://events.linuxfoundation.org/wp-content/uploads/2017/12/ELCE2018_LoRa_final_Andreas-Farber.pdf
 slide 16
[4] https://github.com/BWhitten/lora-modules/blob/master/tx_test.c

RFC -> v1
* Split up commits to sensible order and logical block sizes.
* Added DT binding for TX gain LUT.
* Fixed spelling mistakes.
* Converted metadata enums to suggested integers with suitable sizes.
* Fixed out by 1 in test transmission population.

CC: linux-lp...@lists.infradead.org
CC: netdev@vger.kernel.org
CC: linux-ker...@vger.kernel.org


Ben Whitten (11):
  dt-bindings: net: lora: sx130x: add power lut binding
  net: lora: sx130x: add loading of tx lut from DT
  net: lora: sx130x: add CHRS to volatile register list
  net: lora: sx130x: add helper function for writing to the SX130x MCU
  net: lora: sx130x: initialise AGC
  net: lora: sx130x: add detail to TODO in setup
  net: lora: sx130x: add work queue to tx path
  net: lora: sx130x: add test transmission
  net: lora: introduce lora socket addressing for metadata
  net: lora: sx130x: make use of lora address metadata in transmission
  net: lora: sx130x: add patch to register fields

 .../bindings/net/lora/semtech,sx130x.yaml |  13 +
 drivers/net/lora/sx130x.c | 521 +-
 drivers/net/lora/sx130x.h |  97 
 include/linux/lora/skb.h  |   9 +
 include/uapi/linux/lora.h |  14 +
 net/lora/dgram.c  |  45 ++
 6 files changed, 697 insertions(+), 2 deletions(-)

-- 
2.17.1



[PATCH lora-next 02/11] net: lora: sx130x: add loading of tx lut from DT

2019-01-28 Thread Ben Whitten
From: Ben Whitten 

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 
a valid entry is 5 bytes, a valid table is up to 16 entries.

Signed-off-by: Ben Whitten 
---
 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_privlora;
struct device   *dev;
@@ -59,6 +67,8 @@ struct sx130x_priv {
struct regmap_field 
*regmap_fields[ARRAY_SIZE(sx130x_regmap_fields)];
struct mutexio_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



[PATCH lora-next 01/11] dt-bindings: net: lora: sx130x: add power lut binding

2019-01-28 Thread Ben Whitten
From: Ben Whitten 

Adding power lookup table for the concentrator specified in DT.

These values are calibrated for the hardware and are unique to hardware
designs and certifications.

First byte is signed power in dBm measured at the rf connector.
Second byte is unsigned value for DIGITAL gain.
Third byte is unsigned value for PA gain, 2 bits only.
Fourth byte is unsigned value for DAC gain, 2 bits only.
Fifth byte is unsigned value for MIXER gain, 4 bits only.

Signed-off-by: Ben Whitten 
---
 .../bindings/net/lora/semtech,sx130x.yaml   | 13 +
 1 file changed, 13 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml 
b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
index 24fad1218735..187fa2090a0b 100644
--- a/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
+++ b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
@@ -37,6 +37,15 @@ properties:
 maxItems: 1
 description: A connection of the reset gpio line.
 
+  power-lut:
+description: Power lookup table for the concentrator.
+  Consisting of maximum 16 entries, each entry having the following format;
+  First byte is signed power in dBm measured at the rf connector.
+  Second byte is unsigned value for DIGITAL gain.
+  Third byte is unsigned value for PA gain, 2 bits only.
+  Fourth byte is unsigned value for DAC gain, 2 bits only.
+  Fifth byte is unsigned value for MIXER gain, 4 bits only.
+
   radio-spi:
 type: object
 description: The concentrator can have two radios connected which are
@@ -83,6 +92,10 @@ examples:
 reset-gpios = <&pioB 27 GPIO_ACTIVE_HIGH>;
 spi-max-frequency = <800>;
 
+   power-lut =   [ 00 00 00 03 09
+   03 00 00 03 0C
+   04 00 00 03 0D ];
+
 radio-spi {
   #address-cells = <1>;
   #size-cells = <0>;
-- 
2.17.1



[PATCH lora-next 04/11] net: lora: sx130x: add helper function for writing to the SX130x MCU

2019-01-28 Thread Ben Whitten
From: Ben Whitten 

The transaction to the internal MCU starts with CMD_WAIT to start a
transaction, written to CHRS followed by writing the value, the status of
the command is read back from AGCSTS.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx130x.c | 28 
 drivers/net/lora/sx130x.h |  2 ++
 2 files changed, 30 insertions(+)

diff --git a/drivers/net/lora/sx130x.c b/drivers/net/lora/sx130x.c
index 529ca6622878..818a1c9192b3 100644
--- a/drivers/net/lora/sx130x.c
+++ b/drivers/net/lora/sx130x.c
@@ -337,6 +337,34 @@ static int sx130x_load_firmware(struct sx130x_priv *priv, 
int mcu, const struct
return 0;
 }
 
+static int sx130x_agc_transaction(struct sx130x_priv *priv, unsigned int val,
+ unsigned int *status)
+{
+   int ret;
+
+   ret = regmap_write(priv->regmap, SX1301_CHRS, SX1301_AGC_CMD_WAIT);
+   if (ret) {
+   dev_err(priv->dev, "AGC transaction start failed\n");
+   return ret;
+   }
+   usleep_range(1000, 2000);
+
+   ret = regmap_write(priv->regmap, SX1301_CHRS, val);
+   if (ret) {
+   dev_err(priv->dev, "AGC transaction value failed\n");
+   return ret;
+   }
+   usleep_range(1000, 2000);
+
+   ret = regmap_read(priv->regmap, SX1301_AGCSTS, status);
+   if (ret) {
+   dev_err(priv->dev, "AGC status read failed\n");
+   return ret;
+   }
+
+   return 0;
+}
+
 static int sx130x_agc_calibrate(struct sx130x_priv *priv)
 {
const struct firmware *fw;
diff --git a/drivers/net/lora/sx130x.h b/drivers/net/lora/sx130x.h
index 6330777f4eac..69bb9cbd1aba 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_AGC_CMD_WAIT 16
+
 #define SX1301_TX_GAIN_LUT_MAX 16
 
 /* Page independent */
-- 
2.17.1



[PATCH lora-next 06/11] net: lora: sx130x: add detail to TODO in setup

2019-01-28 Thread Ben Whitten
From: Ben Whitten 

Setup requires a more steps to be complete, call these out specifically
so they are not missed.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx130x.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/net/lora/sx130x.c b/drivers/net/lora/sx130x.c
index 18acfc8e934d..88932fbbb598 100644
--- a/drivers/net/lora/sx130x.c
+++ b/drivers/net/lora/sx130x.c
@@ -688,7 +688,17 @@ static int sx130x_loradev_open(struct net_device *netdev)
if (ret)
goto err_calibrate;
 
-   /* TODO */
+   /* TODO Load constant adjustments, patches */
+
+   /* TODO Frequency time drift */
+
+   /* TODO Configure lora multi demods, bitfield of active */
+
+   /* TODO Load concentrator multi channel frequencies */
+
+   /* TODO enable the correlator on enabled frequencies */
+
+   /* TODO PPM, and modem enable */
 
ret = sx130x_load_all_firmware(priv);
if (ret)
-- 
2.17.1



[PATCH lora-next 03/11] net: lora: sx130x: add CHRS to volatile register list

2019-01-28 Thread Ben Whitten
From: Ben Whitten 

The CHRS register is used in transactions to the MCU within the SX130x,
we need to always write to it.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx130x.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/lora/sx130x.c b/drivers/net/lora/sx130x.c
index 70cfb4532b51..529ca6622878 100644
--- a/drivers/net/lora/sx130x.c
+++ b/drivers/net/lora/sx130x.c
@@ -134,6 +134,7 @@ static bool sx130x_volatile_reg(struct device *dev, 
unsigned int reg)
case SX1301_MPD:
case SX1301_AGCSTS:
 
+   case SX1301_CHRS:
case SX1301_MCU_CTRL:
 
case SX1301_RADIO_A_SPI_DATA_RB:
-- 
2.17.1



[PATCH lora-next 05/11] net: lora: sx130x: initialise AGC

2019-01-28 Thread Ben Whitten
From: Ben Whitten 

Initialisation of the AGC firmware requires a couple of steps to be
completed;
- Loading a TX LUT
- Loading the two MSBs for the radio tx synthesizer frequencies,
  (Always 3 if f > 768 for SX1257 and SX1258 or f > 384 for SX1255)
- Loading a firmware option
- Finish initialisation by writing intended value of the radio select
  register.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx130x.c | 110 ++
 drivers/net/lora/sx130x.h |   7 +++
 2 files changed, 117 insertions(+)

diff --git a/drivers/net/lora/sx130x.c b/drivers/net/lora/sx130x.c
index 818a1c9192b3..18acfc8e934d 100644
--- a/drivers/net/lora/sx130x.c
+++ b/drivers/net/lora/sx130x.c
@@ -537,6 +537,111 @@ static int sx130x_load_all_firmware(struct sx130x_priv 
*priv)
return 0;
 }
 
+static int sx130x_load_tx_gain_lut(struct sx130x_priv *priv)
+{
+   struct net_device *netdev = dev_get_drvdata(priv->dev);
+   struct sx130x_tx_gain_lut *lut = priv->tx_gain_lut;
+   unsigned int status, val;
+   int ret, i;
+
+   for (i = 0; i < priv->tx_gain_lut_size; i++) {
+   val = lut->pa_gain << SX1301_PA_GAIN_OFFSET;
+   val |= lut->dac_gain << SX1301_DAC_GAIN_OFFSET;
+   val |= lut->mix_gain;
+
+   netdev_info(netdev, "AGC LUT entry %d dBm: 0x%02x\n", 
lut->power, val);
+   ret = sx130x_agc_transaction(priv, val, &status);
+   if (ret) {
+   netdev_err(netdev, "AGC LUT load failed\n");
+   return ret;
+   }
+   if (status != (SX1301_AGC_STATUS_SUCCESS | i)) {
+   netdev_err(netdev, "AGC firmware LUT init error: 
0x%02x", status);
+   return -ENXIO;
+   }
+   lut++;
+   }
+
+   /* Abort the transaction if there are less then 16 entries */
+   if (priv->tx_gain_lut_size < SX1301_TX_GAIN_LUT_MAX) {
+   ret = sx130x_agc_transaction(priv, SX1301_AGC_CMD_ABORT, 
&status);
+   if (ret) {
+   netdev_err(netdev, "AGC LUT abort failed\n");
+   return ret;
+   }
+   if (status != SX1301_AGC_STATUS_SUCCESS) {
+   netdev_err(netdev, "AGC firmware LUT abort error: 
0x%02x", status);
+   return -ENXIO;
+   }
+   }
+
+   return ret;
+};
+
+static int sx130x_agc_init(struct sx130x_priv *priv)
+{
+   struct net_device *netdev = dev_get_drvdata(priv->dev);
+   unsigned int tx_msb;
+   unsigned int val;
+   int ret;
+
+   ret = regmap_read(priv->regmap, SX1301_AGCSTS, &val);
+   if (ret) {
+   netdev_err(netdev, "AGC status read failed\n");
+   return ret;
+   }
+   if (val != SX1301_AGC_STATUS_READY) {
+   netdev_err(netdev, "AGC firmware init failure: 0x%02x\n", val);
+   return -ENXIO;
+   }
+
+   ret = sx130x_load_tx_gain_lut(priv);
+   if (ret)
+   return ret;
+
+   /*
+* Load Tx freq MSBs
+* Always 3 if f > 768 for SX1257 and SX1258 or f > 384 for SX1255
+*/
+   tx_msb = 3; /* TODO detect radio type */
+
+   ret = sx130x_agc_transaction(priv, tx_msb, &val);
+   if (ret) {
+   netdev_err(netdev, "AGC Tx MSBs load failed\n");
+   return ret;
+   }
+   if (val != (SX1301_AGC_STATUS_SUCCESS | tx_msb)) {
+   netdev_err(netdev, "AGC firmware Tx MSBs error: 0x%02x", val);
+   return -ENXIO;
+   }
+
+   /* Load chan_select firmware option */
+   ret = sx130x_agc_transaction(priv, 0, &val);
+   if (ret) {
+   netdev_err(netdev, "AGC chan select failed\n");
+   return ret;
+   }
+   if (val != (SX1301_AGC_STATUS_SUCCESS | 0)) {
+   netdev_err(netdev, "AGC firmware chan select error: 0x%02x", 
val);
+   return -ENXIO;
+   }
+
+   /* End AGC firmware init and check status */
+   /* TODO load the intended value of radio_select here
+* LORA IF mapping to radio A/B (per bit, 0=A, 1=B) */
+   ret = sx130x_agc_transaction(priv, 0, &val);
+   if (ret) {
+   netdev_err(netdev, "AGC radio select failed\n");
+   return ret;
+   }
+   if (val != SX1301_AGC_STATUS_INITIALISED) {
+   netdev_err(netdev, "AGC firmware init error: 0x%02x", val);
+   return -ENXIO;
+   }
+
+   return ret;
+}
+
 static netdev_tx_t sx130x_loradev_start_xmit(struct sk_buff *skb, struct 
net_device *netdev)
 {
if (skb->protocol != htons(ETH_P_LORA)) {
@@ -589,6 +694,11 @@ static int sx130x_loradev_open(

[PATCH lora-next 10/11] net: lora: sx130x: make use of lora address metadata in transmission

2019-01-28 Thread Ben Whitten
We take the metadata encoded in the lora address and apply it to the
outgoing transmission.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx130x.c | 58 ---
 1 file changed, 48 insertions(+), 10 deletions(-)

diff --git a/drivers/net/lora/sx130x.c b/drivers/net/lora/sx130x.c
index f96f32d2e1ff..428e82b4ccb8 100644
--- a/drivers/net/lora/sx130x.c
+++ b/drivers/net/lora/sx130x.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "sx130x.h"
@@ -688,12 +689,13 @@ static int sx130x_agc_init(struct sx130x_priv *priv)
return ret;
 }
 
-static int sx130x_tx(struct sx130x_priv *priv, void *data, int len)
+static int sx130x_tx(struct sx130x_priv *priv, struct sk_buff *skb)
 {
int ret, i;
u8 buff[256 + 16];
struct sx130x_tx_header *hdr = (struct sx130x_tx_header *)buff;
struct net_device *netdev = dev_get_drvdata(priv->dev);
+   u8 sf;
 
/* TODO general checks to make sure we CAN send */
 
@@ -722,11 +724,47 @@ static int sx130x_tx(struct sx130x_priv *priv, void 
*data, int len)
hdr->tx_power = 15; /* HACK power entry 15 */
 
hdr->u.lora.crc16_en = 1; /* Enable CRC16 */
-   hdr->u.lora.cr = 1; /* CR 4/5 */
-   hdr->u.lora.sf = 7; /* SF7 */
-   hdr->u.lora.payload_len = len; /* Set the data len to the skb len */
+
+   switch (lora_skb_prv(skb)->cr) {
+   case 5:
+   hdr->u.lora.cr = 1; /* CR 4/5 */
+   break;
+   case 6:
+   hdr->u.lora.cr = 2; /* CR 4/6 */
+   break;
+   case 7:
+   hdr->u.lora.cr = 3; /* CR 4/7 */
+   break;
+   case 8:
+   hdr->u.lora.cr = 4; /* CR 4/8 */
+   break;
+   default:
+   return -ENXIO;
+   }
+
+   sf = lora_skb_prv(skb)->sf;
+   if ((sf < 6) || (sf > 12))
+   return -ENXIO;
+
+   hdr->u.lora.sf = sf;
+
+   hdr->u.lora.payload_len = skb->len; /* Set the data length */
hdr->u.lora.implicit_header = 0; /* No implicit header */
-   hdr->u.lora.mod_bw = 0; /* Set 125KHz BW */
+
+   switch(lora_skb_prv(skb)->bw) {
+   case 125:
+   hdr->u.lora.mod_bw = 0; /* 125KHz BW */
+   break;
+   case 250:
+   hdr->u.lora.mod_bw = 1; /* 250KHz BW */
+   break;
+   case 500:
+   hdr->u.lora.mod_bw = 2; /* 500KHz BW */
+   break;
+   default:
+   return -ENXIO;
+   }
+
hdr->u.lora.ppm_offset = 0; /* TODO no ppm offset? */
hdr->u.lora.invert_pol = 0; /* TODO set no inverted polarity */
 
@@ -737,7 +775,7 @@ static int sx130x_tx(struct sx130x_priv *priv, void *data, 
int len)
 
/* Copy the TX data into the buffer ready to go */
 
-   memcpy((void *)&buff[16], data, len);
+   memcpy((void *)&buff[16], skb->data, skb->len);
 
/* Reset any transmissions */
ret = regmap_write(priv->regmap, SX1301_TX_TRIG, 0);
@@ -749,7 +787,7 @@ static int sx130x_tx(struct sx130x_priv *priv, void *data, 
int len)
if (ret)
return ret;
ret = regmap_noinc_write(priv->regmap, SX1301_TX_DATA_BUF_DATA, buff,
-len + 16);
+skb->len + 16);
if (ret)
return ret;
 
@@ -758,8 +796,8 @@ static int sx130x_tx(struct sx130x_priv *priv, void *data, 
int len)
if (ret)
return ret;
 
-   netdev_dbg(netdev, "Transmitting packet of size %d: ", len);
-   for (i = 0; i < len + 16; i++)
+   netdev_dbg(netdev, "Transmitting packet of size %d: ", skb->len);
+   for (i = 0; i < skb->len + 16; i++)
netdev_dbg(netdev, "%X", buff[i]);
 
return ret;
@@ -791,7 +829,7 @@ static void sx130x_tx_work_handler(struct work_struct *ws)
netdev_dbg(netdev, "%s\n", __func__);
 
if (priv->tx_skb) {
-   ret = sx130x_tx(priv, priv->tx_skb->data, priv->tx_skb->len);
+   ret = sx130x_tx(priv, priv->tx_skb);
if (ret) {
netdev->stats.tx_errors++;
} else {
-- 
2.17.1



[PATCH lora-next 07/11] net: lora: sx130x: add work queue to tx path

2019-01-28 Thread Ben Whitten
As we are not allowed to sleep in _start_xmit, we need to add a work queue
to handle transmission of the packets.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx130x.c | 50 ++-
 1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/drivers/net/lora/sx130x.c b/drivers/net/lora/sx130x.c
index 88932fbbb598..820ec0220e28 100644
--- a/drivers/net/lora/sx130x.c
+++ b/drivers/net/lora/sx130x.c
@@ -69,6 +69,10 @@ struct sx130x_priv {
void*drvdata;
struct sx130x_tx_gain_lut tx_gain_lut[SX1301_TX_GAIN_LUT_MAX];
u8 tx_gain_lut_size;
+
+   struct sk_buff *tx_skb;
+   struct workqueue_struct *wq;
+   struct work_struct tx_work;
 };
 
 struct regmap *sx130x_get_regmap(struct device *dev)
@@ -644,6 +648,8 @@ static int sx130x_agc_init(struct sx130x_priv *priv)
 
 static netdev_tx_t sx130x_loradev_start_xmit(struct sk_buff *skb, struct 
net_device *netdev)
 {
+   struct sx130x_priv *priv = netdev_priv(netdev);
+
if (skb->protocol != htons(ETH_P_LORA)) {
kfree_skb(skb);
netdev->stats.tx_dropped++;
@@ -651,11 +657,36 @@ static netdev_tx_t sx130x_loradev_start_xmit(struct 
sk_buff *skb, struct net_dev
}
 
netif_stop_queue(netdev);
+   priv->tx_skb = skb;
+   queue_work(priv->wq, &priv->tx_work);
 
-   /* TODO */
return NETDEV_TX_OK;
 }
 
+static void sx130x_tx_work_handler(struct work_struct *ws)
+{
+   struct sx130x_priv *priv = container_of(ws, struct sx130x_priv, 
tx_work);
+   struct net_device *netdev = dev_get_drvdata(priv->dev);
+   int ret;
+
+   netdev_dbg(netdev, "%s\n", __func__);
+
+   if (priv->tx_skb) {
+
+   /* TODO actual tx* */
+
+   if (!(netdev->flags & IFF_ECHO) ||
+   priv->tx_skb->pkt_type != PACKET_LOOPBACK ||
+   priv->tx_skb->protocol != htons(ETH_P_LORA))
+   kfree_skb(priv->tx_skb);
+
+   priv->tx_skb = NULL;
+   }
+
+   if (netif_queue_stopped(netdev))
+   netif_wake_queue(netdev);
+}
+
 static int sx130x_loradev_open(struct net_device *netdev)
 {
struct sx130x_priv *priv = netdev_priv(netdev);
@@ -715,6 +746,12 @@ static int sx130x_loradev_open(struct net_device *netdev)
 
mutex_unlock(&priv->io_lock);
 
+   priv->tx_skb = NULL;
+
+   priv->wq = alloc_workqueue("sx130x_wq",
+  WQ_FREEZABLE | WQ_MEM_RECLAIM, 0);
+   INIT_WORK(&priv->tx_work, sx130x_tx_work_handler);
+
netif_start_queue(netdev);
 
return 0;
@@ -729,11 +766,22 @@ static int sx130x_loradev_open(struct net_device *netdev)
 
 static int sx130x_loradev_stop(struct net_device *netdev)
 {
+   struct sx130x_priv *priv = netdev_priv(netdev);
+
netdev_dbg(netdev, "%s", __func__);
 
netif_stop_queue(netdev);
close_loradev(netdev);
 
+   destroy_workqueue(priv->wq);
+   priv->wq = NULL;
+
+   if (priv->tx_skb) {
+   netdev->stats.tx_errors++;
+   dev_kfree_skb(priv->tx_skb);
+   }
+   priv->tx_skb = NULL;
+
return 0;
 }
 
-- 
2.17.1



[PATCH lora-next 09/11] net: lora: introduce lora socket addressing for metadata

2019-01-28 Thread Ben Whitten
Information such as spreading factor, coding rate and power are on a per
transmission basis so we can encode this information in the lora socket
address.
In future we may have a different format for receive with additional
fields which get populated.

Signed-off-by: Ben Whitten 
---
 include/linux/lora/skb.h  |  9 
 include/uapi/linux/lora.h | 14 
 net/lora/dgram.c  | 45 +++
 3 files changed, 68 insertions(+)

diff --git a/include/linux/lora/skb.h b/include/linux/lora/skb.h
index 8806741464d0..6abeb39b8b7f 100644
--- a/include/linux/lora/skb.h
+++ b/include/linux/lora/skb.h
@@ -12,6 +12,15 @@
 
 struct lora_skb_priv {
int ifindex;
+
+   u64 freq;
+   u8 sf;
+   u8 cr;
+   u16 bw;
+
+   u8 sync;
+
+   s8 power;
 };
 
 static inline struct lora_skb_priv *lora_skb_prv(struct sk_buff *skb)
diff --git a/include/uapi/linux/lora.h b/include/uapi/linux/lora.h
index 4ff00b9c3c20..4c458ee3ed9a 100644
--- a/include/uapi/linux/lora.h
+++ b/include/uapi/linux/lora.h
@@ -10,6 +10,18 @@
 #include 
 #include 
 
+/* TX addressing definition */
+struct tx_addr {
+   __u64 freq;
+   __u8 sf;
+   __u8 cr;
+   __u16 bw;
+
+   __u8 sync;
+
+   __s8 power;
+};
+
 /* particular protocols of the protocol family PF_LORA */
 #define LORA_PROTO_DATAGRAM0
 #define LORA_NPROTO1
@@ -17,7 +29,9 @@
 struct sockaddr_lora {
__kernel_sa_family_t lora_family;
int lora_ifindex;
+   __u8 lora_protocol;
union {
+   struct tx_addr  tx;
} lora_addr;
 };
 
diff --git a/net/lora/dgram.c b/net/lora/dgram.c
index 4d931fd3778a..1556ad0f8835 100644
--- a/net/lora/dgram.c
+++ b/net/lora/dgram.c
@@ -20,6 +20,15 @@ struct dgram_sock {
int ifindex;
bool bound;
struct notifier_block notifier;
+
+   u64 freq;
+   u8 sf;
+   u8 cr;
+   u16 bw;
+
+   u8 sync;
+
+   s8 power;
 };
 
 static inline struct dgram_sock *dgram_sk(const struct sock *sk)
@@ -69,6 +78,12 @@ static int dgram_bind(struct socket *sock, struct sockaddr 
*uaddr, int len)
ifindex = 0;
 
dgram->ifindex = ifindex;
+   dgram->freq = addr->lora_addr.tx.freq;
+   dgram->sf = addr->lora_addr.tx.sf;
+   dgram->cr = addr->lora_addr.tx.cr;
+   dgram->bw = addr->lora_addr.tx.bw;
+   dgram->sync = addr->lora_addr.tx.sync;
+   dgram->power = addr->lora_addr.tx.power;
dgram->bound = true;
 
 out:
@@ -118,6 +133,12 @@ static int dgram_sendmsg(struct socket *sock, struct 
msghdr *msg, size_t size)
 
lora_skb_reserve(skb);
lora_skb_prv(skb)->ifindex = netdev->ifindex;
+   lora_skb_prv(skb)->freq = dgram->freq;
+   lora_skb_prv(skb)->sf = dgram->sf;
+   lora_skb_prv(skb)->cr = dgram->cr;
+   lora_skb_prv(skb)->bw = dgram->bw;
+   lora_skb_prv(skb)->sync = dgram->sync;
+   lora_skb_prv(skb)->power = dgram->power;
 
ret = memcpy_from_msg(skb_put(skb, size), msg, size);
if (ret < 0)
@@ -172,6 +193,12 @@ static int dgram_getname(struct socket *sock, struct 
sockaddr *uaddr,
memset(addr, 0, sizeof(*addr));
addr->lora_family = AF_LORA;
addr->lora_ifindex = dgram->ifindex;
+   addr->lora_addr.tx.freq = dgram->freq;
+   addr->lora_addr.tx.sf = dgram->sf;
+   addr->lora_addr.tx.cr = dgram->cr;
+   addr->lora_addr.tx.bw = dgram->bw;
+   addr->lora_addr.tx.sync = dgram->sync;
+   addr->lora_addr.tx.power = dgram->power;
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
return sizeof(*addr);
@@ -198,6 +225,12 @@ static int dgram_release(struct socket *sock)
lock_sock(sk);
 
dgram->ifindex = 0;
+   dgram->freq = 0;
+   dgram->sf = 0;
+   dgram->cr = 0;
+   dgram->bw = 0;
+   dgram->sync = 0;
+   dgram->power = 0;
dgram->bound = false;
 
sock_orphan(sk);
@@ -251,6 +284,12 @@ static int dgram_notifier(struct notifier_block *nb, 
unsigned long msg, void *pt
lock_sock(sk);
 
dgram->ifindex = 0;
+   dgram->freq = 0;
+   dgram->sf = 0;
+   dgram->cr = 0;
+   dgram->bw = 0;
+   dgram->sync = 0;
+   dgram->power = 0;
dgram->bound = false;
 
release_sock(sk);
@@ -277,6 +316,12 @@ static int dgram_init(struct sock *sk)
pr_debug("lora: %s\n", __func__);
 
dgram->bound = false;
+   dgram->freq = 0;
+   dgram->sf = 0;
+   dgram->cr = 0;
+   dgram->bw = 0;
+   dgram->sync = 0;
+   dgram->power = 0;
dgram->ifindex = 0;
 
dgram->notifier.notifier_call = dgram_notifier;
-- 
2.17.1



[PATCH lora-next 11/11] net: lora: sx130x: add patch to register fields

2019-01-28 Thread Ben Whitten
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 
---
 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_FIE

[PATCH lora-next 08/11] net: lora: sx130x: add test transmission

2019-01-28 Thread Ben Whitten
First transmission from the SX130x, all metadata values are hardcoded
and will be replaced with a suitable alternative.
Data sent into the socket is sent straight out of the card.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx130x.c | 128 +-
 drivers/net/lora/sx130x.h |  11 
 2 files changed, 137 insertions(+), 2 deletions(-)

diff --git a/drivers/net/lora/sx130x.c b/drivers/net/lora/sx130x.c
index 820ec0220e28..f96f32d2e1ff 100644
--- a/drivers/net/lora/sx130x.c
+++ b/drivers/net/lora/sx130x.c
@@ -49,8 +49,50 @@ static const struct reg_field sx130x_regmap_fields[] = {
/* EMERGENCY_FORCE_HOST_CTRL */
[F_EMERGENCY_FORCE_HOST_CTRL] =
REG_FIELD(SX1301_EMERGENCY_FORCE_HOST_CTRL, 0, 0),
+   /* TX_TRIG */
+   [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),
 };
 
+struct sx130x_tx_header {
+   u8  tx_freq[3];
+   u32 start;
+   u8  tx_power:4,
+   modulation_type:1,
+   radio_select:1,
+   resered0:2;
+   u8  reserved1;
+
+   union {
+   struct lora_t {
+   u8  sf:4,
+   cr:3,
+   crc16_en:1;
+   u8  payload_len;
+   u8  mod_bw:2,
+   implicit_header:1,
+   ppm_offset:1,
+   invert_pol:1,
+   reserved0:3;
+   u16 preamble;
+   u8  reserved1;
+   u8  reserved2;
+   } lora;
+   struct fsk_t {
+   u8  freq_dev;
+   u8  payload_len;
+   u8  packet_mode:1,
+   crc_en:1,
+   enc_mode:2,
+   crc_mode:1,
+   reserved0:3;
+   u16 preamble;
+   u16 bitrate;
+   } fsk;
+   } u;
+} __packed;
+
 struct sx130x_tx_gain_lut {
s8 power;   /* dBm measured at board connector */
u8 dig_gain;
@@ -646,6 +688,83 @@ static int sx130x_agc_init(struct sx130x_priv *priv)
return ret;
 }
 
+static int sx130x_tx(struct sx130x_priv *priv, void *data, int len)
+{
+   int ret, i;
+   u8 buff[256 + 16];
+   struct sx130x_tx_header *hdr = (struct sx130x_tx_header *)buff;
+   struct net_device *netdev = dev_get_drvdata(priv->dev);
+
+   /* TODO general checks to make sure we CAN send */
+
+   /* TODO Enable notch filter for lora 125 */
+
+   /* TODO get start delay for this TX */
+
+   /* TODO interpret tx power, HACK just set max power */
+
+   /* TODO get TX imbalance for this pow index from calibration step */
+
+   /* TODO set the dig gain */
+
+   /* TODO set TX PLL freq based on radio used to TX */
+
+   memset(buff, 0, sizeof(buff));
+
+   /* HACK set to 868MHz */
+   hdr->tx_freq[0] = 217;
+   hdr->tx_freq[1] = 0;
+   hdr->tx_freq[2] = 0;
+
+   hdr->start = 0; /* Start imediatly */
+   hdr->radio_select = 0; /* HACK Radio A transmit */
+   hdr->modulation_type = 0; /* HACK modulation LORA */
+   hdr->tx_power = 15; /* HACK power entry 15 */
+
+   hdr->u.lora.crc16_en = 1; /* Enable CRC16 */
+   hdr->u.lora.cr = 1; /* CR 4/5 */
+   hdr->u.lora.sf = 7; /* SF7 */
+   hdr->u.lora.payload_len = len; /* Set the data len to the skb len */
+   hdr->u.lora.implicit_header = 0; /* No implicit header */
+   hdr->u.lora.mod_bw = 0; /* Set 125KHz BW */
+   hdr->u.lora.ppm_offset = 0; /* TODO no ppm offset? */
+   hdr->u.lora.invert_pol = 0; /* TODO set no inverted polarity */
+
+   hdr->u.lora.preamble = 8; /* Set the standard preamble */
+
+   /* TODO 2 Msb in tx_freq0 for large narrow filtering, unset for now */
+   hdr->tx_freq[0] &= 0x3F;
+
+   /* Copy the TX data into the buffer ready to go */
+
+   memcpy((void *)&buff[16], data, len);
+
+   /* Reset any transmissions */
+   ret = regmap_write(priv->regmap, SX1301_TX_TRIG, 0);
+   if (ret)
+   return ret;
+
+   /* Put the buffer into the tranmit fifo */
+   ret = regmap_write(priv->regmap, SX1301_TX_DATA_BUF_ADDR, 0);
+   if (ret)
+   return ret;
+   ret = regmap_noinc_write(priv->regmap, SX1301_TX_DATA_BUF_DATA, buff,
+len + 16);
+   if (ret)
+   return ret;
+
+   /* HACK just go for immediate transfer */
+   ret = sx130x_field_force_write(priv, F_TX_TRIG_IMMEDIATE, 1);
+   if (ret)
+ 

Re: [PATCH v3 lora-next 4/4] dt-bindings: lora: sx130x: add clock bindings

2019-01-24 Thread Ben Whitten
Missed linux-lpwan

On Thu, 24 Jan 2019 at 14:53, Ben Whitten  wrote:
>
> From: Ben Whitten 
>
> The SX130x family consumes two clocks, a 32 MHz clock provided by a
> connected IQ transceiver, and a 133 MHz high speed clock.
> It also provides a 32 MHz clock out to the radio in the TX path.
>
> In the example we connect the concentrator to a fixed clock providing
> the 133 MHz high speed clock, and we connect to a connected transceiver
> 32 MHz clock.
>
> A radio in the TX path is also connected to the 32 MHz clock out from the
> concentrator.
>
> The connected radios are both fed from a fixed 32 MHz clock, with only
> one being the clock source back to the SX130x concentrator.
>
> Signed-off-by: Ben Whitten 
> ---
> v2 -> v3:
> * Name input clocks specifically
> * Add output clock for radio in TX path
> v1 -> v2:
> * Fixed incorrect usage of clock cells
> * Fixed wording in commit and descriptions
> ---
>  .../bindings/net/lora/semtech,sx130x.yaml | 52 ++-
>  1 file changed, 51 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml 
> b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
> index 24fad1218735..5d32668d6ca9 100644
> --- a/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
> +++ b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
> @@ -15,7 +15,9 @@ description: |
>demodulating LoRa signals on 8 channels simultaneously.
>
>It is typically paired with two SX125x IQ radios controlled over an
> -  SPI directly from the concentrator.
> +  SPI directly from the concentrator. One of the radios will provide
> +  a 32 MHz clock back into the concentrator.
> +  The concentrator also outputs a 32 MHz clock to the radio(s) in the TX 
> chain.
>
>The concentrator itself is controlled over SPI.
>
> @@ -37,6 +39,30 @@ properties:
>  maxItems: 1
>  description: A connection of the reset gpio line.
>
> +  clocks:
> +maxItems: 2
> +items:
> +  - description: 32 MHz clock provider (CLK32M)
> +  - description: 133 MHz high speed clock provider (CLKHS)
> +description: The chip requires two clock inputs; A 32MHz clock at CMOS
> +  level which is provided from a connected radio.
> +  And a 133MHz high speed clock at CMOS level provided by an oscillator.
> +
> +  clock-names:
> +items:
> +  - const: clk32m
> +  - const: clkhs
> +description: Input clock (CLK32M) name from provider, Input clock (CLKHS)
> +  name from provider.
> +
> +  clock-output-names:
> +items:
> +  - const: sp_clk_out
> +description: Output clock (SP_CLK_OUT) typically connected to the TX 
> radio.
> +
> +  '#clock-cells':
> +const: 0
> +
>radio-spi:
>  type: object
>  description: The concentrator can have two radios connected which are
> @@ -73,6 +99,20 @@ examples:
>
>  #include 
>
> +tcxo: dummy32m {
> +  compatible = "fixed-clock";
> +  clock-frequency = <3200>;
> +  clock-output-names = "tcxo";
> +  #clock-cells = <0>;
> +};
> +
> +clkhs: dummy133m {
> +  compatible = "fixed-clock";
> +  clock-frequency = <13300>;
> +  clock-output-names = "clkhs";
> +  #clock-cells = <0>;
> +};
> +
>  spi {
>#address-cells = <1>;
>#size-cells = <0>;
> @@ -82,6 +122,10 @@ examples:
>  reg = <0>;
>  reset-gpios = <&pioB 27 GPIO_ACTIVE_HIGH>;
>  spi-max-frequency = <800>;
> +clocks = <&radio1>, <&clkhs>;
> +clock-names = "clk32m", "clkhs";
> +clock-output-names = "sp_clk_out";
> +#clock-cells = <0>;
>
>  radio-spi {
>#address-cells = <1>;
> @@ -90,11 +134,17 @@ examples:
>radio0: radio@0 {
>  compatible = "semtech,sx1257";
>  reg = <0>;
> +clocks = <&tcxo>, <&concentrator0>;
> +clock-names = "fxosc", "fclk_in";
>};
>
>radio1: radio@1 {
>  compatible = "semtech,sx1257";
>  reg = <1>;
> +clocks = <&tcxo>;
> +clock-names = "fxosc";
> +clock-output-names = "fclk_out";
> +#clock-cells = <0>;
>};
>  };
>};
> --
> 2.17.1
>


Re: [PATCH v3 lora-next 3/4] dt-bindings: lora: sx125x: add clock bindings

2019-01-24 Thread Ben Whitten
Missed linux-lpwan

On Thu, 24 Jan 2019 at 14:53, Ben Whitten  wrote:
>
> From: Ben Whitten 
>
> The SX125x consumes a clock (FXOSC) ranging from 32 to 36 MHz as its main
> XTAL. It may also consume a clock for the TX synthesizer or DAC input clock
> (FCLK_IN).
> If the radio is coupled with an SX130x the radio is therefor operating in
> master mode and it may also provide a gated version of FXOSC clock for the
> concentrator. In this case the concentrator is expecting a 32 MHz input
> clock.
>
> In the example we connect fxosc to the "txco" clock source, represented by a
> fixed clock. The radio also provides a clock output "fclk_out" for
> consumption by the SX130x concentrator.
>
> Signed-off-by: Ben Whitten 
> ---
> v2 -> v3:
> * Name clock inputs and outputs
> * Add FCLK_IN
> v1 -> v2:
> * Fixed incorrect usage of clock cells
> * Fixed wording in commit and descriptions
> * Dropped enforced clock names
> ---
>  .../bindings/net/lora/semtech,sx125x.yaml | 33 +++
>  1 file changed, 33 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml 
> b/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
> index fe2d2a23c28b..be45bcfd97be 100644
> --- a/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
> +++ b/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
> @@ -27,12 +27,41 @@ properties:
>  description: The chip select on the SPI bus or radio number in 
> concentrator
>, with radio A = 0 and radio B = 1.
>
> +  clocks:
> +maxItems: 2
> +description: Input clock (FXOSC) provider with output ranging from 32 MHz
> +  to 36 MHz. TX synthesizer or DAC input clock (FCLK_IN) provider with
> +  output ranging from 32 MHz to 36 MHz.
> +
> +  clock-names:
> +items:
> +  - const: fxosc
> +  - const: fclk_in
> +description: Input clock (FXOSC), TX synthesizer or DAC input clock
> +  (FCLK_IN)
> +
> +  clock-output-names:
> +items:
> +  - const: fclk_out
> +description: Output clock (FCLK_OUT) name, clock is gated version of the
> +  input (FXOSC). Used in master mode operation.
> +
> +  '#clock-cells':
> +const: 0
> +
>  required:
>- compatible
>- reg
>
>  examples:
>- |
> +tcxo: dummy32m {
> +  compatible = "fixed-clock";
> +  clock-frequency = <3200>;
> +  clock-output-names = "tcxo";
> +  #clock-cells = <0>;
> +};
> +
>  spi {
>#address-cells = <1>;
>#size-cells = <0>;
> @@ -40,5 +69,9 @@ examples:
>radio0: radio@0 {
>  compatible = "semtech,sx1257";
>  reg = <0>;
> +clocks = <&tcxo>;
> +clock-names = "fxosc";
> +clock-output-names = "fclk_out";
> +#clock-cells = <0>;
>};
>  };
> --
> 2.17.1
>


Re: [PATCH v3 lora-next 2/4] dt-bindings: lora: sx125x: add basic documentation

2019-01-24 Thread Ben Whitten
Missed linux-lpwan

On Thu, 24 Jan 2019 at 14:53, Ben Whitten  wrote:
>
> From: Ben Whitten 
>
> The SX125x family are IQ radio transceivers from Semtech configured over
> SPI, they are typically connected to an SX130x series concentrator however
> may be connected to a host directly.
>
> Required properties include the radio number of the host or concentrator
> bus.
>
> Signed-off-by: Ben Whitten 
> ---
> v2 -> v3:
> * Renamed example node name to be consistent with concentrator
> v1 -> v2:
> * Dropped spi-max-frequency binding
> * Wording changes to commit and descriptions
> * Added spi wrapper suggested by Rob H
> * Dual licence
> ---
>  .../bindings/net/lora/semtech,sx125x.yaml | 44 +++
>  1 file changed, 44 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
>
> diff --git a/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml 
> b/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
> new file mode 100644
> index ..fe2d2a23c28b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
> @@ -0,0 +1,44 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/net/lora/semtech,sx125x.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Semtech IQ modulator/de-modulator transeiver
> +
> +maintainers:
> +  - Andreas Färber 
> +  - Ben Whitten 
> +
> +description: |
> +  The SX125x family are transceivers capable of supporting multiple constant
> +  and non-constant envelope modulation schemes.
> +
> +properties:
> +  compatible:
> +items:
> +  - enum:
> +- semtech,sx1255
> +- semtech,sx1257
> +- semtech,sx1258
> +
> +  reg:
> +maxItems: 1
> +description: The chip select on the SPI bus or radio number in 
> concentrator
> +  , with radio A = 0 and radio B = 1.
> +
> +required:
> +  - compatible
> +  - reg
> +
> +examples:
> +  - |
> +spi {
> +  #address-cells = <1>;
> +  #size-cells = <0>;
> +
> +  radio0: radio@0 {
> +compatible = "semtech,sx1257";
> +reg = <0>;
> +  };
> +};
> --
> 2.17.1
>


Re: [PATCH v3 lora-next 1/4] dt-bindings: lora: sx130x: add basic documentation

2019-01-24 Thread Ben Whitten
Missed linux-lpwan
On Thu, 24 Jan 2019 at 14:53, Ben Whitten  wrote:
>
> From: Ben Whitten 
>
> Add basic documentation in YAML format for the SX130x series concentrators
> from Semtech.
> Required is; the location on the SPI bus and the compatible string.
>
> Signed-off-by: Ben Whitten 
> ---
> v2 -> v3:
> * Corrected fallback notation
> * Limited radio node names from anything to 'radio@'
> v1 -> v2:
> * Dropped reset-gpios, radio-spi from required.
> * Dropped spi-max-frequency from binding.
> * Changed compatible to allow fallback from SX1308 to SX1301.
> * Wording changes in commit and descriptions.
> * Dual licence
> * Incorperate Robs comments on child node and spi wrapper
> ---
>  .../bindings/net/lora/semtech,sx130x.yaml | 101 ++
>  1 file changed, 101 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
>
> diff --git a/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml 
> b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
> new file mode 100644
> index ..24fad1218735
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
> @@ -0,0 +1,101 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/net/lora/semtech,sx130x.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Semtech LoRa concentrator
> +
> +maintainers:
> +  - Andreas Färber 
> +  - Ben Whitten 
> +
> +description: |
> +  Semtech LoRa concentrator SX130x digital baseband chip is capable of
> +  demodulating LoRa signals on 8 channels simultaneously.
> +
> +  It is typically paired with two SX125x IQ radios controlled over an
> +  SPI directly from the concentrator.
> +
> +  The concentrator itself is controlled over SPI.
> +
> +properties:
> +  compatible:
> +oneOf:
> +  - items:
> +- enum:
> +  - semtech,sx1308
> +- const: semtech,sx1301
> +  - items:
> +- const: semtech,sx1301
> +
> +  reg:
> +maxItems: 1
> +description: The chip select on the SPI bus.
> +
> +  reset-gpios:
> +maxItems: 1
> +description: A connection of the reset gpio line.
> +
> +  radio-spi:
> +type: object
> +description: The concentrator can have two radios connected which are
> +  contained within the following node.
> +
> +properties:
> +  '#address-cells':
> +const: 1
> +
> +  '#size-cells':
> +const: 0
> +
> +patternProperties:
> +  "^radio@[0-1]$":
> +type: object
> +properties:
> +  reg:
> +maxItems: 1
> +minimum: 0
> +maximum: 1
> +required:
> +  - reg
> +
> +required:
> +  - '#address-cells'
> +  - '#size-cells'
> +
> +required:
> +  - compatible
> +  - reg
> +
> +examples:
> +  - |
> +
> +#include 
> +
> +spi {
> +  #address-cells = <1>;
> +  #size-cells = <0>;
> +
> +  concentrator0: lora@0 {
> +compatible = "semtech,sx1301";
> +reg = <0>;
> +reset-gpios = <&pioB 27 GPIO_ACTIVE_HIGH>;
> +spi-max-frequency = <800>;
> +
> +radio-spi {
> +  #address-cells = <1>;
> +  #size-cells = <0>;
> +
> +  radio0: radio@0 {
> +compatible = "semtech,sx1257";
> +reg = <0>;
> +  };
> +
> +  radio1: radio@1 {
> +compatible = "semtech,sx1257";
> +reg = <1>;
> +  };
> +};
> +  };
> +};
> --
> 2.17.1
>


Re: [PATCH v3 lora-next 0/4] net: lora: Add documentation for SX130x and SX125x parts

2019-01-24 Thread Ben Whitten
Missed linux-lpwan

On Thu, 24 Jan 2019 at 14:53, Ben Whitten  wrote:
>
> Hello,
>
> This series adds documentation for the SX130x and SX125x chips.
> We are using the yaml binding format and this series builds with
> 'make dt_binding_check'.
>
> This series is split such that the basic documentation can be taken
> without clock components, as there is an ongoing problem running clk
> over spi backed regmaps on certain spi controller drivers [1]
>
> Thanks,
> Ben Whitten
>
> v2 -> v3
> * Added the clock input and output names
> * Limited the radio-spi node children names to radio@
> * Fixed fallback compatible for SX1308 -> SX1301
> v1 -> v2
> * Dropped reset-gpios, radio-spi from required.
> * Dropped spi-max-frequency from binding.
> * Changed compatible to allow fallback from SX1308 to SX1301.
> * Wording changes in commit and descriptions.
> * Dual licence
> * Incorperate Robs comments on child node and spi wrapper
>
> [1] http://lists.infradead.org/pipermail/linux-lpwan/2018-December/63.html
>
>
> Ben Whitten (4):
>   dt-bindings: lora: sx130x: add basic documentation
>   dt-bindings: lora: sx125x: add basic documentation
>   dt-bindings: lora: sx125x: add clock bindings
>   dt-bindings: lora: sx130x: add clock bindings
>
>  .../bindings/net/lora/semtech,sx125x.yaml |  77 +
>  .../bindings/net/lora/semtech,sx130x.yaml | 151 ++
>  2 files changed, 228 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
>  create mode 100644 
> Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
>
> --
> 2.17.1
>


[PATCH v3 lora-next 1/4] dt-bindings: lora: sx130x: add basic documentation

2019-01-24 Thread Ben Whitten
From: Ben Whitten 

Add basic documentation in YAML format for the SX130x series concentrators
from Semtech.
Required is; the location on the SPI bus and the compatible string.

Signed-off-by: Ben Whitten 
---
v2 -> v3:
* Corrected fallback notation
* Limited radio node names from anything to 'radio@'
v1 -> v2:
* Dropped reset-gpios, radio-spi from required.
* Dropped spi-max-frequency from binding.
* Changed compatible to allow fallback from SX1308 to SX1301.
* Wording changes in commit and descriptions.
* Dual licence
* Incorperate Robs comments on child node and spi wrapper
---
 .../bindings/net/lora/semtech,sx130x.yaml | 101 ++
 1 file changed, 101 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml

diff --git a/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml 
b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
new file mode 100644
index ..24fad1218735
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
@@ -0,0 +1,101 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/lora/semtech,sx130x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Semtech LoRa concentrator
+
+maintainers:
+  - Andreas Färber 
+  - Ben Whitten 
+
+description: |
+  Semtech LoRa concentrator SX130x digital baseband chip is capable of
+  demodulating LoRa signals on 8 channels simultaneously.
+
+  It is typically paired with two SX125x IQ radios controlled over an
+  SPI directly from the concentrator.
+
+  The concentrator itself is controlled over SPI.
+
+properties:
+  compatible:
+oneOf:
+  - items:
+- enum:
+  - semtech,sx1308
+- const: semtech,sx1301
+  - items:
+- const: semtech,sx1301
+
+  reg:
+maxItems: 1
+description: The chip select on the SPI bus.
+
+  reset-gpios:
+maxItems: 1
+description: A connection of the reset gpio line.
+
+  radio-spi:
+type: object
+description: The concentrator can have two radios connected which are
+  contained within the following node.
+
+properties:
+  '#address-cells':
+const: 1
+
+  '#size-cells':
+const: 0
+
+patternProperties:
+  "^radio@[0-1]$":
+type: object
+properties:
+  reg:
+maxItems: 1
+minimum: 0
+maximum: 1
+required:
+  - reg
+
+required:
+  - '#address-cells'
+  - '#size-cells'
+
+required:
+  - compatible
+  - reg
+
+examples:
+  - |
+
+#include 
+
+spi {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  concentrator0: lora@0 {
+compatible = "semtech,sx1301";
+reg = <0>;
+reset-gpios = <&pioB 27 GPIO_ACTIVE_HIGH>;
+spi-max-frequency = <800>;
+
+radio-spi {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  radio0: radio@0 {
+compatible = "semtech,sx1257";
+reg = <0>;
+  };
+
+  radio1: radio@1 {
+compatible = "semtech,sx1257";
+reg = <1>;
+  };
+};
+  };
+};
-- 
2.17.1



[PATCH v3 lora-next 2/4] dt-bindings: lora: sx125x: add basic documentation

2019-01-24 Thread Ben Whitten
From: Ben Whitten 

The SX125x family are IQ radio transceivers from Semtech configured over
SPI, they are typically connected to an SX130x series concentrator however
may be connected to a host directly.

Required properties include the radio number of the host or concentrator
bus.

Signed-off-by: Ben Whitten 
---
v2 -> v3:
* Renamed example node name to be consistent with concentrator
v1 -> v2:
* Dropped spi-max-frequency binding
* Wording changes to commit and descriptions
* Added spi wrapper suggested by Rob H
* Dual licence
---
 .../bindings/net/lora/semtech,sx125x.yaml | 44 +++
 1 file changed, 44 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml

diff --git a/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml 
b/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
new file mode 100644
index ..fe2d2a23c28b
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/lora/semtech,sx125x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Semtech IQ modulator/de-modulator transeiver
+
+maintainers:
+  - Andreas Färber 
+  - Ben Whitten 
+
+description: |
+  The SX125x family are transceivers capable of supporting multiple constant
+  and non-constant envelope modulation schemes.
+
+properties:
+  compatible:
+items:
+  - enum:
+- semtech,sx1255
+- semtech,sx1257
+- semtech,sx1258
+
+  reg:
+maxItems: 1
+description: The chip select on the SPI bus or radio number in concentrator
+  , with radio A = 0 and radio B = 1.
+
+required:
+  - compatible
+  - reg
+
+examples:
+  - |
+spi {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  radio0: radio@0 {
+compatible = "semtech,sx1257";
+reg = <0>;
+  };
+};
-- 
2.17.1



[PATCH v3 lora-next 0/4] net: lora: Add documentation for SX130x and SX125x parts

2019-01-24 Thread Ben Whitten
Hello,

This series adds documentation for the SX130x and SX125x chips.
We are using the yaml binding format and this series builds with
'make dt_binding_check'.

This series is split such that the basic documentation can be taken
without clock components, as there is an ongoing problem running clk
over spi backed regmaps on certain spi controller drivers [1]

Thanks,
Ben Whitten

v2 -> v3
* Added the clock input and output names
* Limited the radio-spi node children names to radio@
* Fixed fallback compatible for SX1308 -> SX1301
v1 -> v2
* Dropped reset-gpios, radio-spi from required.
* Dropped spi-max-frequency from binding.
* Changed compatible to allow fallback from SX1308 to SX1301.
* Wording changes in commit and descriptions.
* Dual licence
* Incorperate Robs comments on child node and spi wrapper

[1] http://lists.infradead.org/pipermail/linux-lpwan/2018-December/63.html


Ben Whitten (4):
  dt-bindings: lora: sx130x: add basic documentation
  dt-bindings: lora: sx125x: add basic documentation
  dt-bindings: lora: sx125x: add clock bindings
  dt-bindings: lora: sx130x: add clock bindings

 .../bindings/net/lora/semtech,sx125x.yaml |  77 +
 .../bindings/net/lora/semtech,sx130x.yaml | 151 ++
 2 files changed, 228 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
 create mode 100644 
Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml

-- 
2.17.1



[PATCH v3 lora-next 3/4] dt-bindings: lora: sx125x: add clock bindings

2019-01-24 Thread Ben Whitten
From: Ben Whitten 

The SX125x consumes a clock (FXOSC) ranging from 32 to 36 MHz as its main
XTAL. It may also consume a clock for the TX synthesizer or DAC input clock
(FCLK_IN).
If the radio is coupled with an SX130x the radio is therefor operating in
master mode and it may also provide a gated version of FXOSC clock for the
concentrator. In this case the concentrator is expecting a 32 MHz input
clock.

In the example we connect fxosc to the "txco" clock source, represented by a
fixed clock. The radio also provides a clock output "fclk_out" for
consumption by the SX130x concentrator.

Signed-off-by: Ben Whitten 
---
v2 -> v3:
* Name clock inputs and outputs
* Add FCLK_IN
v1 -> v2:
* Fixed incorrect usage of clock cells
* Fixed wording in commit and descriptions
* Dropped enforced clock names
---
 .../bindings/net/lora/semtech,sx125x.yaml | 33 +++
 1 file changed, 33 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml 
b/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
index fe2d2a23c28b..be45bcfd97be 100644
--- a/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
+++ b/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
@@ -27,12 +27,41 @@ properties:
 description: The chip select on the SPI bus or radio number in concentrator
   , with radio A = 0 and radio B = 1.
 
+  clocks:
+maxItems: 2
+description: Input clock (FXOSC) provider with output ranging from 32 MHz
+  to 36 MHz. TX synthesizer or DAC input clock (FCLK_IN) provider with
+  output ranging from 32 MHz to 36 MHz.
+
+  clock-names:
+items:
+  - const: fxosc
+  - const: fclk_in
+description: Input clock (FXOSC), TX synthesizer or DAC input clock
+  (FCLK_IN)
+
+  clock-output-names:
+items:
+  - const: fclk_out
+description: Output clock (FCLK_OUT) name, clock is gated version of the
+  input (FXOSC). Used in master mode operation.
+
+  '#clock-cells':
+const: 0
+
 required:
   - compatible
   - reg
 
 examples:
   - |
+tcxo: dummy32m {
+  compatible = "fixed-clock";
+  clock-frequency = <3200>;
+  clock-output-names = "tcxo";
+  #clock-cells = <0>;
+};
+
 spi {
   #address-cells = <1>;
   #size-cells = <0>;
@@ -40,5 +69,9 @@ examples:
   radio0: radio@0 {
 compatible = "semtech,sx1257";
 reg = <0>;
+clocks = <&tcxo>;
+clock-names = "fxosc";
+clock-output-names = "fclk_out";
+#clock-cells = <0>;
   };
 };
-- 
2.17.1



[PATCH v3 lora-next 4/4] dt-bindings: lora: sx130x: add clock bindings

2019-01-24 Thread Ben Whitten
From: Ben Whitten 

The SX130x family consumes two clocks, a 32 MHz clock provided by a
connected IQ transceiver, and a 133 MHz high speed clock.
It also provides a 32 MHz clock out to the radio in the TX path.

In the example we connect the concentrator to a fixed clock providing
the 133 MHz high speed clock, and we connect to a connected transceiver
32 MHz clock.

A radio in the TX path is also connected to the 32 MHz clock out from the
concentrator.

The connected radios are both fed from a fixed 32 MHz clock, with only
one being the clock source back to the SX130x concentrator.

Signed-off-by: Ben Whitten 
---
v2 -> v3:
* Name input clocks specifically
* Add output clock for radio in TX path
v1 -> v2:
* Fixed incorrect usage of clock cells
* Fixed wording in commit and descriptions
---
 .../bindings/net/lora/semtech,sx130x.yaml | 52 ++-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml 
b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
index 24fad1218735..5d32668d6ca9 100644
--- a/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
+++ b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
@@ -15,7 +15,9 @@ description: |
   demodulating LoRa signals on 8 channels simultaneously.
 
   It is typically paired with two SX125x IQ radios controlled over an
-  SPI directly from the concentrator.
+  SPI directly from the concentrator. One of the radios will provide
+  a 32 MHz clock back into the concentrator.
+  The concentrator also outputs a 32 MHz clock to the radio(s) in the TX chain.
 
   The concentrator itself is controlled over SPI.
 
@@ -37,6 +39,30 @@ properties:
 maxItems: 1
 description: A connection of the reset gpio line.
 
+  clocks:
+maxItems: 2
+items:
+  - description: 32 MHz clock provider (CLK32M)
+  - description: 133 MHz high speed clock provider (CLKHS)
+description: The chip requires two clock inputs; A 32MHz clock at CMOS
+  level which is provided from a connected radio.
+  And a 133MHz high speed clock at CMOS level provided by an oscillator.
+
+  clock-names:
+items:
+  - const: clk32m
+  - const: clkhs
+description: Input clock (CLK32M) name from provider, Input clock (CLKHS)
+  name from provider.
+
+  clock-output-names:
+items:
+  - const: sp_clk_out
+description: Output clock (SP_CLK_OUT) typically connected to the TX radio.
+
+  '#clock-cells':
+const: 0
+
   radio-spi:
 type: object
 description: The concentrator can have two radios connected which are
@@ -73,6 +99,20 @@ examples:
 
 #include 
 
+tcxo: dummy32m {
+  compatible = "fixed-clock";
+  clock-frequency = <3200>;
+  clock-output-names = "tcxo";
+  #clock-cells = <0>;
+};
+
+clkhs: dummy133m {
+  compatible = "fixed-clock";
+  clock-frequency = <13300>;
+  clock-output-names = "clkhs";
+  #clock-cells = <0>;
+};
+
 spi {
   #address-cells = <1>;
   #size-cells = <0>;
@@ -82,6 +122,10 @@ examples:
 reg = <0>;
 reset-gpios = <&pioB 27 GPIO_ACTIVE_HIGH>;
 spi-max-frequency = <800>;
+clocks = <&radio1>, <&clkhs>;
+clock-names = "clk32m", "clkhs";
+clock-output-names = "sp_clk_out";
+#clock-cells = <0>;
 
 radio-spi {
   #address-cells = <1>;
@@ -90,11 +134,17 @@ examples:
   radio0: radio@0 {
 compatible = "semtech,sx1257";
 reg = <0>;
+clocks = <&tcxo>, <&concentrator0>;
+clock-names = "fxosc", "fclk_in";
   };
 
   radio1: radio@1 {
 compatible = "semtech,sx1257";
 reg = <1>;
+clocks = <&tcxo>;
+clock-names = "fxosc";
+clock-output-names = "fclk_out";
+#clock-cells = <0>;
   };
 };
   };
-- 
2.17.1



Re: [PATCH v2 lora-next 1/4] dt-bindings: lora: sx130x: add basic documentation

2019-01-22 Thread Ben Whitten

Hi,

On 22/01/2019 20:04, Rob Herring wrote:

On Tue, Jan 22, 2019 at 12:07 PM Ben Whitten  wrote:


From: Ben Whitten 

Add basic documentation in YAML format for the SX130x series concentrators
from Semtech.
Required is; the location on the SPI bus and the compatible string.

Signed-off-by: Ben Whitten 
---
v1 -> v2:
* Dropped reset-gpios, radio-spi from required.
* Dropped spi-max-frequency from binding.
* Changed compatible to allow fallback from SX1308 to SX1301.
* Wording changes in commit and descriptions.
* Dual licence
* Incorperate Robs comments on child node and spi wrapper
---
  .../bindings/net/lora/semtech,sx130x.yaml | 96 +++
  1 file changed, 96 insertions(+)
  create mode 100644 
Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml

diff --git a/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml 
b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
new file mode 100644
index ..41919fb67ec4
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
@@ -0,0 +1,96 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/lora/semtech,sx130x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Semtech LoRa concentrator
+
+maintainers:
+  - Andreas Färber 
+  - Ben Whitten 
+
+description: |
+  Semtech LoRa concentrator SX130x digital baseband chip is capable of
+  demodulating LoRa signals on 8 channels simultaneously.
+
+  It is typically paired with two SX125x IQ radios controlled over an
+  SPI directly from the concentrator.
+
+  The concentrator itself is controlled over SPI.
+
+properties:
+  compatible:
+items:
+  - enum:
+- semtech,sx1308
+  - enum:
+- semtech,sx1301


I think you want:

oneOf:
   - items:
   - enum:
   - semtech,sx1308
   - const: semtech,sx1301
   - items:
   - const: semtech,sx1301

That covers these 2 cases:
"semtech,sx1308", "semtech,sx1301"
"semtech,sx1301"



Ah yes, that is what I was after. Thanks!


+
+  reg:
+maxItems: 1
+description: The chip select on the SPI bus.
+
+  reset-gpios:
+maxItems: 1
+description: A connection of the reset gpio line.
+
+  radio-spi:
+type: object
+description: The concentrator can have two radios connected which are
+  contained within the following node.
+
+properties:
+  '#address-cells':
+const: 1
+
+  '#size-cells':
+const: 0
+
+patternProperties:
+  "^[a-zA-Z0-9]@[0-1]$":


Is any node name allowed? We like to have generic names. 'lora' is
fine for me, but I'm don't know if other devices could be attached?



This sub bus will only have IQ radios attached to it, perhaps 'radio@0'
as the system can handle other modulations.


I thought up to 8 concentrators was supported? Or channels and radios
aren't 1-1?


You can have multiple concentrator chips (SX130x) however each one may 
have up to two IQ radios (SX125x) attached to its bus.
And in terms of channels the system can listen on, the concentrator has 
9 LoRa demodulators and 1 (G)FSK demodulator.




This too should have 'type: object' since it is a node name.



Ah yes


+properties:
+  reg:
+maxItems: 1


You can add:
minimum: 0
maximum: 1 (or 7?)


+required:
+  - reg
+
+required:
+  - '#address-cells'
+  - '#size-cells'
+
+required:
+  - compatible
+  - reg
+
+examples:
+  - |
+
+#include 
+
+spi {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  concentrator0: lora@0 {
+compatible = "semtech,sx1301";
+reg = <0>;
+reset-gpios = <&pioB 27 GPIO_ACTIVE_HIGH>;
+spi-max-frequency = <800>;
+
+radio-spi {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  radio0: lora@0 {
+compatible = "semtech,sx1257";
+        reg = <0>;
+  };
+
+  radio1: lora@1 {
+compatible = "semtech,sx1257";
+reg = <1>;
+  };
+};
+  };
+};
--
2.17.1



Thanks!
Ben Whitten


[PATCH v2 lora-next 1/4] dt-bindings: lora: sx130x: add basic documentation

2019-01-22 Thread Ben Whitten
From: Ben Whitten 

Add basic documentation in YAML format for the SX130x series concentrators
from Semtech.
Required is; the location on the SPI bus and the compatible string.

Signed-off-by: Ben Whitten 
---
v1 -> v2:
* Dropped reset-gpios, radio-spi from required.
* Dropped spi-max-frequency from binding.
* Changed compatible to allow fallback from SX1308 to SX1301.
* Wording changes in commit and descriptions.
* Dual licence
* Incorperate Robs comments on child node and spi wrapper
---
 .../bindings/net/lora/semtech,sx130x.yaml | 96 +++
 1 file changed, 96 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml

diff --git a/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml 
b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
new file mode 100644
index ..41919fb67ec4
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
@@ -0,0 +1,96 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/lora/semtech,sx130x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Semtech LoRa concentrator
+
+maintainers:
+  - Andreas Färber 
+  - Ben Whitten 
+
+description: |
+  Semtech LoRa concentrator SX130x digital baseband chip is capable of
+  demodulating LoRa signals on 8 channels simultaneously.
+
+  It is typically paired with two SX125x IQ radios controlled over an
+  SPI directly from the concentrator.
+
+  The concentrator itself is controlled over SPI.
+
+properties:
+  compatible:
+items:
+  - enum:
+- semtech,sx1308
+  - enum:
+- semtech,sx1301
+
+  reg:
+maxItems: 1
+description: The chip select on the SPI bus.
+
+  reset-gpios:
+maxItems: 1
+description: A connection of the reset gpio line.
+
+  radio-spi:
+type: object
+description: The concentrator can have two radios connected which are
+  contained within the following node.
+
+properties:
+  '#address-cells':
+const: 1
+
+  '#size-cells':
+const: 0
+
+patternProperties:
+  "^[a-zA-Z0-9]@[0-1]$":
+properties:
+  reg:
+maxItems: 1
+required:
+  - reg
+
+required:
+  - '#address-cells'
+  - '#size-cells'
+
+required:
+  - compatible
+  - reg
+
+examples:
+  - |
+
+#include 
+
+spi {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  concentrator0: lora@0 {
+compatible = "semtech,sx1301";
+reg = <0>;
+reset-gpios = <&pioB 27 GPIO_ACTIVE_HIGH>;
+spi-max-frequency = <800>;
+
+radio-spi {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  radio0: lora@0 {
+compatible = "semtech,sx1257";
+reg = <0>;
+  };
+
+  radio1: lora@1 {
+compatible = "semtech,sx1257";
+reg = <1>;
+  };
+};
+  };
+};
-- 
2.17.1



[PATCH v2 lora-next 0/4] net: lora: Add documentation for SX130x and SX125x parts

2019-01-22 Thread Ben Whitten
Hello,

This series adds documentation for the SX130x and SX125x chips.
We are using the yaml binding format and this series builds with
'make dt_binding_check'.

Thanks,
Ben Whitten

Ben Whitten (4):
  dt-bindings: lora: sx130x: add basic documentation
  dt-bindings: lora: sx125x: add basic documentation
  dt-bindings: lora: sx125x: add clock bindings
  dt-bindings: lora: sx130x: add clock bindings

 .../bindings/net/lora/semtech,sx125x.yaml |  72 ++
 .../bindings/net/lora/semtech,sx130x.yaml | 133 ++
 2 files changed, 205 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
 create mode 100644 
Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml

-- 
2.17.1



[PATCH v2 lora-next 2/4] dt-bindings: lora: sx125x: add basic documentation

2019-01-22 Thread Ben Whitten
From: Ben Whitten 

The SX125x family are IQ radio transceivers from Semtech configured over
SPI, they are typically connected to an SX130x series concentrator however
may be connected to a host directly.

Required properties include the radio number of the host or concentrator
bus.

Signed-off-by: Ben Whitten 
---
v1 -> v2:
* Dropped spi-max-frequency binding
* Wording changes to commit and descriptions
* Added spi wrapper suggested by Rob H
* Dual licence
---
 .../bindings/net/lora/semtech,sx125x.yaml | 44 +++
 1 file changed, 44 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml

diff --git a/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml 
b/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
new file mode 100644
index ..4a51a251d97f
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/lora/semtech,sx125x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Semtech IQ modulator/de-modulator transeiver
+
+maintainers:
+  - Andreas Färber 
+  - Ben Whitten 
+
+description: |
+  The SX125x family are transceivers capable of supporting multiple constant
+  and non-constant envelope modulation schemes.
+
+properties:
+  compatible:
+items:
+  - enum:
+- semtech,sx1255
+- semtech,sx1257
+- semtech,sx1258
+
+  reg:
+maxItems: 1
+description: The chip select on the SPI bus or radio number in concentrator
+  , with radio A = 0 and radio B = 1.
+
+required:
+  - compatible
+  - reg
+
+examples:
+  - |
+spi {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  radio0: lora@0 {
+compatible = "semtech,sx1257";
+reg = <0>;
+  };
+};
-- 
2.17.1



[PATCH v2 lora-next 3/4] dt-bindings: lora: sx125x: add clock bindings

2019-01-22 Thread Ben Whitten
From: Ben Whitten 

The SX125x consumes a clock (FXOSC) ranging from 32 to 36 MHz.
If the radio is coupled with an SX130x the radio is therefor operating in
master mode and it may also provide a gated version of this clock for the
concentrator. In this case the concentrator is expecting a 32 MHz input
clock.

In the example we connect to the "txco" clock source, represented by a
fixed clock. The radio also provides a clock output named "clk32m" for
consumption by the SX130x concentrator.

Signed-off-by: Ben Whitten 
---
v1 -> v2:
* Fixed incorrect usage of clock cells
* Fixed wording in commit and descriptions
* Dropped enforced clock names
---
 .../bindings/net/lora/semtech,sx125x.yaml | 28 +++
 1 file changed, 28 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml 
b/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
index 4a51a251d97f..8287472fd545 100644
--- a/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
+++ b/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
@@ -27,12 +27,36 @@ properties:
 description: The chip select on the SPI bus or radio number in concentrator
   , with radio A = 0 and radio B = 1.
 
+  clocks:
+maxItems: 1
+description: Input clock (FXOSC) provider with output ranging from 32 MHz
+  to 36 MHz.
+
+  clock-names:
+maxItems: 1
+description: Input clock (FXOSC) name from provider.
+
+  clock-output-names:
+maxItems: 1
+description: Output clock (CLK_OUT) name, clock is gated version of the
+  input (FXOSC). Used in master mode operation.
+
+  '#clock-cells':
+const: 0
+
 required:
   - compatible
   - reg
 
 examples:
   - |
+tcxo: dummy32m {
+  compatible = "fixed-clock";
+  clock-frequency = <3200>;
+  clock-output-names = "tcxo";
+  #clock-cells = <0>;
+};
+
 spi {
   #address-cells = <1>;
   #size-cells = <0>;
@@ -40,5 +64,9 @@ examples:
   radio0: lora@0 {
 compatible = "semtech,sx1257";
 reg = <0>;
+clocks = <&tcxo>;
+clock-names = "tcxo";
+clock-output-names = "clk32m";
+#clock-cells = <0>;
   };
 };
-- 
2.17.1



[PATCH v2 lora-next 4/4] dt-bindings: lora: sx130x: add clock bindings

2019-01-22 Thread Ben Whitten
From: Ben Whitten 

The SX130x family consumes two clocks, a 32 MHz clock provided by a
connected IQ transceiver, and a 133 MHz high speed clock.

In the example we connect the concentrator to a fixed clock providing
the 133 MHz high speed clock, and we connect to a connected transceiver
32 MHz clock.

The connected radios are both fed from a fixed 32 MHz clock, with only
one being the clock source back to the SX130x concentrator.

Signed-off-by: Ben Whitten 
---
v1 -> v2:
* Fixed incorrect usage of clock cells
* Fixed wording in commit and descriptions
---
 .../bindings/net/lora/semtech,sx130x.yaml | 39 ++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml 
b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
index 41919fb67ec4..6f9db3c84385 100644
--- a/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
+++ b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
@@ -15,7 +15,8 @@ description: |
   demodulating LoRa signals on 8 channels simultaneously.
 
   It is typically paired with two SX125x IQ radios controlled over an
-  SPI directly from the concentrator.
+  SPI directly from the concentrator. One of the radios will provide
+  a 32 MHz clock back into the concentrator.
 
   The concentrator itself is controlled over SPI.
 
@@ -35,6 +36,20 @@ properties:
 maxItems: 1
 description: A connection of the reset gpio line.
 
+  clocks:
+maxItems: 2
+items:
+  - description: 32 MHz clock provider (CLK32M)
+  - description: 133 MHz high speed clock provider (CLKHS)
+description: The chip requires two clock inputs; A 32MHz clock at CMOS
+  level which is provided from a connected radio.
+  And a 133MHz high speed clock at CMOS level provided by an oscillator.
+
+  clock-names:
+maxItems: 2
+description: Input clock (CLK32M) name from provider, Input clock (CLKHS)
+  name from provider.
+
   radio-spi:
 type: object
 description: The concentrator can have two radios connected which are
@@ -68,6 +83,20 @@ examples:
 
 #include 
 
+tcxo: dummy32m {
+  compatible = "fixed-clock";
+  clock-frequency = <3200>;
+  clock-output-names = "tcxo";
+  #clock-cells = <0>;
+};
+
+clkhs: dummy133m {
+  compatible = "fixed-clock";
+  clock-frequency = <13300>;
+  clock-output-names = "clkhs";
+  #clock-cells = <0>;
+};
+
 spi {
   #address-cells = <1>;
   #size-cells = <0>;
@@ -77,6 +106,8 @@ examples:
 reg = <0>;
 reset-gpios = <&pioB 27 GPIO_ACTIVE_HIGH>;
 spi-max-frequency = <800>;
+clocks = <&radio1>, <&clkhs>;
+clock-names = "clk32m", "clkhs";
 
 radio-spi {
   #address-cells = <1>;
@@ -85,11 +116,17 @@ examples:
   radio0: lora@0 {
 compatible = "semtech,sx1257";
 reg = <0>;
+clocks = <&tcxo>;
+clock-names = "tcxo";
   };
 
   radio1: lora@1 {
 compatible = "semtech,sx1257";
 reg = <1>;
+clocks = <&tcxo>;
+clock-names = "tcxo";
+clock-output-names = "clk32m";
+#clock-cells = <0>;
   };
 };
   };
-- 
2.17.1



RE: [PATCH lora-next 2/4] dt-bindings: lora: sx125x: add basic documentation

2019-01-16 Thread Ben Whitten
Hi Andreas,

> Am 08.01.19 um 09:41 schrieb Ben Whitten:
> > The sx125x family are IQ radio transceivers from Semtech configured over
> > SPI, they are typically connected to an sx130x series concentrator however
> > may be connected to a host directly.
> 
> "SX125x" and "SX130x"
> 
> >
> > Required properties include the radio number of the host or concentrator
> > bus.
> >
> > Signed-off-by: Ben Whitten 
> > ---
> >  .../bindings/lora/semtech,sx125x.yaml | 45 +++
> >  1 file changed, 45 insertions(+)
> >  create mode 100644
> Documentation/devicetree/bindings/lora/semtech,sx125x.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/lora/semtech,sx125x.yaml
> b/Documentation/devicetree/bindings/lora/semtech,sx125x.yaml
> > new file mode 100644
> > index ..5eadec860b70
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/lora/semtech,sx125x.yaml
> > @@ -0,0 +1,45 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/lora/semtech,sx125x.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Semtech IQ modulator/de-modulator transeiver
> > +
> > +maintainers:
> > +  - Andreas Färber 
> > +  - Ben Whitten 
> > +
> > +description: |
> > +  The sx125x family are highly integrated RF front-end to digital I and Q
> > +  modulator/demodulator Multi-PHY mode transceiver capable of
> supporting
> > +  multiple constant and non-constant envelope modulation schemes.
> 
> "SX125x"
> 
> "are ... transceivers"
> 
> > +
> > +properties:
> > +  compatible:
> > +items:
> > +  - enum:
> > +- semtech,sx1255
> > +- semtech,sx1257
> > +- semtech,sx1258
> 
> Do we need all three? Probably yes for the concentrator to make decisions?

We can probe the device version from the concentrator or a host, but if I recall
from a previous review we should not rely on the version register for making
decisions.
The version register of the SX1257 has been missed from the public datasheet
(although exists) and the existing concentrator HAL does not make decisions
based on the version register value.
Better to be explicit in the DT and let the driver use that.

> 
> > +
> > +  reg:
> > +maxItems: 1
> > +description: The chip select on the SPI bus or radio number in
> concentrator.
> 
> ", with radio A = 0 and radio B = 1."
> 
> > +
> > +  spi-max-frequency:
> > +maximum: 1000
> > +default: 800
> > +description: The frequency of the SPI communication to the radio,
> > +  in Hz. Maximum SPI frequency is 10MHz.
> 
> If on the concentrator's SPI bus then this is unused. You don't mark it
> required below, so maybe add a textual note?

As with SX130x comment, this should be covered in common SPI bindings
anyone connecting directly to spi will inherit that, and then anyone using
concentrator will not require it so we can drop this.

> 
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +
> > +examples:
> > +  - |
> > +radio0: lora@0 {
> > +  compatible = "semtech,sx1257";
> > +  reg = <0>;
> > +};
> 
> If you compare my sx127x implementation, should we prepare a
> "radio-frequency" (or "radio-center-frequency") property for the
> antenna, to preconfigure the driver during probe? Contents would then be
> <86800>, for example.

I don’t know the policy of configuration in DT.
Is the value a hardware property of the antenna? Could we call it
"antenna-frequency" or "bandwidth" and give it a high low point?
Whilst considering antenna properties we should include a gain value as
that affects the radiated power at a given transmit power, food for though
when we come to regulatory db.

Thanks,
Ben Whitten


RE: [PATCH lora-next 1/4] dt-bindings: lora: sx130x: add basic documentation

2019-01-16 Thread Ben Whitten
Hi Andreas,

> Am 08.01.19 um 09:41 schrieb Ben Whitten:
> > Add basic documentation in YAML format for the sx130x series concentrators
> > from Semtech.
> > Required is; the location on the SPI bus, the reset gpio and the node for
> > downstream IQ radios, typically sx125x.
> >
> > Signed-off-by: Ben Whitten 
> > ---
> >  .../bindings/lora/semtech,sx130x.yaml | 87 +++
> >  1 file changed, 87 insertions(+)
> >  create mode 100644
> Documentation/devicetree/bindings/lora/semtech,sx130x.yaml
> 
> Patch 3/4 moves this to net/lora/, which I think is more appropriate.

Agreed, I think it was a change merged into the wrong commits by mistake

> >
> > diff --git a/Documentation/devicetree/bindings/lora/semtech,sx130x.yaml
> b/Documentation/devicetree/bindings/lora/semtech,sx130x.yaml
> > new file mode 100644
> > index ..ad263bc4e60d
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/lora/semtech,sx130x.yaml
> > @@ -0,0 +1,87 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/lora/semtech,sx130x.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Semtech LoRa concentrator
> > +
> > +maintainers:
> > +  - Andreas Färber 
> > +  - Ben Whitten 
> > +
> > +description: |
> > +  Semtech LoRa concentrator sx130x digital baseband chip is capable of
> 
> SX130x or SX1301/SX1308, to distinguish from driver name sx130x and to
> avoid ambiguities of which x is a wildcard.
> 
> > +  demodulating LoRa signals on 8 channels simultaneously.
> > +
> > +  It is typically paired with two sx125x IQ radios controlled over an
> 
> Ditto, SX125x
> 
> > +  SPI directly from the concentrator.
> > +
> > +  The concentrator itself it controlled over SPI.
> > +
> > +properties:
> > +  compatible:
> > +items:
> > +  - enum:
> > +- semtech,sx1301
> > +- semtech,sx1308
> 
> We should only list both if we expect differences between the two
> models. Otherwise SX1308 can reuse the SX1301 compatible. If we want to
> mark it up just in case then rearranging the above to be a sequence of
> "semtech,sx1308", "semtech,sx1301" would be an alternative.

It was my understanding that we should name each device that is compatible,
avoiding wildcard 'x' in compatible names. This allows the device tree to be
more accurate to the hardware that it is describing.

I do not expect there to be much difference, but there may be some that I 
am unaware of.

Not sure I follow here, do you wish for the order to be flipped if we do want
to state every device? I see that example-schema does indeed have entries
in reverse.

> 
> > +
> > +  reg:
> > +maxItems: 1
> > +description: The chip select on the SPI bus.
> 
> Is this mandatory now or not with maxItems?

min/maxItems is implied if you have a list but for our chipselect we have no
list. I followed child-node-example.yaml in yaml-bindings and
trivial-devices.yaml in being explicit and stating it be one element and making
reg required.

> 
> > +
> > +  reset-gpios:
> > +maxItems: 1
> > +description: A connection of the reset gpio line.
> 
> This needs to be optional, which I think the maxItems syntax says unlike
> the commit message?
> On an mPCIe card you won't have such a GPIO, for instance. We do a Soft
> Reset, so it's not functionally mandatory.

I'll drop this from required and from the commit message.

> > +
> > +  spi-max-frequency:
> > +maximum: 1000
> > +default: 800
> > +description: The frequency of the SPI communication to the 
> > concentrator,
> > +  in Hz. Maximum SPI frequency is 10MHz although 8MHz is typically used
> > +  on a number of cards.
> 
> Do we really need to describe this here? It should be covered in the
> common SPI bindings, and only applies to SPI bus, not USB picoGW.

True, I'll drop this.

> 
> > +
> > +  radio-spi:
> > +description: The concentrator has two radios connected which are
> contained
> > +  within the following node.
> 
> "can have"
> 
> > +
> > +properties:
> > +  '#address-cells':
> > +const: 1
> > +
> > +  '#size-cells':
> > +const: 0
> > +
> > +required:
> > +  - '#address-cells'
> > +  - '#size-cells'
> 
> I'm pretty sure that Rob would like to have a compatible her

[PATCH lora-next 3/4] dt-bindings: lora: sx125x: add clock bindings

2019-01-08 Thread Ben Whitten
The sx125x consumes a 32MHz clock and if it is coupled with a sx130x
concentrator may also provide a gated version of this 32MHz for the
concentrator.

In the example we connect to output 0 of "txco" clock source. The radio
also provides a single clock output, hence "#clock-cells = <0>", named
"clk32m" for consumption by the sx130x concentrator.

Signed-off-by: Ben Whitten 
---
 .../{ => net}/lora/semtech,sx125x.yaml| 27 +++
 1 file changed, 27 insertions(+)
 rename Documentation/devicetree/bindings/{ => net}/lora/semtech,sx125x.yaml 
(67%)

diff --git a/Documentation/devicetree/bindings/lora/semtech,sx125x.yaml 
b/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
similarity index 67%
rename from Documentation/devicetree/bindings/lora/semtech,sx125x.yaml
rename to Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
index 5eadec860b70..c2fb4ac06341 100644
--- a/Documentation/devicetree/bindings/lora/semtech,sx125x.yaml
+++ b/Documentation/devicetree/bindings/net/lora/semtech,sx125x.yaml
@@ -33,13 +33,40 @@ properties:
 description: The frequency of the SPI communication to the radio,
   in Hz. Maximum SPI frequency is 10MHz.
 
+  clocks:
+maxItems: 1
+description: 32MHz clock provider
+
+  clock-names:
+items:
+  - const: txco
+
+  clock-output-names:
+items:
+  - const: clk32m
+description: 32MHz output clock name
+
+  '#clock-cells':
+const: 0
+
 required:
   - compatible
   - reg
 
 examples:
   - |
+tcxo: dummy32m {
+  compatible = "fixed-clock";
+  clock-frequency = <3200>;
+  clock-output-names = "tcxo";
+  #clock-cells = <0>;
+};
+
 radio0: lora@0 {
   compatible = "semtech,sx1257";
   reg = <0>;
+  clocks = <&tcxo 0>;
+  clock-names = "tcxo";
+  clock-output-names = "clk32m";
+  #clock-cells = <0>;
 };
-- 
2.17.1



[PATCH lora-next 4/4] dt-bindings: lora: sx130x: add clock bindings

2019-01-08 Thread Ben Whitten
The sx130x family consumes two clocks, a 32MHz clock provided by a
connected IQ transceiver, and a 133MHz high speed clock.

In the example we connect the concentrator to output 0 of a fixed clock
providing the 133MHz high speed clock, and we connect to output 0 of a
connected transceiver 32MHz clock.

The connected radios are both fed from output 0 of a fixed 32MHz clock,
with only one being the clock source back with one output to the
sx130x concentrator.

Signed-off-by: Ben Whitten 
---
 .../{ => net}/lora/semtech,sx130x.yaml| 39 ++-
 1 file changed, 38 insertions(+), 1 deletion(-)
 rename Documentation/devicetree/bindings/{ => net}/lora/semtech,sx130x.yaml 
(62%)

diff --git a/Documentation/devicetree/bindings/lora/semtech,sx130x.yaml 
b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
similarity index 62%
rename from Documentation/devicetree/bindings/lora/semtech,sx130x.yaml
rename to Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
index ad263bc4e60d..23a096ca2912 100644
--- a/Documentation/devicetree/bindings/lora/semtech,sx130x.yaml
+++ b/Documentation/devicetree/bindings/net/lora/semtech,sx130x.yaml
@@ -15,7 +15,8 @@ description: |
   demodulating LoRa signals on 8 channels simultaneously.
 
   It is typically paired with two sx125x IQ radios controlled over an
-  SPI directly from the concentrator.
+  SPI directly from the concentrator. One of the radios will provide
+  a 32MHz clock back into the concentrator.
 
   The concentrator itself it controlled over SPI.
 
@@ -41,6 +42,20 @@ properties:
   in Hz. Maximum SPI frequency is 10MHz although 8MHz is typically used
   on a number of cards.
 
+  clocks:
+maxItems: 2
+items:
+  - description: 32MHz clock provider
+  - description: 133MHz high speed clock provider
+description: The chip requires two clock inputs; A 32MHz clock at CMOS
+  level which is provided from a connected radio.
+  And a 133MHz high speed clock at CMOS level provided by an oscillator.
+
+  clock-names:
+items:
+  - const: clk32m
+  - const: clkhs
+
   radio-spi:
 description: The concentrator has two radios connected which are contained
   within the following node.
@@ -64,11 +79,27 @@ required:
 
 examples:
   - |
+tcxo: dummy32m {
+  compatible = "fixed-clock";
+  clock-frequency = <3200>;
+  clock-output-names = "tcxo";
+  #clock-cells = <0>;
+};
+
+clkhs: dummy133m {
+  compatible = "fixed-clock";
+  clock-frequency = <13300>;
+  clock-output-names = "clkhs";
+  #clock-cells = <0>;
+};
+
 concentrator0: lora@0 {
   compatible = "semtech,sx1301";
   reg = <0>;
   reset-gpios = <&pioB 27 GPIO_ACTIVE_HIGH>;
   spi-max-frequency = <800>;
+  clocks = <&radio1 0>, <&clkhs 0>;
+  clock-names = "clk32m", "clkhs";
 
   radio-spi {
 #address-cells = <1>;
@@ -77,11 +108,17 @@ examples:
 radio0: lora@0 {
   compatible = "semtech,sx1257";
   reg = <0>;
+  clocks = <&tcxo 0>;
+  clock-names = "tcxo";
 };
 
 radio1: lora@1 {
   compatible = "semtech,sx1257";
   reg = <1>;
+  clocks = <&tcxo 0>;
+  clock-names = "tcxo";
+  clock-output-names = "clk32m";
+  #clock-cells = <0>;
 };
   };
 };
-- 
2.17.1



[PATCH lora-next 1/4] dt-bindings: lora: sx130x: add basic documentation

2019-01-08 Thread Ben Whitten
Add basic documentation in YAML format for the sx130x series concentrators
from Semtech.
Required is; the location on the SPI bus, the reset gpio and the node for
downstream IQ radios, typically sx125x.

Signed-off-by: Ben Whitten 
---
 .../bindings/lora/semtech,sx130x.yaml | 87 +++
 1 file changed, 87 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/lora/semtech,sx130x.yaml

diff --git a/Documentation/devicetree/bindings/lora/semtech,sx130x.yaml 
b/Documentation/devicetree/bindings/lora/semtech,sx130x.yaml
new file mode 100644
index ..ad263bc4e60d
--- /dev/null
+++ b/Documentation/devicetree/bindings/lora/semtech,sx130x.yaml
@@ -0,0 +1,87 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/lora/semtech,sx130x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Semtech LoRa concentrator
+
+maintainers:
+  - Andreas Färber 
+  - Ben Whitten 
+
+description: |
+  Semtech LoRa concentrator sx130x digital baseband chip is capable of
+  demodulating LoRa signals on 8 channels simultaneously.
+
+  It is typically paired with two sx125x IQ radios controlled over an
+  SPI directly from the concentrator.
+
+  The concentrator itself it controlled over SPI.
+
+properties:
+  compatible:
+items:
+  - enum:
+- semtech,sx1301
+- semtech,sx1308
+
+  reg:
+maxItems: 1
+description: The chip select on the SPI bus.
+
+  reset-gpios:
+maxItems: 1
+description: A connection of the reset gpio line.
+
+  spi-max-frequency:
+maximum: 1000
+default: 800
+description: The frequency of the SPI communication to the concentrator,
+  in Hz. Maximum SPI frequency is 10MHz although 8MHz is typically used
+  on a number of cards.
+
+  radio-spi:
+description: The concentrator has two radios connected which are contained
+  within the following node.
+
+properties:
+  '#address-cells':
+const: 1
+
+  '#size-cells':
+const: 0
+
+required:
+  - '#address-cells'
+  - '#size-cells'
+
+required:
+  - compatible
+  - reg
+  - reset-gpios
+  - radio-spi
+
+examples:
+  - |
+concentrator0: lora@0 {
+  compatible = "semtech,sx1301";
+  reg = <0>;
+  reset-gpios = <&pioB 27 GPIO_ACTIVE_HIGH>;
+  spi-max-frequency = <800>;
+
+  radio-spi {
+#address-cells = <1>;
+#size-cells = <0>;
+
+radio0: lora@0 {
+  compatible = "semtech,sx1257";
+  reg = <0>;
+};
+
+radio1: lora@1 {
+  compatible = "semtech,sx1257";
+  reg = <1>;
+};
+  };
+};
-- 
2.17.1



[PATCH lora-next 2/4] dt-bindings: lora: sx125x: add basic documentation

2019-01-08 Thread Ben Whitten
The sx125x family are IQ radio transceivers from Semtech configured over
SPI, they are typically connected to an sx130x series concentrator however
may be connected to a host directly.

Required properties include the radio number of the host or concentrator
bus.

Signed-off-by: Ben Whitten 
---
 .../bindings/lora/semtech,sx125x.yaml | 45 +++
 1 file changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/lora/semtech,sx125x.yaml

diff --git a/Documentation/devicetree/bindings/lora/semtech,sx125x.yaml 
b/Documentation/devicetree/bindings/lora/semtech,sx125x.yaml
new file mode 100644
index ..5eadec860b70
--- /dev/null
+++ b/Documentation/devicetree/bindings/lora/semtech,sx125x.yaml
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/lora/semtech,sx125x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Semtech IQ modulator/de-modulator transeiver
+
+maintainers:
+  - Andreas Färber 
+  - Ben Whitten 
+
+description: |
+  The sx125x family are highly integrated RF front-end to digital I and Q
+  modulator/demodulator Multi-PHY mode transceiver capable of supporting
+  multiple constant and non-constant envelope modulation schemes.
+
+properties:
+  compatible:
+items:
+  - enum:
+- semtech,sx1255
+- semtech,sx1257
+- semtech,sx1258
+
+  reg:
+maxItems: 1
+description: The chip select on the SPI bus or radio number in 
concentrator.
+
+  spi-max-frequency:
+maximum: 1000
+default: 800
+description: The frequency of the SPI communication to the radio,
+  in Hz. Maximum SPI frequency is 10MHz.
+
+required:
+  - compatible
+  - reg
+
+examples:
+  - |
+radio0: lora@0 {
+  compatible = "semtech,sx1257";
+  reg = <0>;
+};
-- 
2.17.1



Re: [PATCH lora-next 3/5] net: lora: sx130x: Add PicoCell serdev driver

2019-01-05 Thread Ben Whitten
int)mac[1],
+   (unsigned int)mac[2],
+   (unsigned int)mac[3],
+   (unsigned int)mac[4],
+   (unsigned int)mac[5],
+   (unsigned int)mac[6],
+   (unsigned int)mac[7]);
+   while (ret == -ENOTSUPP && ((fw_version & 0xff) > 4)) {
+   ret = picogw_mcu_fw_check(picodev, --fw_version, NULL, HZ);
+   }
+   if (ret == -ENOTSUPP) {
+   dev_warn(&sdev->dev, "firmware check failed (%08x)\n", 
fw_version);
+   } else {
+   dev_err(&sdev->dev, "ID retrieval failed (%d)\n", ret);
+   serdev_device_close(sdev);
+   return ret;
+   }
+
+   ret = sx130x_probe(&sdev->dev);
+   if (ret) {
+   serdev_device_close(sdev);
+   return ret;
+   }
+
+   //dev_info(&sdev->dev, "Done.\n");
+
+   return 0;
+}
+
+static void picogw_serdev_remove(struct serdev_device *sdev)
+{
+   sx130x_remove(&sdev->dev);
+
+   serdev_device_close(sdev);
+
+   //dev_info(&sdev->dev, "Removed\n");
+}
+
+static const struct of_device_id picogw_serdev_of_match[] = {
+   { .compatible = "semtech,lora-picocell" },


lora-picocell or lora-picogw... picocell has mobile connotations, should 
we match the module name?



+   {}
+};
+MODULE_DEVICE_TABLE(of, picogw_serdev_of_match);
+
+static struct serdev_device_driver picogw_serdev_driver = {
+   .probe = picogw_serdev_probe,
+   .remove = picogw_serdev_remove,
+   .driver = {
+   .name = "lora-picogw",
+   .of_match_table = picogw_serdev_of_match,
+   },
+};
+
+static int __init picogw_serdev_init(void)
+{
+   int ret;
+
+   ret = serdev_device_driver_register(&picogw_serdev_driver);
+   if (ret) {
+   pr_err("serdev_device_driver_register failed (%d)", ret);
+   return ret;
+   }
+
+   return 0;
+}
+module_init(picogw_serdev_init);
+
+static void __exit picogw_serdev_exit(void)
+{
+   serdev_device_driver_unregister(&picogw_serdev_driver);
+}
+module_exit(picogw_serdev_exit);
+
+MODULE_LICENSE("GPL");



Thanks,
Ben Whitten


Re: [PATCH RFC lora-next 1/4] net: lora: sx125x sx1301: correct style warnings

2019-01-04 Thread Ben Whitten

Hi Andreas,

On 29/12/2018 09:05, Andreas Färber wrote:

Hi Ben,

Am 19.12.18 um 16:56 schrieb Ben Whitten:

Checkpatch highlights some style issues which need to be addressed.

Signed-off-by: Ben Whitten 
---
  drivers/net/lora/sx125x.c | 20 +--
  drivers/net/lora/sx1301.c | 52 ++-
  drivers/net/lora/sx1301.h |  7 +++---
  3 files changed, 45 insertions(+), 34 deletions(-)


Thanks for splitting this off from the functional changes. This will
need some more explanations and discussion. In particular the comment
changes look wrong to me. Also please don't butcher code just because
checkpatch.pl may warn about line length at this early stage.


Yeh they seemed odd but checkpatch doesn't like a /* on a line by its 
self it seems.




A good catch in there was the unsigned casts, which are no longer
necessary since the regmap conversion, so we should just squash that
into the earlier commits.

Note that I used to run checkpatch.pl as git commit hook:
http://blog.vmsplice.net/2011/03/how-to-automatically-run-checkpatchpl.html
But since some git update that started to break git rebase -i in case of
false positives (with rebase stopping and on trying to continue commits
unintentionally getting squashed), so I deactivated it again and don't
manually check each commit I stage anymore, in favor of slowly
completing implementations to a working point.


Good to know, I'll avoid running it for the time and drop this from the v2

Thanks!
Ben Whitten


Re: [PATCH RFC lora-next 2/4] net: lora: sx1301: add minimal to get AGC working prior to tx work

2019-01-04 Thread Ben Whitten




On 29/12/2018 09:58, Andreas Färber wrote:

Hi Ben,

Am 19.12.18 um 16:56 schrieb Ben Whitten:

As part of initialisation when opening the lora device after loading
the AGC firmware we need to satisfy its startup procedure which involves
a few steps;

Loading a 16 entry lookup table.
For this I have hard coded the laird ETSI certified table for use on the
RG186-M2 (EU) cards, this will need investigation on how other devices
load calibration data.


Isn't calibration performed before this firmware is initialized? I left
out reading the values back from firmware previously, but that should
get implemented. In the userspace implementation, do you get these from
a config file or did you modify the reference code to hardcode them?


The calibration you refer to is the IQ offset calibration, as far as
I can tell this is a separate thing from the power table the chip uses.
In the user space implementation these values are placed in the config
file.



If these are different calibration values from the ones returned by
firmware, then a DT property would be an easy way to get
hardware-specific data into the driver. However, same as with your clk
config, that makes us dependent on DT, which we shouldn't be for ACPI
and USB. If we consider it configuration data rather than an immutable
fact, then we would need a netlink command to set them.


Perhaps we can provide both mechanisms, a DT power table and a mechanism
to set via netlink prior to opening the interface.
As these power settings are hardware dependent and certified for our
card by FCC and ETSI I would prefer to include in DT.



In any case, we have some other vendors on this list, so hopefully
someone can comment. :)



Selecting the correct channel to transmit on.
Currently always 0 for the reference design.


Similarly: DT or netlink depending on whether fixed, and fall back to 0
as default.


Agreed, so on the DT would it be appropriate to have a handle in the
sx1301 node with a link to the radio which can transmit, eg.

tx = <&radio0 0>;

Allowing for both to be transmitters if that if a hardware choice.





Then ending the AGC init procedure and seeing that it has come up.

Signed-off-by: Ben Whitten 
---
  drivers/net/lora/sx1301.c | 254 +-
  drivers/net/lora/sx1301.h |  16 +++
  2 files changed, 268 insertions(+), 2 deletions(-)


Many thanks for working on this! Some nits inline.


diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index e75df93b96d8..0c7b6d0b31af 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -24,6 +24,121 @@
  
  #include "sx1301.h"
  
+static struct sx1301_tx_gain_lut tx_gain_lut[] = {

+   {
+   .dig_gain = 0,
+   .pa_gain = 0,
+   .dac_gain = 3,
+   .mix_gain = 8,
+   .rf_power = -3,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 0,
+   .dac_gain = 3,
+   .mix_gain = 9,
+   .rf_power = 0,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 0,
+   .dac_gain = 3,
+   .mix_gain = 12,
+   .rf_power = 3,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 0,
+   .dac_gain = 3,
+   .mix_gain = 13,
+   .rf_power = 4,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 1,
+   .dac_gain = 3,
+   .mix_gain = 8,
+   .rf_power = 6,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 1,
+   .dac_gain = 3,
+   .mix_gain = 9,
+   .rf_power = 9,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 1,
+   .dac_gain = 3,
+   .mix_gain = 10,
+   .rf_power = 10,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 1,
+   .dac_gain = 3,
+   .mix_gain = 11,
+   .rf_power = 12,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 1,
+   .dac_gain = 3,
+   .mix_gain = 12,
+   .rf_power = 13,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 1,
+   .dac_gain = 3,
+   .mix_gain = 13,
+   .rf_power = 14,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 1,
+   .dac_gain = 3,
+   .mix_gain = 15,
+   .rf_power = 16,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 2,
+   .dac_gain = 3,
+   .mix_gain = 10,
+   .rf_power = 19,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 2,
+   .dac_gain = 3,
+   .mix_gain = 11,

RE: [PATCH v5 5/6] net: maclorawan: Implement maclorawan class module

2018-12-20 Thread Ben Whitten
> > > Am 18.12.18 um 15:27 schrieb Jian-Hong Pan:
> > > >> Sun, Dec 16, 2018 at 11:18:59AM CET, starni...@g.ncu.edu.tw wrote:
> > > >>> LoRaWAN defined by LoRa Alliance(TM) is the MAC layer over LoRa
> > > devices.
> > > >>>
> > > >>> This patch implements part of Class A end-devices SoftMAC defined in
> > > >>> LoRaWAN(TM) Specification Ver. 1.0.2:
> > > >>> 1. End-device receive slot timing
> > > >>> 2. Only single channel and single data rate for now
> > > >>> 3. Unconfirmed data up/down message types
> > > >>>
> > > >>> On the other side, it defines the basic interface and operation
> > > >>> functions for compatible LoRa device drivers.
> > > >>>
> > > >>> Signed-off-by: Jian-Hong Pan 
> > > [...]
> > > >>> net/maclorawan/Kconfig  |  14 +
> > > >>> net/maclorawan/Makefile |   2 +
> > > >>> net/maclorawan/mac.c| 555
> > > 
> > > >>> net/maclorawan/main.c   | 606
> > > 
> > > >>> 4 files changed, 1177 insertions(+)
> > > >>> create mode 100644 net/maclorawan/Kconfig
> > > >>> create mode 100644 net/maclorawan/Makefile
> > > >>> create mode 100644 net/maclorawan/mac.c
> > > >>> create mode 100644 net/maclorawan/main.c
> > > >>
> > > >> I don't get it. In patch "Add LoRaWAN API declaration for LoRa devices"
> > > >> you add headers for "API" and here you implement functions. That is
> just
> > > >> weird. Does it mean you can have other implementations?
> > > >
> > > > LoRaWAN defined by LoRa Alliance(TM) is the MAC layer over LoRa PHY.
> > > > This part is soft-MAC as Andreas mentioned
> > > > http://lists.infradead.org/pipermail/linux-lpwan/2018-
> > > December/10.html
> > > >
> > > >> Also, you don't really have any user of this API in the set. Please
> > > >> introduce at least 1 driver, preferably more (I see that Andreas has
> > > >> multiple ones in his patchset). You cannot push kernel infrastructure
> > > >> without kernel user.
> > > >
> > > > The soft-MAC is suitable for the LoRa chips' device drivers, like
> > > > sx1276/77/78/79, RFM95/96/97/98W ...
> > > > Still waiting for Andreas' sx1276 version 2 patch and more discussion.
> > >
> > > sx1276 regmap conversion was pushed to my staging tree together with
> > > Ben's sx1301 final conversion last night, lightly tested.
> > >
> > > https://git.kernel.org/pub/scm/linux/kernel/git/afaerber/linux-
> > > lora.git/log/?h=lora-next
> > >
> > > TBD: rename to sx127x, implement regmap fields, only auto-detect reset
> > > when no OF node available (all low priority atm, patches welcome)
> > >
> > > (and for sx1301 I still need to update my DT overlays with the new clk)
> > >
> > > > For example, how to make PF_LORA and PF_LORAWAN like Ethernet,
> > > PF_INET
> > > > and PF_INET6 don't need separate devices either, both use eth0.
> > > > https://lkml.org/lkml/2018/8/3/266
> > >
> > > Jiri, I am expecting the maclorawan driver to lower packets from
> > > ETH_P_LORAWAN to ETH_P_LORA in a generic way, so that any of the LoRa
> > > device drivers can benefit of it, with maclorawan using the LoRa netlink
> > > commands that the individual drivers implement.
> > > Not sure what if anything is missing for that in the current revision?
> > > Still dealing with the lower-level infrastructure and my test setup ...
> > > progressing slowly.
> > >
> > > I'll probably need to queue the remaining generic LoRaWAN part 1/6 in my
> > > tree to resolve this circular dependency between Jian-Hong and me, so
> > > that only the soft-MAC implementation remains a separate patch series.
> > > The hard-MAC implementations will be on my plate mostly, as both SX1276
> > > and SX1301 need the soft-MAC.
> >
> > On the SX1301 side of things, the ability to send messages as a LoRaWAN
> > node device is a niche use case, the majority if not all people will use the
> > concentrator card as the pass through gateway to the node.
> >
> > In this mode of operation the parameters for transmission such as;
> frequency,
> > spreading factor / data rate, power, are given by a remote server and passed
> > in from the userspace application which received it.
> > Eventually in the kernel these need to be checked locally to ensure
> regulatory
> > compliance.
> > To that end I have experimented with framing, as CAN does, so that this
> > metadata can be provided on a write from userspace to the SX1301 driver.
> >
> > Sounds like we need different protocols for framing within the protocol
> family.
> > Raw in the case of nodes and framed with metadata in the case of
> concentrator
> > cards, thoughts?
> 
> Yes, I have thought the roles of node and gateway.  They may have
> different skb passing paths.
> As you mentioned, many things of the gateway is controlled by the
> remote server.  So, I only implement the path for nodes right now.
> Maybe, we can have a role flag: node, gateway which can be assigned by
> some way.  Then, the skb can be decode, checked and passed according
> to the role flag.  And module also ch

[PATCH RFC lora-next 1/4] net: lora: sx125x sx1301: correct style warnings

2018-12-19 Thread Ben Whitten
Checkpatch highlights some style issues which need to be addressed.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx125x.c | 20 +--
 drivers/net/lora/sx1301.c | 52 ++-
 drivers/net/lora/sx1301.h |  7 +++---
 3 files changed, 45 insertions(+), 34 deletions(-)

diff --git a/drivers/net/lora/sx125x.c b/drivers/net/lora/sx125x.c
index b7ca782b9386..1a941f663c52 100644
--- a/drivers/net/lora/sx125x.c
+++ b/drivers/net/lora/sx125x.c
@@ -49,7 +49,7 @@ struct sx125x_priv {
 
struct device   *dev;
struct regmap   *regmap;
-   struct regmap_field 
*regmap_fields[ARRAY_SIZE(sx125x_regmap_fields)];
+   struct regmap_field *regmap_fields[ARRAY_SIZE(sx125x_regmap_fields)];
 };
 
 #define to_clkout(_hw) container_of(_hw, struct sx125x_priv, clkout_hw)
@@ -67,13 +67,13 @@ static struct regmap_config __maybe_unused 
sx125x_regmap_config = {
 };
 
 static int sx125x_field_write(struct sx125x_priv *priv,
-   enum sx125x_fields field_id, u8 val)
+ enum sx125x_fields field_id, u8 val)
 {
return regmap_field_write(priv->regmap_fields[field_id], val);
 }
 
 static int sx125x_field_read(struct sx125x_priv *priv,
-   enum sx125x_fields field_id, unsigned int *val)
+enum sx125x_fields field_id, unsigned int *val)
 {
return regmap_field_read(priv->regmap_fields[field_id], val);
 }
@@ -149,8 +149,12 @@ static int sx125x_register_clock_provider(struct 
sx125x_priv *priv)
init.num_parents = 1;
priv->clkout_hw.init = &init;
 
-   of_property_read_string_index(dev->of_node, "clock-output-names", 0,
-   &init.name);
+   ret = of_property_read_string_index(dev->of_node, "clock-output-names",
+   0, &init.name);
+   if (ret) {
+   dev_err(dev, "unable to find output name\n");
+   return ret;
+   }
 
priv->clkout = devm_clk_register(dev, &priv->clkout_hw);
if (IS_ERR(priv->clkout)) {
@@ -158,7 +162,7 @@ static int sx125x_register_clock_provider(struct 
sx125x_priv *priv)
return PTR_ERR(priv->clkout);
}
ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_simple_get,
-   &priv->clkout_hw);
+&priv->clkout_hw);
return ret;
 }
 
@@ -180,8 +184,8 @@ static int __maybe_unused sx125x_regmap_probe(struct device 
*dev, struct regmap
const struct reg_field *reg_fields = sx125x_regmap_fields;
 
priv->regmap_fields[i] = devm_regmap_field_alloc(dev,
-   priv->regmap,
-   reg_fields[i]);
+priv->regmap,
+reg_fields[i]);
if (IS_ERR(priv->regmap_fields[i])) {
ret = PTR_ERR(priv->regmap_fields[i]);
dev_err(dev, "Cannot allocate regmap field: %d\n", ret);
diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 23cbddc364e5..e75df93b96d8 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -1,6 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Semtech SX1301 LoRa concentrator
+/* Semtech SX1301 LoRa concentrator
  *
  * Copyright (c) 2018 Andreas Färber
  * Copyright (c) 2018 Ben Whitten
@@ -55,12 +54,13 @@ static struct regmap_config sx1301_regmap_config = {
 };
 
 static int sx1301_field_write(struct sx1301_priv *priv,
-   enum sx1301_fields field_id, u8 val)
+ enum sx1301_fields field_id, u8 val)
 {
return regmap_field_write(priv->regmap_fields[field_id], val);
 }
 
-static int sx1301_agc_ram_read(struct sx1301_priv *priv, u8 addr, unsigned int 
*val)
+static int sx1301_agc_ram_read(struct sx1301_priv *priv, u8 addr,
+  unsigned int *val)
 {
int ret;
 
@@ -79,7 +79,8 @@ static int sx1301_agc_ram_read(struct sx1301_priv *priv, u8 
addr, unsigned int *
return 0;
 }
 
-static int sx1301_arb_ram_read(struct sx1301_priv *priv, u8 addr, unsigned int 
*val)
+static int sx1301_arb_ram_read(struct sx1301_priv *priv, u8 addr,
+  unsigned int *val)
 {
int ret;
 
@@ -98,7 +99,8 @@ static int sx1301_arb_ram_read(struct sx1301_priv *priv, u8 
addr, unsigned int *
return 0;
 }
 
-static int sx1301_load_firmware(struct sx1301_priv *priv, int mcu, const 
struct firmware *fw)
+static int sx1301_load_firmware(struct sx1301_priv *priv, int mcu,
+   const struct firmware *fw)
 {
u8 *buf;
enum sx1301_fields rst, select_mux;
@@ -165,7 +167,8 @@ st

[PATCH RFC lora-next 2/4] net: lora: sx1301: add minimal to get AGC working prior to tx work

2018-12-19 Thread Ben Whitten
As part of initialisation when opening the lora device after loading
the AGC firmware we need to satisfy its startup procedure which involves
a few steps;

Loading a 16 entry lookup table.
For this I have hard coded the laird ETSI certified table for use on the
RG186-M2 (EU) cards, this will need investigation on how other devices
load calibration data.

Selecting the correct channel to transmit on.
Currently always 0 for the reference design.

Then ending the AGC init procedure and seeing that it has come up.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 254 +-
 drivers/net/lora/sx1301.h |  16 +++
 2 files changed, 268 insertions(+), 2 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index e75df93b96d8..0c7b6d0b31af 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -24,6 +24,121 @@
 
 #include "sx1301.h"
 
+static struct sx1301_tx_gain_lut tx_gain_lut[] = {
+   {
+   .dig_gain = 0,
+   .pa_gain = 0,
+   .dac_gain = 3,
+   .mix_gain = 8,
+   .rf_power = -3,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 0,
+   .dac_gain = 3,
+   .mix_gain = 9,
+   .rf_power = 0,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 0,
+   .dac_gain = 3,
+   .mix_gain = 12,
+   .rf_power = 3,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 0,
+   .dac_gain = 3,
+   .mix_gain = 13,
+   .rf_power = 4,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 1,
+   .dac_gain = 3,
+   .mix_gain = 8,
+   .rf_power = 6,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 1,
+   .dac_gain = 3,
+   .mix_gain = 9,
+   .rf_power = 9,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 1,
+   .dac_gain = 3,
+   .mix_gain = 10,
+   .rf_power = 10,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 1,
+   .dac_gain = 3,
+   .mix_gain = 11,
+   .rf_power = 12,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 1,
+   .dac_gain = 3,
+   .mix_gain = 12,
+   .rf_power = 13,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 1,
+   .dac_gain = 3,
+   .mix_gain = 13,
+   .rf_power = 14,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 1,
+   .dac_gain = 3,
+   .mix_gain = 15,
+   .rf_power = 16,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 2,
+   .dac_gain = 3,
+   .mix_gain = 10,
+   .rf_power = 19,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 2,
+   .dac_gain = 3,
+   .mix_gain = 11,
+   .rf_power = 21,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 2,
+   .dac_gain = 3,
+   .mix_gain = 12,
+   .rf_power = 22,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 2,
+   .dac_gain = 3,
+   .mix_gain = 13,
+   .rf_power = 24,
+   },
+   {
+   .dig_gain = 0,
+   .pa_gain = 2,
+   .dac_gain = 3,
+   .mix_gain = 14,
+   .rf_power = 25,
+   },
+};
+
 static const struct regmap_range_cfg sx1301_regmap_ranges[] = {
{
.name = "Pages",
@@ -184,6 +299,34 @@ static int sx1301_load_firmware(struct sx1301_priv *priv, 
int mcu,
return 0;
 }
 
+static int sx1301_agc_transaction(struct sx1301_priv *priv, unsigned int val,
+ unsigned int *status)
+{
+   int ret;
+
+   ret = regmap_write(priv->regmap, SX1301_CHRS, SX1301_AGC_CMD_WAIT);
+   if (ret) {
+   dev_err(priv->dev, "AGC transaction start failed\n");
+   return ret;
+   }
+   usleep_range(1000, 2000);
+
+   ret = regmap_write(priv->regmap, SX1301_CHRS, val);
+   if (ret) {
+   dev_err(priv->dev, "AGC transaction value failed\n");
+   return ret;
+   }
+   usleep_range(1000, 2000);
+
+   ret = regmap_read(priv->regmap, SX1301_AGCSTS, status);
+   if (ret) {
+   dev_err(priv->dev, "AGC status read failed\n");
+   return ret;
+   }
+
+   return 0;
+}
+
 static int sx1301_agc_calibrate(struct sx1301_priv *priv)
 

[PATCH RFC lora-next 4/4] net: lora: sx1301: introduce a lora frame for packet metadata

2018-12-19 Thread Ben Whitten
Information such as spreading factor, coding rate and power are on a per
transmission basis so it makes sence to include this in a header much
like CAN frames do.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/dev.c|  2 -
 drivers/net/lora/sx1301.c | 79 +--
 include/uapi/linux/lora.h | 46 +++
 3 files changed, 114 insertions(+), 13 deletions(-)

diff --git a/drivers/net/lora/dev.c b/drivers/net/lora/dev.c
index 0d4823de8c06..62dbe21668b0 100644
--- a/drivers/net/lora/dev.c
+++ b/drivers/net/lora/dev.c
@@ -11,8 +11,6 @@
 #include 
 #include 
 
-#define LORA_MTU 256 /* XXX */
-
 struct sk_buff *alloc_lora_skb(struct net_device *dev, u8 **data)
 {
struct sk_buff *skb;
diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 9bcbb967f307..fed6d6201bf3 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -584,7 +584,7 @@ static int sx1301_load_tx_gain_lut(struct sx1301_priv *priv)
return ret;
 };
 
-static int sx1301_tx(struct sx1301_priv *priv, void *data, int len)
+static int sx1301_tx(struct sx1301_priv *priv, struct lora_frame *frame)
 {
int ret, i;
u8 buff[256 + 16];
@@ -617,11 +617,67 @@ static int sx1301_tx(struct sx1301_priv *priv, void 
*data, int len)
hdr->tx_power = 15; /* HACK power entry 15 */
 
hdr->u.lora.crc16_en = 1; /* Enable CRC16 */
-   hdr->u.lora.cr = 1; /* CR 4/5 */
-   hdr->u.lora.sf = 7; /* SF7 */
-   hdr->u.lora.payload_len = len; /* Set the data len to the skb len */
+
+   switch (frame->cr) {
+   case LORA_CR_4_5:
+   hdr->u.lora.cr = 1; /* CR 4/5 */
+   break;
+   case LORA_CR_4_6:
+   hdr->u.lora.cr = 2; /* CR 4/6 */
+   break;
+   case LORA_CR_4_7:
+   hdr->u.lora.cr = 3; /* CR 4/7 */
+   break;
+   case LORA_CR_4_8:
+   hdr->u.lora.cr = 4; /* CR 4/8 */
+   break;
+   default:
+   return -ENXIO;
+   }
+
+   switch (frame->sf) {
+   case LORA_SF_6:
+   hdr->u.lora.sf = 6; /* SF6 */
+   break;
+   case LORA_SF_7:
+   hdr->u.lora.sf = 7; /* SF7 */
+   break;
+   case LORA_SF_8:
+   hdr->u.lora.sf = 8; /* SF8 */
+   break;
+   case LORA_SF_9:
+   hdr->u.lora.sf = 9; /* SF9 */
+   break;
+   case LORA_SF_10:
+   hdr->u.lora.sf = 10; /* SF10 */
+   break;
+   case LORA_SF_11:
+   hdr->u.lora.sf = 11; /* SF11 */
+   break;
+   case LORA_SF_12:
+   hdr->u.lora.sf = 12; /* SF12 */
+   break;
+   default:
+   return -ENXIO;
+   }
+
+   hdr->u.lora.payload_len = frame->len; /* Set the data length */
hdr->u.lora.implicit_header = 0; /* No implicit header */
-   hdr->u.lora.mod_bw = 0; /* Set 125KHz BW */
+
+   switch (frame->bw) {
+   case LORA_BW_125KHZ:
+   hdr->u.lora.mod_bw = 0; /* 125KHz BW */
+   break;
+   case LORA_BW_250KHZ:
+   hdr->u.lora.mod_bw = 1; /* 250KHz BW */
+   break;
+   case LORA_BW_500KHZ:
+   hdr->u.lora.mod_bw = 2; /* 500KHz BW */
+   break;
+   default:
+   return -ENXIO;
+   }
+
hdr->u.lora.ppm_offset = 0; /* TODO no ppm offset? */
hdr->u.lora.invert_pol = 0; /* TODO set no inverted polarity */
 
@@ -632,7 +688,7 @@ static int sx1301_tx(struct sx1301_priv *priv, void *data, 
int len)
 
/* Copy the TX data into the buffer ready to go */
 
-   memcpy((void *)&buff[16], data, len);
+   memcpy((void *)&buff[16], frame->data, frame->len);
 
/* Reset any transmissions */
ret = regmap_write(priv->regmap, SX1301_TX_TRIG, 0);
@@ -644,7 +700,7 @@ static int sx1301_tx(struct sx1301_priv *priv, void *data, 
int len)
if (ret)
return ret;
ret = regmap_noinc_write(priv->regmap, SX1301_TX_DATA_BUF_DATA, buff,
-len + 16);
+frame->len + 16);
if (ret)
return ret;
 
@@ -653,8 +709,8 @@ static int sx1301_tx(struct sx1301_priv *priv, void *data, 
int len)
if (ret)
return ret;
 
-   dev_dbg(priv->dev, "Transmitting packet of size %d: ", len);
-   for (i = 0; i < len + 16; i++)
+   dev_dbg(priv->dev, "Transmitting packet of size %d: ", frame->len);
+   for (i = 0; i < frame->len + 16; i++)
dev_dbg(priv->dev, "%X", buff[i]);
 
return ret;
@@ -683,17 +739,18 @@ static void sx1301_tx_work_handler(struct work_struct *ws)
struct sx1301_priv *priv = container_of(ws, struct sx

[PATCH RFC lora-next 3/4] net: lora: sx1301: add minimal to get transmission out

2018-12-19 Thread Ben Whitten
Because we cannot wait inside start_xmit so we copy the pointer to the skb
and schedule transmission work to be done.

For the transmission a lot is hard coded to just get a signal out of the
sx1301, it looks like using a header like CAN frames do will be a good
mechanism to get information such as coding rate, spreading factor and
power into the transmission.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 166 +-
 drivers/net/lora/sx1301.h |  21 +
 2 files changed, 186 insertions(+), 1 deletion(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 0c7b6d0b31af..9bcbb967f307 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -24,6 +24,44 @@
 
 #include "sx1301.h"
 
+struct sx1301_tx_header {
+   u8  tx_freq[3];
+   u32 start;
+   u8  tx_power:4,
+   modulation_type:1,
+   radio_select:1,
+   resered0:2;
+   u8  reserved1;
+
+   union {
+   struct lora_t {
+   u8  sf:4,
+   cr:3,
+   crc16_en:1;
+   u8  payload_len;
+   u8  mod_bw:2,
+   implicit_header:1,
+   ppm_offset:1,
+   invert_pol:1,
+   reserved0:3;
+   u16 preamble;
+   u8  reserved1;
+   u8  reserved2;
+   } lora;
+   struct fsk_t {
+   u8  freq_dev;
+   u8  payload_len;
+   u8  packet_mode:1,
+   crc_en:1,
+   enc_mode:2,
+   crc_mode:1,
+   reserved0:3;
+   u16 preamble;
+   u16 bitrate;
+   } fsk;
+   } u;
+} __packed;
+
 static struct sx1301_tx_gain_lut tx_gain_lut[] = {
{
.dig_gain = 0,
@@ -546,9 +584,87 @@ static int sx1301_load_tx_gain_lut(struct sx1301_priv 
*priv)
return ret;
 };
 
+static int sx1301_tx(struct sx1301_priv *priv, void *data, int len)
+{
+   int ret, i;
+   u8 buff[256 + 16];
+   struct sx1301_tx_header *hdr = (struct sx1301_tx_header *)buff;
+
+   /* TODO general checks to make sure we CAN send */
+
+   /* TODO Enable notch filter for lora 125 */
+
+   /* TODO get start delay for this TX */
+
+   /* TODO interpret tx power, HACK just set max power */
+
+   /* TODO get TX imbalance for this pow index from calibration step */
+
+   /* TODO set the dig gain */
+
+   /* TODO set TX PLL freq based on radio used to TX */
+
+   memset(buff, 0, sizeof(buff));
+
+   /* HACK set to 868MHz */
+   hdr->tx_freq[0] = 217;
+   hdr->tx_freq[1] = 0;
+   hdr->tx_freq[3] = 0;
+
+   hdr->start = 0; /* Start imediatly */
+   hdr->radio_select = 0; /* HACK Radio A transmit */
+   hdr->modulation_type = 0; /* HACK modulation LORA */
+   hdr->tx_power = 15; /* HACK power entry 15 */
+
+   hdr->u.lora.crc16_en = 1; /* Enable CRC16 */
+   hdr->u.lora.cr = 1; /* CR 4/5 */
+   hdr->u.lora.sf = 7; /* SF7 */
+   hdr->u.lora.payload_len = len; /* Set the data len to the skb len */
+   hdr->u.lora.implicit_header = 0; /* No implicit header */
+   hdr->u.lora.mod_bw = 0; /* Set 125KHz BW */
+   hdr->u.lora.ppm_offset = 0; /* TODO no ppm offset? */
+   hdr->u.lora.invert_pol = 0; /* TODO set no inverted polarity */
+
+   hdr->u.lora.preamble = 8; /* Set the standard preamble */
+
+   /* TODO 2 Msb in tx_freq0 for large narrow filtering, unset for now */
+   hdr->tx_freq[0] &= 0x3F;
+
+   /* Copy the TX data into the buffer ready to go */
+
+   memcpy((void *)&buff[16], data, len);
+
+   /* Reset any transmissions */
+   ret = regmap_write(priv->regmap, SX1301_TX_TRIG, 0);
+   if (ret)
+   return ret;
+
+   /* Put the buffer into the tranmit fifo */
+   ret = regmap_write(priv->regmap, SX1301_TX_DATA_BUF_ADDR, 0);
+   if (ret)
+   return ret;
+   ret = regmap_noinc_write(priv->regmap, SX1301_TX_DATA_BUF_DATA, buff,
+len + 16);
+   if (ret)
+   return ret;
+
+   /* HACK just go for immediate transfer */
+   ret = sx1301_field_write(priv, F_TX_TRIG_IMMEDIATE, 1);
+   if (ret)
+   return ret;
+
+   dev_dbg(priv->dev, "Transmitting packet of size %d: ", len);
+   for (i = 0; i < len + 16; i++)
+   dev_dbg(priv->dev, "%X", buff[i]);
+
+   return ret;
+}
+
 static netdev_tx_t sx130x_loradev_start_xmit(str

[PATCH RFC lora-next 0/4] Get sx1301 to transmit lora packets

2018-12-19 Thread Ben Whitten
If we ignore the first commit here which corrects style issues this
series gets the AGC firmware running then implements framing over
the lora socket to get the metadata the concentrator needs to send
a lora packet.

It could be that we need two protocals in the lora protocal family,
one raw and used for node devices, and one with framing and used in
gateways.
But it depends if node devices need information from the LoRaWAN
layer such as spreading factor and coding rate to initiate a
transmission.

I tested this with a tx_test userspace application [1] to adjust
bandwidth.

[1] https://github.com/BWhitten/lora-modules/blob/master/tx_test.c

Ben Whitten (4):
  net: lora: sx125x sx1301: correct style warnings
  net: lora: sx1301: add minimal to get AGC working prior to tx work
  net: lora: sx1301: add minimal to get transmission out
  net: lora: sx1301: introduce a lora frame for packet metadata

 drivers/net/lora/dev.c|   2 -
 drivers/net/lora/sx125x.c |  20 +-
 drivers/net/lora/sx1301.c | 529 --
 drivers/net/lora/sx1301.h |  44 +++-
 include/uapi/linux/lora.h |  46 
 5 files changed, 602 insertions(+), 39 deletions(-)

-- 
2.17.1



RE: [PATCH v5 5/6] net: maclorawan: Implement maclorawan class module

2018-12-19 Thread Ben Whitten
> Am 18.12.18 um 15:27 schrieb Jian-Hong Pan:
> >> Sun, Dec 16, 2018 at 11:18:59AM CET, starni...@g.ncu.edu.tw wrote:
> >>> LoRaWAN defined by LoRa Alliance(TM) is the MAC layer over LoRa
> devices.
> >>>
> >>> This patch implements part of Class A end-devices SoftMAC defined in
> >>> LoRaWAN(TM) Specification Ver. 1.0.2:
> >>> 1. End-device receive slot timing
> >>> 2. Only single channel and single data rate for now
> >>> 3. Unconfirmed data up/down message types
> >>>
> >>> On the other side, it defines the basic interface and operation
> >>> functions for compatible LoRa device drivers.
> >>>
> >>> Signed-off-by: Jian-Hong Pan 
> [...]
> >>> net/maclorawan/Kconfig  |  14 +
> >>> net/maclorawan/Makefile |   2 +
> >>> net/maclorawan/mac.c| 555
> 
> >>> net/maclorawan/main.c   | 606
> 
> >>> 4 files changed, 1177 insertions(+)
> >>> create mode 100644 net/maclorawan/Kconfig
> >>> create mode 100644 net/maclorawan/Makefile
> >>> create mode 100644 net/maclorawan/mac.c
> >>> create mode 100644 net/maclorawan/main.c
> >>
> >> I don't get it. In patch "Add LoRaWAN API declaration for LoRa devices"
> >> you add headers for "API" and here you implement functions. That is just
> >> weird. Does it mean you can have other implementations?
> >
> > LoRaWAN defined by LoRa Alliance(TM) is the MAC layer over LoRa PHY.
> > This part is soft-MAC as Andreas mentioned
> > http://lists.infradead.org/pipermail/linux-lpwan/2018-
> December/10.html
> >
> >> Also, you don't really have any user of this API in the set. Please
> >> introduce at least 1 driver, preferably more (I see that Andreas has
> >> multiple ones in his patchset). You cannot push kernel infrastructure
> >> without kernel user.
> >
> > The soft-MAC is suitable for the LoRa chips' device drivers, like
> > sx1276/77/78/79, RFM95/96/97/98W ...
> > Still waiting for Andreas' sx1276 version 2 patch and more discussion.
> 
> sx1276 regmap conversion was pushed to my staging tree together with
> Ben's sx1301 final conversion last night, lightly tested.
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/afaerber/linux-
> lora.git/log/?h=lora-next
> 
> TBD: rename to sx127x, implement regmap fields, only auto-detect reset
> when no OF node available (all low priority atm, patches welcome)
> 
> (and for sx1301 I still need to update my DT overlays with the new clk)
> 
> > For example, how to make PF_LORA and PF_LORAWAN like Ethernet,
> PF_INET
> > and PF_INET6 don't need separate devices either, both use eth0.
> > https://lkml.org/lkml/2018/8/3/266
> 
> Jiri, I am expecting the maclorawan driver to lower packets from
> ETH_P_LORAWAN to ETH_P_LORA in a generic way, so that any of the LoRa
> device drivers can benefit of it, with maclorawan using the LoRa netlink
> commands that the individual drivers implement.
> Not sure what if anything is missing for that in the current revision?
> Still dealing with the lower-level infrastructure and my test setup ...
> progressing slowly.
> 
> I'll probably need to queue the remaining generic LoRaWAN part 1/6 in my
> tree to resolve this circular dependency between Jian-Hong and me, so
> that only the soft-MAC implementation remains a separate patch series.
> The hard-MAC implementations will be on my plate mostly, as both SX1276
> and SX1301 need the soft-MAC.

On the SX1301 side of things, the ability to send messages as a LoRaWAN
node device is a niche use case, the majority if not all people will use the
concentrator card as the pass through gateway to the node.

In this mode of operation the parameters for transmission such as; frequency,
spreading factor / data rate, power, are given by a remote server and passed
in from the userspace application which received it.
Eventually in the kernel these need to be checked locally to ensure regulatory
compliance.
To that end I have experimented with framing, as CAN does, so that this
metadata can be provided on a write from userspace to the SX1301 driver.

Sounds like we need different protocols for framing within the protocol family.
Raw in the case of nodes and framed with metadata in the case of concentrator
cards, thoughts?
I will send my experiment RFC to the lpwan mailing list.

Regards,
Ben Whitten


[lora-next RFC] Socket details for PF_LORA on sx1301

2018-11-05 Thread Ben Whitten
Hi,

Using the test application to send data into a PF_LORA socket I have gotten
the sx1301 driver to a point where I was able to produce a LoRa packet
on the air.

There a few options that this socket will need per transmission from the
upper layers which I have compiled with some questions, I will focus on
the LoRa modulation - will FSK have a different socket type?

Transmission frequency in MHz.
Transmit time - can we use SO_TXTIME sockopt?
Modulation bandwidth.
Transmission power in dBm.
Enable CRC16.
Coding rate.
Spreading factor.
Preamble.

The rest of the info needed to program the sx1301 can be inferred from
the hardware configuration or set as a sysfs entry if needed; for example
which radio (A/B) to use as transmitter.
The reference design only has one radios (A) transmit pins connected so
is a static hardware choice set in DTS.

What would be the best way to get this additional info down to the lora
portion of the socket, setsockopts?

Thanks,
Ben Whitten



[PATCH v3 lora-next 2/5] net: lora: sx1301: replace burst spi functions with regmap_noinc

2018-10-12 Thread Ben Whitten
We can now use to regmap_noinc API to allow reading and writing to
the internal FIFO register which controls processor memory.
We also remove the now defunct spi element from the structure as this
completes the move to regmap.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 22 ++
 drivers/net/lora/sx1301.h |  2 --
 2 files changed, 2 insertions(+), 22 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index fd29258..9c85fe7 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -74,23 +74,6 @@ static struct regmap_config sx1301_regmap_config = {
.max_register = SX1301_MAX_REGISTER,
 };
 
-static int sx1301_read_burst(struct sx1301_priv *priv, u8 reg, u8 *val, size_t 
len)
-{
-   u8 addr = reg & 0x7f;
-   return spi_write_then_read(priv->spi, &addr, 1, val, len);
-}
-
-static int sx1301_write_burst(struct sx1301_priv *priv, u8 reg, const u8 *val, 
size_t len)
-{
-   u8 addr = reg | BIT(7);
-   struct spi_transfer xfr[2] = {
-   { .tx_buf = &addr, .len = 1 },
-   { .tx_buf = val, .len = len },
-   };
-
-   return spi_sync_transfer(priv->spi, xfr, 2);
-}
-
 static int sx1301_soft_reset(struct sx1301_priv *priv)
 {
return regmap_write(priv->regmap, SX1301_PAGE, 
REG_PAGE_RESET_SOFT_RESET);
@@ -180,7 +163,7 @@ static int sx1301_load_firmware(struct sx1301_priv *priv, 
int mcu, const struct
return ret;
}
 
-   ret = sx1301_write_burst(priv, SX1301_MPD, fw->data, fw->size);
+   ret = regmap_noinc_write(priv->regmap, SX1301_MPD, fw->data, fw->size);
if (ret) {
dev_err(priv->dev, "MCU prom data write failed\n");
return ret;
@@ -196,7 +179,7 @@ static int sx1301_load_firmware(struct sx1301_priv *priv, 
int mcu, const struct
if (!buf)
return -ENOMEM;
 
-   ret = sx1301_read_burst(priv, SX1301_MPD, buf, fw->size);
+   ret = regmap_noinc_read(priv->regmap, SX1301_MPD, buf, fw->size);
if (ret) {
dev_err(priv->dev, "MCU prom data read failed\n");
kfree(buf);
@@ -566,7 +549,6 @@ static int sx1301_probe(struct spi_device *spi)
 
spi_set_drvdata(spi, netdev);
priv->dev = &spi->dev;
-   priv->spi = spi;
 
priv->regmap = devm_regmap_init_spi(spi, &sx1301_regmap_config);
if (IS_ERR(priv->regmap)) {
diff --git a/drivers/net/lora/sx1301.h b/drivers/net/lora/sx1301.h
index e939c02..e6400f8 100644
--- a/drivers/net/lora/sx1301.h
+++ b/drivers/net/lora/sx1301.h
@@ -12,7 +12,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #define SX1301_CHIP_VERSION 103
 
@@ -64,7 +63,6 @@
 struct sx1301_priv {
struct lora_dev_priv lora;
struct device   *dev;
-   struct spi_device   *spi;
struct gpio_desc *rst_gpio;
struct regmap   *regmap;
 };
-- 
2.7.4



[PATCH v3 lora-next 3/5] net: lora: sx1301: convert to using regmap fields for bit ops

2018-10-12 Thread Ben Whitten
From: Ben Whitten 

We convert to using regmap fields to allow bit access to the registers
where regmap handles the read update write.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 234 +-
 drivers/net/lora/sx1301.h |  46 +
 2 files changed, 110 insertions(+), 170 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 9c85fe7..339f8d9 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -24,27 +24,6 @@
 
 #include "sx1301.h"
 
-#define REG_PAGE_RESET_SOFT_RESET  BIT(7)
-
-#define REG_16_GLOBAL_EN   BIT(3)
-
-#define REG_17_CLK32M_EN   BIT(0)
-
-#define REG_0_105_FORCE_HOST_RADIO_CTRLBIT(1)
-#define REG_0_105_FORCE_HOST_FE_CTRL   BIT(2)
-#define REG_0_105_FORCE_DEC_FILTER_GAINBIT(3)
-
-#define REG_0_MCU_RST_0BIT(0)
-#define REG_0_MCU_RST_1BIT(1)
-#define REG_0_MCU_SELECT_MUX_0 BIT(2)
-#define REG_0_MCU_SELECT_MUX_1 BIT(3)
-
-#define REG_2_43_RADIO_A_ENBIT(0)
-#define REG_2_43_RADIO_B_ENBIT(1)
-#define REG_2_43_RADIO_RST BIT(2)
-
-#define REG_EMERGENCY_FORCE_HOST_CTRL  BIT(0)
-
 static const struct regmap_range_cfg sx1301_regmap_ranges[] = {
{
.name = "Pages",
@@ -74,9 +53,10 @@ static struct regmap_config sx1301_regmap_config = {
.max_register = SX1301_MAX_REGISTER,
 };
 
-static int sx1301_soft_reset(struct sx1301_priv *priv)
+static int sx1301_field_write(struct sx1301_priv *priv,
+   enum sx1301_fields field_id, u8 val)
 {
-   return regmap_write(priv->regmap, SX1301_PAGE, 
REG_PAGE_RESET_SOFT_RESET);
+   return regmap_field_write(priv->regmap_fields[field_id], val);
 }
 
 static int sx1301_agc_ram_read(struct sx1301_priv *priv, u8 addr, unsigned int 
*val)
@@ -120,7 +100,7 @@ static int sx1301_arb_ram_read(struct sx1301_priv *priv, u8 
addr, unsigned int *
 static int sx1301_load_firmware(struct sx1301_priv *priv, int mcu, const 
struct firmware *fw)
 {
u8 *buf;
-   u8 rst, select_mux;
+   enum sx1301_fields rst, select_mux;
unsigned int val;
int ret;
 
@@ -131,29 +111,26 @@ static int sx1301_load_firmware(struct sx1301_priv *priv, 
int mcu, const struct
 
switch (mcu) {
case 0:
-   rst = REG_0_MCU_RST_0;
-   select_mux = REG_0_MCU_SELECT_MUX_0;
+   rst = F_MCU_RST_0;
+   select_mux = F_MCU_SELECT_MUX_0;
break;
case 1:
-   rst = REG_0_MCU_RST_1;
-   select_mux = REG_0_MCU_SELECT_MUX_1;
+   rst = F_MCU_RST_1;
+   select_mux = F_MCU_SELECT_MUX_1;
break;
default:
return -EINVAL;
}
 
-   ret = regmap_read(priv->regmap, SX1301_MCU_CTRL, &val);
+   ret = sx1301_field_write(priv, rst, 1);
if (ret) {
-   dev_err(priv->dev, "MCU read failed\n");
+   dev_err(priv->dev, "MCU reset failed\n");
return ret;
}
 
-   val |= rst;
-   val &= ~select_mux;
-
-   ret = regmap_write(priv->regmap, SX1301_MCU_CTRL, val);
+   ret = sx1301_field_write(priv, select_mux, 0);
if (ret) {
-   dev_err(priv->dev, "MCU reset / select mux write failed\n");
+   dev_err(priv->dev, "MCU RAM select mux failed\n");
return ret;
}
 
@@ -194,17 +171,9 @@ static int sx1301_load_firmware(struct sx1301_priv *priv, 
int mcu, const struct
 
kfree(buf);
 
-   ret = regmap_read(priv->regmap, SX1301_MCU_CTRL, &val);
-   if (ret) {
-   dev_err(priv->dev, "MCU read (1) failed\n");
-   return ret;
-   }
-
-   val |= select_mux;
-
-   ret = regmap_write(priv->regmap, SX1301_MCU_CTRL, val);
+   ret = sx1301_field_write(priv, select_mux, 1);
if (ret) {
-   dev_err(priv->dev, "MCU reset / select mux write (1) failed\n");
+   dev_err(priv->dev, "MCU RAM release mux failed\n");
return ret;
}
 
@@ -230,17 +199,9 @@ static int sx1301_agc_calibrate(struct sx1301_priv *priv)
return ret;
}
 
-   ret = regmap_read(priv->regmap, SX1301_FORCE_CTRL, &val);
-   if (ret) {
-   dev_err(priv->dev, "0|105 read failed\n");
-   return ret;
-   }
-
-   val &= ~REG_0_105_FORCE_HOST_RADIO_CTRL;
-
-   ret = regmap_write(priv->regmap, SX1301_FORCE_CTRL, val);
+   ret = sx1301_field_write(priv, F_FORCE_HOST_RADIO_CTRL, 0);
if (ret) {
-   dev_err(priv->dev, "0|105 write failed\n");
+   dev_err(priv-&g

[PATCH v3 lora-next 4/5] net: lora: sx125x: convert to regmap fields

2018-10-12 Thread Ben Whitten
From: Ben Whitten 

We convert to using regmap fields to allow regmap to take care of read
modify writes and bit shifting for ofset fields.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx125x.c | 59 ---
 1 file changed, 51 insertions(+), 8 deletions(-)

diff --git a/drivers/net/lora/sx125x.c b/drivers/net/lora/sx125x.c
index dc13d1a..36b61b1 100644
--- a/drivers/net/lora/sx125x.c
+++ b/drivers/net/lora/sx125x.c
@@ -25,11 +25,25 @@
 
 #include "sx125x.h"
 
-#define REG_CLK_SELECT_TX_DAC_CLK_SELECT_CLK_INBIT(0)
-#define REG_CLK_SELECT_CLK_OUT BIT(1)
+enum sx125x_fields {
+   F_CLK_OUT,
+   F_TX_DAC_CLK_SEL,
+   F_SX1257_XOSC_GM_STARTUP,
+   F_SX1257_XOSC_DISABLE_CORE,
+};
+
+static const struct reg_field sx125x_regmap_fields[] = {
+   /* CLK_SELECT */
+   [F_CLK_OUT]= REG_FIELD(SX125X_CLK_SELECT, 1, 1),
+   [F_TX_DAC_CLK_SEL] = REG_FIELD(SX125X_CLK_SELECT, 0, 0),
+   /* XOSC */ /* TODO maybe make this dynamic */
+   [F_SX1257_XOSC_GM_STARTUP]  = REG_FIELD(SX1257_XOSC, 0, 3),
+   [F_SX1257_XOSC_DISABLE_CORE]  = REG_FIELD(SX1257_XOSC, 5, 5),
+};
 
 struct sx125x_priv {
struct regmap   *regmap;
+   struct regmap_field 
*regmap_fields[ARRAY_SIZE(sx125x_regmap_fields)];
 };
 
 static struct regmap_config __maybe_unused sx125x_regmap_config = {
@@ -44,11 +58,18 @@ static struct regmap_config __maybe_unused 
sx125x_regmap_config = {
.max_register = SX125X_MAX_REGISTER,
 };
 
+static int sx125x_field_write(struct sx125x_priv *priv,
+   enum sx125x_fields field_id, u8 val)
+{
+   return regmap_field_write(priv->regmap_fields[field_id], val);
+}
+
 static int __maybe_unused sx125x_regmap_probe(struct device *dev, struct 
regmap *regmap, unsigned int radio)
 {
struct sx125x_priv *priv;
unsigned int val;
int ret;
+   int i;
 
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -56,6 +77,18 @@ static int __maybe_unused sx125x_regmap_probe(struct device 
*dev, struct regmap
 
dev_set_drvdata(dev, priv);
priv->regmap = regmap;
+   for (i = 0; i < ARRAY_SIZE(sx125x_regmap_fields); i++) {
+   const struct reg_field *reg_fields = sx125x_regmap_fields;
+
+   priv->regmap_fields[i] = devm_regmap_field_alloc(dev,
+   priv->regmap,
+   reg_fields[i]);
+   if (IS_ERR(priv->regmap_fields[i])) {
+   ret = PTR_ERR(priv->regmap_fields[i]);
+   dev_err(dev, "Cannot allocate regmap field: %d\n", ret);
+   return ret;
+   }
+   }
 
if (true) {
ret = regmap_read(priv->regmap, SX1255_VERSION, &val);
@@ -66,24 +99,34 @@ static int __maybe_unused sx125x_regmap_probe(struct device 
*dev, struct regmap
dev_info(dev, "SX125x version: %02x\n", val);
}
 
-   val = REG_CLK_SELECT_TX_DAC_CLK_SELECT_CLK_IN;
if (radio == 1) { /* HACK */
-   val |= REG_CLK_SELECT_CLK_OUT;
+   ret = sx125x_field_write(priv, F_CLK_OUT, 1);
+   if (ret) {
+   dev_err(dev, "enabling clock output failed\n");
+   return ret;
+   }
+
dev_info(dev, "enabling clock output\n");
}
 
-   ret = regmap_write(priv->regmap, SX125X_CLK_SELECT, val);
+   ret = sx125x_field_write(priv, F_TX_DAC_CLK_SEL, 1);
if (ret) {
-   dev_err(dev, "clk write failed\n");
+   dev_err(dev, "clock select failed\n");
return ret;
}
 
dev_dbg(dev, "clk written\n");
 
if (true) {
-   ret = regmap_write(priv->regmap, SX1257_XOSC, 13 + 2 * 16);
+   ret = sx125x_field_write(priv, F_SX1257_XOSC_DISABLE_CORE, 1);
+   if (ret) {
+   dev_err(dev, "xosc disable failed\n");
+   return ret;
+   }
+
+   ret = sx125x_field_write(priv, F_SX1257_XOSC_GM_STARTUP, 13);
if (ret) {
-   dev_err(dev, "xosc write failed\n");
+   dev_err(dev, "xosc startup adjust failed\n");
return ret;
}
}
-- 
2.7.4



[PATCH v3 lora-next 5/5] net: lora: sx125x sx1301: allow radio to register as a clk provider

2018-10-12 Thread Ben Whitten
From: Ben Whitten 

The 32M is run from the radio, before we just enabled it based on
the radio number but now we can use the clk framework to request the
clk is started when we need it.

The 32M clock produced from the radio is really a gated version of
tcxo which is a fixed clock provided by hardware, and isn't captured
in this patch.

The sx1301 brings the clock up prior to calibration once the radios
have probed themselves.

A sample dts showing the clk link:
sx1301: sx1301@0 {
...
clocks = <&radio1 0>;
clock-names = "clk32m";

radio-spi {
radio0: radio-a@0 {
...
};

radio1: radio-b@1 {
#clock-cells = <0>;
clock-output-names = "clk32m";
};
        };
};

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx125x.c | 112 ++
 drivers/net/lora/sx1301.c |  13 ++
 drivers/net/lora/sx1301.h |   2 +
 3 files changed, 119 insertions(+), 8 deletions(-)

diff --git a/drivers/net/lora/sx125x.c b/drivers/net/lora/sx125x.c
index 36b61b1..b7ca782 100644
--- a/drivers/net/lora/sx125x.c
+++ b/drivers/net/lora/sx125x.c
@@ -9,6 +9,8 @@
  * Copyright (c) 2013 Semtech-Cycleo
  */
 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -42,10 +44,16 @@ static const struct reg_field sx125x_regmap_fields[] = {
 };
 
 struct sx125x_priv {
+   struct clk  *clkout;
+   struct clk_hw   clkout_hw;
+
+   struct device   *dev;
struct regmap   *regmap;
struct regmap_field 
*regmap_fields[ARRAY_SIZE(sx125x_regmap_fields)];
 };
 
+#define to_clkout(_hw) container_of(_hw, struct sx125x_priv, clkout_hw)
+
 static struct regmap_config __maybe_unused sx125x_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -64,6 +72,96 @@ static int sx125x_field_write(struct sx125x_priv *priv,
return regmap_field_write(priv->regmap_fields[field_id], val);
 }
 
+static int sx125x_field_read(struct sx125x_priv *priv,
+   enum sx125x_fields field_id, unsigned int *val)
+{
+   return regmap_field_read(priv->regmap_fields[field_id], val);
+}
+
+static int sx125x_clkout_enable(struct clk_hw *hw)
+{
+   struct sx125x_priv *priv = to_clkout(hw);
+
+   dev_info(priv->dev, "enabling clkout\n");
+   return sx125x_field_write(priv, F_CLK_OUT, 1);
+}
+
+static void sx125x_clkout_disable(struct clk_hw *hw)
+{
+   struct sx125x_priv *priv = to_clkout(hw);
+   int ret;
+
+   dev_info(priv->dev, "disabling clkout\n");
+   ret = sx125x_field_write(priv, F_CLK_OUT, 0);
+   if (ret)
+   dev_err(priv->dev, "error disabling clkout\n");
+}
+
+static int sx125x_clkout_is_enabled(struct clk_hw *hw)
+{
+   struct sx125x_priv *priv = to_clkout(hw);
+   unsigned int enabled;
+   int ret;
+
+   ret = sx125x_field_read(priv, F_CLK_OUT, &enabled);
+   if (ret) {
+   dev_err(priv->dev, "error reading clk enable\n");
+   return 0;
+   }
+   return enabled;
+}
+
+static const struct clk_ops sx125x_clkout_ops = {
+   .enable = sx125x_clkout_enable,
+   .disable = sx125x_clkout_disable,
+   .is_enabled = sx125x_clkout_is_enabled,
+};
+
+static int sx125x_register_clock_provider(struct sx125x_priv *priv)
+{
+   struct device *dev = priv->dev;
+   struct clk_init_data init;
+   const char *parent;
+   int ret;
+
+   /* Disable CLKOUT */
+   ret = sx125x_field_write(priv, F_CLK_OUT, 0);
+   if (ret) {
+   dev_err(dev, "unable to disable clkout\n");
+   return ret;
+   }
+
+   /* Register clock provider if expected in DTB */
+   if (!of_find_property(dev->of_node, "#clock-cells", NULL))
+   return 0;
+
+   dev_info(dev, "registering clkout\n");
+
+   parent = of_clk_get_parent_name(dev->of_node, 0);
+   if (!parent) {
+   dev_err(dev, "Unable to find parent clk\n");
+   return -ENODEV;
+   }
+
+   init.ops = &sx125x_clkout_ops;
+   init.flags = CLK_IS_BASIC;
+   init.parent_names = &parent;
+   init.num_parents = 1;
+   priv->clkout_hw.init = &init;
+
+   of_property_read_string_index(dev->of_node, "clock-output-names", 0,
+   &init.name);
+
+   priv->clkout = devm_clk_register(dev, &priv->clkout_hw);
+   if (IS_ERR(priv->clkout)) {
+   dev_err(dev, "failed to register clkout\n");
+   return PTR_ERR(priv->clkout);
+   }
+   ret = of_clk_add_hw_provid

[PATCH v3 lora-next 0/5] based on 4.19-rc7 migration to regmap and clk framewor

2018-10-12 Thread Ben Whitten
This series is designed to be applied to a lora-next which is based on
v4.19-rc7, not what is currently upstream, there were no additional changes
in this rebase.

In this series we add the write variant to regmap_noinc then use it within
the sx1301 driver to load firmware.

We complete the sx1301 migration to regmap by replacing the SPI burst read
and write with regmap_noinc_read and write.

The various fields of the sx1301 are converted to regmap to pass the read
modify write down to the regmap layer and reduce our code.
The downside is that in the cases of the hand optimised multiple field writes
at once within one register, however if it is desirable these can be replaced
with regmap_update_bits.

Apply the same regmap treatment for the radio device and allow it to register as
a clock provider, this clock is enabled when the lora link is brought up as it
is required prior to calibration of the concentrator.

modprobe lora-sx125x
lora-dev: init
sx1301 spi0.0: SX1301 module probed
sx125x_con spi0.0-a: SX125x version: 21
sx125x_con spi0.0-a: SX125x module probed
sx125x_con spi0.0-b: SX125x version: 21
sx125x_con spi0.0-b: registering clkout
sx125x_con spi0.0-b: SX125x module probed

ip link set lora0 up
sx125x_con spi0.0-b: enabling clkout

Ben Whitten (5):
  regmap: Add regmap_noinc_write API
  net: lora: sx1301: replace burst spi functions with regmap_noinc
  net: lora: sx1301: convert to using regmap fields for bit ops
  net: lora: sx125x: convert to regmap fields
  net: lora: sx125x sx1301: allow radio to register as a clk provider

 drivers/base/regmap/internal.h |   3 +
 drivers/base/regmap/regmap.c   |  77 
 drivers/net/lora/sx125x.c  | 159 +++--
 drivers/net/lora/sx1301.c  | 257 -
 drivers/net/lora/sx1301.h  |  50 +++-
 include/linux/regmap.h |  19 +++
 6 files changed, 369 insertions(+), 196 deletions(-)

-- 
2.7.4



RE: [PATCH v2 lora-next 1/4] net: lora: sx1301: convert burst spi functions to regmap raw

2018-10-10 Thread Ben Whitten
> Subject: Re: [PATCH v2 lora-next 1/4] net: lora: sx1301:
> convert burst spi functions to regmap raw
> 
> Hi Ben and Mark,
> 
> Am 09.10.18 um 14:52 schrieb Ben Whitten:
> > As we have caching disabled we can access the regmap
> using raw for our
> > firmware reading and writing bursts.
> > We also remove the now defunct spi element from the
> structure as this
> > completes the move to regmap.
> >
> > Signed-off-by: Ben Whitten
> 
> > ---
> >  drivers/net/lora/sx1301.c | 26 +--
> ---
> >  drivers/net/lora/sx1301.h |  2 --
> >  2 files changed, 17 insertions(+), 11 deletions(-)
> >
> > diff --git a/drivers/net/lora/sx1301.c
> b/drivers/net/lora/sx1301.c
> > index fd29258..5ab0e2d 100644
> > --- a/drivers/net/lora/sx1301.c
> > +++ b/drivers/net/lora/sx1301.c
> > @@ -76,19 +76,28 @@ static struct regmap_config
> sx1301_regmap_config = {
> >
> >  static int sx1301_read_burst(struct sx1301_priv *priv, u8
> reg, u8 *val, size_t len)
> >  {
> > -   u8 addr = reg & 0x7f;
> > -   return spi_write_then_read(priv->spi, &addr, 1, val,
> len);
> > +   size_t max;
> > +
> > +   max = regmap_get_raw_read_max(priv->regmap);
> > +   if (max && max < len) {
> > +   dev_err(priv->dev, "Burst greater then max
> raw read\n");
> > +   return -EINVAL;
> > +   }
> > +
> > +   return regmap_raw_read(priv->regmap, reg, val,
> len);
> 
> I believe the way we are using it with a single register needs
> regmap_noinc_read() instead, in case we ever want to
> enable caching? ...

Certainly, the noinc was introduced in 4.19 lets rebase lora-next
and use this API instead.

> 
> >  }
> >
> >  static int sx1301_write_burst(struct sx1301_priv *priv, u8
> reg, const u8 *val, size_t len)
> >  {
> > -   u8 addr = reg | BIT(7);
> > -   struct spi_transfer xfr[2] = {
> > -   { .tx_buf = &addr, .len = 1 },
> > -   { .tx_buf = val, .len = len },
> > -   };
> > +   size_t max;
> > +
> > +   max = regmap_get_raw_write_max(priv->regmap);
> > +   if (max && max < len) {
> > +   dev_err(priv->dev, "Burst greater then max
> raw write\n");
> > +   return -EINVAL;
> > +   }
> >
> > -   return spi_sync_transfer(priv->spi, xfr, 2);
> > +   return regmap_raw_write(priv->regmap, reg, val,
> len);
> 
> ... Which would mean we are lacking a noinc API for write
> here!
> 
> @Mark/Stefan, any reason noinc was not implemented
> symmetrically?
> 
> For sx1276 I have local regmap conversion patches, but I
> kept getting
> -EINVAL for bursts and haven't figured out why yet. Need to
> compare to
> your code - I assume you successfully tested this, Ben.

Yes I was able to load and verify/run the firmware using this
patch on my Sentrius RG1xx board.

Thanks,
Ben


[PATCH v2 lora-next 0/4] migration to regmap and clk framework

2018-10-09 Thread Ben Whitten
This series completes the sx1301 migration to regmap by replaceing the SPI
burst read and write with regmap raw reads and writes, this solution is a work
around until there is regmap_noinc_read/write API merged as it sepends on the
fact that we have the regcache turned off.
regmap_noinc_read is available in 4.19 however a write varient isn't.

The various fields of the sx1301 are converted to regmap to pass the read
modify write down to the regmap layer and reduce our code.
The downside is that in the cases of the hand optimised multiple field writes
at once within one register, however if it is desirable these can be replaced
with regmap_update_bits.

Apply the same regmap treatment for the radio device and allow it to register as
a clock provider, this clock is enabled when the lora link is brought up as it
is required prior to calibration of the concentrator.

modprobe lora-sx125x
lora-dev: init
sx1301 spi0.0: SX1301 module probed
sx125x_con spi0.0-a: SX125x version: 21
sx125x_con spi0.0-a: SX125x module probed
sx125x_con spi0.0-b: SX125x version: 21
sx125x_con spi0.0-b: registering clkout
sx125x_con spi0.0-b: SX125x module probed

ip link set lora0 up
sx125x_con spi0.0-b: enabling clkout

Ben Whitten (4):
  net: lora: sx1301: convert burst spi functions to regmap raw
  net: lora: sx1301: convert to using regmap fields for bit ops
  net: lora: sx125x: convert to regmap fields
  net: lora: sx125x sx1301: allow radio to register as a clk provider

 drivers/net/lora/sx125x.c | 159 ++--
 drivers/net/lora/sx1301.c | 265 --
 drivers/net/lora/sx1301.h |  50 -
 3 files changed, 287 insertions(+), 187 deletions(-)

-- 
2.7.4



[PATCH v2 lora-next 2/4] net: lora: sx1301: convert to using regmap fields for bit ops

2018-10-09 Thread Ben Whitten
From: Ben Whitten 

We convert to using regmap fields to allow bit access to the registers
where regmap handles the read update write.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 240 +-
 drivers/net/lora/sx1301.h |  46 +
 2 files changed, 113 insertions(+), 173 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 5ab0e2d..eb89af6 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -24,27 +24,6 @@
 
 #include "sx1301.h"
 
-#define REG_PAGE_RESET_SOFT_RESET  BIT(7)
-
-#define REG_16_GLOBAL_EN   BIT(3)
-
-#define REG_17_CLK32M_EN   BIT(0)
-
-#define REG_0_105_FORCE_HOST_RADIO_CTRLBIT(1)
-#define REG_0_105_FORCE_HOST_FE_CTRL   BIT(2)
-#define REG_0_105_FORCE_DEC_FILTER_GAINBIT(3)
-
-#define REG_0_MCU_RST_0BIT(0)
-#define REG_0_MCU_RST_1BIT(1)
-#define REG_0_MCU_SELECT_MUX_0 BIT(2)
-#define REG_0_MCU_SELECT_MUX_1 BIT(3)
-
-#define REG_2_43_RADIO_A_ENBIT(0)
-#define REG_2_43_RADIO_B_ENBIT(1)
-#define REG_2_43_RADIO_RST BIT(2)
-
-#define REG_EMERGENCY_FORCE_HOST_CTRL  BIT(0)
-
 static const struct regmap_range_cfg sx1301_regmap_ranges[] = {
{
.name = "Pages",
@@ -74,6 +53,12 @@ static struct regmap_config sx1301_regmap_config = {
.max_register = SX1301_MAX_REGISTER,
 };
 
+static int sx1301_field_write(struct sx1301_priv *priv,
+   enum sx1301_fields field_id, u8 val)
+{
+   return regmap_field_write(priv->regmap_fields[field_id], val);
+}
+
 static int sx1301_read_burst(struct sx1301_priv *priv, u8 reg, u8 *val, size_t 
len)
 {
size_t max;
@@ -100,11 +85,6 @@ static int sx1301_write_burst(struct sx1301_priv *priv, u8 
reg, const u8 *val, s
return regmap_raw_write(priv->regmap, reg, val, len);
 }
 
-static int sx1301_soft_reset(struct sx1301_priv *priv)
-{
-   return regmap_write(priv->regmap, SX1301_PAGE, 
REG_PAGE_RESET_SOFT_RESET);
-}
-
 static int sx1301_agc_ram_read(struct sx1301_priv *priv, u8 addr, unsigned int 
*val)
 {
int ret;
@@ -146,7 +126,7 @@ static int sx1301_arb_ram_read(struct sx1301_priv *priv, u8 
addr, unsigned int *
 static int sx1301_load_firmware(struct sx1301_priv *priv, int mcu, const 
struct firmware *fw)
 {
u8 *buf;
-   u8 rst, select_mux;
+   enum sx1301_fields rst, select_mux;
unsigned int val;
int ret;
 
@@ -157,29 +137,26 @@ static int sx1301_load_firmware(struct sx1301_priv *priv, 
int mcu, const struct
 
switch (mcu) {
case 0:
-   rst = REG_0_MCU_RST_0;
-   select_mux = REG_0_MCU_SELECT_MUX_0;
+   rst = F_MCU_RST_0;
+   select_mux = F_MCU_SELECT_MUX_0;
break;
case 1:
-   rst = REG_0_MCU_RST_1;
-   select_mux = REG_0_MCU_SELECT_MUX_1;
+   rst = F_MCU_RST_1;
+   select_mux = F_MCU_SELECT_MUX_1;
break;
default:
return -EINVAL;
}
 
-   ret = regmap_read(priv->regmap, SX1301_MCU_CTRL, &val);
+   ret = sx1301_field_write(priv, rst, 1);
if (ret) {
-   dev_err(priv->dev, "MCU read failed\n");
+   dev_err(priv->dev, "MCU reset failed\n");
return ret;
}
 
-   val |= rst;
-   val &= ~select_mux;
-
-   ret = regmap_write(priv->regmap, SX1301_MCU_CTRL, val);
+   ret = sx1301_field_write(priv, select_mux, 0);
if (ret) {
-   dev_err(priv->dev, "MCU reset / select mux write failed\n");
+   dev_err(priv->dev, "MCU RAM select mux failed\n");
return ret;
}
 
@@ -220,17 +197,9 @@ static int sx1301_load_firmware(struct sx1301_priv *priv, 
int mcu, const struct
 
kfree(buf);
 
-   ret = regmap_read(priv->regmap, SX1301_MCU_CTRL, &val);
+   ret = sx1301_field_write(priv, select_mux, 1);
if (ret) {
-   dev_err(priv->dev, "MCU read (1) failed\n");
-   return ret;
-   }
-
-   val |= select_mux;
-
-   ret = regmap_write(priv->regmap, SX1301_MCU_CTRL, val);
-   if (ret) {
-   dev_err(priv->dev, "MCU reset / select mux write (1) failed\n");
+   dev_err(priv->dev, "MCU RAM release mux failed\n");
return ret;
}
 
@@ -256,17 +225,9 @@ static int sx1301_agc_calibrate(struct sx1301_priv *priv)
return ret;
}
 
-   ret = regmap_read(priv->regmap, SX1301_FORCE_CTRL, &val);
+   ret = sx1301_field_write(priv, F_FORCE_HOST_RADIO_CTRL, 0);
if (ret) {
-   dev_err(priv->dev, "0|105 read failed\

[PATCH v2 lora-next 1/4] net: lora: sx1301: convert burst spi functions to regmap raw

2018-10-09 Thread Ben Whitten
As we have caching disabled we can access the regmap using raw for our
firmware reading and writing bursts.
We also remove the now defunct spi element from the structure as this
completes the move to regmap.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 26 +-
 drivers/net/lora/sx1301.h |  2 --
 2 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index fd29258..5ab0e2d 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -76,19 +76,28 @@ static struct regmap_config sx1301_regmap_config = {
 
 static int sx1301_read_burst(struct sx1301_priv *priv, u8 reg, u8 *val, size_t 
len)
 {
-   u8 addr = reg & 0x7f;
-   return spi_write_then_read(priv->spi, &addr, 1, val, len);
+   size_t max;
+
+   max = regmap_get_raw_read_max(priv->regmap);
+   if (max && max < len) {
+   dev_err(priv->dev, "Burst greater then max raw read\n");
+   return -EINVAL;
+   }
+
+   return regmap_raw_read(priv->regmap, reg, val, len);
 }
 
 static int sx1301_write_burst(struct sx1301_priv *priv, u8 reg, const u8 *val, 
size_t len)
 {
-   u8 addr = reg | BIT(7);
-   struct spi_transfer xfr[2] = {
-   { .tx_buf = &addr, .len = 1 },
-   { .tx_buf = val, .len = len },
-   };
+   size_t max;
+
+   max = regmap_get_raw_write_max(priv->regmap);
+   if (max && max < len) {
+   dev_err(priv->dev, "Burst greater then max raw write\n");
+   return -EINVAL;
+   }
 
-   return spi_sync_transfer(priv->spi, xfr, 2);
+   return regmap_raw_write(priv->regmap, reg, val, len);
 }
 
 static int sx1301_soft_reset(struct sx1301_priv *priv)
@@ -566,7 +575,6 @@ static int sx1301_probe(struct spi_device *spi)
 
spi_set_drvdata(spi, netdev);
priv->dev = &spi->dev;
-   priv->spi = spi;
 
priv->regmap = devm_regmap_init_spi(spi, &sx1301_regmap_config);
if (IS_ERR(priv->regmap)) {
diff --git a/drivers/net/lora/sx1301.h b/drivers/net/lora/sx1301.h
index e939c02..e6400f8 100644
--- a/drivers/net/lora/sx1301.h
+++ b/drivers/net/lora/sx1301.h
@@ -12,7 +12,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #define SX1301_CHIP_VERSION 103
 
@@ -64,7 +63,6 @@
 struct sx1301_priv {
struct lora_dev_priv lora;
struct device   *dev;
-   struct spi_device   *spi;
struct gpio_desc *rst_gpio;
struct regmap   *regmap;
 };
-- 
2.7.4



[PATCH v2 lora-next 3/4] net: lora: sx125x: convert to regmap fields

2018-10-09 Thread Ben Whitten
From: Ben Whitten 

We convert to using regmap fields to allow regmap to take care of read
modify writes and bit shifting for ofset fields.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx125x.c | 59 ---
 1 file changed, 51 insertions(+), 8 deletions(-)

diff --git a/drivers/net/lora/sx125x.c b/drivers/net/lora/sx125x.c
index dc13d1a..36b61b1 100644
--- a/drivers/net/lora/sx125x.c
+++ b/drivers/net/lora/sx125x.c
@@ -25,11 +25,25 @@
 
 #include "sx125x.h"
 
-#define REG_CLK_SELECT_TX_DAC_CLK_SELECT_CLK_INBIT(0)
-#define REG_CLK_SELECT_CLK_OUT BIT(1)
+enum sx125x_fields {
+   F_CLK_OUT,
+   F_TX_DAC_CLK_SEL,
+   F_SX1257_XOSC_GM_STARTUP,
+   F_SX1257_XOSC_DISABLE_CORE,
+};
+
+static const struct reg_field sx125x_regmap_fields[] = {
+   /* CLK_SELECT */
+   [F_CLK_OUT]= REG_FIELD(SX125X_CLK_SELECT, 1, 1),
+   [F_TX_DAC_CLK_SEL] = REG_FIELD(SX125X_CLK_SELECT, 0, 0),
+   /* XOSC */ /* TODO maybe make this dynamic */
+   [F_SX1257_XOSC_GM_STARTUP]  = REG_FIELD(SX1257_XOSC, 0, 3),
+   [F_SX1257_XOSC_DISABLE_CORE]  = REG_FIELD(SX1257_XOSC, 5, 5),
+};
 
 struct sx125x_priv {
struct regmap   *regmap;
+   struct regmap_field 
*regmap_fields[ARRAY_SIZE(sx125x_regmap_fields)];
 };
 
 static struct regmap_config __maybe_unused sx125x_regmap_config = {
@@ -44,11 +58,18 @@ static struct regmap_config __maybe_unused 
sx125x_regmap_config = {
.max_register = SX125X_MAX_REGISTER,
 };
 
+static int sx125x_field_write(struct sx125x_priv *priv,
+   enum sx125x_fields field_id, u8 val)
+{
+   return regmap_field_write(priv->regmap_fields[field_id], val);
+}
+
 static int __maybe_unused sx125x_regmap_probe(struct device *dev, struct 
regmap *regmap, unsigned int radio)
 {
struct sx125x_priv *priv;
unsigned int val;
int ret;
+   int i;
 
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -56,6 +77,18 @@ static int __maybe_unused sx125x_regmap_probe(struct device 
*dev, struct regmap
 
dev_set_drvdata(dev, priv);
priv->regmap = regmap;
+   for (i = 0; i < ARRAY_SIZE(sx125x_regmap_fields); i++) {
+   const struct reg_field *reg_fields = sx125x_regmap_fields;
+
+   priv->regmap_fields[i] = devm_regmap_field_alloc(dev,
+   priv->regmap,
+   reg_fields[i]);
+   if (IS_ERR(priv->regmap_fields[i])) {
+   ret = PTR_ERR(priv->regmap_fields[i]);
+   dev_err(dev, "Cannot allocate regmap field: %d\n", ret);
+   return ret;
+   }
+   }
 
if (true) {
ret = regmap_read(priv->regmap, SX1255_VERSION, &val);
@@ -66,24 +99,34 @@ static int __maybe_unused sx125x_regmap_probe(struct device 
*dev, struct regmap
dev_info(dev, "SX125x version: %02x\n", val);
}
 
-   val = REG_CLK_SELECT_TX_DAC_CLK_SELECT_CLK_IN;
if (radio == 1) { /* HACK */
-   val |= REG_CLK_SELECT_CLK_OUT;
+   ret = sx125x_field_write(priv, F_CLK_OUT, 1);
+   if (ret) {
+   dev_err(dev, "enabling clock output failed\n");
+   return ret;
+   }
+
dev_info(dev, "enabling clock output\n");
}
 
-   ret = regmap_write(priv->regmap, SX125X_CLK_SELECT, val);
+   ret = sx125x_field_write(priv, F_TX_DAC_CLK_SEL, 1);
if (ret) {
-   dev_err(dev, "clk write failed\n");
+   dev_err(dev, "clock select failed\n");
return ret;
}
 
dev_dbg(dev, "clk written\n");
 
if (true) {
-   ret = regmap_write(priv->regmap, SX1257_XOSC, 13 + 2 * 16);
+   ret = sx125x_field_write(priv, F_SX1257_XOSC_DISABLE_CORE, 1);
+   if (ret) {
+   dev_err(dev, "xosc disable failed\n");
+   return ret;
+   }
+
+   ret = sx125x_field_write(priv, F_SX1257_XOSC_GM_STARTUP, 13);
if (ret) {
-   dev_err(dev, "xosc write failed\n");
+   dev_err(dev, "xosc startup adjust failed\n");
return ret;
}
}
-- 
2.7.4



[PATCH v2 lora-next 4/4] net: lora: sx125x sx1301: allow radio to register as a clk provider

2018-10-09 Thread Ben Whitten
From: Ben Whitten 

The 32M is run from the radio, before we just enabled it based on
the radio number but now we can use the clk framework to request the
clk is started when we need it.

The 32M clock produced from the radio is really a gated version of
tcxo which is a fixed clock provided by hardware, and isn't captured
in this patch.

The sx1301 brings the clock up prior to calibration once the radios
have probed themselves.

A sample dts showing the clk link:
sx1301: sx1301@0 {
...
clocks = <&radio1 0>;
clock-names = "clk32m";

radio-spi {
radio0: radio-a@0 {
...
};

radio1: radio-b@1 {
#clock-cells = <0>;
clock-output-names = "clk32m";
};
        };
};

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx125x.c | 112 ++
 drivers/net/lora/sx1301.c |  13 ++
 drivers/net/lora/sx1301.h |   2 +
 3 files changed, 119 insertions(+), 8 deletions(-)

diff --git a/drivers/net/lora/sx125x.c b/drivers/net/lora/sx125x.c
index 36b61b1..b7ca782 100644
--- a/drivers/net/lora/sx125x.c
+++ b/drivers/net/lora/sx125x.c
@@ -9,6 +9,8 @@
  * Copyright (c) 2013 Semtech-Cycleo
  */
 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -42,10 +44,16 @@ static const struct reg_field sx125x_regmap_fields[] = {
 };
 
 struct sx125x_priv {
+   struct clk  *clkout;
+   struct clk_hw   clkout_hw;
+
+   struct device   *dev;
struct regmap   *regmap;
struct regmap_field 
*regmap_fields[ARRAY_SIZE(sx125x_regmap_fields)];
 };
 
+#define to_clkout(_hw) container_of(_hw, struct sx125x_priv, clkout_hw)
+
 static struct regmap_config __maybe_unused sx125x_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -64,6 +72,96 @@ static int sx125x_field_write(struct sx125x_priv *priv,
return regmap_field_write(priv->regmap_fields[field_id], val);
 }
 
+static int sx125x_field_read(struct sx125x_priv *priv,
+   enum sx125x_fields field_id, unsigned int *val)
+{
+   return regmap_field_read(priv->regmap_fields[field_id], val);
+}
+
+static int sx125x_clkout_enable(struct clk_hw *hw)
+{
+   struct sx125x_priv *priv = to_clkout(hw);
+
+   dev_info(priv->dev, "enabling clkout\n");
+   return sx125x_field_write(priv, F_CLK_OUT, 1);
+}
+
+static void sx125x_clkout_disable(struct clk_hw *hw)
+{
+   struct sx125x_priv *priv = to_clkout(hw);
+   int ret;
+
+   dev_info(priv->dev, "disabling clkout\n");
+   ret = sx125x_field_write(priv, F_CLK_OUT, 0);
+   if (ret)
+   dev_err(priv->dev, "error disabling clkout\n");
+}
+
+static int sx125x_clkout_is_enabled(struct clk_hw *hw)
+{
+   struct sx125x_priv *priv = to_clkout(hw);
+   unsigned int enabled;
+   int ret;
+
+   ret = sx125x_field_read(priv, F_CLK_OUT, &enabled);
+   if (ret) {
+   dev_err(priv->dev, "error reading clk enable\n");
+   return 0;
+   }
+   return enabled;
+}
+
+static const struct clk_ops sx125x_clkout_ops = {
+   .enable = sx125x_clkout_enable,
+   .disable = sx125x_clkout_disable,
+   .is_enabled = sx125x_clkout_is_enabled,
+};
+
+static int sx125x_register_clock_provider(struct sx125x_priv *priv)
+{
+   struct device *dev = priv->dev;
+   struct clk_init_data init;
+   const char *parent;
+   int ret;
+
+   /* Disable CLKOUT */
+   ret = sx125x_field_write(priv, F_CLK_OUT, 0);
+   if (ret) {
+   dev_err(dev, "unable to disable clkout\n");
+   return ret;
+   }
+
+   /* Register clock provider if expected in DTB */
+   if (!of_find_property(dev->of_node, "#clock-cells", NULL))
+   return 0;
+
+   dev_info(dev, "registering clkout\n");
+
+   parent = of_clk_get_parent_name(dev->of_node, 0);
+   if (!parent) {
+   dev_err(dev, "Unable to find parent clk\n");
+   return -ENODEV;
+   }
+
+   init.ops = &sx125x_clkout_ops;
+   init.flags = CLK_IS_BASIC;
+   init.parent_names = &parent;
+   init.num_parents = 1;
+   priv->clkout_hw.init = &init;
+
+   of_property_read_string_index(dev->of_node, "clock-output-names", 0,
+   &init.name);
+
+   priv->clkout = devm_clk_register(dev, &priv->clkout_hw);
+   if (IS_ERR(priv->clkout)) {
+   dev_err(dev, "failed to register clkout\n");
+   return PTR_ERR(priv->clkout);
+   }
+   ret = of_clk_add_hw_provid

[PATCH lora-next 3/3] net: lora: sx125x sx1301: allow radio to register as a clk provider

2018-08-22 Thread Ben Whitten
From: Ben Whitten 

The 32M is run from the radio, before we just enabled it based on
the radio number but now we can use the clk framework to request the
clk is started when we need it.

The 32M clock produced from the radio is really a gated version of
tcxo which is a fixed clock provided by hardware, and isn't captured
in this patch.

The sx1301 brings the clock up prior to calibration once the radios
have probed themselves.

A sample dts showing the clk link:
sx1301: sx1301@0 {
...
clocks = <&radio1 0>;
clock-names = "clk32m";

radio-spi {
radio0: radio-a@0 {
...
};

radio1: radio-b@1 {
#clock-cells = <0>;
clock-output-names = "clk32m";
};
        };
};

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx125x.c | 112 ++
 drivers/net/lora/sx1301.c |  13 ++
 drivers/net/lora/sx1301.h |   2 +
 3 files changed, 119 insertions(+), 8 deletions(-)

diff --git a/drivers/net/lora/sx125x.c b/drivers/net/lora/sx125x.c
index b5517e4..5989157 100644
--- a/drivers/net/lora/sx125x.c
+++ b/drivers/net/lora/sx125x.c
@@ -9,6 +9,8 @@
  * Copyright (c) 2013 Semtech-Cycleo
  */
 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -42,10 +44,16 @@ static const struct reg_field sx125x_regmap_fields[] = {
 };
 
 struct sx125x_priv {
+   struct clk  *clkout;
+   struct clk_hw   clkout_hw;
+
+   struct device   *dev;
struct regmap   *regmap;
struct regmap_field 
*regmap_fields[ARRAY_SIZE(sx125x_regmap_fields)];
 };
 
+#define to_clkout(_hw) container_of(_hw, struct sx125x_priv, clkout_hw)
+
 static struct regmap_config __maybe_unused sx125x_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -64,6 +72,96 @@ static int sx125x_field_write(struct sx125x_priv *priv,
return regmap_field_write(priv->regmap_fields[field_id], val);
 }
 
+static int sx125x_field_read(struct sx125x_priv *priv,
+   enum sx125x_fields field_id, unsigned int *val)
+{
+   return regmap_field_read(priv->regmap_fields[field_id], val);
+}
+
+static int sx125x_clkout_enable(struct clk_hw *hw)
+{
+   struct sx125x_priv *priv = to_clkout(hw);
+
+   dev_info(priv->dev, "enabling clkout\n");
+   return sx125x_field_write(priv, F_CLK_OUT, 1);
+}
+
+static void sx125x_clkout_disable(struct clk_hw *hw)
+{
+   struct sx125x_priv *priv = to_clkout(hw);
+   int ret;
+
+   dev_info(priv->dev, "disabling clkout\n");
+   ret = sx125x_field_write(priv, F_CLK_OUT, 0);
+   if (ret)
+   dev_err(priv->dev, "error disabling clkout\n");
+}
+
+static int sx125x_clkout_is_enabled(struct clk_hw *hw)
+{
+   struct sx125x_priv *priv = to_clkout(hw);
+   unsigned int enabled;
+   int ret;
+
+   ret = sx125x_field_read(priv, F_CLK_OUT, &enabled);
+   if (ret) {
+   dev_err(priv->dev, "error reading clk enable\n");
+   return 0;
+   }
+   return enabled;
+}
+
+static const struct clk_ops sx125x_clkout_ops = {
+   .enable = sx125x_clkout_enable,
+   .disable = sx125x_clkout_disable,
+   .is_enabled = sx125x_clkout_is_enabled,
+};
+
+static int sx125x_register_clock_provider(struct sx125x_priv *priv)
+{
+   struct device *dev = priv->dev;
+   struct clk_init_data init;
+   const char *parent;
+   int ret;
+
+   /* Disable CLKOUT */
+   ret = sx125x_field_write(priv, F_CLK_OUT, 0);
+   if (ret) {
+   dev_err(dev, "unable to disable clkout\n");
+   return ret;
+   }
+
+   /* Register clock provider if expected in DTB */
+   if (!of_find_property(dev->of_node, "#clock-cells", NULL))
+   return 0;
+
+   dev_info(dev, "registering clkout\n");
+
+   parent = of_clk_get_parent_name(dev->of_node, 0);
+   if (!parent) {
+   dev_err(dev, "Unable to find parent clk\n");
+   return -ENODEV;
+   }
+
+   init.ops = &sx125x_clkout_ops;
+   init.flags = CLK_IS_BASIC;
+   init.parent_names = &parent;
+   init.num_parents = 1;
+   priv->clkout_hw.init = &init;
+
+   of_property_read_string_index(dev->of_node, "clock-output-names", 0,
+   &init.name);
+
+   priv->clkout = devm_clk_register(dev, &priv->clkout_hw);
+   if (IS_ERR(priv->clkout)) {
+   dev_err(dev, "failed to register clkout\n");
+   return PTR_ERR(priv->clkout);
+   }
+   ret = of_clk_add_hw_provid

[PATCH lora-next 1/3] net: lora: sx1301: convert to using regmap fields for bit ops

2018-08-22 Thread Ben Whitten
From: Ben Whitten 

We convert to using regmap fields to allow bit access to the registers
where regmap handles the read update write.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 240 +-
 drivers/net/lora/sx1301.h |  46 +
 2 files changed, 113 insertions(+), 173 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 971d234..8aad331 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -24,27 +24,6 @@
 
 #include "sx1301.h"
 
-#define REG_PAGE_RESET_SOFT_RESET  BIT(7)
-
-#define REG_16_GLOBAL_EN   BIT(3)
-
-#define REG_17_CLK32M_EN   BIT(0)
-
-#define REG_0_105_FORCE_HOST_RADIO_CTRLBIT(1)
-#define REG_0_105_FORCE_HOST_FE_CTRL   BIT(2)
-#define REG_0_105_FORCE_DEC_FILTER_GAINBIT(3)
-
-#define REG_0_MCU_RST_0BIT(0)
-#define REG_0_MCU_RST_1BIT(1)
-#define REG_0_MCU_SELECT_MUX_0 BIT(2)
-#define REG_0_MCU_SELECT_MUX_1 BIT(3)
-
-#define REG_2_43_RADIO_A_ENBIT(0)
-#define REG_2_43_RADIO_B_ENBIT(1)
-#define REG_2_43_RADIO_RST BIT(2)
-
-#define REG_EMERGENCY_FORCE_HOST_CTRL  BIT(0)
-
 static const struct regmap_range_cfg sx1301_regmap_ranges[] = {
{
.name = "Pages",
@@ -74,6 +53,12 @@ static struct regmap_config sx1301_regmap_config = {
.max_register = SX1301_MAX_REGISTER,
 };
 
+static int sx1301_field_write(struct sx1301_priv *priv,
+   enum sx1301_fields field_id, u8 val)
+{
+   return regmap_field_write(priv->regmap_fields[field_id], val);
+}
+
 static int sx1301_read_burst(struct sx1301_priv *priv, u8 reg, u8 *val, size_t 
len)
 {
u8 addr = reg & 0x7f;
@@ -91,11 +76,6 @@ static int sx1301_write_burst(struct sx1301_priv *priv, u8 
reg, const u8 *val, s
return spi_sync_transfer(priv->spi, xfr, 2);
 }
 
-static int sx1301_soft_reset(struct sx1301_priv *priv)
-{
-   return regmap_write(priv->regmap, SX1301_PAGE, 
REG_PAGE_RESET_SOFT_RESET);
-}
-
 static int sx1301_agc_ram_read(struct sx1301_priv *priv, u8 addr, unsigned int 
*val)
 {
int ret;
@@ -137,7 +117,7 @@ static int sx1301_arb_ram_read(struct sx1301_priv *priv, u8 
addr, unsigned int *
 static int sx1301_load_firmware(struct sx1301_priv *priv, int mcu, const 
struct firmware *fw)
 {
u8 *buf;
-   u8 rst, select_mux;
+   enum sx1301_fields rst, select_mux;
unsigned int val;
int ret;
 
@@ -148,29 +128,26 @@ static int sx1301_load_firmware(struct sx1301_priv *priv, 
int mcu, const struct
 
switch (mcu) {
case 0:
-   rst = REG_0_MCU_RST_0;
-   select_mux = REG_0_MCU_SELECT_MUX_0;
+   rst = F_MCU_RST_0;
+   select_mux = F_MCU_SELECT_MUX_0;
break;
case 1:
-   rst = REG_0_MCU_RST_1;
-   select_mux = REG_0_MCU_SELECT_MUX_1;
+   rst = F_MCU_RST_1;
+   select_mux = F_MCU_SELECT_MUX_1;
break;
default:
return -EINVAL;
}
 
-   ret = regmap_read(priv->regmap, SX1301_MCU_CTRL, &val);
+   ret = sx1301_field_write(priv, rst, 1);
if (ret) {
-   dev_err(priv->dev, "MCU read failed\n");
+   dev_err(priv->dev, "MCU reset failed\n");
return ret;
}
 
-   val |= rst;
-   val &= ~select_mux;
-
-   ret = regmap_write(priv->regmap, SX1301_MCU_CTRL, val);
+   ret = sx1301_field_write(priv, select_mux, 0);
if (ret) {
-   dev_err(priv->dev, "MCU reset / select mux write failed\n");
+   dev_err(priv->dev, "MCU RAM select mux failed\n");
return ret;
}
 
@@ -211,17 +188,9 @@ static int sx1301_load_firmware(struct sx1301_priv *priv, 
int mcu, const struct
 
kfree(buf);
 
-   ret = regmap_read(priv->regmap, SX1301_MCU_CTRL, &val);
+   ret = sx1301_field_write(priv, select_mux, 1);
if (ret) {
-   dev_err(priv->dev, "MCU read (1) failed\n");
-   return ret;
-   }
-
-   val |= select_mux;
-
-   ret = regmap_write(priv->regmap, SX1301_MCU_CTRL, val);
-   if (ret) {
-   dev_err(priv->dev, "MCU reset / select mux write (1) failed\n");
+   dev_err(priv->dev, "MCU RAM release mux failed\n");
return ret;
}
 
@@ -247,17 +216,9 @@ static int sx1301_agc_calibrate(struct sx1301_priv *priv)
return ret;
}
 
-   ret = regmap_read(priv->regmap, SX1301_FORCE_CTRL, &val);
+   ret = sx1301_field_write(priv, F_FORCE_HOST_RADIO_CTRL, 0);
if (ret) {
-   dev_err(priv->dev, "0|105 read fai

[PATCH lora-next 2/3] net: lora: sx125x: convert to regmap fields

2018-08-22 Thread Ben Whitten
From: Ben Whitten 

We convert to using regmap fields to allow regmap to take care of read
modify writes and bit shifting for ofset fields.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx125x.c | 59 ---
 1 file changed, 51 insertions(+), 8 deletions(-)

diff --git a/drivers/net/lora/sx125x.c b/drivers/net/lora/sx125x.c
index 3476a59..b5517e4 100644
--- a/drivers/net/lora/sx125x.c
+++ b/drivers/net/lora/sx125x.c
@@ -25,11 +25,25 @@
 
 #include "sx125x.h"
 
-#define REG_CLK_SELECT_TX_DAC_CLK_SELECT_CLK_INBIT(0)
-#define REG_CLK_SELECT_CLK_OUT BIT(1)
+enum sx125x_fields {
+   F_CLK_OUT,
+   F_TX_DAC_CLK_SEL,
+   F_SX1257_XOSC_GM_STARTUP,
+   F_SX1257_XOSC_DISABLE_CORE,
+};
+
+static const struct reg_field sx125x_regmap_fields[] = {
+   /* CLK_SELECT */
+   [F_CLK_OUT]= REG_FIELD(SX125X_CLK_SELECT, 1, 1),
+   [F_TX_DAC_CLK_SEL] = REG_FIELD(SX125X_CLK_SELECT, 0, 0),
+   /* XOSC */ /* TODO maybe make this dynamic */
+   [F_SX1257_XOSC_GM_STARTUP]  = REG_FIELD(SX1257_XOSC, 0, 3),
+   [F_SX1257_XOSC_DISABLE_CORE]  = REG_FIELD(SX1257_XOSC, 5, 5),
+};
 
 struct sx125x_priv {
struct regmap   *regmap;
+   struct regmap_field 
*regmap_fields[ARRAY_SIZE(sx125x_regmap_fields)];
 };
 
 static struct regmap_config __maybe_unused sx125x_regmap_config = {
@@ -44,11 +58,18 @@ static struct regmap_config __maybe_unused 
sx125x_regmap_config = {
.max_register = SX125X_MAX_REGISTER,
 };
 
+static int sx125x_field_write(struct sx125x_priv *priv,
+   enum sx125x_fields field_id, u8 val)
+{
+   return regmap_field_write(priv->regmap_fields[field_id], val);
+}
+
 static int __maybe_unused sx125x_regmap_probe(struct device *dev, struct 
regmap *regmap, unsigned int radio)
 {
struct sx125x_priv *priv;
unsigned int val;
int ret;
+   int i;
 
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -56,6 +77,18 @@ static int __maybe_unused sx125x_regmap_probe(struct device 
*dev, struct regmap
 
dev_set_drvdata(dev, priv);
priv->regmap = regmap;
+   for (i = 0; i < ARRAY_SIZE(sx125x_regmap_fields); i++) {
+   const struct reg_field *reg_fields = sx125x_regmap_fields;
+
+   priv->regmap_fields[i] = devm_regmap_field_alloc(dev,
+   priv->regmap,
+   reg_fields[i]);
+   if (IS_ERR(priv->regmap_fields[i])) {
+   ret = PTR_ERR(priv->regmap_fields[i]);
+   dev_err(dev, "Cannot allocate regmap field: %d\n", ret);
+   return ret;
+   }
+   }
 
if (false) {
ret = regmap_read(priv->regmap, SX1255_VERSION, &val);
@@ -66,24 +99,34 @@ static int __maybe_unused sx125x_regmap_probe(struct device 
*dev, struct regmap
dev_info(dev, "SX125x version: %02x\n", val);
}
 
-   val = REG_CLK_SELECT_TX_DAC_CLK_SELECT_CLK_IN;
if (radio == 1) { /* HACK */
-   val |= REG_CLK_SELECT_CLK_OUT;
+   ret = sx125x_field_write(priv, F_CLK_OUT, 1);
+   if (ret) {
+   dev_err(dev, "enabling clock output failed\n");
+   return ret;
+   }
+
dev_info(dev, "enabling clock output\n");
}
 
-   ret = regmap_write(priv->regmap, SX125X_CLK_SELECT, val);
+   ret = sx125x_field_write(priv, F_TX_DAC_CLK_SEL, 1);
if (ret) {
-   dev_err(dev, "clk write failed\n");
+   dev_err(dev, "clock select failed\n");
return ret;
}
 
dev_dbg(dev, "clk written\n");
 
if (true) {
-   ret = regmap_write(priv->regmap, SX1257_XOSC, 13 + 2 * 16);
+   ret = sx125x_field_write(priv, F_SX1257_XOSC_DISABLE_CORE, 1);
+   if (ret) {
+   dev_err(dev, "xosc disable failed\n");
+   return ret;
+   }
+
+   ret = sx125x_field_write(priv, F_SX1257_XOSC_GM_STARTUP, 13);
if (ret) {
-   dev_err(dev, "xosc write failed\n");
+   dev_err(dev, "xosc startup adjust failed\n");
return ret;
}
}
-- 
2.7.4



Re: [PATCH lora-next v2 8/8] net: lora: sx1301: convert driver over to regmap reads and writes

2018-08-09 Thread Ben Whitten
On Thu, 9 Aug 2018 at 23:34, Andreas Färber  wrote:
>
> Am 09.08.2018 um 14:33 schrieb Ben Whitten:
> > The reads and writes are replaced with regmap versions and unneeded
> > functions, variable, and defines removed.
> >
> > Signed-off-by: Ben Whitten 
> > ---
> >  drivers/net/lora/sx1301.c | 204 
> > +++---
> >  drivers/net/lora/sx1301.h |  30 +++
> >  2 files changed, 95 insertions(+), 139 deletions(-)
> >
> > diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
> > index 766df06..4db5a43 100644
> > --- a/drivers/net/lora/sx1301.c
> > +++ b/drivers/net/lora/sx1301.c
> [...]
> > @@ -140,50 +115,9 @@ static int sx1301_write(struct sx1301_priv *priv, u8 
> > reg, u8 val)
> >   return sx1301_write_burst(priv, reg, &val, 1);
> >  }
>
> _write and _read are now unused, causing warnings. Dropping.
>
> The _burst versions are still in use for firmware load, and I saw a
> discussion indicating that regmap is lacking the capability to not
> increment the reg for bulk reads at the moment. So we still can't
> cleanly switch to regmap entirely and thereby remain bound to SPI.
>
> [...]
> > @@ -235,8 +169,8 @@ static int sx1301_radio_spi_transfer_one(struct 
> > spi_controller *ctrl,
> >  {
> >   struct spi_sx1301 *ssx = spi_controller_get_devdata(ctrl);
> >   struct sx1301_priv *priv = spi_get_drvdata(ssx->parent);
> > - const u8 *tx_buf = xfr->tx_buf;
> > - u8 *rx_buf = xfr->rx_buf;
> > + const unsigned int *tx_buf = xfr->tx_buf;
> > + unsigned int *rx_buf = xfr->rx_buf;
>
> These are wrong both for Little Endian and even worse for Big Endian.
>
> >   int ret;
> >
> >   if (xfr->len == 0 || xfr->len > 3)
> > @@ -245,13 +179,13 @@ static int sx1301_radio_spi_transfer_one(struct 
> > spi_controller *ctrl,
> >   dev_dbg(&spi->dev, "transferring one (%u)\n", xfr->len);
> >
> >   if (tx_buf) {
> > - ret = sx1301_page_write(priv, ssx->page, ssx->regs + 
> > REG_RADIO_X_ADDR, tx_buf ? tx_buf[0] : 0);
> > + ret = regmap_write(priv->regmap, ssx->regs + 
> > REG_RADIO_X_ADDR, tx_buf ? tx_buf[0] : 0);
> >   if (ret) {
> >   dev_err(&spi->dev, "SPI radio address write 
> > failed\n");
> >   return ret;
> >   }
> >
> > - ret = sx1301_page_write(priv, ssx->page, ssx->regs + 
> > REG_RADIO_X_DATA, (tx_buf && xfr->len >= 2) ? tx_buf[1] : 0);
> > + ret = regmap_write(priv->regmap, ssx->regs + 
> > REG_RADIO_X_DATA, (tx_buf && xfr->len >= 2) ? tx_buf[1] : 0);
> >   if (ret) {
> >   dev_err(&spi->dev, "SPI radio data write failed\n");
> >   return ret;
> > @@ -271,7 +205,7 @@ static int sx1301_radio_spi_transfer_one(struct 
> > spi_controller *ctrl,
> >   }
> >
> >   if (rx_buf) {
> > - ret = sx1301_page_read(priv, ssx->page, ssx->regs + 
> > REG_RADIO_X_DATA_READBACK, &rx_buf[xfr->len - 1]);
> > + ret = regmap_read(priv->regmap, ssx->regs + 
> > REG_RADIO_X_DATA_READBACK, &rx_buf[xfr->len - 1]);
> >   if (ret) {
> >   dev_err(&spi->dev, "SPI radio data read failed\n");
> >   return ret;
>
> Fixing by adding a local variable instead:
>
> @@ -239,6 +163,7 @@ static int sx1301_radio_spi_transfer_one(struct
> spi_controll
> er *ctrl,
> struct sx1301_priv *priv = netdev_priv(netdev);
> const u8 *tx_buf = xfr->tx_buf;
> u8 *rx_buf = xfr->rx_buf;
> +   unsigned int val;
> int ret;
>
> if (xfr->len == 0 || xfr->len > 3)
> [...]
> @@ -273,27 +198,28 @@ static int sx1301_radio_spi_transfer_one(struct
> spi_controller *ctrl,
> }
>
> if (rx_buf) {
> -   ret = sx1301_page_read(priv, ssx->page, ssx->regs +
> REG_RADIO_X_DATA_READBACK, &rx_buf[xfr->len - 1]);
> +   ret = regmap_read(priv->regmap, ssx->regs +
> REG_RADIO_X_DATA_READBACK, &val);
> if (ret) {
> dev_err(&spi->dev, "SPI radio data read failed\n");
> return ret;
> }
> +   rx_buf[xfr->len - 1] = val & 0xff;
>  

Re: [PATCH lora-next v2 3/8] net: lora: sx1301: convert to passing priv data throughout

2018-08-09 Thread Ben Whitten
On Thu, 9 Aug 2018 at 21:43, Andreas Färber  wrote:
>
> Am 09.08.2018 um 14:33 schrieb Ben Whitten:
> > Instead of passing around the spi device we instead pass around our
> > driver data directly.
> >
> > Signed-off-by: Ben Whitten 
> > ---
> >  drivers/net/lora/sx1301.c | 305 
> > +++---
> >  1 file changed, 155 insertions(+), 150 deletions(-)
> >
> > diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
> > index 3c09f5a..7324001 100644
> > --- a/drivers/net/lora/sx1301.c
> > +++ b/drivers/net/lora/sx1301.c
> > @@ -73,24 +73,26 @@ struct spi_sx1301 {
> >  };
> >
> >  struct sx1301_priv {
> > + struct device   *dev;
> > + struct spi_device   *spi;
>
> Obviously this is not a long-term solution, but as interim step it'll
> have to do.
>
> >   struct lora_priv lora;
> >   struct gpio_desc *rst_gpio;
> >   u8 cur_page;
> >   struct spi_controller *radio_a_ctrl, *radio_b_ctrl;
> >  };
> >
> > -static int sx1301_read_burst(struct spi_device *spi, u8 reg, u8 *val, 
> > size_t len)
> > +static int sx1301_read_burst(struct sx1301_priv *priv, u8 reg, u8 *val, 
> > size_t len)
> >  {
> >   u8 addr = reg & 0x7f;
> > - return spi_write_then_read(spi, &addr, 1, val, len);
> > + return spi_write_then_read(priv->spi, &addr, 1, val, len);
> >  }
> >
> > -static int sx1301_read(struct spi_device *spi, u8 reg, u8 *val)
> > +static int sx1301_read(struct sx1301_priv *priv, u8 reg, u8 *val)
> >  {
> > - return sx1301_read_burst(spi, reg, val, 1);
> > + return sx1301_read_burst(priv, reg, val, 1);
> >  }
> >
> > -static int sx1301_write_burst(struct spi_device *spi, u8 reg, const u8 
> > *val, size_t len)
> > +static int sx1301_write_burst(struct sx1301_priv *priv, u8 reg, const u8 
> > *val, size_t len)
> >  {
> >   u8 addr = reg | BIT(7);
> >   struct spi_transfer xfr[2] = {
>
> This hunk did not apply for some reason, I've manually re-applied it.
>
> [...]
> > @@ -654,22 +646,35 @@ static int sx1301_probe(struct spi_device *spi)
> >   priv->rst_gpio = rst;
> >   priv->cur_page = 0xff;
> >
> > - spi_set_drvdata(spi, netdev);
> > + spi_set_drvdata(spi, priv);
>
> This change seems unnecessary and counter-productive for unregistration.
>
> Otherwise applying.

This is actually pretty critical, as it stands with the two spi masters we use
spi_get_drvdata on the parent device of the controller to recover the priv
struct for regmap.

We may have to include the netdev in the priv data, or do a container_of
dance to recover netdev in unregistration.
That said if we wrap things in devm then really our remove function could
be empty, as we have done with the allocation.

Regards,
Ben


RE: [PATCH lora-next 01/10] net: lora: sx1301: add register, bit-fields, and helpers for regmap

2018-08-09 Thread Ben Whitten
> To: Ben Whitten ; Ben
> Whitten 
> Cc: starni...@g.ncu.edu.tw; hasnain.v...@arm.com;
> netdev@vger.kernel.org; Xue Liu
> ; Sebastian Heß
> 
> Subject: Re: [PATCH lora-next 01/10] net: lora: sx1301: add
> register, bit-fields, and helpers for regmap
> 
> + Xue Liu + Sebastian
> 
> Am 08.08.2018 um 17:52 schrieb Ben Whitten:
> >> Subject: Re: [PATCH lora-next 01/10] net: lora: sx1301:
> add
> >> register, bit-fields, and helpers for regmap
> >>
> >> Am 08.08.2018 um 14:32 schrieb Ben Whitten:
> >>>>>  drivers/net/lora/Kconfig  |   1 +
> >>>>>  drivers/net/lora/sx1301.c | 282
> >>>>
> +++-
> >> --
> >>>>>  drivers/net/lora/sx1301.h | 169
> >>>> +++
> >>>>>  3 files changed, 439 insertions(+), 13 deletions(-)
> >>>>>  create mode 100644 drivers/net/lora/sx1301.h
> >>>>
> >>>> My main concern about this patch is its sheer size.
> >> Normally
> >>>> for
> >>>> #defines the rule is not to add unused ones. Here I
> see
> >> for
> >>>> example FSK
> >>>> RSSI fields that we're surely not using yet. Any chance
> to
> >>>> strip this
> >>>> down some more?
> >>>
> >>> Sure, I'll strip the reg_fields down to those only
> required
> >> for
> >>> loading firmware and setting clocks that will be used in
> the
> >>> immediate term. This does clutter the driver a bit
> >>> unnecessarily at the moment.
> >>> I would like to keep the full register dump in the header
> >> file
> >>> though as its self-contained and gives a full picture of
> the
> >> chip.
> >>
> >> Could you do that in more steps though? I'm thinking,
> >> convert only the
> >> registers in use to regmap (that'll make it easier to
> review),
> >> then add
> >> more registers, then convert to regmap fields?
> >
> > I split the conversion function by function but we can
> probably go
> > further if you think it helpful.
> 
> That split feels wrong...
> 
> > Is it more the addition of the replacement register defines
> that you
> > would like to correlate with what's being removed, so you
> can see
> > in one patch that this register has the same page and the
> same
> > address in the new system?
> 
> I am looking for patches that are trivial to review. One
> aspect only.
> So I would much rather get a large patch with a consistent
> series of
> 
> -my_read
> +your_read
> 
> -my_write
> +your_write
> 
> that's quick to review than lots of different refactorings
> mixed into
> one patch, grouped by their file location.
> 
> So I am suggesting that if, for example, you want to pass fw
> to helpers,
> which looks like a great idea, that should be a small patch of
> its own,
> at the very beginning of your series. (git rebase -i is your
> friend.)
> 
> Converting to regmap_read/write I imagine to be a trivial
> search-and-replace type refactoring, leaving my |= and &=
> operations in
> place, to minimize the diff and avoid it mis-detecting the
> patch context.
> Without caching I'd expect regmap to work up to here - if it
> doesn't,
> then we can't apply it to my tree and need to prioritize other
> cleanups
> while we review/debug further.
> 
> Once all registers use regmap successfully, we can optimize
> that code by
> introducing regmap fields. This could be split by location, if
> desired.
> 
> Finally in the end you can introduce more registers and
> fields for
> future use.
> 
> Does that make sense now?

Yep no problem, hopefully my V2 is suitable. I stopped short
of including all registers and doing any regmap_field work
in this series so that we can progress.
I have the sx125x split and conversion to regmap_bus for
the concentrator ready to go in the wings.

> > The problem I face is that these conversions are almost
> blind as
> > when I run on my hardware I either oops with the
> sx1301_read
> > or the cal firmware doesn't verify so I can't finish probe. I
> only
> > get a full sx1301 module probe pass on physical hardware
> when
> > I get right to the end of the series where it's all replaced
> with
> > regmap.
> 
> If patches don't build or don't work then I can't apply them.
> Otherwise
> the 0-day bots will spam us with error reports, as you've
> seen before.

Understood, each patch in v2 has been tested and I was able
to probe and remove modules.

> BTW we'll need this regmap conversion for the picoGW_hal,
> so once we
> have a working SPI regmap driver, we'll need to split out the
> SPI bits,
> similar to sx125x.

I am unfamiliar with the picoGW_hal, do they expose the sx1301
as a device on a regmap_bus then?

Regards,
Ben Whitten


[PATCH lora-next v2 7/8] net: lora: sx1301: add initial registration for regmap

2018-08-09 Thread Ben Whitten
The register and bit-field definitions are taken from the SX1301
datasheet version 2.01 dated June 2014 with the revision information
'First released version'.

The reset state and RW capability of each field is not reflected in this
patch however from the datasheet:
"Bits and registers that are not documented are reserved. They may
include calibration values. It is important not to modify these bits and
registers. If specific bits must be changed in a register with reserved
bits, the register must be read first, specific bits modified while
masking reserved bits and then the register can be written."

Then goes on to state:
"Reserved bits should be written with their reset state, they may be
read different states."

Caching is currently disabled.

The version is read back using regmap_read to verify regmap operation,
in doing so needs to be moved after priv and regmap allocation.

Further registers or fields are added as they are required in conversion.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/Kconfig  |  1 +
 drivers/net/lora/sx1301.c | 46 ++
 drivers/net/lora/sx1301.h | 10 ++
 3 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/drivers/net/lora/Kconfig b/drivers/net/lora/Kconfig
index bb57a01..79d23f2 100644
--- a/drivers/net/lora/Kconfig
+++ b/drivers/net/lora/Kconfig
@@ -49,6 +49,7 @@ config LORA_SX1301
tristate "Semtech SX1301 SPI driver"
default y
depends on SPI
+   select REGMAP_SPI
help
  Semtech SX1301
 
diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 8e81179..766df06 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -20,11 +20,11 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "sx1301.h"
 
 #define REG_PAGE_RESET 0
-#define REG_VERSION1
 #define REG_MCU_PROM_ADDR  9
 #define REG_MCU_PROM_DATA  10
 #define REG_GPIO_SELECT_INPUT  27
@@ -68,6 +68,35 @@
 
 #define REG_EMERGENCY_FORCE_HOST_CTRL  BIT(0)
 
+static const struct regmap_range_cfg sx1301_ranges[] = {
+   {
+   .name = "Pages",
+
+   .range_min = SX1301_VIRT_BASE,
+   .range_max = SX1301_MAX_REGISTER,
+
+   .selector_reg = SX1301_PAGE,
+   .selector_mask = 0x3,
+
+   .window_start = 0,
+   .window_len = SX1301_PAGE_LEN,
+   },
+};
+
+static struct regmap_config sx1301_regmap_config = {
+   .reg_bits = 8,
+   .val_bits = 8,
+
+   .cache_type = REGCACHE_NONE,
+
+   .read_flag_mask = 0,
+   .write_flag_mask = BIT(7),
+
+   .ranges = sx1301_ranges,
+   .num_ranges = ARRAY_SIZE(sx1301_ranges),
+   .max_register = SX1301_MAX_REGISTER,
+};
+
 struct spi_sx1301 {
struct spi_device *parent;
u8 page;
@@ -81,6 +110,7 @@ struct sx1301_priv {
struct gpio_desc *rst_gpio;
u8 cur_page;
struct spi_controller *radio_a_ctrl, *radio_b_ctrl;
+   struct regmap   *regmap;
 };
 
 static int sx1301_read_burst(struct sx1301_priv *priv, u8 reg, u8 *val, size_t 
len)
@@ -614,6 +644,7 @@ static int sx1301_probe(struct spi_device *spi)
struct spi_sx1301 *radio;
struct gpio_desc *rst;
int ret;
+   unsigned int ver;
u8 val;
 
rst = devm_gpiod_get_optional(&spi->dev, "reset", GPIOD_OUT_LOW);
@@ -641,14 +672,21 @@ static int sx1301_probe(struct spi_device *spi)
priv->spi = spi;
SET_NETDEV_DEV(netdev, &spi->dev);
 
-   ret = sx1301_read(priv, REG_VERSION, &val);
+   priv->regmap = devm_regmap_init_spi(spi, &sx1301_regmap_config);
+   if (IS_ERR(priv->regmap)) {
+   ret = PTR_ERR(priv->regmap);
+   dev_err(&spi->dev, "Regmap allocation failed: %d\n", ret);
+   return ret;
+   }
+
+   ret = regmap_read(priv->regmap, SX1301_VER, &ver);
if (ret) {
dev_err(&spi->dev, "version read failed\n");
return ret;
}
 
-   if (val != SX1301_CHIP_VERSION) {
-   dev_err(&spi->dev, "unexpected version: %u\n", val);
+   if (ver != SX1301_CHIP_VERSION) {
+   dev_err(&spi->dev, "unexpected version: %u\n", ver);
return -ENXIO;
}
 
diff --git a/drivers/net/lora/sx1301.h b/drivers/net/lora/sx1301.h
index b37ac56..2fc283f 100644
--- a/drivers/net/lora/sx1301.h
+++ b/drivers/net/lora/sx1301.h
@@ -15,4 +15,14 @@
 #define SX1301_MCU_AGC_FW_VERSION 4
 #define SX1301_MCU_AGC_CAL_FW_VERSION 2
 
+/* Page independent */
+#define SX1301_PAGE 0x00
+#define SX1301_VER  0x01
+
+#define SX1301_VIRT_BASE0x100
+#define SX1301_PAGE_LEN 0x80
+#define SX1301_PAGE_BASE(n) (SX1301_VIRT_BASE + (SX1301_PAGE_LEN * n))
+
+#define SX1301_MAX_REGISTER (SX1301_PAGE_BASE(3) + 0x7F)
+
 #endif
-- 
2.7.4



[PATCH lora-next v2 8/8] net: lora: sx1301: convert driver over to regmap reads and writes

2018-08-09 Thread Ben Whitten
The reads and writes are replaced with regmap versions and unneeded
functions, variable, and defines removed.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 204 +++---
 drivers/net/lora/sx1301.h |  30 +++
 2 files changed, 95 insertions(+), 139 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 766df06..4db5a43 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -24,29 +24,6 @@
 
 #include "sx1301.h"
 
-#define REG_PAGE_RESET 0
-#define REG_MCU_PROM_ADDR  9
-#define REG_MCU_PROM_DATA  10
-#define REG_GPIO_SELECT_INPUT  27
-#define REG_GPIO_SELECT_OUTPUT 28
-#define REG_GPIO_MODE  29
-#define REG_MCU_AGC_STATUS 32
-#define REG_0_RADIO_SELECT 35
-#define REG_0_MCU  106
-#define REG_2_SPI_RADIO_A_DATA 33
-#define REG_2_SPI_RADIO_A_DATA_READBACK34
-#define REG_2_SPI_RADIO_A_ADDR 35
-#define REG_2_SPI_RADIO_A_CS   37
-#define REG_2_SPI_RADIO_B_DATA 38
-#define REG_2_SPI_RADIO_B_DATA_READBACK39
-#define REG_2_SPI_RADIO_B_ADDR 40
-#define REG_2_SPI_RADIO_B_CS   42
-#define REG_2_DBG_ARB_MCU_RAM_DATA 64
-#define REG_2_DBG_AGC_MCU_RAM_DATA 65
-#define REG_2_DBG_ARB_MCU_RAM_ADDR 80
-#define REG_2_DBG_AGC_MCU_RAM_ADDR 81
-#define REG_EMERGENCY_FORCE127
-
 #define REG_PAGE_RESET_SOFT_RESET  BIT(7)
 
 #define REG_16_GLOBAL_EN   BIT(3)
@@ -99,8 +76,7 @@ static struct regmap_config sx1301_regmap_config = {
 
 struct spi_sx1301 {
struct spi_device *parent;
-   u8 page;
-   u8 regs;
+   unsigned int regs;
 };
 
 struct sx1301_priv {
@@ -108,7 +84,6 @@ struct sx1301_priv {
struct spi_device   *spi;
struct lora_priv lora;
struct gpio_desc *rst_gpio;
-   u8 cur_page;
struct spi_controller *radio_a_ctrl, *radio_b_ctrl;
struct regmap   *regmap;
 };
@@ -140,50 +115,9 @@ static int sx1301_write(struct sx1301_priv *priv, u8 reg, 
u8 val)
return sx1301_write_burst(priv, reg, &val, 1);
 }
 
-static int sx1301_page_switch(struct sx1301_priv *priv, u8 page)
-{
-   int ret;
-
-   if (priv->cur_page == page)
-   return 0;
-
-   dev_dbg(priv->dev, "switching to page %u\n", (unsigned)page);
-   ret = sx1301_write(priv, REG_PAGE_RESET, page & 0x3);
-   if (ret) {
-   dev_err(priv->dev, "switching to page %u failed\n", 
(unsigned)page);
-   return ret;
-   }
-
-   priv->cur_page = page;
-
-   return 0;
-}
-
-static int sx1301_page_read(struct sx1301_priv *priv, u8 page, u8 reg, u8 *val)
-{
-   int ret;
-
-   ret = sx1301_page_switch(priv, page);
-   if (ret)
-   return ret;
-
-   return sx1301_read(priv, reg, val);
-}
-
-static int sx1301_page_write(struct sx1301_priv *priv, u8 page, u8 reg, u8 val)
-{
-   int ret;
-
-   ret = sx1301_page_switch(priv, page);
-   if (ret)
-   return ret;
-
-   return sx1301_write(priv, reg, val);
-}
-
 static int sx1301_soft_reset(struct sx1301_priv *priv)
 {
-   return sx1301_write(priv, REG_PAGE_RESET, REG_PAGE_RESET_SOFT_RESET);
+   return regmap_write(priv->regmap, SX1301_PAGE, 
REG_PAGE_RESET_SOFT_RESET);
 }
 
 #define REG_RADIO_X_DATA   0
@@ -195,12 +129,12 @@ static int sx1301_radio_set_cs(struct spi_controller 
*ctrl, bool enable)
 {
struct spi_sx1301 *ssx = spi_controller_get_devdata(ctrl);
struct sx1301_priv *priv = spi_get_drvdata(ssx->parent);
-   u8 cs;
+   unsigned int cs;
int ret;
 
dev_dbg(&ctrl->dev, "setting CS to %s\n", enable ? "1" : "0");
 
-   ret = sx1301_page_read(priv, ssx->page, ssx->regs + REG_RADIO_X_CS, 
&cs);
+   ret = regmap_read(priv->regmap, ssx->regs + REG_RADIO_X_CS, &cs);
if (ret) {
dev_warn(&ctrl->dev, "failed to read CS (%d)\n", ret);
cs = 0;
@@ -211,7 +145,7 @@ static int sx1301_radio_set_cs(struct spi_controller *ctrl, 
bool enable)
else
cs &= ~BIT(0);
 
-   ret = sx1301_page_write(priv, ssx->page, ssx->regs + REG_RADIO_X_CS, 
cs);
+   ret = regmap_write(priv->regmap, ssx->regs + REG_RADIO_X_CS, cs);
if (ret) {
dev_err(&ctrl->dev, "failed to write CS (%d)\n", ret);
return ret;
@@ -235,8 +169,8 @@ static int sx1301_radio_spi_transfer_one(struct 
spi_controller *ctrl,
 {
struct spi_sx1301 *ssx = spi_controller_get_devdata(ctrl);
struct sx1301_priv *priv = spi_get_drvdata(ssx->parent);
-   const u8 *tx_buf = xfr->tx_buf;
-   u8 *rx_buf = xfr->rx_buf;
+   cons

[PATCH lora-next v2 1/8] net: lora: add methods for devm registration

2018-08-09 Thread Ben Whitten
Follow the devm model so that we can avoid lengthy unwind code.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/dev.c   | 28 
 include/linux/lora/dev.h |  1 +
 2 files changed, 29 insertions(+)

diff --git a/drivers/net/lora/dev.c b/drivers/net/lora/dev.c
index 8c01106..e32a870 100644
--- a/drivers/net/lora/dev.c
+++ b/drivers/net/lora/dev.c
@@ -84,6 +84,34 @@ void free_loradev(struct net_device *dev)
 }
 EXPORT_SYMBOL_GPL(free_loradev);
 
+static void devm_free_loradev(struct device *dev, void *res)
+{
+   struct net_device *net = (*(struct net_device **)res);
+   free_loradev(net);
+}
+
+struct net_device *devm_alloc_loradev(struct device *dev, size_t priv)
+{
+   struct net_device **ptr;
+   struct net_device *net;
+
+   net = alloc_loradev(priv);
+   if (!net)
+   return NULL;
+
+   ptr = devres_alloc(devm_free_loradev, sizeof(*ptr), GFP_KERNEL);
+   if (!ptr) {
+   free_loradev(net);
+   return NULL;
+   }
+
+   *ptr = net;
+   devres_add(dev, ptr);
+
+   return net;
+}
+EXPORT_SYMBOL_GPL(devm_alloc_loradev);
+
 static struct rtnl_link_ops lora_link_ops __read_mostly = {
.kind = "lora",
.setup = lora_setup,
diff --git a/include/linux/lora/dev.h b/include/linux/lora/dev.h
index 153f9b2..0f600c9 100644
--- a/include/linux/lora/dev.h
+++ b/include/linux/lora/dev.h
@@ -31,6 +31,7 @@ static inline int lora_strtoeui(const char *str, lora_eui 
*val)
 }
 
 struct net_device *alloc_loradev(int sizeof_priv);
+struct net_device *devm_alloc_loradev(struct device *dev, size_t priv);
 void free_loradev(struct net_device *dev);
 int register_loradev(struct net_device *dev);
 void unregister_loradev(struct net_device *dev);
-- 
2.7.4



[PATCH lora-next v2 6/8] net: lora: sx1301: replace version and size magic numbers with defines

2018-08-09 Thread Ben Whitten
We replace the hard coded numbers for size and version with meaningful
names.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 21 +
 drivers/net/lora/sx1301.h | 18 ++
 2 files changed, 31 insertions(+), 8 deletions(-)
 create mode 100644 drivers/net/lora/sx1301.h

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 916ee40..8e81179 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -21,6 +21,8 @@
 #include 
 #include 
 
+#include "sx1301.h"
+
 #define REG_PAGE_RESET 0
 #define REG_VERSION1
 #define REG_MCU_PROM_ADDR  9
@@ -293,7 +295,7 @@ static int sx1301_load_firmware(struct sx1301_priv *priv, 
int mcu, const struct
u8 val, rst, select_mux;
int ret;
 
-   if (fw->size != 8192) {
+   if (fw->size != SX1301_MCU_FW_BYTE) {
dev_err(priv->dev, "Unexpected firmware size\n");
return -EINVAL;
}
@@ -445,8 +447,9 @@ static int sx1301_agc_calibrate(struct sx1301_priv *priv)
 
dev_info(priv->dev, "AGC calibration firmware version %u\n", 
(unsigned)val);
 
-   if (val != 2) {
-   dev_err(priv->dev, "unexpected firmware version, expecting 
%u\n", 2);
+   if (val != SX1301_MCU_AGC_CAL_FW_VERSION) {
+   dev_err(priv->dev, "unexpected firmware version, expecting 
%u\n",
+   SX1301_MCU_AGC_CAL_FW_VERSION);
return -ENXIO;
}
 
@@ -572,8 +575,9 @@ static int sx1301_load_all_firmware(struct sx1301_priv 
*priv)
 
dev_info(priv->dev, "AGC firmware version %u\n", (unsigned)val);
 
-   if (val != 4) {
-   dev_err(priv->dev, "unexpected firmware version, expecting 
%u\n", 4);
+   if (val != SX1301_MCU_AGC_FW_VERSION) {
+   dev_err(priv->dev, "unexpected firmware version, expecting 
%u\n",
+   SX1301_MCU_AGC_FW_VERSION);
return -ENXIO;
}
 
@@ -585,8 +589,9 @@ static int sx1301_load_all_firmware(struct sx1301_priv 
*priv)
 
dev_info(priv->dev, "ARB firmware version %u\n", (unsigned)val);
 
-   if (val != 1) {
-   dev_err(priv->dev, "unexpected firmware version, expecting 
%u\n", 1);
+   if (val != SX1301_MCU_ARB_FW_VERSION) {
+   dev_err(priv->dev, "unexpected firmware version, expecting 
%u\n",
+   SX1301_MCU_ARB_FW_VERSION);
return -ENXIO;
}
 
@@ -642,7 +647,7 @@ static int sx1301_probe(struct spi_device *spi)
return ret;
}
 
-   if (val != 103) {
+   if (val != SX1301_CHIP_VERSION) {
dev_err(&spi->dev, "unexpected version: %u\n", val);
return -ENXIO;
}
diff --git a/drivers/net/lora/sx1301.h b/drivers/net/lora/sx1301.h
new file mode 100644
index 000..b37ac56
--- /dev/null
+++ b/drivers/net/lora/sx1301.h
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Semtech SX1301 lora concentrator
+ *
+ * Copyright (c) 2018   Ben Whitten
+ */
+
+#ifndef _SX1301_
+#define _SX1301_
+
+#define SX1301_CHIP_VERSION 103
+
+#define SX1301_MCU_FW_BYTE 8192
+#define SX1301_MCU_ARB_FW_VERSION 1
+#define SX1301_MCU_AGC_FW_VERSION 4
+#define SX1301_MCU_AGC_CAL_FW_VERSION 2
+
+#endif
-- 
2.7.4



[PATCH lora-next v2 4/8] net: lora: sx1301: convert load_firmware to take firmware directly

2018-08-09 Thread Ben Whitten
We just pass the pointer to firmware down to the function that loads
it.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 7324001..3f2a532 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -287,13 +287,13 @@ static int sx1301_arb_ram_read(struct sx1301_priv *priv, 
u8 addr, u8 *val)
return 0;
 }
 
-static int sx1301_load_firmware(struct sx1301_priv *priv, int mcu, const u8 
*data, size_t len)
+static int sx1301_load_firmware(struct sx1301_priv *priv, int mcu, const 
struct firmware *fw)
 {
u8 *buf;
u8 val, rst, select_mux;
int ret;
 
-   if (len > 8192)
+   if (fw->size > 8192)
return -EINVAL;
 
switch (mcu) {
@@ -330,7 +330,7 @@ static int sx1301_load_firmware(struct sx1301_priv *priv, 
int mcu, const u8 *dat
return ret;
}
 
-   ret = sx1301_write_burst(priv, REG_MCU_PROM_DATA, data, len);
+   ret = sx1301_write_burst(priv, REG_MCU_PROM_DATA, fw->data, fw->size);
if (ret) {
dev_err(priv->dev, "MCU prom data write failed\n");
return ret;
@@ -342,18 +342,18 @@ static int sx1301_load_firmware(struct sx1301_priv *priv, 
int mcu, const u8 *dat
return ret;
}
 
-   buf = kzalloc(len, GFP_KERNEL);
+   buf = kzalloc(fw->size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
 
-   ret = sx1301_read_burst(priv, REG_MCU_PROM_DATA, buf, len);
+   ret = sx1301_read_burst(priv, REG_MCU_PROM_DATA, buf, fw->size);
if (ret) {
dev_err(priv->dev, "MCU prom data read failed\n");
kfree(buf);
return ret;
}
 
-   if (memcmp(data, buf, len)) {
+   if (memcmp(fw->data, buf, fw->size)) {
dev_err(priv->dev, "MCU prom data read does not match data 
written\n");
kfree(buf);
return -ENXIO;
@@ -395,7 +395,7 @@ static int sx1301_agc_calibrate(struct sx1301_priv *priv)
return -EINVAL;
}
 
-   ret = sx1301_load_firmware(priv, 1, fw->data, fw->size);
+   ret = sx1301_load_firmware(priv, 1, fw);
release_firmware(fw);
if (ret) {
dev_err(priv->dev, "agc cal firmware load failed\n");
@@ -523,7 +523,7 @@ static int sx1301_load_all_firmware(struct sx1301_priv 
*priv)
return -EINVAL;
}
 
-   ret = sx1301_load_firmware(priv, 0, fw->data, fw->size);
+   ret = sx1301_load_firmware(priv, 0, fw);
release_firmware(fw);
if (ret)
return ret;
@@ -540,7 +540,7 @@ static int sx1301_load_all_firmware(struct sx1301_priv 
*priv)
return -EINVAL;
}
 
-   ret = sx1301_load_firmware(priv, 1, fw->data, fw->size);
+   ret = sx1301_load_firmware(priv, 1, fw);
release_firmware(fw);
if (ret)
return ret;
-- 
2.7.4



[PATCH lora-next v2 5/8] net: lora: sx1301: remove duplicate firmware size checks

2018-08-09 Thread Ben Whitten
No need to check the size of the firmware multiple times, just do it once
in the function responsible for loading as the firmwares are the same size.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 21 +++--
 1 file changed, 3 insertions(+), 18 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 3f2a532..916ee40 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -293,8 +293,10 @@ static int sx1301_load_firmware(struct sx1301_priv *priv, 
int mcu, const struct
u8 val, rst, select_mux;
int ret;
 
-   if (fw->size > 8192)
+   if (fw->size != 8192) {
+   dev_err(priv->dev, "Unexpected firmware size\n");
return -EINVAL;
+   }
 
switch (mcu) {
case 0:
@@ -390,11 +392,6 @@ static int sx1301_agc_calibrate(struct sx1301_priv *priv)
return ret;
}
 
-   if (fw->size != 8192) {
-   dev_err(priv->dev, "unexpected agc cal firmware size\n");
-   return -EINVAL;
-   }
-
ret = sx1301_load_firmware(priv, 1, fw);
release_firmware(fw);
if (ret) {
@@ -517,12 +514,6 @@ static int sx1301_load_all_firmware(struct sx1301_priv 
*priv)
return ret;
}
 
-   if (fw->size != 8192) {
-   dev_err(priv->dev, "unexpected arb firmware size\n");
-   release_firmware(fw);
-   return -EINVAL;
-   }
-
ret = sx1301_load_firmware(priv, 0, fw);
release_firmware(fw);
if (ret)
@@ -534,12 +525,6 @@ static int sx1301_load_all_firmware(struct sx1301_priv 
*priv)
return ret;
}
 
-   if (fw->size != 8192) {
-   dev_err(priv->dev, "unexpected agc firmware size\n");
-   release_firmware(fw);
-   return -EINVAL;
-   }
-
ret = sx1301_load_firmware(priv, 1, fw);
release_firmware(fw);
if (ret)
-- 
2.7.4



[PATCH lora-next v2 2/8] net: lora: sx1301: convert to devm registration of netdev

2018-08-09 Thread Ben Whitten
We allow the devres framework handle the clean removal of resources on
teardown of the device, in this case the SPI device, saving lengthy
unwind code and improving clarity.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 87 +++
 1 file changed, 27 insertions(+), 60 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 5342b61..3c09f5a 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -3,6 +3,7 @@
  * Semtech SX1301 LoRa concentrator
  *
  * Copyright (c) 2018 Andreas Färber
+ * Copyright (c) 2018 Ben Whitten
  *
  * Based on SX1301 HAL code:
  * Copyright (c) 2013 Semtech-Cycleo
@@ -637,20 +638,17 @@ static int sx1301_probe(struct spi_device *spi)
ret = sx1301_read(spi, REG_VERSION, &val);
if (ret) {
dev_err(&spi->dev, "version read failed\n");
-   goto err_version;
+   return ret;
}
 
if (val != 103) {
dev_err(&spi->dev, "unexpected version: %u\n", val);
-   ret = -ENXIO;
-   goto err_version;
+   return -ENXIO;
}
 
-   netdev = alloc_loradev(sizeof(*priv));
-   if (!netdev) {
-   ret = -ENOMEM;
-   goto err_alloc_loradev;
-   }
+   netdev = devm_alloc_loradev(&spi->dev, sizeof(*priv));
+   if (!netdev)
+   return -ENOMEM;
 
priv = netdev_priv(netdev);
priv->rst_gpio = rst;
@@ -662,19 +660,19 @@ static int sx1301_probe(struct spi_device *spi)
ret = sx1301_write(spi, REG_PAGE_RESET, 0);
if (ret) {
dev_err(&spi->dev, "page/reset write failed\n");
-   goto err_init_page;
+   return ret;
}
 
ret = sx1301_soft_reset(spi);
if (ret) {
dev_err(&spi->dev, "soft reset failed\n");
-   goto err_soft_reset;
+   return ret;
}
 
ret = sx1301_read(spi, 16, &val);
if (ret) {
dev_err(&spi->dev, "16 read failed\n");
-   goto err_read_global_en_0;
+   return ret;
}
 
val &= ~REG_16_GLOBAL_EN;
@@ -682,13 +680,13 @@ static int sx1301_probe(struct spi_device *spi)
ret = sx1301_write(spi, 16, val);
if (ret) {
dev_err(&spi->dev, "16 write failed\n");
-   goto err_write_global_en_0;
+   return ret;
}
 
ret = sx1301_read(spi, 17, &val);
if (ret) {
dev_err(&spi->dev, "17 read failed\n");
-   goto err_read_clk32m_0;
+   return ret;
}
 
val &= ~REG_17_CLK32M_EN;
@@ -696,7 +694,7 @@ static int sx1301_probe(struct spi_device *spi)
ret = sx1301_write(spi, 17, val);
if (ret) {
dev_err(&spi->dev, "17 write failed\n");
-   goto err_write_clk32m_0;
+   return ret;
}
 
ret = sx1301_page_read(spi, 2, 43, &val);
@@ -749,8 +747,7 @@ static int sx1301_probe(struct spi_device *spi)
 
priv->radio_a_ctrl = spi_alloc_master(&spi->dev, sizeof(*radio));
if (!priv->radio_a_ctrl) {
-   ret = -ENOMEM;
-   goto err_radio_a_alloc;
+   return -ENOMEM;
}
 
sx1301_radio_setup(priv->radio_a_ctrl);
@@ -765,15 +762,14 @@ static int sx1301_probe(struct spi_device *spi)
if (ret) {
dev_err(&spi->dev, "radio A SPI register failed\n");
spi_controller_put(priv->radio_a_ctrl);
-   goto err_radio_a_register;
+   return ret;
}
 
/* radio B */
 
priv->radio_b_ctrl = spi_alloc_master(&spi->dev, sizeof(*radio));
if (!priv->radio_b_ctrl) {
-   ret = -ENOMEM;
-   goto err_radio_b_alloc;
+   return -ENOMEM;
}
 
sx1301_radio_setup(priv->radio_b_ctrl);
@@ -788,7 +784,7 @@ static int sx1301_probe(struct spi_device *spi)
if (ret) {
dev_err(&spi->dev, "radio B SPI register failed\n");
spi_controller_put(priv->radio_b_ctrl);
-   goto err_radio_b_register;
+   return ret;
}
 
/* GPIO */
@@ -796,7 +792,7 @@ static int sx1301_probe(struct spi_device *spi)
ret = sx1301_read(spi, REG_GPIO_MODE, &val);
if (ret) {
dev_err(&spi->dev, "GPIO mode read failed\n");
-   goto err_read_gpio_mode;
+   return ret;
}
 
val |= GENMASK(4, 0);
@@ -804,13 +800,13 @@ static int sx1301_probe(struct spi_device *spi)
ret = sx1301_write(spi, REG_GPIO_MODE, val);
  

[PATCH lora-next v2 3/8] net: lora: sx1301: convert to passing priv data throughout

2018-08-09 Thread Ben Whitten
Instead of passing around the spi device we instead pass around our
driver data directly.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 305 +++---
 1 file changed, 155 insertions(+), 150 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 3c09f5a..7324001 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -73,24 +73,26 @@ struct spi_sx1301 {
 };
 
 struct sx1301_priv {
+   struct device   *dev;
+   struct spi_device   *spi;
struct lora_priv lora;
struct gpio_desc *rst_gpio;
u8 cur_page;
struct spi_controller *radio_a_ctrl, *radio_b_ctrl;
 };
 
-static int sx1301_read_burst(struct spi_device *spi, u8 reg, u8 *val, size_t 
len)
+static int sx1301_read_burst(struct sx1301_priv *priv, u8 reg, u8 *val, size_t 
len)
 {
u8 addr = reg & 0x7f;
-   return spi_write_then_read(spi, &addr, 1, val, len);
+   return spi_write_then_read(priv->spi, &addr, 1, val, len);
 }
 
-static int sx1301_read(struct spi_device *spi, u8 reg, u8 *val)
+static int sx1301_read(struct sx1301_priv *priv, u8 reg, u8 *val)
 {
-   return sx1301_read_burst(spi, reg, val, 1);
+   return sx1301_read_burst(priv, reg, val, 1);
 }
 
-static int sx1301_write_burst(struct spi_device *spi, u8 reg, const u8 *val, 
size_t len)
+static int sx1301_write_burst(struct sx1301_priv *priv, u8 reg, const u8 *val, 
size_t len)
 {
u8 addr = reg | BIT(7);
struct spi_transfer xfr[2] = {
@@ -98,26 +100,25 @@ static int sx1301_write_burst(struct spi_device *spi, u8 
reg, const u8 *val, siz
{ .tx_buf = val, .len = len },
};
 
-   return spi_sync_transfer(spi, xfr, 2);
+   return spi_sync_transfer(priv->spi, xfr, 2);
 }
 
-static int sx1301_write(struct spi_device *spi, u8 reg, u8 val)
+static int sx1301_write(struct sx1301_priv *priv, u8 reg, u8 val)
 {
-   return sx1301_write_burst(spi, reg, &val, 1);
+   return sx1301_write_burst(priv, reg, &val, 1);
 }
 
-static int sx1301_page_switch(struct spi_device *spi, u8 page)
+static int sx1301_page_switch(struct sx1301_priv *priv, u8 page)
 {
-   struct sx1301_priv *priv = spi_get_drvdata(spi);
int ret;
 
if (priv->cur_page == page)
return 0;
 
-   dev_dbg(&spi->dev, "switching to page %u\n", (unsigned)page);
-   ret = sx1301_write(spi, REG_PAGE_RESET, page & 0x3);
+   dev_dbg(priv->dev, "switching to page %u\n", (unsigned)page);
+   ret = sx1301_write(priv, REG_PAGE_RESET, page & 0x3);
if (ret) {
-   dev_err(&spi->dev, "switching to page %u failed\n", 
(unsigned)page);
+   dev_err(priv->dev, "switching to page %u failed\n", 
(unsigned)page);
return ret;
}
 
@@ -126,31 +127,31 @@ static int sx1301_page_switch(struct spi_device *spi, u8 
page)
return 0;
 }
 
-static int sx1301_page_read(struct spi_device *spi, u8 page, u8 reg, u8 *val)
+static int sx1301_page_read(struct sx1301_priv *priv, u8 page, u8 reg, u8 *val)
 {
int ret;
 
-   ret = sx1301_page_switch(spi, page);
+   ret = sx1301_page_switch(priv, page);
if (ret)
return ret;
 
-   return sx1301_read(spi, reg, val);
+   return sx1301_read(priv, reg, val);
 }
 
-static int sx1301_page_write(struct spi_device *spi, u8 page, u8 reg, u8 val)
+static int sx1301_page_write(struct sx1301_priv *priv, u8 page, u8 reg, u8 val)
 {
int ret;
 
-   ret = sx1301_page_switch(spi, page);
+   ret = sx1301_page_switch(priv, page);
if (ret)
return ret;
 
-   return sx1301_write(spi, reg, val);
+   return sx1301_write(priv, reg, val);
 }
 
-static int sx1301_soft_reset(struct spi_device *spi)
+static int sx1301_soft_reset(struct sx1301_priv *priv)
 {
-   return sx1301_write(spi, REG_PAGE_RESET, REG_PAGE_RESET_SOFT_RESET);
+   return sx1301_write(priv, REG_PAGE_RESET, REG_PAGE_RESET_SOFT_RESET);
 }
 
 #define REG_RADIO_X_DATA   0
@@ -161,12 +162,13 @@ static int sx1301_soft_reset(struct spi_device *spi)
 static int sx1301_radio_set_cs(struct spi_controller *ctrl, bool enable)
 {
struct spi_sx1301 *ssx = spi_controller_get_devdata(ctrl);
+   struct sx1301_priv *priv = spi_get_drvdata(ssx->parent);
u8 cs;
int ret;
 
dev_dbg(&ctrl->dev, "setting CS to %s\n", enable ? "1" : "0");
 
-   ret = sx1301_page_read(ssx->parent, ssx->page, ssx->regs + 
REG_RADIO_X_CS, &cs);
+   ret = sx1301_page_read(priv, ssx->page, ssx->regs + REG_RADIO_X_CS, 
&cs);
if (ret) {
dev_warn(&ctrl->dev, "failed to read CS (%d)\n", ret);
cs = 0;
@@ -177,7 +179,7 @@ static int sx1301_radio_set_cs

RE: [PATCH lora-next 01/10] net: lora: sx1301: add register, bit-fields, and helpers for regmap

2018-08-08 Thread Ben Whitten
> Subject: Re: [PATCH lora-next 01/10] net: lora: sx1301: add
> register, bit-fields, and helpers for regmap
> 
> Am 08.08.2018 um 14:32 schrieb Ben Whitten:
> >>>  drivers/net/lora/Kconfig  |   1 +
> >>>  drivers/net/lora/sx1301.c | 282
> >> +++-
> --
> >>>  drivers/net/lora/sx1301.h | 169
> >> +++
> >>>  3 files changed, 439 insertions(+), 13 deletions(-)
> >>>  create mode 100644 drivers/net/lora/sx1301.h
> >>
> >> My main concern about this patch is its sheer size.
> Normally
> >> for
> >> #defines the rule is not to add unused ones. Here I see
> for
> >> example FSK
> >> RSSI fields that we're surely not using yet. Any chance to
> >> strip this
> >> down some more?
> >
> > Sure, I'll strip the reg_fields down to those only required
> for
> > loading firmware and setting clocks that will be used in the
> > immediate term. This does clutter the driver a bit
> > unnecessarily at the moment.
> > I would like to keep the full register dump in the header
> file
> > though as its self-contained and gives a full picture of the
> chip.
> 
> Could you do that in more steps though? I'm thinking,
> convert only the
> registers in use to regmap (that'll make it easier to review),
> then add
> more registers, then convert to regmap fields?

I split the conversion function by function but we can probably go
further if you think it helpful.
Is it more the addition of the replacement register defines that you
would like to correlate with what's being removed, so you can see
in one patch that this register has the same page and the same
address in the new system?

The problem I face is that these conversions are almost blind as
when I run on my hardware I either oops with the sx1301_read
or the cal firmware doesn't verify so I can't finish probe. I only
get a full sx1301 module probe pass on physical hardware when
I get right to the end of the series where it's all replaced with
regmap.

Regards,
Ben Whitten


RE: [PATCH lora-next 01/10] net: lora: sx1301: add register, bit-fields, and helpers for regmap

2018-08-08 Thread Ben Whitten
> Subject: Re: [PATCH lora-next 01/10] net: lora: sx1301: add
> register, bit-fields, and helpers for regmap
> 
> Am 07.08.2018 um 19:32 schrieb Ben Whitten:
> > From: Ben Whitten 
> >
> > The register and bit-field definitions are taken from the
> SX1301
> > datasheet version 2.01 dated June 2014 with the revision
> information
> > 'First released version'.
> >
> > The reset state and RW capability of each field is not
> reflected in this
> > patch however from the datasheet:
> > "Bits and registers that are not documented are reserved.
> They may
> > include calibration values. It is important not to modify
> these bits and
> > registers. If specific bits must be changed in a register with
> reserved
> > bits, the register must be read first, specific bits modified
> while
> > masking reserved bits and then the register can be
> written."
> >
> > Then goes on to state:
> > "Reserved bits should be written with their reset state,
> they may be
> > read different states."
> >
> > Caching is currently disabled.
> >
> > The version is read back using regmap_read to verify
> regmap operation,
> > in doing so needs to be moved after priv and regmap
> allocation.
> >
> > Signed-off-by: Ben Whitten
> 
> > ---
> >  drivers/net/lora/Kconfig  |   1 +
> >  drivers/net/lora/sx1301.c | 282
> +++---
> >  drivers/net/lora/sx1301.h | 169
> +++
> >  3 files changed, 439 insertions(+), 13 deletions(-)
> >  create mode 100644 drivers/net/lora/sx1301.h
> 
> My main concern about this patch is its sheer size. Normally
> for
> #defines the rule is not to add unused ones. Here I see for
> example FSK
> RSSI fields that we're surely not using yet. Any chance to
> strip this
> down some more?

Sure, I'll strip the reg_fields down to those only required for
loading firmware and setting clocks that will be used in the
immediate term. This does clutter the driver a bit
unnecessarily at the moment.
I would like to keep the full register dump in the header file
though as its self-contained and gives a full picture of the chip.

Thanks,
Ben


RE: [PATCH lora-next 01/10] net: lora: sx1301: add register, bit-fields, and helpers for regmap

2018-08-08 Thread Ben Whitten
> Subject: Re: [PATCH lora-next 01/10] net: lora: sx1301: add
> register, bit-fields, and helpers for regmap
> 
> Am 07.08.2018 um 19:32 schrieb Ben Whitten:
> > diff --git a/drivers/net/lora/sx1301.c
> b/drivers/net/lora/sx1301.c
> > index 5342b61..49958f0 100644
> > --- a/drivers/net/lora/sx1301.c
> > +++ b/drivers/net/lora/sx1301.c
> [...]
> > @@ -76,8 +287,29 @@ struct sx1301_priv {
> > struct gpio_desc *rst_gpio;
> > u8 cur_page;
> > struct spi_controller *radio_a_ctrl, *radio_b_ctrl;
> > +   struct regmap   *regmap;
> > +   struct regmap_field
>   *regmap_fields[ARRAY_SIZE(sx1301_reg_fields)];
> >  };
> >
> > +static int sx1301_field_read(struct sx1301_priv *priv,
> > +   enum sx1301_fields field_id)
> > +{
> > +   int ret;
> > +   int val;
> > +
> > +   ret = regmap_field_read(priv-
> >regmap_fields[field_id], &val);
> > +   if (ret)
> > +   return ret;
> > +
> > +   return val;
> 
> This strikes me as a bad idea. Please keep returning the
> value by
> pointer, so that we can clearly distinguish from error values.

Good point, will change it.

> > +}
> > +
> > +static int sx1301_field_write(struct sx1301_priv *priv,
> > +   enum sx1301_fields field_id, u8 val)
> > +{
> > +   return regmap_field_write(priv-
> >regmap_fields[field_id], val);
> > +}
> > +
> >  static int sx1301_read_burst(struct spi_device *spi, u8
> reg, u8 *val, size_t len)
> >  {
> > u8 addr = reg & 0x7f;
> [snip]
> 
> It looks to me as if both of those static functions are unused
> in this
> patch? Please keep things bisectable.

Sure, it was a prep patch bit I can include these functions in the
next one along where they are actually used.

Thanks,
Ben


Re: [RFC] spi: add spi multiplexing functions for dt

2018-08-07 Thread Ben Whitten
On Tue, 7 Aug 2018 at 22:17, Andreas Färber  wrote:
>
> Hi Ben,
>
> Am 07.08.2018 um 19:32 schrieb Ben Whitten:
> > Like I2C busses SPI devices can also sit behind multiplexers.
> > This patch adds is based off the I2C implementation and allows
> > description in the devicetree.
> >
> > Signed-off-by: Ben Whitten 
> > ---
> >  drivers/spi/Kconfig |  10 +++
> >  drivers/spi/Makefile|   3 +
> >  drivers/spi/spi-mux.c   | 181 
> > 
> >  include/linux/spi-mux.h |  55 +++
> >  4 files changed, 249 insertions(+)
> >  create mode 100644 drivers/spi/spi-mux.c
> >  create mode 100644 include/linux/spi-mux.h
>
> Did this get sent by mistake? It needs to go to linux-spi list and
> maintainers.

It certainly did, didn't spot it in my outgoing patches directory.
Please disregard, sorry for the noise.

> Tip: git config sendemail.cccmd "scripts/get_maintainer.pl
> --nogit-fallback --norolestats"

Thanks for the tip

Cheers,
Ben


[PATCH lora-next 01/10] net: lora: sx1301: add register, bit-fields, and helpers for regmap

2018-08-07 Thread Ben Whitten
From: Ben Whitten 

The register and bit-field definitions are taken from the SX1301
datasheet version 2.01 dated June 2014 with the revision information
'First released version'.

The reset state and RW capability of each field is not reflected in this
patch however from the datasheet:
"Bits and registers that are not documented are reserved. They may
include calibration values. It is important not to modify these bits and
registers. If specific bits must be changed in a register with reserved
bits, the register must be read first, specific bits modified while
masking reserved bits and then the register can be written."

Then goes on to state:
"Reserved bits should be written with their reset state, they may be
read different states."

Caching is currently disabled.

The version is read back using regmap_read to verify regmap operation,
in doing so needs to be moved after priv and regmap allocation.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/Kconfig  |   1 +
 drivers/net/lora/sx1301.c | 282 +++---
 drivers/net/lora/sx1301.h | 169 +++
 3 files changed, 439 insertions(+), 13 deletions(-)
 create mode 100644 drivers/net/lora/sx1301.h

diff --git a/drivers/net/lora/Kconfig b/drivers/net/lora/Kconfig
index bb57a01..79d23f2 100644
--- a/drivers/net/lora/Kconfig
+++ b/drivers/net/lora/Kconfig
@@ -49,6 +49,7 @@ config LORA_SX1301
tristate "Semtech SX1301 SPI driver"
default y
depends on SPI
+   select REGMAP_SPI
help
  Semtech SX1301
 
diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 5342b61..49958f0 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -3,6 +3,7 @@
  * Semtech SX1301 LoRa concentrator
  *
  * Copyright (c) 2018 Andreas Färber
+ * Copyright (c) 2018 Ben Whitten
  *
  * Based on SX1301 HAL code:
  * Copyright (c) 2013 Semtech-Cycleo
@@ -19,6 +20,9 @@
 #include 
 #include 
 #include 
+#include 
+
+#include "sx1301.h"
 
 #define REG_PAGE_RESET 0
 #define REG_VERSION1
@@ -65,6 +69,213 @@
 
 #define REG_EMERGENCY_FORCE_HOST_CTRL  BIT(0)
 
+enum sx1301_fields {
+   F_SOFT_RESET,
+   F_START_BIST0,
+   F_START_BIST1,
+   F_BIST0_FINISHED,
+   F_BIST1_FINISHED,
+   F_GLOBAL_EN,
+   F_CLK32M_EN,
+   F_RADIO_A_EN,
+   F_RADIO_B_EN,
+   F_RADIO_RST,
+
+   F_RX_INVERT_IQ,
+   F_MODEM_INVERT_IQ,
+   F_MBWSSF_MODEM_INVERT_IQ,
+   F_RX_EDGE_SELECT,
+   F_MISC_RADIO_EN,
+   F_FSK_MODEM_INVERT_IQ,
+
+   F_RSSI_BB_FILTER_ALPHA,
+   F_RSSI_DEC_FILTER_ALPHA,
+   F_RSSI_CHANN_FILTER_ALPHA,
+
+   F_DEC_GAIN_OFFSET,
+   F_CHAN_GAIN_OFFSET,
+
+   F_LLR_SCALE,
+   F_SNR_AVG_CST,
+
+   F_CORR_NUM_SAME_PEAK,
+   F_CORR_MAC_GAIN,
+
+   F_FSK_CH_BW_EXPO,
+   F_FSK_RSSI_LENGTH,
+   F_FSK_RX_INVERT,
+   F_FSK_PKT_MODE,
+
+   F_FSK_PSIZE,
+   F_FSK_CRC_EN,
+   F_FSK_DCFREE_ENC,
+   F_FSK_CRC_IBM,
+
+   F_FSK_ERROR_OSR_TOL,
+   F_FSK_RADIO_SELECT,
+
+   F_TX_MODE,
+   F_TX_ZERO_PAD,
+   F_TX_EDGE_SELECT,
+   F_TX_EDGE_SELECT_TOP,
+
+   F_TX_GAIN,
+   F_TX_CHIRP_LOW_PASS,
+   F_TX_FCC_WIDEBAND,
+   F_TX_SWAP_IQ,
+
+   F_FSK_TX_GAUSSIAN_EN,
+   F_FSK_TX_GAUSSIAN_SELECT_BT,
+   F_FSK_TX_PATTERN_EN,
+   F_FSK_TX_PREAMBLE_SEQ,
+   F_FSK_TX_PSIZE,
+
+   F_FORCE_HOST_RADIO_CTRL,
+   F_FORCE_HOST_FE_CTRL,
+   F_FORCE_DEC_FILTER_GAIN,
+
+   F_MCU_RST_0,
+   F_MCU_RST_1,
+   F_MCU_SELECT_MUX_0,
+   F_MCU_SELECT_MUX_1,
+   F_MCU_CORRUPTION_DETECTED_0,
+   F_MCU_CORRUPTION_DETECTED_1,
+   F_MCU_SELECT_EDGE_0,
+   F_MCU_SELECT_EDGE_1,
+
+   F_EMERGENCY_FORCE_HOST_CTRL,
+};
+
+static const struct reg_field sx1301_reg_fields[] = {
+   /* PAGE */
+   [F_SOFT_RESET]  = REG_FIELD(SX1301_PAGE, 7, 7),
+   /* BIST */
+   [F_START_BIST0] = REG_FIELD(SX1301_BIST, 0, 0),
+   [F_START_BIST1] = REG_FIELD(SX1301_BIST, 1, 1),
+   /* BIST_S */
+   [F_BIST0_FINISHED]  = REG_FIELD(SX1301_BIST_S, 0, 0),
+   [F_BIST1_FINISHED]  = REG_FIELD(SX1301_BIST_S, 1, 1),
+   /* GEN */
+   [F_GLOBAL_EN]   = REG_FIELD(SX1301_GEN,  3, 3),
+   /* CKEN */
+   [F_CLK32M_EN]   = REG_FIELD(SX1301_CKEN, 0, 0),
+   /* RADIO_CFG */
+   [F_RADIO_A_EN]  = REG_FIELD(SX1301_RADIO_CFG, 0, 0),
+   [F_RADIO_B_EN]  = REG_FIELD(SX1301_RADIO_CFG, 1, 1),
+   [F_RADIO_RST]   = REG_FIELD(SX1301_RADIO_CFG, 2, 2),
+
+   /* IQCFG */
+   [F_RX_INVERT_IQ]= REG_FIELD(SX1301_IQCFG, 0, 0),
+   [F_MODEM_INVERT_IQ] = REG_FIELD(SX1301_IQCFG, 1, 1),
+   [F_MBWSSF_MODEM_INVERT_IQ]  = REG_FIELD(SX1301_IQCFG, 2, 2),
+   [F_RX_EDGE_SELECT]  = REG_F

[PATCH lora-next 08/10] net: lora: sx1301: convert read and write to priv pointer

2018-08-07 Thread Ben Whitten
From: Ben Whitten 

Convert the next layer of read and writes to our private pointer,
once again compatiblity later in the page read and write layer.
The page functions will be removed with this full stack as page switches
are handled by regmap automatically.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 24 
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index ab45b5b..f84a6ce 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -318,9 +318,8 @@ static int sx1301_read_burst(struct sx1301_priv *priv, u8 
reg, u8 *val, size_t l
return spi_write_then_read(priv->spi, &addr, 1, val, len);
 }
 
-static int sx1301_read(struct spi_device *spi, u8 reg, u8 *val)
+static int sx1301_read(struct sx1301_priv *priv, u8 reg, u8 *val)
 {
-   struct sx1301_priv *priv = spi_get_drvdata(spi);
return sx1301_read_burst(priv, reg, val, 1);
 }
 
@@ -335,9 +334,8 @@ static int sx1301_write_burst(struct sx1301_priv *priv, u8 
reg, const u8 *val, s
return spi_sync_transfer(priv->spi, xfr, 2);
 }
 
-static int sx1301_write(struct spi_device *spi, u8 reg, u8 val)
+static int sx1301_write(struct sx1301_priv *priv, u8 reg, u8 val)
 {
-   struct sx1301_priv *priv = spi_get_drvdata(spi);
return sx1301_write_burst(priv, reg, &val, 1);
 }
 
@@ -350,7 +348,7 @@ static int sx1301_page_switch(struct spi_device *spi, u8 
page)
return 0;
 
dev_dbg(&spi->dev, "switching to page %u\n", (unsigned)page);
-   ret = sx1301_write(spi, REG_PAGE_RESET, page & 0x3);
+   ret = sx1301_write(priv, REG_PAGE_RESET, page & 0x3);
if (ret) {
dev_err(&spi->dev, "switching to page %u failed\n", 
(unsigned)page);
return ret;
@@ -364,23 +362,25 @@ static int sx1301_page_switch(struct spi_device *spi, u8 
page)
 static int sx1301_page_read(struct spi_device *spi, u8 page, u8 reg, u8 *val)
 {
int ret;
+   struct sx1301_priv *priv = spi_get_drvdata(spi);
 
ret = sx1301_page_switch(spi, page);
if (ret)
return ret;
 
-   return sx1301_read(spi, reg, val);
+   return sx1301_read(priv, reg, val);
 }
 
 static int sx1301_page_write(struct spi_device *spi, u8 page, u8 reg, u8 val)
 {
int ret;
+   struct sx1301_priv *priv = spi_get_drvdata(spi);
 
ret = sx1301_page_switch(spi, page);
if (ret)
return ret;
 
-   return sx1301_write(spi, reg, val);
+   return sx1301_write(priv, reg, val);
 }
 
 #define REG_RADIO_X_DATA   0
@@ -666,7 +666,7 @@ static int sx1301_agc_calibrate(struct spi_device *spi)
return ret;
}
 
-   ret = sx1301_read(spi, REG_EMERGENCY_FORCE, &val);
+   ret = sx1301_read(priv, REG_EMERGENCY_FORCE, &val);
if (ret) {
dev_err(&spi->dev, "emergency force read failed\n");
return ret;
@@ -674,7 +674,7 @@ static int sx1301_agc_calibrate(struct spi_device *spi)
 
val &= ~REG_EMERGENCY_FORCE_HOST_CTRL;
 
-   ret = sx1301_write(spi, REG_EMERGENCY_FORCE, val);
+   ret = sx1301_write(priv, REG_EMERGENCY_FORCE, val);
if (ret) {
dev_err(&spi->dev, "emergency force write failed\n");
return ret;
@@ -683,7 +683,7 @@ static int sx1301_agc_calibrate(struct spi_device *spi)
dev_err(&spi->dev, "starting calibration...\n");
msleep(2300);
 
-   ret = sx1301_read(spi, REG_EMERGENCY_FORCE, &val);
+   ret = sx1301_read(priv, REG_EMERGENCY_FORCE, &val);
if (ret) {
dev_err(&spi->dev, "emergency force read (1) failed\n");
return ret;
@@ -691,13 +691,13 @@ static int sx1301_agc_calibrate(struct spi_device *spi)
 
val |= REG_EMERGENCY_FORCE_HOST_CTRL;
 
-   ret = sx1301_write(spi, REG_EMERGENCY_FORCE, val);
+   ret = sx1301_write(priv, REG_EMERGENCY_FORCE, val);
if (ret) {
dev_err(&spi->dev, "emergency force write (1) failed\n");
return ret;
}
 
-   ret = sx1301_read(spi, REG_MCU_AGC_STATUS, &val);
+   ret = sx1301_read(priv, REG_MCU_AGC_STATUS, &val);
if (ret) {
dev_err(&spi->dev, "AGC status read failed\n");
return ret;
-- 
2.7.4



[PATCH lora-next 04/10] net: lora: sx1301: convert probe function to regmap access

2018-08-07 Thread Ben Whitten
From: Ben Whitten 

Keeping change sets small we convert the probe function over to regmap
and regmap_field access for initialisation.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 155 +-
 drivers/net/lora/sx1301.h |   7 +++
 2 files changed, 35 insertions(+), 127 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 54bfc31..118e8d8 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -379,11 +379,6 @@ static int sx1301_page_write(struct spi_device *spi, u8 
page, u8 reg, u8 val)
return sx1301_write(spi, reg, val);
 }
 
-static int sx1301_soft_reset(struct spi_device *spi)
-{
-   return sx1301_write(spi, REG_PAGE_RESET, REG_PAGE_RESET_SOFT_RESET);
-}
-
 #define REG_RADIO_X_DATA   0
 #define REG_RADIO_X_DATA_READBACK  1
 #define REG_RADIO_X_ADDR   2
@@ -854,7 +849,6 @@ static int sx1301_probe(struct spi_device *spi)
int ret;
int i;
unsigned int ver;
-   u8 val;
 
rst = devm_gpiod_get_optional(&spi->dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(rst))
@@ -911,96 +905,46 @@ static int sx1301_probe(struct spi_device *spi)
return ret;
}
 
-   if (ver != 103) {
+   if (ver != SX1301_CHIP_VERSION) {
dev_err(&spi->dev, "unexpected version: %u\n", ver);
return -ENXIO;
}
 
-   ret = sx1301_write(spi, REG_PAGE_RESET, 0);
+   ret = regmap_write(priv->regmap, SX1301_PAGE, 0);
if (ret) {
dev_err(&spi->dev, "page/reset write failed\n");
return ret;
}
 
-   ret = sx1301_soft_reset(spi);
+   ret = sx1301_field_write(priv, F_SOFT_RESET, 1);
if (ret) {
dev_err(&spi->dev, "soft reset failed\n");
return ret;
}
 
-   ret = sx1301_read(spi, 16, &val);
-   if (ret) {
-   dev_err(&spi->dev, "16 read failed\n");
-   return ret;
-   }
-
-   val &= ~REG_16_GLOBAL_EN;
-
-   ret = sx1301_write(spi, 16, val);
-   if (ret) {
-   dev_err(&spi->dev, "16 write failed\n");
-   return ret;
-   }
-
-   ret = sx1301_read(spi, 17, &val);
-   if (ret) {
-   dev_err(&spi->dev, "17 read failed\n");
-   return ret;
-   }
-
-   val &= ~REG_17_CLK32M_EN;
-
-   ret = sx1301_write(spi, 17, val);
-   if (ret) {
-   dev_err(&spi->dev, "17 write failed\n");
-   return ret;
-   }
-
-   ret = sx1301_page_read(spi, 2, 43, &val);
-   if (ret) {
-   dev_err(&spi->dev, "2|43 read failed\n");
+   /* gate clocks */
+   ret = sx1301_field_write(priv, F_GLOBAL_EN, 0);
+   if (ret)
return ret;
-   }
-
-   val |= REG_2_43_RADIO_B_EN | REG_2_43_RADIO_A_EN;
-
-   ret = sx1301_page_write(spi, 2, 43, val);
-   if (ret) {
-   dev_err(&spi->dev, "2|43 write failed\n");
+   ret = sx1301_field_write(priv, F_CLK32M_EN, 0);
+   if (ret)
return ret;
-   }
 
-   msleep(500);
-
-   ret = sx1301_page_read(spi, 2, 43, &val);
-   if (ret) {
-   dev_err(&spi->dev, "2|43 read failed\n");
+   /* switch on and reset the radios (also starts the 32 MHz XTAL) */
+   ret = sx1301_field_write(priv, F_RADIO_A_EN, 1);
+   if (ret)
return ret;
-   }
-
-   val |= REG_2_43_RADIO_RST;
-
-   ret = sx1301_page_write(spi, 2, 43, val);
-   if (ret) {
-   dev_err(&spi->dev, "2|43 write failed\n");
+   ret = sx1301_field_write(priv, F_RADIO_B_EN, 1);
+   if (ret)
return ret;
-   }
-
-   msleep(5);
-
-   ret = sx1301_page_read(spi, 2, 43, &val);
-   if (ret) {
-   dev_err(&spi->dev, "2|43 read failed\n");
+   mdelay(500);
+   ret = sx1301_field_write(priv, F_RADIO_RST, 1);
+   if (ret)
return ret;
-   }
-
-   val &= ~REG_2_43_RADIO_RST;
-
-   ret = sx1301_page_write(spi, 2, 43, val);
-   if (ret) {
-   dev_err(&spi->dev, "2|43 write failed\n");
+   mdelay(5);
+   ret = sx1301_field_write(priv, F_RADIO_RST, 0);
+   if (ret)
return ret;
-   }
 
/* radio A */
 
@@ -1047,65 +991,22 @@ static int sx1301_probe(struct spi_device *spi)
}
 
/* GPIO */
-
-   ret = sx1301_read(spi, REG_GPIO_MODE, &val);
-   if (ret) {
-   dev_err(&spi->dev, "GPIO mode read failed\n");
-   return ret;
-   }
-
-   val |= GENMASK(4, 0);
-
-  

[PATCH lora-next 02/10] net: lora: add methods for devm registration

2018-08-07 Thread Ben Whitten
From: Ben Whitten 

Follow the devm model so that we can avoid lengthy unwind code.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/dev.c   | 20 
 include/linux/lora/dev.h |  1 +
 2 files changed, 21 insertions(+)

diff --git a/drivers/net/lora/dev.c b/drivers/net/lora/dev.c
index 8c01106..69a8b52 100644
--- a/drivers/net/lora/dev.c
+++ b/drivers/net/lora/dev.c
@@ -84,6 +84,26 @@ void free_loradev(struct net_device *dev)
 }
 EXPORT_SYMBOL_GPL(free_loradev);
 
+static void devm_lora_unregister(struct device *dev, void *res)
+{
+   free_loradev(*(struct net_device **)res);
+}
+
+int devm_lora_register_netdev(struct device *dev, struct net_device *net)
+{
+   struct net_device **ptr;
+
+   ptr = devres_alloc(devm_lora_unregister, sizeof(*ptr), GFP_KERNEL);
+   if (!ptr)
+   return -ENOMEM;
+
+   *ptr = net;
+   devres_add(dev, ptr);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(devm_lora_register_netdev);
+
 static struct rtnl_link_ops lora_link_ops __read_mostly = {
.kind = "lora",
.setup = lora_setup,
diff --git a/include/linux/lora/dev.h b/include/linux/lora/dev.h
index 153f9b2..3f871c6 100644
--- a/include/linux/lora/dev.h
+++ b/include/linux/lora/dev.h
@@ -32,6 +32,7 @@ static inline int lora_strtoeui(const char *str, lora_eui 
*val)
 
 struct net_device *alloc_loradev(int sizeof_priv);
 void free_loradev(struct net_device *dev);
+int devm_lora_register_netdev(struct device *dev, struct net_device *net);
 int register_loradev(struct net_device *dev);
 void unregister_loradev(struct net_device *dev);
 int open_loradev(struct net_device *dev);
-- 
2.7.4



[PATCH lora-next 03/10] net: lora: sx1301: convert to devm registration of netdev

2018-08-07 Thread Ben Whitten
From: Ben Whitten 

We allow the devres framework handle the clean removal of resources on
teardown of the device, in this case the SPI device, saving lengthy
unwind code and improving clarity.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 87 +--
 1 file changed, 31 insertions(+), 56 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 49958f0..54bfc31 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -869,9 +869,13 @@ static int sx1301_probe(struct spi_device *spi)
spi_setup(spi);
 
netdev = alloc_loradev(sizeof(*priv));
-   if (!netdev) {
-   ret = -ENOMEM;
-   goto err_alloc_loradev;
+   if (!netdev)
+   return -ENOMEM;
+
+   ret = devm_lora_register_netdev(&spi->dev, netdev);
+   if (ret) {
+   free_loradev(netdev);
+   return ret;
}
 
priv = netdev_priv(netdev);
@@ -885,7 +889,7 @@ static int sx1301_probe(struct spi_device *spi)
if (IS_ERR(priv->regmap)) {
ret = PTR_ERR(priv->regmap);
dev_err(&spi->dev, "Regmap allocation failed: %d\n", ret);
-   return err_regmap;
+   return ret;
}
 
for (i = 0; i < ARRAY_SIZE(sx1301_reg_fields); i++) {
@@ -897,38 +901,37 @@ static int sx1301_probe(struct spi_device *spi)
if (IS_ERR(priv->regmap_fields[i])) {
ret = PTR_ERR(priv->regmap_fields[i]);
dev_err(&spi->dev, "Cannot allocate regmap field: 
%d\n", ret);
-   goto err_regmap;
+   return ret;
}
}
 
ret = regmap_read(priv->regmap, SX1301_VER, &ver);
if (ret) {
dev_err(&spi->dev, "version read failed\n");
-   goto err_version;
+   return ret;
}
 
if (ver != 103) {
dev_err(&spi->dev, "unexpected version: %u\n", ver);
-   ret = -ENXIO;
-   goto err_version;
+   return -ENXIO;
}
 
ret = sx1301_write(spi, REG_PAGE_RESET, 0);
if (ret) {
dev_err(&spi->dev, "page/reset write failed\n");
-   goto err_init_page;
+   return ret;
}
 
ret = sx1301_soft_reset(spi);
if (ret) {
dev_err(&spi->dev, "soft reset failed\n");
-   goto err_soft_reset;
+   return ret;
}
 
ret = sx1301_read(spi, 16, &val);
if (ret) {
dev_err(&spi->dev, "16 read failed\n");
-   goto err_read_global_en_0;
+   return ret;
}
 
val &= ~REG_16_GLOBAL_EN;
@@ -936,13 +939,13 @@ static int sx1301_probe(struct spi_device *spi)
ret = sx1301_write(spi, 16, val);
if (ret) {
dev_err(&spi->dev, "16 write failed\n");
-   goto err_write_global_en_0;
+   return ret;
}
 
ret = sx1301_read(spi, 17, &val);
if (ret) {
dev_err(&spi->dev, "17 read failed\n");
-   goto err_read_clk32m_0;
+   return ret;
}
 
val &= ~REG_17_CLK32M_EN;
@@ -950,7 +953,7 @@ static int sx1301_probe(struct spi_device *spi)
ret = sx1301_write(spi, 17, val);
if (ret) {
dev_err(&spi->dev, "17 write failed\n");
-   goto err_write_clk32m_0;
+   return ret;
}
 
ret = sx1301_page_read(spi, 2, 43, &val);
@@ -1003,8 +1006,7 @@ static int sx1301_probe(struct spi_device *spi)
 
priv->radio_a_ctrl = spi_alloc_master(&spi->dev, sizeof(*radio));
if (!priv->radio_a_ctrl) {
-   ret = -ENOMEM;
-   goto err_radio_a_alloc;
+   return -ENOMEM;
}
 
sx1301_radio_setup(priv->radio_a_ctrl);
@@ -1019,15 +1021,14 @@ static int sx1301_probe(struct spi_device *spi)
if (ret) {
dev_err(&spi->dev, "radio A SPI register failed\n");
spi_controller_put(priv->radio_a_ctrl);
-   goto err_radio_a_register;
+   return ret;
}
 
/* radio B */
 
priv->radio_b_ctrl = spi_alloc_master(&spi->dev, sizeof(*radio));
if (!priv->radio_b_ctrl) {
-   ret = -ENOMEM;
-   goto err_radio_b_alloc;
+   return -ENOMEM;
}
 
sx1301_radio_setup(priv->radio_b_ctrl);
@@ -1042,7 +1043,7 @@ static int sx1301_probe(struct spi_device *spi)
if (ret) {
dev_err(&spi->dev, "radio B SPI register failed\

[PATCH lora-next 05/10] net: lora: sx1301: add device to private data and convert ram reads

2018-08-07 Thread Ben Whitten
From: Ben Whitten 

It's easier to simply add a pointer to our device to our private data,
this way we can avoid passing around our spi_device and instead just
pass private data which is more flexible.

As its a two line change its coupled with converting AGC and ARB ram reads
to regmap functions.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 34 +-
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 118e8d8..249551b 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -283,6 +283,7 @@ struct spi_sx1301 {
 };
 
 struct sx1301_priv {
+   struct device *dev;
struct lora_priv lora;
struct gpio_desc *rst_gpio;
u8 cur_page;
@@ -472,40 +473,44 @@ static int sx1301_radio_spi_transfer_one(struct 
spi_controller *ctrl,
return 0;
 }
 
-static int sx1301_agc_ram_read(struct spi_device *spi, u8 addr, u8 *val)
+static int sx1301_agc_ram_read(struct sx1301_priv *priv, u8 addr, u8 *val)
 {
int ret;
+   unsigned int read;
 
-   ret = sx1301_page_write(spi, 2, REG_2_DBG_AGC_MCU_RAM_ADDR, addr);
+   ret = regmap_write(priv->regmap, SX1301_DBG_AGC_MCU_RAM_ADDR, addr);
if (ret) {
-   dev_err(&spi->dev, "AGC RAM addr write failed\n");
+   dev_err(priv->dev, "AGC RAM addr write failed\n");
return ret;
}
 
-   ret = sx1301_page_read(spi, 2, REG_2_DBG_AGC_MCU_RAM_DATA, val);
+   ret = regmap_read(priv->regmap, SX1301_DBG_AGC_MCU_RAM_DATA, &read);
if (ret) {
-   dev_err(&spi->dev, "AGC RAM data read failed\n");
+   dev_err(priv->dev, "AGC RAM data read failed\n");
return ret;
}
+   *val = read;
 
return 0;
 }
 
-static int sx1301_arb_ram_read(struct spi_device *spi, u8 addr, u8 *val)
+static int sx1301_arb_ram_read(struct sx1301_priv *priv, u8 addr, u8 *val)
 {
int ret;
+   unsigned int read;
 
-   ret = sx1301_page_write(spi, 2, REG_2_DBG_ARB_MCU_RAM_ADDR, addr);
+   ret = regmap_write(priv->regmap, SX1301_DBG_ARB_MCU_RAM_ADDR, addr);
if (ret) {
-   dev_err(&spi->dev, "ARB RAM addr write failed\n");
+   dev_err(priv->dev, "ARB RAM addr write failed\n");
return ret;
}
 
-   ret = sx1301_page_read(spi, 2, REG_2_DBG_ARB_MCU_RAM_DATA, val);
+   ret = regmap_read(priv->regmap, SX1301_DBG_ARB_MCU_RAM_DATA, &read);
if (ret) {
-   dev_err(&spi->dev, "ARB RAM data read failed\n");
+   dev_err(priv->dev, "ARB RAM data read failed\n");
return ret;
}
+   *val = read;
 
return 0;
 }
@@ -604,6 +609,7 @@ static int sx1301_load_firmware(struct spi_device *spi, int 
mcu, const u8 *data,
 static int sx1301_agc_calibrate(struct spi_device *spi)
 {
const struct firmware *fw;
+   struct sx1301_priv *priv = spi_get_drvdata(spi);
u8 val;
int ret;
 
@@ -663,7 +669,7 @@ static int sx1301_agc_calibrate(struct spi_device *spi)
return ret;
}
 
-   ret = sx1301_agc_ram_read(spi, 0x20, &val);
+   ret = sx1301_agc_ram_read(priv, 0x20, &val);
if (ret) {
dev_err(&spi->dev, "AGC RAM data read failed\n");
return ret;
@@ -730,6 +736,7 @@ static int sx1301_agc_calibrate(struct spi_device *spi)
 
 static int sx1301_load_all_firmware(struct spi_device *spi)
 {
+   struct sx1301_priv *priv = spi_get_drvdata(spi);
const struct firmware *fw;
u8 val;
int ret;
@@ -802,7 +809,7 @@ static int sx1301_load_all_firmware(struct spi_device *spi)
return ret;
}
 
-   ret = sx1301_agc_ram_read(spi, 0x20, &val);
+   ret = sx1301_agc_ram_read(priv, 0x20, &val);
if (ret) {
dev_err(&spi->dev, "AGC RAM data read failed\n");
return ret;
@@ -815,7 +822,7 @@ static int sx1301_load_all_firmware(struct spi_device *spi)
return -ENXIO;
}
 
-   ret = sx1301_arb_ram_read(spi, 0x20, &val);
+   ret = sx1301_arb_ram_read(priv, 0x20, &val);
if (ret) {
dev_err(&spi->dev, "ARB RAM data read failed\n");
return ret;
@@ -878,6 +885,7 @@ static int sx1301_probe(struct spi_device *spi)
 
spi_set_drvdata(spi, netdev);
SET_NETDEV_DEV(netdev, &spi->dev);
+   priv->dev = &spi->dev;
 
priv->regmap = devm_regmap_init_spi(spi, &sx1301_regmap_config);
if (IS_ERR(priv->regmap)) {
-- 
2.7.4



[RFC] spi: add spi multiplexing functions for dt

2018-08-07 Thread Ben Whitten
Like I2C busses SPI devices can also sit behind multiplexers.
This patch adds is based off the I2C implementation and allows
description in the devicetree.

Signed-off-by: Ben Whitten 
---
 drivers/spi/Kconfig |  10 +++
 drivers/spi/Makefile|   3 +
 drivers/spi/spi-mux.c   | 181 
 include/linux/spi-mux.h |  55 +++
 4 files changed, 249 insertions(+)
 create mode 100644 drivers/spi/spi-mux.c
 create mode 100644 include/linux/spi-mux.h

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index a75f2a2..58eba70 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -51,6 +51,16 @@ config SPI_MASTER
 
 if SPI_MASTER
 
+config SPI_MUX
+   tristate "SPI bus multiplexing support"
+   help
+ Say Y here if you want the SPI core to support the ability to
+ handle multiplexed SPI bus topologies, by presenting each
+ multiplexed segment as an SPI controller.
+
+ This support is also available as a module.  If so, the module
+ will be called spi-mux.
+
 comment "SPI Master Controller Drivers"
 
 config SPI_ALTERA
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 8e0cda7..ef525fe 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -109,6 +109,9 @@ obj-$(CONFIG_SPI_XLP)   += spi-xlp.o
 obj-$(CONFIG_SPI_XTENSA_XTFPGA)+= spi-xtensa-xtfpga.o
 obj-$(CONFIG_SPI_ZYNQMP_GQSPI) += spi-zynqmp-gqspi.o
 
+# SPI muxs
+obj-$(CONFIG_SPI_MUX)  += spi-mux.o
+
 # SPI slave protocol handlers
 obj-$(CONFIG_SPI_SLAVE_TIME)   += spi-slave-time.o
 obj-$(CONFIG_SPI_SLAVE_SYSTEM_CONTROL) += spi-slave-system-control.o
diff --git a/drivers/spi/spi-mux.c b/drivers/spi/spi-mux.c
new file mode 100644
index 000..a2008c1
--- /dev/null
+++ b/drivers/spi/spi-mux.c
@@ -0,0 +1,181 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for an SPI multiplexer
+ *
+ * Copyright (c) 2018   Ben Whitten
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct spi_mux_priv {
+   struct spi_controller *controller;
+   struct spi_mux_core *muxc;
+   u32 chan_id;
+};
+
+struct spi_mux_core *spi_mux_alloc(struct spi_controller *parent,
+  struct device *dev,
+  int max_controllers,
+  int sizeof_priv,
+  int (*select)(struct spi_mux_core *, u32),
+  int (*deselect)(struct spi_mux_core *, u32),
+  int (*transfer_one_message)
+   (struct spi_controller *controller,
+struct spi_message *msg))
+{
+   struct spi_mux_core *muxc;
+
+   muxc = devm_kzalloc(dev, sizeof(*muxc)
+   + max_controllers * sizeof(muxc->controller[0])
+   + sizeof_priv, GFP_KERNEL);
+   if (!muxc)
+   return NULL;
+   if (sizeof_priv)
+   muxc->priv = &muxc->controller[max_controllers];
+
+   muxc->parent = parent;
+   muxc->dev = dev;
+
+   muxc->select = select;
+   muxc->deselect = deselect;
+   muxc->transfer_one_message = transfer_one_message;
+   muxc->max_controllers = max_controllers;
+
+   return muxc;
+}
+EXPORT_SYMBOL_GPL(spi_mux_alloc);
+
+u32 spi_mux_get_chan_id(struct spi_controller *controller)
+{
+   struct spi_mux_priv *priv = spi_controller_get_devdata(controller);
+
+   return priv->chan_id;
+}
+EXPORT_SYMBOL_GPL(spi_mux_get_chan_id);
+
+static int spi_mux_transfer_one_message(struct spi_controller *controller,
+   struct spi_message *msg)
+{
+   struct spi_mux_priv *priv = spi_controller_get_devdata(controller);
+   struct spi_mux_core *muxc = priv->muxc;
+   struct spi_device *spi = to_spi_device(muxc->dev);
+   int ret;
+
+   ret = muxc->select(muxc, priv->chan_id);
+   if (ret < 0)
+   return ret;
+
+   /* If we have a custom transfer, use it */
+   if (muxc->transfer_one_message)
+   ret = muxc->transfer_one_message(controller, msg);
+   else
+   ret = spi_sync(spi, msg);
+
+   if (muxc->deselect)
+   muxc->deselect(muxc, priv->chan_id);
+
+   return ret;
+}
+
+static int spi_mux_add_controller(struct spi_mux_core *muxc, u32 chan_id)
+{
+   struct spi_controller *controller;
+   struct spi_mux_priv *priv;
+   int ret;
+
+   if (muxc->num_controllers >= muxc->max_controllers) {
+   dev_err(muxc->dev, "No room for more spi-mux controllers");
+   return -EINVAL;
+   }
+
+   controller = spi_alloc_master(muxc->dev, sizeof(*priv));
+   if (!controller)
+   

[PATCH lora-next 09/10] net: lora: sx1301: convert agc calibrate to regmap functions

2018-08-07 Thread Ben Whitten
From: Ben Whitten 

We convert the AGC calibration function over to regmap and take the
opportunity to make the expected firmware versions defines.
Switch to taking a pointer to our private data.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 101 --
 1 file changed, 26 insertions(+), 75 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index f84a6ce..21b3f9a 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -589,123 +589,74 @@ static int sx1301_load_firmware(struct sx1301_priv 
*priv, int mcu, const struct
return 0;
 }
 
-static int sx1301_agc_calibrate(struct spi_device *spi)
+static int sx1301_agc_calibrate(struct sx1301_priv *priv)
 {
const struct firmware *fw;
-   struct sx1301_priv *priv = spi_get_drvdata(spi);
u8 val;
int ret;
+   unsigned int cal;
 
ret = request_firmware(&fw, "sx1301_agc_calibration.bin", priv->dev);
if (ret) {
-   dev_err(&spi->dev, "agc cal firmware file load failed\n");
+   dev_err(priv->dev, "AGC CAL firmware file load failed\n");
return ret;
}
 
ret = sx1301_load_firmware(priv, 1, fw);
release_firmware(fw);
if (ret) {
-   dev_err(&spi->dev, "agc cal firmware load failed\n");
-   return ret;
-   }
-
-   ret = sx1301_page_read(spi, 0, 105, &val);
-   if (ret) {
-   dev_err(&spi->dev, "0|105 read failed\n");
+   dev_err(priv->dev, "AGC CAL firmware load failed\n");
return ret;
}
 
-   val &= ~REG_0_105_FORCE_HOST_RADIO_CTRL;
-
-   ret = sx1301_page_write(spi, 0, 105, val);
-   if (ret) {
-   dev_err(&spi->dev, "0|105 write failed\n");
+   ret = sx1301_field_write(priv, F_FORCE_HOST_RADIO_CTRL, 0);
+   if (ret)
return ret;
-   }
 
val = BIT(4); /* with DAC gain=3 */
if (false)
val |= BIT(5); /* SX1255 */
 
-   ret = sx1301_page_write(spi, 0, REG_0_RADIO_SELECT, val);
-   if (ret) {
-   dev_err(&spi->dev, "radio select write failed\n");
-   return ret;
-   }
-
-   ret = sx1301_page_read(spi, 0, REG_0_MCU, &val);
-   if (ret) {
-   dev_err(&spi->dev, "MCU read (0) failed\n");
+   ret = regmap_write(priv->regmap, SX1301_CHRS, val);
+   if (ret)
return ret;
-   }
-
-   val &= ~REG_0_MCU_RST_1;
 
-   ret = sx1301_page_write(spi, 0, REG_0_MCU, val);
-   if (ret) {
-   dev_err(&spi->dev, "MCU write (0) failed\n");
+   ret = sx1301_field_write(priv, F_MCU_RST_1, 0);
+   if (ret)
return ret;
-   }
 
ret = sx1301_agc_ram_read(priv, 0x20, &val);
if (ret) {
-   dev_err(&spi->dev, "AGC RAM data read failed\n");
+   dev_err(priv->dev, "AGC RAM data read failed\n");
return ret;
}
 
-   dev_info(&spi->dev, "AGC calibration firmware version %u\n", 
(unsigned)val);
+   dev_info(priv->dev, "AGC calibration firmware version %u\n", 
(unsigned)val);
 
-   if (val != 2) {
-   dev_err(&spi->dev, "unexpected firmware version, expecting 
%u\n", 2);
+   if (val != SX1301_MCU_AGC_CAL_FW_VERSION) {
+   dev_err(priv->dev, "unexpected firmware version, expecting 
%u\n",
+   SX1301_MCU_AGC_CAL_FW_VERSION);
return -ENXIO;
}
 
-   ret = sx1301_page_switch(spi, 3);
-   if (ret) {
-   dev_err(&spi->dev, "page switch 3 failed\n");
-   return ret;
-   }
-
-   ret = sx1301_read(priv, REG_EMERGENCY_FORCE, &val);
-   if (ret) {
-   dev_err(&spi->dev, "emergency force read failed\n");
-   return ret;
-   }
-
-   val &= ~REG_EMERGENCY_FORCE_HOST_CTRL;
-
-   ret = sx1301_write(priv, REG_EMERGENCY_FORCE, val);
-   if (ret) {
-   dev_err(&spi->dev, "emergency force write failed\n");
+   ret = sx1301_field_write(priv, F_EMERGENCY_FORCE_HOST_CTRL, 0);
+   if (ret)
return ret;
-   }
 
-   dev_err(&spi->dev, "starting calibration...\n");
+   dev_err(priv->dev, "starting calibration...\n");
msleep(2300);
 
-   ret = sx1301_read(priv, REG_EMERGENCY_FORCE, &val);
-   if (ret) {
-   dev_err(&spi->dev, "emergency force read (1) failed\n");
-   return ret;
-   }
-
-   val |= REG_

[PATCH lora-next 07/10] net: lora: sx1301: convert read and write burst to take priv data

2018-08-07 Thread Ben Whitten
From: Ben Whitten 

As part of standardising on passing our priv data around we convert read
and write burst to take the priv data, there is a small compat step
needed in the old _read and _write functions and will be removed in the
next step.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 18 ++
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 4cec524..ab45b5b 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -312,18 +312,19 @@ static int sx1301_field_write(struct sx1301_priv *priv,
return regmap_field_write(priv->regmap_fields[field_id], val);
 }
 
-static int sx1301_read_burst(struct spi_device *spi, u8 reg, u8 *val, size_t 
len)
+static int sx1301_read_burst(struct sx1301_priv *priv, u8 reg, u8 *val, size_t 
len)
 {
u8 addr = reg & 0x7f;
-   return spi_write_then_read(spi, &addr, 1, val, len);
+   return spi_write_then_read(priv->spi, &addr, 1, val, len);
 }
 
 static int sx1301_read(struct spi_device *spi, u8 reg, u8 *val)
 {
-   return sx1301_read_burst(spi, reg, val, 1);
+   struct sx1301_priv *priv = spi_get_drvdata(spi);
+   return sx1301_read_burst(priv, reg, val, 1);
 }
 
-static int sx1301_write_burst(struct spi_device *spi, u8 reg, const u8 *val, 
size_t len)
+static int sx1301_write_burst(struct sx1301_priv *priv, u8 reg, const u8 *val, 
size_t len)
 {
u8 addr = reg | BIT(7);
struct spi_transfer xfr[2] = {
@@ -331,12 +332,13 @@ static int sx1301_write_burst(struct spi_device *spi, u8 
reg, const u8 *val, siz
{ .tx_buf = val, .len = len },
};
 
-   return spi_sync_transfer(spi, xfr, 2);
+   return spi_sync_transfer(priv->spi, xfr, 2);
 }
 
 static int sx1301_write(struct spi_device *spi, u8 reg, u8 val)
 {
-   return sx1301_write_burst(spi, reg, &val, 1);
+   struct sx1301_priv *priv = spi_get_drvdata(spi);
+   return sx1301_write_burst(priv, reg, &val, 1);
 }
 
 static int sx1301_page_switch(struct spi_device *spi, u8 page)
@@ -551,7 +553,7 @@ static int sx1301_load_firmware(struct sx1301_priv *priv, 
int mcu, const struct
if (ret)
return ret;
 
-   ret = sx1301_write_burst(priv->spi, REG_MCU_PROM_DATA, fw->data, 
fw->size);
+   ret = sx1301_write_burst(priv, REG_MCU_PROM_DATA, fw->data, fw->size);
if (ret) {
dev_err(priv->dev, "MCU prom data write failed\n");
return ret;
@@ -567,7 +569,7 @@ static int sx1301_load_firmware(struct sx1301_priv *priv, 
int mcu, const struct
if (!buf)
return -ENOMEM;
 
-   ret = sx1301_read_burst(priv->spi, REG_MCU_PROM_DATA, buf, fw->size);
+   ret = sx1301_read_burst(priv, REG_MCU_PROM_DATA, buf, fw->size);
if (ret) {
dev_err(priv->dev, "MCU prom data read failed\n");
return ret;
-- 
2.7.4



[PATCH lora-next 10/10] net: lora: sx1301: convert all firmware to regmap

2018-08-07 Thread Ben Whitten
The last stage in the probe function loads the final firmwares to
the sx1301.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 67 ---
 1 file changed, 28 insertions(+), 39 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 21b3f9a..7f4bfa1 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -663,16 +663,15 @@ static int sx1301_agc_calibrate(struct sx1301_priv *priv)
return 0;
 }
 
-static int sx1301_load_all_firmware(struct spi_device *spi)
+static int sx1301_load_all_firmware(struct sx1301_priv *priv)
 {
-   struct sx1301_priv *priv = spi_get_drvdata(spi);
const struct firmware *fw;
u8 val;
int ret;
 
ret = request_firmware(&fw, "sx1301_arb.bin", priv->dev);
if (ret) {
-   dev_err(priv->dev, "arb firmware file load failed\n");
+   dev_err(priv->dev, "ARB firmware file load failed\n");
return ret;
}
 
@@ -683,7 +682,7 @@ static int sx1301_load_all_firmware(struct spi_device *spi)
 
ret = request_firmware(&fw, "sx1301_agc.bin", priv->dev);
if (ret) {
-   dev_err(priv->dev, "agc firmware file load failed\n");
+   dev_err(priv->dev, "AGC firmware file load failed\n");
return ret;
}
 
@@ -692,63 +691,53 @@ static int sx1301_load_all_firmware(struct spi_device 
*spi)
if (ret)
return ret;
 
-   ret = sx1301_page_read(spi, 0, 105, &val);
-   if (ret) {
-   dev_err(&spi->dev, "0|105 read failed\n");
+   ret = sx1301_field_write(priv, F_FORCE_HOST_RADIO_CTRL, 0);
+   if (ret)
return ret;
-   }
-
-   val &= ~(REG_0_105_FORCE_HOST_RADIO_CTRL | REG_0_105_FORCE_HOST_FE_CTRL 
| REG_0_105_FORCE_DEC_FILTER_GAIN);
-
-   ret = sx1301_page_write(spi, 0, 105, val);
-   if (ret) {
-   dev_err(&spi->dev, "0|105 write failed\n");
+   ret = sx1301_field_write(priv, F_FORCE_HOST_FE_CTRL, 0);
+   if (ret)
return ret;
-   }
-
-   ret = sx1301_page_write(spi, 0, REG_0_RADIO_SELECT, 0);
-   if (ret) {
-   dev_err(&spi->dev, "radio select write failed\n");
+   ret = sx1301_field_write(priv, F_FORCE_DEC_FILTER_GAIN, 0);
+   if (ret)
return ret;
-   }
 
-   ret = sx1301_page_read(spi, 0, REG_0_MCU, &val);
-   if (ret) {
-   dev_err(&spi->dev, "MCU read (0) failed\n");
+   ret = regmap_write(priv->regmap, SX1301_CHRS, 0);
+   if (ret)
return ret;
-   }
-
-   val &= ~(REG_0_MCU_RST_1 | REG_0_MCU_RST_0);
 
-   ret = sx1301_page_write(spi, 0, REG_0_MCU, val);
-   if (ret) {
-   dev_err(&spi->dev, "MCU write (0) failed\n");
+   /* Release the CPUs */
+   ret = sx1301_field_write(priv, F_MCU_RST_0, 0);
+   if (ret)
+   return ret;
+   ret = sx1301_field_write(priv, F_MCU_RST_1, 0);
+   if (ret)
return ret;
-   }
 
ret = sx1301_agc_ram_read(priv, 0x20, &val);
if (ret) {
-   dev_err(&spi->dev, "AGC RAM data read failed\n");
+   dev_err(priv->dev, "AGC RAM data read failed\n");
return ret;
}
 
-   dev_info(&spi->dev, "AGC firmware version %u\n", (unsigned)val);
+   dev_info(priv->dev, "AGC firmware version %u\n", (unsigned)val);
 
-   if (val != 4) {
-   dev_err(&spi->dev, "unexpected firmware version, expecting 
%u\n", 4);
+   if (val != SX1301_MCU_AGC_FW_VERSION) {
+   dev_err(priv->dev, "unexpected firmware version, expecting 
%u\n",
+   SX1301_MCU_AGC_FW_VERSION);
return -ENXIO;
}
 
ret = sx1301_arb_ram_read(priv, 0x20, &val);
if (ret) {
-   dev_err(&spi->dev, "ARB RAM data read failed\n");
+   dev_err(priv->dev, "ARB RAM data read failed\n");
return ret;
}
 
-   dev_info(&spi->dev, "ARB firmware version %u\n", (unsigned)val);
+   dev_info(priv->dev, "ARB firmware version %u\n", (unsigned)val);
 
-   if (val != 1) {
-   dev_err(&spi->dev, "unexpected firmware version, expecting 
%u\n", 1);
+   if (val != SX1301_MCU_ARB_FW_VERSION) {
+   dev_err(priv->dev, "unexpected firmware version, expecting 
%u\n",
+   SX1301_MCU_ARB_FW_VERSION);
return -ENXIO;
}
 
@@ -942,7 +931,7 @@ static int sx1301_probe(struct spi_device *spi)
 
/* TODO */
 
-   ret = sx1301_load_all_firmware(spi);
+   ret = sx1301_load_all_firmware(priv);
if (ret)
return ret;
 
-- 
2.7.4



[PATCH lora-next 00/10] Conversing sx1301 to regmap and regfield

2018-08-07 Thread Ben Whitten
This series converts the majority of sx1301 code to using regmap and regfield
system.
The SPI subsystem is as yet untouched but will be converted to a regmap_bus
in a future series with sx1257 conversions.

Interestingly the initial state did not work for me as I was getting kernel
oopses somewhere todo with sx1301_page_read on my hardware.
Since conversion to regmap the sx1301 initialises properly, sx1257 still oopses
because of the SPI bus read but presumably will go away with regmap_bus.

Ben Whitten (10):
  net: lora: sx1301: add register, bit-fields, and helpers for regmap
  net: lora: add methods for devm registration
  net: lora: sx1301: convert to devm registration of netdev
  net: lora: sx1301: convert probe function to regmap access
  net: lora: sx1301: add device to private data and convert ram reads
  net: lora: sx1301: simplify firmware loading and convert
  net: lora: sx1301: convert read and write burst to take priv data
  net: lora: sx1301: convert read and write to priv pointer
  net: lora: sx1301: convert agc calibrate to regmap functions
  net: lora: sx1301: convert all firmware to regmap

 drivers/net/lora/Kconfig  |   1 +
 drivers/net/lora/dev.c|  20 ++
 drivers/net/lora/sx1301.c | 803 --
 drivers/net/lora/sx1301.h | 176 ++
 include/linux/lora/dev.h  |   1 +
 5 files changed, 623 insertions(+), 378 deletions(-)
 create mode 100644 drivers/net/lora/sx1301.h

-- 
2.7.4



[PATCH lora-next 06/10] net: lora: sx1301: simplify firmware loading and convert

2018-08-07 Thread Ben Whitten
From: Ben Whitten 

As part of changing our internal pointers to our priv data we add the
spi_device temporarily for downstream burst read/writes.
Just pass firmware pointer to the load and remove redundant size checks,
as both MCUs have the same program size add a define.

Use devm_kzalloc for automatic cleanup on failure to load firmware,
manually cleaup this memory on success.

Convert firmware loading to regmap functions.

Signed-off-by: Ben Whitten 
---
 drivers/net/lora/sx1301.c | 109 --
 1 file changed, 37 insertions(+), 72 deletions(-)

diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 249551b..4cec524 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -284,6 +284,7 @@ struct spi_sx1301 {
 
 struct sx1301_priv {
struct device *dev;
+   struct spi_device *spi;
struct lora_priv lora;
struct gpio_desc *rst_gpio;
u8 cur_page;
@@ -515,93 +516,73 @@ static int sx1301_arb_ram_read(struct sx1301_priv *priv, 
u8 addr, u8 *val)
return 0;
 }
 
-static int sx1301_load_firmware(struct spi_device *spi, int mcu, const u8 
*data, size_t len)
+static int sx1301_load_firmware(struct sx1301_priv *priv, int mcu, const 
struct firmware *fw)
 {
u8 *buf;
-   u8 val, rst, select_mux;
int ret;
+   unsigned int read;
+   enum sx1301_fields rst, select_mux;
 
-   if (len > 8192)
+   if (fw->size > SX1301_MCU_FW_BYTE)
return -EINVAL;
 
switch (mcu) {
case 0:
-   rst = REG_0_MCU_RST_0;
-   select_mux = REG_0_MCU_SELECT_MUX_0;
+   rst = F_MCU_RST_0;
+   select_mux = F_MCU_SELECT_MUX_0;
break;
case 1:
-   rst = REG_0_MCU_RST_1;
-   select_mux = REG_0_MCU_SELECT_MUX_1;
+   rst = F_MCU_RST_1;
+   select_mux = F_MCU_SELECT_MUX_1;
break;
default:
return -EINVAL;
}
 
-   ret = sx1301_page_read(spi, 0, REG_0_MCU, &val);
-   if (ret) {
-   dev_err(&spi->dev, "MCU read failed\n");
+   ret = sx1301_field_write(priv, rst, 1);
+   if (ret)
return ret;
-   }
-
-   val |= rst;
-   val &= ~select_mux;
-
-   ret = sx1301_page_write(spi, 0, REG_0_MCU, val);
-   if (ret) {
-   dev_err(&spi->dev, "MCU reset / select mux write failed\n");
+   ret = sx1301_field_write(priv, select_mux, 0);
+   if (ret)
return ret;
-   }
 
-   ret = sx1301_write(spi, REG_MCU_PROM_ADDR, 0);
-   if (ret) {
-   dev_err(&spi->dev, "MCU prom addr write failed\n");
+   /* Load firmware into the data register */
+   ret = regmap_write(priv->regmap, SX1301_MPA, 0);
+   if (ret)
return ret;
-   }
 
-   ret = sx1301_write_burst(spi, REG_MCU_PROM_DATA, data, len);
+   ret = sx1301_write_burst(priv->spi, REG_MCU_PROM_DATA, fw->data, 
fw->size);
if (ret) {
-   dev_err(&spi->dev, "MCU prom data write failed\n");
+   dev_err(priv->dev, "MCU prom data write failed\n");
return ret;
}
 
-   ret = sx1301_read(spi, REG_MCU_PROM_DATA, &val);
+   ret = regmap_read(priv->regmap, SX1301_MPD, &read);
if (ret) {
-   dev_err(&spi->dev, "MCU prom data dummy read failed\n");
+   dev_err(priv->dev, "MCU prom data dummy read failed\n");
return ret;
}
 
-   buf = kzalloc(len, GFP_KERNEL);
+   buf = devm_kzalloc(priv->dev, fw->size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
 
-   ret = sx1301_read_burst(spi, REG_MCU_PROM_DATA, buf, len);
+   ret = sx1301_read_burst(priv->spi, REG_MCU_PROM_DATA, buf, fw->size);
if (ret) {
-   dev_err(&spi->dev, "MCU prom data read failed\n");
-   kfree(buf);
+   dev_err(priv->dev, "MCU prom data read failed\n");
return ret;
}
 
-   if (memcmp(data, buf, len)) {
-   dev_err(&spi->dev, "MCU prom data read does not match data 
written\n");
-   kfree(buf);
+   if (memcmp(fw->data, buf, fw->size)) {
+   dev_err(priv->dev, "MCU prom data read does not match data 
written\n");
return -ENXIO;
}
 
-   kfree(buf);
+   devm_kfree(priv->dev, buf);
 
-   ret = sx1301_page_read(spi, 0, REG_0_MCU, &val);
-   if (ret) {
-   dev_err(&spi->dev, "MCU read (1) failed\n");
-   return ret;
-   }
-
-   val |= select_mux;
-
-   ret = sx1301_page_write(spi, 0, REG_0_MCU, val)

[PATCH v5] leds: trigger: Introduce a NETDEV trigger

2017-12-10 Thread Ben Whitten
This commit introduces a NETDEV trigger for named device
activity. Available triggers are link, rx, and tx.

Signed-off-by: Ben Whitten 

---
Changes in v5:
Adjust header comment style to be consistent
Changes in v4:
Adopt SPDX licence header
Changes in v3:
Cancel the software blink prior to a oneshot re-queue
Changes in v2:
Sort includes and redate documentation
Correct licence
Remove macro and replace with generic function using enums
Convert blink logic in stats work to use led_blink_oneshot
Uses configured brightness instead of FULL
---
 .../ABI/testing/sysfs-class-led-trigger-netdev |  45 ++
 drivers/leds/trigger/Kconfig   |   7 +
 drivers/leds/trigger/Makefile  |   1 +
 drivers/leds/trigger/ledtrig-netdev.c  | 496 +
 4 files changed, 549 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-led-trigger-netdev
 create mode 100644 drivers/leds/trigger/ledtrig-netdev.c

diff --git a/Documentation/ABI/testing/sysfs-class-led-trigger-netdev 
b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
new file mode 100644
index 000..451af6d
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
@@ -0,0 +1,45 @@
+What:  /sys/class/leds//device_name
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Specifies the network device name to monitor.
+
+What:  /sys/class/leds//interval
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Specifies the duration of the LED blink in milliseconds.
+   Defaults to 50 ms.
+
+What:  /sys/class/leds//link
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Signal the link state of the named network device.
+   If set to 0 (default), the LED's normal state is off.
+   If set to 1, the LED's normal state reflects the link state
+   of the named network device.
+   Setting this value also immediately changes the LED state.
+
+What:  /sys/class/leds//tx
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Signal transmission of data on the named network device.
+   If set to 0 (default), the LED will not blink on transmission.
+   If set to 1, the LED will blink for the milliseconds specified
+   in interval to signal transmission.
+
+What:  /sys/class/leds//rx
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Signal reception of data on the named network device.
+   If set to 0 (default), the LED will not blink on reception.
+   If set to 1, the LED will blink for the milliseconds specified
+   in interval to signal reception.
diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig
index 3f9ddb9..4ec1853 100644
--- a/drivers/leds/trigger/Kconfig
+++ b/drivers/leds/trigger/Kconfig
@@ -126,4 +126,11 @@ config LEDS_TRIGGER_PANIC
  a different trigger.
  If unsure, say Y.
 
+config LEDS_TRIGGER_NETDEV
+   tristate "LED Netdev Trigger"
+   depends on NET && LEDS_TRIGGERS
+   help
+ This allows LEDs to be controlled by network device activity.
+ If unsure, say Y.
+
 endif # LEDS_TRIGGERS
diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile
index 9f2e868..59e163d 100644
--- a/drivers/leds/trigger/Makefile
+++ b/drivers/leds/trigger/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
 obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT)   += ledtrig-transient.o
 obj-$(CONFIG_LEDS_TRIGGER_CAMERA)  += ledtrig-camera.o
 obj-$(CONFIG_LEDS_TRIGGER_PANIC)   += ledtrig-panic.o
+obj-$(CONFIG_LEDS_TRIGGER_NETDEV)  += ledtrig-netdev.o
diff --git a/drivers/leds/trigger/ledtrig-netdev.c 
b/drivers/leds/trigger/ledtrig-netdev.c
new file mode 100644
index 000..6df4781
--- /dev/null
+++ b/drivers/leds/trigger/ledtrig-netdev.c
@@ -0,0 +1,496 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright 2017 Ben Whitten 
+// Copyright 2007 Oliver Jowett 
+//
+// LED Kernel Netdev Trigger
+//
+// Toggles the LED to reflect the link and traffic state of a named net device
+//
+// Derived from ledtrig-timer.c which is:
+//  Copyright 2005-2006 Openedhand Ltd.
+//  Author: Richard Purdie 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "../leds.h"
+
+/*
+ * Configurable sysfs attributes:
+ *
+ * device_name - network device name to monitor
+ * interval - duration of LED blink, in milliseconds
+ * link -  LED's normal state reflects whether 

Re: [PATCH v4] leds: trigger: Introduce a NETDEV trigger

2017-12-10 Thread Ben Whitten
Hi Jacek,

On 10 December 2017 at 18:31, Jacek Anaszewski
 wrote:
> Hi Ben,
>
> Thanks for the update. I have one doubt about comment style
> at the top of the file. Please refer below.
>
> On 12/10/2017 05:24 PM, Ben Whitten wrote:
>> This commit introduces a NETDEV trigger for named device
>> activity. Available triggers are link, rx, and tx.
>>
>> Signed-off-by: Ben Whitten 
>>
>> ---
>> Changes in v4:
>> Adopt SPDX licence header
>> Changes in v3:
>> Cancel the software blink prior to a oneshot re-queue
>> Changes in v2:
>> Sort includes and redate documentation
>> Correct licence
>> Remove macro and replace with generic function using enums
>> Convert blink logic in stats work to use led_blink_oneshot
>> Uses configured brightness instead of FULL
>> ---
>>  .../ABI/testing/sysfs-class-led-trigger-netdev |  45 ++
>>  drivers/leds/trigger/Kconfig   |   7 +
>>  drivers/leds/trigger/Makefile  |   1 +
>>  drivers/leds/trigger/ledtrig-netdev.c  | 498 
>> +
>>  4 files changed, 551 insertions(+)
>>  create mode 100644 Documentation/ABI/testing/sysfs-class-led-trigger-netdev
>>  create mode 100644 drivers/leds/trigger/ledtrig-netdev.c
>>
>> diff --git a/Documentation/ABI/testing/sysfs-class-led-trigger-netdev 
>> b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
>> new file mode 100644
>> index 000..451af6d
>> --- /dev/null
>> +++ b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
>> @@ -0,0 +1,45 @@
>> +What:/sys/class/leds//device_name
>> +Date:Dec 2017
>> +KernelVersion:   4.16
>> +Contact: linux-l...@vger.kernel.org
>> +Description:
>> + Specifies the network device name to monitor.
>> +
>> +What:/sys/class/leds//interval
>> +Date:Dec 2017
>> +KernelVersion:   4.16
>> +Contact: linux-l...@vger.kernel.org
>> +Description:
>> + Specifies the duration of the LED blink in milliseconds.
>> + Defaults to 50 ms.
>> +
>> +What:/sys/class/leds//link
>> +Date:Dec 2017
>> +KernelVersion:   4.16
>> +Contact: linux-l...@vger.kernel.org
>> +Description:
>> + Signal the link state of the named network device.
>> + If set to 0 (default), the LED's normal state is off.
>> + If set to 1, the LED's normal state reflects the link state
>> + of the named network device.
>> + Setting this value also immediately changes the LED state.
>> +
>> +What:/sys/class/leds//tx
>> +Date:Dec 2017
>> +KernelVersion:   4.16
>> +Contact: linux-l...@vger.kernel.org
>> +Description:
>> + Signal transmission of data on the named network device.
>> + If set to 0 (default), the LED will not blink on transmission.
>> + If set to 1, the LED will blink for the milliseconds specified
>> + in interval to signal transmission.
>> +
>> +What:/sys/class/leds//rx
>> +Date:Dec 2017
>> +KernelVersion:   4.16
>> +Contact: linux-l...@vger.kernel.org
>> +Description:
>> + Signal reception of data on the named network device.
>> + If set to 0 (default), the LED will not blink on reception.
>> + If set to 1, the LED will blink for the milliseconds specified
>> + in interval to signal reception.
>> diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig
>> index 3f9ddb9..4ec1853 100644
>> --- a/drivers/leds/trigger/Kconfig
>> +++ b/drivers/leds/trigger/Kconfig
>> @@ -126,4 +126,11 @@ config LEDS_TRIGGER_PANIC
>> a different trigger.
>> If unsure, say Y.
>>
>> +config LEDS_TRIGGER_NETDEV
>> + tristate "LED Netdev Trigger"
>> + depends on NET && LEDS_TRIGGERS
>> + help
>> +   This allows LEDs to be controlled by network device activity.
>> +   If unsure, say Y.
>> +
>>  endif # LEDS_TRIGGERS
>> diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile
>> index 9f2e868..59e163d 100644
>> --- a/drivers/leds/trigger/Makefile
>> +++ b/drivers/leds/trigger/Makefile
>> @@ -11,3 +11,4 @@ obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)   += 
>> ledtrig-default-on.o
>>  obj-$(CONFIG_LEDS_T

[PATCH v4] leds: trigger: Introduce a NETDEV trigger

2017-12-10 Thread Ben Whitten
This commit introduces a NETDEV trigger for named device
activity. Available triggers are link, rx, and tx.

Signed-off-by: Ben Whitten 

---
Changes in v4:
Adopt SPDX licence header
Changes in v3:
Cancel the software blink prior to a oneshot re-queue
Changes in v2:
Sort includes and redate documentation
Correct licence
Remove macro and replace with generic function using enums
Convert blink logic in stats work to use led_blink_oneshot
Uses configured brightness instead of FULL
---
 .../ABI/testing/sysfs-class-led-trigger-netdev |  45 ++
 drivers/leds/trigger/Kconfig   |   7 +
 drivers/leds/trigger/Makefile  |   1 +
 drivers/leds/trigger/ledtrig-netdev.c  | 498 +
 4 files changed, 551 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-led-trigger-netdev
 create mode 100644 drivers/leds/trigger/ledtrig-netdev.c

diff --git a/Documentation/ABI/testing/sysfs-class-led-trigger-netdev 
b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
new file mode 100644
index 000..451af6d
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
@@ -0,0 +1,45 @@
+What:  /sys/class/leds//device_name
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Specifies the network device name to monitor.
+
+What:  /sys/class/leds//interval
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Specifies the duration of the LED blink in milliseconds.
+   Defaults to 50 ms.
+
+What:  /sys/class/leds//link
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Signal the link state of the named network device.
+   If set to 0 (default), the LED's normal state is off.
+   If set to 1, the LED's normal state reflects the link state
+   of the named network device.
+   Setting this value also immediately changes the LED state.
+
+What:  /sys/class/leds//tx
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Signal transmission of data on the named network device.
+   If set to 0 (default), the LED will not blink on transmission.
+   If set to 1, the LED will blink for the milliseconds specified
+   in interval to signal transmission.
+
+What:  /sys/class/leds//rx
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Signal reception of data on the named network device.
+   If set to 0 (default), the LED will not blink on reception.
+   If set to 1, the LED will blink for the milliseconds specified
+   in interval to signal reception.
diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig
index 3f9ddb9..4ec1853 100644
--- a/drivers/leds/trigger/Kconfig
+++ b/drivers/leds/trigger/Kconfig
@@ -126,4 +126,11 @@ config LEDS_TRIGGER_PANIC
  a different trigger.
  If unsure, say Y.
 
+config LEDS_TRIGGER_NETDEV
+   tristate "LED Netdev Trigger"
+   depends on NET && LEDS_TRIGGERS
+   help
+ This allows LEDs to be controlled by network device activity.
+ If unsure, say Y.
+
 endif # LEDS_TRIGGERS
diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile
index 9f2e868..59e163d 100644
--- a/drivers/leds/trigger/Makefile
+++ b/drivers/leds/trigger/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
 obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT)   += ledtrig-transient.o
 obj-$(CONFIG_LEDS_TRIGGER_CAMERA)  += ledtrig-camera.o
 obj-$(CONFIG_LEDS_TRIGGER_PANIC)   += ledtrig-panic.o
+obj-$(CONFIG_LEDS_TRIGGER_NETDEV)  += ledtrig-netdev.o
diff --git a/drivers/leds/trigger/ledtrig-netdev.c 
b/drivers/leds/trigger/ledtrig-netdev.c
new file mode 100644
index 000..3d24573
--- /dev/null
+++ b/drivers/leds/trigger/ledtrig-netdev.c
@@ -0,0 +1,498 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright 2017 Ben Whitten 
+// Copyright 2007 Oliver Jowett 
+/*
+ * LED Kernel Netdev Trigger
+ *
+ * Toggles the LED to reflect the link and traffic state of a named net device
+ *
+ * Derived from ledtrig-timer.c which is:
+ *  Copyright 2005-2006 Openedhand Ltd.
+ *  Author: Richard Purdie 
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "../leds.h"
+
+/*
+ * Configurable sysfs attributes:
+ *
+ * device_name - network device name to monitor
+ * interval - duration of LED blink, in milliseconds
+ * link -  LED's normal state reflects whether the link is up
+ * (has carrier) or not
+ * 

Re: [PATCH v3] leds: trigger: Introduce a NETDEV trigger

2017-12-07 Thread Ben Whitten
Philippe,

On 7 December 2017 at 13:01, Philippe Ombredanne  wrote:
> Ben,
>
> On Thu, Dec 7, 2017 at 12:46 PM, Ben Whitten  wrote:
>> From: Ben Whitten 
>>
>> This commit introduces a NETDEV trigger for named device
>> activity. Available triggers are link, rx, and tx.
>>
>> Signed-off-by: Ben Whitten 
> []
>> --- /dev/null
>> +++ b/drivers/leds/trigger/ledtrig-netdev.c
>> @@ -0,0 +1,503 @@
>> +/*
>> + * LED Kernel Netdev Trigger
>> + *
>> + * Toggles the LED to reflect the link and traffic state of a named net 
>> device
>> + *
>> + * Copyright 2017 Ben Whitten 
>> + *
>> + * Copyright 2007 Oliver Jowett 
>> + *
>> + * Derived from ledtrig-timer.c which is:
>> + *  Copyright 2005-2006 Openedhand Ltd.
>> + *  Author: Richard Purdie 
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + */
>
> Have you considered using the new SPDX id instead ? See Thomas doc
> patches and Greg and Linus comments on the topic
> Here this would likely come out this way (yes, using a C++ comment at the 
> top):
>
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * LED Kernel Netdev Trigger
>> + *
>> + * Toggles the LED to reflect the link and traffic state of a named net 
>> device
>> + *
>> + * Copyright 2017 Ben Whitten 
>> + *
>> + * Copyright 2007 Oliver Jowett 
>> + *
>> + * Derived from ledtrig-timer.c which is:
>> + *  Copyright 2005-2006 Openedhand Ltd.
>> + *  Author: Richard Purdie 
>> + *
>> + */
>
>
> This is cleaner and simpler, don't you think?

Much cleaner. Thank you for the suggestion, I was unaware of this.

Kind regards,
Ben Whitten


[PATCH v3] leds: trigger: Introduce a NETDEV trigger

2017-12-07 Thread Ben Whitten
From: Ben Whitten 

This commit introduces a NETDEV trigger for named device
activity. Available triggers are link, rx, and tx.

Signed-off-by: Ben Whitten 

---
Changes in v3:
Cancel the software blink prior to a oneshot re-queue
Changes in v2:
Sort includes and redate documentation
Correct licence
Remove macro and replace with generic function using enums
Convert blink logic in stats work to use led_blink_oneshot
Uses configured brightness instead of FULL
---
 .../ABI/testing/sysfs-class-led-trigger-netdev |  45 ++
 drivers/leds/trigger/Kconfig   |   7 +
 drivers/leds/trigger/Makefile  |   1 +
 drivers/leds/trigger/ledtrig-netdev.c  | 503 +
 4 files changed, 556 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-led-trigger-netdev
 create mode 100644 drivers/leds/trigger/ledtrig-netdev.c

diff --git a/Documentation/ABI/testing/sysfs-class-led-trigger-netdev 
b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
new file mode 100644
index 000..451af6d
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
@@ -0,0 +1,45 @@
+What:  /sys/class/leds//device_name
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Specifies the network device name to monitor.
+
+What:  /sys/class/leds//interval
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Specifies the duration of the LED blink in milliseconds.
+   Defaults to 50 ms.
+
+What:  /sys/class/leds//link
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Signal the link state of the named network device.
+   If set to 0 (default), the LED's normal state is off.
+   If set to 1, the LED's normal state reflects the link state
+   of the named network device.
+   Setting this value also immediately changes the LED state.
+
+What:  /sys/class/leds//tx
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Signal transmission of data on the named network device.
+   If set to 0 (default), the LED will not blink on transmission.
+   If set to 1, the LED will blink for the milliseconds specified
+   in interval to signal transmission.
+
+What:  /sys/class/leds//rx
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Signal reception of data on the named network device.
+   If set to 0 (default), the LED will not blink on reception.
+   If set to 1, the LED will blink for the milliseconds specified
+   in interval to signal reception.
diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig
index 3f9ddb9..4ec1853 100644
--- a/drivers/leds/trigger/Kconfig
+++ b/drivers/leds/trigger/Kconfig
@@ -126,4 +126,11 @@ config LEDS_TRIGGER_PANIC
  a different trigger.
  If unsure, say Y.
 
+config LEDS_TRIGGER_NETDEV
+   tristate "LED Netdev Trigger"
+   depends on NET && LEDS_TRIGGERS
+   help
+ This allows LEDs to be controlled by network device activity.
+ If unsure, say Y.
+
 endif # LEDS_TRIGGERS
diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile
index 9f2e868..59e163d 100644
--- a/drivers/leds/trigger/Makefile
+++ b/drivers/leds/trigger/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
 obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT)   += ledtrig-transient.o
 obj-$(CONFIG_LEDS_TRIGGER_CAMERA)  += ledtrig-camera.o
 obj-$(CONFIG_LEDS_TRIGGER_PANIC)   += ledtrig-panic.o
+obj-$(CONFIG_LEDS_TRIGGER_NETDEV)  += ledtrig-netdev.o
diff --git a/drivers/leds/trigger/ledtrig-netdev.c 
b/drivers/leds/trigger/ledtrig-netdev.c
new file mode 100644
index 000..fb36b08
--- /dev/null
+++ b/drivers/leds/trigger/ledtrig-netdev.c
@@ -0,0 +1,503 @@
+/*
+ * LED Kernel Netdev Trigger
+ *
+ * Toggles the LED to reflect the link and traffic state of a named net device
+ *
+ * Copyright 2017 Ben Whitten 
+ *
+ * Copyright 2007 Oliver Jowett 
+ *
+ * Derived from ledtrig-timer.c which is:
+ *  Copyright 2005-2006 Openedhand Ltd.
+ *  Author: Richard Purdie 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "../leds.h"
+
+/*
+ * Configurable sysfs attributes:
+ *
+ * device_name - network device name to monitor
+ * interval - 

Re: [PATCH/RFC v2] leds: trigger: Introduce a NETDEV trigger

2017-12-07 Thread Ben Whitten
On 6 December 2017 at 20:07, Ben Whitten  wrote:
> Hi Jacek,
>
> On 5 December 2017 at 20:38, Jacek Anaszewski
>  wrote:
>> Hi Ben,
>>
>> On 12/05/2017 12:19 PM, Ben Whitten wrote:
>>> From: Ben Whitten 
>>>
>>> The patch was converted to led_blink_oneshot, in doing so we find that the
>>> behaviour has changed. As I dont want to break 'userspace' led behaviour 
>>> this
>>> patch shouldn't be merged as is. Open to suggestions.
>>>
>>> Given an interval of 50ms and heavy throughput, the previous implementation
>>> produced a blink with 100ms period and 50% dutycycle. The led_blink_oneshot
>>> version produces a blink with 140ms period and 57% dutycycle.
>>
>> Please check if the LED class driver you're testing the trigger with
>> implements blink_set op. If yes it would be good to check if it doesn't
>> align the delay intervals to the hardware capabilities instead of
>> failing and relying on a LED core software blink fallback.
>
> The led are using gpio-led set from device tree on an embedded system, sama5
> based. So as far as I can tell blink_op is NULL in this case and it
> then relies on
> software for the blink in the form of timers.
> I assume its the jiffies playing a part here, taking a jiffy or two to
> queue up a flash
> may add 10ms to the desired 50ms delay_on/delay_off that I am seeing. Then the
> extra time may be due to the stats workqueue not aligning with the
> blink timer to
> kick it off again.

I have found a solution. As oneshot appears run in software regardless
based on the
check in led_blink_setup, cancelling the software timer in the stats
worker allows for
an immidiate requeue. This brings the period back down to 110ms and looks
identical to the previous implementation.

Best regards,
Ben


Re: [PATCH/RFC v2] leds: trigger: Introduce a NETDEV trigger

2017-12-06 Thread Ben Whitten
Hi Jacek,

On 5 December 2017 at 20:38, Jacek Anaszewski
 wrote:
> Hi Ben,
>
> On 12/05/2017 12:19 PM, Ben Whitten wrote:
>> From: Ben Whitten 
>>
>> The patch was converted to led_blink_oneshot, in doing so we find that the
>> behaviour has changed. As I dont want to break 'userspace' led behaviour this
>> patch shouldn't be merged as is. Open to suggestions.
>>
>> Given an interval of 50ms and heavy throughput, the previous implementation
>> produced a blink with 100ms period and 50% dutycycle. The led_blink_oneshot
>> version produces a blink with 140ms period and 57% dutycycle.
>
> Please check if the LED class driver you're testing the trigger with
> implements blink_set op. If yes it would be good to check if it doesn't
> align the delay intervals to the hardware capabilities instead of
> failing and relying on a LED core software blink fallback.

The led are using gpio-led set from device tree on an embedded system, sama5
based. So as far as I can tell blink_op is NULL in this case and it
then relies on
software for the blink in the form of timers.
I assume its the jiffies playing a part here, taking a jiffy or two to
queue up a flash
may add 10ms to the desired 50ms delay_on/delay_off that I am seeing. Then the
extra time may be due to the stats workqueue not aligning with the
blink timer to
kick it off again.

Best regards,
Ben


[PATCH/RFC v2] leds: trigger: Introduce a NETDEV trigger

2017-12-05 Thread Ben Whitten
From: Ben Whitten 

This commit introduces a NETDEV trigger for named device
activity. Available triggers are link, rx, and tx.

Signed-off-by: Ben Whitten 

---
Changes in v2:
Sort includes and redate documentation
Correct licence
Remove macro and replace with generic function using enums
Convert blink logic in stats work to use led_blink_oneshot
Uses configured brightness instead of FULL
---
 .../ABI/testing/sysfs-class-led-trigger-netdev |  45 ++
 drivers/leds/trigger/Kconfig   |   7 +
 drivers/leds/trigger/Makefile  |   1 +
 drivers/leds/trigger/ledtrig-netdev.c  | 507 +
 4 files changed, 560 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-led-trigger-netdev
 create mode 100644 drivers/leds/trigger/ledtrig-netdev.c

diff --git a/Documentation/ABI/testing/sysfs-class-led-trigger-netdev 
b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
new file mode 100644
index 000..451af6d
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
@@ -0,0 +1,45 @@
+What:  /sys/class/leds//device_name
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Specifies the network device name to monitor.
+
+What:  /sys/class/leds//interval
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Specifies the duration of the LED blink in milliseconds.
+   Defaults to 50 ms.
+
+What:  /sys/class/leds//link
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Signal the link state of the named network device.
+   If set to 0 (default), the LED's normal state is off.
+   If set to 1, the LED's normal state reflects the link state
+   of the named network device.
+   Setting this value also immediately changes the LED state.
+
+What:  /sys/class/leds//tx
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Signal transmission of data on the named network device.
+   If set to 0 (default), the LED will not blink on transmission.
+   If set to 1, the LED will blink for the milliseconds specified
+   in interval to signal transmission.
+
+What:  /sys/class/leds//rx
+Date:  Dec 2017
+KernelVersion: 4.16
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Signal reception of data on the named network device.
+   If set to 0 (default), the LED will not blink on reception.
+   If set to 1, the LED will blink for the milliseconds specified
+   in interval to signal reception.
diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig
index 3f9ddb9..4ec1853 100644
--- a/drivers/leds/trigger/Kconfig
+++ b/drivers/leds/trigger/Kconfig
@@ -126,4 +126,11 @@ config LEDS_TRIGGER_PANIC
  a different trigger.
  If unsure, say Y.
 
+config LEDS_TRIGGER_NETDEV
+   tristate "LED Netdev Trigger"
+   depends on NET && LEDS_TRIGGERS
+   help
+ This allows LEDs to be controlled by network device activity.
+ If unsure, say Y.
+
 endif # LEDS_TRIGGERS
diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile
index 9f2e868..59e163d 100644
--- a/drivers/leds/trigger/Makefile
+++ b/drivers/leds/trigger/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
 obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT)   += ledtrig-transient.o
 obj-$(CONFIG_LEDS_TRIGGER_CAMERA)  += ledtrig-camera.o
 obj-$(CONFIG_LEDS_TRIGGER_PANIC)   += ledtrig-panic.o
+obj-$(CONFIG_LEDS_TRIGGER_NETDEV)  += ledtrig-netdev.o
diff --git a/drivers/leds/trigger/ledtrig-netdev.c 
b/drivers/leds/trigger/ledtrig-netdev.c
new file mode 100644
index 000..3b6075d
--- /dev/null
+++ b/drivers/leds/trigger/ledtrig-netdev.c
@@ -0,0 +1,507 @@
+/*
+ * LED Kernel Netdev Trigger
+ *
+ * Toggles the LED to reflect the link and traffic state of a named net device
+ *
+ * Copyright 2017 Ben Whitten 
+ *
+ * Copyright 2007 Oliver Jowett 
+ *
+ * Derived from ledtrig-timer.c which is:
+ *  Copyright 2005-2006 Openedhand Ltd.
+ *  Author: Richard Purdie 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * Configurable sysfs attributes:
+ *
+ * device_name - network device name to monitor
+ * interval - duration of LED blink, in milliseconds
+ * link -  LED's normal state reflects whether the li

[PATCH/RFC v2] leds: trigger: Introduce a NETDEV trigger

2017-12-05 Thread Ben Whitten
From: Ben Whitten 

The patch was converted to led_blink_oneshot, in doing so we find that the
behaviour has changed. As I dont want to break 'userspace' led behaviour this
patch shouldn't be merged as is. Open to suggestions.

Given an interval of 50ms and heavy throughput, the previous implementation
produced a blink with 100ms period and 50% dutycycle. The led_blink_oneshot
version produces a blink with 140ms period and 57% dutycycle.
I assume a fudge factor on the oneshot delay to bring the period back to 100ms
would be device specific so not suitable.

Kind regards,
Ben Whitten (1):
  leds: trigger: Introduce a NETDEV trigger

 .../ABI/testing/sysfs-class-led-trigger-netdev |  45 ++
 drivers/leds/trigger/Kconfig   |   7 +
 drivers/leds/trigger/Makefile  |   1 +
 drivers/leds/trigger/ledtrig-netdev.c  | 507 +
 4 files changed, 560 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-led-trigger-netdev
 create mode 100644 drivers/leds/trigger/ledtrig-netdev.c

-- 
2.7.4



Re: [PATCH] leds: trigger: Introduce a NETDEV trigger

2017-12-04 Thread Ben Whitten
   \
>> + if (state)  \
>> + set_bit(LED_BLINK_##field, &trigger_data->mode);\
>> + else\
>> + clear_bit(LED_BLINK_##field, &trigger_data->mode);  \
>> + \
>> + set_baseline_state(trigger_data);   \
>> + \
>> + return size;\
>> +}\
>> +static DEVICE_ATTR_RW(field);
>
> In order to get rid of this macro and avoid the need for camel case
> macro name we could have one function that would accept an enum e.g.
>
> enum netdev_led_attr {
> NETDEV_ATTR_LINK,
> NETDEV_ATTR_RX,
> NETDEV_ATTR_TX
> };
>
> The function would be called from each sysfs attr callback with the
> related enum, and would alter the state of the related bit.
>

I was aiming for a bit of code de duplication, but it ended up a mess.
Fixed as per your suggestion.

--
Kind regards,
Ben Whitten


[PATCH] leds: trigger: Introduce a NETDEV trigger

2017-11-28 Thread Ben Whitten
This commit introduces a NETDEV trigger for named device
activity. Available triggers are link, rx, and tx.

Signed-off-by: Ben Whitten 
---
 .../ABI/testing/sysfs-class-led-trigger-netdev |  45 +++
 drivers/leds/trigger/Kconfig   |   7 +
 drivers/leds/trigger/Makefile  |   1 +
 drivers/leds/trigger/ledtrig-netdev.c  | 428 +
 4 files changed, 481 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-led-trigger-netdev
 create mode 100644 drivers/leds/trigger/ledtrig-netdev.c

diff --git a/Documentation/ABI/testing/sysfs-class-led-trigger-netdev 
b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
new file mode 100644
index 000..2c917df
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
@@ -0,0 +1,45 @@
+What:  /sys/class/leds//device_name
+Date:  Nov 2017
+KernelVersion: 4.15
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Specifies the network device name to monitor.
+
+What:  /sys/class/leds//interval
+Date:  Nov 2017
+KernelVersion: 4.15
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Specifies the duration of the LED blink in milliseconds.
+   Defaults to 50 ms.
+
+What:  /sys/class/leds//link
+Date:  Nov 2017
+KernelVersion: 4.15
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Signal the link state of the named network device.
+   If set to 0 (default), the LED's normal state is off.
+   If set to 1, the LED's normal state reflects the link state
+   of the named network device.
+   Setting this value also immediately changes the LED state.
+
+What:  /sys/class/leds//tx
+Date:  Nov 2017
+KernelVersion: 4.15
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Signal transmission of data on the named network device.
+   If set to 0 (default), the LED will not blink on transmission.
+   If set to 1, the LED will blink for the milliseconds specified
+   in interval to signal transmission.
+
+What:  /sys/class/leds//rx
+Date:  Nov 2017
+KernelVersion: 4.15
+Contact:   linux-l...@vger.kernel.org
+Description:
+   Signal reception of data on the named network device.
+   If set to 0 (default), the LED will not blink on reception.
+   If set to 1, the LED will blink for the milliseconds specified
+   in interval to signal reception.
diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig
index 3f9ddb9..4ec1853 100644
--- a/drivers/leds/trigger/Kconfig
+++ b/drivers/leds/trigger/Kconfig
@@ -126,4 +126,11 @@ config LEDS_TRIGGER_PANIC
  a different trigger.
  If unsure, say Y.
 
+config LEDS_TRIGGER_NETDEV
+   tristate "LED Netdev Trigger"
+   depends on NET && LEDS_TRIGGERS
+   help
+ This allows LEDs to be controlled by network device activity.
+ If unsure, say Y.
+
 endif # LEDS_TRIGGERS
diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile
index 9f2e868..59e163d 100644
--- a/drivers/leds/trigger/Makefile
+++ b/drivers/leds/trigger/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
 obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT)   += ledtrig-transient.o
 obj-$(CONFIG_LEDS_TRIGGER_CAMERA)  += ledtrig-camera.o
 obj-$(CONFIG_LEDS_TRIGGER_PANIC)   += ledtrig-panic.o
+obj-$(CONFIG_LEDS_TRIGGER_NETDEV)  += ledtrig-netdev.o
diff --git a/drivers/leds/trigger/ledtrig-netdev.c 
b/drivers/leds/trigger/ledtrig-netdev.c
new file mode 100644
index 000..2953b41
--- /dev/null
+++ b/drivers/leds/trigger/ledtrig-netdev.c
@@ -0,0 +1,428 @@
+/*
+ * LED Kernel Netdev Trigger
+ *
+ * Toggles the LED to reflect the link and traffic state of a named net device
+ *
+ * Copyright 2017 Ben Whitten 
+ *
+ * Copyright 2007 Oliver Jowett 
+ *
+ * Derived from ledtrig-timer.c which is:
+ *  Copyright 2005-2006 Openedhand Ltd.
+ *  Author: Richard Purdie 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * Configurable sysfs attributes:
+ *
+ * device_name - network device name to monitor
+ *
+ * interval - duration of LED blink, in milliseconds
+ *
+ * link -  LED's normal state reflects whether the link is up
+ * (has carrier) or not
+ * tx -  LED blinks on transmitted data
+ * rx -  LED blinks on receive data
+ *
+ */
+
+struct led_netdev_data {
+   spinlock_t lock;
+
+   struct delayed_work work;
+   struct notifier

[PATCH] Introduce a NETDEV LED trigger

2017-11-28 Thread Ben Whitten
It's quite useful to be able to trigger LEDs based on network activity,
similar mechanisms exist in routers and gateway devices.
I am looking to mainline a patch that has existed out of tree for
some time in OpenWRT/LEDE.
The patch has been updated and restructured and most of the issues raised
in the initial submission have been addressed [1].

I am also including the netdev mailing list as it was suggested previously
that if there is no activity the interval will still run and is wasteful

[1] https://lkml.org/lkml/2010/11/14/116

Ben Whitten (1):
  leds: trigger: Introduce a NETDEV trigger

 .../ABI/testing/sysfs-class-led-trigger-netdev |  45 +++
 drivers/leds/trigger/Kconfig   |   7 +
 drivers/leds/trigger/Makefile  |   1 +
 drivers/leds/trigger/ledtrig-netdev.c  | 428 +
 4 files changed, 481 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-led-trigger-netdev
 create mode 100644 drivers/leds/trigger/ledtrig-netdev.c

-- 
2.7.4