staging:iio:ad7606: Factor out common code between periodic and one-shot capture
authorLars-Peter Clausen <lars@metafoo.de>
Wed, 19 Oct 2016 17:07:02 +0000 (19:07 +0200)
committerJonathan Cameron <jic23@kernel.org>
Sun, 23 Oct 2016 18:34:15 +0000 (19:34 +0100)
Both the periodic buffer based and one-shot sysfs based capture methods
share a large portion of their code. Factor this out into a common helper
function.

Also provide a comment that better explains in more detail what is going on
in the capture function.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
drivers/staging/iio/adc/ad7606.h
drivers/staging/iio/adc/ad7606_core.c
drivers/staging/iio/adc/ad7606_ring.c

index 129f94e57c238a472d95ed467064f73153cfd280..2257bdbcd73a48daa1e9b94a21a43fd335bd8d06 100644 (file)
@@ -84,6 +84,7 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq,
                              const struct ad7606_bus_ops *bops);
 int ad7606_remove(struct iio_dev *indio_dev, int irq);
 int ad7606_reset(struct ad7606_state *st);
+int ad7606_read_samples(struct ad7606_state *st);
 
 enum ad7606_supported_device_ids {
        ID_AD7606_8,
index 7c093e2a0faf1f8ad1855378712bd25f525b3b9c..4ce103a16eeb50e736f28d4462f78cb91b34d203 100644 (file)
@@ -36,6 +36,39 @@ int ad7606_reset(struct ad7606_state *st)
        return -ENODEV;
 }
 
+int ad7606_read_samples(struct ad7606_state *st)
+{
+       unsigned int num = st->chip_info->num_channels;
+       u16 *data = st->data;
+       int ret;
+
+       /*
+        * The frstdata signal is set to high while and after reading the sample
+        * of the first channel and low for all other channels. This can be used
+        * to check that the incoming data is correctly aligned. During normal
+        * operation the data should never become unaligned, but some glitch or
+        * electrostatic discharge might cause an extra read or clock cycle.
+        * Monitoring the frstdata signal allows to recover from such failure
+        * situations.
+        */
+
+       if (gpio_is_valid(st->pdata->gpio_frstdata)) {
+               ret = st->bops->read_block(st->dev, 1, data);
+               if (ret)
+                       return ret;
+
+               if (!gpio_get_value(st->pdata->gpio_frstdata)) {
+                       ad7606_reset(st);
+                       return -EIO;
+               }
+
+               data++;
+               num--;
+       }
+
+       return st->bops->read_block(st->dev, num, data);
+}
+
 static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch)
 {
        struct ad7606_state *st = iio_priv(indio_dev);
@@ -48,28 +81,9 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch)
        if (ret)
                goto error_ret;
 
-       if (gpio_is_valid(st->pdata->gpio_frstdata)) {
-               ret = st->bops->read_block(st->dev, 1, st->data);
-               if (ret)
-                       goto error_ret;
-               if (!gpio_get_value(st->pdata->gpio_frstdata)) {
-                       /* This should never happen */
-                       ad7606_reset(st);
-                       ret = -EIO;
-                       goto error_ret;
-               }
-               ret = st->bops->read_block(st->dev,
-                       st->chip_info->num_channels - 1, &st->data[1]);
-               if (ret)
-                       goto error_ret;
-       } else {
-               ret = st->bops->read_block(st->dev,
-                       st->chip_info->num_channels, st->data);
-               if (ret)
-                       goto error_ret;
-       }
-
-       ret = st->data[ch];
+       ret = ad7606_read_samples(st);
+       if (ret == 0)
+               ret = st->data[ch];
 
 error_ret:
        gpio_set_value(st->pdata->gpio_convst, 0);
index 7fa4ccccb72761ef72ccdbb257e68dfd99922967..b7bf0cf87b10d88042673d29b2e098ab91ef7307 100644 (file)
@@ -48,33 +48,11 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s)
        struct iio_dev *indio_dev = iio_priv_to_dev(st);
        int ret;
 
-       if (gpio_is_valid(st->pdata->gpio_frstdata)) {
-               ret = st->bops->read_block(st->dev, 1, st->data);
-               if (ret)
-                       goto done;
-               if (!gpio_get_value(st->pdata->gpio_frstdata)) {
-                       /* This should never happen. However
-                        * some signal glitch caused by bad PCB desgin or
-                        * electrostatic discharge, could cause an extra read
-                        * or clock. This allows recovery.
-                        */
-                       ad7606_reset(st);
-                       goto done;
-               }
-               ret = st->bops->read_block(st->dev,
-                       st->chip_info->num_channels - 1, st->data + 1);
-               if (ret)
-                       goto done;
-       } else {
-               ret = st->bops->read_block(st->dev,
-                       st->chip_info->num_channels, st->data);
-               if (ret)
-                       goto done;
-       }
+       ret = ad7606_read_samples(st);
+       if (ret == 0)
+               iio_push_to_buffers_with_timestamp(indio_dev, st->data,
+                                                  iio_get_time_ns(indio_dev));
 
-       iio_push_to_buffers_with_timestamp(indio_dev, st->data,
-                                          iio_get_time_ns(indio_dev));
-done:
        gpio_set_value(st->pdata->gpio_convst, 0);
        iio_trigger_notify_done(indio_dev->trig);
 }