[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 int1_bitmask,
+  

[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 int1_bitmask,
+