staging:iio:cdc:ad7150: Timeout register covers both directions so both need updating
authorJonathan Cameron <Jonathan.Cameron@huawei.com>
Sun, 14 Mar 2021 18:14:51 +0000 (18:14 +0000)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Wed, 7 Apr 2021 07:36:36 +0000 (08:36 +0100)
The timeout is treated as one single value, but the datasheet describes
it as two 4 bit values, one for each direction of event.
As such change the driver to support the separate directions.
Also add limit checking to ensure it fits within the 4 bits.

Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
Link: https://lore.kernel.org/r/20210314181511.531414-5-jic23@kernel.org
drivers/staging/iio/cdc/ad7150.c

index d6a7bfd94f1c4918bf1336075dea17afba12ecbb..0dce1b8ce76d8bc6b730aaf047fb451537d7c749 100644 (file)
@@ -49,6 +49,8 @@
 /* AD7150 masks */
 #define AD7150_THRESHTYPE_MSK                  GENMASK(6, 5)
 
+#define AD7150_CH_TIMEOUT_RECEDING             GENMASK(3, 0)
+#define AD7150_CH_TIMEOUT_APPROACHING          GENMASK(7, 4)
 /**
  * struct ad7150_chip_info - instance specific chip data
  * @client: i2c client for this device
@@ -59,7 +61,9 @@
  *     from 'average' value.
  * @thresh_timeout: a timeout, in samples from the moment an
  *     adaptive threshold event occurs to when the average
- *     value jumps to current value.
+ *     value jumps to current value.  Note made up of two fields,
+ *      3:0 are for timeout receding - applies if below lower threshold
+ *      7:4 are for timeout approaching - applies if above upper threshold
  * @old_state: store state from previous event, allowing confirmation
  *     of new condition.
  * @conversion_mode: the current conversion mode.
@@ -191,7 +195,14 @@ static int ad7150_write_event_params(struct iio_dev *indio_dev,
                if (ret)
                        return ret;
 
-               timeout = chip->thresh_timeout[rising][chan];
+               /*
+                * Single timeout register contains timeouts for both
+                * directions.
+                */
+               timeout = FIELD_PREP(AD7150_CH_TIMEOUT_APPROACHING,
+                                    chip->thresh_timeout[1][chan]);
+               timeout |= FIELD_PREP(AD7150_CH_TIMEOUT_RECEDING,
+                                     chip->thresh_timeout[0][chan]);
                return i2c_smbus_write_byte_data(chip->client,
                                                 ad7150_addresses[chan][5],
                                                 timeout);
@@ -365,6 +376,9 @@ static ssize_t ad7150_store_timeout(struct device *dev,
        if (ret < 0)
                return ret;
 
+       if (data > GENMASK(3, 0))
+               return -EINVAL;
+
        mutex_lock(&chip->state_lock);
        switch (type) {
        case IIO_EV_TYPE_THRESH_ADAPTIVE: