Add FIFO watermark configuration and evaluation. Let a watermark to be configured. Evaluate the interrupt accordingly. Read out the FIFO content and push the values to the IIO channel. Signed-off-by: Lothar Rubusch <l.rubusch@xxxxxxxxx> --- drivers/iio/accel/adxl313.h | 1 + drivers/iio/accel/adxl313_core.c | 60 ++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/drivers/iio/accel/adxl313.h b/drivers/iio/accel/adxl313.h index 4cb1fe1f2616..9c7aedf7da7a 100644 --- a/drivers/iio/accel/adxl313.h +++ b/drivers/iio/accel/adxl313.h @@ -89,6 +89,7 @@ struct adxl313_data { const struct adxl313_chip_info *chip_info; struct mutex lock; /* lock to protect transf_buf */ int irq; + u8 watermark; u8 fifo_mode; __le16 transf_buf __aligned(IIO_DMA_MINALIGN); __le16 fifo_buf[ADXL313_NUM_AXIS * ADXL313_FIFO_SIZE + 1]; diff --git a/drivers/iio/accel/adxl313_core.c b/drivers/iio/accel/adxl313_core.c index 574962a8f35d..0a93af89ba19 100644 --- a/drivers/iio/accel/adxl313_core.c +++ b/drivers/iio/accel/adxl313_core.c @@ -374,6 +374,25 @@ static int adxl313_write_raw(struct iio_dev *indio_dev, } } +static int adxl313_set_watermark(struct iio_dev *indio_dev, unsigned int value) +{ + struct adxl313_data *data = iio_priv(indio_dev); + const unsigned int fifo_mask = 0x1f, watermark_mask = 0x02; + int ret; + + value = min(value, ADXL313_FIFO_SIZE - 1); + + ret = regmap_update_bits(data->regmap, ADXL313_REG_FIFO_CTL, + fifo_mask, value); + if (ret) + return ret; + + data->watermark = value; + + return regmap_update_bits(data->regmap, ADXL313_REG_INT_ENABLE, + watermark_mask, ADXL313_INT_WATERMARK); +} + static int adxl313_get_samples(struct adxl313_data *data) { unsigned int regval = 0; @@ -400,6 +419,8 @@ static int adxl313_set_fifo(struct adxl313_data *data) return ret; ret = regmap_write(data->regmap, ADXL313_REG_FIFO_CTL, + FIELD_PREP(ADXL313_REG_FIFO_CTL_SAMPLES_MSK, + data->watermark) | FIELD_PREP(ADXL313_REG_FIFO_CTL_MODE_MSK, data->fifo_mode)); @@ -467,6 +488,41 @@ static const struct iio_buffer_setup_ops adxl313_buffer_ops = { .predisable = adxl313_buffer_predisable, }; +static int adxl313_fifo_push(struct iio_dev *indio_dev, int samples) +{ + struct adxl313_data *data = iio_priv(indio_dev); + int i, ret; + + if (samples <= 0) + return -EINVAL; + + ret = adxl313_fifo_transfer(data, samples); + if (ret) + return ret; + + for (i = 0; i < ADXL313_NUM_AXIS * samples; i += ADXL313_NUM_AXIS) + iio_push_to_buffers(indio_dev, &data->fifo_buf[i]); + + return 0; +} + +static int adxl313_push_event(struct iio_dev *indio_dev, int int_stat) +{ + struct adxl313_data *data = iio_priv(indio_dev); + int samples; + int ret = -ENOENT; + + if (FIELD_GET(ADXL313_INT_WATERMARK, int_stat)) { + samples = adxl313_get_samples(data); + if (samples < 0) + return -EINVAL; + + ret = adxl313_fifo_push(indio_dev, samples); + } + + return ret; +} + static irqreturn_t adxl313_irq_handler(int irq, void *p) { struct iio_dev *indio_dev = p; @@ -476,6 +532,9 @@ static irqreturn_t adxl313_irq_handler(int irq, void *p) if (regmap_read(data->regmap, ADXL313_REG_INT_SOURCE, &int_stat)) return IRQ_NONE; + if (adxl313_push_event(indio_dev, int_stat)) + goto err; + if (FIELD_GET(ADXL313_INT_OVERRUN, int_stat)) goto err; @@ -500,6 +559,7 @@ static const struct iio_info adxl313_info = { .read_raw = adxl313_read_raw, .write_raw = adxl313_write_raw, .read_avail = adxl313_read_freq_avail, + .hwfifo_set_watermark = adxl313_set_watermark, .debugfs_reg_access = &adxl313_reg_access, }; -- 2.39.5