[PATCH] staging: iio: ad7192: Use the dedicated reset function

2017-09-14 Thread Stefan Popa
SPI host drivers can use DMA to transfer data, so the buffer should be properly 
allocated.
Keeping it on the stack could cause an undefined behavior.

The dedicated reset function solves this issue.

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
 drivers/staging/iio/adc/ad7192.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
index d11c6de..6150d27 100644
--- a/drivers/staging/iio/adc/ad7192.c
+++ b/drivers/staging/iio/adc/ad7192.c
@@ -223,11 +223,9 @@ static int ad7192_setup(struct ad7192_state *st,
struct iio_dev *indio_dev = spi_get_drvdata(st->sd.spi);
unsigned long long scale_uv;
int i, ret, id;
-   u8 ones[6];
 
/* reset the serial interface */
-   memset(, 0xFF, 6);
-   ret = spi_write(st->sd.spi, , 6);
+   ret = ad_sd_reset(>sd, 48);
if (ret < 0)
goto out;
usleep_range(500, 1000); /* Wait for at least 500us */
-- 
2.7.4



[PATCH v2 2/2] iio:dac:ad5686: Add AD5681R/AD5682R/AD5683/AD5683R support

2018-05-18 Thread Stefan Popa
The AD5681R/AD5682R/AD5683/AD5683R are a family of one channel DACs with
12-bit, 14-bit and 16-bit precision respectively. The devices have either
no built-in reference, or built-in 2.5V reference.

These devices are similar to AD5691R/AD5692R/AD5693/AD5693R except
with a few notable differences:
 * they use the SPI interface instead of I2C
 * in the write control register, DB18 and DB17 are used for setting the
   power mode, while DB16 is the REF bit. This is why a new regmap type
   was defined and checked accordingly.
 * the shift register is 24 bits wide, the first four bits are the command
   bits followed by the data bits. As the data comprises of 20-bit, 18-bit
   or 16-bit input code, this means that 4 LSB bits are don't care. This is
   why the data needs to be shifted on the left with four bits. Therefore,
   AD5683_REGMAP is checked inside a switch case in the ad5686_spi_write()
   function. On the other hand, similar devices such as AD5693R family,
   have the 4 MSB command bits followed by 4 don't care bits.

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5683R_5682R_5681R_5683.pdf

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
- Nothing changed, just to follow the patch set version.

 drivers/iio/dac/ad5686-spi.c | 42 ++
 drivers/iio/dac/ad5686.c | 32 
 drivers/iio/dac/ad5686.h |  8 
 3 files changed, 74 insertions(+), 8 deletions(-)

diff --git a/drivers/iio/dac/ad5686-spi.c b/drivers/iio/dac/ad5686-spi.c
index 6bb09e9..1df9143 100644
--- a/drivers/iio/dac/ad5686-spi.c
+++ b/drivers/iio/dac/ad5686-spi.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * AD5672R, AD5676, AD5676R, AD5684, AD5684R, AD5684R, AD5685R, AD5686, AD5686R
+ * AD5672R, AD5676, AD5676R, AD5681R, AD5682R, AD5683, AD5683R,
+ * AD5684, AD5684R, AD5685R, AD5686, AD5686R
  * Digital to analog converters driver
  *
  * Copyright 2018 Analog Devices Inc.
@@ -15,12 +16,27 @@ static int ad5686_spi_write(struct ad5686_state *st,
u8 cmd, u8 addr, u16 val)
 {
struct spi_device *spi = to_spi_device(st->dev);
-
-   st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
- AD5686_ADDR(addr) |
- val);
-
-   return spi_write(spi, >data[0].d8[1], 3);
+   u8 tx_len, *buf;
+
+   switch (st->chip_info->regmap_type) {
+   case AD5683_REGMAP:
+   st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
+ AD5683_DATA(val));
+   buf = >data[0].d8[1];
+   tx_len = 3;
+   break;
+   case AD5686_REGMAP:
+   st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
+ AD5686_ADDR(addr) |
+ val);
+   buf = >data[0].d8[1];
+   tx_len = 3;
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   return spi_write(spi, buf, tx_len);
 }
 
 static int ad5686_spi_read(struct ad5686_state *st, u8 addr)
@@ -37,9 +53,15 @@ static int ad5686_spi_read(struct ad5686_state *st, u8 addr)
},
};
struct spi_device *spi = to_spi_device(st->dev);
+   u8 cmd = 0;
int ret;
 
-   st->data[0].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_READBACK_ENABLE) |
+   if (st->chip_info->regmap_type == AD5686_REGMAP)
+   cmd = AD5686_CMD_READBACK_ENABLE;
+   else if (st->chip_info->regmap_type == AD5683_REGMAP)
+   cmd = AD5686_CMD_READBACK_ENABLE_V2;
+
+   st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
  AD5686_ADDR(addr));
st->data[1].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP));
 
@@ -67,6 +89,10 @@ static const struct spi_device_id ad5686_spi_id[] = {
{"ad5672r", ID_AD5672R},
{"ad5676", ID_AD5676},
{"ad5676r", ID_AD5676R},
+   {"ad5681r", ID_AD5681R},
+   {"ad5682r", ID_AD5682R},
+   {"ad5683", ID_AD5683},
+   {"ad5683r", ID_AD5683R},
{"ad5684", ID_AD5684},
{"ad5684r", ID_AD5684R},
{"ad5685", ID_AD5685R}, /* Does not exist */
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 1fc0c56..e136f0f 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -83,6 +83,10 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev 
*indio_dev,
st->pwr_down_mask &= ~(0x3 << (chan->channel * 2));
 
switch (st->chip_info->regmap_type) {
+   case AD5683_REGMAP:
+   shift = 13;
+   ref_bit_msk = AD5683_REF_BIT_MSK;
+  

[PATCH v2 1/2] iio:dac:ad5686: Add AD5691R/AD5692R/AD5693/AD5693R support

2018-05-18 Thread Stefan Popa
The AD5691R/AD5692R/AD5693/AD5693R are a family of one channel DACs with
12-bit, 14-bit and 16-bit precision respectively. The devices have either
no built-in reference, or built-in 2.5V reference.

These devices are pretty similar to AD5671R/AD5675R and
AD5694/AD5694R/AD5695R/AD5696/AD5696R, except that they have one channel.
Another difference is that they use a write control register(addr 0x04) for
setting the power down modes and the internal reference instead of separate
registers for each function.

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5693R_5692R_5691R_5693.pdf

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
- Removed the initialization for ref_bit_msk and shift variables
  from ad5686_write_dac_powerdown() and ad5686_probe().
- Added the the missing default case from
  ad5686_write_dac_powerdown() and ad5686_probe().

 drivers/iio/dac/ad5686.c | 93 +---
 drivers/iio/dac/ad5686.h | 16 
 drivers/iio/dac/ad5696-i2c.c |  7 +++-
 3 files changed, 109 insertions(+), 7 deletions(-)

diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 89c5f08..1fc0c56 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -70,6 +70,8 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev 
*indio_dev,
bool readin;
int ret;
struct ad5686_state *st = iio_priv(indio_dev);
+   unsigned int val, ref_bit_msk;
+   u8 shift;
 
ret = strtobool(buf, );
if (ret)
@@ -80,9 +82,24 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev 
*indio_dev,
else
st->pwr_down_mask &= ~(0x3 << (chan->channel * 2));
 
-   ret = st->write(st, AD5686_CMD_POWERDOWN_DAC, 0,
-   st->pwr_down_mask & st->pwr_down_mode);
+   switch (st->chip_info->regmap_type) {
+   case AD5686_REGMAP:
+   shift = 0;
+   ref_bit_msk = 0;
+   break;
+   case AD5693_REGMAP:
+   shift = 13;
+   ref_bit_msk = AD5693_REF_BIT_MSK;
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   val = ((st->pwr_down_mask & st->pwr_down_mode) << shift);
+   if (!st->use_internal_vref)
+   val |= ref_bit_msk;
 
+   ret = st->write(st, AD5686_CMD_POWERDOWN_DAC, 0, val);
 
return ret ? ret : len;
 }
@@ -175,6 +192,11 @@ static const struct iio_chan_spec_ext_info 
ad5686_ext_info[] = {
.ext_info = ad5686_ext_info,\
 }
 
+#define DECLARE_AD5693_CHANNELS(name, bits, _shift)\
+static struct iio_chan_spec name[] = { \
+   AD5868_CHANNEL(0, 0, bits, _shift), \
+}
+
 #define DECLARE_AD5686_CHANNELS(name, bits, _shift)\
 static struct iio_chan_spec name[] = { \
AD5868_CHANNEL(0, 1, bits, _shift), \
@@ -200,72 +222,112 @@ DECLARE_AD5676_CHANNELS(ad5676_channels, 16, 0);
 DECLARE_AD5686_CHANNELS(ad5684_channels, 12, 4);
 DECLARE_AD5686_CHANNELS(ad5685r_channels, 14, 2);
 DECLARE_AD5686_CHANNELS(ad5686_channels, 16, 0);
+DECLARE_AD5693_CHANNELS(ad5693_channels, 16, 0);
+DECLARE_AD5693_CHANNELS(ad5692r_channels, 14, 2);
+DECLARE_AD5693_CHANNELS(ad5691r_channels, 12, 4);
 
 static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
[ID_AD5671R] = {
.channels = ad5672_channels,
.int_vref_mv = 2500,
.num_channels = 8,
+   .regmap_type = AD5686_REGMAP,
},
[ID_AD5672R] = {
.channels = ad5672_channels,
.int_vref_mv = 2500,
.num_channels = 8,
+   .regmap_type = AD5686_REGMAP,
},
[ID_AD5675R] = {
.channels = ad5676_channels,
.int_vref_mv = 2500,
.num_channels = 8,
+   .regmap_type = AD5686_REGMAP,
},
[ID_AD5676] = {
.channels = ad5676_channels,
.num_channels = 8,
+   .regmap_type = AD5686_REGMAP,
},
[ID_AD5676R] = {
.channels = ad5676_channels,
.int_vref_mv = 2500,
.num_channels = 8,
+   .regmap_type = AD5686_REGMAP,
},
[ID_AD5684] = {
.channels = ad5684_channels,
.num_channels = 4,
+   .regmap_type = AD5686_REGMAP,
},
[ID_AD5684R] = {
.channels = ad5684_channels,
.int_vref_mv = 2500,
.num_channels = 4,
+   .regmap_type = AD5686_REGMAP,
},
[ID_AD5685R] = {
.channels = ad5685r_channels,
.int_vref_mv = 2500,

[PATCH 1/2] iio:dac:ad5686: Add AD5691R/AD5692R/AD5693/AD5693R support

2018-05-18 Thread Stefan Popa
The AD5691R/AD5692R/AD5693/AD5693R are a family of one channel DACs with
12-bit, 14-bit and 16-bit precision respectively. The devices have either
no built-in reference, or built-in 2.5V reference.

These devices are pretty similar to AD5671R/AD5675R and
AD5694/AD5694R/AD5695R/AD5696/AD5696R, except that they have one channel.
Another difference is that they use a write control register(addr 0x04) for
setting the power down modes and the internal reference instead of separate
registers for each function.

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5693R_5692R_5691R_5693.pdf

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
 drivers/iio/dac/ad5686.c | 88 +---
 drivers/iio/dac/ad5686.h | 16 
 drivers/iio/dac/ad5696-i2c.c |  7 +++-
 3 files changed, 104 insertions(+), 7 deletions(-)

diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 89c5f08..be803e8 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -70,6 +70,8 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev 
*indio_dev,
bool readin;
int ret;
struct ad5686_state *st = iio_priv(indio_dev);
+   unsigned int val, ref_bit_msk = 0;
+   u8 shift = 0;
 
ret = strtobool(buf, );
if (ret)
@@ -80,9 +82,22 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev 
*indio_dev,
else
st->pwr_down_mask &= ~(0x3 << (chan->channel * 2));
 
-   ret = st->write(st, AD5686_CMD_POWERDOWN_DAC, 0,
-   st->pwr_down_mask & st->pwr_down_mode);
+   switch (st->chip_info->regmap_type) {
+   case AD5686_REGMAP:
+   shift = 0;
+   ref_bit_msk = 0;
+   break;
+   case AD5693_REGMAP:
+   shift = 13;
+   ref_bit_msk = AD5693_REF_BIT_MSK;
+   break;
+   }
 
+   val = ((st->pwr_down_mask & st->pwr_down_mode) << shift);
+   if (!st->use_internal_vref)
+   val |= ref_bit_msk;
+
+   ret = st->write(st, AD5686_CMD_POWERDOWN_DAC, 0, val);
 
return ret ? ret : len;
 }
@@ -175,6 +190,11 @@ static const struct iio_chan_spec_ext_info 
ad5686_ext_info[] = {
.ext_info = ad5686_ext_info,\
 }
 
+#define DECLARE_AD5693_CHANNELS(name, bits, _shift)\
+static struct iio_chan_spec name[] = { \
+   AD5868_CHANNEL(0, 0, bits, _shift), \
+}
+
 #define DECLARE_AD5686_CHANNELS(name, bits, _shift)\
 static struct iio_chan_spec name[] = { \
AD5868_CHANNEL(0, 1, bits, _shift), \
@@ -200,72 +220,112 @@ DECLARE_AD5676_CHANNELS(ad5676_channels, 16, 0);
 DECLARE_AD5686_CHANNELS(ad5684_channels, 12, 4);
 DECLARE_AD5686_CHANNELS(ad5685r_channels, 14, 2);
 DECLARE_AD5686_CHANNELS(ad5686_channels, 16, 0);
+DECLARE_AD5693_CHANNELS(ad5693_channels, 16, 0);
+DECLARE_AD5693_CHANNELS(ad5692r_channels, 14, 2);
+DECLARE_AD5693_CHANNELS(ad5691r_channels, 12, 4);
 
 static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
[ID_AD5671R] = {
.channels = ad5672_channels,
.int_vref_mv = 2500,
.num_channels = 8,
+   .regmap_type = AD5686_REGMAP,
},
[ID_AD5672R] = {
.channels = ad5672_channels,
.int_vref_mv = 2500,
.num_channels = 8,
+   .regmap_type = AD5686_REGMAP,
},
[ID_AD5675R] = {
.channels = ad5676_channels,
.int_vref_mv = 2500,
.num_channels = 8,
+   .regmap_type = AD5686_REGMAP,
},
[ID_AD5676] = {
.channels = ad5676_channels,
.num_channels = 8,
+   .regmap_type = AD5686_REGMAP,
},
[ID_AD5676R] = {
.channels = ad5676_channels,
.int_vref_mv = 2500,
.num_channels = 8,
+   .regmap_type = AD5686_REGMAP,
},
[ID_AD5684] = {
.channels = ad5684_channels,
.num_channels = 4,
+   .regmap_type = AD5686_REGMAP,
},
[ID_AD5684R] = {
.channels = ad5684_channels,
.int_vref_mv = 2500,
.num_channels = 4,
+   .regmap_type = AD5686_REGMAP,
},
[ID_AD5685R] = {
.channels = ad5685r_channels,
.int_vref_mv = 2500,
.num_channels = 4,
+   .regmap_type = AD5686_REGMAP,
},
[ID_AD5686] = {
.channels = ad5686_channels,
.num_channels = 4,
+   .regmap_type = AD5686_REGMAP,
},
[ID_AD5686R] = {
.channels = ad5686_channels,
   

[PATCH 2/2] iio:dac:ad5686: Add AD5681R/AD5682R/AD5683/AD5683R support

2018-05-18 Thread Stefan Popa
The AD5681R/AD5682R/AD5683/AD5683R are a family of one channel DACs with
12-bit, 14-bit and 16-bit precision respectively. The devices have either
no built-in reference, or built-in 2.5V reference.

These devices are similar to AD5691R/AD5692R/AD5693/AD5693R except
with a few notable differences:
 * they use the SPI interface instead of I2C
 * in the write control register, DB18 and DB17 are used for setting the
   power mode, while DB16 is the REF bit. This is why a new regmap type
   was defined and checked accordingly.
 * the shift register is 24 bits wide, the first four bits are the command
   bits followed by the data bits. As the data comprises of 20-bit, 18-bit
   or 16-bit input code, this means that 4 LSB bits are don't care. This is
   why the data needs to be shifted on the left with four bits. Therefore,
   AD5683_REGMAP is checked inside a switch case in the ad5686_spi_write()
   function. On the other hand, similar devices such as AD5693R family,
   have the 4 MSB command bits followed by 4 don't care bits.

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5683R_5682R_5681R_5683.pdf

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
 drivers/iio/dac/ad5686-spi.c | 42 ++
 drivers/iio/dac/ad5686.c | 32 
 drivers/iio/dac/ad5686.h |  8 
 3 files changed, 74 insertions(+), 8 deletions(-)

diff --git a/drivers/iio/dac/ad5686-spi.c b/drivers/iio/dac/ad5686-spi.c
index 6bb09e9..1df9143 100644
--- a/drivers/iio/dac/ad5686-spi.c
+++ b/drivers/iio/dac/ad5686-spi.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * AD5672R, AD5676, AD5676R, AD5684, AD5684R, AD5684R, AD5685R, AD5686, AD5686R
+ * AD5672R, AD5676, AD5676R, AD5681R, AD5682R, AD5683, AD5683R,
+ * AD5684, AD5684R, AD5685R, AD5686, AD5686R
  * Digital to analog converters driver
  *
  * Copyright 2018 Analog Devices Inc.
@@ -15,12 +16,27 @@ static int ad5686_spi_write(struct ad5686_state *st,
u8 cmd, u8 addr, u16 val)
 {
struct spi_device *spi = to_spi_device(st->dev);
-
-   st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
- AD5686_ADDR(addr) |
- val);
-
-   return spi_write(spi, >data[0].d8[1], 3);
+   u8 tx_len, *buf;
+
+   switch (st->chip_info->regmap_type) {
+   case AD5683_REGMAP:
+   st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
+ AD5683_DATA(val));
+   buf = >data[0].d8[1];
+   tx_len = 3;
+   break;
+   case AD5686_REGMAP:
+   st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
+ AD5686_ADDR(addr) |
+ val);
+   buf = >data[0].d8[1];
+   tx_len = 3;
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   return spi_write(spi, buf, tx_len);
 }
 
 static int ad5686_spi_read(struct ad5686_state *st, u8 addr)
@@ -37,9 +53,15 @@ static int ad5686_spi_read(struct ad5686_state *st, u8 addr)
},
};
struct spi_device *spi = to_spi_device(st->dev);
+   u8 cmd = 0;
int ret;
 
-   st->data[0].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_READBACK_ENABLE) |
+   if (st->chip_info->regmap_type == AD5686_REGMAP)
+   cmd = AD5686_CMD_READBACK_ENABLE;
+   else if (st->chip_info->regmap_type == AD5683_REGMAP)
+   cmd = AD5686_CMD_READBACK_ENABLE_V2;
+
+   st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
  AD5686_ADDR(addr));
st->data[1].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP));
 
@@ -67,6 +89,10 @@ static const struct spi_device_id ad5686_spi_id[] = {
{"ad5672r", ID_AD5672R},
{"ad5676", ID_AD5676},
{"ad5676r", ID_AD5676R},
+   {"ad5681r", ID_AD5681R},
+   {"ad5682r", ID_AD5682R},
+   {"ad5683", ID_AD5683},
+   {"ad5683r", ID_AD5683R},
{"ad5684", ID_AD5684},
{"ad5684r", ID_AD5684R},
{"ad5685", ID_AD5685R}, /* Does not exist */
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index be803e8..1719d51 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -83,6 +83,10 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev 
*indio_dev,
st->pwr_down_mask &= ~(0x3 << (chan->channel * 2));
 
switch (st->chip_info->regmap_type) {
+   case AD5683_REGMAP:
+   shift = 13;
+   ref_bit_msk = AD5683_REF_BIT_MSK;
+   break;
case AD5686_REGMAP:
shift = 0;
ref

[PATCH v2 2/2] dt-bindings: iio: dac: Add docs for AD5758 DAC

2018-06-07 Thread Stefan Popa
Signed-off-by: Stefan Popa 
---
Changes in v2:
- Nothing changed, just to follow the patch set version.

 .../devicetree/bindings/iio/dac/ad5758.txt | 84 ++
 MAINTAINERS|  1 +
 2 files changed, 85 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/dac/ad5758.txt

diff --git a/Documentation/devicetree/bindings/iio/dac/ad5758.txt 
b/Documentation/devicetree/bindings/iio/dac/ad5758.txt
new file mode 100644
index 000..75fff6c
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/ad5758.txt
@@ -0,0 +1,84 @@
+Analog Devices AD5758 DAC device driver
+
+Required properties for the AD5758:
+   - compatible: Must be "adi,ad5758"
+   - reg: SPI chip select number for the device
+   - spi-max-frequency: Max SPI frequency to use (< 5000)
+   - spi-cpha: is the only mode that is supported
+
+Optional properties:
+
+ - adi,dc-dc-mode: Mode of operation of the dc-to-dc converter
+  The following values are currently supported:
+   * 0: DC-to-DC converter powered off
+   * 1: DPC current mode
+   * 2: DPC voltage mode
+   * 3: PPC current mode
+
+ - adi,dc-dc-ilim: The dc-to-dc converter current limit
+  The following values are currently supported [mA]:
+   * 150
+   * 200
+   * 250
+   * 300
+   * 350
+   * 400
+
+ - adi,slew: Array of slewrate settings should contain 3 fields:
+   1: Should be either 0 or 1 in order to enable or disable slewrate.
+   2: Slew rate clock:
+   Valid values for the slew rate update frequency [Hz]:
+   * 24
+   * 20
+   * 15
+   * 128000
+   * 64000
+   * 32000
+   * 16000
+   * 8000
+   * 4000
+   * 2000
+   * 1000
+   * 512
+   * 256
+   * 128
+   * 64
+   * 16
+   3: Slew rate step:
+   Defines by how much the output value changes at each update.
+   Valid values for the step size LSBs:
+   * 4
+   * 12
+   * 64
+   * 120
+   * 256
+   * 500
+   * 1820
+   * 2048
+
+ - adi,range: The output range
+ The following values are currently supported:
+   * 0: 0 V to 5 V voltage range
+   * 1: 0 V to 10 V voltage range
+   * 2: ±5 V voltage range
+   * 3: ±10 V voltage range
+   * 8: 0 mA to 20 mA current range
+   * 9: 0 mA to 24 mA current range
+   * 10: 4 mA to 20 mA current range
+   * 11: ±20 mA current range
+   * 12: ±24 mA current range
+   * 13: −1 mA to +22 mA current range
+
+AD5758 Example:
+
+   ad5758@0 {
+   compatible = "adi,ad5758";
+   reg = <0>;
+   spi-max-frequency = <100>;
+   spi-cpha;
+
+   adi,dc-dc-mode = <2>;
+   adi,dc-dc-ilim = <200>;
+   adi,slew = <1 20 12>;
+   adi,range = <1>;
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 1993779..f640146 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -808,6 +808,7 @@ L:  linux-...@vger.kernel.org
 W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/iio/dac/ad5758.c
+F: Documentation/devicetree/bindings/iio/dac/ad5758.txt
 
 ANALOG DEVICES INC AD9389B DRIVER
 M: Hans Verkuil 
-- 
2.7.4



[PATCH v2 1/2] iio: dac: Add AD5758 support

2018-06-07 Thread Stefan Popa
The AD5758 is a single channel DAC with 16-bit precision which uses the SPI
interface that operates at clock rates up to 50MHz.

The output can be configured as voltage or current and is available on a
single terminal.

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/ad5758.pdf

Signed-off-by: Stefan Popa 
---
Changes in v2:
- removed unnecessary parenthesis in AD5758_REG_WRITE macro.
- added missing documentation fields of ad5758_state struct.
- changed the type of pwr_down attribute to bool.
- changed ad5758_dc_dc_ilimt[] to ad5758_dc_dc_ilim[].
- ad5758_spi_reg_write() now returns spi_write(st->spi,
  >data[0].d32, sizeof(st->data[0].d32));
- removed unnecessary new line in ad5758_calib_mem_refresh().
- changed the type of the mode parameter in
  ad5758_set_dc_dc_conv_mode() from unsigned int to enum
  ad5758_dc_dc_mode.
- removed unnecessary parenthesis in ad5758_slew_rate_config().
- changed the type of the enable parameter in
  ad5758_fault_prot_switch_en() from unsigned char to bool.
- the same as above, but for ad5758_internal_buffers_en().
- added a missing mutex_unlock() in ad5758_reg_access().
- moved the mutex_unlock() in ad5758_read_raw() and removed the
  unreachable return.
- returned directly where it was possible in ad5758_write_raw().
- removed the channel, scan_type and scan_index fields.
- in ad5758_parse_dt(), added missing "\n", and specified what the
  default mode actually is.
- returned directly at the end of ad5758_init().
- in ad5758_probe() used device managed for registering the device
  and returned directly without the error message.

 MAINTAINERS  |   7 +
 drivers/iio/dac/Kconfig  |  10 +
 drivers/iio/dac/Makefile |   1 +
 drivers/iio/dac/ad5758.c | 805 +++
 4 files changed, 823 insertions(+)
 create mode 100644 drivers/iio/dac/ad5758.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 4b65225..1993779 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -802,6 +802,13 @@ S: Supported
 F: drivers/iio/dac/ad5686*
 F: drivers/iio/dac/ad5696*
 
+ANALOG DEVICES INC AD5758 DRIVER
+M: Stefan Popa 
+L: linux-...@vger.kernel.org
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/dac/ad5758.c
+
 ANALOG DEVICES INC AD9389B DRIVER
 M: Hans Verkuil 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 06e90de..80beb64 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -167,6 +167,16 @@ config AD5755
  To compile this driver as a module, choose M here: the
  module will be called ad5755.
 
+config AD5758
+   tristate "Analog Devices AD5758 DAC driver"
+   depends on SPI_MASTER
+   help
+ Say yes here to build support for Analog Devices AD5758 single channel
+ Digital to Analog Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5758.
+
 config AD5761
tristate "Analog Devices AD5761/61R/21/21R DAC driver"
depends on SPI_MASTER
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 57aa230..e859f2d 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_AD5592R_BASE) += ad5592r-base.o
 obj-$(CONFIG_AD5592R) += ad5592r.o
 obj-$(CONFIG_AD5593R) += ad5593r.o
 obj-$(CONFIG_AD5755) += ad5755.o
+obj-$(CONFIG_AD5758) += ad5758.o
 obj-$(CONFIG_AD5761) += ad5761.o
 obj-$(CONFIG_AD5764) += ad5764.o
 obj-$(CONFIG_AD5791) += ad5791.o
diff --git a/drivers/iio/dac/ad5758.c b/drivers/iio/dac/ad5758.c
new file mode 100644
index 000..3008a3a
--- /dev/null
+++ b/drivers/iio/dac/ad5758.c
@@ -0,0 +1,805 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * AD5758 Digital to analog converters driver
+ *
+ * Copyright 2018 Analog Devices Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+/* AD5758 registers definition */
+#define AD5758_NOP 0x00
+#define AD5758_DAC_INPUT   0x01
+#define AD5758_DAC_OUTPUT  0x02
+#define AD5758_CLEAR_CODE  0x03
+#define AD5758_USER_GAIN   0x04
+#define AD5758_USER_OFFSET 0x05
+#define AD5758_DAC_CONFIG  0x06
+#define AD5758_SW_LDAC 0x07
+#define AD5758_KEY 0x08
+#define AD5758_GP_CONFIG1  0x09
+#define AD5758_GP_CONFIG2  0x0A
+#define AD5758_DCDC_CONFIG1  

[PATCH] iio:dac:ad5686: Add AD5311R support

2018-06-04 Thread Stefan Popa
AD5311R is a single channel DAC with 10-bit precision and i2c interface.
The device includes a 2.5V internal reference which is enabled by default.

This device is similar to AD5691R/AD5692R/AD5693/AD5693R, the only
difference is that it has 10-bit precision.

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5310R_5311R.pdf

Signed-off-by: Stefan Popa 
---
 drivers/iio/dac/ad5686.c | 7 +++
 drivers/iio/dac/ad5686.h | 1 +
 drivers/iio/dac/ad5696-i2c.c | 1 +
 3 files changed, 9 insertions(+)

diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index e136f0f..2ddbfc3 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -221,6 +221,7 @@ static struct iio_chan_spec name[] = {  
\
AD5868_CHANNEL(7, 7, bits, _shift), \
 }
 
+DECLARE_AD5693_CHANNELS(ad5311r_channels, 10, 6);
 DECLARE_AD5676_CHANNELS(ad5672_channels, 12, 4);
 DECLARE_AD5676_CHANNELS(ad5676_channels, 16, 0);
 DECLARE_AD5686_CHANNELS(ad5684_channels, 12, 4);
@@ -231,6 +232,12 @@ DECLARE_AD5693_CHANNELS(ad5692r_channels, 14, 2);
 DECLARE_AD5693_CHANNELS(ad5691r_channels, 12, 4);
 
 static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
+   [ID_AD5311R] = {
+   .channels = ad5311r_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 1,
+   .regmap_type = AD5693_REGMAP,
+   },
[ID_AD5671R] = {
.channels = ad5672_channels,
.int_vref_mv = 2500,
diff --git a/drivers/iio/dac/ad5686.h b/drivers/iio/dac/ad5686.h
index d05cda9..57b3c61 100644
--- a/drivers/iio/dac/ad5686.h
+++ b/drivers/iio/dac/ad5686.h
@@ -45,6 +45,7 @@
  * ad5686_supported_device_ids:
  */
 enum ad5686_supported_device_ids {
+   ID_AD5311R,
ID_AD5671R,
ID_AD5672R,
ID_AD5675R,
diff --git a/drivers/iio/dac/ad5696-i2c.c b/drivers/iio/dac/ad5696-i2c.c
index d18735d..7350d98 100644
--- a/drivers/iio/dac/ad5696-i2c.c
+++ b/drivers/iio/dac/ad5696-i2c.c
@@ -71,6 +71,7 @@ static int ad5686_i2c_remove(struct i2c_client *i2c)
 }
 
 static const struct i2c_device_id ad5686_i2c_id[] = {
+   {"ad5311r", ID_AD5311R},
{"ad5671r", ID_AD5671R},
{"ad5675r", ID_AD5675R},
{"ad5691r", ID_AD5691R},
-- 
2.7.4



[PATCH 1/2] iio: dac: Add AD5758 support

2018-06-05 Thread Stefan Popa
The AD5758 is a single channel DAC with 16-bit precision which uses the SPI
interface that operates at clock rates up to 50MHz.

The output can be configured as voltage or current and is available on a
single terminal.

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/ad5758.pdf

Signed-off-by: Stefan Popa 
---
 MAINTAINERS  |   7 +
 drivers/iio/dac/Kconfig  |  10 +
 drivers/iio/dac/Makefile |   1 +
 drivers/iio/dac/ad5758.c | 826 +++
 4 files changed, 844 insertions(+)
 create mode 100644 drivers/iio/dac/ad5758.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 4b65225..1993779 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -802,6 +802,13 @@ S: Supported
 F: drivers/iio/dac/ad5686*
 F: drivers/iio/dac/ad5696*
 
+ANALOG DEVICES INC AD5758 DRIVER
+M: Stefan Popa 
+L: linux-...@vger.kernel.org
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/dac/ad5758.c
+
 ANALOG DEVICES INC AD9389B DRIVER
 M: Hans Verkuil 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 06e90de..80beb64 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -167,6 +167,16 @@ config AD5755
  To compile this driver as a module, choose M here: the
  module will be called ad5755.
 
+config AD5758
+   tristate "Analog Devices AD5758 DAC driver"
+   depends on SPI_MASTER
+   help
+ Say yes here to build support for Analog Devices AD5758 single channel
+ Digital to Analog Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5758.
+
 config AD5761
tristate "Analog Devices AD5761/61R/21/21R DAC driver"
depends on SPI_MASTER
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 57aa230..e859f2d 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_AD5592R_BASE) += ad5592r-base.o
 obj-$(CONFIG_AD5592R) += ad5592r.o
 obj-$(CONFIG_AD5593R) += ad5593r.o
 obj-$(CONFIG_AD5755) += ad5755.o
+obj-$(CONFIG_AD5758) += ad5758.o
 obj-$(CONFIG_AD5761) += ad5761.o
 obj-$(CONFIG_AD5764) += ad5764.o
 obj-$(CONFIG_AD5791) += ad5791.o
diff --git a/drivers/iio/dac/ad5758.c b/drivers/iio/dac/ad5758.c
new file mode 100644
index 000..0a26b9d
--- /dev/null
+++ b/drivers/iio/dac/ad5758.c
@@ -0,0 +1,826 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * AD5758 Digital to analog converters driver
+ *
+ * Copyright 2018 Analog Devices Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+/* AD5758 registers definition */
+#define AD5758_NOP 0x00
+#define AD5758_DAC_INPUT   0x01
+#define AD5758_DAC_OUTPUT  0x02
+#define AD5758_CLEAR_CODE  0x03
+#define AD5758_USER_GAIN   0x04
+#define AD5758_USER_OFFSET 0x05
+#define AD5758_DAC_CONFIG  0x06
+#define AD5758_SW_LDAC 0x07
+#define AD5758_KEY 0x08
+#define AD5758_GP_CONFIG1  0x09
+#define AD5758_GP_CONFIG2  0x0A
+#define AD5758_DCDC_CONFIG10x0B
+#define AD5758_DCDC_CONFIG20x0C
+#define AD5758_WDT_CONFIG  0x0F
+#define AD5758_DIGITAL_DIAG_CONFIG 0x10
+#define AD5758_ADC_CONFIG  0x11
+#define AD5758_FAULT_PIN_CONFIG0x12
+#define AD5758_TWO_STAGE_READBACK_SELECT   0x13
+#define AD5758_DIGITAL_DIAG_RESULTS0x14
+#define AD5758_ANALOG_DIAG_RESULTS 0x15
+#define AD5758_STATUS  0x16
+#define AD5758_CHIP_ID 0x17
+#define AD5758_FREQ_MONITOR0x18
+#define AD5758_DEVICE_ID_0 0x19
+#define AD5758_DEVICE_ID_1 0x1A
+#define AD5758_DEVICE_ID_2 0x1B
+#define AD5758_DEVICE_ID_3 0x1C
+
+/* AD5758_DAC_CONFIG */
+#define AD5758_DAC_CONFIG_RANGE_MSKGENMASK(3, 0)
+#define AD5758_DAC_CONFIG_RANGE_MODE(x)(((x) & 0xF) << 
0)
+#define AD5758_DAC_CONFIG_OVRNG_EN_MSK BIT(4)
+#define AD5758_DAC_CONFIG_OVRNG_EN_MODE(x) (((x) & 0x1) << 4)
+#define AD5758_DAC_CONFIG_INT_EN_MSK   BIT(5)
+#define AD5758_DAC_CONFIG_INT_EN_MODE(x)   (((x) & 0x1) << 5)
+#define AD5758_DAC_CONFIG_OUT_EN_MSK

[PATCH 2/2] dt-bindings: iio: dac: Add docs for AD5758 DAC

2018-06-05 Thread Stefan Popa
Signed-off-by: Stefan Popa 
---
 .../devicetree/bindings/iio/dac/ad5758.txt | 84 ++
 MAINTAINERS|  1 +
 2 files changed, 85 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/dac/ad5758.txt

diff --git a/Documentation/devicetree/bindings/iio/dac/ad5758.txt 
b/Documentation/devicetree/bindings/iio/dac/ad5758.txt
new file mode 100644
index 000..75fff6c
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/ad5758.txt
@@ -0,0 +1,84 @@
+Analog Devices AD5758 DAC device driver
+
+Required properties for the AD5758:
+   - compatible: Must be "adi,ad5758"
+   - reg: SPI chip select number for the device
+   - spi-max-frequency: Max SPI frequency to use (< 5000)
+   - spi-cpha: is the only mode that is supported
+
+Optional properties:
+
+ - adi,dc-dc-mode: Mode of operation of the dc-to-dc converter
+  The following values are currently supported:
+   * 0: DC-to-DC converter powered off
+   * 1: DPC current mode
+   * 2: DPC voltage mode
+   * 3: PPC current mode
+
+ - adi,dc-dc-ilim: The dc-to-dc converter current limit
+  The following values are currently supported [mA]:
+   * 150
+   * 200
+   * 250
+   * 300
+   * 350
+   * 400
+
+ - adi,slew: Array of slewrate settings should contain 3 fields:
+   1: Should be either 0 or 1 in order to enable or disable slewrate.
+   2: Slew rate clock:
+   Valid values for the slew rate update frequency [Hz]:
+   * 24
+   * 20
+   * 15
+   * 128000
+   * 64000
+   * 32000
+   * 16000
+   * 8000
+   * 4000
+   * 2000
+   * 1000
+   * 512
+   * 256
+   * 128
+   * 64
+   * 16
+   3: Slew rate step:
+   Defines by how much the output value changes at each update.
+   Valid values for the step size LSBs:
+   * 4
+   * 12
+   * 64
+   * 120
+   * 256
+   * 500
+   * 1820
+   * 2048
+
+ - adi,range: The output range
+ The following values are currently supported:
+   * 0: 0 V to 5 V voltage range
+   * 1: 0 V to 10 V voltage range
+   * 2: ±5 V voltage range
+   * 3: ±10 V voltage range
+   * 8: 0 mA to 20 mA current range
+   * 9: 0 mA to 24 mA current range
+   * 10: 4 mA to 20 mA current range
+   * 11: ±20 mA current range
+   * 12: ±24 mA current range
+   * 13: −1 mA to +22 mA current range
+
+AD5758 Example:
+
+   ad5758@0 {
+   compatible = "adi,ad5758";
+   reg = <0>;
+   spi-max-frequency = <100>;
+   spi-cpha;
+
+   adi,dc-dc-mode = <2>;
+   adi,dc-dc-ilim = <200>;
+   adi,slew = <1 20 12>;
+   adi,range = <1>;
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 1993779..f640146 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -808,6 +808,7 @@ L:  linux-...@vger.kernel.org
 W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/iio/dac/ad5758.c
+F: Documentation/devicetree/bindings/iio/dac/ad5758.txt
 
 ANALOG DEVICES INC AD9389B DRIVER
 M: Hans Verkuil 
-- 
2.7.4



[PATCH v2 2/6] dt-bindings: iio: accel: Add docs for ADXL372

2018-08-01 Thread Stefan Popa
Add the device tree binding documentation for the ADXL372 3-axis digital
accelerometer.

Signed-off-by: Stefan Popa 
---
Changes in v2:
- introduced all the DT bindings in a single patch.

 .../devicetree/bindings/iio/accel/adxl372.txt  | 24 ++
 MAINTAINERS|  1 +
 2 files changed, 25 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/accel/adxl372.txt

diff --git a/Documentation/devicetree/bindings/iio/accel/adxl372.txt 
b/Documentation/devicetree/bindings/iio/accel/adxl372.txt
new file mode 100644
index 000..41493d9
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/accel/adxl372.txt
@@ -0,0 +1,24 @@
+Analog Devices ADXL372 3-Axis, +/-(200g) Digital Accelerometer
+
+http://www.analog.com/media/en/technical-documentation/data-sheets/adxl372.pdf
+
+Required properties:
+ - compatible : should be "adi,adxl372"
+ - reg: SPI chip select number for the device
+ - spi-max-frequency: Max SPI frequency to use
+
+Optional properties:
+ - interrupt-parent : phandle to the parent interrupt controller as documented
+   in Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+ - interrupts: interrupt mapping for IRQ as documented in
+   Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+
+Example:
+
+   accelerometer@0 {
+   compatible = "adi,adxl372";
+   reg = <0>;
+   spi-max-frequency = <100>;
+   interrupt-parent = <>;
+   interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 2ba47bb..c8dd09c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -548,6 +548,7 @@ M:  Stefan Popa 
 W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/iio/accel/adxl372.c
+F: Documentation/devicetree/bindings/iio/accel/adxl372.txt
 
 AF9013 MEDIA DRIVER
 M: Antti Palosaari 
-- 
2.7.4



[PATCH v2 1/6] iio: adxl372: New driver for Analog Devices ADXL372 Accelerometer

2018-08-01 Thread Stefan Popa
This patch adds basic support for Analog Devices ADXL372 SPI-Bus
Three-Axis Digital Accelerometer.

The device is probed and configured the with some initial default
values. With this basic driver, it is possible to read raw acceleration
data.

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL372.pdf

Signed-off-by: Stefan Popa 
---
Changes in v2:
- removed ADXL372_RD_FLAG_MSK and ADXL372_WR_FLAG_MSK macros.
- handled regmap read/write by setting reg_bits and pad_bits
  fields in regmap_config struct.
- removed the buffer specifications when defining the channels.
- changed the activity and inactivity thresholds.
- added two new functions for setting the activity and inactivity
  timers: adxl372_set_inactivity_time_ms() and
  adxl372_set_activity_time_ms().

 MAINTAINERS |   6 +
 drivers/iio/accel/Kconfig   |  11 +
 drivers/iio/accel/Makefile  |   1 +
 drivers/iio/accel/adxl372.c | 530 
 4 files changed, 548 insertions(+)
 create mode 100644 drivers/iio/accel/adxl372.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 60b1028..2ba47bb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -543,6 +543,12 @@ W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/input/misc/adxl34x.c
 
+ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
+M: Stefan Popa 
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/accel/adxl372.c
+
 AF9013 MEDIA DRIVER
 M: Antti Palosaari 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 62ae7e5..1b496ef 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -60,6 +60,17 @@ config ADXL345_SPI
  will be called adxl345_spi and you will also get adxl345_core
  for the core module.
 
+config ADXL372
+   tristate "Analog Devices ADXL372 3-Axis Accelerometer Driver"
+   depends on SPI
+   select IIO_BUFFER
+   select IIO_TRIGGERED_BUFFER
+   help
+ Say yes here to add support for the Analog Devices ADXL372 triaxial
+ acceleration sensor.
+ To compile this driver as a module, choose M here: the
+ module will be called adxl372.
+
 config BMA180
tristate "Bosch BMA180/BMA250 3-Axis Accelerometer Driver"
depends on I2C
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index 636d4d1..5758ffc 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_ADIS16209) += adis16209.o
 obj-$(CONFIG_ADXL345) += adxl345_core.o
 obj-$(CONFIG_ADXL345_I2C) += adxl345_i2c.o
 obj-$(CONFIG_ADXL345_SPI) += adxl345_spi.o
+obj-$(CONFIG_ADXL372) += adxl372.o
 obj-$(CONFIG_BMA180) += bma180.o
 obj-$(CONFIG_BMA220) += bma220_spi.o
 obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
new file mode 100644
index 000..7d5092d
--- /dev/null
+++ b/drivers/iio/accel/adxl372.c
@@ -0,0 +1,530 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * ADXL372 3-Axis Digital Accelerometer SPI driver
+ *
+ * Copyright 2018 Analog Devices Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+/* ADXL372 registers definition */
+#define ADXL372_DEVID  0x00
+#define ADXL372_DEVID_MST  0x01
+#define ADXL372_PARTID 0x02
+#define ADXL372_REVID  0x03
+#define ADXL372_STATUS_1   0x04
+#define ADXL372_STATUS_2   0x05
+#define ADXL372_FIFO_ENTRIES_2 0x06
+#define ADXL372_FIFO_ENTRIES_1 0x07
+#define ADXL372_X_DATA_H   0x08
+#define ADXL372_X_DATA_L   0x09
+#define ADXL372_Y_DATA_H   0x0A
+#define ADXL372_Y_DATA_L   0x0B
+#define ADXL372_Z_DATA_H   0x0C
+#define ADXL372_Z_DATA_L   0x0D
+#define ADXL372_X_MAXPEAK_H0x15
+#define ADXL372_X_MAXPEAK_L0x16
+#define ADXL372_Y_MAXPEAK_H0x17
+#define ADXL372_Y_MAXPEAK_L0x18
+#define ADXL372_Z_MAXPEAK_H0x19
+#define ADXL372_Z_MAXPEAK_L0x1A
+#define ADXL372_OFFSET_X   0x20
+#define ADXL372_OFFSET_Y   0x21
+#define ADXL372_OFFSET_Z   0x22
+#define ADXL372_X_THRESH_ACT_H 0x23
+#define ADXL372_X_THRESH_ACT_L 0x24
+#define ADXL372_Y_THRESH_ACT_H 0x25
+#define ADXL372_Y_THRESH_ACT_L 0x26
+#define ADXL372_Z_THRESH_ACT_H 0x27
+#define ADXL372_Z_THRESH_ACT_L 0x28
+#define ADXL372_TIME_ACT   0x29
+#define ADXL372_X_THRESH_INACT_H   0x2A
+#define ADXL372_X_THRESH_INACT_L   0x2B
+#define ADXL372_Y_THRESH_INACT_H   0x2C
+#define ADXL372_Y_THRESH_INACT_L   0x2D
+#define ADXL372_Z_THRESH_INACT_H

[PATCH v3 4/6] iio:adxl372: Add FIFO and interrupts support

2018-08-03 Thread Stefan Popa
This patch adds support for the adxl372 FIFO. In order to accomplish this,
triggered buffers were used.

The number of FIFO samples which trigger the watermark interrupt can be
configured by using the buffer watermark. The FIFO format is determined by
configuring the scan elements for each axis. The FIFO data is pushed to the
IIO device's buffer.

Signed-off-by: Stefan Popa 
---
 drivers/iio/accel/adxl372.c | 346 +++-
 1 file changed, 345 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 7d5092d..e31e096 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -6,12 +6,19 @@
  */
 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
 
 /* ADXL372 registers definition */
 #define ADXL372_DEVID  0x00
@@ -123,6 +130,9 @@
 #define ADXL372_INT1_MAP_LOW_MSK   BIT(7)
 #define ADXL372_INT1_MAP_LOW_MODE(x)   (((x) & 0x1) << 7)
 
+/* The ADXL372 includes a deep, 512 sample FIFO buffer */
+#define ADXL372_FIFO_SIZE  512
+
 /*
  * At +/- 200g with 12-bit resolution, scale is computed as:
  * (200 + 200) * 9.81 / (2^12 - 1) = 0.958241
@@ -164,6 +174,43 @@ enum adxl372_bandwidth {
ADXL372_BW_3200HZ,
 };
 
+enum adxl372_fifo_format {
+   ADXL372_XYZ_FIFO,
+   ADXL372_X_FIFO,
+   ADXL372_Y_FIFO,
+   ADXL372_XY_FIFO,
+   ADXL372_Z_FIFO,
+   ADXL372_XZ_FIFO,
+   ADXL372_YZ_FIFO,
+   ADXL372_XYZ_PEAK_FIFO,
+};
+
+enum adxl372_fifo_mode {
+   ADXL372_FIFO_BYPASSED,
+   ADXL372_FIFO_STREAMED,
+   ADXL372_FIFO_TRIGGERED,
+   ADXL372_FIFO_OLD_SAVED
+};
+
+static const int adxl372_samp_freq_tbl[5] = {
+   400, 800, 1600, 3200, 6400,
+};
+
+struct adxl372_axis_lookup {
+   unsigned int bits;
+   enum adxl372_fifo_format fifo_format;
+};
+
+static const struct adxl372_axis_lookup adxl372_axis_lookup_table[] = {
+   { BIT(0), ADXL372_X_FIFO },
+   { BIT(1), ADXL372_Y_FIFO },
+   { BIT(2), ADXL372_Z_FIFO },
+   { BIT(0) | BIT(1), ADXL372_XY_FIFO },
+   { BIT(0) | BIT(2), ADXL372_XZ_FIFO },
+   { BIT(1) | BIT(2), ADXL372_YZ_FIFO },
+   { BIT(0) | BIT(1) | BIT(2), ADXL372_XYZ_FIFO },
+};
+
 #define ADXL372_ACCEL_CHANNEL(index, reg, axis) {  \
.type = IIO_ACCEL,  \
.address = reg, \
@@ -171,6 +218,13 @@ enum adxl372_bandwidth {
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
+   .scan_index = index,\
+   .scan_type = {  \
+   .sign = 's',\
+   .realbits = 12, \
+   .storagebits = 16,  \
+   .shift = 4, \
+   },  \
 }
 
 static const struct iio_chan_spec adxl372_channels[] = {
@@ -182,14 +236,37 @@ static const struct iio_chan_spec adxl372_channels[] = {
 struct adxl372_state {
struct spi_device   *spi;
struct regmap   *regmap;
+   struct iio_trigger  *dready_trig;
+   enum adxl372_fifo_mode  fifo_mode;
+   enum adxl372_fifo_formatfifo_format;
enum adxl372_op_modeop_mode;
enum adxl372_act_proc_mode  act_proc_mode;
enum adxl372_odrodr;
enum adxl372_bandwidth  bw;
u32 act_time_ms;
u32 inact_time_ms;
+   u8  fifo_set_size;
+   u8  int1_bitmask;
+   u8  int2_bitmask;
+   u16 watermark;
+   __be16  fifo_buf[ADXL372_FIFO_SIZE];
+};
+
+static const unsigned long adxl372_channel_masks[] = {
+   BIT(0), BIT(1), BIT(2),
+   BIT(0) | BIT(1),
+   BIT(0) | BIT(2),
+   BIT(1) | BIT(2),
+   BIT(0) | BIT(1) | BIT(2),
+   0
 };
 
+static int adxl372_read_fifo(struct adxl372_state *st, u16 fifo_entries)
+{
+   return regmap_noinc_read(st->regmap, ADXL372_FIFO_DATA,
+st->fifo_buf, fifo_entries * sizeof(u16));
+}
+
 static int adxl372_read_axis(struct adxl372_state *st, u8 addr)
 {
__be16 regval;
@@ -364,6 +441,109 @@ static int adxl372_set_inactivity_time_ms(struct 
a

[PATCH v3 3/6] regmap: Add regmap_noinc_read API

2018-08-03 Thread Stefan Popa
From: Crestez Dan Leonard 

The regmap API usually assumes that bulk read operations will read a
range of registers but some I2C/SPI devices have certain registers for
which a such a read operation will return data from an internal FIFO
instead. Add an explicit API to support bulk read without range semantics.

Some linux drivers use regmap_bulk_read or regmap_raw_read for such
registers, for example mpu6050 or bmi150 from IIO. This only happens to
work because when caching is disabled a single regmap read op will map
to a single bus read op (as desired). This breaks if caching is enabled and
reg+1 happens to be a cacheable register.

Without regmap support refactoring a driver to enable regmap caching
requires separate I2C and SPI paths. This is exactly what regmap is
supposed to help avoid.

Suggested-by: Jonathan Cameron 
Signed-off-by: Crestez Dan Leonard 
Signed-off-by: Stefan Popa 
---
 drivers/base/regmap/regmap.c | 65 +++-
 include/linux/regmap.h   |  9 ++
 2 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 3bc8488..e632503 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -2564,7 +2564,70 @@ int regmap_raw_read(struct regmap *map, unsigned int 
reg, void *val,
 EXPORT_SYMBOL_GPL(regmap_raw_read);
 
 /**
- * regmap_field_read() - Read a value to a single register field
+ * regmap_noinc_read(): Read data from a register without incrementing the
+ * register number
+ *
+ * @map: Register map to read from
+ * @reg: Register to read from
+ * @val: Pointer to data buffer
+ * @val_len: Length of output buffer in bytes.
+ *
+ * The regmap API usually assumes that bulk bus read operations will read a
+ * range of registers. Some devices have certain registers for which a read
+ * operation read will read from an internal FIFO.
+ *
+ * The target register must be volatile but registers after it can be
+ * completely unrelated cacheable registers.
+ *
+ * This will attempt multiple reads as required to read val_len bytes.
+ *
+ * A value of zero will be returned on success, a negative errno will be
+ * returned in error cases.
+ */
+int regmap_noinc_read(struct regmap *map, unsigned int reg,
+ void *val, size_t val_len)
+{
+   size_t read_len;
+   int ret;
+
+   if (!map->bus)
+   return -EINVAL;
+   if (!map->bus->read)
+   return -ENOTSUPP;
+   if (val_len % map->format.val_bytes)
+   return -EINVAL;
+   if (!IS_ALIGNED(reg, map->reg_stride))
+   return -EINVAL;
+   if (val_len == 0)
+   return -EINVAL;
+
+   map->lock(map->lock_arg);
+
+   if (!regmap_volatile(map, reg) || !regmap_readable(map, reg)) {
+   ret = -EINVAL;
+   goto out_unlock;
+   }
+
+   while (val_len) {
+   if (map->max_raw_read && map->max_raw_read < val_len)
+   read_len = map->max_raw_read;
+   else
+   read_len = val_len;
+   ret = _regmap_raw_read(map, reg, val, read_len);
+   if (ret)
+   goto out_unlock;
+   val = ((u8 *)val) + read_len;
+   val_len -= read_len;
+   }
+
+out_unlock:
+   map->unlock(map->lock_arg);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_noinc_read);
+
+/**
+ * regmap_field_read(): Read a value to a single register field
  *
  * @field: Register field to read from
  * @val: Pointer to store read value
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 4f38068..b6e6040 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -946,6 +946,8 @@ int regmap_raw_write_async(struct regmap *map, unsigned int 
reg,
 int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);
 int regmap_raw_read(struct regmap *map, unsigned int reg,
void *val, size_t val_len);
+int regmap_noinc_read(struct regmap *map, unsigned int reg,
+ void *val, size_t val_len);
 int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
 size_t val_count);
 int regmap_update_bits_base(struct regmap *map, unsigned int reg,
@@ -1196,6 +1198,13 @@ static inline int regmap_raw_read(struct regmap *map, 
unsigned int reg,
return -EINVAL;
 }
 
+static inline int regmap_pipe_read(struct regmap *map, unsigned int reg,
+  void *val, size_t val_len)
+{
+   WARN_ONCE(1, "regmap API is disabled");
+   return -EINVAL;
+}
+
 static inline int regmap_bulk_read(struct regmap *map, unsigned int reg,
   void *val, size_t val_count)
 {
-- 
2.7.4



[PATCH v3 6/6] iio:adxl372: Add filter bandwidth support

2018-08-03 Thread Stefan Popa
This patch adds the option for the user to select the filter bandwidth. The
user can also read the available bandwidths which are always adjusted to be
at most half of the sampling frequency. Furthermore, the currently selected
bandwidth can be read via the read_raw function, while the write_raw sets a
new bandwidth value.

Signed-off-by: Stefan Popa 
---
 drivers/iio/accel/adxl372.c | 38 --
 1 file changed, 36 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 80b1838..3a9d55a 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -196,6 +196,10 @@ static const int adxl372_samp_freq_tbl[5] = {
400, 800, 1600, 3200, 6400,
 };
 
+static const int adxl372_bw_freq_tbl[5] = {
+   200, 400, 800, 1600, 3200,
+};
+
 struct adxl372_axis_lookup {
unsigned int bits;
enum adxl372_fifo_format fifo_format;
@@ -218,7 +222,8 @@ static const struct adxl372_axis_lookup 
adxl372_axis_lookup_table[] = {
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
-   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ) |  \
+   BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),   \
.scan_index = index,\
.scan_type = {  \
.sign = 's',\
@@ -656,6 +661,9 @@ static int adxl372_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SAMP_FREQ:
*val = adxl372_samp_freq_tbl[st->odr];
return IIO_VAL_INT;
+   case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+   *val = adxl372_bw_freq_tbl[st->bw];
+   return IIO_VAL_INT;
}
 
return -EINVAL;
@@ -666,7 +674,7 @@ static int adxl372_write_raw(struct iio_dev *indio_dev,
 int val, int val2, long info)
 {
struct adxl372_state *st = iio_priv(indio_dev);
-   int odr_index, ret;
+   int odr_index, bw_index, ret;
 
switch (info) {
case IIO_CHAN_INFO_SAMP_FREQ:
@@ -698,11 +706,34 @@ static int adxl372_write_raw(struct iio_dev *indio_dev,
ret = adxl372_set_bandwidth(st, odr_index);
 
return ret;
+   case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+   bw_index = adxl372_find_closest_match(adxl372_bw_freq_tbl,
+   ARRAY_SIZE(adxl372_bw_freq_tbl),
+   val);
+   return adxl372_set_bandwidth(st, bw_index);
default:
return -EINVAL;
}
 }
 
+static ssize_t adxl372_show_filter_freq_avail(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+   struct adxl372_state *st = iio_priv(indio_dev);
+   int i;
+   size_t len = 0;
+
+   for (i = 0; i <= st->odr; i++)
+   len += scnprintf(buf + len, PAGE_SIZE - len,
+"%d ", adxl372_bw_freq_tbl[i]);
+
+   buf[len - 1] = '\n';
+
+   return len;
+}
+
 static ssize_t adxl372_get_fifo_enabled(struct device *dev,
  struct device_attribute *attr,
  char *buf)
@@ -826,9 +857,12 @@ static const struct iio_trigger_ops adxl372_trigger_ops = {
 };
 
 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400");
+static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available,
+  0444, adxl372_show_filter_freq_avail, NULL, 0);
 
 static struct attribute *adxl372_attributes[] = {
_const_attr_sampling_frequency_available.dev_attr.attr,
+   
_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr,
NULL,
 };
 
-- 
2.7.4



[PATCH v3 5/6] iio:adxl372: Add sampling frequency support

2018-08-03 Thread Stefan Popa
This patch adds the option for the user to select the sampling frequency.
Also, the user can read the available frequencies and read the currently
set frequency via the read_raw function. The frequency can be set via the
write_raw function.

When the frequency is set, the bandwidth is also checked and ensured
that it is constrained to at most half of the sampling frequency. Also, the
activity and inactivity timers have to be updated because they depend on
the selected ODR.

Signed-off-by: Stefan Popa 
---
 drivers/iio/accel/adxl372.c | 74 -
 1 file changed, 73 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index e31e096..80b1838 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -217,7 +217,8 @@ static const struct adxl372_axis_lookup 
adxl372_axis_lookup_table[] = {
.modified = 1,  \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
-   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
+   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
.scan_index = index,\
.scan_type = {  \
.sign = 's',\
@@ -311,6 +312,19 @@ static int adxl372_set_odr(struct adxl372_state *st,
return ret;
 }
 
+static int adxl372_find_closest_match(const int *array,
+ unsigned int size, int val)
+{
+   int i;
+
+   for (i = 0; i < size; i++) {
+   if (val <= array[i])
+   return i;
+   }
+
+   return size - 1;
+}
+
 static int adxl372_set_bandwidth(struct adxl372_state *st,
 enum adxl372_bandwidth bw)
 {
@@ -639,6 +653,51 @@ static int adxl372_read_raw(struct iio_dev *indio_dev,
*val = 0;
*val2 = ADXL372_USCALE;
return IIO_VAL_INT_PLUS_MICRO;
+   case IIO_CHAN_INFO_SAMP_FREQ:
+   *val = adxl372_samp_freq_tbl[st->odr];
+   return IIO_VAL_INT;
+   }
+
+   return -EINVAL;
+}
+
+static int adxl372_write_raw(struct iio_dev *indio_dev,
+struct iio_chan_spec const *chan,
+int val, int val2, long info)
+{
+   struct adxl372_state *st = iio_priv(indio_dev);
+   int odr_index, ret;
+
+   switch (info) {
+   case IIO_CHAN_INFO_SAMP_FREQ:
+   odr_index = adxl372_find_closest_match(adxl372_samp_freq_tbl,
+   ARRAY_SIZE(adxl372_samp_freq_tbl),
+   val);
+   ret = adxl372_set_odr(st, odr_index);
+   if (ret < 0)
+   return ret;
+   /*
+* The timer period depends on the ODR selected.
+* At 3200 Hz and below, it is 6.6 ms; at 6400 Hz, it is 3.3 ms
+*/
+   ret = adxl372_set_activity_time_ms(st, st->act_time_ms);
+   if (ret < 0)
+   return ret;
+   /*
+* The timer period depends on the ODR selected.
+* At 3200 Hz and below, it is 26 ms; at 6400 Hz, it is 13 ms
+*/
+   ret = adxl372_set_inactivity_time_ms(st, st->inact_time_ms);
+   if (ret < 0)
+   return ret;
+   /*
+* The maximum bandwidth is constrained to at most half of
+* the ODR to ensure that the Nyquist criteria is not violated
+*/
+   if (st->bw > odr_index)
+   ret = adxl372_set_bandwidth(st, odr_index);
+
+   return ret;
default:
return -EINVAL;
}
@@ -766,8 +825,21 @@ static const struct iio_trigger_ops adxl372_trigger_ops = {
.set_trigger_state = adxl372_dready_trig_set_state,
 };
 
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400");
+
+static struct attribute *adxl372_attributes[] = {
+   _const_attr_sampling_frequency_available.dev_attr.attr,
+   NULL,
+};
+
+static const struct attribute_group adxl372_attrs_group = {
+   .attrs = adxl372_attributes,
+};
+
 static const struct iio_info adxl372_info = {
+   .attrs = _attrs_group,
.read_raw = adxl372_read_raw,
+   .write_raw = adxl372_write_raw,
.debugfs_reg_access = _reg_access,
.hwfifo_set_watermark = adxl372_set_watermark,
 };
-- 
2.7.4



[PATCH v3 1/6] iio: adxl372: New driver for Analog Devices ADXL372 Accelerometer

2018-08-03 Thread Stefan Popa
This patch adds basic support for Analog Devices ADXL372 SPI-Bus
Three-Axis Digital Accelerometer.

The device is probed and configured the with some initial default
values. With this basic driver, it is possible to read raw acceleration
data.

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL372.pdf

Signed-off-by: Stefan Popa 
---
 MAINTAINERS |   6 +
 drivers/iio/accel/Kconfig   |  11 +
 drivers/iio/accel/Makefile  |   1 +
 drivers/iio/accel/adxl372.c | 530 
 4 files changed, 548 insertions(+)
 create mode 100644 drivers/iio/accel/adxl372.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 60b1028..2ba47bb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -543,6 +543,12 @@ W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/input/misc/adxl34x.c
 
+ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
+M: Stefan Popa 
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/accel/adxl372.c
+
 AF9013 MEDIA DRIVER
 M: Antti Palosaari 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 62ae7e5..1b496ef 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -60,6 +60,17 @@ config ADXL345_SPI
  will be called adxl345_spi and you will also get adxl345_core
  for the core module.
 
+config ADXL372
+   tristate "Analog Devices ADXL372 3-Axis Accelerometer Driver"
+   depends on SPI
+   select IIO_BUFFER
+   select IIO_TRIGGERED_BUFFER
+   help
+ Say yes here to add support for the Analog Devices ADXL372 triaxial
+ acceleration sensor.
+ To compile this driver as a module, choose M here: the
+ module will be called adxl372.
+
 config BMA180
tristate "Bosch BMA180/BMA250 3-Axis Accelerometer Driver"
depends on I2C
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index 636d4d1..5758ffc 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_ADIS16209) += adis16209.o
 obj-$(CONFIG_ADXL345) += adxl345_core.o
 obj-$(CONFIG_ADXL345_I2C) += adxl345_i2c.o
 obj-$(CONFIG_ADXL345_SPI) += adxl345_spi.o
+obj-$(CONFIG_ADXL372) += adxl372.o
 obj-$(CONFIG_BMA180) += bma180.o
 obj-$(CONFIG_BMA220) += bma220_spi.o
 obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
new file mode 100644
index 000..7d5092d
--- /dev/null
+++ b/drivers/iio/accel/adxl372.c
@@ -0,0 +1,530 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * ADXL372 3-Axis Digital Accelerometer SPI driver
+ *
+ * Copyright 2018 Analog Devices Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+/* ADXL372 registers definition */
+#define ADXL372_DEVID  0x00
+#define ADXL372_DEVID_MST  0x01
+#define ADXL372_PARTID 0x02
+#define ADXL372_REVID  0x03
+#define ADXL372_STATUS_1   0x04
+#define ADXL372_STATUS_2   0x05
+#define ADXL372_FIFO_ENTRIES_2 0x06
+#define ADXL372_FIFO_ENTRIES_1 0x07
+#define ADXL372_X_DATA_H   0x08
+#define ADXL372_X_DATA_L   0x09
+#define ADXL372_Y_DATA_H   0x0A
+#define ADXL372_Y_DATA_L   0x0B
+#define ADXL372_Z_DATA_H   0x0C
+#define ADXL372_Z_DATA_L   0x0D
+#define ADXL372_X_MAXPEAK_H0x15
+#define ADXL372_X_MAXPEAK_L0x16
+#define ADXL372_Y_MAXPEAK_H0x17
+#define ADXL372_Y_MAXPEAK_L0x18
+#define ADXL372_Z_MAXPEAK_H0x19
+#define ADXL372_Z_MAXPEAK_L0x1A
+#define ADXL372_OFFSET_X   0x20
+#define ADXL372_OFFSET_Y   0x21
+#define ADXL372_OFFSET_Z   0x22
+#define ADXL372_X_THRESH_ACT_H 0x23
+#define ADXL372_X_THRESH_ACT_L 0x24
+#define ADXL372_Y_THRESH_ACT_H 0x25
+#define ADXL372_Y_THRESH_ACT_L 0x26
+#define ADXL372_Z_THRESH_ACT_H 0x27
+#define ADXL372_Z_THRESH_ACT_L 0x28
+#define ADXL372_TIME_ACT   0x29
+#define ADXL372_X_THRESH_INACT_H   0x2A
+#define ADXL372_X_THRESH_INACT_L   0x2B
+#define ADXL372_Y_THRESH_INACT_H   0x2C
+#define ADXL372_Y_THRESH_INACT_L   0x2D
+#define ADXL372_Z_THRESH_INACT_H   0x2E
+#define ADXL372_Z_THRESH_INACT_L   0x2F
+#define ADXL372_TIME_INACT_H   0x30
+#define ADXL372_TIME_INACT_L   0x31
+#define ADXL372_X_THRESH_ACT2_H0x32
+#define ADXL372_X_THRESH_ACT2_L0x33
+#define ADXL372_Y_THRESH_ACT2_H0x34
+#define ADXL372_Y_THRESH_ACT2_L0x35
+#define ADXL372_Z_THRESH_ACT2_H0x36
+#define ADXL372_Z_THRESH_ACT2_L0x37
+#define ADXL372_HPF 

[PATCH v3 2/6] dt-bindings: iio: accel: Add docs for ADXL372

2018-08-03 Thread Stefan Popa
Add the device tree binding documentation for the ADXL372 3-axis digital
accelerometer.

Signed-off-by: Stefan Popa 
---
 .../devicetree/bindings/iio/accel/adxl372.txt  | 24 ++
 MAINTAINERS|  1 +
 2 files changed, 25 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/accel/adxl372.txt

diff --git a/Documentation/devicetree/bindings/iio/accel/adxl372.txt 
b/Documentation/devicetree/bindings/iio/accel/adxl372.txt
new file mode 100644
index 000..41493d9
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/accel/adxl372.txt
@@ -0,0 +1,24 @@
+Analog Devices ADXL372 3-Axis, +/-(200g) Digital Accelerometer
+
+http://www.analog.com/media/en/technical-documentation/data-sheets/adxl372.pdf
+
+Required properties:
+ - compatible : should be "adi,adxl372"
+ - reg: SPI chip select number for the device
+ - spi-max-frequency: Max SPI frequency to use
+
+Optional properties:
+ - interrupt-parent : phandle to the parent interrupt controller as documented
+   in Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+ - interrupts: interrupt mapping for IRQ as documented in
+   Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+
+Example:
+
+   accelerometer@0 {
+   compatible = "adi,adxl372";
+   reg = <0>;
+   spi-max-frequency = <100>;
+   interrupt-parent = <>;
+   interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 2ba47bb..c8dd09c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -548,6 +548,7 @@ M:  Stefan Popa 
 W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/iio/accel/adxl372.c
+F: Documentation/devicetree/bindings/iio/accel/adxl372.txt
 
 AF9013 MEDIA DRIVER
 M: Antti Palosaari 
-- 
2.7.4



[PATCH v3 0/6] iio: accel: Add adxl372 driver

2018-08-03 Thread Stefan Popa
Changes in v3:
Patch 1, 2:
- nothing changed
Patch 3:
- changed the name from regmap_pipe_read() to regmap_noinc_read()
- added a check for readable registers
Patch 4:
- dropped the fifo peak mode
- corrected the patch based on feedback from Peter Meerwald-Stadler.
Patch 5 and 6:
- nothing changed

Changes in v2:
Patch 1:
- removed ADXL372_RD_FLAG_MSK and ADXL372_WR_FLAG_MSK macros.
- handled regmap read/write by setting reg_bits and pad_bits
  fields in regmap_config struct.
- removed the buffer specifications when defining the channels.
- changed the activity and inactivity thresholds.
- added two new functions for setting the activity and inactivity
  timers: adxl372_set_inactivity_time_ms() and
  adxl372_set_activity_time_ms().
Patch 2:
- introduced all the DT bindings in a single patch.
Patch 3:
- backported the patch based on this discussion: 
  https://lkml.org/lkml/2016/6/16/548.
- this patch is required as the regmap_pipe_read() API will be used 
  to read the data from the FIFO.
Patch 4:
- removed DT bindings changes from this patch.
- removed the linux/gpio/consumer.h header.
- used regmap_pipe_read() instead of regmap_bulk_read() when
  reading data from the FIFO.
- used multiple regmap_write() calls instead of a single
  regmap_bulk_write() if there is no fast path.
- used be32_to_cpu() inside the adxl372_get_status() function.
- added a new in_accel_x_peak scan element which allows the
  user to set the FIFO into XYZ peak mode.
- used a adxl372_axis_lookup_table() to determine the fifo format
  from the active_scan_mask.
- made IRQ optional.
Patch 5 and 6:
- nothing changed

Crestez Dan Leonard (1):
  regmap: Add regmap_noinc_read API

Stefan Popa (5):
  iio: adxl372: New driver for Analog Devices ADXL372 Accelerometer
  dt-bindings: iio: accel: Add docs for ADXL372
  iio:adxl372: Add FIFO and interrupts support
  iio:adxl372: Add sampling frequency support
  iio:adxl372: Add filter bandwidth support

 .../devicetree/bindings/iio/accel/adxl372.txt  |  24 +
 MAINTAINERS|   7 +
 drivers/base/regmap/regmap.c   |  65 +-
 drivers/iio/accel/Kconfig  |  11 +
 drivers/iio/accel/Makefile |   1 +
 drivers/iio/accel/adxl372.c| 980 +
 include/linux/regmap.h |   9 +
 7 files changed, 1096 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/iio/accel/adxl372.txt
 create mode 100644 drivers/iio/accel/adxl372.c

-- 
2.7.4



[PATCH v2 3/6] regmap: Add regmap_pipe_read API

2018-08-01 Thread Stefan Popa
From: Crestez Dan Leonard 

The regmap API usually assumes that bulk read operations will read a
range of registers but some I2C/SPI devices have certain registers for
which a such a read operation will return data from an internal FIFO
instead. Add an explicit API to support bulk read with pipe rather than
range semantics.

Some linux drivers use regmap_bulk_read or regmap_raw_read for such
registers, for example mpu6050 or bmi150 from IIO. This only happens to
work because when caching is disabled a single regmap read op will map
to a single bus read op (as desired). This breaks if caching is enabled and
reg+1 happens to be a cacheable register.

Without regmap support refactoring a driver to enable regmap caching
requires separate I2C and SPI paths. This is exactly what regmap is
supposed to help avoid.

Suggested-by: Jonathan Cameron 
Signed-off-by: Crestez Dan Leonard 
Signed-off-by: Stefan Popa 
---
Changes in v2:
Included as part of this patch series as the regmap_pipe_read()
API will be used to read the data from the FIFO.

 drivers/base/regmap/regmap.c | 64 +++-
 include/linux/regmap.h   |  9 +++
 2 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 3bc8488..73bacbd 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -2564,7 +2564,69 @@ int regmap_raw_read(struct regmap *map, unsigned int 
reg, void *val,
 EXPORT_SYMBOL_GPL(regmap_raw_read);
 
 /**
- * regmap_field_read() - Read a value to a single register field
+ * regmap_pipe_read(): Read data from a register with pipe semantics
+ *
+ * @map: Register map to read from
+ * @reg: Register to read from
+ * @val: Pointer to data buffer
+ * @val_len: Length of output buffer in bytes.
+ *
+ * The regmap API usually assumes that bulk bus read operations will read a
+ * range of registers. Some devices have certain registers for which a read
+ * operation read will read from an internal FIFO.
+ *
+ * The target register must be volatile but registers after it can be
+ * completely unrelated cacheable registers.
+ *
+ * This will attempt multiple reads as required to read val_len bytes.
+ *
+ * A value of zero will be returned on success, a negative errno will be
+ * returned in error cases.
+ */
+int regmap_pipe_read(struct regmap *map, unsigned int reg,
+void *val, size_t val_len)
+{
+   size_t read_len;
+   int ret;
+
+   if (!map->bus)
+   return -EINVAL;
+   if (!map->bus->read)
+   return -ENOTSUPP;
+   if (val_len % map->format.val_bytes)
+   return -EINVAL;
+   if (!IS_ALIGNED(reg, map->reg_stride))
+   return -EINVAL;
+   if (val_len == 0)
+   return -EINVAL;
+
+   map->lock(map->lock_arg);
+
+   if (!regmap_volatile(map, reg)) {
+   ret = -EINVAL;
+   goto out_unlock;
+   }
+
+   while (val_len) {
+   if (map->max_raw_read && map->max_raw_read < val_len)
+   read_len = map->max_raw_read;
+   else
+   read_len = val_len;
+   ret = _regmap_raw_read(map, reg, val, read_len);
+   if (ret)
+   goto out_unlock;
+   val = ((u8 *)val) + read_len;
+   val_len -= read_len;
+   }
+
+out_unlock:
+   map->unlock(map->lock_arg);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_pipe_read);
+
+/**
+ * regmap_field_read(): Read a value to a single register field
  *
  * @field: Register field to read from
  * @val: Pointer to store read value
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 4f38068..91c5cb6 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -946,6 +946,8 @@ int regmap_raw_write_async(struct regmap *map, unsigned int 
reg,
 int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);
 int regmap_raw_read(struct regmap *map, unsigned int reg,
void *val, size_t val_len);
+int regmap_pipe_read(struct regmap *map, unsigned int reg,
+void *val, size_t val_len);
 int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
 size_t val_count);
 int regmap_update_bits_base(struct regmap *map, unsigned int reg,
@@ -1196,6 +1198,13 @@ static inline int regmap_raw_read(struct regmap *map, 
unsigned int reg,
return -EINVAL;
 }
 
+static inline int regmap_pipe_read(struct regmap *map, unsigned int reg,
+  void *val, size_t val_len)
+{
+   WARN_ONCE(1, "regmap API is disabled");
+   return -EINVAL;
+}
+
 static inline int regmap_bulk_read(struct regmap *map, unsigned int reg,
   void *val, size_t val_count)
 {
-- 
2.7.4



[PATCH v2 5/6] iio:adxl372: Add sampling frequency support

2018-08-01 Thread Stefan Popa
This patch adds the option for the user to select the sampling frequency.
Also, the user can read the available frequencies and read the currently
set frequency via the read_raw function. The frequency can be set via the
write_raw function.

When the frequency is set, the bandwidth is also checked and ensured
that it is constrained to at most half of the sampling frequency. Also, the
activity and inactivity timers have to be updated because they depend on
the selected ODR.

Signed-off-by: Stefan Popa 
---
Changes in v2:
- nothing changed.

 drivers/iio/accel/adxl372.c | 74 -
 1 file changed, 73 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 68862bf..d9e4826 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -217,7 +217,8 @@ static const struct adxl372_axis_lookup 
adxl372_axis_lookup_table[] = {
.modified = 1,  \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
-   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
+   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
.scan_index = index,\
.scan_type = {  \
.sign = 's',\
@@ -325,6 +326,19 @@ static int adxl372_set_odr(struct adxl372_state *st,
return ret;
 }
 
+static int adxl372_find_closest_match(const int *array,
+ unsigned int size, int val)
+{
+   int i;
+
+   for (i = 0; i < size; i++) {
+   if (val <= array[i])
+   return i;
+   }
+
+   return size - 1;
+}
+
 static int adxl372_set_bandwidth(struct adxl372_state *st,
 enum adxl372_bandwidth bw)
 {
@@ -651,6 +665,51 @@ static int adxl372_read_raw(struct iio_dev *indio_dev,
*val = 0;
*val2 = ADXL372_USCALE;
return IIO_VAL_INT_PLUS_MICRO;
+   case IIO_CHAN_INFO_SAMP_FREQ:
+   *val = adxl372_samp_freq_tbl[st->odr];
+   return IIO_VAL_INT;
+   }
+
+   return -EINVAL;
+}
+
+static int adxl372_write_raw(struct iio_dev *indio_dev,
+struct iio_chan_spec const *chan,
+int val, int val2, long info)
+{
+   struct adxl372_state *st = iio_priv(indio_dev);
+   int odr_index, ret;
+
+   switch (info) {
+   case IIO_CHAN_INFO_SAMP_FREQ:
+   odr_index = adxl372_find_closest_match(adxl372_samp_freq_tbl,
+   ARRAY_SIZE(adxl372_samp_freq_tbl),
+   val);
+   ret = adxl372_set_odr(st, odr_index);
+   if (ret < 0)
+   return ret;
+   /*
+* The timer period depends on the ODR selected.
+* At 3200 Hz and below, it is 6.6 ms; at 6400 Hz, it is 3.3 ms
+*/
+   ret = adxl372_set_activity_time_ms(st, st->act_time_ms);
+   if (ret < 0)
+   return ret;
+   /*
+* The timer period depends on the ODR selected.
+* At 3200 Hz and below, it is 26 ms; at 6400 Hz, it is 13 ms
+*/
+   ret = adxl372_set_inactivity_time_ms(st, st->inact_time_ms);
+   if (ret < 0)
+   return ret;
+   /*
+* The maximum bandwidth is constrained to at most half of
+* the ODR to ensure that the Nyquist criteria is not violated
+*/
+   if (st->bw > odr_index)
+   ret = adxl372_set_bandwidth(st, odr_index);
+
+   return ret;
default:
return -EINVAL;
}
@@ -782,8 +841,21 @@ static const struct iio_trigger_ops adxl372_trigger_ops = {
.set_trigger_state = adxl372_dready_trig_set_state,
 };
 
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400");
+
+static struct attribute *adxl372_attributes[] = {
+   _const_attr_sampling_frequency_available.dev_attr.attr,
+   NULL,
+};
+
+static const struct attribute_group adxl372_attrs_group = {
+   .attrs = adxl372_attributes,
+};
+
 static const struct iio_info adxl372_info = {
+   .attrs = _attrs_group,
.read_raw = adxl372_read_raw,
+   .write_raw = adxl372_write_raw,
.debugfs_reg_access = _reg_access,
.hwfifo_set_watermark = adxl372_set_watermark,
 };
-- 
2.7.4



[PATCH v2 4/6] iio:adxl372: Add FIFO and interrupts support

2018-08-01 Thread Stefan Popa
This patch adds support for the adxl372 FIFO. In order to accomplish this,
triggered buffers were used.

The number of FIFO samples which trigger the watermark interrupt can be
configured by using the buffer watermark. The FIFO format is determined by
configuring the scan elements for each axis. Moreover, the FIFO can also
be configured in the XYZ peak mode.

The FIFO data is pushed to the IIO device's buffer.

Signed-off-by: Stefan Popa 
---
Changes in v2:
- removed DT bindings changes from this patch.
- removed the linux/gpio/consumer.h header.
- used regmap_pipe_read() instead of regmap_bulk_read() when
  reading data from the FIFO.
- used multiple regmap_write() calls instead of a single
  regmap_bulk_write() if there is no fast path.
- used be32_to_cpu() inside the adxl372_get_status() function.
- added a new in_accel_x_peak scan element which allows the
  user to set the FIFO into XYZ peak mode.
- used a adxl372_axis_lookup_table() to determine the fifo format
  from the active_scan_mask.
- made IRQ optional.

 drivers/iio/accel/adxl372.c | 362 +++-
 1 file changed, 361 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 7d5092d..68862bf 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -6,12 +6,19 @@
  */
 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
 
 /* ADXL372 registers definition */
 #define ADXL372_DEVID  0x00
@@ -123,6 +130,8 @@
 #define ADXL372_INT1_MAP_LOW_MSK   BIT(7)
 #define ADXL372_INT1_MAP_LOW_MODE(x)   (((x) & 0x1) << 7)
 
+#define ADXL372_FIFO_SIZE  512
+
 /*
  * At +/- 200g with 12-bit resolution, scale is computed as:
  * (200 + 200) * 9.81 / (2^12 - 1) = 0.958241
@@ -164,6 +173,44 @@ enum adxl372_bandwidth {
ADXL372_BW_3200HZ,
 };
 
+enum adxl372_fifo_format {
+   ADXL372_XYZ_FIFO,
+   ADXL372_X_FIFO,
+   ADXL372_Y_FIFO,
+   ADXL372_XY_FIFO,
+   ADXL372_Z_FIFO,
+   ADXL372_XZ_FIFO,
+   ADXL372_YZ_FIFO,
+   ADXL372_XYZ_PEAK_FIFO,
+};
+
+enum adxl372_fifo_mode {
+   ADXL372_FIFO_BYPASSED,
+   ADXL372_FIFO_STREAMED,
+   ADXL372_FIFO_TRIGGERED,
+   ADXL372_FIFO_OLD_SAVED
+};
+
+static const int adxl372_samp_freq_tbl[5] = {
+   400, 800, 1600, 3200, 6400,
+};
+
+struct adxl372_axis_lookup {
+   unsigned int bits;
+   enum adxl372_fifo_format fifo_format;
+};
+
+static const struct adxl372_axis_lookup adxl372_axis_lookup_table[] = {
+   { BIT(0), ADXL372_X_FIFO },
+   { BIT(1), ADXL372_Y_FIFO },
+   { BIT(2), ADXL372_Z_FIFO },
+   { BIT(0) | BIT(1), ADXL372_XY_FIFO },
+   { BIT(0) | BIT(2), ADXL372_XZ_FIFO },
+   { BIT(1) | BIT(2), ADXL372_YZ_FIFO },
+   { BIT(0) | BIT(1) | BIT(2), ADXL372_XYZ_FIFO },
+   { BIT(3), ADXL372_XYZ_PEAK_FIFO }
+};
+
 #define ADXL372_ACCEL_CHANNEL(index, reg, axis) {  \
.type = IIO_ACCEL,  \
.address = reg, \
@@ -171,25 +218,69 @@ enum adxl372_bandwidth {
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
+   .scan_index = index,\
+   .scan_type = {  \
+   .sign = 's',\
+   .realbits = 12, \
+   .storagebits = 16,  \
+   .shift = 4, \
+   },  \
 }
 
 static const struct iio_chan_spec adxl372_channels[] = {
ADXL372_ACCEL_CHANNEL(0, ADXL372_X_DATA_H, X),
ADXL372_ACCEL_CHANNEL(1, ADXL372_Y_DATA_H, Y),
ADXL372_ACCEL_CHANNEL(2, ADXL372_Z_DATA_H, Z),
+   {
+   .type = IIO_ACCEL,
+   .modified = 1,
+   .channel2 = IIO_MOD_X_AND_Y_AND_Z,
+   .extend_name = "peak",
+   .scan_index = 3,
+   .scan_type = {
+   .sign = 's',
+   .realbits = 12,
+   .storagebits = 16,
+   .shift = 4,
+   }
+   }
 };
 
 struct adxl372_state {
struct spi_device   *spi;
struct regmap   *regmap;
+   struct iio_trigger  *dready_trig;
+   enum adxl372_fifo_mode  fif

[PATCH v2 6/6] iio:adxl372: Add filter bandwidth support

2018-08-01 Thread Stefan Popa
This patch adds the option for the user to select the filter bandwidth. The
user can also read the available bandwidths which are always adjusted to be
at most half of the sampling frequency. Furthermore, the currently selected
bandwidth can be read via the read_raw function, while the write_raw sets a
new bandwidth value.

Signed-off-by: Stefan Popa 
---
Changes in v2:
- nothing changed.

 drivers/iio/accel/adxl372.c | 38 --
 1 file changed, 36 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index d9e4826..5c55bed 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -195,6 +195,10 @@ static const int adxl372_samp_freq_tbl[5] = {
400, 800, 1600, 3200, 6400,
 };
 
+static const int adxl372_bw_freq_tbl[5] = {
+   200, 400, 800, 1600, 3200,
+};
+
 struct adxl372_axis_lookup {
unsigned int bits;
enum adxl372_fifo_format fifo_format;
@@ -218,7 +222,8 @@ static const struct adxl372_axis_lookup 
adxl372_axis_lookup_table[] = {
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
-   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ) |  \
+   BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),   \
.scan_index = index,\
.scan_type = {  \
.sign = 's',\
@@ -668,6 +673,9 @@ static int adxl372_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SAMP_FREQ:
*val = adxl372_samp_freq_tbl[st->odr];
return IIO_VAL_INT;
+   case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+   *val = adxl372_bw_freq_tbl[st->bw];
+   return IIO_VAL_INT;
}
 
return -EINVAL;
@@ -678,7 +686,7 @@ static int adxl372_write_raw(struct iio_dev *indio_dev,
 int val, int val2, long info)
 {
struct adxl372_state *st = iio_priv(indio_dev);
-   int odr_index, ret;
+   int odr_index, bw_index, ret;
 
switch (info) {
case IIO_CHAN_INFO_SAMP_FREQ:
@@ -710,11 +718,34 @@ static int adxl372_write_raw(struct iio_dev *indio_dev,
ret = adxl372_set_bandwidth(st, odr_index);
 
return ret;
+   case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+   bw_index = adxl372_find_closest_match(adxl372_bw_freq_tbl,
+   ARRAY_SIZE(adxl372_bw_freq_tbl),
+   val);
+   return adxl372_set_bandwidth(st, bw_index);
default:
return -EINVAL;
}
 }
 
+static ssize_t adxl372_show_filter_freq_avail(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+   struct adxl372_state *st = iio_priv(indio_dev);
+   int i;
+   size_t len = 0;
+
+   for (i = 0; i <= st->odr; i++)
+   len += scnprintf(buf + len, PAGE_SIZE - len,
+"%d ", adxl372_bw_freq_tbl[i]);
+
+   buf[len - 1] = '\n';
+
+   return len;
+}
+
 static ssize_t adxl372_get_fifo_enabled(struct device *dev,
  struct device_attribute *attr,
  char *buf)
@@ -842,9 +873,12 @@ static const struct iio_trigger_ops adxl372_trigger_ops = {
 };
 
 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400");
+static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available,
+  0444, adxl372_show_filter_freq_avail, NULL, 0);
 
 static struct attribute *adxl372_attributes[] = {
_const_attr_sampling_frequency_available.dev_attr.attr,
+   
_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr,
NULL,
 };
 
-- 
2.7.4



[PATCH v4 3/6] regmap: Add regmap_noinc_read API

2018-08-06 Thread Stefan Popa
From: Crestez Dan Leonard 

The regmap API usually assumes that bulk read operations will read a
range of registers but some I2C/SPI devices have certain registers for
which a such a read operation will return data from an internal FIFO
instead. Add an explicit API to support bulk read without range semantics.

Some linux drivers use regmap_bulk_read or regmap_raw_read for such
registers, for example mpu6050 or bmi150 from IIO. This only happens to
work because when caching is disabled a single regmap read op will map
to a single bus read op (as desired). This breaks if caching is enabled and
reg+1 happens to be a cacheable register.

Without regmap support refactoring a driver to enable regmap caching
requires separate I2C and SPI paths. This is exactly what regmap is
supposed to help avoid.

Suggested-by: Jonathan Cameron 
Signed-off-by: Crestez Dan Leonard 
Signed-off-by: Stefan Popa 
---
 drivers/base/regmap/regmap.c | 65 +++-
 include/linux/regmap.h   |  9 ++
 2 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 3bc8488..e632503 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -2564,7 +2564,70 @@ int regmap_raw_read(struct regmap *map, unsigned int 
reg, void *val,
 EXPORT_SYMBOL_GPL(regmap_raw_read);
 
 /**
- * regmap_field_read() - Read a value to a single register field
+ * regmap_noinc_read(): Read data from a register without incrementing the
+ * register number
+ *
+ * @map: Register map to read from
+ * @reg: Register to read from
+ * @val: Pointer to data buffer
+ * @val_len: Length of output buffer in bytes.
+ *
+ * The regmap API usually assumes that bulk bus read operations will read a
+ * range of registers. Some devices have certain registers for which a read
+ * operation read will read from an internal FIFO.
+ *
+ * The target register must be volatile but registers after it can be
+ * completely unrelated cacheable registers.
+ *
+ * This will attempt multiple reads as required to read val_len bytes.
+ *
+ * A value of zero will be returned on success, a negative errno will be
+ * returned in error cases.
+ */
+int regmap_noinc_read(struct regmap *map, unsigned int reg,
+ void *val, size_t val_len)
+{
+   size_t read_len;
+   int ret;
+
+   if (!map->bus)
+   return -EINVAL;
+   if (!map->bus->read)
+   return -ENOTSUPP;
+   if (val_len % map->format.val_bytes)
+   return -EINVAL;
+   if (!IS_ALIGNED(reg, map->reg_stride))
+   return -EINVAL;
+   if (val_len == 0)
+   return -EINVAL;
+
+   map->lock(map->lock_arg);
+
+   if (!regmap_volatile(map, reg) || !regmap_readable(map, reg)) {
+   ret = -EINVAL;
+   goto out_unlock;
+   }
+
+   while (val_len) {
+   if (map->max_raw_read && map->max_raw_read < val_len)
+   read_len = map->max_raw_read;
+   else
+   read_len = val_len;
+   ret = _regmap_raw_read(map, reg, val, read_len);
+   if (ret)
+   goto out_unlock;
+   val = ((u8 *)val) + read_len;
+   val_len -= read_len;
+   }
+
+out_unlock:
+   map->unlock(map->lock_arg);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_noinc_read);
+
+/**
+ * regmap_field_read(): Read a value to a single register field
  *
  * @field: Register field to read from
  * @val: Pointer to store read value
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 4f38068..ddaa5e6 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -946,6 +946,8 @@ int regmap_raw_write_async(struct regmap *map, unsigned int 
reg,
 int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);
 int regmap_raw_read(struct regmap *map, unsigned int reg,
void *val, size_t val_len);
+int regmap_noinc_read(struct regmap *map, unsigned int reg,
+ void *val, size_t val_len);
 int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
 size_t val_count);
 int regmap_update_bits_base(struct regmap *map, unsigned int reg,
@@ -1196,6 +1198,13 @@ static inline int regmap_raw_read(struct regmap *map, 
unsigned int reg,
return -EINVAL;
 }
 
+static inline int regmap_noinc_read(struct regmap *map, unsigned int reg,
+   void *val, size_t val_len)
+{
+   WARN_ONCE(1, "regmap API is disabled");
+   return -EINVAL;
+}
+
 static inline int regmap_bulk_read(struct regmap *map, unsigned int reg,
   void *val, size_t val_count)
 {
-- 
2.7.4



[PATCH v4 6/6] iio:adxl372: Add filter bandwidth support

2018-08-06 Thread Stefan Popa
This patch adds the option for the user to select the filter bandwidth. The
user can also read the available bandwidths which are always adjusted to be
at most half of the sampling frequency. Furthermore, the currently selected
bandwidth can be read via the read_raw function, while the write_raw sets a
new bandwidth value.

Signed-off-by: Stefan Popa 
---
 drivers/iio/accel/adxl372.c | 38 --
 1 file changed, 36 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index d991d1c..58e2f61 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -202,6 +202,10 @@ static const int adxl372_samp_freq_tbl[5] = {
400, 800, 1600, 3200, 6400,
 };
 
+static const int adxl372_bw_freq_tbl[5] = {
+   200, 400, 800, 1600, 3200,
+};
+
 struct adxl372_axis_lookup {
unsigned int bits;
enum adxl372_fifo_format fifo_format;
@@ -224,7 +228,8 @@ static const struct adxl372_axis_lookup 
adxl372_axis_lookup_table[] = {
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
-   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ) |  \
+   BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),   \
.scan_index = index,\
.scan_type = {  \
.sign = 's',\
@@ -648,6 +653,9 @@ static int adxl372_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SAMP_FREQ:
*val = adxl372_samp_freq_tbl[st->odr];
return IIO_VAL_INT;
+   case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+   *val = adxl372_bw_freq_tbl[st->bw];
+   return IIO_VAL_INT;
}
 
return -EINVAL;
@@ -658,7 +666,7 @@ static int adxl372_write_raw(struct iio_dev *indio_dev,
 int val, int val2, long info)
 {
struct adxl372_state *st = iio_priv(indio_dev);
-   int odr_index, ret;
+   int odr_index, bw_index, ret;
 
switch (info) {
case IIO_CHAN_INFO_SAMP_FREQ:
@@ -690,11 +698,34 @@ static int adxl372_write_raw(struct iio_dev *indio_dev,
ret = adxl372_set_bandwidth(st, odr_index);
 
return ret;
+   case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+   bw_index = adxl372_find_closest_match(adxl372_bw_freq_tbl,
+   ARRAY_SIZE(adxl372_bw_freq_tbl),
+   val);
+   return adxl372_set_bandwidth(st, bw_index);
default:
return -EINVAL;
}
 }
 
+static ssize_t adxl372_show_filter_freq_avail(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+   struct adxl372_state *st = iio_priv(indio_dev);
+   int i;
+   size_t len = 0;
+
+   for (i = 0; i <= st->odr; i++)
+   len += scnprintf(buf + len, PAGE_SIZE - len,
+"%d ", adxl372_bw_freq_tbl[i]);
+
+   buf[len - 1] = '\n';
+
+   return len;
+}
+
 static ssize_t adxl372_get_fifo_enabled(struct device *dev,
  struct device_attribute *attr,
  char *buf)
@@ -823,9 +854,12 @@ static const struct iio_trigger_ops adxl372_trigger_ops = {
 };
 
 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400");
+static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available,
+  0444, adxl372_show_filter_freq_avail, NULL, 0);
 
 static struct attribute *adxl372_attributes[] = {
_const_attr_sampling_frequency_available.dev_attr.attr,
+   
_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr,
NULL,
 };
 
-- 
2.7.4



[PATCH v4 5/6] iio:adxl372: Add sampling frequency support

2018-08-06 Thread Stefan Popa
This patch adds the option for the user to select the sampling frequency.
Also, the user can read the available frequencies and read the currently
set frequency via the read_raw function. The frequency can be set via the
write_raw function.

When the frequency is set, the bandwidth is also checked and ensured
that it is constrained to at most half of the sampling frequency. Also, the
activity and inactivity timers have to be updated because they depend on
the selected ODR.

Signed-off-by: Stefan Popa 
---
 drivers/iio/accel/adxl372.c | 74 -
 1 file changed, 73 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 623c32d..d991d1c 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -223,7 +223,8 @@ static const struct adxl372_axis_lookup 
adxl372_axis_lookup_table[] = {
.modified = 1,  \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
-   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
+   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
.scan_index = index,\
.scan_type = {  \
.sign = 's',\
@@ -311,6 +312,19 @@ static int adxl372_set_odr(struct adxl372_state *st,
return ret;
 }
 
+static int adxl372_find_closest_match(const int *array,
+ unsigned int size, int val)
+{
+   int i;
+
+   for (i = 0; i < size; i++) {
+   if (val <= array[i])
+   return i;
+   }
+
+   return size - 1;
+}
+
 static int adxl372_set_bandwidth(struct adxl372_state *st,
 enum adxl372_bandwidth bw)
 {
@@ -631,6 +645,51 @@ static int adxl372_read_raw(struct iio_dev *indio_dev,
*val = 0;
*val2 = ADXL372_USCALE;
return IIO_VAL_INT_PLUS_MICRO;
+   case IIO_CHAN_INFO_SAMP_FREQ:
+   *val = adxl372_samp_freq_tbl[st->odr];
+   return IIO_VAL_INT;
+   }
+
+   return -EINVAL;
+}
+
+static int adxl372_write_raw(struct iio_dev *indio_dev,
+struct iio_chan_spec const *chan,
+int val, int val2, long info)
+{
+   struct adxl372_state *st = iio_priv(indio_dev);
+   int odr_index, ret;
+
+   switch (info) {
+   case IIO_CHAN_INFO_SAMP_FREQ:
+   odr_index = adxl372_find_closest_match(adxl372_samp_freq_tbl,
+   ARRAY_SIZE(adxl372_samp_freq_tbl),
+   val);
+   ret = adxl372_set_odr(st, odr_index);
+   if (ret < 0)
+   return ret;
+   /*
+* The timer period depends on the ODR selected.
+* At 3200 Hz and below, it is 6.6 ms; at 6400 Hz, it is 3.3 ms
+*/
+   ret = adxl372_set_activity_time_ms(st, st->act_time_ms);
+   if (ret < 0)
+   return ret;
+   /*
+* The timer period depends on the ODR selected.
+* At 3200 Hz and below, it is 26 ms; at 6400 Hz, it is 13 ms
+*/
+   ret = adxl372_set_inactivity_time_ms(st, st->inact_time_ms);
+   if (ret < 0)
+   return ret;
+   /*
+* The maximum bandwidth is constrained to at most half of
+* the ODR to ensure that the Nyquist criteria is not violated
+*/
+   if (st->bw > odr_index)
+   ret = adxl372_set_bandwidth(st, odr_index);
+
+   return ret;
default:
return -EINVAL;
}
@@ -763,8 +822,21 @@ static const struct iio_trigger_ops adxl372_trigger_ops = {
.set_trigger_state = adxl372_dready_trig_set_state,
 };
 
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400");
+
+static struct attribute *adxl372_attributes[] = {
+   _const_attr_sampling_frequency_available.dev_attr.attr,
+   NULL,
+};
+
+static const struct attribute_group adxl372_attrs_group = {
+   .attrs = adxl372_attributes,
+};
+
 static const struct iio_info adxl372_info = {
+   .attrs = _attrs_group,
.read_raw = adxl372_read_raw,
+   .write_raw = adxl372_write_raw,
.debugfs_reg_access = _reg_access,
.hwfifo_set_watermark = adxl372_set_watermark,
 };
-- 
2.7.4



[PATCH v5 5/6] iio:adxl372: Add sampling frequency support

2018-08-07 Thread Stefan Popa
This patch adds the option for the user to select the sampling frequency.
Also, the user can read the available frequencies and read the currently
set frequency via the read_raw function. The frequency can be set via the
write_raw function.

When the frequency is set, the bandwidth is also checked and ensured
that it is constrained to at most half of the sampling frequency. Also, the
activity and inactivity timers have to be updated because they depend on
the selected ODR.

Signed-off-by: Stefan Popa 
---
 drivers/iio/accel/adxl372.c | 74 -
 1 file changed, 73 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index dfdceeb..76c4a1d 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -223,7 +223,8 @@ static const struct adxl372_axis_lookup 
adxl372_axis_lookup_table[] = {
.modified = 1,  \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
-   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
+   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
.scan_index = index,\
.scan_type = {  \
.sign = 's',\
@@ -311,6 +312,19 @@ static int adxl372_set_odr(struct adxl372_state *st,
return ret;
 }
 
+static int adxl372_find_closest_match(const int *array,
+ unsigned int size, int val)
+{
+   int i;
+
+   for (i = 0; i < size; i++) {
+   if (val <= array[i])
+   return i;
+   }
+
+   return size - 1;
+}
+
 static int adxl372_set_bandwidth(struct adxl372_state *st,
 enum adxl372_bandwidth bw)
 {
@@ -631,6 +645,51 @@ static int adxl372_read_raw(struct iio_dev *indio_dev,
*val = 0;
*val2 = ADXL372_USCALE;
return IIO_VAL_INT_PLUS_MICRO;
+   case IIO_CHAN_INFO_SAMP_FREQ:
+   *val = adxl372_samp_freq_tbl[st->odr];
+   return IIO_VAL_INT;
+   }
+
+   return -EINVAL;
+}
+
+static int adxl372_write_raw(struct iio_dev *indio_dev,
+struct iio_chan_spec const *chan,
+int val, int val2, long info)
+{
+   struct adxl372_state *st = iio_priv(indio_dev);
+   int odr_index, ret;
+
+   switch (info) {
+   case IIO_CHAN_INFO_SAMP_FREQ:
+   odr_index = adxl372_find_closest_match(adxl372_samp_freq_tbl,
+   ARRAY_SIZE(adxl372_samp_freq_tbl),
+   val);
+   ret = adxl372_set_odr(st, odr_index);
+   if (ret < 0)
+   return ret;
+   /*
+* The timer period depends on the ODR selected.
+* At 3200 Hz and below, it is 6.6 ms; at 6400 Hz, it is 3.3 ms
+*/
+   ret = adxl372_set_activity_time_ms(st, st->act_time_ms);
+   if (ret < 0)
+   return ret;
+   /*
+* The timer period depends on the ODR selected.
+* At 3200 Hz and below, it is 26 ms; at 6400 Hz, it is 13 ms
+*/
+   ret = adxl372_set_inactivity_time_ms(st, st->inact_time_ms);
+   if (ret < 0)
+   return ret;
+   /*
+* The maximum bandwidth is constrained to at most half of
+* the ODR to ensure that the Nyquist criteria is not violated
+*/
+   if (st->bw > odr_index)
+   ret = adxl372_set_bandwidth(st, odr_index);
+
+   return ret;
default:
return -EINVAL;
}
@@ -763,8 +822,21 @@ static const struct iio_trigger_ops adxl372_trigger_ops = {
.set_trigger_state = adxl372_dready_trig_set_state,
 };
 
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400");
+
+static struct attribute *adxl372_attributes[] = {
+   _const_attr_sampling_frequency_available.dev_attr.attr,
+   NULL,
+};
+
+static const struct attribute_group adxl372_attrs_group = {
+   .attrs = adxl372_attributes,
+};
+
 static const struct iio_info adxl372_info = {
+   .attrs = _attrs_group,
.read_raw = adxl372_read_raw,
+   .write_raw = adxl372_write_raw,
.debugfs_reg_access = _reg_access,
.hwfifo_set_watermark = adxl372_set_watermark,
 };
-- 
2.7.4



[PATCH v5 4/6] iio:adxl372: Add FIFO and interrupts support

2018-08-07 Thread Stefan Popa
This patch adds support for the adxl372 FIFO. In order to accomplish this,
triggered buffers were used.

The number of FIFO samples which trigger the watermark interrupt can be
configured by using the buffer watermark. The FIFO format is determined by
configuring the scan elements for each axis. The FIFO data is pushed to the
IIO device's buffer.

Signed-off-by: Stefan Popa 
---
 drivers/iio/accel/adxl372.c | 354 +++-
 1 file changed, 353 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index db9ecd2..dfdceeb 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -6,12 +6,19 @@
  */
 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
 
 /* ADXL372 registers definition */
 #define ADXL372_DEVID  0x00
@@ -123,6 +130,9 @@
 #define ADXL372_INT1_MAP_LOW_MSK   BIT(7)
 #define ADXL372_INT1_MAP_LOW_MODE(x)   (((x) & 0x1) << 7)
 
+/* The ADXL372 includes a deep, 512 sample FIFO buffer */
+#define ADXL372_FIFO_SIZE  512
+
 /*
  * At +/- 200g with 12-bit resolution, scale is computed as:
  * (200 + 200) * 9.81 / (2^12 - 1) = 0.958241
@@ -170,6 +180,43 @@ static const unsigned int adxl372_th_reg_high_addr[3] = {
[ADXL372_INACTIVITY] = ADXL372_X_THRESH_INACT_H,
 };
 
+enum adxl372_fifo_format {
+   ADXL372_XYZ_FIFO,
+   ADXL372_X_FIFO,
+   ADXL372_Y_FIFO,
+   ADXL372_XY_FIFO,
+   ADXL372_Z_FIFO,
+   ADXL372_XZ_FIFO,
+   ADXL372_YZ_FIFO,
+   ADXL372_XYZ_PEAK_FIFO,
+};
+
+enum adxl372_fifo_mode {
+   ADXL372_FIFO_BYPASSED,
+   ADXL372_FIFO_STREAMED,
+   ADXL372_FIFO_TRIGGERED,
+   ADXL372_FIFO_OLD_SAVED
+};
+
+static const int adxl372_samp_freq_tbl[5] = {
+   400, 800, 1600, 3200, 6400,
+};
+
+struct adxl372_axis_lookup {
+   unsigned int bits;
+   enum adxl372_fifo_format fifo_format;
+};
+
+static const struct adxl372_axis_lookup adxl372_axis_lookup_table[] = {
+   { BIT(0), ADXL372_X_FIFO },
+   { BIT(1), ADXL372_Y_FIFO },
+   { BIT(2), ADXL372_Z_FIFO },
+   { BIT(0) | BIT(1), ADXL372_XY_FIFO },
+   { BIT(0) | BIT(2), ADXL372_XZ_FIFO },
+   { BIT(1) | BIT(2), ADXL372_YZ_FIFO },
+   { BIT(0) | BIT(1) | BIT(2), ADXL372_XYZ_FIFO },
+};
+
 #define ADXL372_ACCEL_CHANNEL(index, reg, axis) {  \
.type = IIO_ACCEL,  \
.address = reg, \
@@ -177,6 +224,13 @@ static const unsigned int adxl372_th_reg_high_addr[3] = {
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
+   .scan_index = index,\
+   .scan_type = {  \
+   .sign = 's',\
+   .realbits = 12, \
+   .storagebits = 16,  \
+   .shift = 4, \
+   },  \
 }
 
 static const struct iio_chan_spec adxl372_channels[] = {
@@ -188,12 +242,29 @@ static const struct iio_chan_spec adxl372_channels[] = {
 struct adxl372_state {
struct spi_device   *spi;
struct regmap   *regmap;
+   struct iio_trigger  *dready_trig;
+   enum adxl372_fifo_mode  fifo_mode;
+   enum adxl372_fifo_formatfifo_format;
enum adxl372_op_modeop_mode;
enum adxl372_act_proc_mode  act_proc_mode;
enum adxl372_odrodr;
enum adxl372_bandwidth  bw;
u32 act_time_ms;
u32 inact_time_ms;
+   u8  fifo_set_size;
+   u8  int1_bitmask;
+   u8  int2_bitmask;
+   u16 watermark;
+   __be16  fifo_buf[ADXL372_FIFO_SIZE];
+};
+
+static const unsigned long adxl372_channel_masks[] = {
+   BIT(0), BIT(1), BIT(2),
+   BIT(0) | BIT(1),
+   BIT(0) | BIT(2),
+   BIT(1) | BIT(2),
+   BIT(0) | BIT(1) | BIT(2),
+   0
 };
 
 static int adxl372_read_axis(struct adxl372_state *st, u8 addr)
@@ -359,6 +430,112 @@ static int adxl372_set_inactivity_time_ms(struct 
adxl372_state *st,
return ret;
 }
 
+static int adxl372_set_interrupts(struct adxl372_state *st,
+ unsigned char in

[PATCH v5 1/6] iio: adxl372: New driver for Analog Devices ADXL372 Accelerometer

2018-08-07 Thread Stefan Popa
This patch adds basic support for Analog Devices ADXL372 SPI-Bus
Three-Axis Digital Accelerometer.

The device is probed and configured the with some initial default
values. With this basic driver, it is possible to read raw acceleration
data.

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL372.pdf

Signed-off-by: Stefan Popa 
---
 MAINTAINERS |   6 +
 drivers/iio/accel/Kconfig   |  11 +
 drivers/iio/accel/Makefile  |   1 +
 drivers/iio/accel/adxl372.c | 525 
 4 files changed, 543 insertions(+)
 create mode 100644 drivers/iio/accel/adxl372.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 60b1028..2ba47bb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -543,6 +543,12 @@ W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/input/misc/adxl34x.c
 
+ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
+M: Stefan Popa 
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/accel/adxl372.c
+
 AF9013 MEDIA DRIVER
 M: Antti Palosaari 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 62ae7e5..1b496ef 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -60,6 +60,17 @@ config ADXL345_SPI
  will be called adxl345_spi and you will also get adxl345_core
  for the core module.
 
+config ADXL372
+   tristate "Analog Devices ADXL372 3-Axis Accelerometer Driver"
+   depends on SPI
+   select IIO_BUFFER
+   select IIO_TRIGGERED_BUFFER
+   help
+ Say yes here to add support for the Analog Devices ADXL372 triaxial
+ acceleration sensor.
+ To compile this driver as a module, choose M here: the
+ module will be called adxl372.
+
 config BMA180
tristate "Bosch BMA180/BMA250 3-Axis Accelerometer Driver"
depends on I2C
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index 636d4d1..5758ffc 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_ADIS16209) += adis16209.o
 obj-$(CONFIG_ADXL345) += adxl345_core.o
 obj-$(CONFIG_ADXL345_I2C) += adxl345_i2c.o
 obj-$(CONFIG_ADXL345_SPI) += adxl345_spi.o
+obj-$(CONFIG_ADXL372) += adxl372.o
 obj-$(CONFIG_BMA180) += bma180.o
 obj-$(CONFIG_BMA220) += bma220_spi.o
 obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
new file mode 100644
index 000..db9ecd2
--- /dev/null
+++ b/drivers/iio/accel/adxl372.c
@@ -0,0 +1,525 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * ADXL372 3-Axis Digital Accelerometer SPI driver
+ *
+ * Copyright 2018 Analog Devices Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+/* ADXL372 registers definition */
+#define ADXL372_DEVID  0x00
+#define ADXL372_DEVID_MST  0x01
+#define ADXL372_PARTID 0x02
+#define ADXL372_REVID  0x03
+#define ADXL372_STATUS_1   0x04
+#define ADXL372_STATUS_2   0x05
+#define ADXL372_FIFO_ENTRIES_2 0x06
+#define ADXL372_FIFO_ENTRIES_1 0x07
+#define ADXL372_X_DATA_H   0x08
+#define ADXL372_X_DATA_L   0x09
+#define ADXL372_Y_DATA_H   0x0A
+#define ADXL372_Y_DATA_L   0x0B
+#define ADXL372_Z_DATA_H   0x0C
+#define ADXL372_Z_DATA_L   0x0D
+#define ADXL372_X_MAXPEAK_H0x15
+#define ADXL372_X_MAXPEAK_L0x16
+#define ADXL372_Y_MAXPEAK_H0x17
+#define ADXL372_Y_MAXPEAK_L0x18
+#define ADXL372_Z_MAXPEAK_H0x19
+#define ADXL372_Z_MAXPEAK_L0x1A
+#define ADXL372_OFFSET_X   0x20
+#define ADXL372_OFFSET_Y   0x21
+#define ADXL372_OFFSET_Z   0x22
+#define ADXL372_X_THRESH_ACT_H 0x23
+#define ADXL372_X_THRESH_ACT_L 0x24
+#define ADXL372_Y_THRESH_ACT_H 0x25
+#define ADXL372_Y_THRESH_ACT_L 0x26
+#define ADXL372_Z_THRESH_ACT_H 0x27
+#define ADXL372_Z_THRESH_ACT_L 0x28
+#define ADXL372_TIME_ACT   0x29
+#define ADXL372_X_THRESH_INACT_H   0x2A
+#define ADXL372_X_THRESH_INACT_L   0x2B
+#define ADXL372_Y_THRESH_INACT_H   0x2C
+#define ADXL372_Y_THRESH_INACT_L   0x2D
+#define ADXL372_Z_THRESH_INACT_H   0x2E
+#define ADXL372_Z_THRESH_INACT_L   0x2F
+#define ADXL372_TIME_INACT_H   0x30
+#define ADXL372_TIME_INACT_L   0x31
+#define ADXL372_X_THRESH_ACT2_H0x32
+#define ADXL372_X_THRESH_ACT2_L0x33
+#define ADXL372_Y_THRESH_ACT2_H0x34
+#define ADXL372_Y_THRESH_ACT2_L0x35
+#define ADXL372_Z_THRESH_ACT2_H0x36
+#define ADXL372_Z_THRESH_ACT2_L0x37
+#define ADXL372_HPF 

[PATCH v4 2/6] dt-bindings: iio: accel: Add docs for ADXL372

2018-08-06 Thread Stefan Popa
Add the device tree binding documentation for the ADXL372 3-axis digital
accelerometer.

Signed-off-by: Stefan Popa 
---
 .../devicetree/bindings/iio/accel/adxl372.txt  | 22 ++
 MAINTAINERS|  1 +
 2 files changed, 23 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/accel/adxl372.txt

diff --git a/Documentation/devicetree/bindings/iio/accel/adxl372.txt 
b/Documentation/devicetree/bindings/iio/accel/adxl372.txt
new file mode 100644
index 000..9409984
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/accel/adxl372.txt
@@ -0,0 +1,22 @@
+Analog Devices ADXL372 3-Axis, +/-(200g) Digital Accelerometer
+
+http://www.analog.com/media/en/technical-documentation/data-sheets/adxl372.pdf
+
+Required properties:
+ - compatible : should be "adi,adxl372"
+ - reg: SPI chip select number for the device
+ - spi-max-frequency: Max SPI frequency to use
+
+Optional properties:
+ - interrupts: interrupt mapping for IRQ as documented in
+   Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+
+Example:
+
+   accelerometer@0 {
+   compatible = "adi,adxl372";
+   reg = <0>;
+   spi-max-frequency = <100>;
+   interrupt-parent = <>;
+   interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 2ba47bb..c8dd09c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -548,6 +548,7 @@ M:  Stefan Popa 
 W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/iio/accel/adxl372.c
+F: Documentation/devicetree/bindings/iio/accel/adxl372.txt
 
 AF9013 MEDIA DRIVER
 M: Antti Palosaari 
-- 
2.7.4



[PATCH v4 1/6] iio: adxl372: New driver for Analog Devices ADXL372 Accelerometer

2018-08-06 Thread Stefan Popa
This patch adds basic support for Analog Devices ADXL372 SPI-Bus
Three-Axis Digital Accelerometer.

The device is probed and configured the with some initial default
values. With this basic driver, it is possible to read raw acceleration
data.

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL372.pdf

Signed-off-by: Stefan Popa 
---
 MAINTAINERS |   6 +
 drivers/iio/accel/Kconfig   |  11 +
 drivers/iio/accel/Makefile  |   1 +
 drivers/iio/accel/adxl372.c | 525 
 4 files changed, 543 insertions(+)
 create mode 100644 drivers/iio/accel/adxl372.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 60b1028..2ba47bb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -543,6 +543,12 @@ W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/input/misc/adxl34x.c
 
+ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
+M: Stefan Popa 
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/accel/adxl372.c
+
 AF9013 MEDIA DRIVER
 M: Antti Palosaari 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 62ae7e5..1b496ef 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -60,6 +60,17 @@ config ADXL345_SPI
  will be called adxl345_spi and you will also get adxl345_core
  for the core module.
 
+config ADXL372
+   tristate "Analog Devices ADXL372 3-Axis Accelerometer Driver"
+   depends on SPI
+   select IIO_BUFFER
+   select IIO_TRIGGERED_BUFFER
+   help
+ Say yes here to add support for the Analog Devices ADXL372 triaxial
+ acceleration sensor.
+ To compile this driver as a module, choose M here: the
+ module will be called adxl372.
+
 config BMA180
tristate "Bosch BMA180/BMA250 3-Axis Accelerometer Driver"
depends on I2C
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index 636d4d1..5758ffc 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_ADIS16209) += adis16209.o
 obj-$(CONFIG_ADXL345) += adxl345_core.o
 obj-$(CONFIG_ADXL345_I2C) += adxl345_i2c.o
 obj-$(CONFIG_ADXL345_SPI) += adxl345_spi.o
+obj-$(CONFIG_ADXL372) += adxl372.o
 obj-$(CONFIG_BMA180) += bma180.o
 obj-$(CONFIG_BMA220) += bma220_spi.o
 obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
new file mode 100644
index 000..db9ecd2
--- /dev/null
+++ b/drivers/iio/accel/adxl372.c
@@ -0,0 +1,525 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * ADXL372 3-Axis Digital Accelerometer SPI driver
+ *
+ * Copyright 2018 Analog Devices Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+/* ADXL372 registers definition */
+#define ADXL372_DEVID  0x00
+#define ADXL372_DEVID_MST  0x01
+#define ADXL372_PARTID 0x02
+#define ADXL372_REVID  0x03
+#define ADXL372_STATUS_1   0x04
+#define ADXL372_STATUS_2   0x05
+#define ADXL372_FIFO_ENTRIES_2 0x06
+#define ADXL372_FIFO_ENTRIES_1 0x07
+#define ADXL372_X_DATA_H   0x08
+#define ADXL372_X_DATA_L   0x09
+#define ADXL372_Y_DATA_H   0x0A
+#define ADXL372_Y_DATA_L   0x0B
+#define ADXL372_Z_DATA_H   0x0C
+#define ADXL372_Z_DATA_L   0x0D
+#define ADXL372_X_MAXPEAK_H0x15
+#define ADXL372_X_MAXPEAK_L0x16
+#define ADXL372_Y_MAXPEAK_H0x17
+#define ADXL372_Y_MAXPEAK_L0x18
+#define ADXL372_Z_MAXPEAK_H0x19
+#define ADXL372_Z_MAXPEAK_L0x1A
+#define ADXL372_OFFSET_X   0x20
+#define ADXL372_OFFSET_Y   0x21
+#define ADXL372_OFFSET_Z   0x22
+#define ADXL372_X_THRESH_ACT_H 0x23
+#define ADXL372_X_THRESH_ACT_L 0x24
+#define ADXL372_Y_THRESH_ACT_H 0x25
+#define ADXL372_Y_THRESH_ACT_L 0x26
+#define ADXL372_Z_THRESH_ACT_H 0x27
+#define ADXL372_Z_THRESH_ACT_L 0x28
+#define ADXL372_TIME_ACT   0x29
+#define ADXL372_X_THRESH_INACT_H   0x2A
+#define ADXL372_X_THRESH_INACT_L   0x2B
+#define ADXL372_Y_THRESH_INACT_H   0x2C
+#define ADXL372_Y_THRESH_INACT_L   0x2D
+#define ADXL372_Z_THRESH_INACT_H   0x2E
+#define ADXL372_Z_THRESH_INACT_L   0x2F
+#define ADXL372_TIME_INACT_H   0x30
+#define ADXL372_TIME_INACT_L   0x31
+#define ADXL372_X_THRESH_ACT2_H0x32
+#define ADXL372_X_THRESH_ACT2_L0x33
+#define ADXL372_Y_THRESH_ACT2_H0x34
+#define ADXL372_Y_THRESH_ACT2_L0x35
+#define ADXL372_Z_THRESH_ACT2_H0x36
+#define ADXL372_Z_THRESH_ACT2_L0x37
+#define ADXL372_HPF 

[PATCH v4 0/6] iio: accel: Add adxl372 driver

2018-08-06 Thread Stefan Popa
Changes in v4:
Patch 1:
- used a lookup table in adxl372_set_activity_threshold() instead
  of a switch(case).
Patch 2: 
- removed the interrupt-parent from the bindings.
Patch 3:
- renamed regmap_pipe_read() stub to regmap_noinc_read().
Patch 4:
- removed the adxl372_read_fifo() wrapper and directly called
  regmap_noinc_read().
- called iio_triggered_buffer_predisable() before doing the local
  changes.
Patch 5:
- nothing changed.
Patch 6:
- nothing changed.

Changes in v3:
Patch 1, 2:
- nothing changed
Patch 3:
- changed the name from regmap_pipe_read() to regmap_noinc_read()
- added a check for readable registers
Patch 4:
- dropped the fifo peak mode
- corrected the patch based on feedback from Peter Meerwald-Stadler.
Patch 5 and 6:
- nothing changed

Changes in v2:
Patch 1:
- removed ADXL372_RD_FLAG_MSK and ADXL372_WR_FLAG_MSK macros.
- handled regmap read/write by setting reg_bits and pad_bits
  fields in regmap_config struct.
- removed the buffer specifications when defining the channels.
- changed the activity and inactivity thresholds.
- added two new functions for setting the activity and inactivity
  timers: adxl372_set_inactivity_time_ms() and
  adxl372_set_activity_time_ms().
Patch 2:
- introduced all the DT bindings in a single patch.
Patch 3:
- backported the patch based on this discussion: 
  https://lkml.org/lkml/2016/6/16/548.
- this patch is required as the regmap_pipe_read() API will be used 
  to read the data from the FIFO.
Patch 4:
- removed DT bindings changes from this patch.
- removed the linux/gpio/consumer.h header.
- used regmap_pipe_read() instead of regmap_bulk_read() when
  reading data from the FIFO.
- used multiple regmap_write() calls instead of a single
  regmap_bulk_write() if there is no fast path.
- used be32_to_cpu() inside the adxl372_get_status() function.
- added a new in_accel_x_peak scan element which allows the
  user to set the FIFO into XYZ peak mode.
- used a adxl372_axis_lookup_table() to determine the fifo format
  from the active_scan_mask.
- made IRQ optional.
Patch 5 and 6:
- nothing changed

Crestez Dan Leonard (1):
  regmap: Add regmap_noinc_read API

Stefan Popa (5):
  iio: adxl372: New driver for Analog Devices ADXL372 Accelerometer
  dt-bindings: iio: accel: Add docs for ADXL372
  iio:adxl372: Add FIFO and interrupts support
  iio:adxl372: Add sampling frequency support
  iio:adxl372: Add filter bandwidth support

 .../devicetree/bindings/iio/accel/adxl372.txt  |  22 +
 MAINTAINERS|   7 +
 drivers/base/regmap/regmap.c   |  65 +-
 drivers/iio/accel/Kconfig  |  11 +
 drivers/iio/accel/Makefile |   1 +
 drivers/iio/accel/adxl372.c| 977 +
 include/linux/regmap.h |   9 +
 7 files changed, 1091 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/iio/accel/adxl372.txt
 create mode 100644 drivers/iio/accel/adxl372.c

-- 
2.7.4



[PATCH v4 4/6] iio:adxl372: Add FIFO and interrupts support

2018-08-06 Thread Stefan Popa
This patch adds support for the adxl372 FIFO. In order to accomplish this,
triggered buffers were used.

The number of FIFO samples which trigger the watermark interrupt can be
configured by using the buffer watermark. The FIFO format is determined by
configuring the scan elements for each axis. The FIFO data is pushed to the
IIO device's buffer.

Signed-off-by: Stefan Popa 
---
 drivers/iio/accel/adxl372.c | 348 +++-
 1 file changed, 347 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index db9ecd2..623c32d 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -6,12 +6,19 @@
  */
 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
 
 /* ADXL372 registers definition */
 #define ADXL372_DEVID  0x00
@@ -123,6 +130,9 @@
 #define ADXL372_INT1_MAP_LOW_MSK   BIT(7)
 #define ADXL372_INT1_MAP_LOW_MODE(x)   (((x) & 0x1) << 7)
 
+/* The ADXL372 includes a deep, 512 sample FIFO buffer */
+#define ADXL372_FIFO_SIZE  512
+
 /*
  * At +/- 200g with 12-bit resolution, scale is computed as:
  * (200 + 200) * 9.81 / (2^12 - 1) = 0.958241
@@ -170,6 +180,43 @@ static const unsigned int adxl372_th_reg_high_addr[3] = {
[ADXL372_INACTIVITY] = ADXL372_X_THRESH_INACT_H,
 };
 
+enum adxl372_fifo_format {
+   ADXL372_XYZ_FIFO,
+   ADXL372_X_FIFO,
+   ADXL372_Y_FIFO,
+   ADXL372_XY_FIFO,
+   ADXL372_Z_FIFO,
+   ADXL372_XZ_FIFO,
+   ADXL372_YZ_FIFO,
+   ADXL372_XYZ_PEAK_FIFO,
+};
+
+enum adxl372_fifo_mode {
+   ADXL372_FIFO_BYPASSED,
+   ADXL372_FIFO_STREAMED,
+   ADXL372_FIFO_TRIGGERED,
+   ADXL372_FIFO_OLD_SAVED
+};
+
+static const int adxl372_samp_freq_tbl[5] = {
+   400, 800, 1600, 3200, 6400,
+};
+
+struct adxl372_axis_lookup {
+   unsigned int bits;
+   enum adxl372_fifo_format fifo_format;
+};
+
+static const struct adxl372_axis_lookup adxl372_axis_lookup_table[] = {
+   { BIT(0), ADXL372_X_FIFO },
+   { BIT(1), ADXL372_Y_FIFO },
+   { BIT(2), ADXL372_Z_FIFO },
+   { BIT(0) | BIT(1), ADXL372_XY_FIFO },
+   { BIT(0) | BIT(2), ADXL372_XZ_FIFO },
+   { BIT(1) | BIT(2), ADXL372_YZ_FIFO },
+   { BIT(0) | BIT(1) | BIT(2), ADXL372_XYZ_FIFO },
+};
+
 #define ADXL372_ACCEL_CHANNEL(index, reg, axis) {  \
.type = IIO_ACCEL,  \
.address = reg, \
@@ -177,6 +224,13 @@ static const unsigned int adxl372_th_reg_high_addr[3] = {
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
+   .scan_index = index,\
+   .scan_type = {  \
+   .sign = 's',\
+   .realbits = 12, \
+   .storagebits = 16,  \
+   .shift = 4, \
+   },  \
 }
 
 static const struct iio_chan_spec adxl372_channels[] = {
@@ -188,12 +242,29 @@ static const struct iio_chan_spec adxl372_channels[] = {
 struct adxl372_state {
struct spi_device   *spi;
struct regmap   *regmap;
+   struct iio_trigger  *dready_trig;
+   enum adxl372_fifo_mode  fifo_mode;
+   enum adxl372_fifo_formatfifo_format;
enum adxl372_op_modeop_mode;
enum adxl372_act_proc_mode  act_proc_mode;
enum adxl372_odrodr;
enum adxl372_bandwidth  bw;
u32 act_time_ms;
u32 inact_time_ms;
+   u8  fifo_set_size;
+   u8  int1_bitmask;
+   u8  int2_bitmask;
+   u16 watermark;
+   __be16  fifo_buf[ADXL372_FIFO_SIZE];
+};
+
+static const unsigned long adxl372_channel_masks[] = {
+   BIT(0), BIT(1), BIT(2),
+   BIT(0) | BIT(1),
+   BIT(0) | BIT(2),
+   BIT(1) | BIT(2),
+   BIT(0) | BIT(1) | BIT(2),
+   0
 };
 
 static int adxl372_read_axis(struct adxl372_state *st, u8 addr)
@@ -359,6 +430,112 @@ static int adxl372_set_inactivity_time_ms(struct 
adxl372_state *st,
return ret;
 }
 
+static int adxl372_set_interrupts(struct adxl372_state *st,
+ unsigned char in

[PATCH v5 0/6] iio: accel: Add adxl372 driver

2018-08-07 Thread Stefan Popa
Changes in v5:
Patch 1, 2:
- nothing changed
Patch 3:
- added a new readable_noinc operation based on feedback from
  Mark Brown
Patch 4:
- added a readable_noinc callback based on the changes from the
  previous patch.
Patch 5, 6:
- nothing changed

Changes in v4:
Patch 1:
- used a lookup table in adxl372_set_activity_threshold() instead
  of a switch(case).
Patch 2: 
- removed the interrupt-parent from the bindings.
Patch 3:
- renamed regmap_pipe_read() stub to regmap_noinc_read().
Patch 4:
- removed the adxl372_read_fifo() wrapper and directly called
  regmap_noinc_read().
- called iio_triggered_buffer_predisable() before doing the local
  changes.
Patch 5:
- nothing changed.
Patch 6:
- nothing changed.

Changes in v3:
Patch 1, 2:
- nothing changed
Patch 3:
- changed the name from regmap_pipe_read() to regmap_noinc_read()
- added a check for readable registers
Patch 4:
- dropped the fifo peak mode
- corrected the patch based on feedback from Peter Meerwald-Stadler.
Patch 5 and 6:
- nothing changed

Changes in v2:
Patch 1:
- removed ADXL372_RD_FLAG_MSK and ADXL372_WR_FLAG_MSK macros.
- handled regmap read/write by setting reg_bits and pad_bits
  fields in regmap_config struct.
- removed the buffer specifications when defining the channels.
- changed the activity and inactivity thresholds.
- added two new functions for setting the activity and inactivity
  timers: adxl372_set_inactivity_time_ms() and
  adxl372_set_activity_time_ms().
Patch 2:
- introduced all the DT bindings in a single patch.
Patch 3:
- backported the patch based on this discussion: 
  https://lkml.org/lkml/2016/6/16/548.
- this patch is required as the regmap_pipe_read() API will be used 
  to read the data from the FIFO.
Patch 4:
- removed DT bindings changes from this patch.
- removed the linux/gpio/consumer.h header.
- used regmap_pipe_read() instead of regmap_bulk_read() when
  reading data from the FIFO.
- used multiple regmap_write() calls instead of a single
  regmap_bulk_write() if there is no fast path.
- used be32_to_cpu() inside the adxl372_get_status() function.
- added a new in_accel_x_peak scan element which allows the
  user to set the FIFO into XYZ peak mode.
- used a adxl372_axis_lookup_table() to determine the fifo format
  from the active_scan_mask.
- made IRQ optional.
Patch 5 and 6:
- nothing changed


Crestez Dan Leonard (1):
  regmap: Add regmap_noinc_read API

Stefan Popa (5):
  iio: adxl372: New driver for Analog Devices ADXL372 Accelerometer
  dt-bindings: iio: accel: Add docs for ADXL372
  iio:adxl372: Add FIFO and interrupts support
  iio:adxl372: Add sampling frequency support
  iio:adxl372: Add filter bandwidth support

 .../devicetree/bindings/iio/accel/adxl372.txt  |  22 +
 MAINTAINERS|   7 +
 drivers/base/regmap/internal.h |   3 +
 drivers/base/regmap/regmap.c   |  79 +-
 drivers/iio/accel/Kconfig  |  11 +
 drivers/iio/accel/Makefile |   1 +
 drivers/iio/accel/adxl372.c| 983 +
 include/linux/regmap.h |  19 +
 8 files changed, 1124 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/iio/accel/adxl372.txt
 create mode 100644 drivers/iio/accel/adxl372.c

-- 
2.7.4



[PATCH v5 6/6] iio:adxl372: Add filter bandwidth support

2018-08-07 Thread Stefan Popa
This patch adds the option for the user to select the filter bandwidth. The
user can also read the available bandwidths which are always adjusted to be
at most half of the sampling frequency. Furthermore, the currently selected
bandwidth can be read via the read_raw function, while the write_raw sets a
new bandwidth value.

Signed-off-by: Stefan Popa 
---
 drivers/iio/accel/adxl372.c | 38 --
 1 file changed, 36 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 76c4a1d..c6f4b95 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -202,6 +202,10 @@ static const int adxl372_samp_freq_tbl[5] = {
400, 800, 1600, 3200, 6400,
 };
 
+static const int adxl372_bw_freq_tbl[5] = {
+   200, 400, 800, 1600, 3200,
+};
+
 struct adxl372_axis_lookup {
unsigned int bits;
enum adxl372_fifo_format fifo_format;
@@ -224,7 +228,8 @@ static const struct adxl372_axis_lookup 
adxl372_axis_lookup_table[] = {
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
-   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ) |  \
+   BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),   \
.scan_index = index,\
.scan_type = {  \
.sign = 's',\
@@ -648,6 +653,9 @@ static int adxl372_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SAMP_FREQ:
*val = adxl372_samp_freq_tbl[st->odr];
return IIO_VAL_INT;
+   case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+   *val = adxl372_bw_freq_tbl[st->bw];
+   return IIO_VAL_INT;
}
 
return -EINVAL;
@@ -658,7 +666,7 @@ static int adxl372_write_raw(struct iio_dev *indio_dev,
 int val, int val2, long info)
 {
struct adxl372_state *st = iio_priv(indio_dev);
-   int odr_index, ret;
+   int odr_index, bw_index, ret;
 
switch (info) {
case IIO_CHAN_INFO_SAMP_FREQ:
@@ -690,11 +698,34 @@ static int adxl372_write_raw(struct iio_dev *indio_dev,
ret = adxl372_set_bandwidth(st, odr_index);
 
return ret;
+   case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+   bw_index = adxl372_find_closest_match(adxl372_bw_freq_tbl,
+   ARRAY_SIZE(adxl372_bw_freq_tbl),
+   val);
+   return adxl372_set_bandwidth(st, bw_index);
default:
return -EINVAL;
}
 }
 
+static ssize_t adxl372_show_filter_freq_avail(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+   struct adxl372_state *st = iio_priv(indio_dev);
+   int i;
+   size_t len = 0;
+
+   for (i = 0; i <= st->odr; i++)
+   len += scnprintf(buf + len, PAGE_SIZE - len,
+"%d ", adxl372_bw_freq_tbl[i]);
+
+   buf[len - 1] = '\n';
+
+   return len;
+}
+
 static ssize_t adxl372_get_fifo_enabled(struct device *dev,
  struct device_attribute *attr,
  char *buf)
@@ -823,9 +854,12 @@ static const struct iio_trigger_ops adxl372_trigger_ops = {
 };
 
 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400");
+static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available,
+  0444, adxl372_show_filter_freq_avail, NULL, 0);
 
 static struct attribute *adxl372_attributes[] = {
_const_attr_sampling_frequency_available.dev_attr.attr,
+   
_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr,
NULL,
 };
 
-- 
2.7.4



[PATCH v5 2/6] dt-bindings: iio: accel: Add docs for ADXL372

2018-08-07 Thread Stefan Popa
Add the device tree binding documentation for the ADXL372 3-axis digital
accelerometer.

Signed-off-by: Stefan Popa 
---
 .../devicetree/bindings/iio/accel/adxl372.txt  | 22 ++
 MAINTAINERS|  1 +
 2 files changed, 23 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/accel/adxl372.txt

diff --git a/Documentation/devicetree/bindings/iio/accel/adxl372.txt 
b/Documentation/devicetree/bindings/iio/accel/adxl372.txt
new file mode 100644
index 000..9409984
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/accel/adxl372.txt
@@ -0,0 +1,22 @@
+Analog Devices ADXL372 3-Axis, +/-(200g) Digital Accelerometer
+
+http://www.analog.com/media/en/technical-documentation/data-sheets/adxl372.pdf
+
+Required properties:
+ - compatible : should be "adi,adxl372"
+ - reg: SPI chip select number for the device
+ - spi-max-frequency: Max SPI frequency to use
+
+Optional properties:
+ - interrupts: interrupt mapping for IRQ as documented in
+   Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+
+Example:
+
+   accelerometer@0 {
+   compatible = "adi,adxl372";
+   reg = <0>;
+   spi-max-frequency = <100>;
+   interrupt-parent = <>;
+   interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 2ba47bb..c8dd09c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -548,6 +548,7 @@ M:  Stefan Popa 
 W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/iio/accel/adxl372.c
+F: Documentation/devicetree/bindings/iio/accel/adxl372.txt
 
 AF9013 MEDIA DRIVER
 M: Antti Palosaari 
-- 
2.7.4



[PATCH v5 3/6] regmap: Add regmap_noinc_read API

2018-08-07 Thread Stefan Popa
From: Crestez Dan Leonard 

The regmap API usually assumes that bulk read operations will read a
range of registers but some I2C/SPI devices have certain registers for
which a such a read operation will return data from an internal FIFO
instead. Add an explicit API to support bulk read without range semantics.

Some linux drivers use regmap_bulk_read or regmap_raw_read for such
registers, for example mpu6050 or bmi150 from IIO. This only happens to
work because when caching is disabled a single regmap read op will map
to a single bus read op (as desired). This breaks if caching is enabled and
reg+1 happens to be a cacheable register.

Without regmap support refactoring a driver to enable regmap caching
requires separate I2C and SPI paths. This is exactly what regmap is
supposed to help avoid.

Suggested-by: Jonathan Cameron 
Signed-off-by: Crestez Dan Leonard 
Signed-off-by: Stefan Popa 
---
 drivers/base/regmap/internal.h |  3 ++
 drivers/base/regmap/regmap.c   | 79 +-
 include/linux/regmap.h | 19 ++
 3 files changed, 100 insertions(+), 1 deletion(-)

diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 53785e0..a6bf34d63 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -94,10 +94,12 @@ struct regmap {
bool (*readable_reg)(struct device *dev, unsigned int reg);
bool (*volatile_reg)(struct device *dev, unsigned int reg);
bool (*precious_reg)(struct device *dev, unsigned int reg);
+   bool (*readable_noinc_reg)(struct device *dev, unsigned int reg);
const struct regmap_access_table *wr_table;
const struct regmap_access_table *rd_table;
const struct regmap_access_table *volatile_table;
const struct regmap_access_table *precious_table;
+   const struct regmap_access_table *rd_noinc_table;
 
int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
int (*reg_write)(void *context, unsigned int reg, unsigned int val);
@@ -181,6 +183,7 @@ bool regmap_writeable(struct regmap *map, unsigned int reg);
 bool regmap_readable(struct regmap *map, unsigned int reg);
 bool regmap_volatile(struct regmap *map, unsigned int reg);
 bool regmap_precious(struct regmap *map, unsigned int reg);
+bool regmap_readable_noinc(struct regmap *map, unsigned int reg);
 
 int _regmap_write(struct regmap *map, unsigned int reg,
  unsigned int val);
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 3bc8488..0360a90 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -168,6 +168,17 @@ bool regmap_precious(struct regmap *map, unsigned int reg)
return false;
 }
 
+bool regmap_readable_noinc(struct regmap *map, unsigned int reg)
+{
+   if (map->readable_noinc_reg)
+   return map->readable_noinc_reg(map->dev, reg);
+
+   if (map->rd_noinc_table)
+   return regmap_check_range_table(map, reg, map->rd_noinc_table);
+
+   return true;
+}
+
 static bool regmap_volatile_range(struct regmap *map, unsigned int reg,
size_t num)
 {
@@ -766,10 +777,12 @@ struct regmap *__regmap_init(struct device *dev,
map->rd_table = config->rd_table;
map->volatile_table = config->volatile_table;
map->precious_table = config->precious_table;
+   map->rd_noinc_table = config->rd_noinc_table;
map->writeable_reg = config->writeable_reg;
map->readable_reg = config->readable_reg;
map->volatile_reg = config->volatile_reg;
map->precious_reg = config->precious_reg;
+   map->readable_noinc_reg = config->readable_noinc_reg;
map->cache_type = config->cache_type;
 
spin_lock_init(>async_lock);
@@ -1285,6 +1298,7 @@ int regmap_reinit_cache(struct regmap *map, const struct 
regmap_config *config)
map->readable_reg = config->readable_reg;
map->volatile_reg = config->volatile_reg;
map->precious_reg = config->precious_reg;
+   map->readable_noinc_reg = config->readable_noinc_reg;
map->cache_type = config->cache_type;
 
regmap_debugfs_init(map, config->name);
@@ -2564,7 +2578,70 @@ int regmap_raw_read(struct regmap *map, unsigned int 
reg, void *val,
 EXPORT_SYMBOL_GPL(regmap_raw_read);
 
 /**
- * regmap_field_read() - Read a value to a single register field
+ * regmap_noinc_read(): Read data from a register without incrementing the
+ * register number
+ *
+ * @map: Register map to read from
+ * @reg: Register to read from
+ * @val: Pointer to data buffer
+ * @val_len: Length of output buffer in bytes.
+ *
+ * The regmap API usually assumes that bulk bus read operations will read a
+ * range of registers. Some devices have certain registers for which a read
+ * operation read will read from an internal FIFO

[PATCH v6 2/6] dt-bindings: iio: accel: Add docs for ADXL372

2018-08-10 Thread Stefan Popa
Add the device tree binding documentation for the ADXL372 3-axis digital
accelerometer.

Signed-off-by: Stefan Popa 
Reviewed-by: Rob Herring 
---
 .../devicetree/bindings/iio/accel/adxl372.txt  | 22 ++
 MAINTAINERS|  1 +
 2 files changed, 23 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/accel/adxl372.txt

diff --git a/Documentation/devicetree/bindings/iio/accel/adxl372.txt 
b/Documentation/devicetree/bindings/iio/accel/adxl372.txt
new file mode 100644
index 000..9409984
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/accel/adxl372.txt
@@ -0,0 +1,22 @@
+Analog Devices ADXL372 3-Axis, +/-(200g) Digital Accelerometer
+
+http://www.analog.com/media/en/technical-documentation/data-sheets/adxl372.pdf
+
+Required properties:
+ - compatible : should be "adi,adxl372"
+ - reg: SPI chip select number for the device
+ - spi-max-frequency: Max SPI frequency to use
+
+Optional properties:
+ - interrupts: interrupt mapping for IRQ as documented in
+   Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+
+Example:
+
+   accelerometer@0 {
+   compatible = "adi,adxl372";
+   reg = <0>;
+   spi-max-frequency = <100>;
+   interrupt-parent = <>;
+   interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 2ba47bb..c8dd09c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -548,6 +548,7 @@ M:  Stefan Popa 
 W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/iio/accel/adxl372.c
+F: Documentation/devicetree/bindings/iio/accel/adxl372.txt
 
 AF9013 MEDIA DRIVER
 M: Antti Palosaari 
-- 
2.7.4



[PATCH v6 1/6] iio: adxl372: New driver for Analog Devices ADXL372 Accelerometer

2018-08-10 Thread Stefan Popa
This patch adds basic support for Analog Devices ADXL372 SPI-Bus
Three-Axis Digital Accelerometer.

The device is probed and configured the with some initial default
values. With this basic driver, it is possible to read raw acceleration
data.

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL372.pdf

Signed-off-by: Stefan Popa 
---
 MAINTAINERS |   6 +
 drivers/iio/accel/Kconfig   |  11 +
 drivers/iio/accel/Makefile  |   1 +
 drivers/iio/accel/adxl372.c | 525 
 4 files changed, 543 insertions(+)
 create mode 100644 drivers/iio/accel/adxl372.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 60b1028..2ba47bb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -543,6 +543,12 @@ W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/input/misc/adxl34x.c
 
+ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
+M: Stefan Popa 
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/accel/adxl372.c
+
 AF9013 MEDIA DRIVER
 M: Antti Palosaari 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 62ae7e5..1b496ef 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -60,6 +60,17 @@ config ADXL345_SPI
  will be called adxl345_spi and you will also get adxl345_core
  for the core module.
 
+config ADXL372
+   tristate "Analog Devices ADXL372 3-Axis Accelerometer Driver"
+   depends on SPI
+   select IIO_BUFFER
+   select IIO_TRIGGERED_BUFFER
+   help
+ Say yes here to add support for the Analog Devices ADXL372 triaxial
+ acceleration sensor.
+ To compile this driver as a module, choose M here: the
+ module will be called adxl372.
+
 config BMA180
tristate "Bosch BMA180/BMA250 3-Axis Accelerometer Driver"
depends on I2C
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index 636d4d1..5758ffc 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_ADIS16209) += adis16209.o
 obj-$(CONFIG_ADXL345) += adxl345_core.o
 obj-$(CONFIG_ADXL345_I2C) += adxl345_i2c.o
 obj-$(CONFIG_ADXL345_SPI) += adxl345_spi.o
+obj-$(CONFIG_ADXL372) += adxl372.o
 obj-$(CONFIG_BMA180) += bma180.o
 obj-$(CONFIG_BMA220) += bma220_spi.o
 obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
new file mode 100644
index 000..db9ecd2
--- /dev/null
+++ b/drivers/iio/accel/adxl372.c
@@ -0,0 +1,525 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * ADXL372 3-Axis Digital Accelerometer SPI driver
+ *
+ * Copyright 2018 Analog Devices Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+/* ADXL372 registers definition */
+#define ADXL372_DEVID  0x00
+#define ADXL372_DEVID_MST  0x01
+#define ADXL372_PARTID 0x02
+#define ADXL372_REVID  0x03
+#define ADXL372_STATUS_1   0x04
+#define ADXL372_STATUS_2   0x05
+#define ADXL372_FIFO_ENTRIES_2 0x06
+#define ADXL372_FIFO_ENTRIES_1 0x07
+#define ADXL372_X_DATA_H   0x08
+#define ADXL372_X_DATA_L   0x09
+#define ADXL372_Y_DATA_H   0x0A
+#define ADXL372_Y_DATA_L   0x0B
+#define ADXL372_Z_DATA_H   0x0C
+#define ADXL372_Z_DATA_L   0x0D
+#define ADXL372_X_MAXPEAK_H0x15
+#define ADXL372_X_MAXPEAK_L0x16
+#define ADXL372_Y_MAXPEAK_H0x17
+#define ADXL372_Y_MAXPEAK_L0x18
+#define ADXL372_Z_MAXPEAK_H0x19
+#define ADXL372_Z_MAXPEAK_L0x1A
+#define ADXL372_OFFSET_X   0x20
+#define ADXL372_OFFSET_Y   0x21
+#define ADXL372_OFFSET_Z   0x22
+#define ADXL372_X_THRESH_ACT_H 0x23
+#define ADXL372_X_THRESH_ACT_L 0x24
+#define ADXL372_Y_THRESH_ACT_H 0x25
+#define ADXL372_Y_THRESH_ACT_L 0x26
+#define ADXL372_Z_THRESH_ACT_H 0x27
+#define ADXL372_Z_THRESH_ACT_L 0x28
+#define ADXL372_TIME_ACT   0x29
+#define ADXL372_X_THRESH_INACT_H   0x2A
+#define ADXL372_X_THRESH_INACT_L   0x2B
+#define ADXL372_Y_THRESH_INACT_H   0x2C
+#define ADXL372_Y_THRESH_INACT_L   0x2D
+#define ADXL372_Z_THRESH_INACT_H   0x2E
+#define ADXL372_Z_THRESH_INACT_L   0x2F
+#define ADXL372_TIME_INACT_H   0x30
+#define ADXL372_TIME_INACT_L   0x31
+#define ADXL372_X_THRESH_ACT2_H0x32
+#define ADXL372_X_THRESH_ACT2_L0x33
+#define ADXL372_Y_THRESH_ACT2_H0x34
+#define ADXL372_Y_THRESH_ACT2_L0x35
+#define ADXL372_Z_THRESH_ACT2_H0x36
+#define ADXL372_Z_THRESH_ACT2_L0x37
+#define ADXL372_HPF 

[PATCH v6 3/6] regmap: Add regmap_noinc_read API

2018-08-10 Thread Stefan Popa
From: Crestez Dan Leonard 

The regmap API usually assumes that bulk read operations will read a
range of registers but some I2C/SPI devices have certain registers for
which a such a read operation will return data from an internal FIFO
instead. Add an explicit API to support bulk read without range semantics.

Some linux drivers use regmap_bulk_read or regmap_raw_read for such
registers, for example mpu6050 or bmi150 from IIO. This only happens to
work because when caching is disabled a single regmap read op will map
to a single bus read op (as desired). This breaks if caching is enabled and
reg+1 happens to be a cacheable register.

Without regmap support refactoring a driver to enable regmap caching
requires separate I2C and SPI paths. This is exactly what regmap is
supposed to help avoid.

Suggested-by: Jonathan Cameron 
Signed-off-by: Crestez Dan Leonard 
Signed-off-by: Stefan Popa 
Reviewed-by: Jonathan Cameron 
---
 drivers/base/regmap/internal.h |  3 ++
 drivers/base/regmap/regmap.c   | 79 +-
 include/linux/regmap.h | 19 ++
 3 files changed, 100 insertions(+), 1 deletion(-)

diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 53785e0..a6bf34d63 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -94,10 +94,12 @@ struct regmap {
bool (*readable_reg)(struct device *dev, unsigned int reg);
bool (*volatile_reg)(struct device *dev, unsigned int reg);
bool (*precious_reg)(struct device *dev, unsigned int reg);
+   bool (*readable_noinc_reg)(struct device *dev, unsigned int reg);
const struct regmap_access_table *wr_table;
const struct regmap_access_table *rd_table;
const struct regmap_access_table *volatile_table;
const struct regmap_access_table *precious_table;
+   const struct regmap_access_table *rd_noinc_table;
 
int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
int (*reg_write)(void *context, unsigned int reg, unsigned int val);
@@ -181,6 +183,7 @@ bool regmap_writeable(struct regmap *map, unsigned int reg);
 bool regmap_readable(struct regmap *map, unsigned int reg);
 bool regmap_volatile(struct regmap *map, unsigned int reg);
 bool regmap_precious(struct regmap *map, unsigned int reg);
+bool regmap_readable_noinc(struct regmap *map, unsigned int reg);
 
 int _regmap_write(struct regmap *map, unsigned int reg,
  unsigned int val);
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 3bc8488..0360a90 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -168,6 +168,17 @@ bool regmap_precious(struct regmap *map, unsigned int reg)
return false;
 }
 
+bool regmap_readable_noinc(struct regmap *map, unsigned int reg)
+{
+   if (map->readable_noinc_reg)
+   return map->readable_noinc_reg(map->dev, reg);
+
+   if (map->rd_noinc_table)
+   return regmap_check_range_table(map, reg, map->rd_noinc_table);
+
+   return true;
+}
+
 static bool regmap_volatile_range(struct regmap *map, unsigned int reg,
size_t num)
 {
@@ -766,10 +777,12 @@ struct regmap *__regmap_init(struct device *dev,
map->rd_table = config->rd_table;
map->volatile_table = config->volatile_table;
map->precious_table = config->precious_table;
+   map->rd_noinc_table = config->rd_noinc_table;
map->writeable_reg = config->writeable_reg;
map->readable_reg = config->readable_reg;
map->volatile_reg = config->volatile_reg;
map->precious_reg = config->precious_reg;
+   map->readable_noinc_reg = config->readable_noinc_reg;
map->cache_type = config->cache_type;
 
spin_lock_init(>async_lock);
@@ -1285,6 +1298,7 @@ int regmap_reinit_cache(struct regmap *map, const struct 
regmap_config *config)
map->readable_reg = config->readable_reg;
map->volatile_reg = config->volatile_reg;
map->precious_reg = config->precious_reg;
+   map->readable_noinc_reg = config->readable_noinc_reg;
map->cache_type = config->cache_type;
 
regmap_debugfs_init(map, config->name);
@@ -2564,7 +2578,70 @@ int regmap_raw_read(struct regmap *map, unsigned int 
reg, void *val,
 EXPORT_SYMBOL_GPL(regmap_raw_read);
 
 /**
- * regmap_field_read() - Read a value to a single register field
+ * regmap_noinc_read(): Read data from a register without incrementing the
+ * register number
+ *
+ * @map: Register map to read from
+ * @reg: Register to read from
+ * @val: Pointer to data buffer
+ * @val_len: Length of output buffer in bytes.
+ *
+ * The regmap API usually assumes that bulk bus read operations will read a
+ * range of registers. Some devices have certain registers for which a read
+ * operatio

[PATCH v6 6/6] iio:adxl372: Add filter bandwidth support

2018-08-10 Thread Stefan Popa
This patch adds the option for the user to select the filter bandwidth. The
user can also read the available bandwidths which are always adjusted to be
at most half of the sampling frequency. Furthermore, the currently selected
bandwidth can be read via the read_raw function, while the write_raw sets a
new bandwidth value.

Signed-off-by: Stefan Popa 
---
 drivers/iio/accel/adxl372.c | 38 --
 1 file changed, 36 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index fedb623..7097775 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -202,6 +202,10 @@ static const int adxl372_samp_freq_tbl[5] = {
400, 800, 1600, 3200, 6400,
 };
 
+static const int adxl372_bw_freq_tbl[5] = {
+   200, 400, 800, 1600, 3200,
+};
+
 struct adxl372_axis_lookup {
unsigned int bits;
enum adxl372_fifo_format fifo_format;
@@ -224,7 +228,8 @@ static const struct adxl372_axis_lookup 
adxl372_axis_lookup_table[] = {
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
-   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ) |  \
+   BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),   \
.scan_index = index,\
.scan_type = {  \
.sign = 's',\
@@ -648,6 +653,9 @@ static int adxl372_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SAMP_FREQ:
*val = adxl372_samp_freq_tbl[st->odr];
return IIO_VAL_INT;
+   case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+   *val = adxl372_bw_freq_tbl[st->bw];
+   return IIO_VAL_INT;
}
 
return -EINVAL;
@@ -658,7 +666,7 @@ static int adxl372_write_raw(struct iio_dev *indio_dev,
 int val, int val2, long info)
 {
struct adxl372_state *st = iio_priv(indio_dev);
-   int odr_index, ret;
+   int odr_index, bw_index, ret;
 
switch (info) {
case IIO_CHAN_INFO_SAMP_FREQ:
@@ -690,11 +698,34 @@ static int adxl372_write_raw(struct iio_dev *indio_dev,
ret = adxl372_set_bandwidth(st, odr_index);
 
return ret;
+   case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+   bw_index = adxl372_find_closest_match(adxl372_bw_freq_tbl,
+   ARRAY_SIZE(adxl372_bw_freq_tbl),
+   val);
+   return adxl372_set_bandwidth(st, bw_index);
default:
return -EINVAL;
}
 }
 
+static ssize_t adxl372_show_filter_freq_avail(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+   struct adxl372_state *st = iio_priv(indio_dev);
+   int i;
+   size_t len = 0;
+
+   for (i = 0; i <= st->odr; i++)
+   len += scnprintf(buf + len, PAGE_SIZE - len,
+"%d ", adxl372_bw_freq_tbl[i]);
+
+   buf[len - 1] = '\n';
+
+   return len;
+}
+
 static ssize_t adxl372_get_fifo_enabled(struct device *dev,
  struct device_attribute *attr,
  char *buf)
@@ -826,9 +857,12 @@ static const struct iio_trigger_ops adxl372_trigger_ops = {
 };
 
 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400");
+static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available,
+  0444, adxl372_show_filter_freq_avail, NULL, 0);
 
 static struct attribute *adxl372_attributes[] = {
_const_attr_sampling_frequency_available.dev_attr.attr,
+   
_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr,
NULL,
 };
 
-- 
2.7.4



[PATCH v6 5/6] iio:adxl372: Add sampling frequency support

2018-08-10 Thread Stefan Popa
This patch adds the option for the user to select the sampling frequency.
Also, the user can read the available frequencies and read the currently
set frequency via the read_raw function. The frequency can be set via the
write_raw function.

When the frequency is set, the bandwidth is also checked and ensured
that it is constrained to at most half of the sampling frequency. Also, the
activity and inactivity timers have to be updated because they depend on
the selected ODR.

Signed-off-by: Stefan Popa 
---
 drivers/iio/accel/adxl372.c | 74 -
 1 file changed, 73 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 1e2519a..fedb623 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -223,7 +223,8 @@ static const struct adxl372_axis_lookup 
adxl372_axis_lookup_table[] = {
.modified = 1,  \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
-   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
+   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
.scan_index = index,\
.scan_type = {  \
.sign = 's',\
@@ -311,6 +312,19 @@ static int adxl372_set_odr(struct adxl372_state *st,
return ret;
 }
 
+static int adxl372_find_closest_match(const int *array,
+ unsigned int size, int val)
+{
+   int i;
+
+   for (i = 0; i < size; i++) {
+   if (val <= array[i])
+   return i;
+   }
+
+   return size - 1;
+}
+
 static int adxl372_set_bandwidth(struct adxl372_state *st,
 enum adxl372_bandwidth bw)
 {
@@ -631,6 +645,51 @@ static int adxl372_read_raw(struct iio_dev *indio_dev,
*val = 0;
*val2 = ADXL372_USCALE;
return IIO_VAL_INT_PLUS_MICRO;
+   case IIO_CHAN_INFO_SAMP_FREQ:
+   *val = adxl372_samp_freq_tbl[st->odr];
+   return IIO_VAL_INT;
+   }
+
+   return -EINVAL;
+}
+
+static int adxl372_write_raw(struct iio_dev *indio_dev,
+struct iio_chan_spec const *chan,
+int val, int val2, long info)
+{
+   struct adxl372_state *st = iio_priv(indio_dev);
+   int odr_index, ret;
+
+   switch (info) {
+   case IIO_CHAN_INFO_SAMP_FREQ:
+   odr_index = adxl372_find_closest_match(adxl372_samp_freq_tbl,
+   ARRAY_SIZE(adxl372_samp_freq_tbl),
+   val);
+   ret = adxl372_set_odr(st, odr_index);
+   if (ret < 0)
+   return ret;
+   /*
+* The timer period depends on the ODR selected.
+* At 3200 Hz and below, it is 6.6 ms; at 6400 Hz, it is 3.3 ms
+*/
+   ret = adxl372_set_activity_time_ms(st, st->act_time_ms);
+   if (ret < 0)
+   return ret;
+   /*
+* The timer period depends on the ODR selected.
+* At 3200 Hz and below, it is 26 ms; at 6400 Hz, it is 13 ms
+*/
+   ret = adxl372_set_inactivity_time_ms(st, st->inact_time_ms);
+   if (ret < 0)
+   return ret;
+   /*
+* The maximum bandwidth is constrained to at most half of
+* the ODR to ensure that the Nyquist criteria is not violated
+*/
+   if (st->bw > odr_index)
+   ret = adxl372_set_bandwidth(st, odr_index);
+
+   return ret;
default:
return -EINVAL;
}
@@ -766,8 +825,21 @@ static const struct iio_trigger_ops adxl372_trigger_ops = {
.set_trigger_state = adxl372_dready_trig_set_state,
 };
 
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400");
+
+static struct attribute *adxl372_attributes[] = {
+   _const_attr_sampling_frequency_available.dev_attr.attr,
+   NULL,
+};
+
+static const struct attribute_group adxl372_attrs_group = {
+   .attrs = adxl372_attributes,
+};
+
 static const struct iio_info adxl372_info = {
+   .attrs = _attrs_group,
.read_raw = adxl372_read_raw,
+   .write_raw = adxl372_write_raw,
.debugfs_reg_access = _reg_access,
.hwfifo_set_watermark = adxl372_set_watermark,
 };
-- 
2.7.4



[PATCH v6 4/6] iio:adxl372: Add FIFO and interrupts support

2018-08-10 Thread Stefan Popa
This patch adds support for the adxl372 FIFO. In order to accomplish this,
triggered buffers were used.

The number of FIFO samples which trigger the watermark interrupt can be
configured by using the buffer watermark. The FIFO format is determined by
configuring the scan elements for each axis. The FIFO data is pushed to the
IIO device's buffer.

Signed-off-by: Stefan Popa 
---
 drivers/iio/accel/adxl372.c | 357 +++-
 1 file changed, 356 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index db9ecd2..1e2519a 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -6,12 +6,19 @@
  */
 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
 
 /* ADXL372 registers definition */
 #define ADXL372_DEVID  0x00
@@ -123,6 +130,9 @@
 #define ADXL372_INT1_MAP_LOW_MSK   BIT(7)
 #define ADXL372_INT1_MAP_LOW_MODE(x)   (((x) & 0x1) << 7)
 
+/* The ADXL372 includes a deep, 512 sample FIFO buffer */
+#define ADXL372_FIFO_SIZE  512
+
 /*
  * At +/- 200g with 12-bit resolution, scale is computed as:
  * (200 + 200) * 9.81 / (2^12 - 1) = 0.958241
@@ -170,6 +180,43 @@ static const unsigned int adxl372_th_reg_high_addr[3] = {
[ADXL372_INACTIVITY] = ADXL372_X_THRESH_INACT_H,
 };
 
+enum adxl372_fifo_format {
+   ADXL372_XYZ_FIFO,
+   ADXL372_X_FIFO,
+   ADXL372_Y_FIFO,
+   ADXL372_XY_FIFO,
+   ADXL372_Z_FIFO,
+   ADXL372_XZ_FIFO,
+   ADXL372_YZ_FIFO,
+   ADXL372_XYZ_PEAK_FIFO,
+};
+
+enum adxl372_fifo_mode {
+   ADXL372_FIFO_BYPASSED,
+   ADXL372_FIFO_STREAMED,
+   ADXL372_FIFO_TRIGGERED,
+   ADXL372_FIFO_OLD_SAVED
+};
+
+static const int adxl372_samp_freq_tbl[5] = {
+   400, 800, 1600, 3200, 6400,
+};
+
+struct adxl372_axis_lookup {
+   unsigned int bits;
+   enum adxl372_fifo_format fifo_format;
+};
+
+static const struct adxl372_axis_lookup adxl372_axis_lookup_table[] = {
+   { BIT(0), ADXL372_X_FIFO },
+   { BIT(1), ADXL372_Y_FIFO },
+   { BIT(2), ADXL372_Z_FIFO },
+   { BIT(0) | BIT(1), ADXL372_XY_FIFO },
+   { BIT(0) | BIT(2), ADXL372_XZ_FIFO },
+   { BIT(1) | BIT(2), ADXL372_YZ_FIFO },
+   { BIT(0) | BIT(1) | BIT(2), ADXL372_XYZ_FIFO },
+};
+
 #define ADXL372_ACCEL_CHANNEL(index, reg, axis) {  \
.type = IIO_ACCEL,  \
.address = reg, \
@@ -177,6 +224,13 @@ static const unsigned int adxl372_th_reg_high_addr[3] = {
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
+   .scan_index = index,\
+   .scan_type = {  \
+   .sign = 's',\
+   .realbits = 12, \
+   .storagebits = 16,  \
+   .shift = 4, \
+   },  \
 }
 
 static const struct iio_chan_spec adxl372_channels[] = {
@@ -188,12 +242,29 @@ static const struct iio_chan_spec adxl372_channels[] = {
 struct adxl372_state {
struct spi_device   *spi;
struct regmap   *regmap;
+   struct iio_trigger  *dready_trig;
+   enum adxl372_fifo_mode  fifo_mode;
+   enum adxl372_fifo_formatfifo_format;
enum adxl372_op_modeop_mode;
enum adxl372_act_proc_mode  act_proc_mode;
enum adxl372_odrodr;
enum adxl372_bandwidth  bw;
u32 act_time_ms;
u32 inact_time_ms;
+   u8  fifo_set_size;
+   u8  int1_bitmask;
+   u8  int2_bitmask;
+   u16 watermark;
+   __be16  fifo_buf[ADXL372_FIFO_SIZE];
+};
+
+static const unsigned long adxl372_channel_masks[] = {
+   BIT(0), BIT(1), BIT(2),
+   BIT(0) | BIT(1),
+   BIT(0) | BIT(2),
+   BIT(1) | BIT(2),
+   BIT(0) | BIT(1) | BIT(2),
+   0
 };
 
 static int adxl372_read_axis(struct adxl372_state *st, u8 addr)
@@ -359,6 +430,112 @@ static int adxl372_set_inactivity_time_ms(struct 
adxl372_state *st,
return ret;
 }
 
+static int adxl372_set_interrupts(struct adxl372_state *st,
+ unsigned char in

[PATCH v6 0/6] iio: accel: Add adxl372 driver

2018-08-10 Thread Stefan Popa
Changes in v6:
Patch 1:
- nothing changed.
Patch 2, 3:
- added reviewed-by's which were lost when new versions were added.
Patch 4:
- fixed kbuild warning by adding a buffer overflow check in
  adxl372_buffer_postenable().
Patch 5, 6:
- nothing changed

Changes in v5:
Patch 1, 2:
- nothing changed
Patch 3:
- added a new readable_noinc operation based on feedback from
  Mark Brown
Patch 4:
- added a readable_noinc callback based on the changes from the
  previous patch.
Patch 5, 6:
- nothing changed

Changes in v4:
Patch 1:
- used a lookup table in adxl372_set_activity_threshold() instead
  of a switch(case).
Patch 2: 
- removed the interrupt-parent from the bindings.
Patch 3:
- renamed regmap_pipe_read() stub to regmap_noinc_read().
Patch 4:
- removed the adxl372_read_fifo() wrapper and directly called
  regmap_noinc_read().
- called iio_triggered_buffer_predisable() before doing the local
  changes.
Patch 5:
- nothing changed.
Patch 6:
- nothing changed.

Changes in v3:
Patch 1, 2:
- nothing changed
Patch 3:
- changed the name from regmap_pipe_read() to regmap_noinc_read()
- added a check for readable registers
Patch 4:
- dropped the fifo peak mode
- corrected the patch based on feedback from Peter Meerwald-Stadler.
Patch 5 and 6:
- nothing changed

Changes in v2:
Patch 1:
- removed ADXL372_RD_FLAG_MSK and ADXL372_WR_FLAG_MSK macros.
- handled regmap read/write by setting reg_bits and pad_bits
  fields in regmap_config struct.
- removed the buffer specifications when defining the channels.
- changed the activity and inactivity thresholds.
- added two new functions for setting the activity and inactivity
  timers: adxl372_set_inactivity_time_ms() and
  adxl372_set_activity_time_ms().
Patch 2:
- introduced all the DT bindings in a single patch.
Patch 3:
- backported the patch based on this discussion: 
  https://lkml.org/lkml/2016/6/16/548.
- this patch is required as the regmap_pipe_read() API will be used 
  to read the data from the FIFO.
Patch 4:
- removed DT bindings changes from this patch.
- removed the linux/gpio/consumer.h header.
- used regmap_pipe_read() instead of regmap_bulk_read() when
  reading data from the FIFO.
- used multiple regmap_write() calls instead of a single
  regmap_bulk_write() if there is no fast path.
- used be32_to_cpu() inside the adxl372_get_status() function.
- added a new in_accel_x_peak scan element which allows the
  user to set the FIFO into XYZ peak mode.
- used a adxl372_axis_lookup_table() to determine the fifo format
  from the active_scan_mask.
- made IRQ optional.
Patch 5 and 6:
- nothing changed

Crestez Dan Leonard (1):
  regmap: Add regmap_noinc_read API

Stefan Popa (5):
  iio: adxl372: New driver for Analog Devices ADXL372 Accelerometer
  dt-bindings: iio: accel: Add docs for ADXL372
  iio:adxl372: Add FIFO and interrupts support
  iio:adxl372: Add sampling frequency support
  iio:adxl372: Add filter bandwidth support

 .../devicetree/bindings/iio/accel/adxl372.txt  |  22 +
 MAINTAINERS|   7 +
 drivers/base/regmap/internal.h |   3 +
 drivers/base/regmap/regmap.c   |  79 +-
 drivers/iio/accel/Kconfig  |  11 +
 drivers/iio/accel/Makefile |   1 +
 drivers/iio/accel/adxl372.c| 986 +
 include/linux/regmap.h |  19 +
 8 files changed, 1127 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/iio/accel/adxl372.txt
 create mode 100644 drivers/iio/accel/adxl372.c

-- 
2.7.4



[PATCH 3/3] iio:adxl372: Add filter bandwidth support

2018-08-20 Thread Stefan Popa
This patch adds the option for the user to select the filter bandwidth. The
user can also read the available bandwidths which are always adjusted to be
at most half of the sampling frequency. Furthermore, the currently selected
bandwidth can be read via the read_raw function, while the write_raw sets a
new bandwidth value.

Signed-off-by: Stefan Popa 
---
 drivers/iio/accel/adxl372.c | 38 --
 1 file changed, 36 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 6281e4a..fdaaa58 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -202,6 +202,10 @@ static const int adxl372_samp_freq_tbl[5] = {
400, 800, 1600, 3200, 6400,
 };
 
+static const int adxl372_bw_freq_tbl[5] = {
+   200, 400, 800, 1600, 3200,
+};
+
 struct adxl372_axis_lookup {
unsigned int bits;
enum adxl372_fifo_format fifo_format;
@@ -224,7 +228,8 @@ static const struct adxl372_axis_lookup 
adxl372_axis_lookup_table[] = {
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
-   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ) |  \
+   BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),   \
.scan_index = index,\
.scan_type = {  \
.sign = 's',\
@@ -648,6 +653,9 @@ static int adxl372_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SAMP_FREQ:
*val = adxl372_samp_freq_tbl[st->odr];
return IIO_VAL_INT;
+   case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+   *val = adxl372_bw_freq_tbl[st->bw];
+   return IIO_VAL_INT;
}
 
return -EINVAL;
@@ -658,7 +666,7 @@ static int adxl372_write_raw(struct iio_dev *indio_dev,
 int val, int val2, long info)
 {
struct adxl372_state *st = iio_priv(indio_dev);
-   int odr_index, ret;
+   int odr_index, bw_index, ret;
 
switch (info) {
case IIO_CHAN_INFO_SAMP_FREQ:
@@ -690,11 +698,34 @@ static int adxl372_write_raw(struct iio_dev *indio_dev,
ret = adxl372_set_bandwidth(st, odr_index);
 
return ret;
+   case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+   bw_index = adxl372_find_closest_match(adxl372_bw_freq_tbl,
+   ARRAY_SIZE(adxl372_bw_freq_tbl),
+   val);
+   return adxl372_set_bandwidth(st, bw_index);
default:
return -EINVAL;
}
 }
 
+static ssize_t adxl372_show_filter_freq_avail(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+   struct adxl372_state *st = iio_priv(indio_dev);
+   int i;
+   size_t len = 0;
+
+   for (i = 0; i <= st->odr; i++)
+   len += scnprintf(buf + len, PAGE_SIZE - len,
+"%d ", adxl372_bw_freq_tbl[i]);
+
+   buf[len - 1] = '\n';
+
+   return len;
+}
+
 static ssize_t adxl372_get_fifo_enabled(struct device *dev,
  struct device_attribute *attr,
  char *buf)
@@ -838,9 +869,12 @@ static const struct iio_trigger_ops adxl372_trigger_ops = {
 };
 
 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400");
+static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available,
+  0444, adxl372_show_filter_freq_avail, NULL, 0);
 
 static struct attribute *adxl372_attributes[] = {
_const_attr_sampling_frequency_available.dev_attr.attr,
+   
_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr,
NULL,
 };
 
-- 
2.7.4



[PATCH 1/3] iio: adxl372: Provide validate_trigger and validate_device callbacks

2018-08-20 Thread Stefan Popa
This patch provides a validate_device callback for the trigger which makes
sure that other devices are rejected.

Signed-off-by: Stefan Popa 
---
 drivers/iio/accel/adxl372.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index d2fdc75..5a039ba 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -762,11 +762,24 @@ static int adxl372_dready_trig_set_state(struct 
iio_trigger *trig,
return adxl372_set_interrupts(st, mask, 0);
 }
 
+static int adxl372_validate_trigger(struct iio_dev *indio_dev,
+   struct iio_trigger *trig)
+{
+   struct adxl372_state *st = iio_priv(indio_dev);
+
+   if (st->dready_trig != trig)
+   return -EINVAL;
+
+   return 0;
+}
+
 static const struct iio_trigger_ops adxl372_trigger_ops = {
+   .validate_device = _trigger_validate_own_device,
.set_trigger_state = adxl372_dready_trig_set_state,
 };
 
 static const struct iio_info adxl372_info = {
+   .validate_trigger = _validate_trigger,
.read_raw = adxl372_read_raw,
.debugfs_reg_access = _reg_access,
.hwfifo_set_watermark = adxl372_set_watermark,
-- 
2.7.4



[PATCH 2/3] iio:adxl372: Add sampling frequency support

2018-08-20 Thread Stefan Popa
This patch adds the option for the user to select the sampling frequency.
Also, the user can read the available frequencies and read the currently
set frequency via the read_raw function. The frequency can be set via the
write_raw function.

When the frequency is set, the bandwidth is also checked and ensured
that it is constrained to at most half of the sampling frequency. Also, the
activity and inactivity timers have to be updated because they depend on
the selected ODR.

Signed-off-by: Stefan Popa 
---
 drivers/iio/accel/adxl372.c | 74 -
 1 file changed, 73 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 5a039ba..6281e4a 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -223,7 +223,8 @@ static const struct adxl372_axis_lookup 
adxl372_axis_lookup_table[] = {
.modified = 1,  \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
-   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
+   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
.scan_index = index,\
.scan_type = {  \
.sign = 's',\
@@ -311,6 +312,19 @@ static int adxl372_set_odr(struct adxl372_state *st,
return ret;
 }
 
+static int adxl372_find_closest_match(const int *array,
+ unsigned int size, int val)
+{
+   int i;
+
+   for (i = 0; i < size; i++) {
+   if (val <= array[i])
+   return i;
+   }
+
+   return size - 1;
+}
+
 static int adxl372_set_bandwidth(struct adxl372_state *st,
 enum adxl372_bandwidth bw)
 {
@@ -631,6 +645,51 @@ static int adxl372_read_raw(struct iio_dev *indio_dev,
*val = 0;
*val2 = ADXL372_USCALE;
return IIO_VAL_INT_PLUS_MICRO;
+   case IIO_CHAN_INFO_SAMP_FREQ:
+   *val = adxl372_samp_freq_tbl[st->odr];
+   return IIO_VAL_INT;
+   }
+
+   return -EINVAL;
+}
+
+static int adxl372_write_raw(struct iio_dev *indio_dev,
+struct iio_chan_spec const *chan,
+int val, int val2, long info)
+{
+   struct adxl372_state *st = iio_priv(indio_dev);
+   int odr_index, ret;
+
+   switch (info) {
+   case IIO_CHAN_INFO_SAMP_FREQ:
+   odr_index = adxl372_find_closest_match(adxl372_samp_freq_tbl,
+   ARRAY_SIZE(adxl372_samp_freq_tbl),
+   val);
+   ret = adxl372_set_odr(st, odr_index);
+   if (ret < 0)
+   return ret;
+   /*
+* The timer period depends on the ODR selected.
+* At 3200 Hz and below, it is 6.6 ms; at 6400 Hz, it is 3.3 ms
+*/
+   ret = adxl372_set_activity_time_ms(st, st->act_time_ms);
+   if (ret < 0)
+   return ret;
+   /*
+* The timer period depends on the ODR selected.
+* At 3200 Hz and below, it is 26 ms; at 6400 Hz, it is 13 ms
+*/
+   ret = adxl372_set_inactivity_time_ms(st, st->inact_time_ms);
+   if (ret < 0)
+   return ret;
+   /*
+* The maximum bandwidth is constrained to at most half of
+* the ODR to ensure that the Nyquist criteria is not violated
+*/
+   if (st->bw > odr_index)
+   ret = adxl372_set_bandwidth(st, odr_index);
+
+   return ret;
default:
return -EINVAL;
}
@@ -778,9 +837,22 @@ static const struct iio_trigger_ops adxl372_trigger_ops = {
.set_trigger_state = adxl372_dready_trig_set_state,
 };
 
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400");
+
+static struct attribute *adxl372_attributes[] = {
+   _const_attr_sampling_frequency_available.dev_attr.attr,
+   NULL,
+};
+
+static const struct attribute_group adxl372_attrs_group = {
+   .attrs = adxl372_attributes,
+};
+
 static const struct iio_info adxl372_info = {
.validate_trigger = _validate_trigger,
+   .attrs = _attrs_group,
.read_raw = adxl372_read_raw,
+   .write_raw = adxl372_write_raw,
.debugfs_reg_access = _reg_access,
.hwfifo_set_watermark = adxl372_set_watermark,
 };
-- 
2.7.4



[PATCH] iio: dac: ad5758: Add support for hard reset

2018-08-29 Thread Stefan Popa
The ad5758 has a hardware reset active low input pin. This patch adds a
devicetree entry for a reset GPIO and a new ad5758_reset() function.
During
initialization, it is checked if the reset property is specified and the
the GPIO is being asserted, therefore the device will become active.

When the reset function is called, if the gpio_reset var is set, then
the
GPIO will be toggled, otherwise a software reset is performed.

Signed-off-by: Stefan Popa 
---
 .../devicetree/bindings/iio/dac/ad5758.txt |  5 
 drivers/iio/dac/ad5758.c   | 27 --
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/iio/dac/ad5758.txt 
b/Documentation/devicetree/bindings/iio/dac/ad5758.txt
index bba01a5..bbcd789 100644
--- a/Documentation/devicetree/bindings/iio/dac/ad5758.txt
+++ b/Documentation/devicetree/bindings/iio/dac/ad5758.txt
@@ -50,6 +50,9 @@ Required properties:
 
 Optional properties:
 
+ - reset-gpios : GPIO spec for the RESET pin. If specified, it will be
+asserted during driver probe.
+
  - adi,dc-dc-ilim-microamp: The dc-to-dc converter current limit
   The following values are currently supported [uA]:
* 15
@@ -71,6 +74,8 @@ AD5758 Example:
spi-max-frequency = <100>;
spi-cpha;
 
+   reset-gpios = < 22 0>;
+
adi,dc-dc-mode = <2>;
adi,range-microvolt = <0 1000>;
adi,dc-dc-ilim-microamp = <20>;
diff --git a/drivers/iio/dac/ad5758.c b/drivers/iio/dac/ad5758.c
index bd36333..b5cc5bd 100644
--- a/drivers/iio/dac/ad5758.c
+++ b/drivers/iio/dac/ad5758.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -108,6 +109,7 @@ struct ad5758_range {
 struct ad5758_state {
struct spi_device *spi;
struct mutex lock;
+   struct gpio_desc *gpio_reset;
struct ad5758_range out_range;
unsigned int dc_dc_mode;
unsigned int dc_dc_ilim;
@@ -474,6 +476,22 @@ static int ad5758_internal_buffers_en(struct ad5758_state 
*st, bool enable)
 AD5758_CAL_MEM_UNREFRESHED_MSK);
 }
 
+static int ad5758_reset(struct ad5758_state *st)
+{
+   if (st->gpio_reset) {
+   gpiod_set_value(st->gpio_reset, 0);
+   usleep_range(100, 1000);
+   gpiod_set_value(st->gpio_reset, 1);
+   } else {
+   /* Perform a software reset */
+   return ad5758_soft_reset(st);
+   }
+
+   usleep_range(100, 1000);
+
+   return 0;
+}
+
 static int ad5758_reg_access(struct iio_dev *indio_dev,
 unsigned int reg,
 unsigned int writeval,
@@ -768,13 +786,18 @@ static int ad5758_init(struct ad5758_state *st)
 {
int regval, ret;
 
+   st->gpio_reset = devm_gpiod_get_optional(>spi->dev, "reset",
+GPIOD_OUT_HIGH);
+   if (IS_ERR(st->gpio_reset))
+   return PTR_ERR(st->gpio_reset);
+
/* Disable CRC checks */
ret = ad5758_crc_disable(st);
if (ret < 0)
return ret;
 
-   /* Perform a software reset */
-   ret = ad5758_soft_reset(st);
+   /* Perform a reset */
+   ret = ad5758_reset(st);
if (ret < 0)
return ret;
 
-- 
2.7.4



[PATCH 1/3] iio: adxl372: Refactor the driver

2018-09-04 Thread Stefan Popa
This patch restructures the existing adxl372 driver by adding a module for
SPI and a header file, while the baseline module deals with the chip-logic.

This is a necessary step, as this driver should support in the future
a similar device which differs only in the type of interface used (I2C
instead of SPI).

Signed-off-by: Stefan Popa 
---
 MAINTAINERS |  1 +
 drivers/iio/accel/Kconfig   | 11 +--
 drivers/iio/accel/Makefile  |  1 +
 drivers/iio/accel/adxl372.c | 73 ++---
 drivers/iio/accel/adxl372.h | 15 +
 drivers/iio/accel/adxl372_spi.c | 52 +
 6 files changed, 102 insertions(+), 51 deletions(-)
 create mode 100644 drivers/iio/accel/adxl372.h
 create mode 100644 drivers/iio/accel/adxl372_spi.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 2bfc9b0..2938632 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -548,6 +548,7 @@ M:  Stefan Popa 
 W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/iio/accel/adxl372.c
+F: drivers/iio/accel/adxl372_spi.c
 F: Documentation/devicetree/bindings/iio/accel/adxl372.txt
 
 AF9013 MEDIA DRIVER
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index eae23d6..bed5da8 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -61,15 +61,20 @@ config ADXL345_SPI
  for the core module.
 
 config ADXL372
-   tristate "Analog Devices ADXL372 3-Axis Accelerometer Driver"
-   depends on SPI
+   tristate
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
+
+config ADXL372_SPI
+   tristate "Analog Devices ADXL372 3-Axis Accelerometer SPI Driver"
+   depends on SPI
+   select ADXL372
+   select REGMAP_SPI
help
  Say yes here to add support for the Analog Devices ADXL372 triaxial
  acceleration sensor.
  To compile this driver as a module, choose M here: the
- module will be called adxl372.
+ module will be called adxl372_spi.
 
 config BMA180
tristate "Bosch BMA180/BMA250 3-Axis Accelerometer Driver"
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index 5758ffc..c9c5db9 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_ADXL345) += adxl345_core.o
 obj-$(CONFIG_ADXL345_I2C) += adxl345_i2c.o
 obj-$(CONFIG_ADXL345_SPI) += adxl345_spi.o
 obj-$(CONFIG_ADXL372) += adxl372.o
+obj-$(CONFIG_ADXL372_SPI) += adxl372_spi.o
 obj-$(CONFIG_BMA180) += bma180.o
 obj-$(CONFIG_BMA220) += bma220_spi.o
 obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index fdaaa58..f1df89d 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * ADXL372 3-Axis Digital Accelerometer SPI driver
+ * ADXL372 3-Axis Digital Accelerometer core driver
  *
  * Copyright 2018 Analog Devices Inc.
  */
@@ -20,6 +20,8 @@
 #include 
 #include 
 
+#include "adxl372.h"
+
 /* ADXL372 registers definition */
 #define ADXL372_DEVID  0x00
 #define ADXL372_DEVID_MST  0x01
@@ -246,7 +248,8 @@ static const struct iio_chan_spec adxl372_channels[] = {
 };
 
 struct adxl372_state {
-   struct spi_device   *spi;
+   int irq;
+   struct device   *dev;
struct regmap   *regmap;
struct iio_trigger  *dready_trig;
enum adxl372_fifo_mode  fifo_mode;
@@ -565,7 +568,7 @@ static int adxl372_setup(struct adxl372_state *st)
return ret;
 
if (regval != ADXL372_DEVID_VAL) {
-   dev_err(>spi->dev, "Invalid chip id %x\n", regval);
+   dev_err(st->dev, "Invalid chip id %x\n", regval);
return -ENODEV;
}
 
@@ -891,56 +894,45 @@ static const struct iio_info adxl372_info = {
.hwfifo_set_watermark = adxl372_set_watermark,
 };
 
-static bool adxl372_readable_noinc_reg(struct device *dev, unsigned int reg)
+bool adxl372_readable_noinc_reg(struct device *dev, unsigned int reg)
 {
return (reg == ADXL372_FIFO_DATA);
 }
+EXPORT_SYMBOL_GPL(adxl372_readable_noinc_reg);
 
-static const struct regmap_config adxl372_spi_regmap_config = {
-   .reg_bits = 7,
-   .pad_bits = 1,
-   .val_bits = 8,
-   .read_flag_mask = BIT(0),
-   .readable_noinc_reg = adxl372_readable_noinc_reg,
-};
-
-static int adxl372_probe(struct spi_device *spi)
+int adxl372_probe(struct device *dev, struct regmap *regmap,
+ int irq, const char *name)
 {
struct iio_dev *indio_dev;
struct adxl372_state *st;
-   struct regmap *regmap;
int ret;
 
-   indio_dev = devm_iio_device_alloc(>dev, sizeof(*st));
+   ind

[PATCH 2/3] iio: adxl372: Add support for I2C communication

2018-09-04 Thread Stefan Popa
The adxl372 is designed to communicate in either SPI or I2C protocol. It
autodetects the format being used, requiring no configuration control to
select the format.

Signed-off-by: Stefan Popa 
---
 MAINTAINERS |  1 +
 drivers/iio/accel/Kconfig   | 11 
 drivers/iio/accel/Makefile  |  1 +
 drivers/iio/accel/adxl372.c |  1 -
 drivers/iio/accel/adxl372.h |  2 ++
 drivers/iio/accel/adxl372_i2c.c | 61 +
 6 files changed, 76 insertions(+), 1 deletion(-)
 create mode 100644 drivers/iio/accel/adxl372_i2c.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 2938632..2b9a364 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -549,6 +549,7 @@ W:  http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/iio/accel/adxl372.c
 F: drivers/iio/accel/adxl372_spi.c
+F: drivers/iio/accel/adxl372_i2c.c
 F: Documentation/devicetree/bindings/iio/accel/adxl372.txt
 
 AF9013 MEDIA DRIVER
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index bed5da8..7993a67 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -76,6 +76,17 @@ config ADXL372_SPI
  To compile this driver as a module, choose M here: the
  module will be called adxl372_spi.
 
+config ADXL372_I2C
+   tristate "Analog Devices ADXL372 3-Axis Accelerometer I2C Driver"
+   depends on I2C
+   select ADXL372
+   select REGMAP_I2C
+   help
+ Say yes here to add support for the Analog Devices ADXL372 triaxial
+ acceleration sensor.
+ To compile this driver as a module, choose M here: the
+ module will be called adxl372_i2c.
+
 config BMA180
tristate "Bosch BMA180/BMA250 3-Axis Accelerometer Driver"
depends on I2C
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index c9c5db9..56bd021 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_ADXL345) += adxl345_core.o
 obj-$(CONFIG_ADXL345_I2C) += adxl345_i2c.o
 obj-$(CONFIG_ADXL345_SPI) += adxl345_spi.o
 obj-$(CONFIG_ADXL372) += adxl372.o
+obj-$(CONFIG_ADXL372_I2C) += adxl372_i2c.o
 obj-$(CONFIG_ADXL372_SPI) += adxl372_spi.o
 obj-$(CONFIG_BMA180) += bma180.o
 obj-$(CONFIG_BMA220) += bma220_spi.o
diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index f1df89d..3b84cb2 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -26,7 +26,6 @@
 #define ADXL372_DEVID  0x00
 #define ADXL372_DEVID_MST  0x01
 #define ADXL372_PARTID 0x02
-#define ADXL372_REVID  0x03
 #define ADXL372_STATUS_1   0x04
 #define ADXL372_STATUS_2   0x05
 #define ADXL372_FIFO_ENTRIES_2 0x06
diff --git a/drivers/iio/accel/adxl372.h b/drivers/iio/accel/adxl372.h
index 5da89b1..80a0aa9 100644
--- a/drivers/iio/accel/adxl372.h
+++ b/drivers/iio/accel/adxl372.h
@@ -8,6 +8,8 @@
 #ifndef _ADXL372_H_
 #define _ADXL372_H_
 
+#define ADXL372_REVID  0x03
+
 int adxl372_probe(struct device *dev, struct regmap *regmap,
  int irq, const char *name);
 bool adxl372_readable_noinc_reg(struct device *dev, unsigned int reg);
diff --git a/drivers/iio/accel/adxl372_i2c.c b/drivers/iio/accel/adxl372_i2c.c
new file mode 100644
index 000..e1affe4
--- /dev/null
+++ b/drivers/iio/accel/adxl372_i2c.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * ADXL372 3-Axis Digital Accelerometer I2C driver
+ *
+ * Copyright 2018 Analog Devices Inc.
+ */
+
+#include 
+#include 
+#include 
+
+#include "adxl372.h"
+
+static const struct regmap_config adxl372_regmap_config = {
+   .reg_bits = 8,
+   .val_bits = 8,
+   .readable_noinc_reg = adxl372_readable_noinc_reg,
+};
+
+static int adxl372_i2c_probe(struct i2c_client *client,
+const struct i2c_device_id *id)
+{
+   struct regmap *regmap;
+   unsigned int regval;
+   int ret;
+
+   regmap = devm_regmap_init_i2c(client, _regmap_config);
+   if (IS_ERR(regmap))
+   return PTR_ERR(regmap);
+
+   ret = regmap_read(regmap, ADXL372_REVID, );
+   if (ret < 0)
+   return ret;
+
+   /* Starting with the 3rd revision an I2C chip bug was fixed */
+   if (regval < 3)
+   dev_warn(>dev,
+   "I2C might not work properly with other devices on the bus");
+
+   return adxl372_probe(>dev, regmap, client->irq, id->name);
+}
+
+static const struct i2c_device_id adxl372_i2c_id[] = {
+   { "adxl372", 0 },
+   {}
+};
+MODULE_DEVICE_TABLE(i2c, adxl372_i2c_id);
+
+static struct i2c_driver adxl372_i2c_driver = {
+   .driver = {
+   .name = "adxl372_i2c",
+   },
+   .probe = adxl372_i2c_probe,
+   .id_table = adxl372_i2c_id,
+};
+
+module_i2c_driver(adxl372_i2c_driver);
+

[PATCH 3/3] dt-bindings: adxl372: Document the adxl372 I2C bindings

2018-09-04 Thread Stefan Popa
The adxl372 is designed to communicate in either SPI or I2C protocol.
This patch adds the documentation of device tree bindings for adxl372
I2C.

Signed-off-by: Stefan Popa 
---
 Documentation/devicetree/bindings/iio/accel/adxl372.txt | 15 +--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/iio/accel/adxl372.txt 
b/Documentation/devicetree/bindings/iio/accel/adxl372.txt
index 9409984..a289964 100644
--- a/Documentation/devicetree/bindings/iio/accel/adxl372.txt
+++ b/Documentation/devicetree/bindings/iio/accel/adxl372.txt
@@ -4,14 +4,25 @@ 
http://www.analog.com/media/en/technical-documentation/data-sheets/adxl372.pdf
 
 Required properties:
  - compatible : should be "adi,adxl372"
- - reg: SPI chip select number for the device
+ - reg: the I2C address or SPI chip select number for the device
+
+Required properties for SPI bus usage:
  - spi-max-frequency: Max SPI frequency to use
 
 Optional properties:
  - interrupts: interrupt mapping for IRQ as documented in
Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
 
-Example:
+Example for a I2C device node:
+
+   accelerometer@53 {
+   compatible = "adi,adxl372";
+   reg = <0x53>;
+   interrupt-parent = <>;
+   interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
+   };
+
+Example for a SPI device node:
 
accelerometer@0 {
compatible = "adi,adxl372";
-- 
2.7.4



[PATCH 4/5] iio:adxl372: Add sampling frequency support

2018-07-12 Thread Stefan Popa
This patch adds the option for the user to select the sampling frequency.
Also, the user can read the available frequencies and read the currently
set frequency via the read_raw function. The frequency can be set via the
write_raw function.

When the frequency is set, the bandwidth is also checked and ensured
that it is constrained to at most half of the sampling frequency.

Signed-off-by: Stefan Popa 
---
 drivers/iio/accel/adxl372.c | 60 -
 1 file changed, 59 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 645902d..498c740 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -205,7 +205,8 @@ static const int adxl372_samp_freq_tbl[5] = {
.modified = 1,  \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
-   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
+   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
.scan_index = index,\
.scan_type = {  \
.sign = 's',\
@@ -291,6 +292,19 @@ static int adxl372_set_odr(struct adxl372_state *st,
return ret;
 }
 
+static int adxl372_find_closest_match(const int *array,
+ unsigned int size, int val)
+{
+   int i;
+
+   for (i = 0; i < size; i++) {
+   if (val <= array[i])
+   return i;
+   }
+
+   return size - 1;
+}
+
 static int adxl372_set_bandwidth(struct adxl372_state *st,
 enum adxl372_bandwidth bw)
 {
@@ -568,6 +582,37 @@ static int adxl372_read_raw(struct iio_dev *indio_dev,
*val = 0;
*val2 = ADXL372_USCALE;
return IIO_VAL_INT_PLUS_MICRO;
+   case IIO_CHAN_INFO_SAMP_FREQ:
+   *val = adxl372_samp_freq_tbl[st->odr];
+   return IIO_VAL_INT;
+   }
+
+   return -EINVAL;
+}
+
+static int adxl372_write_raw(struct iio_dev *indio_dev,
+struct iio_chan_spec const *chan,
+int val, int val2, long info)
+{
+   struct adxl372_state *st = iio_priv(indio_dev);
+   int odr_index, ret;
+
+   switch (info) {
+   case IIO_CHAN_INFO_SAMP_FREQ:
+   odr_index = adxl372_find_closest_match(adxl372_samp_freq_tbl,
+   ARRAY_SIZE(adxl372_samp_freq_tbl),
+   val);
+   ret = adxl372_set_odr(st, odr_index);
+   if (ret < 0)
+   return ret;
+   /*
+* The maximum bandwidth is constrained to at most half of
+* the ODR to ensure that the Nyquist criteria is not violated
+*/
+   if (st->bw > odr_index)
+   ret = adxl372_set_bandwidth(st, odr_index);
+
+   return ret;
default:
return -EINVAL;
}
@@ -722,8 +767,21 @@ static const struct iio_trigger_ops adxl372_trigger_ops = {
.set_trigger_state = adxl372_dready_trig_set_state,
 };
 
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400");
+
+static struct attribute *adxl372_attributes[] = {
+   _const_attr_sampling_frequency_available.dev_attr.attr,
+   NULL,
+};
+
+static const struct attribute_group adxl372_attrs_group = {
+   .attrs = adxl372_attributes,
+};
+
 static const struct iio_info adxl372_info = {
+   .attrs = _attrs_group,
.read_raw = adxl372_read_raw,
+   .write_raw = adxl372_write_raw,
.debugfs_reg_access = _reg_access,
.hwfifo_set_watermark = adxl372_set_watermark,
 };
-- 
2.7.4



[PATCH 2/5] dt-bindings: iio: accel: Add docs for ADXL372

2018-07-12 Thread Stefan Popa
Add the device tree binding documentation for the ADXL372 3-axis digital
accelerometer.

Signed-off-by: Stefan Popa 
---
 Documentation/devicetree/bindings/iio/accel/adxl372.txt | 16 
 MAINTAINERS |  1 +
 2 files changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/accel/adxl372.txt

diff --git a/Documentation/devicetree/bindings/iio/accel/adxl372.txt 
b/Documentation/devicetree/bindings/iio/accel/adxl372.txt
new file mode 100644
index 000..fea4baf
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/accel/adxl372.txt
@@ -0,0 +1,16 @@
+Analog Devices ADXL372 3-Axis, +/-(200g) Digital Accelerometer
+
+http://www.analog.com/media/en/technical-documentation/data-sheets/adxl372.pdf
+
+Required properties:
+ - compatible : should be "adi,adxl372"
+ - reg: SPI chip select number for the device
+ - spi-max-frequency: Max SPI frequency to use
+
+Example:
+
+   accelerometer@0 {
+   compatible = "adi,adxl372";
+   reg = <0>;
+   spi-max-frequency = <100>;
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 2ba47bb..c8dd09c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -548,6 +548,7 @@ M:  Stefan Popa 
 W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/iio/accel/adxl372.c
+F: Documentation/devicetree/bindings/iio/accel/adxl372.txt
 
 AF9013 MEDIA DRIVER
 M: Antti Palosaari 
-- 
2.7.4



[PATCH 5/5] iio:adxl372: Add filter bandwidth support

2018-07-12 Thread Stefan Popa
This patch adds the option for the user to select the filter bandwidth. The
user can also read the available bandwidths which are always adjusted to be
at most half of the sampling frequency. Furthermore, the currently selected
bandwidth can be read via the read_raw function, while the write_raw sets a
new bandwidth value.

Signed-off-by: Stefan Popa 
---
 drivers/iio/accel/adxl372.c | 38 --
 1 file changed, 36 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 498c740..a73482e 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -199,6 +199,10 @@ static const int adxl372_samp_freq_tbl[5] = {
400, 800, 1600, 3200, 6400,
 };
 
+static const int adxl372_bw_freq_tbl[5] = {
+   200, 400, 800, 1600, 3200,
+};
+
 #define ADXL372_ACCEL_CHANNEL(index, reg, axis) {  \
.type = IIO_ACCEL,  \
.address = reg, \
@@ -206,7 +210,8 @@ static const int adxl372_samp_freq_tbl[5] = {
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
-   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ) |  \
+   BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),   \
.scan_index = index,\
.scan_type = {  \
.sign = 's',\
@@ -585,6 +590,9 @@ static int adxl372_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SAMP_FREQ:
*val = adxl372_samp_freq_tbl[st->odr];
return IIO_VAL_INT;
+   case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+   *val = adxl372_bw_freq_tbl[st->bw];
+   return IIO_VAL_INT;
}
 
return -EINVAL;
@@ -595,7 +603,7 @@ static int adxl372_write_raw(struct iio_dev *indio_dev,
 int val, int val2, long info)
 {
struct adxl372_state *st = iio_priv(indio_dev);
-   int odr_index, ret;
+   int odr_index, bw_index, ret;
 
switch (info) {
case IIO_CHAN_INFO_SAMP_FREQ:
@@ -613,11 +621,34 @@ static int adxl372_write_raw(struct iio_dev *indio_dev,
ret = adxl372_set_bandwidth(st, odr_index);
 
return ret;
+   case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+   bw_index = adxl372_find_closest_match(adxl372_bw_freq_tbl,
+   ARRAY_SIZE(adxl372_bw_freq_tbl),
+   val);
+   return adxl372_set_bandwidth(st, bw_index);
default:
return -EINVAL;
}
 }
 
+static ssize_t adxl372_show_filter_freq_avail(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+   struct adxl372_state *st = iio_priv(indio_dev);
+   int i;
+   size_t len = 0;
+
+   for (i = 0; i <= st->odr; i++)
+   len += scnprintf(buf + len, PAGE_SIZE - len,
+"%d ", adxl372_bw_freq_tbl[i]);
+
+   buf[len - 1] = '\n';
+
+   return len;
+}
+
 static ssize_t adxl372_get_fifo_enabled(struct device *dev,
  struct device_attribute *attr,
  char *buf)
@@ -768,9 +799,12 @@ static const struct iio_trigger_ops adxl372_trigger_ops = {
 };
 
 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400");
+static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available,
+  0444, adxl372_show_filter_freq_avail, NULL, 0);
 
 static struct attribute *adxl372_attributes[] = {
_const_attr_sampling_frequency_available.dev_attr.attr,
+   
_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr,
NULL,
 };
 
-- 
2.7.4



[PATCH 1/5] iio: adxl372: New driver for Analog Devices ADXL372 Accelerometer

2018-07-12 Thread Stefan Popa
This patch adds basic support for Analog Devices ADXL372 SPI-Bus
Three-Axis Digital Accelerometer.

The device is probed and configured the with some initial default
values. With this basic driver, it is possible to read raw acceleration
data.

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL372.pdf

Signed-off-by: Stefan Popa 
---
 MAINTAINERS |   6 +
 drivers/iio/accel/Kconfig   |  11 +
 drivers/iio/accel/Makefile  |   1 +
 drivers/iio/accel/adxl372.c | 483 
 4 files changed, 501 insertions(+)
 create mode 100644 drivers/iio/accel/adxl372.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 60b1028..2ba47bb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -543,6 +543,12 @@ W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/input/misc/adxl34x.c
 
+ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
+M: Stefan Popa 
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/accel/adxl372.c
+
 AF9013 MEDIA DRIVER
 M: Antti Palosaari 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 62ae7e5..1b496ef 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -60,6 +60,17 @@ config ADXL345_SPI
  will be called adxl345_spi and you will also get adxl345_core
  for the core module.
 
+config ADXL372
+   tristate "Analog Devices ADXL372 3-Axis Accelerometer Driver"
+   depends on SPI
+   select IIO_BUFFER
+   select IIO_TRIGGERED_BUFFER
+   help
+ Say yes here to add support for the Analog Devices ADXL372 triaxial
+ acceleration sensor.
+ To compile this driver as a module, choose M here: the
+ module will be called adxl372.
+
 config BMA180
tristate "Bosch BMA180/BMA250 3-Axis Accelerometer Driver"
depends on I2C
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index 636d4d1..5758ffc 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_ADIS16209) += adis16209.o
 obj-$(CONFIG_ADXL345) += adxl345_core.o
 obj-$(CONFIG_ADXL345_I2C) += adxl345_i2c.o
 obj-$(CONFIG_ADXL345_SPI) += adxl345_spi.o
+obj-$(CONFIG_ADXL372) += adxl372.o
 obj-$(CONFIG_BMA180) += bma180.o
 obj-$(CONFIG_BMA220) += bma220_spi.o
 obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
new file mode 100644
index 000..62ce238
--- /dev/null
+++ b/drivers/iio/accel/adxl372.c
@@ -0,0 +1,483 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * ADXL372 3-Axis Digital Accelerometer SPI driver
+ *
+ * Copyright 2018 Analog Devices Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+/* ADXL372 registers definition */
+#define ADXL372_DEVID  0x00
+#define ADXL372_DEVID_MST  0x01
+#define ADXL372_PARTID 0x02
+#define ADXL372_REVID  0x03
+#define ADXL372_STATUS_1   0x04
+#define ADXL372_STATUS_2   0x05
+#define ADXL372_FIFO_ENTRIES_2 0x06
+#define ADXL372_FIFO_ENTRIES_1 0x07
+#define ADXL372_X_DATA_H   0x08
+#define ADXL372_X_DATA_L   0x09
+#define ADXL372_Y_DATA_H   0x0A
+#define ADXL372_Y_DATA_L   0x0B
+#define ADXL372_Z_DATA_H   0x0C
+#define ADXL372_Z_DATA_L   0x0D
+#define ADXL372_X_MAXPEAK_H0x15
+#define ADXL372_X_MAXPEAK_L0x16
+#define ADXL372_Y_MAXPEAK_H0x17
+#define ADXL372_Y_MAXPEAK_L0x18
+#define ADXL372_Z_MAXPEAK_H0x19
+#define ADXL372_Z_MAXPEAK_L0x1A
+#define ADXL372_OFFSET_X   0x20
+#define ADXL372_OFFSET_Y   0x21
+#define ADXL372_OFFSET_Z   0x22
+#define ADXL372_X_THRESH_ACT_H 0x23
+#define ADXL372_X_THRESH_ACT_L 0x24
+#define ADXL372_Y_THRESH_ACT_H 0x25
+#define ADXL372_Y_THRESH_ACT_L 0x26
+#define ADXL372_Z_THRESH_ACT_H 0x27
+#define ADXL372_Z_THRESH_ACT_L 0x28
+#define ADXL372_TIME_ACT   0x29
+#define ADXL372_X_THRESH_INACT_H   0x2A
+#define ADXL372_X_THRESH_INACT_L   0x2B
+#define ADXL372_Y_THRESH_INACT_H   0x2C
+#define ADXL372_Y_THRESH_INACT_L   0x2D
+#define ADXL372_Z_THRESH_INACT_H   0x2E
+#define ADXL372_Z_THRESH_INACT_L   0x2F
+#define ADXL372_TIME_INACT_H   0x30
+#define ADXL372_TIME_INACT_L   0x31
+#define ADXL372_X_THRESH_ACT2_H0x32
+#define ADXL372_X_THRESH_ACT2_L0x33
+#define ADXL372_Y_THRESH_ACT2_H0x34
+#define ADXL372_Y_THRESH_ACT2_L0x35
+#define ADXL372_Z_THRESH_ACT2_H0x36
+#define ADXL372_Z_THRESH_ACT2_L0x37
+#define ADXL372_HPF 

[PATCH 3/5] iio:adxl372: Add FIFO and interrupts support

2018-07-12 Thread Stefan Popa
This patch adds support for the adxl372 FIFO. In order to accomplish this,
triggered buffers were used.

The number of FIFO samples which trigger the watermark interrupt can be
configured by using the buffer watermark, while the format depends on the
selected channels.The FIFO data along with the timestamp is pushed to the
IIO device's buffer.

Signed-off-by: Stefan Popa 
---
 .../devicetree/bindings/iio/accel/adxl372.txt  |   7 +
 drivers/iio/accel/adxl372.c| 346 -
 2 files changed, 352 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/iio/accel/adxl372.txt 
b/Documentation/devicetree/bindings/iio/accel/adxl372.txt
index fea4baf..73d7e03 100644
--- a/Documentation/devicetree/bindings/iio/accel/adxl372.txt
+++ b/Documentation/devicetree/bindings/iio/accel/adxl372.txt
@@ -7,10 +7,17 @@ Required properties:
  - reg: SPI chip select number for the device
  - spi-max-frequency: Max SPI frequency to use
 
+Optional properties:
+ - interrupt-parent: phandle to the parent interrupt controller
+ - interrupts: interrupt mapping for GPIO IRQ, it should by configured with
+   flag IRQ_TYPE_EDGE_FALLING
+
 Example:
 
accelerometer@0 {
compatible = "adi,adxl372";
reg = <0>;
spi-max-frequency = <100>;
+   interrupt-parent = <>;
+   interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
};
diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 62ce238..645902d 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -6,12 +6,20 @@
  */
 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
 
 /* ADXL372 registers definition */
 #define ADXL372_DEVID  0x00
@@ -126,6 +134,8 @@
 #define ADXL372_INT1_MAP_LOW_MSK   BIT(7)
 #define ADXL372_INT1_MAP_LOW_MODE(x)   (((x) & 0x1) << 7)
 
+#define ADXL372_FIFO_SIZE  512
+
 /*
  * At +/- 200g with 12-bit resolution, scale is computed as:
  * (200 + 200) * 9.81 / (2^12 - 1) = 0.958241
@@ -167,6 +177,28 @@ enum adxl372_bandwidth {
ADXL372_BW_3200HZ,
 };
 
+enum adxl372_fifo_format {
+   ADXL372_XYZ_FIFO,
+   ADXL372_X_FIFO,
+   ADXL372_Y_FIFO,
+   ADXL372_XY_FIFO,
+   ADXL372_Z_FIFO,
+   ADXL372_XZ_FIFO,
+   ADXL372_YZ_FIFO,
+   ADXL372_XYZ_PEAK_FIFO,
+};
+
+enum adxl372_fifo_mode {
+   ADXL372_FIFO_BYPASSED,
+   ADXL372_FIFO_STREAMED,
+   ADXL372_FIFO_TRIGGERED,
+   ADXL372_FIFO_OLD_SAVED
+};
+
+static const int adxl372_samp_freq_tbl[5] = {
+   400, 800, 1600, 3200, 6400,
+};
+
 #define ADXL372_ACCEL_CHANNEL(index, reg, axis) {  \
.type = IIO_ACCEL,  \
.address = reg, \
@@ -193,12 +225,27 @@ static const struct iio_chan_spec adxl372_channels[] = {
 struct adxl372_state {
struct spi_device   *spi;
struct regmap   *regmap;
+   struct iio_trigger  *dready_trig;
+   enum adxl372_fifo_mode  fifo_mode;
+   enum adxl372_fifo_formatfifo_format;
enum adxl372_op_modeop_mode;
enum adxl372_act_proc_mode  act_proc_mode;
enum adxl372_odrodr;
enum adxl372_bandwidth  bw;
+   u8  fifo_set_size;
+   u8  int1_bitmask;
+   u8  int2_bitmask;
+   u16 watermark;
+   __be16  fifo_buf[512];
 };
 
+static int adxl372_read_fifo(struct adxl372_state *st, u16 fifo_entries)
+{
+   return regmap_bulk_read(st->regmap,
+   ADXL372_RD_FLAG_MSK(ADXL372_FIFO_DATA),
+   st->fifo_buf, fifo_entries * 2);
+}
+
 static int adxl372_read_axis(struct adxl372_state *st, u8 addr)
 {
__be16 regval;
@@ -313,6 +360,114 @@ static int adxl372_set_activity_threshold(struct 
adxl372_state *st,
 buf, ARRAY_SIZE(buf));
 }
 
+static int adxl372_set_interrupts(struct adxl372_state *st,
+ unsigned char int1_bitmask,
+ unsigned char int2_bitmask)
+{
+   unsigned char buf[2];
+   int ret;
+
+   buf[0] = int1_bitmask;
+   buf[1] = int2_bitmask;
+
+   /* INT1_MAP and INT2_MAP are adjacent registers */
+   ret = regmap_bulk_write(st->regmap,
+   ADXL372_WR_FLAG_MSK(ADXL372_INT1_MAP),
+   buf, ARRAY_SIZE(buf));
+   if (ret < 0)
+   return ret;
+
+   st->int1_bitm

[PATCH v5 2/2] dt-bindings: iio: dac: Add docs for AD5758 DAC

2018-07-04 Thread Stefan Popa
Signed-off-by: Stefan Popa 
---
Changes in v5:
- used a dac@0 as a more generic node name instead of ad5758@0.
Changes in v4:
- Nothing changed, just to follow the patch set version.
Changes in v3:
- AD5758 can be both a current and voltage output DAC. The
  decision is made based on the DT and the channel type is set
  during probe.
- range was replaced by range-microvolt and range-microamp
- dc-dc-mode, range-microvolt and range-microamp are required
  properties.
- Introduced a slew-time-us property from which slew rate clock
  and slew rate step are calculated using a best match algorithm.
- Added units in the name of the properties.
- Offered more explanation for the various modes of operation.

Changes in v2:
- Nothing changed, just to follow the patch set version.

 .../devicetree/bindings/iio/dac/ad5758.txt | 73 ++
 MAINTAINERS|  1 +
 2 files changed, 74 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/dac/ad5758.txt

diff --git a/Documentation/devicetree/bindings/iio/dac/ad5758.txt 
b/Documentation/devicetree/bindings/iio/dac/ad5758.txt
new file mode 100644
index 000..90bc496
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/ad5758.txt
@@ -0,0 +1,73 @@
+Analog Devices AD5758 DAC device driver
+
+Required properties for the AD5758:
+   - compatible: Must be "adi,ad5758"
+   - reg: SPI chip select number for the device
+   - spi-max-frequency: Max SPI frequency to use (< 5000)
+   - spi-cpha: is the only mode that is supported
+
+Required properties:
+
+ - adi,dc-dc-mode: Mode of operation of the dc-to-dc converter
+  Dynamic Power Control (DPC)
+  In this mode, the AD5758 circuitry senses the output voltage 
and
+  dynamically regulates the supply voltage, VDPC+, to meet 
compliance
+  requirements plus an optimized headroom voltage for the 
output buffer.
+
+  Programmable Power Control (PPC)
+  In this mode, the VDPC+ voltage is user-programmable to a 
fixed level
+  that needs to accommodate the maximum output load required.
+
+  The output of the DAC core is either converted to a current 
or voltage
+  output at the VIOUT pin. Only one mode can be enabled at any 
one time.
+
+  The following values are currently supported:
+   * 1: DPC current mode
+   * 2: DPC voltage mode
+   * 3: PPC current mode
+
+ Depending on the selected output mode (voltage or current) one of the two 
properties must
+ be present:
+
+ - adi,range-microvolt: Voltage output range
+   The array of voltage output ranges must contain two fields:
+   * <0 500>: 0 V to 5 V voltage range
+   * <0 1000>: 0 V to 10 V voltage range
+   * <(-500) 500>: ±5 V voltage range
+   * <(-1000) 1000>: ±10 V voltage range
+ - adi,range-microamp: Current output range
+   The array of current output ranges must contain two fields:
+   * <0 2>: 0 mA to 20 mA current range
+   * <0 24000>: 0 mA to 24 mA current range
+   * <4 24000>: 4 mA to 20 mA current range
+   * <(-2) 2>: ±20 mA current range
+   * <(-24000) 24000>: ±24 mA current range
+   * <(-1000) 22000>: −1 mA to +22 mA current range
+
+Optional properties:
+
+ - adi,dc-dc-ilim-microamp: The dc-to-dc converter current limit
+  The following values are currently supported [uA]:
+   * 15
+   * 20
+   * 25
+   * 30
+   * 35
+   * 40
+
+ - adi,slew-time-us: The time it takes for the output to reach the full scale 
[uS]
+The supported range is between 133us up to 1023984375us
+
+AD5758 Example:
+
+   dac@0 {
+   compatible = "adi,ad5758";
+   reg = <0>;
+   spi-max-frequency = <100>;
+   spi-cpha;
+
+   adi,dc-dc-mode = <2>;
+   adi,range-microvolt = <0 1000>;
+   adi,dc-dc-ilim-microamp = <20>;
+   adi,slew-time-us = <125000>;
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 12d102d..60b1028 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -802,6 +802,7 @@ L:  linux-...@vger.kernel.org
 W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/iio/dac/ad5758.c
+F: Documentation/devicetree/bindings/iio/dac/ad5758.txt
 
 ANALOG DEVICES INC AD5686 DRIVER
 M: Stefan Popa 
-- 
2.7.4



[PATCH v5 1/2] iio: dac: Add AD5758 support

2018-07-04 Thread Stefan Popa
The AD5758 is a single channel DAC with 16-bit precision which uses the
SPI interface that operates at clock rates up to 50MHz.

The output can be configured as voltage or current and is available on a
single terminal.

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/ad5758.pdf

Signed-off-by: Stefan Popa 
---
Changes in v5:
- changed the handling choice of voltage vs current by picking
  between two constant structs.
- returned ad5758_wait_for_task_complete() directly where possible.
- fixed double spaces and removed unnecessary parentheses.
- kept the includes in alphabetical order and removed asm/div64.h.
- used usleep_range() instead of udelay().
- removed unnecessary casting when calling bsearch().
Changes in v4:
- fixed kbuild test robot warnings.
Changes in v3:
- AD5758 can be both a current and voltage output DAC. The
  decision is made based on the DT and the channel type is set
  during probe.
- dc-dc-mode, range-microvolt and range-microamp are required
  properties.
- Introduced a slew-time-us property from which slew rate clock
  and slew rate step are calculated using a best match algorithm.
- Dropped the union from ad5758_state struct.
- Introduced a IIO_CHAN_INFO_OFFSET case part of ad5758_read_raw().
- Added a TODO comment which specifies that CRC is not supported.
- Kept the includes in order and removed the unused ones.
- Removed unused macros and shortened the lengthy ones.
- Renamed AD5758_REG_WRITE to AD5758_WR_FLAG_MSK.
- Added an explanation for enum ad5758_output_range.
- Used bsearch() instead of ad5758_get_array_index().
- Reduced the delays.
- strtobool() -> kstrtobool().

Changes in v2:
- removed unnecessary parenthesis in AD5758_REG_WRITE macro.
- added missing documentation fields of ad5758_state struct.
- changed the type of pwr_down attribute to bool.
- changed ad5758_dc_dc_ilimt[] to ad5758_dc_dc_ilim[].
- ad5758_spi_reg_write() now returns spi_write(st->spi,
  >data[0].d32, sizeof(st->data[0].d32));
- removed unnecessary new line in ad5758_calib_mem_refresh().
- changed the type of the mode parameter in
  ad5758_set_dc_dc_conv_mode() from unsigned int to enum
  ad5758_dc_dc_mode.
- removed unnecessary parenthesis in ad5758_slew_rate_config().
- changed the type of the enable parameter in
  ad5758_fault_prot_switch_en() from unsigned char to bool.
- the same as above, but for ad5758_internal_buffers_en().
- added a missing mutex_unlock() in ad5758_reg_access().
- moved the mutex_unlock() in ad5758_read_raw() and removed the
  unreachable return.
- returned directly where it was possible in ad5758_write_raw().
- removed the channel, scan_type and scan_index fields.
- in ad5758_parse_dt(), added missing "\n", and specified what the
  default mode actually is.
- returned directly at the end of ad5758_init().
- in ad5758_probe() used device managed for registering the device
  and returned directly without the error message.

 MAINTAINERS  |   7 +
 drivers/iio/dac/Kconfig  |  10 +
 drivers/iio/dac/Makefile |   1 +
 drivers/iio/dac/ad5758.c | 897 +++
 4 files changed, 915 insertions(+)
 create mode 100644 drivers/iio/dac/ad5758.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 00e9670..12d102d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -796,6 +796,13 @@ M: Michael Hanselmann 
 S: Supported
 F: drivers/macintosh/ams/
 
+ANALOG DEVICES INC AD5758 DRIVER
+M: Stefan Popa 
+L: linux-...@vger.kernel.org
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/dac/ad5758.c
+
 ANALOG DEVICES INC AD5686 DRIVER
 M: Stefan Popa 
 L: linux...@vger.kernel.org
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 06e90de..80beb64 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -167,6 +167,16 @@ config AD5755
  To compile this driver as a module, choose M here: the
  module will be called ad5755.
 
+config AD5758
+   tristate "Analog Devices AD5758 DAC driver"
+   depends on SPI_MASTER
+   help
+ Say yes here to build support for Analog Devices AD5758 single channel
+ Digital to Analog Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5758.
+
 config AD5761
tristate "Analog Devices AD5761/61R/21/21R DAC driver"
depends on SPI_MASTER
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 57aa230..a1b37cf 100644
--- a/drivers/iio/dac/Makefile
+++

[PATCH v2 2/3] adp5061: Add support for battery charging enable

2018-04-10 Thread Stefan Popa
This patch adds the option to enable/disable battery charging. This
option is not configurable via the power_supply properties, therefore,
access via sysfs was provided to examine and modify this attribute on the
fly.

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
  - Fixed kbuild test error by changing the type of the
charging_enabled_show() and charging_enabled_store() functions from
int to ssize_t.

 .../ABI/testing/sysfs-class-power-adp5061  | 10 
 MAINTAINERS|  1 +
 drivers/power/supply/adp5061.c | 63 ++
 3 files changed, 74 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-power-adp5061

diff --git a/Documentation/ABI/testing/sysfs-class-power-adp5061 
b/Documentation/ABI/testing/sysfs-class-power-adp5061
new file mode 100644
index 000..0d056aa
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-power-adp5061
@@ -0,0 +1,10 @@
+What: /sys/class/power_supply/adp5061/charging_enabled
+Description:
+   Enable/disable battery charging.
+
+   The ADP5061 charging function can be enabled by setting
+   this attribute to 1. See device datasheet for details.
+
+   Valid values:
+   - 1: enabled
+   - 0: disabled
diff --git a/MAINTAINERS b/MAINTAINERS
index a9ca73b..9271246 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -804,6 +804,7 @@ W:  http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: Documentation/devicetree/bindings/power/supply/adp5061.txt
 F: drivers/power/supply/adp5061.c
+F: Documentation/ABI/testing/sysfs-class-power-adp5061
 
 ANALOG DEVICES INC ADV7180 DRIVER
 M: Lars-Peter Clausen <l...@metafoo.de>
diff --git a/drivers/power/supply/adp5061.c b/drivers/power/supply/adp5061.c
index c00a02e..99871e6 100644
--- a/drivers/power/supply/adp5061.c
+++ b/drivers/power/supply/adp5061.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 
+
 /* ADP5061 registers definition */
 #define ADP5061_ID 0x00
 #define ADP5061_REV0x01
@@ -79,6 +80,10 @@
 #define ADP5061_IEND_IEND_MSK  GENMASK(7, 5)
 #define ADP5061_IEND_IEND_MODE(x)  (((x) & 0x07) << 5)
 
+/* ADP5061_FUNC_SET_1 */
+#define ADP5061_FUNC_SET_1_EN_CHG_MSK  BIT(0)
+#define ADP5061_FUNC_SET_1_EN_CHG_MODE(x)  (((x) & 0x01) << 0)
+
 #define ADP5061_NO_BATTERY 0x01
 #define ADP5061_ICHG_MAX   1300 // mA
 
@@ -692,11 +697,63 @@ static const struct power_supply_desc adp5061_desc = {
.num_properties = ARRAY_SIZE(adp5061_props),
 };
 
+static ssize_t charging_enabled_show(struct device *dev,
+struct device_attribute *attr,
+char *buf)
+{
+   struct power_supply *psy = dev_get_drvdata(dev);
+   struct adp5061_state *st = power_supply_get_drvdata(psy);
+   unsigned int regval;
+   int ret;
+
+   ret = regmap_read(st->regmap, ADP5061_FUNC_SET_1, );
+   if (ret < 0)
+   return ret;
+
+   regval &= ADP5061_FUNC_SET_1_EN_CHG_MSK;
+   return sprintf(buf, "%d\n", regval);
+}
+
+static ssize_t charging_enabled_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   struct power_supply *psy = dev_get_drvdata(dev);
+   struct adp5061_state *st = power_supply_get_drvdata(psy);
+   u8 chg_en;
+   int ret;
+
+   ret = kstrtou8(buf, 0, _en);
+   if (ret < 0)
+   return ret;
+
+   ret = regmap_update_bits(st->regmap, ADP5061_FUNC_SET_1,
+ADP5061_FUNC_SET_1_EN_CHG_MSK,
+ADP5061_FUNC_SET_1_EN_CHG_MODE(!!chg_en));
+
+   if (ret < 0)
+   return ret;
+
+   return count;
+}
+
+static DEVICE_ATTR_RW(charging_enabled);
+
+static struct attribute *adp5061_attributes[] = {
+   _attr_charging_enabled.attr,
+   NULL
+};
+
+static const struct attribute_group adp5061_attr_group = {
+   .attrs = adp5061_attributes,
+};
+
 static int adp5061_probe(struct i2c_client *client,
 const struct i2c_device_id *id)
 {
struct power_supply_config psy_cfg = {};
struct adp5061_state *st;
+   int ret;
 
st = devm_kzalloc(>dev, sizeof(*st), GFP_KERNEL);
if (!st)
@@ -722,6 +779,12 @@ static int adp5061_probe(struct i2c_client *client,
return PTR_ERR(st->psy);
}
 
+   ret = sysfs_create_group(>psy->dev.kobj, _attr_group);
+   if (ret < 0) {
+   dev_err(>dev, "failed to create sysfs group\n");
+   return ret;
+   }
+
return 0;
 }
 
-- 
2.7.4



[PATCH v2 1/3] adp5061: New driver for ADP5061 I2C battery charger

2018-04-10 Thread Stefan Popa
This patch adds basic support for Analog Devices I2C programmable linear
battery charger.

With this driver, some parameters can be read and configured such as:
* trickle charge current level
* trickle charge voltage threshold
* weak charge threshold
* constant current
* constant charge voltage limit
* battery full
* input current limit
* charger status
* battery status
* termination current

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/ADP5061.pdf

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
  - Fixed typo in Kconfig file: build -> built

 .../devicetree/bindings/power/supply/adp5061.txt   |  17 +
 MAINTAINERS|   8 +
 drivers/power/supply/Kconfig   |  11 +
 drivers/power/supply/Makefile  |   1 +
 drivers/power/supply/adp5061.c | 745 +
 5 files changed, 782 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/power/supply/adp5061.txt
 create mode 100644 drivers/power/supply/adp5061.c

diff --git a/Documentation/devicetree/bindings/power/supply/adp5061.txt 
b/Documentation/devicetree/bindings/power/supply/adp5061.txt
new file mode 100644
index 000..7447446
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/adp5061.txt
@@ -0,0 +1,17 @@
+Analog Devices ADP5061 Programmable Linear Battery Charger Driver
+
+Required properties:
+  - compatible:should be "adi,adp5061"
+  - reg:   i2c address of the device
+
+The node for this driver must be a child node of a I2C controller, hence
+all mandatory properties described in
+Documentation/devicetree/bindings/i2c/i2c.txt
+must be specified.
+
+Example:
+
+   adp5061@14 {
+   compatible = "adi,adp5061";
+   reg = <0x14>;
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 3bdc260..a9ca73b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -797,6 +797,14 @@ L: linux-me...@vger.kernel.org
 S: Maintained
 F: drivers/media/i2c/ad9389b*
 
+ANALOG DEVICES INC ADP5061 DRIVER
+M: Stefan Popa <stefan.p...@analog.com>
+L: linux...@vger.kernel.org
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: Documentation/devicetree/bindings/power/supply/adp5061.txt
+F: drivers/power/supply/adp5061.c
+
 ANALOG DEVICES INC ADV7180 DRIVER
 M: Lars-Peter Clausen <l...@metafoo.de>
 L: linux-me...@vger.kernel.org
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 428b426..4cc9aa9 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -75,6 +75,17 @@ config BATTERY_88PM860X
help
  Say Y here to enable battery monitor for Marvell 88PM860x chip.
 
+config CHARGER_ADP5061
+   tristate "ADP5061 battery charger driver"
+   depends on I2C
+   select REGMAP_I2C
+   help
+ Say Y here to enable support for the ADP5061 standalone battery
+ charger.
+
+ This driver can be built as a module. If so, the module will be
+ called adp5061.
+
 config BATTERY_ACT8945A
tristate "Active-semi ACT8945A charger driver"
depends on MFD_ACT8945A || COMPILE_TEST
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index e83aa84..71b1398 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_WM8350_POWER)+= wm8350_power.o
 obj-$(CONFIG_TEST_POWER)   += test_power.o
 
 obj-$(CONFIG_BATTERY_88PM860X) += 88pm860x_battery.o
+obj-$(CONFIG_CHARGER_ADP5061)  += adp5061.o
 obj-$(CONFIG_BATTERY_ACT8945A) += act8945a_charger.o
 obj-$(CONFIG_BATTERY_AXP20X)   += axp20x_battery.o
 obj-$(CONFIG_CHARGER_AXP20X)   += axp20x_ac_power.o
diff --git a/drivers/power/supply/adp5061.c b/drivers/power/supply/adp5061.c
new file mode 100644
index 000..c00a02e
--- /dev/null
+++ b/drivers/power/supply/adp5061.c
@@ -0,0 +1,745 @@
+/*
+ * ADP5061 I2C Programmable Linear Battery Charger
+ *
+ * Copyright 2018 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* ADP5061 registers definition */
+#define ADP5061_ID 0x00
+#define ADP5061_REV0x01
+#define ADP5061_VINX_SET   0x02
+#define ADP5061_TERM_SET   0x03
+#define ADP5061_CHG_CURR   0x04
+#define ADP5061_VOLTAGE_TH 0x05
+#define ADP5061_TIMER_SET  0x06
+#define ADP5061_FUNC_SET_1 0x07
+#define ADP5061_FUNC_SET_2 0x08
+#define ADP5061_INT_EN 0x09
+#define ADP5061_INT_ACT0x0A
+#define ADP5061_CHG_STATUS_1   0x0B
+#define ADP5061_CHG_STATUS_2   0x0C
+#define ADP5061_FAULT

[PATCH v2 3/3] adp5061: Add support for charging voltage limit enable

2018-04-10 Thread Stefan Popa
This patch adds the option to activate/deactivate the charging voltage
limit. If activated, the charger prevents charging until the battery
voltage drops below the VCHG_VLIM threshold.

This option is not configurable via the power_supply properties,
therefore, access via sysfs was provided to examine and modify this
attribute on the fly.

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
  - Fixed the kbuild test error by changing the type of the
charging_vlim_enabled_show() and charging_vlim_enabled_store()
functions from int to ssize_t.

 .../ABI/testing/sysfs-class-power-adp5061  | 13 ++
 drivers/power/supply/adp5061.c | 46 ++
 2 files changed, 59 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-power-adp5061 
b/Documentation/ABI/testing/sysfs-class-power-adp5061
index 0d056aa..25064c1 100644
--- a/Documentation/ABI/testing/sysfs-class-power-adp5061
+++ b/Documentation/ABI/testing/sysfs-class-power-adp5061
@@ -8,3 +8,16 @@ Description:
Valid values:
- 1: enabled
- 0: disabled
+
+What: /sys/class/power_supply/adp5061/charging_vlim_enabled
+Description:
+   Enable/disable charging voltage limit
+
+   The ADP5061 charging voltage limit can be enabled by setting
+   this attribute to 1. When enabled, the charger prevents charging
+   until the battery voltage drops bellow the VCHG_VLIM threshold.
+   See device datasheet for details.
+
+   Valid values:
+   - 1: enabled
+   - 0: disabled
diff --git a/drivers/power/supply/adp5061.c b/drivers/power/supply/adp5061.c
index 99871e6..9716059 100644
--- a/drivers/power/supply/adp5061.c
+++ b/drivers/power/supply/adp5061.c
@@ -84,6 +84,10 @@
 #define ADP5061_FUNC_SET_1_EN_CHG_MSK  BIT(0)
 #define ADP5061_FUNC_SET_1_EN_CHG_MODE(x)  (((x) & 0x01) << 0)
 
+/* ADP5061_FUNC_SET_2 */
+#define ADP5061_FUNC_SET_2_EN_CHG_VLIM_MSK BIT(5)
+#define ADP5061_FUNC_SET_2_EN_CHG_VLIM_MODE(x) (((x) & 0x01) << 5)
+
 #define ADP5061_NO_BATTERY 0x01
 #define ADP5061_ICHG_MAX   1300 // mA
 
@@ -737,10 +741,52 @@ static ssize_t charging_enabled_store(struct device *dev,
return count;
 }
 
+static ssize_t charging_vlim_enabled_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct power_supply *psy = dev_get_drvdata(dev);
+   struct adp5061_state *st = power_supply_get_drvdata(psy);
+   unsigned int regval;
+   int ret;
+
+   ret = regmap_read(st->regmap, ADP5061_FUNC_SET_2, );
+   if (ret < 0)
+   return ret;
+
+   regval = (regval & ADP5061_FUNC_SET_2_EN_CHG_VLIM_MSK) >> 5;
+   return sprintf(buf, "%d\n", regval);
+}
+
+static ssize_t charging_vlim_enabled_store(struct device *dev,
+  struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   struct power_supply *psy = dev_get_drvdata(dev);
+   struct adp5061_state *st = power_supply_get_drvdata(psy);
+   u8 chg_vlim_en;
+   int ret;
+
+   ret = kstrtou8(buf, 0, _vlim_en);
+   if (ret < 0)
+   return ret;
+
+   ret = regmap_update_bits(st->regmap, ADP5061_FUNC_SET_2,
+   ADP5061_FUNC_SET_2_EN_CHG_VLIM_MSK,
+   ADP5061_FUNC_SET_2_EN_CHG_VLIM_MODE(!!chg_vlim_en));
+
+   if (ret < 0)
+   return ret;
+
+   return count;
+}
+
 static DEVICE_ATTR_RW(charging_enabled);
+static DEVICE_ATTR_RW(charging_vlim_enabled);
 
 static struct attribute *adp5061_attributes[] = {
_attr_charging_enabled.attr,
+   _attr_charging_vlim_enabled.attr,
NULL
 };
 
-- 
2.7.4



[PATCH v2 1/6] iio:dac:ad5686: Style fixes no functional changes

2018-04-10 Thread Stefan Popa
This patch fixes some indentation issues and does not modify the
functionality of the driver.

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
 drivers/iio/dac/ad5686.c | 25 ++---
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 20254df..f7f975c 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -24,7 +24,7 @@
 #define AD5686_ADDR(x) ((x) << 16)
 #define AD5686_CMD(x)  ((x) << 20)
 
-#define AD5686_ADDR_DAC(chan)  (0x1 << (chan))
+#define AD5686_ADDR_DAC(chan)  (0x1 << (chan))
 #define AD5686_ADDR_ALL_DAC0xF
 
 #define AD5686_CMD_NOOP0x0
@@ -137,7 +137,7 @@ static const char * const ad5686_powerdown_modes[] = {
 };
 
 static int ad5686_get_powerdown_mode(struct iio_dev *indio_dev,
-   const struct iio_chan_spec *chan)
+const struct iio_chan_spec *chan)
 {
struct ad5686_state *st = iio_priv(indio_dev);
 
@@ -145,7 +145,8 @@ static int ad5686_get_powerdown_mode(struct iio_dev 
*indio_dev,
 }
 
 static int ad5686_set_powerdown_mode(struct iio_dev *indio_dev,
-   const struct iio_chan_spec *chan, unsigned int mode)
+const struct iio_chan_spec *chan,
+unsigned int mode)
 {
struct ad5686_state *st = iio_priv(indio_dev);
 
@@ -163,17 +164,19 @@ static const struct iio_enum ad5686_powerdown_mode_enum = 
{
 };
 
 static ssize_t ad5686_read_dac_powerdown(struct iio_dev *indio_dev,
-   uintptr_t private, const struct iio_chan_spec *chan, char *buf)
+   uintptr_t private, const struct iio_chan_spec *chan, char *buf)
 {
struct ad5686_state *st = iio_priv(indio_dev);
 
return sprintf(buf, "%d\n", !!(st->pwr_down_mask &
-   (0x3 << (chan->channel * 2;
+  (0x3 << (chan->channel * 2;
 }
 
 static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev,
-uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
-size_t len)
+ uintptr_t private,
+ const struct iio_chan_spec *chan,
+ const char *buf,
+ size_t len)
 {
bool readin;
int ret;
@@ -221,10 +224,10 @@ static int ad5686_read_raw(struct iio_dev *indio_dev,
 }
 
 static int ad5686_write_raw(struct iio_dev *indio_dev,
-  struct iio_chan_spec const *chan,
-  int val,
-  int val2,
-  long mask)
+   struct iio_chan_spec const *chan,
+   int val,
+   int val2,
+   long mask)
 {
struct ad5686_state *st = iio_priv(indio_dev);
int ret;
-- 
2.7.4



[PATCH v2 4/6] iio:dac:ad5686: Add AD5672R/76/76R/84R/86R support

2018-04-10 Thread Stefan Popa
The AD5684R/AD5686R are a family of 4 channel DACs with 12-bit, 14-bit and
16-bit precision respectively. The devices come either with a built-in
reference or no built-in reference.

The AD5672R/AD5676/AD5676R are similar, except that they have 8 channels
instead of 4.

Datasheets:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5672R_5676R.pdf
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5686R_5685R_5684R.pdf

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
- Refactored the patch to add support for new parts
 drivers/iio/dac/ad5686.c | 46 ++
 1 file changed, 46 insertions(+)

diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 7353c03..5fb0179 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -88,9 +88,14 @@ struct ad5686_state {
  */
 
 enum ad5686_supported_device_ids {
+   ID_AD5672R,
+   ID_AD5676,
+   ID_AD5676R,
ID_AD5684,
+   ID_AD5684R,
ID_AD5685R,
ID_AD5686,
+   ID_AD5686R
 };
 static int ad5686_spi_write(struct ad5686_state *st,
 u8 cmd, u8 addr, u16 val, u8 shift)
@@ -294,15 +299,47 @@ static struct iio_chan_spec name[] = {
\
AD5868_CHANNEL(3, 8, bits, _shift), \
 }
 
+#define DECLARE_AD5676_CHANNELS(name, bits, _shift)\
+static struct iio_chan_spec name[] = { \
+   AD5868_CHANNEL(0, 0, bits, _shift), \
+   AD5868_CHANNEL(1, 1, bits, _shift), \
+   AD5868_CHANNEL(2, 2, bits, _shift), \
+   AD5868_CHANNEL(3, 3, bits, _shift), \
+   AD5868_CHANNEL(4, 4, bits, _shift), \
+   AD5868_CHANNEL(5, 5, bits, _shift), \
+   AD5868_CHANNEL(6, 6, bits, _shift), \
+   AD5868_CHANNEL(7, 7, bits, _shift), \
+}
+
+DECLARE_AD5676_CHANNELS(ad5672_channels, 12, 4);
+DECLARE_AD5676_CHANNELS(ad5676_channels, 16, 0);
 DECLARE_AD5686_CHANNELS(ad5684_channels, 12, 4);
 DECLARE_AD5686_CHANNELS(ad5685r_channels, 14, 2);
 DECLARE_AD5686_CHANNELS(ad5686_channels, 16, 0);
 
 static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
+   [ID_AD5672R] = {
+   .channels = ad5672_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 8,
+   },
+   [ID_AD5676] = {
+   .channels = ad5676_channels,
+   .num_channels = 8,
+   },
+   [ID_AD5676R] = {
+   .channels = ad5676_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 8,
+   },
[ID_AD5684] = {
.channels = ad5684_channels,
.num_channels = 4,
+   },
+   [ID_AD5684R] = {
+   .channels = ad5684_channels,
.int_vref_mv = 2500,
+   .num_channels = 4,
},
[ID_AD5685R] = {
.channels = ad5685r_channels,
@@ -312,7 +349,11 @@ static const struct ad5686_chip_info 
ad5686_chip_info_tbl[] = {
[ID_AD5686] = {
.channels = ad5686_channels,
.num_channels = 4,
+   },
+   [ID_AD5686R] = {
+   .channels = ad5686_channels,
.int_vref_mv = 2500,
+   .num_channels = 4,
},
 };
 
@@ -392,9 +433,14 @@ static int ad5686_remove(struct spi_device *spi)
 }
 
 static const struct spi_device_id ad5686_id[] = {
+   {"ad5672r", ID_AD5672R},
+   {"ad5676", ID_AD5676},
+   {"ad5676r", ID_AD5676R},
{"ad5684", ID_AD5684},
+   {"ad5684r", ID_AD5684R},
{"ad5685r", ID_AD5685R},
{"ad5686", ID_AD5686},
+   {"ad5686r", ID_AD5686R},
{}
 };
 MODULE_DEVICE_TABLE(spi, ad5686_id);
-- 
2.7.4



[PATCH v2 3/6] iio:dac:ad5686: Add support for AD5685R

2018-04-10 Thread Stefan Popa
This driver acctually supports the AD5685R device and NOT the AD5685, which
does not exist.

More information can be found in the datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5686_5684.pdf

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
- Refactored the patch to add support for new parts

 drivers/iio/dac/ad5686.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 4d1ae3d..7353c03 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -89,7 +89,7 @@ struct ad5686_state {
 
 enum ad5686_supported_device_ids {
ID_AD5684,
-   ID_AD5685,
+   ID_AD5685R,
ID_AD5686,
 };
 static int ad5686_spi_write(struct ad5686_state *st,
@@ -304,7 +304,7 @@ static const struct ad5686_chip_info ad5686_chip_info_tbl[] 
= {
.num_channels = 4,
.int_vref_mv = 2500,
},
-   [ID_AD5685] = {
+   [ID_AD5685R] = {
.channels = ad5685r_channels,
.int_vref_mv = 2500,
.num_channels = 4,
@@ -393,7 +393,7 @@ static int ad5686_remove(struct spi_device *spi)
 
 static const struct spi_device_id ad5686_id[] = {
{"ad5684", ID_AD5684},
-   {"ad5685", ID_AD5685},
+   {"ad5685r", ID_AD5685R},
{"ad5686", ID_AD5686},
{}
 };
-- 
2.7.4



[PATCH v2 2/6] iio:dac:ad5686: Add support for various number of channels

2018-04-10 Thread Stefan Popa
This patch adds a new num_channels attribute as part of the
ad5686_chip_info struct which replaces the AD5686_DAC_CHANNELS define. This
is a necessary step, since this driver should support similar devices which
differ only in the number of channels.

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
- Refactored the patch to add num_channels and the new macro forms
  for the existing parts.

 drivers/iio/dac/ad5686.c | 45 +
 1 file changed, 25 insertions(+), 20 deletions(-)

diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index f7f975c..4d1ae3d 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -19,8 +19,6 @@
 #include 
 #include 
 
-#define AD5686_DAC_CHANNELS4
-
 #define AD5686_ADDR(x) ((x) << 16)
 #define AD5686_CMD(x)  ((x) << 20)
 
@@ -46,12 +44,14 @@
 /**
  * struct ad5686_chip_info - chip specific information
  * @int_vref_mv:   AD5620/40/60: the internal reference voltage
+ * @num_channels:  number of channels
  * @channel:   channel specification
 */
 
 struct ad5686_chip_info {
u16 int_vref_mv;
-   struct iio_chan_specchannel[AD5686_DAC_CHANNELS];
+   unsigned intnum_channels;
+   struct iio_chan_spec*channels;
 };
 
 /**
@@ -269,14 +269,14 @@ static const struct iio_chan_spec_ext_info 
ad5686_ext_info[] = {
{ },
 };
 
-#define AD5868_CHANNEL(chan, bits, _shift) {   \
+#define AD5868_CHANNEL(chan, addr, bits, _shift) { \
.type = IIO_VOLTAGE,\
.indexed = 1,   \
.output = 1,\
.channel = chan,\
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\
-   .address = AD5686_ADDR_DAC(chan),   \
+   .address = addr,\
.scan_type = {  \
.sign = 'u',\
.realbits = (bits), \
@@ -286,31 +286,36 @@ static const struct iio_chan_spec_ext_info 
ad5686_ext_info[] = {
.ext_info = ad5686_ext_info,\
 }
 
+#define DECLARE_AD5686_CHANNELS(name, bits, _shift)\
+static struct iio_chan_spec name[] = { \
+   AD5868_CHANNEL(0, 1, bits, _shift), \
+   AD5868_CHANNEL(1, 2, bits, _shift), \
+   AD5868_CHANNEL(2, 4, bits, _shift), \
+   AD5868_CHANNEL(3, 8, bits, _shift), \
+}
+
+DECLARE_AD5686_CHANNELS(ad5684_channels, 12, 4);
+DECLARE_AD5686_CHANNELS(ad5685r_channels, 14, 2);
+DECLARE_AD5686_CHANNELS(ad5686_channels, 16, 0);
+
 static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
[ID_AD5684] = {
-   .channel[0] = AD5868_CHANNEL(0, 12, 4),
-   .channel[1] = AD5868_CHANNEL(1, 12, 4),
-   .channel[2] = AD5868_CHANNEL(2, 12, 4),
-   .channel[3] = AD5868_CHANNEL(3, 12, 4),
+   .channels = ad5684_channels,
+   .num_channels = 4,
.int_vref_mv = 2500,
},
[ID_AD5685] = {
-   .channel[0] = AD5868_CHANNEL(0, 14, 2),
-   .channel[1] = AD5868_CHANNEL(1, 14, 2),
-   .channel[2] = AD5868_CHANNEL(2, 14, 2),
-   .channel[3] = AD5868_CHANNEL(3, 14, 2),
+   .channels = ad5685r_channels,
.int_vref_mv = 2500,
+   .num_channels = 4,
},
[ID_AD5686] = {
-   .channel[0] = AD5868_CHANNEL(0, 16, 0),
-   .channel[1] = AD5868_CHANNEL(1, 16, 0),
-   .channel[2] = AD5868_CHANNEL(2, 16, 0),
-   .channel[3] = AD5868_CHANNEL(3, 16, 0),
+   .channels = ad5686_channels,
+   .num_channels = 4,
.int_vref_mv = 2500,
},
 };
 
-
 static int ad5686_probe(struct spi_device *spi)
 {
struct ad5686_state *st;
@@ -354,8 +359,8 @@ static int ad5686_probe(struct spi_device *spi)
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->info = _info;
indio_dev->modes = INDIO_DIRECT_MODE;
-   indio_dev->channels = st->chip_info->channel;
-   indio_dev->num_channels = AD5686_DAC_CHANNELS;
+   indio_dev->channels = st->chip_info->channels;
+   indio_dev->num_channels = st->chip_info->num_channels;
 
ret = ad5686_spi_write(st, AD5686_CMD_INTERNAL_REFER_SETUP, 0,
!!voltage_uv, 0);
-- 
2.7.4



[PATCH v2 5/6] iio:dac:ad5686: Refactor the driver

2018-04-10 Thread Stefan Popa
In this patch restructures the existing ad5686 driver by adding a module
for SPI and a header file, while the baseline module deals with the
chip-logic.

This is a necessary step, as this driver should support in the future
similar devices which differ only in the type of interface used (I2C
instead of SPI).

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
- Refactored the patch
- Use st->write directly instead of the ad5686_write() wrapper
- Use st->read directly instead of the ad5686_read() wrapper

 MAINTAINERS  |   7 ++
 drivers/iio/dac/Kconfig  |  17 ++--
 drivers/iio/dac/Makefile |   1 +
 drivers/iio/dac/ad5686-spi.c |  93 +
 drivers/iio/dac/ad5686.c | 190 +++
 drivers/iio/dac/ad5686.h | 107 
 6 files changed, 248 insertions(+), 167 deletions(-)
 create mode 100644 drivers/iio/dac/ad5686-spi.c
 create mode 100644 drivers/iio/dac/ad5686.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 473ac00..637e62d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -791,6 +791,13 @@ M: Michael Hanselmann <linux-ker...@hansmi.ch>
 S: Supported
 F: drivers/macintosh/ams/
 
+ANALOG DEVICES INC AD5686 DRIVER
+M: Stefan Popa <stefan.p...@analog.com>
+L: linux...@vger.kernel.org
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/dac/ad5686*
+
 ANALOG DEVICES INC AD9389B DRIVER
 M: Hans Verkuil <hans.verk...@cisco.com>
 L: linux-me...@vger.kernel.org
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 965d5c0..a00fc45 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -131,15 +131,20 @@ config LTC2632
  module will be called ltc2632.
 
 config AD5686
-   tristate "Analog Devices AD5686R/AD5685R/AD5684R DAC SPI driver"
+   tristate
+
+config AD5686_SPI
+   tristate "Analog Devices AD5686 and similar multi-channel DACs (SPI)"
depends on SPI
+   select AD5686
help
- Say yes here to build support for Analog Devices AD5686R, AD5685R,
- AD5684R, AD5791 Voltage Output Digital to
- Analog Converter.
+   Say yes here to build support for Analog Devices AD5672R, AD5676,
+   AD5676R, AD5684, AD5684R, AD5684R, AD5685R, AD5686, AD5686R.
+   Voltage Output Digital to Analog Converter.
+
+   To compile this driver as a module, choose M here: the
+   module will be called ad5686.
 
- To compile this driver as a module, choose M here: the
- module will be called ad5686.
 
 config AD5755
tristate "Analog Devices AD5755/AD5755-1/AD5757/AD5735/AD5737 DAC 
driver"
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 81e710e..07db92e 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_AD5761) += ad5761.o
 obj-$(CONFIG_AD5764) += ad5764.o
 obj-$(CONFIG_AD5791) += ad5791.o
 obj-$(CONFIG_AD5686) += ad5686.o
+obj-$(CONFIG_AD5686_SPI) += ad5686-spi.o
 obj-$(CONFIG_AD7303) += ad7303.o
 obj-$(CONFIG_AD8801) += ad8801.o
 obj-$(CONFIG_CIO_DAC) += cio-dac.o
diff --git a/drivers/iio/dac/ad5686-spi.c b/drivers/iio/dac/ad5686-spi.c
new file mode 100644
index 000..d68579b
--- /dev/null
+++ b/drivers/iio/dac/ad5686-spi.c
@@ -0,0 +1,93 @@
+/*
+ * AD5672R, AD5676, AD5676R, AD5684, AD5684R, AD5684R, AD5685R, AD5686, AD5686R
+ * Digital to analog converters driver
+ *
+ * Copyright 2018 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include "ad5686.h"
+
+#include 
+#include 
+
+static int ad5686_spi_write(struct ad5686_state *st,
+   u8 cmd, u8 addr, u16 val)
+{
+   struct spi_device *spi = to_spi_device(st->dev);
+
+   st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
+ AD5686_ADDR(addr) |
+ val);
+
+   return spi_write(spi, >data[0].d8[1], 3);
+}
+
+static int ad5686_spi_read(struct ad5686_state *st, u8 addr)
+{
+   struct spi_transfer t[] = {
+   {
+   .tx_buf = >data[0].d8[1],
+   .len = 3,
+   .cs_change = 1,
+   }, {
+   .tx_buf = >data[1].d8[1],
+   .rx_buf = >data[2].d8[1],
+   .len = 3,
+   },
+   };
+   struct spi_device *spi = to_spi_device(st->dev);
+   int ret;
+
+   st->data[0].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_READBACK_ENABLE) |
+ AD5686_ADDR(addr));
+   st->data[1].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP));
+
+   ret = spi_sync_transfer(spi, t, ARRAY_SIZE(t));
+   if (ret < 0)
+   return ret;
+
+   return be32_to_cpu(st->data[2].d3

[PATCH v2 6/6] iio:dac:ad5686: Add AD5671R/75R/94/94R/95R/96/96R support

2018-04-10 Thread Stefan Popa
The AD5694/AD5694R/AD5695R/AD5696/AD5696R are a family of 4 channel DACs
with 12-bit, 14-bit and 16-bit precision respectively. The devices have
either no built-in reference, or built-in 2.5V reference.

The AD5671R/AD5675R are similar, except that they have 8 instead of 4
channels.

These devices are similar to AD5672R/AD5676/AD5676R and
AD5684/AD5684R/AD5684/AD5685R/AD5686/AD5686R, except that they use i2c
instead of spi.

Datasheets:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5671R_5675R.pdf
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5696R_5695R_5694R.pdf

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
- Refactored the patch

 MAINTAINERS  |  1 +
 drivers/iio/dac/Kconfig  | 10 +
 drivers/iio/dac/Makefile |  1 +
 drivers/iio/dac/ad5686.c | 28 +
 drivers/iio/dac/ad5686.h |  7 
 drivers/iio/dac/ad5696-i2c.c | 98 
 6 files changed, 145 insertions(+)
 create mode 100644 drivers/iio/dac/ad5696-i2c.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 637e62d..002cb01 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -797,6 +797,7 @@ L:  linux...@vger.kernel.org
 W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/iio/dac/ad5686*
+F: drivers/iio/dac/ad5696*
 
 ANALOG DEVICES INC AD9389B DRIVER
 M: Hans Verkuil <hans.verk...@cisco.com>
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index a00fc45..dab0b8a 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -145,6 +145,16 @@ config AD5686_SPI
To compile this driver as a module, choose M here: the
module will be called ad5686.
 
+config AD5696_I2C
+   tristate "Analog Devices AD5696 and similar multi-channel DACs (I2C)"
+   depends on I2C
+   select AD5686
+   help
+   Say yes here to build support for Analog Devices AD5671R, AD5675R,
+   AD5694, AD5694R, AD5695R, AD5696, AD5696R Voltage Output Digital to
+   Analog Converter.
+   To compile this driver as a module, choose M here: the module will be
+   called ad5696.
 
 config AD5755
tristate "Analog Devices AD5755/AD5755-1/AD5757/AD5735/AD5737 DAC 
driver"
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 07db92e..4397e21 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_AD5764) += ad5764.o
 obj-$(CONFIG_AD5791) += ad5791.o
 obj-$(CONFIG_AD5686) += ad5686.o
 obj-$(CONFIG_AD5686_SPI) += ad5686-spi.o
+obj-$(CONFIG_AD5696_I2C) += ad5696-i2c.o
 obj-$(CONFIG_AD7303) += ad7303.o
 obj-$(CONFIG_AD8801) += ad8801.o
 obj-$(CONFIG_CIO_DAC) += cio-dac.o
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 95de8b8..596e1c9 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -203,11 +203,21 @@ DECLARE_AD5686_CHANNELS(ad5685r_channels, 14, 2);
 DECLARE_AD5686_CHANNELS(ad5686_channels, 16, 0);
 
 static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
+   [ID_AD5671R] = {
+   .channels = ad5672_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 8,
+   },
[ID_AD5672R] = {
.channels = ad5672_channels,
.int_vref_mv = 2500,
.num_channels = 8,
},
+   [ID_AD5675R] = {
+   .channels = ad5676_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 8,
+   },
[ID_AD5676] = {
.channels = ad5676_channels,
.num_channels = 8,
@@ -240,6 +250,24 @@ static const struct ad5686_chip_info 
ad5686_chip_info_tbl[] = {
.int_vref_mv = 2500,
.num_channels = 4,
},
+   [ID_AD5694] = {
+   .channels = ad5684_channels,
+   .num_channels = 4,
+   },
+   [ID_AD5694R] = {
+   .channels = ad5684_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 4,
+   },
+   [ID_AD5696] = {
+   .channels = ad5686_channels,
+   .num_channels = 4,
+   },
+   [ID_AD5696R] = {
+   .channels = ad5686_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 4,
+   },
 };
 
 int ad5686_probe(struct device *dev,
diff --git a/drivers/iio/dac/ad5686.h b/drivers/iio/dac/ad5686.h
index e6423af..b2b0110 100644
--- a/drivers/iio/dac/ad5686.h
+++ b/drivers/iio/dac/ad5686.h
@@ -32,7 +32,9 @@
  * ad5686_supported_device_ids:
  */
 enum ad5686_supported_device_ids {
+   ID_AD5671R,
ID_AD5672R,
+   ID_AD5675R,
ID_AD5676,
ID_AD5676R,
ID_AD5684,
@@ -40,6 +42,11 @@ enum ad5686_supported_device_ids {
ID_AD5685R,
ID_AD5686,
ID_AD5686R,
+   ID_AD5694,
+   ID_AD5694R,
+   ID_AD5695R,
+

[PATCH v3 4/7] iio:dac:ad5686: Add support for AD5685R

2018-04-11 Thread Stefan Popa
This driver acctually supports the AD5685R device and NOT the AD5685, which
does not exist.

More information can be found in the datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5686_5684.pdf

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
- Refactored the patch to add support for new parts
Changes in v3:
- Nothing changed, just to follow the patch set version.

 drivers/iio/dac/ad5686.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 87d6e6e..a753ffd 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -88,7 +88,7 @@ struct ad5686_state {
 
 enum ad5686_supported_device_ids {
ID_AD5684,
-   ID_AD5685,
+   ID_AD5685R,
ID_AD5686,
 };
 static int ad5686_spi_write(struct ad5686_state *st,
@@ -303,7 +303,7 @@ static const struct ad5686_chip_info ad5686_chip_info_tbl[] 
= {
.num_channels = 4,
.int_vref_mv = 2500,
},
-   [ID_AD5685] = {
+   [ID_AD5685R] = {
.channels = ad5685r_channels,
.int_vref_mv = 2500,
.num_channels = 4,
@@ -392,7 +392,7 @@ static int ad5686_remove(struct spi_device *spi)
 
 static const struct spi_device_id ad5686_id[] = {
{"ad5684", ID_AD5684},
-   {"ad5685", ID_AD5685},
+   {"ad5685r", ID_AD5685R},
{"ad5686", ID_AD5686},
{}
 };
-- 
2.7.4



[PATCH v3 5/7] iio:dac:ad5686: Add AD5672R/76/76R/84R/86R support

2018-04-11 Thread Stefan Popa
The AD5684R/AD5686R are a family of 4 channel DACs with 12-bit, 14-bit and
16-bit precision respectively. The devices come either with a built-in
reference or no built-in reference.

The AD5672R/AD5676/AD5676R are similar, except that they have 8 channels
instead of 4.

Datasheets:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5672R_5676R.pdf
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5686R_5685R_5684R.pdf

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
- Refactored the patch to add support for new parts
Changes in v3:
- Nothing changed, just to follow the patch set version

 drivers/iio/dac/ad5686.c | 46 ++
 1 file changed, 46 insertions(+)

diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index a753ffd..54f67d5 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -87,9 +87,14 @@ struct ad5686_state {
  */
 
 enum ad5686_supported_device_ids {
+   ID_AD5672R,
+   ID_AD5676,
+   ID_AD5676R,
ID_AD5684,
+   ID_AD5684R,
ID_AD5685R,
ID_AD5686,
+   ID_AD5686R
 };
 static int ad5686_spi_write(struct ad5686_state *st,
 u8 cmd, u8 addr, u16 val, u8 shift)
@@ -293,15 +298,47 @@ static struct iio_chan_spec name[] = {
\
AD5868_CHANNEL(3, 8, bits, _shift), \
 }
 
+#define DECLARE_AD5676_CHANNELS(name, bits, _shift)\
+static struct iio_chan_spec name[] = { \
+   AD5868_CHANNEL(0, 0, bits, _shift), \
+   AD5868_CHANNEL(1, 1, bits, _shift), \
+   AD5868_CHANNEL(2, 2, bits, _shift), \
+   AD5868_CHANNEL(3, 3, bits, _shift), \
+   AD5868_CHANNEL(4, 4, bits, _shift), \
+   AD5868_CHANNEL(5, 5, bits, _shift), \
+   AD5868_CHANNEL(6, 6, bits, _shift), \
+   AD5868_CHANNEL(7, 7, bits, _shift), \
+}
+
+DECLARE_AD5676_CHANNELS(ad5672_channels, 12, 4);
+DECLARE_AD5676_CHANNELS(ad5676_channels, 16, 0);
 DECLARE_AD5686_CHANNELS(ad5684_channels, 12, 4);
 DECLARE_AD5686_CHANNELS(ad5685r_channels, 14, 2);
 DECLARE_AD5686_CHANNELS(ad5686_channels, 16, 0);
 
 static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
+   [ID_AD5672R] = {
+   .channels = ad5672_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 8,
+   },
+   [ID_AD5676] = {
+   .channels = ad5676_channels,
+   .num_channels = 8,
+   },
+   [ID_AD5676R] = {
+   .channels = ad5676_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 8,
+   },
[ID_AD5684] = {
.channels = ad5684_channels,
.num_channels = 4,
+   },
+   [ID_AD5684R] = {
+   .channels = ad5684_channels,
.int_vref_mv = 2500,
+   .num_channels = 4,
},
[ID_AD5685R] = {
.channels = ad5685r_channels,
@@ -311,7 +348,11 @@ static const struct ad5686_chip_info 
ad5686_chip_info_tbl[] = {
[ID_AD5686] = {
.channels = ad5686_channels,
.num_channels = 4,
+   },
+   [ID_AD5686R] = {
+   .channels = ad5686_channels,
.int_vref_mv = 2500,
+   .num_channels = 4,
},
 };
 
@@ -391,9 +432,14 @@ static int ad5686_remove(struct spi_device *spi)
 }
 
 static const struct spi_device_id ad5686_id[] = {
+   {"ad5672r", ID_AD5672R},
+   {"ad5676", ID_AD5676},
+   {"ad5676r", ID_AD5676R},
{"ad5684", ID_AD5684},
+   {"ad5684r", ID_AD5684R},
{"ad5685r", ID_AD5685R},
{"ad5686", ID_AD5686},
+   {"ad5686r", ID_AD5686R},
{}
 };
 MODULE_DEVICE_TABLE(spi, ad5686_id);
-- 
2.7.4



[PATCH v3 1/7] iio:dac:ad5686: Style fixes no functional changes

2018-04-11 Thread Stefan Popa
This patch fixes some indentation issues and does not modify the
functionality of the driver.

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes v2:
- Nothing changed, just follow the patch set version.
Changes v3:
- Nothing changed, just follow the patch set version.

 drivers/iio/dac/ad5686.c | 25 ++---
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 20254df..f7f975c 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -24,7 +24,7 @@
 #define AD5686_ADDR(x) ((x) << 16)
 #define AD5686_CMD(x)  ((x) << 20)
 
-#define AD5686_ADDR_DAC(chan)  (0x1 << (chan))
+#define AD5686_ADDR_DAC(chan)  (0x1 << (chan))
 #define AD5686_ADDR_ALL_DAC0xF
 
 #define AD5686_CMD_NOOP0x0
@@ -137,7 +137,7 @@ static const char * const ad5686_powerdown_modes[] = {
 };
 
 static int ad5686_get_powerdown_mode(struct iio_dev *indio_dev,
-   const struct iio_chan_spec *chan)
+const struct iio_chan_spec *chan)
 {
struct ad5686_state *st = iio_priv(indio_dev);
 
@@ -145,7 +145,8 @@ static int ad5686_get_powerdown_mode(struct iio_dev 
*indio_dev,
 }
 
 static int ad5686_set_powerdown_mode(struct iio_dev *indio_dev,
-   const struct iio_chan_spec *chan, unsigned int mode)
+const struct iio_chan_spec *chan,
+unsigned int mode)
 {
struct ad5686_state *st = iio_priv(indio_dev);
 
@@ -163,17 +164,19 @@ static const struct iio_enum ad5686_powerdown_mode_enum = 
{
 };
 
 static ssize_t ad5686_read_dac_powerdown(struct iio_dev *indio_dev,
-   uintptr_t private, const struct iio_chan_spec *chan, char *buf)
+   uintptr_t private, const struct iio_chan_spec *chan, char *buf)
 {
struct ad5686_state *st = iio_priv(indio_dev);
 
return sprintf(buf, "%d\n", !!(st->pwr_down_mask &
-   (0x3 << (chan->channel * 2;
+  (0x3 << (chan->channel * 2;
 }
 
 static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev,
-uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
-size_t len)
+ uintptr_t private,
+ const struct iio_chan_spec *chan,
+ const char *buf,
+ size_t len)
 {
bool readin;
int ret;
@@ -221,10 +224,10 @@ static int ad5686_read_raw(struct iio_dev *indio_dev,
 }
 
 static int ad5686_write_raw(struct iio_dev *indio_dev,
-  struct iio_chan_spec const *chan,
-  int val,
-  int val2,
-  long mask)
+   struct iio_chan_spec const *chan,
+   int val,
+   int val2,
+   long mask)
 {
struct ad5686_state *st = iio_priv(indio_dev);
int ret;
-- 
2.7.4



[PATCH v3 2/7] iio:dac:ad5686: Change license description

2018-04-11 Thread Stefan Popa
Add GPLv2+ SPDX identifier and remove license notice to keep the whole
purpose of using an SPDx id.

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v3:
- Created a new patch to use the SPDx identifier

 drivers/iio/dac/ad5686.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index f7f975c..e328513 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -1,9 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * AD5686R, AD5685R, AD5684R Digital to analog converters  driver
  *
  * Copyright 2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
  */
 
 #include 
-- 
2.7.4



[PATCH v3 6/7] iio:dac:ad5686: Refactor the driver

2018-04-11 Thread Stefan Popa
In this patch restructures the existing ad5686 driver by adding a module
for SPI and a header file, while the baseline module deals with the
chip-logic.

This is a necessary step, as this driver should support in the future
similar devices which differ only in the type of interface used (I2C
instead of SPI).

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
- Refactored the patch
- Use st->write directly instead of the ad5686_write() wrapper
- Use st->read directly instead of the ad5686_read() wrapper
Changes in v3:
- Indented the the help text from the Konfig file with 2
  additional spaces.
- Changed the license description to use an SPDX tag.

 MAINTAINERS  |   7 ++
 drivers/iio/dac/Kconfig  |  13 ++-
 drivers/iio/dac/Makefile |   1 +
 drivers/iio/dac/ad5686-spi.c |  92 +
 drivers/iio/dac/ad5686.c | 190 +++
 drivers/iio/dac/ad5686.h | 114 ++
 6 files changed, 252 insertions(+), 165 deletions(-)
 create mode 100644 drivers/iio/dac/ad5686-spi.c
 create mode 100644 drivers/iio/dac/ad5686.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 473ac00..637e62d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -791,6 +791,13 @@ M: Michael Hanselmann <linux-ker...@hansmi.ch>
 S: Supported
 F: drivers/macintosh/ams/
 
+ANALOG DEVICES INC AD5686 DRIVER
+M: Stefan Popa <stefan.p...@analog.com>
+L: linux...@vger.kernel.org
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/dac/ad5686*
+
 ANALOG DEVICES INC AD9389B DRIVER
 M: Hans Verkuil <hans.verk...@cisco.com>
 L: linux-me...@vger.kernel.org
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 965d5c0..7a81f1e 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -131,16 +131,21 @@ config LTC2632
  module will be called ltc2632.
 
 config AD5686
-   tristate "Analog Devices AD5686R/AD5685R/AD5684R DAC SPI driver"
+   tristate
+
+config AD5686_SPI
+   tristate "Analog Devices AD5686 and similar multi-channel DACs (SPI)"
depends on SPI
+   select AD5686
help
- Say yes here to build support for Analog Devices AD5686R, AD5685R,
- AD5684R, AD5791 Voltage Output Digital to
- Analog Converter.
+ Say yes here to build support for Analog Devices AD5672R, AD5676,
+ AD5676R, AD5684, AD5684R, AD5684R, AD5685R, AD5686, AD5686R.
+ Voltage Output Digital to Analog Converter.
 
  To compile this driver as a module, choose M here: the
  module will be called ad5686.
 
+
 config AD5755
tristate "Analog Devices AD5755/AD5755-1/AD5757/AD5735/AD5737 DAC 
driver"
depends on SPI_MASTER
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 81e710e..07db92e 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_AD5761) += ad5761.o
 obj-$(CONFIG_AD5764) += ad5764.o
 obj-$(CONFIG_AD5791) += ad5791.o
 obj-$(CONFIG_AD5686) += ad5686.o
+obj-$(CONFIG_AD5686_SPI) += ad5686-spi.o
 obj-$(CONFIG_AD7303) += ad7303.o
 obj-$(CONFIG_AD8801) += ad8801.o
 obj-$(CONFIG_CIO_DAC) += cio-dac.o
diff --git a/drivers/iio/dac/ad5686-spi.c b/drivers/iio/dac/ad5686-spi.c
new file mode 100644
index 000..1cc807b
--- /dev/null
+++ b/drivers/iio/dac/ad5686-spi.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * AD5672R, AD5676, AD5676R, AD5684, AD5684R, AD5684R, AD5685R, AD5686, AD5686R
+ * Digital to analog converters driver
+ *
+ * Copyright 2018 Analog Devices Inc.
+ */
+
+#include "ad5686.h"
+
+#include 
+#include 
+
+static int ad5686_spi_write(struct ad5686_state *st,
+   u8 cmd, u8 addr, u16 val)
+{
+   struct spi_device *spi = to_spi_device(st->dev);
+
+   st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
+ AD5686_ADDR(addr) |
+ val);
+
+   return spi_write(spi, >data[0].d8[1], 3);
+}
+
+static int ad5686_spi_read(struct ad5686_state *st, u8 addr)
+{
+   struct spi_transfer t[] = {
+   {
+   .tx_buf = >data[0].d8[1],
+   .len = 3,
+   .cs_change = 1,
+   }, {
+   .tx_buf = >data[1].d8[1],
+   .rx_buf = >data[2].d8[1],
+   .len = 3,
+   },
+   };
+   struct spi_device *spi = to_spi_device(st->dev);
+   int ret;
+
+   st->data[0].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_READBACK_ENABLE) |
+ AD5686_ADDR(addr));
+   st->data[1].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP));
+
+   ret = spi_sync_transfer(spi, t, ARRAY_SIZE(t

[PATCH v3 7/7] iio:dac:ad5686: Add AD5671R/75R/94/94R/95R/96/96R support

2018-04-11 Thread Stefan Popa
The AD5694/AD5694R/AD5695R/AD5696/AD5696R are a family of 4 channel DACs
with 12-bit, 14-bit and 16-bit precision respectively. The devices have
either no built-in reference, or built-in 2.5V reference.

The AD5671R/AD5675R are similar, except that they have 8 instead of 4
channels.

These devices are similar to AD5672R/AD5676/AD5676R and
AD5684/AD5684R/AD5684/AD5685R/AD5686/AD5686R, except that they use i2c
instead of spi.

Datasheets:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5671R_5675R.pdf
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5696R_5695R_5694R.pdf

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
- Refactored the patch
Changes in v3:
- Indented the the help text from the Konfig file with 2
  additional spaces.
- Changed the license description to use an SPDX tag.

 MAINTAINERS  |  1 +
 drivers/iio/dac/Kconfig  | 10 +
 drivers/iio/dac/Makefile |  1 +
 drivers/iio/dac/ad5686.c | 28 +
 drivers/iio/dac/ad5686.h |  7 
 drivers/iio/dac/ad5696-i2c.c | 97 
 6 files changed, 144 insertions(+)
 create mode 100644 drivers/iio/dac/ad5696-i2c.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 637e62d..002cb01 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -797,6 +797,7 @@ L:  linux...@vger.kernel.org
 W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/iio/dac/ad5686*
+F: drivers/iio/dac/ad5696*
 
 ANALOG DEVICES INC AD9389B DRIVER
 M: Hans Verkuil <hans.verk...@cisco.com>
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 7a81f1e..3ff8a32 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -145,6 +145,16 @@ config AD5686_SPI
  To compile this driver as a module, choose M here: the
  module will be called ad5686.
 
+config AD5696_I2C
+   tristate "Analog Devices AD5696 and similar multi-channel DACs (I2C)"
+   depends on I2C
+   select AD5686
+   help
+ Say yes here to build support for Analog Devices AD5671R, AD5675R,
+ AD5694, AD5694R, AD5695R, AD5696, AD5696R Voltage Output Digital to
+ Analog Converter.
+ To compile this driver as a module, choose M here: the module will be
+ called ad5696.
 
 config AD5755
tristate "Analog Devices AD5755/AD5755-1/AD5757/AD5735/AD5737 DAC 
driver"
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 07db92e..4397e21 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_AD5764) += ad5764.o
 obj-$(CONFIG_AD5791) += ad5791.o
 obj-$(CONFIG_AD5686) += ad5686.o
 obj-$(CONFIG_AD5686_SPI) += ad5686-spi.o
+obj-$(CONFIG_AD5696_I2C) += ad5696-i2c.o
 obj-$(CONFIG_AD7303) += ad7303.o
 obj-$(CONFIG_AD8801) += ad8801.o
 obj-$(CONFIG_CIO_DAC) += cio-dac.o
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 79abff5..89c5f08 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -202,11 +202,21 @@ DECLARE_AD5686_CHANNELS(ad5685r_channels, 14, 2);
 DECLARE_AD5686_CHANNELS(ad5686_channels, 16, 0);
 
 static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
+   [ID_AD5671R] = {
+   .channels = ad5672_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 8,
+   },
[ID_AD5672R] = {
.channels = ad5672_channels,
.int_vref_mv = 2500,
.num_channels = 8,
},
+   [ID_AD5675R] = {
+   .channels = ad5676_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 8,
+   },
[ID_AD5676] = {
.channels = ad5676_channels,
.num_channels = 8,
@@ -239,6 +249,24 @@ static const struct ad5686_chip_info 
ad5686_chip_info_tbl[] = {
.int_vref_mv = 2500,
.num_channels = 4,
},
+   [ID_AD5694] = {
+   .channels = ad5684_channels,
+   .num_channels = 4,
+   },
+   [ID_AD5694R] = {
+   .channels = ad5684_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 4,
+   },
+   [ID_AD5696] = {
+   .channels = ad5686_channels,
+   .num_channels = 4,
+   },
+   [ID_AD5696R] = {
+   .channels = ad5686_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 4,
+   },
 };
 
 int ad5686_probe(struct device *dev,
diff --git a/drivers/iio/dac/ad5686.h b/drivers/iio/dac/ad5686.h
index c8e1565..05f0ce9 100644
--- a/drivers/iio/dac/ad5686.h
+++ b/drivers/iio/dac/ad5686.h
@@ -39,7 +39,9 @@
  * ad5686_supported_device_ids:
  */
 enum ad5686_supported_device_ids {
+   ID_AD5671R,
ID_AD5672R,
+   ID_AD5675R,
ID_AD5676,
ID_AD5676R,
ID

[PATCH v3 3/7] iio:dac:ad5686: Add support for various number of channels

2018-04-11 Thread Stefan Popa
This patch adds a new num_channels attribute as part of the
ad5686_chip_info struct which replaces the AD5686_DAC_CHANNELS define. This
is a necessary step, since this driver should support similar devices which
differ only in the number of channels.

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
- Refactored the patch to add num_channels and the new macro forms
  for the existing parts.
Changes in v3:
- Nothing changed, just follow the patch set version.

 drivers/iio/dac/ad5686.c | 45 +
 1 file changed, 25 insertions(+), 20 deletions(-)

diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index e328513..87d6e6e 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -18,8 +18,6 @@
 #include 
 #include 
 
-#define AD5686_DAC_CHANNELS4
-
 #define AD5686_ADDR(x) ((x) << 16)
 #define AD5686_CMD(x)  ((x) << 20)
 
@@ -45,12 +43,14 @@
 /**
  * struct ad5686_chip_info - chip specific information
  * @int_vref_mv:   AD5620/40/60: the internal reference voltage
+ * @num_channels:  number of channels
  * @channel:   channel specification
 */
 
 struct ad5686_chip_info {
u16 int_vref_mv;
-   struct iio_chan_specchannel[AD5686_DAC_CHANNELS];
+   unsigned intnum_channels;
+   struct iio_chan_spec*channels;
 };
 
 /**
@@ -268,14 +268,14 @@ static const struct iio_chan_spec_ext_info 
ad5686_ext_info[] = {
{ },
 };
 
-#define AD5868_CHANNEL(chan, bits, _shift) {   \
+#define AD5868_CHANNEL(chan, addr, bits, _shift) { \
.type = IIO_VOLTAGE,\
.indexed = 1,   \
.output = 1,\
.channel = chan,\
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\
-   .address = AD5686_ADDR_DAC(chan),   \
+   .address = addr,\
.scan_type = {  \
.sign = 'u',\
.realbits = (bits), \
@@ -285,31 +285,36 @@ static const struct iio_chan_spec_ext_info 
ad5686_ext_info[] = {
.ext_info = ad5686_ext_info,\
 }
 
+#define DECLARE_AD5686_CHANNELS(name, bits, _shift)\
+static struct iio_chan_spec name[] = { \
+   AD5868_CHANNEL(0, 1, bits, _shift), \
+   AD5868_CHANNEL(1, 2, bits, _shift), \
+   AD5868_CHANNEL(2, 4, bits, _shift), \
+   AD5868_CHANNEL(3, 8, bits, _shift), \
+}
+
+DECLARE_AD5686_CHANNELS(ad5684_channels, 12, 4);
+DECLARE_AD5686_CHANNELS(ad5685r_channels, 14, 2);
+DECLARE_AD5686_CHANNELS(ad5686_channels, 16, 0);
+
 static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
[ID_AD5684] = {
-   .channel[0] = AD5868_CHANNEL(0, 12, 4),
-   .channel[1] = AD5868_CHANNEL(1, 12, 4),
-   .channel[2] = AD5868_CHANNEL(2, 12, 4),
-   .channel[3] = AD5868_CHANNEL(3, 12, 4),
+   .channels = ad5684_channels,
+   .num_channels = 4,
.int_vref_mv = 2500,
},
[ID_AD5685] = {
-   .channel[0] = AD5868_CHANNEL(0, 14, 2),
-   .channel[1] = AD5868_CHANNEL(1, 14, 2),
-   .channel[2] = AD5868_CHANNEL(2, 14, 2),
-   .channel[3] = AD5868_CHANNEL(3, 14, 2),
+   .channels = ad5685r_channels,
.int_vref_mv = 2500,
+   .num_channels = 4,
},
[ID_AD5686] = {
-   .channel[0] = AD5868_CHANNEL(0, 16, 0),
-   .channel[1] = AD5868_CHANNEL(1, 16, 0),
-   .channel[2] = AD5868_CHANNEL(2, 16, 0),
-   .channel[3] = AD5868_CHANNEL(3, 16, 0),
+   .channels = ad5686_channels,
+   .num_channels = 4,
.int_vref_mv = 2500,
},
 };
 
-
 static int ad5686_probe(struct spi_device *spi)
 {
struct ad5686_state *st;
@@ -353,8 +358,8 @@ static int ad5686_probe(struct spi_device *spi)
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->info = _info;
indio_dev->modes = INDIO_DIRECT_MODE;
-   indio_dev->channels = st->chip_info->channel;
-   indio_dev->num_channels = AD5686_DAC_CHANNELS;
+   indio_dev->channels = st->chip_info->channels;
+   indio_dev->num_channels = st->chip_info->num_channels;
 
r

[PATCH v3 1/4] adp5061: New driver for ADP5061 I2C battery charger

2018-04-11 Thread Stefan Popa
This patch adds basic support for Analog Devices I2C programmable linear
battery charger.

With this driver, some parameters can be read and configured such as:
* trickle charge current level (PRECHARGE_CURRENT)
* trickle charge voltage threshold (VOLTAGE_MIN)
* weak charge threshold (VOLTAGE_AVG)
* constant current (CONSTANT_CHARGE_CURRENT)
* constant charge voltage limit (CONSTANT_CHARGE_VOLTAGE_MAX)
* battery full (CAPACITY_LEVEL)
* input current limit (INPUT_CURRENT_LIMIT)
* charger status (STATUS)
* battery status (CAPACITY_LEVEL)
* termination current (CHARGE_TERM_CURRENT)

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/ADP5061.pdf

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
- Fixed typo in Kconfig file: build -> built.
Changes in v3:
- Described the commit message parameters with bindings to
  power-supply properties.
 MAINTAINERS|   7 +
 drivers/power/supply/Kconfig   |  11 +
 drivers/power/supply/Makefile  |   1 +
 drivers/power/supply/adp5061.c | 745 +
 4 files changed, 764 insertions(+)
 create mode 100644 drivers/power/supply/adp5061.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 3bdc260..60cd6db 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -797,6 +797,13 @@ L: linux-me...@vger.kernel.org
 S: Maintained
 F: drivers/media/i2c/ad9389b*
 
+ANALOG DEVICES INC ADP5061 DRIVER
+M:     Stefan Popa <stefan.p...@analog.com>
+L: linux...@vger.kernel.org
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/power/supply/adp5061.c
+
 ANALOG DEVICES INC ADV7180 DRIVER
 M: Lars-Peter Clausen <l...@metafoo.de>
 L: linux-me...@vger.kernel.org
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 428b426..4cc9aa9 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -75,6 +75,17 @@ config BATTERY_88PM860X
help
  Say Y here to enable battery monitor for Marvell 88PM860x chip.
 
+config CHARGER_ADP5061
+   tristate "ADP5061 battery charger driver"
+   depends on I2C
+   select REGMAP_I2C
+   help
+ Say Y here to enable support for the ADP5061 standalone battery
+ charger.
+
+ This driver can be built as a module. If so, the module will be
+ called adp5061.
+
 config BATTERY_ACT8945A
tristate "Active-semi ACT8945A charger driver"
depends on MFD_ACT8945A || COMPILE_TEST
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index e83aa84..71b1398 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_WM8350_POWER)+= wm8350_power.o
 obj-$(CONFIG_TEST_POWER)   += test_power.o
 
 obj-$(CONFIG_BATTERY_88PM860X) += 88pm860x_battery.o
+obj-$(CONFIG_CHARGER_ADP5061)  += adp5061.o
 obj-$(CONFIG_BATTERY_ACT8945A) += act8945a_charger.o
 obj-$(CONFIG_BATTERY_AXP20X)   += axp20x_battery.o
 obj-$(CONFIG_CHARGER_AXP20X)   += axp20x_ac_power.o
diff --git a/drivers/power/supply/adp5061.c b/drivers/power/supply/adp5061.c
new file mode 100644
index 000..c00a02e
--- /dev/null
+++ b/drivers/power/supply/adp5061.c
@@ -0,0 +1,745 @@
+/*
+ * ADP5061 I2C Programmable Linear Battery Charger
+ *
+ * Copyright 2018 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* ADP5061 registers definition */
+#define ADP5061_ID 0x00
+#define ADP5061_REV0x01
+#define ADP5061_VINX_SET   0x02
+#define ADP5061_TERM_SET   0x03
+#define ADP5061_CHG_CURR   0x04
+#define ADP5061_VOLTAGE_TH 0x05
+#define ADP5061_TIMER_SET  0x06
+#define ADP5061_FUNC_SET_1 0x07
+#define ADP5061_FUNC_SET_2 0x08
+#define ADP5061_INT_EN 0x09
+#define ADP5061_INT_ACT0x0A
+#define ADP5061_CHG_STATUS_1   0x0B
+#define ADP5061_CHG_STATUS_2   0x0C
+#define ADP5061_FAULT  0x0D
+#define ADP5061_BATTERY_SHORT  0x10
+#define ADP5061_IEND   0x11
+
+/* ADP5061_VINX_SET */
+#define ADP5061_VINX_SET_ILIM_MSK  GENMASK(3, 0)
+#define ADP5061_VINX_SET_ILIM_MODE(x)  (((x) & 0x0F) << 0)
+
+/* ADP5061_TERM_SET */
+#define ADP5061_TERM_SET_VTRM_MSK  GENMASK(7, 2)
+#define ADP5061_TERM_SET_VTRM_MODE(x)  (((x) & 0x3F) << 2)
+#define ADP5061_TERM_SET_CHG_VLIM_MSK  GENMASK(1, 0)
+#define ADP5061_TERM_SET_CHG_VLIM_MODE(x)  (((x) & 0x03) << 0)
+
+/* ADP5061_CHG_CURR */
+#define ADP5061_CHG_CURR_ICHG_MSK  GENMASK(6, 2)
+#define ADP5061_CHG_CURR_ICHG_MODE(x)  (((x) & 0x1F) &

[PATCH v3 2/4] dt-bindings:power:supply: Add docs for ADP5061 battery charger

2018-04-11 Thread Stefan Popa
Document adi,adp5061 properties.

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v3:
- Split devicetree bindings into a separate patch.

 .../devicetree/bindings/power/supply/adp5061.txt| 17 +
 MAINTAINERS |  1 +
 2 files changed, 18 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/power/supply/adp5061.txt

diff --git a/Documentation/devicetree/bindings/power/supply/adp5061.txt 
b/Documentation/devicetree/bindings/power/supply/adp5061.txt
new file mode 100644
index 000..7447446
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/adp5061.txt
@@ -0,0 +1,17 @@
+Analog Devices ADP5061 Programmable Linear Battery Charger Driver
+
+Required properties:
+  - compatible:should be "adi,adp5061"
+  - reg:   i2c address of the device
+
+The node for this driver must be a child node of a I2C controller, hence
+all mandatory properties described in
+Documentation/devicetree/bindings/i2c/i2c.txt
+must be specified.
+
+Example:
+
+   adp5061@14 {
+   compatible = "adi,adp5061";
+   reg = <0x14>;
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 60cd6db..a9ca73b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -802,6 +802,7 @@ M:  Stefan Popa <stefan.p...@analog.com>
 L: linux...@vger.kernel.org
 W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
+F: Documentation/devicetree/bindings/power/supply/adp5061.txt
 F: drivers/power/supply/adp5061.c
 
 ANALOG DEVICES INC ADV7180 DRIVER
-- 
2.7.4



[PATCH v3 3/4] adp5061: Add support for battery charging enable

2018-04-11 Thread Stefan Popa
This patch adds the option to enable/disable battery charging. This
option is not configurable via the power_supply properties, therefore,
access via sysfs was provided to examine and modify this attribute on the
fly.

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
- Fixed kbuild test error by changing the type of the
  charging_enabled_show() and charging_enabled_store() functions
  from int to ssize_t.
Changes in v3:
- Nothing changed, just to follow the patch set version.

 .../ABI/testing/sysfs-class-power-adp5061  | 10 
 MAINTAINERS|  1 +
 drivers/power/supply/adp5061.c | 63 ++
 3 files changed, 74 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-power-adp5061

diff --git a/Documentation/ABI/testing/sysfs-class-power-adp5061 
b/Documentation/ABI/testing/sysfs-class-power-adp5061
new file mode 100644
index 000..0d056aa
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-power-adp5061
@@ -0,0 +1,10 @@
+What: /sys/class/power_supply/adp5061/charging_enabled
+Description:
+   Enable/disable battery charging.
+
+   The ADP5061 charging function can be enabled by setting
+   this attribute to 1. See device datasheet for details.
+
+   Valid values:
+   - 1: enabled
+   - 0: disabled
diff --git a/MAINTAINERS b/MAINTAINERS
index a9ca73b..9271246 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -804,6 +804,7 @@ W:  http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: Documentation/devicetree/bindings/power/supply/adp5061.txt
 F: drivers/power/supply/adp5061.c
+F: Documentation/ABI/testing/sysfs-class-power-adp5061
 
 ANALOG DEVICES INC ADV7180 DRIVER
 M: Lars-Peter Clausen <l...@metafoo.de>
diff --git a/drivers/power/supply/adp5061.c b/drivers/power/supply/adp5061.c
index c00a02e..99871e6 100644
--- a/drivers/power/supply/adp5061.c
+++ b/drivers/power/supply/adp5061.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 
+
 /* ADP5061 registers definition */
 #define ADP5061_ID 0x00
 #define ADP5061_REV0x01
@@ -79,6 +80,10 @@
 #define ADP5061_IEND_IEND_MSK  GENMASK(7, 5)
 #define ADP5061_IEND_IEND_MODE(x)  (((x) & 0x07) << 5)
 
+/* ADP5061_FUNC_SET_1 */
+#define ADP5061_FUNC_SET_1_EN_CHG_MSK  BIT(0)
+#define ADP5061_FUNC_SET_1_EN_CHG_MODE(x)  (((x) & 0x01) << 0)
+
 #define ADP5061_NO_BATTERY 0x01
 #define ADP5061_ICHG_MAX   1300 // mA
 
@@ -692,11 +697,63 @@ static const struct power_supply_desc adp5061_desc = {
.num_properties = ARRAY_SIZE(adp5061_props),
 };
 
+static ssize_t charging_enabled_show(struct device *dev,
+struct device_attribute *attr,
+char *buf)
+{
+   struct power_supply *psy = dev_get_drvdata(dev);
+   struct adp5061_state *st = power_supply_get_drvdata(psy);
+   unsigned int regval;
+   int ret;
+
+   ret = regmap_read(st->regmap, ADP5061_FUNC_SET_1, );
+   if (ret < 0)
+   return ret;
+
+   regval &= ADP5061_FUNC_SET_1_EN_CHG_MSK;
+   return sprintf(buf, "%d\n", regval);
+}
+
+static ssize_t charging_enabled_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   struct power_supply *psy = dev_get_drvdata(dev);
+   struct adp5061_state *st = power_supply_get_drvdata(psy);
+   u8 chg_en;
+   int ret;
+
+   ret = kstrtou8(buf, 0, _en);
+   if (ret < 0)
+   return ret;
+
+   ret = regmap_update_bits(st->regmap, ADP5061_FUNC_SET_1,
+ADP5061_FUNC_SET_1_EN_CHG_MSK,
+ADP5061_FUNC_SET_1_EN_CHG_MODE(!!chg_en));
+
+   if (ret < 0)
+   return ret;
+
+   return count;
+}
+
+static DEVICE_ATTR_RW(charging_enabled);
+
+static struct attribute *adp5061_attributes[] = {
+   _attr_charging_enabled.attr,
+   NULL
+};
+
+static const struct attribute_group adp5061_attr_group = {
+   .attrs = adp5061_attributes,
+};
+
 static int adp5061_probe(struct i2c_client *client,
 const struct i2c_device_id *id)
 {
struct power_supply_config psy_cfg = {};
struct adp5061_state *st;
+   int ret;
 
st = devm_kzalloc(>dev, sizeof(*st), GFP_KERNEL);
if (!st)
@@ -722,6 +779,12 @@ static int adp5061_probe(struct i2c_client *client,
return PTR_ERR(st->psy);
}
 
+   ret = sysfs_create_group(>psy->dev.kobj, _attr_group);
+   if (ret < 0) {
+   dev_err(>dev, "failed to create sysfs group\n");
+   return ret;
+   }
+
return 0;
 }
 
-- 
2.7.4



[PATCH v3 4/4] adp5061: Add support for charging voltage limit enable

2018-04-11 Thread Stefan Popa
This patch adds the option to activate/deactivate the charging voltage
limit. If activated, the charger prevents charging until the battery
voltage drops below the VCHG_VLIM threshold.

This option is not configurable via the power_supply properties,
therefore, access via sysfs was provided to examine and modify this
attribute on the fly.

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
Changes in v2:
- Fixed the kbuild test error by changing the type of the
  charging_vlim_enabled_show() and charging_vlim_enabled_store()
  functions from int to ssize_t.
Changes in v3:
- Nothing changed, just to follow the patch set version.

 .../ABI/testing/sysfs-class-power-adp5061  | 13 ++
 drivers/power/supply/adp5061.c | 46 ++
 2 files changed, 59 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-power-adp5061 
b/Documentation/ABI/testing/sysfs-class-power-adp5061
index 0d056aa..25064c1 100644
--- a/Documentation/ABI/testing/sysfs-class-power-adp5061
+++ b/Documentation/ABI/testing/sysfs-class-power-adp5061
@@ -8,3 +8,16 @@ Description:
Valid values:
- 1: enabled
- 0: disabled
+
+What: /sys/class/power_supply/adp5061/charging_vlim_enabled
+Description:
+   Enable/disable charging voltage limit
+
+   The ADP5061 charging voltage limit can be enabled by setting
+   this attribute to 1. When enabled, the charger prevents charging
+   until the battery voltage drops bellow the VCHG_VLIM threshold.
+   See device datasheet for details.
+
+   Valid values:
+   - 1: enabled
+   - 0: disabled
diff --git a/drivers/power/supply/adp5061.c b/drivers/power/supply/adp5061.c
index 99871e6..9716059 100644
--- a/drivers/power/supply/adp5061.c
+++ b/drivers/power/supply/adp5061.c
@@ -84,6 +84,10 @@
 #define ADP5061_FUNC_SET_1_EN_CHG_MSK  BIT(0)
 #define ADP5061_FUNC_SET_1_EN_CHG_MODE(x)  (((x) & 0x01) << 0)
 
+/* ADP5061_FUNC_SET_2 */
+#define ADP5061_FUNC_SET_2_EN_CHG_VLIM_MSK BIT(5)
+#define ADP5061_FUNC_SET_2_EN_CHG_VLIM_MODE(x) (((x) & 0x01) << 5)
+
 #define ADP5061_NO_BATTERY 0x01
 #define ADP5061_ICHG_MAX   1300 // mA
 
@@ -737,10 +741,52 @@ static ssize_t charging_enabled_store(struct device *dev,
return count;
 }
 
+static ssize_t charging_vlim_enabled_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct power_supply *psy = dev_get_drvdata(dev);
+   struct adp5061_state *st = power_supply_get_drvdata(psy);
+   unsigned int regval;
+   int ret;
+
+   ret = regmap_read(st->regmap, ADP5061_FUNC_SET_2, );
+   if (ret < 0)
+   return ret;
+
+   regval = (regval & ADP5061_FUNC_SET_2_EN_CHG_VLIM_MSK) >> 5;
+   return sprintf(buf, "%d\n", regval);
+}
+
+static ssize_t charging_vlim_enabled_store(struct device *dev,
+  struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   struct power_supply *psy = dev_get_drvdata(dev);
+   struct adp5061_state *st = power_supply_get_drvdata(psy);
+   u8 chg_vlim_en;
+   int ret;
+
+   ret = kstrtou8(buf, 0, _vlim_en);
+   if (ret < 0)
+   return ret;
+
+   ret = regmap_update_bits(st->regmap, ADP5061_FUNC_SET_2,
+   ADP5061_FUNC_SET_2_EN_CHG_VLIM_MSK,
+   ADP5061_FUNC_SET_2_EN_CHG_VLIM_MODE(!!chg_vlim_en));
+
+   if (ret < 0)
+   return ret;
+
+   return count;
+}
+
 static DEVICE_ATTR_RW(charging_enabled);
+static DEVICE_ATTR_RW(charging_vlim_enabled);
 
 static struct attribute *adp5061_attributes[] = {
_attr_charging_enabled.attr,
+   _attr_charging_vlim_enabled.attr,
NULL
 };
 
-- 
2.7.4



[PATCH 2/3] iio:dac:ad5686: Add AD5672R/AD5676/AD5676R/AD5684R/AD5685R/AD5686R support

2018-03-30 Thread Stefan Popa
The AD5684R/AD5685R/AD5686R are a family of 4 channel DACs with 12-bit,
14-bit and 16-bit precision respectively. The devices come either with a
built-in reference or no built-in reference.

The AD5672R/AD5676/AD5676R are similar, except that they have 8 channels
instead of 4.

Datasheets:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5672R_5676R.pdf
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5686R_5685R_5684R.pdf

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
 drivers/iio/dac/ad5686.c | 97 
 1 file changed, 74 insertions(+), 23 deletions(-)

diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index f7f975c..5fb0179 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -19,8 +19,6 @@
 #include 
 #include 
 
-#define AD5686_DAC_CHANNELS4
-
 #define AD5686_ADDR(x) ((x) << 16)
 #define AD5686_CMD(x)  ((x) << 20)
 
@@ -46,12 +44,14 @@
 /**
  * struct ad5686_chip_info - chip specific information
  * @int_vref_mv:   AD5620/40/60: the internal reference voltage
+ * @num_channels:  number of channels
  * @channel:   channel specification
 */
 
 struct ad5686_chip_info {
u16 int_vref_mv;
-   struct iio_chan_specchannel[AD5686_DAC_CHANNELS];
+   unsigned intnum_channels;
+   struct iio_chan_spec*channels;
 };
 
 /**
@@ -88,9 +88,14 @@ struct ad5686_state {
  */
 
 enum ad5686_supported_device_ids {
+   ID_AD5672R,
+   ID_AD5676,
+   ID_AD5676R,
ID_AD5684,
-   ID_AD5685,
+   ID_AD5684R,
+   ID_AD5685R,
ID_AD5686,
+   ID_AD5686R
 };
 static int ad5686_spi_write(struct ad5686_state *st,
 u8 cmd, u8 addr, u16 val, u8 shift)
@@ -269,14 +274,14 @@ static const struct iio_chan_spec_ext_info 
ad5686_ext_info[] = {
{ },
 };
 
-#define AD5868_CHANNEL(chan, bits, _shift) {   \
+#define AD5868_CHANNEL(chan, addr, bits, _shift) { \
.type = IIO_VOLTAGE,\
.indexed = 1,   \
.output = 1,\
.channel = chan,\
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\
-   .address = AD5686_ADDR_DAC(chan),   \
+   .address = addr,\
.scan_type = {  \
.sign = 'u',\
.realbits = (bits), \
@@ -286,31 +291,72 @@ static const struct iio_chan_spec_ext_info 
ad5686_ext_info[] = {
.ext_info = ad5686_ext_info,\
 }
 
+#define DECLARE_AD5686_CHANNELS(name, bits, _shift)\
+static struct iio_chan_spec name[] = { \
+   AD5868_CHANNEL(0, 1, bits, _shift), \
+   AD5868_CHANNEL(1, 2, bits, _shift), \
+   AD5868_CHANNEL(2, 4, bits, _shift), \
+   AD5868_CHANNEL(3, 8, bits, _shift), \
+}
+
+#define DECLARE_AD5676_CHANNELS(name, bits, _shift)\
+static struct iio_chan_spec name[] = { \
+   AD5868_CHANNEL(0, 0, bits, _shift), \
+   AD5868_CHANNEL(1, 1, bits, _shift), \
+   AD5868_CHANNEL(2, 2, bits, _shift), \
+   AD5868_CHANNEL(3, 3, bits, _shift), \
+   AD5868_CHANNEL(4, 4, bits, _shift), \
+   AD5868_CHANNEL(5, 5, bits, _shift), \
+   AD5868_CHANNEL(6, 6, bits, _shift), \
+   AD5868_CHANNEL(7, 7, bits, _shift), \
+}
+
+DECLARE_AD5676_CHANNELS(ad5672_channels, 12, 4);
+DECLARE_AD5676_CHANNELS(ad5676_channels, 16, 0);
+DECLARE_AD5686_CHANNELS(ad5684_channels, 12, 4);
+DECLARE_AD5686_CHANNELS(ad5685r_channels, 14, 2);
+DECLARE_AD5686_CHANNELS(ad5686_channels, 16, 0);
+
 static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
+   [ID_AD5672R] = {
+   .channels = ad5672_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 8,
+   },
+   [ID_AD5676] = {
+   .channels = ad5676_channels,
+   .num_channels = 8,
+   },
+   [ID_AD5676R] = {
+   .channels = ad5676_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 8,
+   },
[ID_AD5684] = {
-   .channel[0] = AD5868_CHANNEL(0, 12, 4),
-   .channel[1] = AD586

[PATCH 1/3] iio:dac:ad5686: Style fixes no functional changes

2018-03-30 Thread Stefan Popa
This patch fixes some indentation issues and does not modify the
functionality of the driver.

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
 drivers/iio/dac/ad5686.c | 25 ++---
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 20254df..f7f975c 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -24,7 +24,7 @@
 #define AD5686_ADDR(x) ((x) << 16)
 #define AD5686_CMD(x)  ((x) << 20)
 
-#define AD5686_ADDR_DAC(chan)  (0x1 << (chan))
+#define AD5686_ADDR_DAC(chan)  (0x1 << (chan))
 #define AD5686_ADDR_ALL_DAC0xF
 
 #define AD5686_CMD_NOOP0x0
@@ -137,7 +137,7 @@ static const char * const ad5686_powerdown_modes[] = {
 };
 
 static int ad5686_get_powerdown_mode(struct iio_dev *indio_dev,
-   const struct iio_chan_spec *chan)
+const struct iio_chan_spec *chan)
 {
struct ad5686_state *st = iio_priv(indio_dev);
 
@@ -145,7 +145,8 @@ static int ad5686_get_powerdown_mode(struct iio_dev 
*indio_dev,
 }
 
 static int ad5686_set_powerdown_mode(struct iio_dev *indio_dev,
-   const struct iio_chan_spec *chan, unsigned int mode)
+const struct iio_chan_spec *chan,
+unsigned int mode)
 {
struct ad5686_state *st = iio_priv(indio_dev);
 
@@ -163,17 +164,19 @@ static const struct iio_enum ad5686_powerdown_mode_enum = 
{
 };
 
 static ssize_t ad5686_read_dac_powerdown(struct iio_dev *indio_dev,
-   uintptr_t private, const struct iio_chan_spec *chan, char *buf)
+   uintptr_t private, const struct iio_chan_spec *chan, char *buf)
 {
struct ad5686_state *st = iio_priv(indio_dev);
 
return sprintf(buf, "%d\n", !!(st->pwr_down_mask &
-   (0x3 << (chan->channel * 2;
+  (0x3 << (chan->channel * 2;
 }
 
 static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev,
-uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
-size_t len)
+ uintptr_t private,
+ const struct iio_chan_spec *chan,
+ const char *buf,
+ size_t len)
 {
bool readin;
int ret;
@@ -221,10 +224,10 @@ static int ad5686_read_raw(struct iio_dev *indio_dev,
 }
 
 static int ad5686_write_raw(struct iio_dev *indio_dev,
-  struct iio_chan_spec const *chan,
-  int val,
-  int val2,
-  long mask)
+   struct iio_chan_spec const *chan,
+   int val,
+   int val2,
+   long mask)
 {
struct ad5686_state *st = iio_priv(indio_dev);
int ret;
-- 
2.7.4



[PATCH 3/3] iio:dac:ad5686: Add AD5671R/75R/94/94R/95R/96/96R support

2018-03-30 Thread Stefan Popa
The AD5694/AD5694R/AD5695R/AD5696/AD5696R are a family of 4 channel DAC
s with 12-bit, 14-bit and 16-bit precision respectively. The devices have
either no built-in reference, or built-in 2.5V reference.

The AD5671R/AD5675R are similar, except that they have 8 instead of 4
channels.

These devices are similar to AD5672R/AD5676/AD5676R and
AD5684/AD5684R/AD5684/AD5685R/AD5686/AD5686R, except that they use i2c
instead of spi. In order to add support in the previously existing driver,
three modules were created. One baseline module that has all the
chip-logic and then one module for SPI and one for I2C.

Datasheets:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5671R_5675R.pdf
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5696R_5695R_5694R.pdf

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
 MAINTAINERS  |   8 ++
 drivers/iio/dac/Kconfig  |  27 --
 drivers/iio/dac/ad5686-spi.c |  93 ++
 drivers/iio/dac/ad5686.c | 222 +--
 drivers/iio/dac/ad5686.h | 114 ++
 drivers/iio/dac/ad5696-i2c.c |  98 +++
 6 files changed, 400 insertions(+), 162 deletions(-)
 create mode 100644 drivers/iio/dac/ad5686-spi.c
 create mode 100644 drivers/iio/dac/ad5686.h
 create mode 100644 drivers/iio/dac/ad5696-i2c.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 473ac00..002cb01 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -791,6 +791,14 @@ M: Michael Hanselmann <linux-ker...@hansmi.ch>
 S: Supported
 F: drivers/macintosh/ams/
 
+ANALOG DEVICES INC AD5686 DRIVER
+M: Stefan Popa <stefan.p...@analog.com>
+L: linux...@vger.kernel.org
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/dac/ad5686*
+F: drivers/iio/dac/ad5696*
+
 ANALOG DEVICES INC AD9389B DRIVER
 M: Hans Verkuil <hans.verk...@cisco.com>
 L: linux-me...@vger.kernel.org
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 965d5c0..dab0b8a 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -131,15 +131,30 @@ config LTC2632
  module will be called ltc2632.
 
 config AD5686
-   tristate "Analog Devices AD5686R/AD5685R/AD5684R DAC SPI driver"
+   tristate
+
+config AD5686_SPI
+   tristate "Analog Devices AD5686 and similar multi-channel DACs (SPI)"
depends on SPI
+   select AD5686
help
- Say yes here to build support for Analog Devices AD5686R, AD5685R,
- AD5684R, AD5791 Voltage Output Digital to
- Analog Converter.
+   Say yes here to build support for Analog Devices AD5672R, AD5676,
+   AD5676R, AD5684, AD5684R, AD5684R, AD5685R, AD5686, AD5686R.
+   Voltage Output Digital to Analog Converter.
 
- To compile this driver as a module, choose M here: the
- module will be called ad5686.
+   To compile this driver as a module, choose M here: the
+   module will be called ad5686.
+
+config AD5696_I2C
+   tristate "Analog Devices AD5696 and similar multi-channel DACs (I2C)"
+   depends on I2C
+   select AD5686
+   help
+   Say yes here to build support for Analog Devices AD5671R, AD5675R,
+   AD5694, AD5694R, AD5695R, AD5696, AD5696R Voltage Output Digital to
+   Analog Converter.
+   To compile this driver as a module, choose M here: the module will be
+   called ad5696.
 
 config AD5755
tristate "Analog Devices AD5755/AD5755-1/AD5757/AD5735/AD5737 DAC 
driver"
diff --git a/drivers/iio/dac/ad5686-spi.c b/drivers/iio/dac/ad5686-spi.c
new file mode 100644
index 000..d68579b
--- /dev/null
+++ b/drivers/iio/dac/ad5686-spi.c
@@ -0,0 +1,93 @@
+/*
+ * AD5672R, AD5676, AD5676R, AD5684, AD5684R, AD5684R, AD5685R, AD5686, AD5686R
+ * Digital to analog converters driver
+ *
+ * Copyright 2018 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include "ad5686.h"
+
+#include 
+#include 
+
+static int ad5686_spi_write(struct ad5686_state *st,
+   u8 cmd, u8 addr, u16 val)
+{
+   struct spi_device *spi = to_spi_device(st->dev);
+
+   st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
+ AD5686_ADDR(addr) |
+ val);
+
+   return spi_write(spi, >data[0].d8[1], 3);
+}
+
+static int ad5686_spi_read(struct ad5686_state *st, u8 addr)
+{
+   struct spi_transfer t[] = {
+   {
+   .tx_buf = >data[0].d8[1],
+   .len = 3,
+   .cs_change = 1,
+   }, {
+   .tx_buf = >data[1].d8[1],
+   .rx_buf = >data[2].d8[1],
+   .len = 3,
+   },
+   };
+   struct spi_device *spi = to_spi_device(st->dev);

[PATCH 3/3] adp5061: Add support for charging voltage limit enable

2018-04-04 Thread Stefan Popa
This patch adds the option to activate/deactivate the charging voltage
limit. If activated, the charger prevents charging until the battery
voltage drops below the VCHG_VLIM threshold.

This option is not configurable via the power_supply properties,
therefore, access via sysfs was provided to examine and modify this
attribute on the fly.

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
 .../ABI/testing/sysfs-class-power-adp5061  | 13 ++
 drivers/power/supply/adp5061.c | 46 ++
 2 files changed, 59 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-power-adp5061 
b/Documentation/ABI/testing/sysfs-class-power-adp5061
index 0d056aa..25064c1 100644
--- a/Documentation/ABI/testing/sysfs-class-power-adp5061
+++ b/Documentation/ABI/testing/sysfs-class-power-adp5061
@@ -8,3 +8,16 @@ Description:
Valid values:
- 1: enabled
- 0: disabled
+
+What: /sys/class/power_supply/adp5061/charging_vlim_enabled
+Description:
+   Enable/disable charging voltage limit
+
+   The ADP5061 charging voltage limit can be enabled by setting
+   this attribute to 1. When enabled, the charger prevents charging
+   until the battery voltage drops bellow the VCHG_VLIM threshold.
+   See device datasheet for details.
+
+   Valid values:
+   - 1: enabled
+   - 0: disabled
diff --git a/drivers/power/supply/adp5061.c b/drivers/power/supply/adp5061.c
index 7cd2e67..5931e45 100644
--- a/drivers/power/supply/adp5061.c
+++ b/drivers/power/supply/adp5061.c
@@ -83,6 +83,10 @@
 #define ADP5061_FUNC_SET_1_EN_CHG_MSK  BIT(0)
 #define ADP5061_FUNC_SET_1_EN_CHG_MODE(x)  (((x) & 0x01) << 0)
 
+/* ADP5061_FUNC_SET_2 */
+#define ADP5061_FUNC_SET_2_EN_CHG_VLIM_MSK BIT(5)
+#define ADP5061_FUNC_SET_2_EN_CHG_VLIM_MODE(x) (((x) & 0x01) << 5)
+
 #define ADP5061_NO_BATTERY 0x01
 #define ADP5061_ICHG_MAX   1300 // mA
 
@@ -736,10 +740,52 @@ static int charging_enabled_store(struct device *dev,
return count;
 }
 
+static int charging_vlim_enabled_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct power_supply *psy = dev_get_drvdata(dev);
+   struct adp5061_state *st = power_supply_get_drvdata(psy);
+   unsigned int regval;
+   int ret;
+
+   ret = regmap_read(st->regmap, ADP5061_FUNC_SET_2, );
+   if (ret < 0)
+   return ret;
+
+   regval = (regval & ADP5061_FUNC_SET_2_EN_CHG_VLIM_MSK) >> 5;
+   return sprintf(buf, "%d\n", regval);
+}
+
+static int charging_vlim_enabled_store(struct device *dev,
+  struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   struct power_supply *psy = dev_get_drvdata(dev);
+   struct adp5061_state *st = power_supply_get_drvdata(psy);
+   u8 chg_vlim_en;
+   int ret;
+
+   ret = kstrtou8(buf, 0, _vlim_en);
+   if (ret < 0)
+   return ret;
+
+   ret = regmap_update_bits(st->regmap, ADP5061_FUNC_SET_2,
+   ADP5061_FUNC_SET_2_EN_CHG_VLIM_MSK,
+   ADP5061_FUNC_SET_2_EN_CHG_VLIM_MODE(!!chg_vlim_en));
+
+   if (ret < 0)
+   return ret;
+
+   return count;
+}
+
 static DEVICE_ATTR_RW(charging_enabled);
+static DEVICE_ATTR_RW(charging_vlim_enabled);
 
 static struct attribute *adp5061_attributes[] = {
_attr_charging_enabled.attr,
+   _attr_charging_vlim_enabled.attr,
NULL
 };
 
-- 
2.7.4



[PATCH 1/3] adp5061: New driver for ADP5061 I2C battery charger

2018-04-04 Thread Stefan Popa
This patch adds basic support for Analog Devices I2C programmable linear
battery charger.

With this driver, some parameters can be read and configured such as:
* trickle charge current level
* trickle charge voltage threshold
* weak charge threshold
* constant current
* constant charge voltage limit
* battery full
* input current limit
* charger status
* battery status
* termination current

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/ADP5061.pdf

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
 .../devicetree/bindings/power/supply/adp5061.txt   |  17 +
 MAINTAINERS|   8 +
 drivers/power/supply/Kconfig   |  11 +
 drivers/power/supply/Makefile  |   1 +
 drivers/power/supply/adp5061.c | 745 +
 5 files changed, 782 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/power/supply/adp5061.txt
 create mode 100644 drivers/power/supply/adp5061.c

diff --git a/Documentation/devicetree/bindings/power/supply/adp5061.txt 
b/Documentation/devicetree/bindings/power/supply/adp5061.txt
new file mode 100644
index 000..7447446
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/adp5061.txt
@@ -0,0 +1,17 @@
+Analog Devices ADP5061 Programmable Linear Battery Charger Driver
+
+Required properties:
+  - compatible:should be "adi,adp5061"
+  - reg:   i2c address of the device
+
+The node for this driver must be a child node of a I2C controller, hence
+all mandatory properties described in
+Documentation/devicetree/bindings/i2c/i2c.txt
+must be specified.
+
+Example:
+
+   adp5061@14 {
+   compatible = "adi,adp5061";
+   reg = <0x14>;
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 3bdc260..a9ca73b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -797,6 +797,14 @@ L: linux-me...@vger.kernel.org
 S: Maintained
 F: drivers/media/i2c/ad9389b*
 
+ANALOG DEVICES INC ADP5061 DRIVER
+M: Stefan Popa <stefan.p...@analog.com>
+L: linux...@vger.kernel.org
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: Documentation/devicetree/bindings/power/supply/adp5061.txt
+F: drivers/power/supply/adp5061.c
+
 ANALOG DEVICES INC ADV7180 DRIVER
 M: Lars-Peter Clausen <l...@metafoo.de>
 L: linux-me...@vger.kernel.org
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 428b426..761cc52 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -75,6 +75,17 @@ config BATTERY_88PM860X
help
  Say Y here to enable battery monitor for Marvell 88PM860x chip.
 
+config CHARGER_ADP5061
+   tristate "ADP5061 battery charger driver"
+   depends on I2C
+   select REGMAP_I2C
+   help
+ Say Y here to enable support for the ADP5061 standalone battery
+ charger.
+
+ This driver can be build as a module. If so, the module will be
+ called adp5061.
+
 config BATTERY_ACT8945A
tristate "Active-semi ACT8945A charger driver"
depends on MFD_ACT8945A || COMPILE_TEST
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index e83aa84..71b1398 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_WM8350_POWER)+= wm8350_power.o
 obj-$(CONFIG_TEST_POWER)   += test_power.o
 
 obj-$(CONFIG_BATTERY_88PM860X) += 88pm860x_battery.o
+obj-$(CONFIG_CHARGER_ADP5061)  += adp5061.o
 obj-$(CONFIG_BATTERY_ACT8945A) += act8945a_charger.o
 obj-$(CONFIG_BATTERY_AXP20X)   += axp20x_battery.o
 obj-$(CONFIG_CHARGER_AXP20X)   += axp20x_ac_power.o
diff --git a/drivers/power/supply/adp5061.c b/drivers/power/supply/adp5061.c
new file mode 100644
index 000..c00a02e
--- /dev/null
+++ b/drivers/power/supply/adp5061.c
@@ -0,0 +1,745 @@
+/*
+ * ADP5061 I2C Programmable Linear Battery Charger
+ *
+ * Copyright 2018 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* ADP5061 registers definition */
+#define ADP5061_ID 0x00
+#define ADP5061_REV0x01
+#define ADP5061_VINX_SET   0x02
+#define ADP5061_TERM_SET   0x03
+#define ADP5061_CHG_CURR   0x04
+#define ADP5061_VOLTAGE_TH 0x05
+#define ADP5061_TIMER_SET  0x06
+#define ADP5061_FUNC_SET_1 0x07
+#define ADP5061_FUNC_SET_2 0x08
+#define ADP5061_INT_EN 0x09
+#define ADP5061_INT_ACT0x0A
+#define ADP5061_CHG_STATUS_1   0x0B
+#define ADP5061_CHG_STATUS_2   0x0C
+#define ADP5061_FAULT  0x0D
+#define ADP5061_BATTERY_SHORT  0x10
+#d

[PATCH 2/3] adp5061: Add support for battery charging enable

2018-04-04 Thread Stefan Popa
This patch adds the option to enable/disable battery charging. This
option is not configurable via the power_supply properties, therefore,
access via sysfs was provided to examine and modify this attribute on the
fly.

Signed-off-by: Stefan Popa <stefan.p...@analog.com>
---
 .../ABI/testing/sysfs-class-power-adp5061  | 10 
 MAINTAINERS|  1 +
 drivers/power/supply/adp5061.c | 62 ++
 3 files changed, 73 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-power-adp5061

diff --git a/Documentation/ABI/testing/sysfs-class-power-adp5061 
b/Documentation/ABI/testing/sysfs-class-power-adp5061
new file mode 100644
index 000..0d056aa
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-power-adp5061
@@ -0,0 +1,10 @@
+What: /sys/class/power_supply/adp5061/charging_enabled
+Description:
+   Enable/disable battery charging.
+
+   The ADP5061 charging function can be enabled by setting
+   this attribute to 1. See device datasheet for details.
+
+   Valid values:
+   - 1: enabled
+   - 0: disabled
diff --git a/MAINTAINERS b/MAINTAINERS
index a9ca73b..9271246 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -804,6 +804,7 @@ W:  http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: Documentation/devicetree/bindings/power/supply/adp5061.txt
 F: drivers/power/supply/adp5061.c
+F: Documentation/ABI/testing/sysfs-class-power-adp5061
 
 ANALOG DEVICES INC ADV7180 DRIVER
 M: Lars-Peter Clausen <l...@metafoo.de>
diff --git a/drivers/power/supply/adp5061.c b/drivers/power/supply/adp5061.c
index c00a02e..7cd2e67 100644
--- a/drivers/power/supply/adp5061.c
+++ b/drivers/power/supply/adp5061.c
@@ -79,6 +79,10 @@
 #define ADP5061_IEND_IEND_MSK  GENMASK(7, 5)
 #define ADP5061_IEND_IEND_MODE(x)  (((x) & 0x07) << 5)
 
+/* ADP5061_FUNC_SET_1 */
+#define ADP5061_FUNC_SET_1_EN_CHG_MSK  BIT(0)
+#define ADP5061_FUNC_SET_1_EN_CHG_MODE(x)  (((x) & 0x01) << 0)
+
 #define ADP5061_NO_BATTERY 0x01
 #define ADP5061_ICHG_MAX   1300 // mA
 
@@ -692,11 +696,63 @@ static const struct power_supply_desc adp5061_desc = {
.num_properties = ARRAY_SIZE(adp5061_props),
 };
 
+static int charging_enabled_show(struct device *dev,
+struct device_attribute *attr,
+char *buf)
+{
+   struct power_supply *psy = dev_get_drvdata(dev);
+   struct adp5061_state *st = power_supply_get_drvdata(psy);
+   unsigned int regval;
+   int ret;
+
+   ret = regmap_read(st->regmap, ADP5061_FUNC_SET_1, );
+   if (ret < 0)
+   return ret;
+
+   regval &= ADP5061_FUNC_SET_1_EN_CHG_MSK;
+   return sprintf(buf, "%d\n", regval);
+}
+
+static int charging_enabled_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   struct power_supply *psy = dev_get_drvdata(dev);
+   struct adp5061_state *st = power_supply_get_drvdata(psy);
+   u8 chg_en;
+   int ret;
+
+   ret = kstrtou8(buf, 0, _en);
+   if (ret < 0)
+   return ret;
+
+   ret = regmap_update_bits(st->regmap, ADP5061_FUNC_SET_1,
+ADP5061_FUNC_SET_1_EN_CHG_MSK,
+ADP5061_FUNC_SET_1_EN_CHG_MODE(!!chg_en));
+
+   if (ret < 0)
+   return ret;
+
+   return count;
+}
+
+static DEVICE_ATTR_RW(charging_enabled);
+
+static struct attribute *adp5061_attributes[] = {
+   _attr_charging_enabled.attr,
+   NULL
+};
+
+static const struct attribute_group adp5061_attr_group = {
+   .attrs = adp5061_attributes,
+};
+
 static int adp5061_probe(struct i2c_client *client,
 const struct i2c_device_id *id)
 {
struct power_supply_config psy_cfg = {};
struct adp5061_state *st;
+   int ret;
 
st = devm_kzalloc(>dev, sizeof(*st), GFP_KERNEL);
if (!st)
@@ -722,6 +778,12 @@ static int adp5061_probe(struct i2c_client *client,
return PTR_ERR(st->psy);
}
 
+   ret = sysfs_create_group(>psy->dev.kobj, _attr_group);
+   if (ret < 0) {
+   dev_err(>dev, "failed to create sysfs group\n");
+   return ret;
+   }
+
return 0;
 }
 
-- 
2.7.4



[PATCH v4 2/2] dt-bindings: iio: dac: Add docs for AD5758 DAC

2018-06-29 Thread Stefan Popa
Signed-off-by: Stefan Popa 
---
Changes in v4:
- Nothing changed, just to follow the patch set version.
Changes in v3:
- AD5758 can be both a current and voltage output DAC. The
  decision is made based on the DT and the channel type is set
  during probe.
- range was replaced by range-microvolt and range-microamp
- dc-dc-mode, range-microvolt and range-microamp are required
  properties.
- Introduced a slew-time-us property from which slew rate clock
  and slew rate step are calculated using a best match algorithm.
- Added units in the name of the properties.
- Offered more explanation for the various modes of operation.

Changes in v2:
- Nothing changed, just to follow the patch set version.

 .../devicetree/bindings/iio/dac/ad5758.txt | 73 ++
 MAINTAINERS|  1 +
 2 files changed, 74 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/dac/ad5758.txt

diff --git a/Documentation/devicetree/bindings/iio/dac/ad5758.txt 
b/Documentation/devicetree/bindings/iio/dac/ad5758.txt
new file mode 100644
index 000..797df9b
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/ad5758.txt
@@ -0,0 +1,73 @@
+Analog Devices AD5758 DAC device driver
+
+Required properties for the AD5758:
+   - compatible: Must be "adi,ad5758"
+   - reg: SPI chip select number for the device
+   - spi-max-frequency: Max SPI frequency to use (< 5000)
+   - spi-cpha: is the only mode that is supported
+
+Required properties:
+
+ - adi,dc-dc-mode: Mode of operation of the dc-to-dc converter
+  Dynamic Power Control (DPC)
+  In this mode, the AD5758 circuitry senses the output voltage 
and
+  dynamically regulates the supply voltage, VDPC+, to meet 
compliance
+  requirements plus an optimized headroom voltage for the 
output buffer.
+
+  Programmable Power Control (PPC)
+  In this mode, the VDPC+ voltage is user-programmable to a 
fixed level
+  that needs to accommodate the maximum output load required.
+
+  The output of the DAC core is either converted to a current 
or voltage
+  output at the VIOUT pin. Only one mode can be enabled at any 
one time.
+
+  The following values are currently supported:
+   * 1: DPC current mode
+   * 2: DPC voltage mode
+   * 3: PPC current mode
+
+ Depending on the selected output mode (voltage or current) one of the two 
properties must
+ be present:
+
+ - adi,range-microvolt: Voltage output range
+   The array of voltage output ranges must contain two fields:
+   * <0 500>: 0 V to 5 V voltage range
+   * <0 1000>: 0 V to 10 V voltage range
+   * <(-500) 500>: ±5 V voltage range
+   * <(-1000) 1000>: ±10 V voltage range
+ - adi,range-microamp: Current output range
+   The array of current output ranges must contain two fields:
+   * <0 2>: 0 mA to 20 mA current range
+   * <0 24000>: 0 mA to 24 mA current range
+   * <4 24000>: 4 mA to 20 mA current range
+   * <(-2) 2>: ±20 mA current range
+   * <(-24000) 24000>: ±24 mA current range
+   * <(-1000) 22000>: −1 mA to +22 mA current range
+
+Optional properties:
+
+ - adi,dc-dc-ilim-microamp: The dc-to-dc converter current limit
+  The following values are currently supported [uA]:
+   * 15
+   * 20
+   * 25
+   * 30
+   * 35
+   * 40
+
+ - adi,slew-time-us: The time it takes for the output to reach the full scale 
[uS]
+The supported range is between 133us up to 1023984375us
+
+AD5758 Example:
+
+   ad5758@0 {
+   compatible = "adi,ad5758";
+   reg = <0>;
+   spi-max-frequency = <100>;
+   spi-cpha;
+
+   adi,dc-dc-mode = <2>;
+   adi,range-microvolt = <0 1000>;
+   adi,dc-dc-ilim-microamp = <20>;
+   adi,slew-time-us = <125000>;
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 12d102d..60b1028 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -802,6 +802,7 @@ L:  linux-...@vger.kernel.org
 W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/iio/dac/ad5758.c
+F: Documentation/devicetree/bindings/iio/dac/ad5758.txt
 
 ANALOG DEVICES INC AD5686 DRIVER
 M: Stefan Popa 
-- 
2.7.4



[PATCH v4 1/2] iio: dac: Add AD5758 support

2018-06-29 Thread Stefan Popa
The AD5758 is a single channel DAC with 16-bit precision which uses the
SPI interface that operates at clock rates up to 50MHz.

The output can be configured as voltage or current and is available on a
single terminal.

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/ad5758.pdf

Signed-off-by: Stefan Popa 
---
Changes in v4:
- fixed kbuild test robot warnings.
Changes in v3:
- AD5758 can be both a current and voltage output DAC. The
  decision is made based on the DT and the channel type is set
  during probe.
- dc-dc-mode, range-microvolt and range-microamp are required
  properties.
- Introduced a slew-time-us property from which slew rate clock
  and slew rate step are calculated using a best match algorithm.
- Dropped the union from ad5758_state struct.
- Introduced a IIO_CHAN_INFO_OFFSET case part of ad5758_read_raw().
- Added a TODO comment which specifies that CRC is not supported.
- Kept the includes in order and removed the unused ones.
- Removed unused macros and shortened the lengthy ones.
- Renamed AD5758_REG_WRITE to AD5758_WR_FLAG_MSK.
- Added an explanation for enum ad5758_output_range.
- Used bsearch() instead of ad5758_get_array_index().
- Reduced the delays.
- strtobool() -> kstrtobool().

Changes in v2:
- removed unnecessary parenthesis in AD5758_REG_WRITE macro.
- added missing documentation fields of ad5758_state struct.
- changed the type of pwr_down attribute to bool.
- changed ad5758_dc_dc_ilimt[] to ad5758_dc_dc_ilim[].
- ad5758_spi_reg_write() now returns spi_write(st->spi,
  >data[0].d32, sizeof(st->data[0].d32));
- removed unnecessary new line in ad5758_calib_mem_refresh().
- changed the type of the mode parameter in
  ad5758_set_dc_dc_conv_mode() from unsigned int to enum
  ad5758_dc_dc_mode.
- removed unnecessary parenthesis in ad5758_slew_rate_config().
- changed the type of the enable parameter in
  ad5758_fault_prot_switch_en() from unsigned char to bool.
- the same as above, but for ad5758_internal_buffers_en().
- added a missing mutex_unlock() in ad5758_reg_access().
- moved the mutex_unlock() in ad5758_read_raw() and removed the
  unreachable return.
- returned directly where it was possible in ad5758_write_raw().
- removed the channel, scan_type and scan_index fields.
- in ad5758_parse_dt(), added missing "\n", and specified what the
  default mode actually is.
- returned directly at the end of ad5758_init().
- in ad5758_probe() used device managed for registering the device
  and returned directly without the error message.

 MAINTAINERS  |   7 +
 drivers/iio/dac/Kconfig  |  10 +
 drivers/iio/dac/Makefile |   1 +
 drivers/iio/dac/ad5758.c | 899 +++
 4 files changed, 917 insertions(+)
 create mode 100644 drivers/iio/dac/ad5758.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 00e9670..12d102d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -796,6 +796,13 @@ M: Michael Hanselmann 
 S: Supported
 F: drivers/macintosh/ams/
 
+ANALOG DEVICES INC AD5758 DRIVER
+M: Stefan Popa 
+L: linux-...@vger.kernel.org
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/dac/ad5758.c
+
 ANALOG DEVICES INC AD5686 DRIVER
 M: Stefan Popa 
 L: linux...@vger.kernel.org
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 06e90de..80beb64 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -167,6 +167,16 @@ config AD5755
  To compile this driver as a module, choose M here: the
  module will be called ad5755.
 
+config AD5758
+   tristate "Analog Devices AD5758 DAC driver"
+   depends on SPI_MASTER
+   help
+ Say yes here to build support for Analog Devices AD5758 single channel
+ Digital to Analog Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5758.
+
 config AD5761
tristate "Analog Devices AD5761/61R/21/21R DAC driver"
depends on SPI_MASTER
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 57aa230..a1b37cf 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_AD5592R_BASE) += ad5592r-base.o
 obj-$(CONFIG_AD5592R) += ad5592r.o
 obj-$(CONFIG_AD5593R) += ad5593r.o
 obj-$(CONFIG_AD5755) += ad5755.o
+obj-$(CONFIG_AD5755) += ad5758.o
 obj-$(CONFIG_AD5761) += ad5761.o
 obj-$(CONFIG_AD5764) += ad5764.o
 obj-$(CONFIG_AD5791) += ad5791.o
diff --git a/drivers/iio/dac/ad5758.c b/drivers/iio/dac/ad5758.c
new file mode 100644
index 000..bd1bed7
--- /dev/n

[PATCH v3 1/2] iio: dac: Add AD5758 support

2018-06-28 Thread Stefan Popa
The AD5758 is a single channel DAC with 16-bit precision which uses the
SPI interface that operates at clock rates up to 50MHz.

The output can be configured as voltage or current and is available on a
single terminal.

Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/ad5758.pdf

Signed-off-by: Stefan Popa 
---
Changes in v3:
- AD5758 can be both a current and voltage output DAC. The
  decision is made based on the DT and the channel type is set
  during probe.
- dc-dc-mode, range-microvolt and range-microamp are required
  properties.
- Introduced a slew-time-us property from which slew rate clock
  and slew rate step are calculated using a best match algorithm.
- Dropped the union from ad5758_state struct.
- Introduced a IIO_CHAN_INFO_OFFSET case part of ad5758_read_raw().
- Added a TODO comment which specifies that CRC is not supported.
- Kept the includes in order and removed the unused ones.
- Removed unused macros and shortened the lengthy ones.
- Renamed AD5758_REG_WRITE to AD5758_WR_FLAG_MSK.
- Added an explanation for enum ad5758_output_range.
- Used bsearch() instead of ad5758_get_array_index().
- Reduced the delays.
- strtobool() -> kstrtobool().

Changes in v2:
- removed unnecessary parenthesis in AD5758_REG_WRITE macro.
- added missing documentation fields of ad5758_state struct.
- changed the type of pwr_down attribute to bool.
- changed ad5758_dc_dc_ilimt[] to ad5758_dc_dc_ilim[].
- ad5758_spi_reg_write() now returns spi_write(st->spi,
  >data[0].d32, sizeof(st->data[0].d32));
- removed unnecessary new line in ad5758_calib_mem_refresh().
- changed the type of the mode parameter in
  ad5758_set_dc_dc_conv_mode() from unsigned int to enum
  ad5758_dc_dc_mode.
- removed unnecessary parenthesis in ad5758_slew_rate_config().
- changed the type of the enable parameter in
  ad5758_fault_prot_switch_en() from unsigned char to bool.
- the same as above, but for ad5758_internal_buffers_en().
- added a missing mutex_unlock() in ad5758_reg_access().
- moved the mutex_unlock() in ad5758_read_raw() and removed the
  unreachable return.
- returned directly where it was possible in ad5758_write_raw().
- removed the channel, scan_type and scan_index fields.
- in ad5758_parse_dt(), added missing "\n", and specified what the
  default mode actually is.
- returned directly at the end of ad5758_init().
- in ad5758_probe() used device managed for registering the device
  and returned directly without the error message.

 MAINTAINERS  |   7 +
 drivers/iio/dac/Kconfig  |  10 +
 drivers/iio/dac/Makefile |   1 +
 drivers/iio/dac/ad5758.c | 899 +++
 4 files changed, 917 insertions(+)
 create mode 100644 drivers/iio/dac/ad5758.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 00e9670..12d102d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -796,6 +796,13 @@ M: Michael Hanselmann 
 S: Supported
 F: drivers/macintosh/ams/
 
+ANALOG DEVICES INC AD5758 DRIVER
+M: Stefan Popa 
+L: linux-...@vger.kernel.org
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/dac/ad5758.c
+
 ANALOG DEVICES INC AD5686 DRIVER
 M: Stefan Popa 
 L: linux...@vger.kernel.org
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 06e90de..80beb64 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -167,6 +167,16 @@ config AD5755
  To compile this driver as a module, choose M here: the
  module will be called ad5755.
 
+config AD5758
+   tristate "Analog Devices AD5758 DAC driver"
+   depends on SPI_MASTER
+   help
+ Say yes here to build support for Analog Devices AD5758 single channel
+ Digital to Analog Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5758.
+
 config AD5761
tristate "Analog Devices AD5761/61R/21/21R DAC driver"
depends on SPI_MASTER
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 57aa230..a1b37cf 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_AD5592R_BASE) += ad5592r-base.o
 obj-$(CONFIG_AD5592R) += ad5592r.o
 obj-$(CONFIG_AD5593R) += ad5593r.o
 obj-$(CONFIG_AD5755) += ad5755.o
+obj-$(CONFIG_AD5755) += ad5758.o
 obj-$(CONFIG_AD5761) += ad5761.o
 obj-$(CONFIG_AD5764) += ad5764.o
 obj-$(CONFIG_AD5791) += ad5791.o
diff --git a/drivers/iio/dac/ad5758.c b/drivers/iio/dac/ad5758.c
new file mode 100644
index 000..2aaddf9
--- /dev/null
+++ b/drivers/iio/dac/ad5758.c
@@ -0,0 +1,899 @@
+// SPDX-L

[PATCH v3 2/2] dt-bindings: iio: dac: Add docs for AD5758 DAC

2018-06-28 Thread Stefan Popa
Signed-off-by: Stefan Popa 
---
Changes in v3:
- AD5758 can be both a current and voltage output DAC. The
  decision is made based on the DT and the channel type is set
  during probe.
- range was replaced by range-microvolt and range-microamp
- dc-dc-mode, range-microvolt and range-microamp are required
  properties.
- Introduced a slew-time-us property from which slew rate clock
  and slew rate step are calculated using a best match algorithm.
- Added units in the name of the properties.
- Offered more explanation for the various modes of operation.

Changes in v2:
- Nothing changed, just to follow the patch set version.
 .../devicetree/bindings/iio/dac/ad5758.txt | 73 ++
 MAINTAINERS|  1 +
 2 files changed, 74 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/dac/ad5758.txt

diff --git a/Documentation/devicetree/bindings/iio/dac/ad5758.txt 
b/Documentation/devicetree/bindings/iio/dac/ad5758.txt
new file mode 100644
index 000..797df9b
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/ad5758.txt
@@ -0,0 +1,73 @@
+Analog Devices AD5758 DAC device driver
+
+Required properties for the AD5758:
+   - compatible: Must be "adi,ad5758"
+   - reg: SPI chip select number for the device
+   - spi-max-frequency: Max SPI frequency to use (< 5000)
+   - spi-cpha: is the only mode that is supported
+
+Required properties:
+
+ - adi,dc-dc-mode: Mode of operation of the dc-to-dc converter
+  Dynamic Power Control (DPC)
+  In this mode, the AD5758 circuitry senses the output voltage 
and
+  dynamically regulates the supply voltage, VDPC+, to meet 
compliance
+  requirements plus an optimized headroom voltage for the 
output buffer.
+
+  Programmable Power Control (PPC)
+  In this mode, the VDPC+ voltage is user-programmable to a 
fixed level
+  that needs to accommodate the maximum output load required.
+
+  The output of the DAC core is either converted to a current 
or voltage
+  output at the VIOUT pin. Only one mode can be enabled at any 
one time.
+
+  The following values are currently supported:
+   * 1: DPC current mode
+   * 2: DPC voltage mode
+   * 3: PPC current mode
+
+ Depending on the selected output mode (voltage or current) one of the two 
properties must
+ be present:
+
+ - adi,range-microvolt: Voltage output range
+   The array of voltage output ranges must contain two fields:
+   * <0 500>: 0 V to 5 V voltage range
+   * <0 1000>: 0 V to 10 V voltage range
+   * <(-500) 500>: ±5 V voltage range
+   * <(-1000) 1000>: ±10 V voltage range
+ - adi,range-microamp: Current output range
+   The array of current output ranges must contain two fields:
+   * <0 2>: 0 mA to 20 mA current range
+   * <0 24000>: 0 mA to 24 mA current range
+   * <4 24000>: 4 mA to 20 mA current range
+   * <(-2) 2>: ±20 mA current range
+   * <(-24000) 24000>: ±24 mA current range
+   * <(-1000) 22000>: −1 mA to +22 mA current range
+
+Optional properties:
+
+ - adi,dc-dc-ilim-microamp: The dc-to-dc converter current limit
+  The following values are currently supported [uA]:
+   * 15
+   * 20
+   * 25
+   * 30
+   * 35
+   * 40
+
+ - adi,slew-time-us: The time it takes for the output to reach the full scale 
[uS]
+The supported range is between 133us up to 1023984375us
+
+AD5758 Example:
+
+   ad5758@0 {
+   compatible = "adi,ad5758";
+   reg = <0>;
+   spi-max-frequency = <100>;
+   spi-cpha;
+
+   adi,dc-dc-mode = <2>;
+   adi,range-microvolt = <0 1000>;
+   adi,dc-dc-ilim-microamp = <20>;
+   adi,slew-time-us = <125000>;
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 12d102d..60b1028 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -802,6 +802,7 @@ L:  linux-...@vger.kernel.org
 W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/iio/dac/ad5758.c
+F: Documentation/devicetree/bindings/iio/dac/ad5758.txt
 
 ANALOG DEVICES INC AD5686 DRIVER
 M: Stefan Popa 
-- 
2.7.4



[PATCH v2 2/3] iio: adc: Add ad7124 support

2018-10-19 Thread Stefan Popa
The ad7124-4 and ad7124-8 are a family of 4 and 8 channel sigma-delta ADCs
with 24-bit precision and reference.

Three power modes are available which in turn affect the output data rate:
 * Full power: 9.38 SPS to 19,200 SPS
 * Mid power: 2.34 SPS to 4800 SPS
 * Low power: 1.17 SPS to 2400 SPS

The ad7124-4 can be configured to have four differential inputs, while
ad7124-8 can have 8. Moreover, ad7124 also supports per channel
configuration. Each configuration consists of gain, reference source,
output data rate and bipolar/unipolar configuration.

Datasheets:
Link: 
http://www.analog.com/media/en/technical-documentation/data-sheets/AD7124-4.pdf
Link: 
http://www.analog.com/media/en/technical-documentation/data-sheets/ad7124-8.pdf

Signed-off-by: Stefan Popa 
---
Changes in v2:
- Nothing changed.

 MAINTAINERS  |   7 +
 drivers/iio/adc/Kconfig  |  11 +
 drivers/iio/adc/Makefile |   1 +
 drivers/iio/adc/ad7124.c | 655 +++
 4 files changed, 674 insertions(+)
 create mode 100644 drivers/iio/adc/ad7124.c

diff --git a/MAINTAINERS b/MAINTAINERS
index f642044..3a1bfcb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -839,6 +839,13 @@ S: Supported
 F: drivers/iio/dac/ad5758.c
 F: Documentation/devicetree/bindings/iio/dac/ad5758.txt
 
+ANALOG DEVICES INC AD7124 DRIVER
+M: Stefan Popa 
+L: linux-...@vger.kernel.org
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/adc/ad7124.c
+
 ANALOG DEVICES INC AD9389B DRIVER
 M: Hans Verkuil 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index a52fea8..148a10f 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -10,6 +10,17 @@ config AD_SIGMA_DELTA
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
 
+config AD7124
+   tristate "Analog Devices AD7124 and similar sigma-delta ADCs driver"
+   depends on SPI_MASTER
+   select AD_SIGMA_DELTA
+   help
+ Say yes here to build support for Analog Devices AD7124-4 and AD7124-8
+ SPI analog to digital converters (ADC).
+
+ To compile this driver as a module, choose M here: the module will be
+ called ad7124.
+
 config AD7266
tristate "Analog Devices AD7265/AD7266 ADC driver"
depends on SPI_MASTER
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index a6e6a0b..76168b2 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -5,6 +5,7 @@
 
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
+obj-$(CONFIG_AD7124) += ad7124.o
 obj-$(CONFIG_AD7266) += ad7266.o
 obj-$(CONFIG_AD7291) += ad7291.o
 obj-$(CONFIG_AD7298) += ad7298.o
diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c
new file mode 100644
index 000..c6d9798
--- /dev/null
+++ b/drivers/iio/adc/ad7124.c
@@ -0,0 +1,655 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * AD7124 SPI ADC driver
+ *
+ * Copyright 2018 Analog Devices Inc.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+/* AD7124 registers */
+#define AD7124_COMMS   0x00
+#define AD7124_STATUS  0x00
+#define AD7124_ADC_CONTROL 0x01
+#define AD7124_DATA0x02
+#define AD7124_IO_CONTROL_10x03
+#define AD7124_IO_CONTROL_20x04
+#define AD7124_ID  0x05
+#define AD7124_ERROR   0x06
+#define AD7124_ERROR_EN0x07
+#define AD7124_MCLK_COUNT  0x08
+#define AD7124_CHANNEL(x)  (0x09 + (x))
+#define AD7124_CONFIG(x)   (0x19 + (x))
+#define AD7124_FILTER(x)   (0x21 + (x))
+#define AD7124_OFFSET(x)   (0x29 + (x))
+#define AD7124_GAIN(x) (0x31 + (x))
+
+/* AD7124_STATUS */
+#define AD7124_STATUS_POR_FLAG_MSK BIT(4)
+
+/* AD7124_ADC_CONTROL */
+#define AD7124_ADC_CTRL_PWR_MSKGENMASK(7, 6)
+#define AD7124_ADC_CTRL_PWR(x) FIELD_PREP(AD7124_ADC_CTRL_PWR_MSK, x)
+#define AD7124_ADC_CTRL_MODE_MSK   GENMASK(5, 2)
+#define AD7124_ADC_CTRL_MODE(x)FIELD_PREP(AD7124_ADC_CTRL_MODE_MSK, x)
+
+/* AD7124_CHANNEL_X */
+#define AD7124_CHANNEL_EN_MSK  BIT(15)
+#define AD7124_CHANNEL_EN(x)   FIELD_PREP(AD7124_CHANNEL_EN_MSK, x)
+#define AD7124_CHANNEL_SETUP_MSK   GENMASK(14, 12)
+#define AD7124_CHANNEL_SETUP(x)FIELD_PREP(AD7124_CHANNEL_SETUP_MSK, x)
+#define AD7124_CHANNEL_AINP_MSKGENMASK(9, 5)
+#define AD7124_CHANNEL_AINP(x) FIELD_PREP(AD7124_CHANNEL_AINP_MSK, x)
+#define AD7124_CHANNEL_AINM_MSKGENMASK(4, 0)
+#define AD7124_CHANNEL_AINM(x) FIELD_PREP(AD7124_CHANNEL_AINM_MSK, x)
+
+/* AD7124_CONFIG_X */
+#define AD7124_CONFIG_BIPOLAR_MSK  BIT(11)
+#define AD7

[PATCH v2 1/3] iio: ad_sigma_delta: Allow to provide custom data register address

2018-10-19 Thread Stefan Popa
From: Lars-Peter Clausen 

Some newer devices from the Sigma-Delta ADC family do have their data
register at a different address than the current default address. Add a
parameter to the ad_sigma_delta_info struct which allows to override the
default address.

Signed-off-by: Lars-Peter Clausen 
Signed-off-by: Stefan Popa 
---
Changes in v2:
- Added this commit.

 drivers/iio/adc/ad_sigma_delta.c   | 22 +-
 include/linux/iio/adc/ad_sigma_delta.h |  3 +++
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index fc95107..ff5f2da 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -278,6 +278,7 @@ int ad_sigma_delta_single_conversion(struct iio_dev 
*indio_dev,
 {
struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
unsigned int sample, raw_sample;
+   unsigned int data_reg;
int ret = 0;
 
if (iio_buffer_enabled(indio_dev))
@@ -305,7 +306,12 @@ int ad_sigma_delta_single_conversion(struct iio_dev 
*indio_dev,
if (ret < 0)
goto out;
 
-   ret = ad_sd_read_reg(sigma_delta, AD_SD_REG_DATA,
+   if (sigma_delta->info->data_reg != 0)
+   data_reg = sigma_delta->info->data_reg;
+   else
+   data_reg = AD_SD_REG_DATA;
+
+   ret = ad_sd_read_reg(sigma_delta, data_reg,
DIV_ROUND_UP(chan->scan_type.realbits + chan->scan_type.shift, 
8),
_sample);
 
@@ -392,6 +398,7 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
unsigned int reg_size;
+   unsigned int data_reg;
uint8_t data[16];
int ret;
 
@@ -401,18 +408,23 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
indio_dev->channels[0].scan_type.shift;
reg_size = DIV_ROUND_UP(reg_size, 8);
 
+   if (sigma_delta->info->data_reg != 0)
+   data_reg = sigma_delta->info->data_reg;
+   else
+   data_reg = AD_SD_REG_DATA;
+
switch (reg_size) {
case 4:
case 2:
case 1:
-   ret = ad_sd_read_reg_raw(sigma_delta, AD_SD_REG_DATA,
-   reg_size, [0]);
+   ret = ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size,
+   [0]);
break;
case 3:
/* We store 24 bit samples in a 32 bit word. Keep the upper
 * byte set to zero. */
-   ret = ad_sd_read_reg_raw(sigma_delta, AD_SD_REG_DATA,
-   reg_size, [1]);
+   ret = ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size,
+   [1]);
break;
}
 
diff --git a/include/linux/iio/adc/ad_sigma_delta.h 
b/include/linux/iio/adc/ad_sigma_delta.h
index 730ead1..7e84351 100644
--- a/include/linux/iio/adc/ad_sigma_delta.h
+++ b/include/linux/iio/adc/ad_sigma_delta.h
@@ -39,6 +39,8 @@ struct iio_dev;
  * if there is just one read-only sample data shift register.
  * @addr_shift: Shift of the register address in the communications register.
  * @read_mask: Mask for the communications register having the read bit set.
+ * @data_reg: Address of the data register, if 0 the default address of 0x3 
will
+ *   be used.
  */
 struct ad_sigma_delta_info {
int (*set_channel)(struct ad_sigma_delta *, unsigned int channel);
@@ -47,6 +49,7 @@ struct ad_sigma_delta_info {
bool has_registers;
unsigned int addr_shift;
unsigned int read_mask;
+   unsigned int data_reg;
 };
 
 /**
-- 
2.7.4



[PATCH v2 3/3] dt-bindings: iio: adc: Add docs for ad7124

2018-10-19 Thread Stefan Popa
Add support for Analog Devices AD7124 4-channels and 8-channels ADC.

Signed-off-by: Stefan Popa 
---
Changes in v2:
- Nothing changed.

 .../devicetree/bindings/iio/adc/adi,ad7124.txt | 96 ++
 MAINTAINERS|  1 +
 2 files changed, 97 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt

diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt 
b/Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt
new file mode 100644
index 000..77a7b92
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt
@@ -0,0 +1,96 @@
+Analog Devices AD7124 ADC device driver
+
+Required properties for the AD7124:
+   - compatible: Must be one of "adi,ad7124-4" or "adi,ad7124-8"
+   - reg: SPI chip select number for the device
+   - spi-max-frequency: Max SPI frequency to use
+   see: Documentation/devicetree/bindings/spi/spi-bus.txt
+   - clocks: phandle to the master clock (mclk)
+   see: Documentation/devicetree/bindings/clock/clock-bindings.txt
+   - clock-names: Must be "mclk".
+   - interrupts: IRQ line for the ADC
+   see: 
Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+
+   - adi,channels: List of external channels connected to the ADC:
+ Required properties:
+   * #address-cells: Must be 2.
+   * #size-cells: Must be 0.
+
+ The child nodes of this node represent the external channels which are
+ connected to the ADC.
+
+ Each child node represents one channel and has the following
+ properties:
+   Required properties:
+   * reg: Pins the channel is connected to. The first 
value specifies
+ the positive input pin, the second value the negative 
input pin.
+   * adi,channel-number: It can have up to 4 channels on 
ad7124-4 and
+ 8 channels on ad7124-8, numbered from 0 to 15.
+
+   Optional properties:
+   * adi,bipolar: If set the channel is used in bipolar 
mode.
+   * adi,reference-select: Select the reference source to 
use when
+ converting on the the specific channel. Valid values 
are:
+ 0: REFIN1(+)/REFIN1(−).
+ 1: REFIN2(+)/REFIN2(−).
+ 3: AVDD
+ If this field is left empty, internal reference is 
selected.
+   * adi,gain: Select the gain when converting on the 
specific channel.
+ Valid values are: 1, 2, 4, 8, 16, 32, 64, 128.
+ If this field is left empty, gain of 1 is selected.
+   * adi,odr-hz: The output data rate can be programmed 
from:
+ 9 to 19200 for full power mode (when the master clock 
is 614.4 kHz)
+ 2 to 4800 for mid power mode (when the master clock 
is 153.6 kHz)
+ 1 to 2400 for low power mode (when the master clock 
is 76.8 kHz)
+ If this field is left empty, odr of 9 is selected.
+
+Optional properties:
+   - refin1-supply: refin1 supply can be used as reference for conversion.
+   - refin2-supply: refin2 supply can be used as reference for conversion.
+   - avdd-supply: avdd supply can be used as reference for conversion.
+
+Example:
+   adc@0 {
+   compatible = "adi,ad7124-4";
+   reg = <0>;
+   spi-max-frequency = <500>;
+   interrupts = <25 2>;
+   interrupt-parent = <>;
+   refin1-supply = <_vref>;
+   clocks = <_mclk>;
+   clock-names = "mclk";
+
+   adi,channels {
+   #address-cells = <2>;
+   #size-cells = <0>;
+
+   channel@0 {
+   reg = <0 1>;
+   adi,channel-number = <0>;
+   adi,reference-select = <0>;
+   adi,gain = <2>;
+   adi,odr-hz = <10>;
+   };
+
+   channel@1 {
+   reg = <2 3>;
+   adi,bipolar;
+   adi,channel-number = <1>;
+   adi,reference-select = <0>;
+   adi,gain = <4>;
+   adi,odr-hz = <50>;
+   };
+
+   channel@2 {
+   reg = <4 5&

[PATCH 1/2] staging: iio: ad7606: Move out of staging

2018-10-18 Thread Stefan Popa
Move ad7606 ADC driver out of staging and into the mainline.

Signed-off-by: Stefan Popa 
---
 MAINTAINERS  |   7 +
 drivers/iio/adc/Kconfig  |  34 +++
 drivers/iio/adc/Makefile |   3 +
 drivers/iio/adc/ad7606.c | 565 +++
 drivers/iio/adc/ad7606.h | 106 +++
 drivers/iio/adc/ad7606_par.c | 113 +++
 drivers/iio/adc/ad7606_spi.c |  79 +
 drivers/staging/iio/adc/Kconfig  |  34 ---
 drivers/staging/iio/adc/Makefile |   3 -
 drivers/staging/iio/adc/ad7606.c | 565 ---
 drivers/staging/iio/adc/ad7606.h | 106 ---
 drivers/staging/iio/adc/ad7606_par.c | 113 ---
 drivers/staging/iio/adc/ad7606_spi.c |  79 -
 13 files changed, 907 insertions(+), 900 deletions(-)
 create mode 100644 drivers/iio/adc/ad7606.c
 create mode 100644 drivers/iio/adc/ad7606.h
 create mode 100644 drivers/iio/adc/ad7606_par.c
 create mode 100644 drivers/iio/adc/ad7606_spi.c
 delete mode 100644 drivers/staging/iio/adc/ad7606.c
 delete mode 100644 drivers/staging/iio/adc/ad7606.h
 delete mode 100644 drivers/staging/iio/adc/ad7606_par.c
 delete mode 100644 drivers/staging/iio/adc/ad7606_spi.c

diff --git a/MAINTAINERS b/MAINTAINERS
index f642044..843545d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -839,6 +839,13 @@ S: Supported
 F: drivers/iio/dac/ad5758.c
 F: Documentation/devicetree/bindings/iio/dac/ad5758.txt
 
+ANALOG DEVICES INC AD7606 DRIVER
+M: Stefan Popa 
+L: linux-...@vger.kernel.org
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/adc/ad7606.c
+
 ANALOG DEVICES INC AD9389B DRIVER
 M: Hans Verkuil 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index a52fea8..22bafdc 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -58,6 +58,40 @@ config AD7476
  To compile this driver as a module, choose M here: the
  module will be called ad7476.
 
+config AD7606
+   tristate "Analog Devices AD7606 ADC driver"
+   depends on GPIOLIB || COMPILE_TEST
+   depends on HAS_IOMEM
+   select IIO_BUFFER
+   select IIO_TRIGGERED_BUFFER
+   help
+ Say yes here to build support for Analog Devices:
+ ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters 
(ADC).
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad7606.
+
+config AD7606_IFACE_PARALLEL
+   tristate "parallel interface support"
+   depends on AD7606
+   help
+ Say yes here to include parallel interface support on the AD7606
+ ADC driver.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad7606_parallel.
+
+config AD7606_IFACE_SPI
+   tristate "spi interface support"
+   depends on AD7606
+   depends on SPI
+   help
+ Say yes here to include parallel interface support on the AD7606
+ ADC driver.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad7606_spi.
+
 config AD7766
tristate "Analog Devices AD7766/AD7767 ADC driver"
depends on SPI_MASTER
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index a6e6a0b..b734f4f 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -8,6 +8,9 @@ obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
 obj-$(CONFIG_AD7266) += ad7266.o
 obj-$(CONFIG_AD7291) += ad7291.o
 obj-$(CONFIG_AD7298) += ad7298.o
+obj-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o
+obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
+obj-$(CONFIG_AD7606) += ad7606.o
 obj-$(CONFIG_AD7923) += ad7923.o
 obj-$(CONFIG_AD7476) += ad7476.o
 obj-$(CONFIG_AD7766) += ad7766.o
diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c
new file mode 100644
index 000..0b728b6
--- /dev/null
+++ b/drivers/iio/adc/ad7606.c
@@ -0,0 +1,565 @@
+/*
+ * AD7606 SPI ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ad7606.h"
+
+/*
+ * Scales are computed as 5000/32768 and 1/32768 respectively,
+ * so that when applied to the raw values they provide mV values
+ */
+static const unsigned int scale_avail[2][2] = {
+   {0, 152588}, {0, 305176}
+};
+
+static int ad7606_reset(struct ad7606_state *st)
+{
+   if (st->gpio_reset) {
+   gpiod_set_value(st->gpio_reset, 1);
+   ndelay(100); /* t_reset >= 100ns */
+   gpiod_set_value(st->gpio_reset, 0);
+   return 0;
+   }
+
+   return -ENODEV;
+}
+
+static int ad7606_read_sam

[PATCH 2/2] dt-bindings: iio: adc: Add docs for AD7606 ADC

2018-10-18 Thread Stefan Popa
Document support for AD7606 Analog to Digital Converter.

Signed-off-by: Stefan Popa 
---
 .../devicetree/bindings/iio/adc/adi,ad7606.txt | 51 ++
 MAINTAINERS|  1 +
 2 files changed, 52 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt

diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt 
b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt
new file mode 100644
index 000..dede581
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt
@@ -0,0 +1,51 @@
+Analog Devices AD7606 Simultaneous Sampling ADC
+
+Required properties for the AD7606:
+
+ - compatible: Must be one of "adi,ad7605-4", "adi,ad7606-8", "adi,ad7606-6" or
+  "adi,ad7606-4".
+ - reg: SPI chip select number for the device
+ - spi-max-frequency: Max SPI frequency to use
+   see: Documentation/devicetree/bindings/spi/spi-bus.txt
+ - spi-cpha: See Documentation/devicetree/bindings/spi/spi-bus.txt
+ - avcc-supply: phandle to the Avcc power supply
+ - interrupts: IRQ line for the ADC
+   see: 
Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+ - conversion-start-gpio: must be the device tree identifier of the CONVST pin.
+ This logic input is used to initiate conversions on
+ the analog input channels.
+
+Optional properties:
+
+ - reset-gpio: must be the device tree identifier of the RESET pin. If 
specified,
+  it will be asserted during driver probe.
+ - first-data-gpio: must be the device tree identifier of the FRSTDATA pin.
+   The FRSTDATA output indicates when the first channel, V1, is
+   being read back on either the parallel, byte or serial 
interface.
+- standby-gpio: must be the device tree identifier of the STBY pin. This pin 
is used
+   to place the AD7606 into one of two power-down modes, Standby 
mode or
+   Shutdown mode.
+- range-gpio: must be the device tree identifier of the RANGE pin. The 
polarity on
+ this pin determines the input range of the analog input channels. 
If
+ this pin is tied to a logic high, the analog input range is ±10V 
for
+ allchannels. If this pin is tied to a logic low, the analog input 
range
+ is ±5V for all channels.
+
+Example:
+
+   adc@0 {
+   compatible = "adi,ad7606-8";
+   reg = <0>;
+   spi-max-frequency = <100>;
+   spi-cpol;
+
+   avcc-supply = <_vref>;
+
+   interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
+   interrupt-parent = <>;
+
+   conversion-start-gpio = < 17 0>;
+   reset-gpio = < 27 0>;
+   first-data-gpio = < 22 0>;
+   standby-gpio = < 24 0>;
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 843545d..6d63db4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -845,6 +845,7 @@ L:  linux-...@vger.kernel.org
 W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/iio/adc/ad7606.c
+F: Documentation/devicetree/bindings/iio/adc/ad7606.txt
 
 ANALOG DEVICES INC AD9389B DRIVER
 M: Hans Verkuil 
-- 
2.7.4



[PATCH 1/2] iio: adc: Add ad7124 support

2018-10-18 Thread Stefan Popa
The ad7124-4 and ad7124-8 are a family of 4 and 8 channel sigma-delta ADCs
with 24-bit precision and reference.

Three power modes are available which in turn affect the output data rate:
 * Full power: 9.38 SPS to 19,200 SPS
 * Mid power: 2.34 SPS to 4800 SPS
 * Low power: 1.17 SPS to 2400 SPS

The ad7124-4 can be configured to have four differential inputs, while
ad7124-8 can have 8. Moreover, ad7124 also supports per channel
configuration. Each configuration consists of gain, reference source,
output data rate and bipolar/unipolar configuration.

Datasheets:
Link: 
http://www.analog.com/media/en/technical-documentation/data-sheets/AD7124-4.pdf
Link: 
http://www.analog.com/media/en/technical-documentation/data-sheets/ad7124-8.pdf

Signed-off-by: Stefan Popa 
---
 MAINTAINERS  |   7 +
 drivers/iio/adc/Kconfig  |  11 +
 drivers/iio/adc/Makefile |   1 +
 drivers/iio/adc/ad7124.c | 655 +++
 4 files changed, 674 insertions(+)
 create mode 100644 drivers/iio/adc/ad7124.c

diff --git a/MAINTAINERS b/MAINTAINERS
index f642044..3a1bfcb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -839,6 +839,13 @@ S: Supported
 F: drivers/iio/dac/ad5758.c
 F: Documentation/devicetree/bindings/iio/dac/ad5758.txt
 
+ANALOG DEVICES INC AD7124 DRIVER
+M: Stefan Popa 
+L: linux-...@vger.kernel.org
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/adc/ad7124.c
+
 ANALOG DEVICES INC AD9389B DRIVER
 M: Hans Verkuil 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index a52fea8..148a10f 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -10,6 +10,17 @@ config AD_SIGMA_DELTA
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
 
+config AD7124
+   tristate "Analog Devices AD7124 and similar sigma-delta ADCs driver"
+   depends on SPI_MASTER
+   select AD_SIGMA_DELTA
+   help
+ Say yes here to build support for Analog Devices AD7124-4 and AD7124-8
+ SPI analog to digital converters (ADC).
+
+ To compile this driver as a module, choose M here: the module will be
+ called ad7124.
+
 config AD7266
tristate "Analog Devices AD7265/AD7266 ADC driver"
depends on SPI_MASTER
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index a6e6a0b..76168b2 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -5,6 +5,7 @@
 
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
+obj-$(CONFIG_AD7124) += ad7124.o
 obj-$(CONFIG_AD7266) += ad7266.o
 obj-$(CONFIG_AD7291) += ad7291.o
 obj-$(CONFIG_AD7298) += ad7298.o
diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c
new file mode 100644
index 000..c6d9798
--- /dev/null
+++ b/drivers/iio/adc/ad7124.c
@@ -0,0 +1,655 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * AD7124 SPI ADC driver
+ *
+ * Copyright 2018 Analog Devices Inc.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+/* AD7124 registers */
+#define AD7124_COMMS   0x00
+#define AD7124_STATUS  0x00
+#define AD7124_ADC_CONTROL 0x01
+#define AD7124_DATA0x02
+#define AD7124_IO_CONTROL_10x03
+#define AD7124_IO_CONTROL_20x04
+#define AD7124_ID  0x05
+#define AD7124_ERROR   0x06
+#define AD7124_ERROR_EN0x07
+#define AD7124_MCLK_COUNT  0x08
+#define AD7124_CHANNEL(x)  (0x09 + (x))
+#define AD7124_CONFIG(x)   (0x19 + (x))
+#define AD7124_FILTER(x)   (0x21 + (x))
+#define AD7124_OFFSET(x)   (0x29 + (x))
+#define AD7124_GAIN(x) (0x31 + (x))
+
+/* AD7124_STATUS */
+#define AD7124_STATUS_POR_FLAG_MSK BIT(4)
+
+/* AD7124_ADC_CONTROL */
+#define AD7124_ADC_CTRL_PWR_MSKGENMASK(7, 6)
+#define AD7124_ADC_CTRL_PWR(x) FIELD_PREP(AD7124_ADC_CTRL_PWR_MSK, x)
+#define AD7124_ADC_CTRL_MODE_MSK   GENMASK(5, 2)
+#define AD7124_ADC_CTRL_MODE(x)FIELD_PREP(AD7124_ADC_CTRL_MODE_MSK, x)
+
+/* AD7124_CHANNEL_X */
+#define AD7124_CHANNEL_EN_MSK  BIT(15)
+#define AD7124_CHANNEL_EN(x)   FIELD_PREP(AD7124_CHANNEL_EN_MSK, x)
+#define AD7124_CHANNEL_SETUP_MSK   GENMASK(14, 12)
+#define AD7124_CHANNEL_SETUP(x)FIELD_PREP(AD7124_CHANNEL_SETUP_MSK, x)
+#define AD7124_CHANNEL_AINP_MSKGENMASK(9, 5)
+#define AD7124_CHANNEL_AINP(x) FIELD_PREP(AD7124_CHANNEL_AINP_MSK, x)
+#define AD7124_CHANNEL_AINM_MSKGENMASK(4, 0)
+#define AD7124_CHANNEL_AINM(x) FIELD_PREP(AD7124_CHANNEL_AINM_MSK, x)
+
+/* AD7124_CONFIG_X */
+#define AD7124_CONFIG_BIPOLAR_MSK  BIT(11)
+#define AD7124_CONFIG_BIPOLAR(x)   FIELD_PREP(AD7124_C

[PATCH 2/2] dt-bindings: iio: adc: Add docs for ad7124

2018-10-18 Thread Stefan Popa
Add support for Analog Devices AD7124 4-channels and 8-channels ADC.

Signed-off-by: Stefan Popa 
---
 .../devicetree/bindings/iio/adc/adi,ad7124.txt | 96 ++
 MAINTAINERS|  1 +
 2 files changed, 97 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt

diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt 
b/Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt
new file mode 100644
index 000..77a7b92
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt
@@ -0,0 +1,96 @@
+Analog Devices AD7124 ADC device driver
+
+Required properties for the AD7124:
+   - compatible: Must be one of "adi,ad7124-4" or "adi,ad7124-8"
+   - reg: SPI chip select number for the device
+   - spi-max-frequency: Max SPI frequency to use
+   see: Documentation/devicetree/bindings/spi/spi-bus.txt
+   - clocks: phandle to the master clock (mclk)
+   see: Documentation/devicetree/bindings/clock/clock-bindings.txt
+   - clock-names: Must be "mclk".
+   - interrupts: IRQ line for the ADC
+   see: 
Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+
+   - adi,channels: List of external channels connected to the ADC:
+ Required properties:
+   * #address-cells: Must be 2.
+   * #size-cells: Must be 0.
+
+ The child nodes of this node represent the external channels which are
+ connected to the ADC.
+
+ Each child node represents one channel and has the following
+ properties:
+   Required properties:
+   * reg: Pins the channel is connected to. The first 
value specifies
+ the positive input pin, the second value the negative 
input pin.
+   * adi,channel-number: It can have up to 4 channels on 
ad7124-4 and
+ 8 channels on ad7124-8, numbered from 0 to 15.
+
+   Optional properties:
+   * adi,bipolar: If set the channel is used in bipolar 
mode.
+   * adi,reference-select: Select the reference source to 
use when
+ converting on the the specific channel. Valid values 
are:
+ 0: REFIN1(+)/REFIN1(−).
+ 1: REFIN2(+)/REFIN2(−).
+ 3: AVDD
+ If this field is left empty, internal reference is 
selected.
+   * adi,gain: Select the gain when converting on the 
specific channel.
+ Valid values are: 1, 2, 4, 8, 16, 32, 64, 128.
+ If this field is left empty, gain of 1 is selected.
+   * adi,odr-hz: The output data rate can be programmed 
from:
+ 9 to 19200 for full power mode (when the master clock 
is 614.4 kHz)
+ 2 to 4800 for mid power mode (when the master clock 
is 153.6 kHz)
+ 1 to 2400 for low power mode (when the master clock 
is 76.8 kHz)
+ If this field is left empty, odr of 9 is selected.
+
+Optional properties:
+   - refin1-supply: refin1 supply can be used as reference for conversion.
+   - refin2-supply: refin2 supply can be used as reference for conversion.
+   - avdd-supply: avdd supply can be used as reference for conversion.
+
+Example:
+   adc@0 {
+   compatible = "adi,ad7124-4";
+   reg = <0>;
+   spi-max-frequency = <500>;
+   interrupts = <25 2>;
+   interrupt-parent = <>;
+   refin1-supply = <_vref>;
+   clocks = <_mclk>;
+   clock-names = "mclk";
+
+   adi,channels {
+   #address-cells = <2>;
+   #size-cells = <0>;
+
+   channel@0 {
+   reg = <0 1>;
+   adi,channel-number = <0>;
+   adi,reference-select = <0>;
+   adi,gain = <2>;
+   adi,odr-hz = <10>;
+   };
+
+   channel@1 {
+   reg = <2 3>;
+   adi,bipolar;
+   adi,channel-number = <1>;
+   adi,reference-select = <0>;
+   adi,gain = <4>;
+   adi,odr-hz = <50>;
+   };
+
+   channel@2 {
+   reg = <4 5>;
+   adi,channel-number = <2&g

[PATCH v3 3/3] dt-bindings: iio: adc: Add docs for ad7124

2018-10-29 Thread Stefan Popa
Add support for Analog Devices AD7124 4-channels and 8-channels ADC.

Signed-off-by: Stefan Popa 
---
Changes in v2:
- Nothing changed.
Changes in v3:
- Removed the "adi,channels" property.
- Used the "reg" property to get the channel number and 
"adi,diff-channels"
  for the differential pins. The "adi,channel-number" property was 
removed.
- adi,bipolar is of boolean type.

 .../devicetree/bindings/iio/adc/adi,ad7124.txt | 90 ++
 MAINTAINERS|  1 +
 2 files changed, 91 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt

diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt 
b/Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt
new file mode 100644
index 000..46a9b71
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt
@@ -0,0 +1,90 @@
+Analog Devices AD7124 ADC device driver
+
+Required properties for the AD7124:
+   - compatible: Must be one of "adi,ad7124-4" or "adi,ad7124-8"
+   - reg: SPI chip select number for the device
+   - spi-max-frequency: Max SPI frequency to use
+   see: Documentation/devicetree/bindings/spi/spi-bus.txt
+   - clocks: phandle to the master clock (mclk)
+   see: Documentation/devicetree/bindings/clock/clock-bindings.txt
+   - clock-names: Must be "mclk".
+   - interrupts: IRQ line for the ADC
+   see: 
Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+
+ Required properties:
+   * #address-cells: Must be 1.
+   * #size-cells: Must be 0.
+
+ Subnode(s) represent the external channels which are connected to the 
ADC.
+ Each subnode represents one channel and has the following properties:
+   Required properties:
+   * reg: The channel number. It can have up to 4 channels 
on ad7124-4
+ and 8 channels on ad7124-8, numbered from 0 to 15.
+   * adi,diff-channels: Pins the channel is connected to. 
The first value
+ specifies the positive input pin, the second value 
the negative input pin.
+
+   Optional properties:
+   * adi,bipolar: Boolean, if set the channel is used in 
bipolar mode.
+   * adi,reference-select: Select the reference source to 
use when
+ converting on the the specific channel. Valid values 
are:
+ 0: REFIN1(+)/REFIN1(−).
+ 1: REFIN2(+)/REFIN2(−).
+ 3: AVDD
+ If this field is left empty, internal reference is 
selected.
+   * adi,gain: Select the gain when converting on the 
specific channel.
+ Valid values are: 1, 2, 4, 8, 16, 32, 64, 128.
+ If this field is left empty, gain of 1 is selected.
+   * adi,odr-hz: The output data rate can be programmed 
from:
+ 9 to 19200 for full power mode (when the master clock 
is 614.4 kHz)
+ 2 to 4800 for mid power mode (when the master clock 
is 153.6 kHz)
+ 1 to 2400 for low power mode (when the master clock 
is 76.8 kHz)
+ If this field is left empty, odr of 9 is selected.
+
+Optional properties:
+   - refin1-supply: refin1 supply can be used as reference for conversion.
+   - refin2-supply: refin2 supply can be used as reference for conversion.
+   - avdd-supply: avdd supply can be used as reference for conversion.
+
+Example:
+   adc@0 {
+   compatible = "adi,ad7124-4";
+   reg = <0>;
+   spi-max-frequency = <500>;
+   interrupts = <25 2>;
+   interrupt-parent = <>;
+   refin1-supply = <_vref>;
+   clocks = <_mclk>;
+   clock-names = "mclk";
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   channel@0 {
+   reg = <0>;
+   adi,diff-channels = <0 1>;
+   adi,reference-select = <0>;
+   adi,gain = <2>;
+   adi,odr-hz = <10>;
+   };
+
+   channel@1 {
+   reg = <1>;
+   adi,bipolar;
+   adi,diff-channels = <2 3>;
+   adi,reference-select = <0>;
+   adi,gain = <4>;
+   adi,odr-hz = <50>;
+   };
+
+   channel@2 {
+ 

[PATCH v3 1/3] iio: ad_sigma_delta: Allow to provide custom data register address

2018-10-29 Thread Stefan Popa
From: Lars-Peter Clausen 

Some newer devices from the Sigma-Delta ADC family do have their data
register at a different address than the current default address. Add a
parameter to the ad_sigma_delta_info struct which allows to override the
default address.

Signed-off-by: Lars-Peter Clausen 
Signed-off-by: Stefan Popa 
---
Changes in v2:
- Added this commit.
Changes in v3:
- Nothing changed.

 drivers/iio/adc/ad_sigma_delta.c   | 22 +-
 include/linux/iio/adc/ad_sigma_delta.h |  3 +++
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index fc95107..ff5f2da 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -278,6 +278,7 @@ int ad_sigma_delta_single_conversion(struct iio_dev 
*indio_dev,
 {
struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
unsigned int sample, raw_sample;
+   unsigned int data_reg;
int ret = 0;
 
if (iio_buffer_enabled(indio_dev))
@@ -305,7 +306,12 @@ int ad_sigma_delta_single_conversion(struct iio_dev 
*indio_dev,
if (ret < 0)
goto out;
 
-   ret = ad_sd_read_reg(sigma_delta, AD_SD_REG_DATA,
+   if (sigma_delta->info->data_reg != 0)
+   data_reg = sigma_delta->info->data_reg;
+   else
+   data_reg = AD_SD_REG_DATA;
+
+   ret = ad_sd_read_reg(sigma_delta, data_reg,
DIV_ROUND_UP(chan->scan_type.realbits + chan->scan_type.shift, 
8),
_sample);
 
@@ -392,6 +398,7 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
unsigned int reg_size;
+   unsigned int data_reg;
uint8_t data[16];
int ret;
 
@@ -401,18 +408,23 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
indio_dev->channels[0].scan_type.shift;
reg_size = DIV_ROUND_UP(reg_size, 8);
 
+   if (sigma_delta->info->data_reg != 0)
+   data_reg = sigma_delta->info->data_reg;
+   else
+   data_reg = AD_SD_REG_DATA;
+
switch (reg_size) {
case 4:
case 2:
case 1:
-   ret = ad_sd_read_reg_raw(sigma_delta, AD_SD_REG_DATA,
-   reg_size, [0]);
+   ret = ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size,
+   [0]);
break;
case 3:
/* We store 24 bit samples in a 32 bit word. Keep the upper
 * byte set to zero. */
-   ret = ad_sd_read_reg_raw(sigma_delta, AD_SD_REG_DATA,
-   reg_size, [1]);
+   ret = ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size,
+   [1]);
break;
}
 
diff --git a/include/linux/iio/adc/ad_sigma_delta.h 
b/include/linux/iio/adc/ad_sigma_delta.h
index 730ead1..7e84351 100644
--- a/include/linux/iio/adc/ad_sigma_delta.h
+++ b/include/linux/iio/adc/ad_sigma_delta.h
@@ -39,6 +39,8 @@ struct iio_dev;
  * if there is just one read-only sample data shift register.
  * @addr_shift: Shift of the register address in the communications register.
  * @read_mask: Mask for the communications register having the read bit set.
+ * @data_reg: Address of the data register, if 0 the default address of 0x3 
will
+ *   be used.
  */
 struct ad_sigma_delta_info {
int (*set_channel)(struct ad_sigma_delta *, unsigned int channel);
@@ -47,6 +49,7 @@ struct ad_sigma_delta_info {
bool has_registers;
unsigned int addr_shift;
unsigned int read_mask;
+   unsigned int data_reg;
 };
 
 /**
-- 
2.7.4



[PATCH v3 2/3] iio: adc: Add ad7124 support

2018-10-29 Thread Stefan Popa
The ad7124-4 and ad7124-8 are a family of 4 and 8 channel sigma-delta ADCs
with 24-bit precision and reference.

Three power modes are available which in turn affect the output data rate:
 * Full power: 9.38 SPS to 19,200 SPS
 * Mid power: 2.34 SPS to 4800 SPS
 * Low power: 1.17 SPS to 2400 SPS

The ad7124-4 can be configured to have four differential inputs, while
ad7124-8 can have 8. Moreover, ad7124 also supports per channel
configuration. Each configuration consists of gain, reference source,
output data rate and bipolar/unipolar configuration.

Datasheets:
Link: 
http://www.analog.com/media/en/technical-documentation/data-sheets/AD7124-4.pdf
Link: 
http://www.analog.com/media/en/technical-documentation/data-sheets/ad7124-8.pdf

Signed-off-by: Stefan Popa 
---
Changes in v2:
- Added this commit.
Changes in v3:
- Removed channel, address, scan_index and shift fields from
  ad7124_channel_template.
- Added a sanity check for val2 in ad7124_write_raw().
- Used the "reg" property to get the channel address and 
"adi,diff-channels"
  for the differential pins. The "adi,channel-number" property was 
removed.
- When calling regulator_get_optional, the probe is given up in case of 
error,
  but continues in case of -ENODEV.
- clk_disable_unprepare() is called before 
ad_sd_cleanup_buffer_and_trigger
  in ad7124_remove().

 MAINTAINERS  |   7 +
 drivers/iio/adc/Kconfig  |  11 +
 drivers/iio/adc/Makefile |   1 +
 drivers/iio/adc/ad7124.c | 648 +++
 4 files changed, 667 insertions(+)
 create mode 100644 drivers/iio/adc/ad7124.c

diff --git a/MAINTAINERS b/MAINTAINERS
index f642044..3a1bfcb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -839,6 +839,13 @@ S: Supported
 F: drivers/iio/dac/ad5758.c
 F: Documentation/devicetree/bindings/iio/dac/ad5758.txt
 
+ANALOG DEVICES INC AD7124 DRIVER
+M: Stefan Popa 
+L: linux-...@vger.kernel.org
+W: http://ez.analog.com/community/linux-device-drivers
+S: Supported
+F: drivers/iio/adc/ad7124.c
+
 ANALOG DEVICES INC AD9389B DRIVER
 M: Hans Verkuil 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index a52fea8..148a10f 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -10,6 +10,17 @@ config AD_SIGMA_DELTA
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
 
+config AD7124
+   tristate "Analog Devices AD7124 and similar sigma-delta ADCs driver"
+   depends on SPI_MASTER
+   select AD_SIGMA_DELTA
+   help
+ Say yes here to build support for Analog Devices AD7124-4 and AD7124-8
+ SPI analog to digital converters (ADC).
+
+ To compile this driver as a module, choose M here: the module will be
+ called ad7124.
+
 config AD7266
tristate "Analog Devices AD7265/AD7266 ADC driver"
depends on SPI_MASTER
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index a6e6a0b..76168b2 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -5,6 +5,7 @@
 
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
+obj-$(CONFIG_AD7124) += ad7124.o
 obj-$(CONFIG_AD7266) += ad7266.o
 obj-$(CONFIG_AD7291) += ad7291.o
 obj-$(CONFIG_AD7298) += ad7298.o
diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c
new file mode 100644
index 000..0660135
--- /dev/null
+++ b/drivers/iio/adc/ad7124.c
@@ -0,0 +1,648 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * AD7124 SPI ADC driver
+ *
+ * Copyright 2018 Analog Devices Inc.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+/* AD7124 registers */
+#define AD7124_COMMS   0x00
+#define AD7124_STATUS  0x00
+#define AD7124_ADC_CONTROL 0x01
+#define AD7124_DATA0x02
+#define AD7124_IO_CONTROL_10x03
+#define AD7124_IO_CONTROL_20x04
+#define AD7124_ID  0x05
+#define AD7124_ERROR   0x06
+#define AD7124_ERROR_EN0x07
+#define AD7124_MCLK_COUNT  0x08
+#define AD7124_CHANNEL(x)  (0x09 + (x))
+#define AD7124_CONFIG(x)   (0x19 + (x))
+#define AD7124_FILTER(x)   (0x21 + (x))
+#define AD7124_OFFSET(x)   (0x29 + (x))
+#define AD7124_GAIN(x) (0x31 + (x))
+
+/* AD7124_STATUS */
+#define AD7124_STATUS_POR_FLAG_MSK BIT(4)
+
+/* AD7124_ADC_CONTROL */
+#define AD7124_ADC_CTRL_PWR_MSKGENMASK(7, 6)
+#define AD7124_ADC_CTRL_PWR(x) FIELD_PREP(AD7124_ADC_CTRL_PWR_MSK, x)
+#define AD7124_ADC_CTRL_MODE_MSK   GENMASK(5, 2)
+#define AD7124_ADC_CTRL_MODE(x)FIELD_PREP(AD7124_ADC_CTRL_MODE_MSK, x)
+
+/* 

[PATCH v5 4/4] dt-bindings: iio: adc: Add docs for ad7124

2018-11-13 Thread Stefan Popa
Add support for Analog Devices AD7124 4-channels and 8-channels ADC.

Signed-off-by: Stefan Popa 
---
Changes in v2:
- Nothing changed.
Changes in v3:
- Removed the "adi,channels" property.
- Used the "reg" property to get the channel number and 
"adi,diff-channels"
  for the differential pins. The "adi,channel-number" property was 
removed.
- adi,bipolar is of boolean type.
Changes in v4:
- Used the bipolar and diff-channels properties defined in the new 
adc.txt doc.
Changes in v5:
- Removed the gain and odr properties from the example.

 .../devicetree/bindings/iio/adc/adi,ad7124.txt | 75 ++
 MAINTAINERS|  1 +
 2 files changed, 76 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt

diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt 
b/Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt
new file mode 100644
index 000..416273d
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt
@@ -0,0 +1,75 @@
+Analog Devices AD7124 ADC device driver
+
+Required properties for the AD7124:
+   - compatible: Must be one of "adi,ad7124-4" or "adi,ad7124-8"
+   - reg: SPI chip select number for the device
+   - spi-max-frequency: Max SPI frequency to use
+   see: Documentation/devicetree/bindings/spi/spi-bus.txt
+   - clocks: phandle to the master clock (mclk)
+   see: Documentation/devicetree/bindings/clock/clock-bindings.txt
+   - clock-names: Must be "mclk".
+   - interrupts: IRQ line for the ADC
+   see: 
Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+
+ Required properties:
+   * #address-cells: Must be 1.
+   * #size-cells: Must be 0.
+
+ Subnode(s) represent the external channels which are connected to the 
ADC.
+ Each subnode represents one channel and has the following properties:
+   Required properties:
+   * reg: The channel number. It can have up to 4 channels 
on ad7124-4
+ and 8 channels on ad7124-8, numbered from 0 to 15.
+   * diff-channels: see: 
Documentation/devicetree/bindings/iio/adc/adc.txt
+
+   Optional properties:
+   * bipolar: see: 
Documentation/devicetree/bindings/iio/adc/adc.txt
+   * adi,reference-select: Select the reference source to 
use when
+ converting on the the specific channel. Valid values 
are:
+ 0: REFIN1(+)/REFIN1(−).
+ 1: REFIN2(+)/REFIN2(−).
+ 3: AVDD
+ If this field is left empty, internal reference is 
selected.
+
+Optional properties:
+   - refin1-supply: refin1 supply can be used as reference for conversion.
+   - refin2-supply: refin2 supply can be used as reference for conversion.
+   - avdd-supply: avdd supply can be used as reference for conversion.
+
+Example:
+   adc@0 {
+   compatible = "adi,ad7124-4";
+   reg = <0>;
+   spi-max-frequency = <500>;
+   interrupts = <25 2>;
+   interrupt-parent = <>;
+   refin1-supply = <_vref>;
+   clocks = <_mclk>;
+   clock-names = "mclk";
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   channel@0 {
+   reg = <0>;
+   diff-channels = <0 1>;
+   adi,reference-select = <0>;
+   };
+
+   channel@1 {
+   reg = <1>;
+   bipolar;
+   diff-channels = <2 3>;
+   adi,reference-select = <0>;
+   };
+
+   channel@2 {
+   reg = <2>;
+   diff-channels = <4 5>;
+   };
+
+   channel@3 {
+   reg = <3>;
+   diff-channels = <6 7>;
+   };
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 3a1bfcb..f2fa508 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -845,6 +845,7 @@ L:  linux-...@vger.kernel.org
 W: http://ez.analog.com/community/linux-device-drivers
 S: Supported
 F: drivers/iio/adc/ad7124.c
+F: Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt
 
 ANALOG DEVICES INC AD9389B DRIVER
 M: Hans Verkuil 
-- 
2.7.4



[PATCH v5 2/4] dt-bindings: iio: adc: Add common ADCs properties to a separate file

2018-11-13 Thread Stefan Popa
There are several ADC drivers that depend on the same device tree
bindings. Rather than continue to duplicate the properties, this patch
adds a common adc binding document that can be referenced. For beginning,
only two properties are documented.

Signed-off-by: Stefan Popa 
---
Changes in v2, v3:
- N/A.
Changes in v4:
- Added this commit.
Changes in v5:
- Nothing changed.

 Documentation/devicetree/bindings/iio/adc/adc.txt | 23 +++
 1 file changed, 23 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/adc.txt

diff --git a/Documentation/devicetree/bindings/iio/adc/adc.txt 
b/Documentation/devicetree/bindings/iio/adc/adc.txt
new file mode 100644
index 000..5bbaa33
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/adc.txt
@@ -0,0 +1,23 @@
+Common ADCs properties
+
+Optional properties for child nodes:
+- bipolar : Boolean, if set the channel is used in bipolar mode.
+- diff-channels : Differential channels muxed for this ADC. The first value
+   specifies the positive input pin, the second value the negative
+   input pin.
+
+Example:
+   adc@0 {
+   compatible = "some,adc";
+   ...
+   channel@0 {
+   bipolar;
+   diff-channels = <0 1>;
+   ...
+   };
+
+   channel@1 {
+   diff-channels = <2 3>;
+   ...
+   };
+   };
-- 
2.7.4



  1   2   3   4   >