Merge tag 'iio-for-3.8e' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio...
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Nov 2012 20:32:57 +0000 (12:32 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Nov 2012 20:32:57 +0000 (12:32 -0800)
From Jonathan:

  "Fifth round of new IIO drivers, cleanups and fixes for the 3.8 cycle.

  Here we have a number of minor fixes.
  * a quirk for the hid sensor driver should be a boolean option.
  * return an error for a failed memdup in the hid sensor driver.
  * Fix a return value in adt7410.
  * A double free in the IIO event infrastructure.
  * Disabling interrupts in tsl2563 was wrong (never been correct!)
  * Incorrect signature for the iio_buffer_register stub
  * Incorrect return for isl29018 write_raw callback.
  * A number of minor fixes as part of the various rework series.

  New drivers and major rework.
  * Introduce and use extensively an adis library for numerous spi
    Analog Devices mems sensors.  This then moves out of staging.
  * Lots of new stuff then added to this library to support newer
    sensors.
  * New drivers for ADIS16136 and ADIS16480 and similar.
  * Core support for barometric pressure sensors.
  * ad7298 cleanup and move out of staging.

  The bulk of this is from Lars-Peter Clausen.  He's been rather
  busy!"

65 files changed:
Documentation/ABI/testing/sysfs-bus-iio
drivers/iio/Kconfig
drivers/iio/Makefile
drivers/iio/accel/hid-sensor-accel-3d.c
drivers/iio/adc/Kconfig
drivers/iio/adc/Makefile
drivers/iio/adc/ad7298.c [new file with mode: 0644]
drivers/iio/common/hid-sensors/Kconfig
drivers/iio/common/hid-sensors/hid-sensor-trigger.c
drivers/iio/gyro/Kconfig
drivers/iio/gyro/Makefile
drivers/iio/gyro/adis16136.c [new file with mode: 0644]
drivers/iio/gyro/hid-sensor-gyro-3d.c
drivers/iio/imu/Kconfig [new file with mode: 0644]
drivers/iio/imu/Makefile [new file with mode: 0644]
drivers/iio/imu/adis.c [new file with mode: 0644]
drivers/iio/imu/adis16480.c [new file with mode: 0644]
drivers/iio/imu/adis_buffer.c [new file with mode: 0644]
drivers/iio/imu/adis_trigger.c [new file with mode: 0644]
drivers/iio/industrialio-core.c
drivers/iio/industrialio-event.c
drivers/iio/light/hid-sensor-als.c
drivers/iio/magnetometer/hid-sensor-magn-3d.c
drivers/staging/iio/accel/Kconfig
drivers/staging/iio/accel/Makefile
drivers/staging/iio/accel/adis16201.h
drivers/staging/iio/accel/adis16201_core.c
drivers/staging/iio/accel/adis16201_ring.c [deleted file]
drivers/staging/iio/accel/adis16201_trigger.c [deleted file]
drivers/staging/iio/accel/adis16203.h
drivers/staging/iio/accel/adis16203_core.c
drivers/staging/iio/accel/adis16203_ring.c [deleted file]
drivers/staging/iio/accel/adis16203_trigger.c [deleted file]
drivers/staging/iio/accel/adis16204.h
drivers/staging/iio/accel/adis16204_core.c
drivers/staging/iio/accel/adis16204_ring.c [deleted file]
drivers/staging/iio/accel/adis16204_trigger.c [deleted file]
drivers/staging/iio/accel/adis16209.h
drivers/staging/iio/accel/adis16209_core.c
drivers/staging/iio/accel/adis16209_ring.c [deleted file]
drivers/staging/iio/accel/adis16209_trigger.c [deleted file]
drivers/staging/iio/accel/adis16220.h
drivers/staging/iio/accel/adis16220_core.c
drivers/staging/iio/accel/adis16240.h
drivers/staging/iio/accel/adis16240_core.c
drivers/staging/iio/accel/adis16240_ring.c [deleted file]
drivers/staging/iio/accel/adis16240_trigger.c [deleted file]
drivers/staging/iio/adc/Kconfig
drivers/staging/iio/adc/Makefile
drivers/staging/iio/adc/ad7298.h [deleted file]
drivers/staging/iio/adc/ad7298_core.c [deleted file]
drivers/staging/iio/adc/ad7298_ring.c [deleted file]
drivers/staging/iio/adc/adt7410.c
drivers/staging/iio/gyro/Makefile
drivers/staging/iio/gyro/adis16260.h
drivers/staging/iio/gyro/adis16260_core.c
drivers/staging/iio/gyro/adis16260_ring.c [deleted file]
drivers/staging/iio/gyro/adis16260_trigger.c [deleted file]
drivers/staging/iio/light/isl29018.c
drivers/staging/iio/light/tsl2563.c
include/linux/iio/buffer.h
include/linux/iio/iio.h
include/linux/iio/imu/adis.h [new file with mode: 0644]
include/linux/iio/types.h
include/linux/platform_data/ad7298.h [new file with mode: 0644]

index 2f06d40fe07d4d5c293561d4187a622cdd1bc05f..2e33dc6b23463046614586deba015d3f1c1ebb66 100644 (file)
@@ -189,6 +189,14 @@ Description:
                A computed peak value based on the sum squared magnitude of
                the underlying value in the specified directions.
 
+What:          /sys/bus/iio/devices/iio:deviceX/in_pressureY_raw
+What:          /sys/bus/iio/devices/iio:deviceX/in_pressure_raw
+KernelVersion: 3.8
+Contact:       linux-iio@vger.kernel.org
+Description:
+               Raw pressure measurement from channel Y. Units after
+               application of scale and offset are kilopascal.
+
 What:          /sys/bus/iio/devices/iio:deviceX/in_accel_offset
 What:          /sys/bus/iio/devices/iio:deviceX/in_accel_x_offset
 What:          /sys/bus/iio/devices/iio:deviceX/in_accel_y_offset
@@ -197,6 +205,8 @@ What:               /sys/bus/iio/devices/iio:deviceX/in_voltageY_offset
 What:          /sys/bus/iio/devices/iio:deviceX/in_voltage_offset
 What:          /sys/bus/iio/devices/iio:deviceX/in_tempY_offset
 What:          /sys/bus/iio/devices/iio:deviceX/in_temp_offset
+What:          /sys/bus/iio/devices/iio:deviceX/in_pressureY_offset
+What:          /sys/bus/iio/devices/iio:deviceX/in_pressure_offset
 KernelVersion: 2.6.35
 Contact:       linux-iio@vger.kernel.org
 Description:
@@ -226,6 +236,8 @@ What:               /sys/bus/iio/devices/iio:deviceX/in_magn_scale
 What:          /sys/bus/iio/devices/iio:deviceX/in_magn_x_scale
 What:          /sys/bus/iio/devices/iio:deviceX/in_magn_y_scale
 What:          /sys/bus/iio/devices/iio:deviceX/in_magn_z_scale
+What:          /sys/bus/iio/devices/iio:deviceX/in_pressureY_scale
+What:          /sys/bus/iio/devices/iio:deviceX/in_pressure_scale
 KernelVersion: 2.6.35
 Contact:       linux-iio@vger.kernel.org
 Description:
@@ -245,6 +257,8 @@ What:               /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias
 What:          /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias
 What:          /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibbias
 What:          /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibbias
+What:          /sys/bus/iio/devices/iio:deviceX/in_pressureY_calibbias
+What:          /sys/bus/iio/devices/iio:deviceX/in_pressure_calibbias
 KernelVersion: 2.6.35
 Contact:       linux-iio@vger.kernel.org
 Description:
@@ -262,6 +276,8 @@ What                /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibscale
 What           /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibscale
 what           /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibscale
 what           /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibscale
+What:          /sys/bus/iio/devices/iio:deviceX/in_pressureY_calibscale
+What:          /sys/bus/iio/devices/iio:deviceX/in_pressure_calibscale
 KernelVersion: 2.6.35
 Contact:       linux-iio@vger.kernel.org
 Description:
@@ -275,6 +291,8 @@ What:               /sys/.../iio:deviceX/in_voltage-voltage_scale_available
 What:          /sys/.../iio:deviceX/out_voltageX_scale_available
 What:          /sys/.../iio:deviceX/out_altvoltageX_scale_available
 What:          /sys/.../iio:deviceX/in_capacitance_scale_available
+What:          /sys/.../iio:deviceX/in_pressure_scale_available
+What:          /sys/.../iio:deviceX/in_pressureY_scale_available
 KernelVersion: 2.6.35
 Contact:       linux-iio@vger.kernel.org
 Description:
@@ -694,6 +712,8 @@ What:               /sys/.../buffer/scan_elements/in_voltageY_en
 What:          /sys/.../buffer/scan_elements/in_voltageY-voltageZ_en
 What:          /sys/.../buffer/scan_elements/in_incli_x_en
 What:          /sys/.../buffer/scan_elements/in_incli_y_en
+What:          /sys/.../buffer/scan_elements/in_pressureY_en
+What:          /sys/.../buffer/scan_elements/in_pressure_en
 KernelVersion: 2.6.37
 Contact:       linux-iio@vger.kernel.org
 Description:
@@ -707,6 +727,8 @@ What:               /sys/.../buffer/scan_elements/in_voltageY_type
 What:          /sys/.../buffer/scan_elements/in_voltage_type
 What:          /sys/.../buffer/scan_elements/in_voltageY_supply_type
 What:          /sys/.../buffer/scan_elements/in_timestamp_type
+What:          /sys/.../buffer/scan_elements/in_pressureY_type
+What:          /sys/.../buffer/scan_elements/in_pressure_type
 KernelVersion: 2.6.37
 Contact:       linux-iio@vger.kernel.org
 Description:
@@ -751,6 +773,8 @@ What:               /sys/.../buffer/scan_elements/in_magn_z_index
 What:          /sys/.../buffer/scan_elements/in_incli_x_index
 What:          /sys/.../buffer/scan_elements/in_incli_y_index
 What:          /sys/.../buffer/scan_elements/in_timestamp_index
+What:          /sys/.../buffer/scan_elements/in_pressureY_index
+What:          /sys/.../buffer/scan_elements/in_pressure_index
 KernelVersion: 2.6.37
 Contact:       linux-iio@vger.kernel.org
 Description:
index 65ae734c607d0fdd162d39db0784d19f70f3902b..b2f963be39937d2f6fe0775f5c9510866e69f4ea 100644 (file)
@@ -63,11 +63,12 @@ config IIO_CONSUMERS_PER_TRIGGER
 source "drivers/iio/accel/Kconfig"
 source "drivers/iio/adc/Kconfig"
 source "drivers/iio/amplifiers/Kconfig"
-source "drivers/iio/light/Kconfig"
-source "drivers/iio/frequency/Kconfig"
-source "drivers/iio/dac/Kconfig"
 source "drivers/iio/common/Kconfig"
+source "drivers/iio/dac/Kconfig"
+source "drivers/iio/frequency/Kconfig"
 source "drivers/iio/gyro/Kconfig"
+source "drivers/iio/imu/Kconfig"
+source "drivers/iio/light/Kconfig"
 source "drivers/iio/magnetometer/Kconfig"
 
 endif # IIO
index 31d76a07ec65056afc59483ae19ee7001423b6c8..a0e8cdd67e4ddef91083600d1ea80b7e1ea069dd 100644 (file)
@@ -14,9 +14,10 @@ obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
 obj-y += accel/
 obj-y += adc/
 obj-y += amplifiers/
-obj-y += light/
-obj-y += frequency/
-obj-y += dac/
 obj-y += common/
+obj-y += dac/
 obj-y += gyro/
+obj-y += frequency/
+obj-y += imu/
+obj-y += light/
 obj-y += magnetometer/
index a95cda0e387f6c2781fa663bd020211693671d57..e67bb912bd197b90de0cfccfda2a50041325c52f 100644 (file)
@@ -306,10 +306,10 @@ static int __devinit hid_accel_3d_probe(struct platform_device *pdev)
                goto error_free_dev;
        }
 
-       channels = kmemdup(accel_3d_channels,
-                                       sizeof(accel_3d_channels),
-                                       GFP_KERNEL);
+       channels = kmemdup(accel_3d_channels, sizeof(accel_3d_channels),
+                          GFP_KERNEL);
        if (!channels) {
+               ret = -ENOMEM;
                dev_err(&pdev->dev, "failed to duplicate channels\n");
                goto error_free_dev;
        }
index ef5200a6850e150fbc88820baa69ae343bc463a3..cd5eed60be2836479626c24eea423d588de6e2a7 100644 (file)
@@ -18,6 +18,18 @@ config AD7266
          Say yes here to build support for Analog Devices AD7265 and AD7266
          ADCs.
 
+config AD7298
+       tristate "Analog Devices AD7298 ADC driver"
+       depends on SPI
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
+       help
+         Say yes here to build support for Analog Devices AD7298
+         8 Channel ADC with temperature sensor.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ad7298.
+
 config AD7791
        tristate "Analog Devices AD7791 ADC driver"
        depends on SPI
index 54ac7bbcd01b71523770bce9537f6e1428fd262e..3256dc64a466123539cb2a800f6ed0135fd27066 100644 (file)
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
 obj-$(CONFIG_AD7266) += ad7266.o
+obj-$(CONFIG_AD7298) += ad7298.o
 obj-$(CONFIG_AD7476) += ad7476.o
 obj-$(CONFIG_AD7791) += ad7791.o
 obj-$(CONFIG_AD7887) += ad7887.o
diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c
new file mode 100644 (file)
index 0000000..2364807
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * AD7298 SPI ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#include <linux/platform_data/ad7298.h>
+
+#define AD7298_WRITE   (1 << 15) /* write to the control register */
+#define AD7298_REPEAT  (1 << 14) /* repeated conversion enable */
+#define AD7298_CH(x)   (1 << (13 - (x))) /* channel select */
+#define AD7298_TSENSE  (1 << 5) /* temperature conversion enable */
+#define AD7298_EXTREF  (1 << 2) /* external reference enable */
+#define AD7298_TAVG    (1 << 1) /* temperature sensor averaging enable */
+#define AD7298_PDD     (1 << 0) /* partial power down enable */
+
+#define AD7298_MAX_CHAN                8
+#define AD7298_BITS            12
+#define AD7298_STORAGE_BITS    16
+#define AD7298_INTREF_mV       2500
+
+#define AD7298_CH_TEMP         9
+
+#define RES_MASK(bits) ((1 << (bits)) - 1)
+
+struct ad7298_state {
+       struct spi_device               *spi;
+       struct regulator                *reg;
+       unsigned                        ext_ref;
+       struct spi_transfer             ring_xfer[10];
+       struct spi_transfer             scan_single_xfer[3];
+       struct spi_message              ring_msg;
+       struct spi_message              scan_single_msg;
+       /*
+        * DMA (thus cache coherency maintenance) requires the
+        * transfer buffers to live in their own cache lines.
+        */
+       __be16                          rx_buf[12] ____cacheline_aligned;
+       __be16                          tx_buf[2];
+};
+
+#define AD7298_V_CHAN(index)                                           \
+       {                                                               \
+               .type = IIO_VOLTAGE,                                    \
+               .indexed = 1,                                           \
+               .channel = index,                                       \
+               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |           \
+               IIO_CHAN_INFO_SCALE_SHARED_BIT,                         \
+               .address = index,                                       \
+               .scan_index = index,                                    \
+               .scan_type = {                                          \
+                       .sign = 'u',                                    \
+                       .realbits = 12,                                 \
+                       .storagebits = 16,                              \
+                       .endianness = IIO_BE,                           \
+               },                                                      \
+       }
+
+static const struct iio_chan_spec ad7298_channels[] = {
+       {
+               .type = IIO_TEMP,
+               .indexed = 1,
+               .channel = 0,
+               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+                       IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+                       IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
+               .address = AD7298_CH_TEMP,
+               .scan_index = -1,
+               .scan_type = {
+                       .sign = 's',
+                       .realbits = 32,
+                       .storagebits = 32,
+               },
+       },
+       AD7298_V_CHAN(0),
+       AD7298_V_CHAN(1),
+       AD7298_V_CHAN(2),
+       AD7298_V_CHAN(3),
+       AD7298_V_CHAN(4),
+       AD7298_V_CHAN(5),
+       AD7298_V_CHAN(6),
+       AD7298_V_CHAN(7),
+       IIO_CHAN_SOFT_TIMESTAMP(8),
+};
+
+/**
+ * ad7298_update_scan_mode() setup the spi transfer buffer for the new scan mask
+ **/
+static int ad7298_update_scan_mode(struct iio_dev *indio_dev,
+       const unsigned long *active_scan_mask)
+{
+       struct ad7298_state *st = iio_priv(indio_dev);
+       int i, m;
+       unsigned short command;
+       int scan_count;
+
+       /* Now compute overall size */
+       scan_count = bitmap_weight(active_scan_mask, indio_dev->masklength);
+
+       command = AD7298_WRITE | st->ext_ref;
+
+       for (i = 0, m = AD7298_CH(0); i < AD7298_MAX_CHAN; i++, m >>= 1)
+               if (test_bit(i, active_scan_mask))
+                       command |= m;
+
+       st->tx_buf[0] = cpu_to_be16(command);
+
+       /* build spi ring message */
+       st->ring_xfer[0].tx_buf = &st->tx_buf[0];
+       st->ring_xfer[0].len = 2;
+       st->ring_xfer[0].cs_change = 1;
+       st->ring_xfer[1].tx_buf = &st->tx_buf[1];
+       st->ring_xfer[1].len = 2;
+       st->ring_xfer[1].cs_change = 1;
+
+       spi_message_init(&st->ring_msg);
+       spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg);
+       spi_message_add_tail(&st->ring_xfer[1], &st->ring_msg);
+
+       for (i = 0; i < scan_count; i++) {
+               st->ring_xfer[i + 2].rx_buf = &st->rx_buf[i];
+               st->ring_xfer[i + 2].len = 2;
+               st->ring_xfer[i + 2].cs_change = 1;
+               spi_message_add_tail(&st->ring_xfer[i + 2], &st->ring_msg);
+       }
+       /* make sure last transfer cs_change is not set */
+       st->ring_xfer[i + 1].cs_change = 0;
+
+       return 0;
+}
+
+/**
+ * ad7298_trigger_handler() bh of trigger launched polling to ring buffer
+ *
+ * Currently there is no option in this driver to disable the saving of
+ * timestamps within the ring.
+ **/
+static irqreturn_t ad7298_trigger_handler(int irq, void *p)
+{
+       struct iio_poll_func *pf = p;
+       struct iio_dev *indio_dev = pf->indio_dev;
+       struct ad7298_state *st = iio_priv(indio_dev);
+       s64 time_ns = 0;
+       int b_sent;
+
+       b_sent = spi_sync(st->spi, &st->ring_msg);
+       if (b_sent)
+               goto done;
+
+       if (indio_dev->scan_timestamp) {
+               time_ns = iio_get_time_ns();
+               memcpy((u8 *)st->rx_buf + indio_dev->scan_bytes - sizeof(s64),
+                       &time_ns, sizeof(time_ns));
+       }
+
+       iio_push_to_buffers(indio_dev, (u8 *)st->rx_buf);
+
+done:
+       iio_trigger_notify_done(indio_dev->trig);
+
+       return IRQ_HANDLED;
+}
+
+static int ad7298_scan_direct(struct ad7298_state *st, unsigned ch)
+{
+       int ret;
+       st->tx_buf[0] = cpu_to_be16(AD7298_WRITE | st->ext_ref |
+                                  (AD7298_CH(0) >> ch));
+
+       ret = spi_sync(st->spi, &st->scan_single_msg);
+       if (ret)
+               return ret;
+
+       return be16_to_cpu(st->rx_buf[0]);
+}
+
+static int ad7298_scan_temp(struct ad7298_state *st, int *val)
+{
+       int ret;
+       __be16 buf;
+
+       buf = cpu_to_be16(AD7298_WRITE | AD7298_TSENSE |
+                         AD7298_TAVG | st->ext_ref);
+
+       ret = spi_write(st->spi, (u8 *)&buf, 2);
+       if (ret)
+               return ret;
+
+       buf = cpu_to_be16(0);
+
+       ret = spi_write(st->spi, (u8 *)&buf, 2);
+       if (ret)
+               return ret;
+
+       usleep_range(101, 1000); /* sleep > 100us */
+
+       ret = spi_read(st->spi, (u8 *)&buf, 2);
+       if (ret)
+               return ret;
+
+       *val = sign_extend32(be16_to_cpu(buf), 11);
+
+       return 0;
+}
+
+static int ad7298_get_ref_voltage(struct ad7298_state *st)
+{
+       int vref;
+
+       if (st->ext_ref) {
+               vref = regulator_get_voltage(st->reg);
+               if (vref < 0)
+                       return vref;
+
+               return vref / 1000;
+       } else {
+               return AD7298_INTREF_mV;
+       }
+}
+
+static int ad7298_read_raw(struct iio_dev *indio_dev,
+                          struct iio_chan_spec const *chan,
+                          int *val,
+                          int *val2,
+                          long m)
+{
+       int ret;
+       struct ad7298_state *st = iio_priv(indio_dev);
+
+       switch (m) {
+       case IIO_CHAN_INFO_RAW:
+               mutex_lock(&indio_dev->mlock);
+               if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
+                       ret = -EBUSY;
+               } else {
+                       if (chan->address == AD7298_CH_TEMP)
+                               ret = ad7298_scan_temp(st, val);
+                       else
+                               ret = ad7298_scan_direct(st, chan->address);
+               }
+               mutex_unlock(&indio_dev->mlock);
+
+               if (ret < 0)
+                       return ret;
+
+               if (chan->address != AD7298_CH_TEMP)
+                       *val = ret & RES_MASK(AD7298_BITS);
+
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_SCALE:
+               switch (chan->type) {
+               case IIO_VOLTAGE:
+                       *val = ad7298_get_ref_voltage(st);
+                       *val2 = chan->scan_type.realbits;
+                       return IIO_VAL_FRACTIONAL_LOG2;
+               case IIO_TEMP:
+                       *val = ad7298_get_ref_voltage(st);
+                       *val2 = 10;
+                       return IIO_VAL_FRACTIONAL;
+               default:
+                       return -EINVAL;
+               }
+       case IIO_CHAN_INFO_OFFSET:
+               *val = 1093 - 2732500 / ad7298_get_ref_voltage(st);
+               return IIO_VAL_INT;
+       }
+       return -EINVAL;
+}
+
+static const struct iio_info ad7298_info = {
+       .read_raw = &ad7298_read_raw,
+       .update_scan_mode = ad7298_update_scan_mode,
+       .driver_module = THIS_MODULE,
+};
+
+static int __devinit ad7298_probe(struct spi_device *spi)
+{
+       struct ad7298_platform_data *pdata = spi->dev.platform_data;
+       struct ad7298_state *st;
+       struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+       int ret;
+
+       if (indio_dev == NULL)
+               return -ENOMEM;
+
+       st = iio_priv(indio_dev);
+
+       if (pdata && pdata->ext_ref)
+               st->ext_ref = AD7298_EXTREF;
+
+       if (st->ext_ref) {
+               st->reg = regulator_get(&spi->dev, "vref");
+               if (IS_ERR(st->reg)) {
+                       ret = PTR_ERR(st->reg);
+                       goto error_free;
+               }
+               ret = regulator_enable(st->reg);
+               if (ret)
+                       goto error_put_reg;
+       }
+
+       spi_set_drvdata(spi, indio_dev);
+
+       st->spi = spi;
+
+       indio_dev->name = spi_get_device_id(spi)->name;
+       indio_dev->dev.parent = &spi->dev;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->channels = ad7298_channels;
+       indio_dev->num_channels = ARRAY_SIZE(ad7298_channels);
+       indio_dev->info = &ad7298_info;
+
+       /* Setup default message */
+
+       st->scan_single_xfer[0].tx_buf = &st->tx_buf[0];
+       st->scan_single_xfer[0].len = 2;
+       st->scan_single_xfer[0].cs_change = 1;
+       st->scan_single_xfer[1].tx_buf = &st->tx_buf[1];
+       st->scan_single_xfer[1].len = 2;
+       st->scan_single_xfer[1].cs_change = 1;
+       st->scan_single_xfer[2].rx_buf = &st->rx_buf[0];
+       st->scan_single_xfer[2].len = 2;
+
+       spi_message_init(&st->scan_single_msg);
+       spi_message_add_tail(&st->scan_single_xfer[0], &st->scan_single_msg);
+       spi_message_add_tail(&st->scan_single_xfer[1], &st->scan_single_msg);
+       spi_message_add_tail(&st->scan_single_xfer[2], &st->scan_single_msg);
+
+       ret = iio_triggered_buffer_setup(indio_dev, NULL,
+                       &ad7298_trigger_handler, NULL);
+       if (ret)
+               goto error_disable_reg;
+
+       ret = iio_device_register(indio_dev);
+       if (ret)
+               goto error_cleanup_ring;
+
+       return 0;
+
+error_cleanup_ring:
+       iio_triggered_buffer_cleanup(indio_dev);
+error_disable_reg:
+       if (st->ext_ref)
+               regulator_disable(st->reg);
+error_put_reg:
+       if (st->ext_ref)
+               regulator_put(st->reg);
+error_free:
+       iio_device_free(indio_dev);
+
+       return ret;
+}
+
+static int __devexit ad7298_remove(struct spi_device *spi)
+{
+       struct iio_dev *indio_dev = spi_get_drvdata(spi);
+       struct ad7298_state *st = iio_priv(indio_dev);
+
+       iio_device_unregister(indio_dev);
+       iio_triggered_buffer_cleanup(indio_dev);
+       if (st->ext_ref) {
+               regulator_disable(st->reg);
+               regulator_put(st->reg);
+       }
+       iio_device_free(indio_dev);
+
+       return 0;
+}
+
+static const struct spi_device_id ad7298_id[] = {
+       {"ad7298", 0},
+       {}
+};
+MODULE_DEVICE_TABLE(spi, ad7298_id);
+
+static struct spi_driver ad7298_driver = {
+       .driver = {
+               .name   = "ad7298",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = ad7298_probe,
+       .remove         = __devexit_p(ad7298_remove),
+       .id_table       = ad7298_id,
+};
+module_spi_driver(ad7298_driver);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD7298 ADC");
+MODULE_LICENSE("GPL v2");
index 8e63d81d652a482478834a8a3cca371cbf64050e..ae10778da7aa1e7b1c11b558a562e998e78cfdcb 100644 (file)
@@ -15,7 +15,7 @@ config HID_SENSOR_IIO_COMMON
          attributes.
 
 config HID_SENSOR_ENUM_BASE_QUIRKS
-       tristate "ENUM base quirks for HID Sensor IIO drivers"
+       bool "ENUM base quirks for HID Sensor IIO drivers"
        depends on HID_SENSOR_IIO_COMMON
        help
          Say yes here to build support for sensor hub FW using
index d4b790d18efb6e5c3b4d2a96aba5f5097fc243bb..d60198a6ca29a0ee6fa187fb6dbdbb2016df5ca3 100644 (file)
@@ -36,10 +36,8 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
        int state_val;
 
        state_val = state ? 1 : 0;
-#if (defined CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS) || \
-       (defined CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS_MODULE)
-       ++state_val;
-#endif
+       if (IS_ENABLED(CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS))
+               ++state_val;
        st->data_ready = state;
        sensor_hub_set_feature(st->hsdev, st->power_state.report_id,
                                        st->power_state.index,
index 21e27e2fc68cf586e374f1709024c99e0204ba15..48ed1483ff27260e8ac24634cc670acf32f33172 100644 (file)
@@ -3,6 +3,15 @@
 #
 menu "Digital gyroscope sensors"
 
+config ADIS16136
+       tristate "Analog devices ADIS16136 and similar gyroscopes driver"
+       depends on SPI_MASTER
+       select IIO_ADIS_LIB
+       select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
+       help
+         Say yes here to build support for the Analog Devices ADIS16133, ADIS16135,
+         ADIS16136 gyroscope devices.
+
 config HID_SENSOR_GYRO_3D
        depends on HID_SENSOR_HUB
        select IIO_BUFFER
index 8a895d9fcbceb2b38f86c2163feb4143d9068bf4..702a058907e35c96ef66aa42053b6be85eac1834 100644 (file)
@@ -2,4 +2,5 @@
 # Makefile for industrial I/O gyroscope sensor drivers
 #
 
+obj-$(CONFIG_ADIS16136) += adis16136.o
 obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o
diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c
new file mode 100644 (file)
index 0000000..05486df
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * ADIS16133/ADIS16135/ADIS16136 gyroscope driver
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *   Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
+
+#include <linux/iio/iio.h>
+#include <linux/debugfs.h>
+
+#define ADIS16136_REG_FLASH_CNT                0x00
+#define ADIS16136_REG_TEMP_OUT         0x02
+#define ADIS16136_REG_GYRO_OUT2                0x04
+#define ADIS16136_REG_GYRO_OUT         0x06
+#define ADIS16136_REG_GYRO_OFF2                0x08
+#define ADIS16136_REG_GYRO_OFF         0x0A
+#define ADIS16136_REG_ALM_MAG1         0x10
+#define ADIS16136_REG_ALM_MAG2         0x12
+#define ADIS16136_REG_ALM_SAMPL1       0x14
+#define ADIS16136_REG_ALM_SAMPL2       0x16
+#define ADIS16136_REG_ALM_CTRL         0x18
+#define ADIS16136_REG_GPIO_CTRL                0x1A
+#define ADIS16136_REG_MSC_CTRL         0x1C
+#define ADIS16136_REG_SMPL_PRD         0x1E
+#define ADIS16136_REG_AVG_CNT          0x20
+#define ADIS16136_REG_DEC_RATE         0x22
+#define ADIS16136_REG_SLP_CTRL         0x24
+#define ADIS16136_REG_DIAG_STAT                0x26
+#define ADIS16136_REG_GLOB_CMD         0x28
+#define ADIS16136_REG_LOT1             0x32
+#define ADIS16136_REG_LOT2             0x34
+#define ADIS16136_REG_LOT3             0x36
+#define ADIS16136_REG_PROD_ID          0x38
+#define ADIS16136_REG_SERIAL_NUM       0x3A
+
+#define ADIS16136_DIAG_STAT_FLASH_UPDATE_FAIL  2
+#define ADIS16136_DIAG_STAT_SPI_FAIL           3
+#define ADIS16136_DIAG_STAT_SELF_TEST_FAIL     5
+#define ADIS16136_DIAG_STAT_FLASH_CHKSUM_FAIL  6
+
+#define ADIS16136_MSC_CTRL_MEMORY_TEST BIT(11)
+#define ADIS16136_MSC_CTRL_SELF_TEST BIT(10)
+
+struct adis16136_chip_info {
+       unsigned int precision;
+       unsigned int fullscale;
+};
+
+struct adis16136 {
+       const struct adis16136_chip_info *chip_info;
+
+       struct adis adis;
+};
+
+#ifdef CONFIG_DEBUG_FS
+
+static ssize_t adis16136_show_serial(struct file *file,
+               char __user *userbuf, size_t count, loff_t *ppos)
+{
+       struct adis16136 *adis16136 = file->private_data;
+       uint16_t lot1, lot2, lot3, serial;
+       char buf[20];
+       size_t len;
+       int ret;
+
+       ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SERIAL_NUM,
+               &serial);
+       if (ret < 0)
+               return ret;
+
+       ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT1, &lot1);
+       if (ret < 0)
+               return ret;
+
+       ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT2, &lot2);
+       if (ret < 0)
+               return ret;
+
+       ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT3, &lot3);
+       if (ret < 0)
+               return ret;
+
+       len = snprintf(buf, sizeof(buf), "%.4x%.4x%.4x-%.4x\n", lot1, lot2,
+               lot3, serial);
+
+       return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+
+static const struct file_operations adis16136_serial_fops = {
+       .open = simple_open,
+       .read = adis16136_show_serial,
+       .llseek = default_llseek,
+       .owner = THIS_MODULE,
+};
+
+static int adis16136_show_product_id(void *arg, u64 *val)
+{
+       struct adis16136 *adis16136 = arg;
+       u16 prod_id;
+       int ret;
+
+       ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_PROD_ID,
+               &prod_id);
+       if (ret < 0)
+               return ret;
+
+       *val = prod_id;
+
+       return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(adis16136_product_id_fops,
+       adis16136_show_product_id, NULL, "%llu\n");
+
+static int adis16136_show_flash_count(void *arg, u64 *val)
+{
+       struct adis16136 *adis16136 = arg;
+       uint16_t flash_count;
+       int ret;
+
+       ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_FLASH_CNT,
+               &flash_count);
+       if (ret < 0)
+               return ret;
+
+       *val = flash_count;
+
+       return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(adis16136_flash_count_fops,
+       adis16136_show_flash_count, NULL, "%lld\n");
+
+static int adis16136_debugfs_init(struct iio_dev *indio_dev)
+{
+       struct adis16136 *adis16136 = iio_priv(indio_dev);
+
+       debugfs_create_file("serial_number", 0400, indio_dev->debugfs_dentry,
+               adis16136, &adis16136_serial_fops);
+       debugfs_create_file("product_id", 0400, indio_dev->debugfs_dentry,
+               adis16136, &adis16136_product_id_fops);
+       debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry,
+               adis16136, &adis16136_flash_count_fops);
+
+       return 0;
+}
+
+#else
+
+static int adis16136_debugfs_init(struct iio_dev *indio_dev)
+{
+       return 0;
+}
+
+#endif
+
+static int adis16136_set_freq(struct adis16136 *adis16136, unsigned int freq)
+{
+       unsigned int t;
+
+       t = 32768 / freq;
+       if (t < 0xf)
+               t = 0xf;
+       else if (t > 0xffff)
+               t = 0xffff;
+       else
+               t--;
+
+       return adis_write_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, t);
+}
+
+static int adis16136_get_freq(struct adis16136 *adis16136, unsigned int *freq)
+{
+       uint16_t t;
+       int ret;
+
+       ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, &t);
+       if (ret < 0)
+               return ret;
+
+       *freq = 32768 / (t + 1);
+
+       return 0;
+}
+
+static ssize_t adis16136_write_frequency(struct device *dev,
+       struct device_attribute *attr, const char *buf, size_t len)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct adis16136 *adis16136 = iio_priv(indio_dev);
+       long val;
+       int ret;
+
+       ret = kstrtol(buf, 10, &val);
+       if (ret)
+               return ret;
+
+       if (val == 0)
+               return -EINVAL;
+
+       ret = adis16136_set_freq(adis16136, val);
+
+       return ret ? ret : len;
+}
+
+static ssize_t adis16136_read_frequency(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct adis16136 *adis16136 = iio_priv(indio_dev);
+       unsigned int freq;
+       int ret;
+
+       ret = adis16136_get_freq(adis16136, &freq);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", freq);
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
+                                 adis16136_read_frequency,
+                                 adis16136_write_frequency);
+
+static const unsigned adis16136_3db_divisors[] = {
+       [0] = 2, /* Special case */
+       [1] = 6,
+       [2] = 12,
+       [3] = 25,
+       [4] = 50,
+       [5] = 100,
+       [6] = 200,
+       [7] = 200, /* Not a valid setting */
+};
+
+static int adis16136_set_filter(struct iio_dev *indio_dev, int val)
+{
+       struct adis16136 *adis16136 = iio_priv(indio_dev);
+       unsigned int freq;
+       int i, ret;
+
+       ret = adis16136_get_freq(adis16136, &freq);
+       if (ret < 0)
+               return ret;
+
+       for (i = ARRAY_SIZE(adis16136_3db_divisors) - 1; i >= 1; i--) {
+               if (freq / adis16136_3db_divisors[i] >= val)
+                       break;
+       }
+
+       return adis_write_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, i);
+}
+
+static int adis16136_get_filter(struct iio_dev *indio_dev, int *val)
+{
+       struct adis16136 *adis16136 = iio_priv(indio_dev);
+       unsigned int freq;
+       uint16_t val16;
+       int ret;
+
+       mutex_lock(&indio_dev->mlock);
+
+       ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, &val16);
+       if (ret < 0)
+               goto err_unlock;
+
+       ret = adis16136_get_freq(adis16136, &freq);
+       if (ret < 0)
+               goto err_unlock;
+
+       *val = freq / adis16136_3db_divisors[val16 & 0x07];
+
+err_unlock:
+       mutex_unlock(&indio_dev->mlock);
+
+       return ret ? ret : IIO_VAL_INT;
+}
+
+static int adis16136_read_raw(struct iio_dev *indio_dev,
+       const struct iio_chan_spec *chan, int *val, int *val2, long info)
+{
+       struct adis16136 *adis16136 = iio_priv(indio_dev);
+       uint32_t val32;
+       int ret;
+
+       switch (info) {
+       case IIO_CHAN_INFO_RAW:
+               return adis_single_conversion(indio_dev, chan, 0, val);
+       case IIO_CHAN_INFO_SCALE:
+               switch (chan->type) {
+               case IIO_ANGL_VEL:
+                       *val = adis16136->chip_info->precision;
+                       *val2 = (adis16136->chip_info->fullscale << 16);
+                       return IIO_VAL_FRACTIONAL;
+               case IIO_TEMP:
+                       *val = 10;
+                       *val2 = 697000; /* 0.010697 degree Celsius */
+                       return IIO_VAL_INT_PLUS_MICRO;
+               default:
+                       return -EINVAL;
+               }
+       case IIO_CHAN_INFO_CALIBBIAS:
+               ret = adis_read_reg_32(&adis16136->adis,
+                       ADIS16136_REG_GYRO_OFF2, &val32);
+               if (ret < 0)
+                       return ret;
+
+               *val = sign_extend32(val32, 31);
+
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+               return adis16136_get_filter(indio_dev, val);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int adis16136_write_raw(struct iio_dev *indio_dev,
+       const struct iio_chan_spec *chan, int val, int val2, long info)
+{
+       struct adis16136 *adis16136 = iio_priv(indio_dev);
+
+       switch (info) {
+       case IIO_CHAN_INFO_CALIBBIAS:
+               return adis_write_reg_32(&adis16136->adis,
+                       ADIS16136_REG_GYRO_OFF2, val);
+       case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+               return adis16136_set_filter(indio_dev, val);
+       default:
+               break;
+       }
+
+       return -EINVAL;
+}
+
+enum {
+       ADIS16136_SCAN_GYRO,
+       ADIS16136_SCAN_TEMP,
+};
+
+static const struct iio_chan_spec adis16136_channels[] = {
+       {
+               .type = IIO_ANGL_VEL,
+               .modified = 1,
+               .channel2 = IIO_MOD_X,
+               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+                       IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+                       IIO_CHAN_INFO_SCALE_SHARED_BIT |
+                       IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT,
+               .address = ADIS16136_REG_GYRO_OUT2,
+               .scan_index = ADIS16136_SCAN_GYRO,
+               .scan_type = {
+                       .sign = 's',
+                       .realbits = 32,
+                       .storagebits = 32,
+                       .endianness = IIO_BE,
+               },
+       }, {
+               .type = IIO_TEMP,
+               .indexed = 1,
+               .channel = 0,
+               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+                       IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+               .address = ADIS16136_REG_TEMP_OUT,
+               .scan_index = ADIS16136_SCAN_TEMP,
+               .scan_type = {
+                       .sign = 's',
+                       .realbits = 16,
+                       .storagebits = 16,
+                       .endianness = IIO_BE,
+               },
+       },
+       IIO_CHAN_SOFT_TIMESTAMP(2),
+};
+
+static struct attribute *adis16136_attributes[] = {
+       &iio_dev_attr_sampling_frequency.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group adis16136_attribute_group = {
+       .attrs = adis16136_attributes,
+};
+
+static const struct iio_info adis16136_info = {
+       .driver_module = THIS_MODULE,
+       .attrs = &adis16136_attribute_group,
+       .read_raw = &adis16136_read_raw,
+       .write_raw = &adis16136_write_raw,
+       .update_scan_mode = adis_update_scan_mode,
+       .debugfs_reg_access = adis_debugfs_reg_access,
+};
+
+static int adis16136_stop_device(struct iio_dev *indio_dev)
+{
+       struct adis16136 *adis16136 = iio_priv(indio_dev);
+       int ret;
+
+       ret = adis_write_reg_16(&adis16136->adis, ADIS16136_REG_SLP_CTRL, 0xff);
+       if (ret)
+               dev_err(&indio_dev->dev,
+                       "Could not power down device: %d\n", ret);
+
+       return ret;
+}
+
+static int adis16136_initial_setup(struct iio_dev *indio_dev)
+{
+       struct adis16136 *adis16136 = iio_priv(indio_dev);
+       unsigned int device_id;
+       uint16_t prod_id;
+       int ret;
+
+       ret = adis_initial_startup(&adis16136->adis);
+       if (ret)
+               return ret;
+
+       ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_PROD_ID,
+               &prod_id);
+       if (ret)
+               return ret;
+
+       sscanf(indio_dev->name, "adis%u\n", &device_id);
+
+       if (prod_id != device_id)
+               dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.",
+                               device_id, prod_id);
+
+       return 0;
+}
+
+static const char * const adis16136_status_error_msgs[] = {
+       [ADIS16136_DIAG_STAT_FLASH_UPDATE_FAIL] = "Flash update failed",
+       [ADIS16136_DIAG_STAT_SPI_FAIL] = "SPI failure",
+       [ADIS16136_DIAG_STAT_SELF_TEST_FAIL] = "Self test error",
+       [ADIS16136_DIAG_STAT_FLASH_CHKSUM_FAIL] = "Flash checksum error",
+};
+
+static const struct adis_data adis16136_data = {
+       .diag_stat_reg = ADIS16136_REG_DIAG_STAT,
+       .glob_cmd_reg = ADIS16136_REG_GLOB_CMD,
+       .msc_ctrl_reg = ADIS16136_REG_MSC_CTRL,
+
+       .self_test_mask = ADIS16136_MSC_CTRL_SELF_TEST,
+       .startup_delay = 80,
+
+       .read_delay = 10,
+       .write_delay = 10,
+
+       .status_error_msgs = adis16136_status_error_msgs,
+       .status_error_mask = BIT(ADIS16136_DIAG_STAT_FLASH_UPDATE_FAIL) |
+               BIT(ADIS16136_DIAG_STAT_SPI_FAIL) |
+               BIT(ADIS16136_DIAG_STAT_SELF_TEST_FAIL) |
+               BIT(ADIS16136_DIAG_STAT_FLASH_CHKSUM_FAIL),
+};
+
+enum adis16136_id {
+       ID_ADIS16133,
+       ID_ADIS16135,
+       ID_ADIS16136,
+};
+
+static const struct adis16136_chip_info adis16136_chip_info[] = {
+       [ID_ADIS16133] = {
+               .precision = IIO_DEGREE_TO_RAD(1200),
+               .fullscale = 24000,
+       },
+       [ID_ADIS16135] = {
+               .precision = IIO_DEGREE_TO_RAD(300),
+               .fullscale = 24000,
+       },
+       [ID_ADIS16136] = {
+               .precision = IIO_DEGREE_TO_RAD(450),
+               .fullscale = 24623,
+       },
+};
+
+static int adis16136_probe(struct spi_device *spi)
+{
+       const struct spi_device_id *id = spi_get_device_id(spi);
+       struct adis16136 *adis16136;
+       struct iio_dev *indio_dev;
+       int ret;
+
+       indio_dev = iio_device_alloc(sizeof(*adis16136));
+       if (indio_dev == NULL)
+               return -ENOMEM;
+
+       spi_set_drvdata(spi, indio_dev);
+
+       adis16136 = iio_priv(indio_dev);
+
+       adis16136->chip_info = &adis16136_chip_info[id->driver_data];
+       indio_dev->dev.parent = &spi->dev;
+       indio_dev->name = spi_get_device_id(spi)->name;
+       indio_dev->channels = adis16136_channels;
+       indio_dev->num_channels = ARRAY_SIZE(adis16136_channels);
+       indio_dev->info = &adis16136_info;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+
+       ret = adis_init(&adis16136->adis, indio_dev, spi, &adis16136_data);
+       if (ret)
+               goto error_free_dev;
+
+       ret = adis_setup_buffer_and_trigger(&adis16136->adis, indio_dev, NULL);
+       if (ret)
+               goto error_free_dev;
+
+       ret = adis16136_initial_setup(indio_dev);
+       if (ret)
+               goto error_cleanup_buffer;
+
+       ret = iio_device_register(indio_dev);
+       if (ret)
+               goto error_stop_device;
+
+       adis16136_debugfs_init(indio_dev);
+
+       return 0;
+
+error_stop_device:
+       adis16136_stop_device(indio_dev);
+error_cleanup_buffer:
+       adis_cleanup_buffer_and_trigger(&adis16136->adis, indio_dev);
+error_free_dev:
+       iio_device_free(indio_dev);
+       return ret;
+}
+
+static int adis16136_remove(struct spi_device *spi)
+{
+       struct iio_dev *indio_dev = spi_get_drvdata(spi);
+       struct adis16136 *adis16136 = iio_priv(indio_dev);
+
+       iio_device_unregister(indio_dev);
+       adis16136_stop_device(indio_dev);
+
+       adis_cleanup_buffer_and_trigger(&adis16136->adis, indio_dev);
+
+       iio_device_free(indio_dev);
+
+       return 0;
+}
+
+static const struct spi_device_id adis16136_ids[] = {
+       { "adis16133", ID_ADIS16133 },
+       { "adis16135", ID_ADIS16135 },
+       { "adis16136", ID_ADIS16136 },
+       { }
+};
+MODULE_DEVICE_TABLE(spi, adis16136_ids);
+
+static struct spi_driver adis16136_driver = {
+       .driver = {
+               .name = "adis16136",
+               .owner = THIS_MODULE,
+       },
+       .id_table = adis16136_ids,
+       .probe = adis16136_probe,
+       .remove = adis16136_remove,
+};
+module_spi_driver(adis16136_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Analog Devices ADIS16133/ADIS16135/ADIS16136 gyroscope driver");
+MODULE_LICENSE("GPL v2");
index 02ef989b830d2d897ba580c8cc3c3305b06ba31b..4c8b158e40e18d508d4dfd53d7108249e2f2a455 100644 (file)
@@ -306,10 +306,10 @@ static int __devinit hid_gyro_3d_probe(struct platform_device *pdev)
                goto error_free_dev;
        }
 
-       channels = kmemdup(gyro_3d_channels,
-                                       sizeof(gyro_3d_channels),
-                                       GFP_KERNEL);
+       channels = kmemdup(gyro_3d_channels, sizeof(gyro_3d_channels),
+                          GFP_KERNEL);
        if (!channels) {
+               ret = -ENOMEM;
                dev_err(&pdev->dev, "failed to duplicate channels\n");
                goto error_free_dev;
        }
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
new file mode 100644 (file)
index 0000000..3d79a40
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# IIO imu drivers configuration
+#
+menu "Inertial measurement units"
+
+config ADIS16480
+       tristate "Analog Devices ADIS16480 and similar IMU driver"
+       depends on SPI
+       select IIO_ADIS_LIB
+       select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
+       help
+         Say yes here to build support for Analog Devices ADIS16375, ADIS16480,
+         ADIS16485, ADIS16488 inertial sensors.
+
+endmenu
+
+config IIO_ADIS_LIB
+       tristate
+       help
+         A set of IO helper functions for the Analog Devices ADIS* device family.
+
+config IIO_ADIS_LIB_BUFFER
+       bool
+       select IIO_TRIGGERED_BUFFER
+       help
+         A set of buffer helper functions for the Analog Devices ADIS* device
+         family.
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
new file mode 100644 (file)
index 0000000..cfe5763
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for Inertial Measurement Units
+#
+
+obj-$(CONFIG_ADIS16480) += adis16480.o
+
+adis_lib-y += adis.o
+adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o
+adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
+obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c
new file mode 100644 (file)
index 0000000..911255d
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * Common library for ADIS16XXX devices
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *   Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <asm/unaligned.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
+
+#define ADIS_MSC_CTRL_DATA_RDY_EN      BIT(2)
+#define ADIS_MSC_CTRL_DATA_RDY_POL_HIGH        BIT(1)
+#define ADIS_MSC_CTRL_DATA_RDY_DIO2    BIT(0)
+#define ADIS_GLOB_CMD_SW_RESET         BIT(7)
+
+int adis_write_reg(struct adis *adis, unsigned int reg,
+       unsigned int value, unsigned int size)
+{
+       unsigned int page = reg / ADIS_PAGE_SIZE;
+       int ret, i;
+       struct spi_message msg;
+       struct spi_transfer xfers[] = {
+               {
+                       .tx_buf = adis->tx,
+                       .bits_per_word = 8,
+                       .len = 2,
+                       .cs_change = 1,
+                       .delay_usecs = adis->data->write_delay,
+               }, {
+                       .tx_buf = adis->tx + 2,
+                       .bits_per_word = 8,
+                       .len = 2,
+                       .cs_change = 1,
+                       .delay_usecs = adis->data->write_delay,
+               }, {
+                       .tx_buf = adis->tx + 4,
+                       .bits_per_word = 8,
+                       .len = 2,
+                       .cs_change = 1,
+                       .delay_usecs = adis->data->write_delay,
+               }, {
+                       .tx_buf = adis->tx + 6,
+                       .bits_per_word = 8,
+                       .len = 2,
+                       .delay_usecs = adis->data->write_delay,
+               }, {
+                       .tx_buf = adis->tx + 8,
+                       .bits_per_word = 8,
+                       .len = 2,
+                       .delay_usecs = adis->data->write_delay,
+               },
+       };
+
+       mutex_lock(&adis->txrx_lock);
+
+       spi_message_init(&msg);
+
+       if (adis->current_page != page) {
+               adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID);
+               adis->tx[1] = page;
+               spi_message_add_tail(&xfers[0], &msg);
+       }
+
+       switch (size) {
+       case 4:
+               adis->tx[8] = ADIS_WRITE_REG(reg + 3);
+               adis->tx[9] = (value >> 24) & 0xff;
+               adis->tx[6] = ADIS_WRITE_REG(reg + 2);
+               adis->tx[7] = (value >> 16) & 0xff;
+       case 2:
+               adis->tx[4] = ADIS_WRITE_REG(reg + 1);
+               adis->tx[5] = (value >> 8) & 0xff;
+       case 1:
+               adis->tx[2] = ADIS_WRITE_REG(reg);
+               adis->tx[3] = value & 0xff;
+               break;
+       default:
+               ret = -EINVAL;
+               goto out_unlock;
+       }
+
+       xfers[size].cs_change = 0;
+
+       for (i = 1; i <= size; i++)
+               spi_message_add_tail(&xfers[i], &msg);
+
+       ret = spi_sync(adis->spi, &msg);
+       if (ret) {
+               dev_err(&adis->spi->dev, "Failed to write register 0x%02X: %d\n",
+                               reg, ret);
+       } else {
+               adis->current_page = page;
+       }
+
+out_unlock:
+       mutex_unlock(&adis->txrx_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(adis_write_reg);
+
+/**
+ * adis_read_reg() - read 2 bytes from a 16-bit register
+ * @adis: The adis device
+ * @reg: The address of the lower of the two registers
+ * @val: The value read back from the device
+ */
+int adis_read_reg(struct adis *adis, unsigned int reg,
+       unsigned int *val, unsigned int size)
+{
+       unsigned int page = reg / ADIS_PAGE_SIZE;
+       struct spi_message msg;
+       int ret;
+       struct spi_transfer xfers[] = {
+               {
+                       .tx_buf = adis->tx,
+                       .bits_per_word = 8,
+                       .len = 2,
+                       .cs_change = 1,
+                       .delay_usecs = adis->data->write_delay,
+               }, {
+                       .tx_buf = adis->tx + 2,
+                       .bits_per_word = 8,
+                       .len = 2,
+                       .cs_change = 1,
+                       .delay_usecs = adis->data->read_delay,
+               }, {
+                       .tx_buf = adis->tx + 4,
+                       .rx_buf = adis->rx,
+                       .bits_per_word = 8,
+                       .len = 2,
+                       .cs_change = 1,
+                       .delay_usecs = adis->data->read_delay,
+               }, {
+                       .rx_buf = adis->rx + 2,
+                       .bits_per_word = 8,
+                       .len = 2,
+                       .delay_usecs = adis->data->read_delay,
+               },
+       };
+
+       mutex_lock(&adis->txrx_lock);
+       spi_message_init(&msg);
+
+       if (adis->current_page != page) {
+               adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID);
+               adis->tx[1] = page;
+               spi_message_add_tail(&xfers[0], &msg);
+       }
+
+       switch (size) {
+       case 4:
+               adis->tx[2] = ADIS_READ_REG(reg + 2);
+               adis->tx[3] = 0;
+               spi_message_add_tail(&xfers[1], &msg);
+       case 2:
+               adis->tx[4] = ADIS_READ_REG(reg);
+               adis->tx[5] = 0;
+               spi_message_add_tail(&xfers[2], &msg);
+               spi_message_add_tail(&xfers[3], &msg);
+               break;
+       default:
+               ret = -EINVAL;
+               goto out_unlock;
+       }
+
+       ret = spi_sync(adis->spi, &msg);
+       if (ret) {
+               dev_err(&adis->spi->dev, "Failed to read register 0x%02X: %d\n",
+                               reg, ret);
+               goto out_unlock;
+       } else {
+               adis->current_page = page;
+       }
+
+       switch (size) {
+       case 4:
+               *val = get_unaligned_be32(adis->rx);
+               break;
+       case 2:
+               *val = get_unaligned_be16(adis->rx + 2);
+               break;
+       }
+
+out_unlock:
+       mutex_unlock(&adis->txrx_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(adis_read_reg);
+
+#ifdef CONFIG_DEBUG_FS
+
+int adis_debugfs_reg_access(struct iio_dev *indio_dev,
+       unsigned int reg, unsigned int writeval, unsigned int *readval)
+{
+       struct adis *adis = iio_device_get_drvdata(indio_dev);
+
+       if (readval) {
+               uint16_t val16;
+               int ret;
+
+               ret = adis_read_reg_16(adis, reg, &val16);
+               *readval = val16;
+
+               return ret;
+       } else {
+               return adis_write_reg_16(adis, reg, writeval);
+       }
+}
+EXPORT_SYMBOL(adis_debugfs_reg_access);
+
+#endif
+
+/**
+ * adis_enable_irq() - Enable or disable data ready IRQ
+ * @adis: The adis device
+ * @enable: Whether to enable the IRQ
+ *
+ * Returns 0 on success, negative error code otherwise
+ */
+int adis_enable_irq(struct adis *adis, bool enable)
+{
+       int ret = 0;
+       uint16_t msc;
+
+       if (adis->data->enable_irq)
+               return adis->data->enable_irq(adis, enable);
+
+       ret = adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc);
+       if (ret)
+               goto error_ret;
+
+       msc |= ADIS_MSC_CTRL_DATA_RDY_POL_HIGH;
+       msc &= ~ADIS_MSC_CTRL_DATA_RDY_DIO2;
+       if (enable)
+               msc |= ADIS_MSC_CTRL_DATA_RDY_EN;
+       else
+               msc &= ~ADIS_MSC_CTRL_DATA_RDY_EN;
+
+       ret = adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc);
+
+error_ret:
+       return ret;
+}
+EXPORT_SYMBOL(adis_enable_irq);
+
+/**
+ * adis_check_status() - Check the device for error conditions
+ * @adis: The adis device
+ *
+ * Returns 0 on success, a negative error code otherwise
+ */
+int adis_check_status(struct adis *adis)
+{
+       uint16_t status;
+       int ret;
+       int i;
+
+       ret = adis_read_reg_16(adis, adis->data->diag_stat_reg, &status);
+       if (ret < 0)
+               return ret;
+
+       status &= adis->data->status_error_mask;
+
+       if (status == 0)
+               return 0;
+
+       for (i = 0; i < 16; ++i) {
+               if (status & BIT(i)) {
+                       dev_err(&adis->spi->dev, "%s.\n",
+                               adis->data->status_error_msgs[i]);
+               }
+       }
+
+       return -EIO;
+}
+EXPORT_SYMBOL_GPL(adis_check_status);
+
+/**
+ * adis_reset() - Reset the device
+ * @adis: The adis device
+ *
+ * Returns 0 on success, a negative error code otherwise
+ */
+int adis_reset(struct adis *adis)
+{
+       int ret;
+
+       ret = adis_write_reg_8(adis, adis->data->glob_cmd_reg,
+                       ADIS_GLOB_CMD_SW_RESET);
+       if (ret)
+               dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(adis_reset);
+
+static int adis_self_test(struct adis *adis)
+{
+       int ret;
+
+       ret = adis_write_reg_16(adis, adis->data->msc_ctrl_reg,
+                       adis->data->self_test_mask);
+       if (ret) {
+               dev_err(&adis->spi->dev, "Failed to initiate self test: %d\n",
+                       ret);
+               return ret;
+       }
+
+       msleep(adis->data->startup_delay);
+
+       return adis_check_status(adis);
+}
+
+/**
+ * adis_inital_startup() - Performs device self-test
+ * @adis: The adis device
+ *
+ * Returns 0 if the device is operational, a negative error code otherwise.
+ *
+ * This function should be called early on in the device initialization sequence
+ * to ensure that the device is in a sane and known state and that it is usable.
+ */
+int adis_initial_startup(struct adis *adis)
+{
+       int ret;
+
+       ret = adis_self_test(adis);
+       if (ret) {
+               dev_err(&adis->spi->dev, "Self-test failed, trying reset.\n");
+               adis_reset(adis);
+               msleep(adis->data->startup_delay);
+               ret = adis_self_test(adis);
+               if (ret) {
+                       dev_err(&adis->spi->dev, "Second self-test failed, giving up.\n");
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(adis_initial_startup);
+
+/**
+ * adis_single_conversion() - Performs a single sample conversion
+ * @indio_dev: The IIO device
+ * @chan: The IIO channel
+ * @error_mask: Mask for the error bit
+ * @val: Result of the conversion
+ *
+ * Returns IIO_VAL_INT on success, a negative error code otherwise.
+ *
+ * The function performs a single conversion on a given channel and post
+ * processes the value accordingly to the channel spec. If a error_mask is given
+ * the function will check if the mask is set in the returned raw value. If it
+ * is set the function will perform a self-check. If the device does not report
+ * a error bit in the channels raw value set error_mask to 0.
+ */
+int adis_single_conversion(struct iio_dev *indio_dev,
+       const struct iio_chan_spec *chan, unsigned int error_mask, int *val)
+{
+       struct adis *adis = iio_device_get_drvdata(indio_dev);
+       unsigned int uval;
+       int ret;
+
+       mutex_lock(&indio_dev->mlock);
+
+       ret = adis_read_reg(adis, chan->address, &uval,
+                       chan->scan_type.storagebits / 8);
+       if (ret)
+               goto err_unlock;
+
+       if (uval & error_mask) {
+               ret = adis_check_status(adis);
+               if (ret)
+                       goto err_unlock;
+       }
+
+       if (chan->scan_type.sign == 's')
+               *val = sign_extend32(uval, chan->scan_type.realbits - 1);
+       else
+               *val = uval & ((1 << chan->scan_type.realbits) - 1);
+
+       ret = IIO_VAL_INT;
+err_unlock:
+       mutex_unlock(&indio_dev->mlock);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(adis_single_conversion);
+
+/**
+ * adis_init() - Initialize adis device structure
+ * @adis:      The adis device
+ * @indio_dev: The iio device
+ * @spi:       The spi device
+ * @data:      Chip specific data
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * This function must be called, before any other adis helper function may be
+ * called.
+ */
+int adis_init(struct adis *adis, struct iio_dev *indio_dev,
+       struct spi_device *spi, const struct adis_data *data)
+{
+       mutex_init(&adis->txrx_lock);
+       adis->spi = spi;
+       adis->data = data;
+       iio_device_set_drvdata(indio_dev, adis);
+
+       if (data->has_paging) {
+               /* Need to set the page before first read/write */
+               adis->current_page = -1;
+       } else {
+               /* Page will always be 0 */
+               adis->current_page = 0;
+       }
+
+       return adis_enable_irq(adis, false);
+}
+EXPORT_SYMBOL_GPL(adis_init);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Common library code for ADIS16XXX devices");
diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c
new file mode 100644 (file)
index 0000000..a080b35
--- /dev/null
@@ -0,0 +1,925 @@
+/*
+ * ADIS16480 and similar IMUs driver
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
+
+#include <linux/iio/iio.h>
+#include <linux/debugfs.h>
+
+#define ADIS16480_PAGE_SIZE 0x80
+
+#define ADIS16480_REG(page, reg) ((page) * ADIS16480_PAGE_SIZE + (reg))
+
+#define ADIS16480_REG_PAGE_ID 0x00 /* Same address on each page */
+#define ADIS16480_REG_SEQ_CNT                  ADIS16480_REG(0x00, 0x06)
+#define ADIS16480_REG_SYS_E_FLA                        ADIS16480_REG(0x00, 0x08)
+#define ADIS16480_REG_DIAG_STS                 ADIS16480_REG(0x00, 0x0A)
+#define ADIS16480_REG_ALM_STS                  ADIS16480_REG(0x00, 0x0C)
+#define ADIS16480_REG_TEMP_OUT                 ADIS16480_REG(0x00, 0x0E)
+#define ADIS16480_REG_X_GYRO_OUT               ADIS16480_REG(0x00, 0x10)
+#define ADIS16480_REG_Y_GYRO_OUT               ADIS16480_REG(0x00, 0x14)
+#define ADIS16480_REG_Z_GYRO_OUT               ADIS16480_REG(0x00, 0x18)
+#define ADIS16480_REG_X_ACCEL_OUT              ADIS16480_REG(0x00, 0x1C)
+#define ADIS16480_REG_Y_ACCEL_OUT              ADIS16480_REG(0x00, 0x20)
+#define ADIS16480_REG_Z_ACCEL_OUT              ADIS16480_REG(0x00, 0x24)
+#define ADIS16480_REG_X_MAGN_OUT               ADIS16480_REG(0x00, 0x28)
+#define ADIS16480_REG_Y_MAGN_OUT               ADIS16480_REG(0x00, 0x2A)
+#define ADIS16480_REG_Z_MAGN_OUT               ADIS16480_REG(0x00, 0x2C)
+#define ADIS16480_REG_BAROM_OUT                        ADIS16480_REG(0x00, 0x2E)
+#define ADIS16480_REG_X_DELTAANG_OUT           ADIS16480_REG(0x00, 0x40)
+#define ADIS16480_REG_Y_DELTAANG_OUT           ADIS16480_REG(0x00, 0x44)
+#define ADIS16480_REG_Z_DELTAANG_OUT           ADIS16480_REG(0x00, 0x48)
+#define ADIS16480_REG_X_DELTAVEL_OUT           ADIS16480_REG(0x00, 0x4C)
+#define ADIS16480_REG_Y_DELTAVEL_OUT           ADIS16480_REG(0x00, 0x50)
+#define ADIS16480_REG_Z_DELTAVEL_OUT           ADIS16480_REG(0x00, 0x54)
+#define ADIS16480_REG_PROD_ID                  ADIS16480_REG(0x00, 0x7E)
+
+#define ADIS16480_REG_X_GYRO_SCALE             ADIS16480_REG(0x02, 0x04)
+#define ADIS16480_REG_Y_GYRO_SCALE             ADIS16480_REG(0x02, 0x06)
+#define ADIS16480_REG_Z_GYRO_SCALE             ADIS16480_REG(0x02, 0x08)
+#define ADIS16480_REG_X_ACCEL_SCALE            ADIS16480_REG(0x02, 0x0A)
+#define ADIS16480_REG_Y_ACCEL_SCALE            ADIS16480_REG(0x02, 0x0C)
+#define ADIS16480_REG_Z_ACCEL_SCALE            ADIS16480_REG(0x02, 0x0E)
+#define ADIS16480_REG_X_GYRO_BIAS              ADIS16480_REG(0x02, 0x10)
+#define ADIS16480_REG_Y_GYRO_BIAS              ADIS16480_REG(0x02, 0x14)
+#define ADIS16480_REG_Z_GYRO_BIAS              ADIS16480_REG(0x02, 0x18)
+#define ADIS16480_REG_X_ACCEL_BIAS             ADIS16480_REG(0x02, 0x1C)
+#define ADIS16480_REG_Y_ACCEL_BIAS             ADIS16480_REG(0x02, 0x20)
+#define ADIS16480_REG_Z_ACCEL_BIAS             ADIS16480_REG(0x02, 0x24)
+#define ADIS16480_REG_X_HARD_IRON              ADIS16480_REG(0x02, 0x28)
+#define ADIS16480_REG_Y_HARD_IRON              ADIS16480_REG(0x02, 0x2A)
+#define ADIS16480_REG_Z_HARD_IRON              ADIS16480_REG(0x02, 0x2C)
+#define ADIS16480_REG_BAROM_BIAS               ADIS16480_REG(0x02, 0x40)
+#define ADIS16480_REG_FLASH_CNT                        ADIS16480_REG(0x02, 0x7C)
+
+#define ADIS16480_REG_GLOB_CMD                 ADIS16480_REG(0x03, 0x02)
+#define ADIS16480_REG_FNCTIO_CTRL              ADIS16480_REG(0x03, 0x06)
+#define ADIS16480_REG_GPIO_CTRL                        ADIS16480_REG(0x03, 0x08)
+#define ADIS16480_REG_CONFIG                   ADIS16480_REG(0x03, 0x0A)
+#define ADIS16480_REG_DEC_RATE                 ADIS16480_REG(0x03, 0x0C)
+#define ADIS16480_REG_SLP_CNT                  ADIS16480_REG(0x03, 0x10)
+#define ADIS16480_REG_FILTER_BNK0              ADIS16480_REG(0x03, 0x16)
+#define ADIS16480_REG_FILTER_BNK1              ADIS16480_REG(0x03, 0x18)
+#define ADIS16480_REG_ALM_CNFG0                        ADIS16480_REG(0x03, 0x20)
+#define ADIS16480_REG_ALM_CNFG1                        ADIS16480_REG(0x03, 0x22)
+#define ADIS16480_REG_ALM_CNFG2                        ADIS16480_REG(0x03, 0x24)
+#define ADIS16480_REG_XG_ALM_MAGN              ADIS16480_REG(0x03, 0x28)
+#define ADIS16480_REG_YG_ALM_MAGN              ADIS16480_REG(0x03, 0x2A)
+#define ADIS16480_REG_ZG_ALM_MAGN              ADIS16480_REG(0x03, 0x2C)
+#define ADIS16480_REG_XA_ALM_MAGN              ADIS16480_REG(0x03, 0x2E)
+#define ADIS16480_REG_YA_ALM_MAGN              ADIS16480_REG(0x03, 0x30)
+#define ADIS16480_REG_ZA_ALM_MAGN              ADIS16480_REG(0x03, 0x32)
+#define ADIS16480_REG_XM_ALM_MAGN              ADIS16480_REG(0x03, 0x34)
+#define ADIS16480_REG_YM_ALM_MAGN              ADIS16480_REG(0x03, 0x36)
+#define ADIS16480_REG_ZM_ALM_MAGN              ADIS16480_REG(0x03, 0x38)
+#define ADIS16480_REG_BR_ALM_MAGN              ADIS16480_REG(0x03, 0x3A)
+#define ADIS16480_REG_FIRM_REV                 ADIS16480_REG(0x03, 0x78)
+#define ADIS16480_REG_FIRM_DM                  ADIS16480_REG(0x03, 0x7A)
+#define ADIS16480_REG_FIRM_Y                   ADIS16480_REG(0x03, 0x7C)
+
+#define ADIS16480_REG_SERIAL_NUM               ADIS16480_REG(0x04, 0x20)
+
+/* Each filter coefficent bank spans two pages */
+#define ADIS16480_FIR_COEF(page) (x < 60 ? ADIS16480_REG(page, (x) + 8) : \
+               ADIS16480_REG((page) + 1, (x) - 60 + 8))
+#define ADIS16480_FIR_COEF_A(x)                        ADIS16480_FIR_COEF(0x05, (x))
+#define ADIS16480_FIR_COEF_B(x)                        ADIS16480_FIR_COEF(0x07, (x))
+#define ADIS16480_FIR_COEF_C(x)                        ADIS16480_FIR_COEF(0x09, (x))
+#define ADIS16480_FIR_COEF_D(x)                        ADIS16480_FIR_COEF(0x0B, (x))
+
+struct adis16480_chip_info {
+       unsigned int num_channels;
+       const struct iio_chan_spec *channels;
+};
+
+struct adis16480 {
+       const struct adis16480_chip_info *chip_info;
+
+       struct adis adis;
+};
+
+#ifdef CONFIG_DEBUG_FS
+
+static ssize_t adis16480_show_firmware_revision(struct file *file,
+               char __user *userbuf, size_t count, loff_t *ppos)
+{
+       struct adis16480 *adis16480 = file->private_data;
+       char buf[6];
+       size_t len;
+       u16 rev;
+       int ret;
+
+       ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_FIRM_REV, &rev);
+       if (ret < 0)
+               return ret;
+
+       len = snprintf(buf, sizeof(buf), "%x.%x\n", rev >> 8, rev & 0xff);
+
+       return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+
+static const struct file_operations adis16480_firmware_revision_fops = {
+       .open = simple_open,
+       .read = adis16480_show_firmware_revision,
+       .llseek = default_llseek,
+       .owner = THIS_MODULE,
+};
+
+static ssize_t adis16480_show_firmware_date(struct file *file,
+               char __user *userbuf, size_t count, loff_t *ppos)
+{
+       struct adis16480 *adis16480 = file->private_data;
+       u16 md, year;
+       char buf[12];
+       size_t len;
+       int ret;
+
+       ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_FIRM_Y, &year);
+       if (ret < 0)
+               return ret;
+
+       ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_FIRM_DM, &md);
+       if (ret < 0)
+               return ret;
+
+       len = snprintf(buf, sizeof(buf), "%.2x-%.2x-%.4x\n",
+                       md >> 8, md & 0xff, year);
+
+       return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+
+static const struct file_operations adis16480_firmware_date_fops = {
+       .open = simple_open,
+       .read = adis16480_show_firmware_date,
+       .llseek = default_llseek,
+       .owner = THIS_MODULE,
+};
+
+static int adis16480_show_serial_number(void *arg, u64 *val)
+{
+       struct adis16480 *adis16480 = arg;
+       u16 serial;
+       int ret;
+
+       ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_SERIAL_NUM,
+               &serial);
+       if (ret < 0)
+               return ret;
+
+       *val = serial;
+
+       return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(adis16480_serial_number_fops,
+       adis16480_show_serial_number, NULL, "0x%.4llx\n");
+
+static int adis16480_show_product_id(void *arg, u64 *val)
+{
+       struct adis16480 *adis16480 = arg;
+       u16 prod_id;
+       int ret;
+
+       ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_PROD_ID,
+               &prod_id);
+       if (ret < 0)
+               return ret;
+
+       *val = prod_id;
+
+       return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(adis16480_product_id_fops,
+       adis16480_show_product_id, NULL, "%llu\n");
+
+static int adis16480_show_flash_count(void *arg, u64 *val)
+{
+       struct adis16480 *adis16480 = arg;
+       u32 flash_count;
+       int ret;
+
+       ret = adis_read_reg_32(&adis16480->adis, ADIS16480_REG_FLASH_CNT,
+               &flash_count);
+       if (ret < 0)
+               return ret;
+
+       *val = flash_count;
+
+       return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(adis16480_flash_count_fops,
+       adis16480_show_flash_count, NULL, "%lld\n");
+
+static int adis16480_debugfs_init(struct iio_dev *indio_dev)
+{
+       struct adis16480 *adis16480 = iio_priv(indio_dev);
+
+       debugfs_create_file("firmware_revision", 0400,
+               indio_dev->debugfs_dentry, adis16480,
+               &adis16480_firmware_revision_fops);
+       debugfs_create_file("firmware_date", 0400, indio_dev->debugfs_dentry,
+               adis16480, &adis16480_firmware_date_fops);
+       debugfs_create_file("serial_number", 0400, indio_dev->debugfs_dentry,
+               adis16480, &adis16480_serial_number_fops);
+       debugfs_create_file("product_id", 0400, indio_dev->debugfs_dentry,
+               adis16480, &adis16480_product_id_fops);
+       debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry,
+               adis16480, &adis16480_flash_count_fops);
+
+       return 0;
+}
+
+#else
+
+static int adis16480_debugfs_init(struct iio_dev *indio_dev)
+{
+       return 0;
+}
+
+#endif
+
+static int adis16480_set_freq(struct adis16480 *st, unsigned int freq)
+{
+       unsigned int t;
+
+       t = 2460000 / freq;
+       if (t > 2048)
+               t = 2048;
+
+       if (t != 0)
+               t--;
+
+       return adis_write_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, t);
+}
+
+static int adis16480_get_freq(struct adis16480 *st, unsigned int *freq)
+{
+       uint16_t t;
+       int ret;
+
+       ret = adis_read_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, &t);
+       if (ret < 0)
+               return ret;
+
+       *freq = 2460000 / (t + 1);
+
+       return 0;
+}
+
+static ssize_t adis16480_read_frequency(struct device *dev,
+               struct device_attribute *attr,
+               char *buf)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct adis16480 *st = iio_priv(indio_dev);
+       unsigned int freq;
+       int ret;
+
+       ret = adis16480_get_freq(st, &freq);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d.%.3d\n", freq / 1000, freq % 1000);
+}
+
+static ssize_t adis16480_write_frequency(struct device *dev,
+               struct device_attribute *attr,
+               const char *buf,
+               size_t len)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct adis16480 *st = iio_priv(indio_dev);
+       int freq_int, freq_fract;
+       long val;
+       int ret;
+
+       ret = iio_str_to_fixpoint(buf, 100, &freq_int, &freq_fract);
+       if (ret)
+               return ret;
+
+       val = freq_int * 1000 + freq_fract;
+
+       if (val <= 0)
+               return -EINVAL;
+
+       ret = adis16480_set_freq(st, val);
+
+       return ret ? ret : len;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
+                             adis16480_read_frequency,
+                             adis16480_write_frequency);
+
+enum {
+       ADIS16480_SCAN_GYRO_X,
+       ADIS16480_SCAN_GYRO_Y,
+       ADIS16480_SCAN_GYRO_Z,
+       ADIS16480_SCAN_ACCEL_X,
+       ADIS16480_SCAN_ACCEL_Y,
+       ADIS16480_SCAN_ACCEL_Z,
+       ADIS16480_SCAN_MAGN_X,
+       ADIS16480_SCAN_MAGN_Y,
+       ADIS16480_SCAN_MAGN_Z,
+       ADIS16480_SCAN_BARO,
+       ADIS16480_SCAN_TEMP,
+};
+
+static const unsigned int adis16480_calibbias_regs[] = {
+       [ADIS16480_SCAN_GYRO_X] = ADIS16480_REG_X_GYRO_BIAS,
+       [ADIS16480_SCAN_GYRO_Y] = ADIS16480_REG_Y_GYRO_BIAS,
+       [ADIS16480_SCAN_GYRO_Z] = ADIS16480_REG_Z_GYRO_BIAS,
+       [ADIS16480_SCAN_ACCEL_X] = ADIS16480_REG_X_ACCEL_BIAS,
+       [ADIS16480_SCAN_ACCEL_Y] = ADIS16480_REG_Y_ACCEL_BIAS,
+       [ADIS16480_SCAN_ACCEL_Z] = ADIS16480_REG_Z_ACCEL_BIAS,
+       [ADIS16480_SCAN_MAGN_X] = ADIS16480_REG_X_HARD_IRON,
+       [ADIS16480_SCAN_MAGN_Y] = ADIS16480_REG_Y_HARD_IRON,
+       [ADIS16480_SCAN_MAGN_Z] = ADIS16480_REG_Z_HARD_IRON,
+       [ADIS16480_SCAN_BARO] = ADIS16480_REG_BAROM_BIAS,
+};
+
+static const unsigned int adis16480_calibscale_regs[] = {
+       [ADIS16480_SCAN_GYRO_X] = ADIS16480_REG_X_GYRO_SCALE,
+       [ADIS16480_SCAN_GYRO_Y] = ADIS16480_REG_Y_GYRO_SCALE,
+       [ADIS16480_SCAN_GYRO_Z] = ADIS16480_REG_Z_GYRO_SCALE,
+       [ADIS16480_SCAN_ACCEL_X] = ADIS16480_REG_X_ACCEL_SCALE,
+       [ADIS16480_SCAN_ACCEL_Y] = ADIS16480_REG_Y_ACCEL_SCALE,
+       [ADIS16480_SCAN_ACCEL_Z] = ADIS16480_REG_Z_ACCEL_SCALE,
+};
+
+static int adis16480_set_calibbias(struct iio_dev *indio_dev,
+       const struct iio_chan_spec *chan, int bias)
+{
+       unsigned int reg = adis16480_calibbias_regs[chan->scan_index];
+       struct adis16480 *st = iio_priv(indio_dev);
+
+       switch (chan->type) {
+       case IIO_MAGN:
+       case IIO_PRESSURE:
+               if (bias < -0x8000 || bias >= 0x8000)
+                       return -EINVAL;
+               return adis_write_reg_16(&st->adis, reg, bias);
+       case IIO_ANGL_VEL:
+       case IIO_ACCEL:
+               return adis_write_reg_32(&st->adis, reg, bias);
+       default:
+               break;
+       }
+
+       return -EINVAL;
+}
+
+static int adis16480_get_calibbias(struct iio_dev *indio_dev,
+       const struct iio_chan_spec *chan, int *bias)
+{
+       unsigned int reg = adis16480_calibbias_regs[chan->scan_index];
+       struct adis16480 *st = iio_priv(indio_dev);
+       uint16_t val16;
+       uint32_t val32;
+       int ret;
+
+       switch (chan->type) {
+       case IIO_MAGN:
+       case IIO_PRESSURE:
+               ret = adis_read_reg_16(&st->adis, reg, &val16);
+               *bias = sign_extend32(val16, 15);
+               break;
+       case IIO_ANGL_VEL:
+       case IIO_ACCEL:
+               ret = adis_read_reg_32(&st->adis, reg, &val32);
+               *bias = sign_extend32(val32, 31);
+               break;
+       default:
+                       ret = -EINVAL;
+       }
+
+       if (ret < 0)
+               return ret;
+
+       return IIO_VAL_INT;
+}
+
+static int adis16480_set_calibscale(struct iio_dev *indio_dev,
+       const struct iio_chan_spec *chan, int scale)
+{
+       unsigned int reg = adis16480_calibscale_regs[chan->scan_index];
+       struct adis16480 *st = iio_priv(indio_dev);
+
+       if (scale < -0x8000 || scale >= 0x8000)
+               return -EINVAL;
+
+       return adis_write_reg_16(&st->adis, reg, scale);
+}
+
+static int adis16480_get_calibscale(struct iio_dev *indio_dev,
+       const struct iio_chan_spec *chan, int *scale)
+{
+       unsigned int reg = adis16480_calibscale_regs[chan->scan_index];
+       struct adis16480 *st = iio_priv(indio_dev);
+       uint16_t val16;
+       int ret;
+
+       ret = adis_read_reg_16(&st->adis, reg, &val16);
+       if (ret < 0)
+               return ret;
+
+       *scale = sign_extend32(val16, 15);
+       return IIO_VAL_INT;
+}
+
+static const unsigned int adis16480_def_filter_freqs[] = {
+       310,
+       55,
+       275,
+       63,
+};
+
+static const unsigned int ad16480_filter_data[][2] = {
+       [ADIS16480_SCAN_GYRO_X]         = { ADIS16480_REG_FILTER_BNK0, 0 },
+       [ADIS16480_SCAN_GYRO_Y]         = { ADIS16480_REG_FILTER_BNK0, 3 },
+       [ADIS16480_SCAN_GYRO_Z]         = { ADIS16480_REG_FILTER_BNK0, 6 },
+       [ADIS16480_SCAN_ACCEL_X]        = { ADIS16480_REG_FILTER_BNK0, 9 },
+       [ADIS16480_SCAN_ACCEL_Y]        = { ADIS16480_REG_FILTER_BNK0, 12 },
+       [ADIS16480_SCAN_ACCEL_Z]        = { ADIS16480_REG_FILTER_BNK1, 0 },
+       [ADIS16480_SCAN_MAGN_X]         = { ADIS16480_REG_FILTER_BNK1, 3 },
+       [ADIS16480_SCAN_MAGN_Y]         = { ADIS16480_REG_FILTER_BNK1, 6 },
+       [ADIS16480_SCAN_MAGN_Z]         = { ADIS16480_REG_FILTER_BNK1, 9 },
+};
+
+static int adis16480_get_filter_freq(struct iio_dev *indio_dev,
+       const struct iio_chan_spec *chan, int *freq)
+{
+       struct adis16480 *st = iio_priv(indio_dev);
+       unsigned int enable_mask, offset, reg;
+       uint16_t val;
+       int ret;
+
+       reg = ad16480_filter_data[chan->scan_index][0];
+       offset = ad16480_filter_data[chan->scan_index][1];
+       enable_mask = BIT(offset + 2);
+
+       ret = adis_read_reg_16(&st->adis, reg, &val);
+       if (ret < 0)
+               return ret;
+
+       if (!(val & enable_mask))
+               *freq = 0;
+       else
+               *freq = adis16480_def_filter_freqs[(val >> offset) & 0x3];
+
+       return IIO_VAL_INT;
+}
+
+static int adis16480_set_filter_freq(struct iio_dev *indio_dev,
+       const struct iio_chan_spec *chan, unsigned int freq)
+{
+       struct adis16480 *st = iio_priv(indio_dev);
+       unsigned int enable_mask, offset, reg;
+       unsigned int diff, best_diff;
+       unsigned int i, best_freq;
+       uint16_t val;
+       int ret;
+
+       reg = ad16480_filter_data[chan->scan_index][0];
+       offset = ad16480_filter_data[chan->scan_index][1];
+       enable_mask = BIT(offset + 2);
+
+       ret = adis_read_reg_16(&st->adis, reg, &val);
+       if (ret < 0)
+               return ret;
+
+       if (freq == 0) {
+               val &= ~enable_mask;
+       } else {
+               best_freq = 0;
+               best_diff = 310;
+               for (i = 0; i < ARRAY_SIZE(adis16480_def_filter_freqs); i++) {
+                       if (adis16480_def_filter_freqs[i] >= freq) {
+                               diff = adis16480_def_filter_freqs[i] - freq;
+                               if (diff < best_diff) {
+                                       best_diff = diff;
+                                       best_freq = i;
+                               }
+                       }
+               }
+
+               val &= ~(0x3 << offset);
+               val |= best_freq << offset;
+               val |= enable_mask;
+       }
+
+       return adis_write_reg_16(&st->adis, reg, val);
+}
+
+static int adis16480_read_raw(struct iio_dev *indio_dev,
+       const struct iio_chan_spec *chan, int *val, int *val2, long info)
+{
+       switch (info) {
+       case IIO_CHAN_INFO_RAW:
+               return adis_single_conversion(indio_dev, chan, 0, val);
+       case IIO_CHAN_INFO_SCALE:
+               switch (chan->type) {
+               case IIO_ANGL_VEL:
+                       *val = 0;
+                       *val2 = IIO_DEGREE_TO_RAD(20000); /* 0.02 degree/sec */
+                       return IIO_VAL_INT_PLUS_MICRO;
+               case IIO_ACCEL:
+                       *val = 0;
+                       *val2 = IIO_G_TO_M_S_2(800); /* 0.8 mg */
+                       return IIO_VAL_INT_PLUS_MICRO;
+               case IIO_MAGN:
+                       *val = 0;
+                       *val2 = 100; /* 0.0001 gauss */
+                       return IIO_VAL_INT_PLUS_MICRO;
+               case IIO_TEMP:
+                       *val = 5;
+                       *val2 = 650000; /* 5.65 milli degree Celsius */
+                       return IIO_VAL_INT_PLUS_MICRO;
+               case IIO_PRESSURE:
+                       *val = 0;
+                       *val2 = 4000; /* 40ubar = 0.004 kPa */
+                       return IIO_VAL_INT_PLUS_MICRO;
+               default:
+                       return -EINVAL;
+               }
+       case IIO_CHAN_INFO_OFFSET:
+               /* Only the temperature channel has a offset */
+               *val = 4425; /* 25 degree Celsius = 0x0000 */
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_CALIBBIAS:
+               return adis16480_get_calibbias(indio_dev, chan, val);
+       case IIO_CHAN_INFO_CALIBSCALE:
+               return adis16480_get_calibscale(indio_dev, chan, val);
+       case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+               return adis16480_get_filter_freq(indio_dev, chan, val);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int adis16480_write_raw(struct iio_dev *indio_dev,
+       const struct iio_chan_spec *chan, int val, int val2, long info)
+{
+       switch (info) {
+       case IIO_CHAN_INFO_CALIBBIAS:
+               return adis16480_set_calibbias(indio_dev, chan, val);
+       case IIO_CHAN_INFO_CALIBSCALE:
+               return adis16480_set_calibscale(indio_dev, chan, val);
+       case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+               return adis16480_set_filter_freq(indio_dev, chan, val);
+       default:
+               return -EINVAL;
+       }
+}
+
+#define ADIS16480_MOD_CHANNEL(_type, _mod, _address, _si, _info, _bits) \
+       { \
+               .type = (_type), \
+               .modified = 1, \
+               .channel2 = (_mod), \
+               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+                       IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
+                       IIO_CHAN_INFO_SCALE_SHARED_BIT | \
+                       _info, \
+               .address = (_address), \
+               .scan_index = (_si), \
+               .scan_type = { \
+                       .sign = 's', \
+                       .realbits = (_bits), \
+                       .storagebits = (_bits), \
+                       .endianness = IIO_BE, \
+               }, \
+       }
+
+#define ADIS16480_GYRO_CHANNEL(_mod) \
+       ADIS16480_MOD_CHANNEL(IIO_ANGL_VEL, IIO_MOD_ ## _mod, \
+       ADIS16480_REG_ ## _mod ## _GYRO_OUT, ADIS16480_SCAN_GYRO_ ## _mod, \
+       IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT | \
+       IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, \
+       32)
+
+#define ADIS16480_ACCEL_CHANNEL(_mod) \
+       ADIS16480_MOD_CHANNEL(IIO_ACCEL, IIO_MOD_ ## _mod, \
+       ADIS16480_REG_ ## _mod ## _ACCEL_OUT, ADIS16480_SCAN_ACCEL_ ## _mod, \
+       IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT | \
+       IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, \
+       32)
+
+#define ADIS16480_MAGN_CHANNEL(_mod) \
+       ADIS16480_MOD_CHANNEL(IIO_MAGN, IIO_MOD_ ## _mod, \
+       ADIS16480_REG_ ## _mod ## _MAGN_OUT, ADIS16480_SCAN_MAGN_ ## _mod, \
+       IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT, \
+       16)
+
+#define ADIS16480_PRESSURE_CHANNEL() \
+       { \
+               .type = IIO_PRESSURE, \
+               .indexed = 1, \
+               .channel = 0, \
+               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+                       IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
+                       IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+               .address = ADIS16480_REG_BAROM_OUT, \
+               .scan_index = ADIS16480_SCAN_BARO, \
+               .scan_type = { \
+                       .sign = 's', \
+                       .realbits = 32, \
+                       .storagebits = 32, \
+                       .endianness = IIO_BE, \
+               }, \
+       }
+
+#define ADIS16480_TEMP_CHANNEL() { \
+               .type = IIO_TEMP, \
+               .indexed = 1, \
+               .channel = 0, \
+               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+                       IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
+                       IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, \
+               .address = ADIS16480_REG_TEMP_OUT, \
+               .scan_index = ADIS16480_SCAN_TEMP, \
+               .scan_type = { \
+                       .sign = 's', \
+                       .realbits = 16, \
+                       .storagebits = 16, \
+                       .endianness = IIO_BE, \
+               }, \
+       }
+
+static const struct iio_chan_spec adis16480_channels[] = {
+       ADIS16480_GYRO_CHANNEL(X),
+       ADIS16480_GYRO_CHANNEL(Y),
+       ADIS16480_GYRO_CHANNEL(Z),
+       ADIS16480_ACCEL_CHANNEL(X),
+       ADIS16480_ACCEL_CHANNEL(Y),
+       ADIS16480_ACCEL_CHANNEL(Z),
+       ADIS16480_MAGN_CHANNEL(X),
+       ADIS16480_MAGN_CHANNEL(Y),
+       ADIS16480_MAGN_CHANNEL(Z),
+       ADIS16480_PRESSURE_CHANNEL(),
+       ADIS16480_TEMP_CHANNEL(),
+       IIO_CHAN_SOFT_TIMESTAMP(11)
+};
+
+static const struct iio_chan_spec adis16485_channels[] = {
+       ADIS16480_GYRO_CHANNEL(X),
+       ADIS16480_GYRO_CHANNEL(Y),
+       ADIS16480_GYRO_CHANNEL(Z),
+       ADIS16480_ACCEL_CHANNEL(X),
+       ADIS16480_ACCEL_CHANNEL(Y),
+       ADIS16480_ACCEL_CHANNEL(Z),
+       ADIS16480_TEMP_CHANNEL(),
+       IIO_CHAN_SOFT_TIMESTAMP(7)
+};
+
+enum adis16480_variant {
+       ADIS16375,
+       ADIS16480,
+       ADIS16485,
+       ADIS16488,
+};
+
+static const struct adis16480_chip_info adis16480_chip_info[] = {
+       [ADIS16375] = {
+               .channels = adis16485_channels,
+               .num_channels = ARRAY_SIZE(adis16485_channels),
+       },
+       [ADIS16480] = {
+               .channels = adis16480_channels,
+               .num_channels = ARRAY_SIZE(adis16480_channels),
+       },
+       [ADIS16485] = {
+               .channels = adis16485_channels,
+               .num_channels = ARRAY_SIZE(adis16485_channels),
+       },
+       [ADIS16488] = {
+               .channels = adis16480_channels,
+               .num_channels = ARRAY_SIZE(adis16480_channels),
+       },
+};
+
+static struct attribute *adis16480_attributes[] = {
+       &iio_dev_attr_sampling_frequency.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group adis16480_attribute_group = {
+       .attrs = adis16480_attributes,
+};
+
+static const struct iio_info adis16480_info = {
+       .attrs = &adis16480_attribute_group,
+       .read_raw = &adis16480_read_raw,
+       .write_raw = &adis16480_write_raw,
+       .update_scan_mode = adis_update_scan_mode,
+       .driver_module = THIS_MODULE,
+};
+
+static int adis16480_stop_device(struct iio_dev *indio_dev)
+{
+       struct adis16480 *st = iio_priv(indio_dev);
+       int ret;
+
+       ret = adis_write_reg_16(&st->adis, ADIS16480_REG_SLP_CNT, BIT(9));
+       if (ret)
+               dev_err(&indio_dev->dev,
+                       "Could not power down device: %d\n", ret);
+
+       return ret;
+}
+
+static int adis16480_enable_irq(struct adis *adis, bool enable)
+{
+       return adis_write_reg_16(adis, ADIS16480_REG_FNCTIO_CTRL,
+               enable ? BIT(3) : 0);
+}
+
+static int adis16480_initial_setup(struct iio_dev *indio_dev)
+{
+       struct adis16480 *st = iio_priv(indio_dev);
+       uint16_t prod_id;
+       unsigned int device_id;
+       int ret;
+
+       adis_reset(&st->adis);
+       msleep(70);
+
+       ret = adis_write_reg_16(&st->adis, ADIS16480_REG_GLOB_CMD, BIT(1));
+       if (ret)
+               return ret;
+       msleep(30);
+
+       ret = adis_check_status(&st->adis);
+       if (ret)
+               return ret;
+
+       ret = adis_read_reg_16(&st->adis, ADIS16480_REG_PROD_ID, &prod_id);
+       if (ret)
+               return ret;
+
+       sscanf(indio_dev->name, "adis%u\n", &device_id);
+
+       if (prod_id != device_id)
+               dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.",
+                               device_id, prod_id);
+
+       return 0;
+}
+
+#define ADIS16480_DIAG_STAT_XGYRO_FAIL 0
+#define ADIS16480_DIAG_STAT_YGYRO_FAIL 1
+#define ADIS16480_DIAG_STAT_ZGYRO_FAIL 2
+#define ADIS16480_DIAG_STAT_XACCL_FAIL 3
+#define ADIS16480_DIAG_STAT_YACCL_FAIL 4
+#define ADIS16480_DIAG_STAT_ZACCL_FAIL 5
+#define ADIS16480_DIAG_STAT_XMAGN_FAIL 8
+#define ADIS16480_DIAG_STAT_YMAGN_FAIL 9
+#define ADIS16480_DIAG_STAT_ZMAGN_FAIL 10
+#define ADIS16480_DIAG_STAT_BARO_FAIL 11
+
+static const char * const adis16480_status_error_msgs[] = {
+       [ADIS16480_DIAG_STAT_XGYRO_FAIL] = "X-axis gyroscope self-test failure",
+       [ADIS16480_DIAG_STAT_YGYRO_FAIL] = "Y-axis gyroscope self-test failure",
+       [ADIS16480_DIAG_STAT_ZGYRO_FAIL] = "Z-axis gyroscope self-test failure",
+       [ADIS16480_DIAG_STAT_XACCL_FAIL] = "X-axis accelerometer self-test failure",
+       [ADIS16480_DIAG_STAT_YACCL_FAIL] = "Y-axis accelerometer self-test failure",
+       [ADIS16480_DIAG_STAT_ZACCL_FAIL] = "Z-axis accelerometer self-test failure",
+       [ADIS16480_DIAG_STAT_XMAGN_FAIL] = "X-axis magnetometer self-test failure",
+       [ADIS16480_DIAG_STAT_YMAGN_FAIL] = "Y-axis magnetometer self-test failure",
+       [ADIS16480_DIAG_STAT_ZMAGN_FAIL] = "Z-axis magnetometer self-test failure",
+       [ADIS16480_DIAG_STAT_BARO_FAIL] = "Barometer self-test failure",
+};
+
+static const struct adis_data adis16480_data = {
+       .diag_stat_reg = ADIS16480_REG_DIAG_STS,
+       .glob_cmd_reg = ADIS16480_REG_GLOB_CMD,
+       .has_paging = true,
+
+       .read_delay = 5,
+       .write_delay = 5,
+
+       .status_error_msgs = adis16480_status_error_msgs,
+       .status_error_mask = BIT(ADIS16480_DIAG_STAT_XGYRO_FAIL) |
+               BIT(ADIS16480_DIAG_STAT_YGYRO_FAIL) |
+               BIT(ADIS16480_DIAG_STAT_ZGYRO_FAIL) |
+               BIT(ADIS16480_DIAG_STAT_XACCL_FAIL) |
+               BIT(ADIS16480_DIAG_STAT_YACCL_FAIL) |
+               BIT(ADIS16480_DIAG_STAT_ZACCL_FAIL) |
+               BIT(ADIS16480_DIAG_STAT_XMAGN_FAIL) |
+               BIT(ADIS16480_DIAG_STAT_YMAGN_FAIL) |
+               BIT(ADIS16480_DIAG_STAT_ZMAGN_FAIL) |
+               BIT(ADIS16480_DIAG_STAT_BARO_FAIL),
+
+       .enable_irq = adis16480_enable_irq,
+};
+
+static int adis16480_probe(struct spi_device *spi)
+{
+       const struct spi_device_id *id = spi_get_device_id(spi);
+       struct iio_dev *indio_dev;
+       struct adis16480 *st;
+       int ret;
+
+       indio_dev = iio_device_alloc(sizeof(*st));
+       if (indio_dev == NULL)
+               return -ENOMEM;
+
+       spi_set_drvdata(spi, indio_dev);
+
+       st = iio_priv(indio_dev);
+
+       st->chip_info = &adis16480_chip_info[id->driver_data];
+       indio_dev->dev.parent = &spi->dev;
+       indio_dev->name = spi_get_device_id(spi)->name;
+       indio_dev->channels = st->chip_info->channels;
+       indio_dev->num_channels = st->chip_info->num_channels;
+       indio_dev->info = &adis16480_info;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+
+       ret = adis_init(&st->adis, indio_dev, spi, &adis16480_data);
+       if (ret)
+               goto error_free_dev;
+
+       ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL);
+       if (ret)
+               goto error_free_dev;
+
+       ret = adis16480_initial_setup(indio_dev);
+       if (ret)
+               goto error_cleanup_buffer;
+
+       ret = iio_device_register(indio_dev);
+       if (ret)
+               goto error_stop_device;
+
+       adis16480_debugfs_init(indio_dev);
+
+       return 0;
+
+error_stop_device:
+       adis16480_stop_device(indio_dev);
+error_cleanup_buffer:
+       adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
+error_free_dev:
+       iio_device_free(indio_dev);
+       return ret;
+}
+
+static int adis16480_remove(struct spi_device *spi)
+{
+       struct iio_dev *indio_dev = spi_get_drvdata(spi);
+       struct adis16480 *st = iio_priv(indio_dev);
+
+       iio_device_unregister(indio_dev);
+       adis16480_stop_device(indio_dev);
+
+       adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
+
+       iio_device_free(indio_dev);
+
+       return 0;
+}
+
+static const struct spi_device_id adis16480_ids[] = {
+       { "adis16375", ADIS16375 },
+       { "adis16480", ADIS16480 },
+       { "adis16485", ADIS16485 },
+       { "adis16488", ADIS16488 },
+       { }
+};
+MODULE_DEVICE_TABLE(spi, adis16480_ids);
+
+static struct spi_driver adis16480_driver = {
+       .driver = {
+               .name = "adis16480",
+               .owner = THIS_MODULE,
+       },
+       .id_table = adis16480_ids,
+       .probe = adis16480_probe,
+       .remove = adis16480_remove,
+};
+module_spi_driver(adis16480_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Analog Devices ADIS16480 IMU driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c
new file mode 100644 (file)
index 0000000..99d8e0b
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Common library for ADIS16XXX devices
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *   Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/export.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/imu/adis.h>
+
+int adis_update_scan_mode(struct iio_dev *indio_dev,
+       const unsigned long *scan_mask)
+{
+       struct adis *adis = iio_device_get_drvdata(indio_dev);
+       const struct iio_chan_spec *chan;
+       unsigned int scan_count;
+       unsigned int i, j;
+       __be16 *tx, *rx;
+
+       kfree(adis->xfer);
+       kfree(adis->buffer);
+
+       scan_count = indio_dev->scan_bytes / 2;
+
+       adis->xfer = kcalloc(scan_count + 1, sizeof(*adis->xfer), GFP_KERNEL);
+       if (!adis->xfer)
+               return -ENOMEM;
+
+       adis->buffer = kzalloc(indio_dev->scan_bytes * 2, GFP_KERNEL);
+       if (!adis->buffer)
+               return -ENOMEM;
+
+       rx = adis->buffer;
+       tx = rx + indio_dev->scan_bytes;
+
+       spi_message_init(&adis->msg);
+
+       for (j = 0; j <= scan_count; j++) {
+               adis->xfer[j].bits_per_word = 8;
+               if (j != scan_count)
+                       adis->xfer[j].cs_change = 1;
+               adis->xfer[j].len = 2;
+               adis->xfer[j].delay_usecs = adis->data->read_delay;
+               if (j < scan_count)
+                       adis->xfer[j].tx_buf = &tx[j];
+               if (j >= 1)
+                       adis->xfer[j].rx_buf = &rx[j - 1];
+               spi_message_add_tail(&adis->xfer[j], &adis->msg);
+       }
+
+       chan = indio_dev->channels;
+       for (i = 0; i < indio_dev->num_channels; i++, chan++) {
+               if (!test_bit(chan->scan_index, scan_mask))
+                       continue;
+               if (chan->scan_type.storagebits == 32)
+                       *tx++ = cpu_to_be16((chan->address + 2) << 8);
+               *tx++ = cpu_to_be16(chan->address << 8);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(adis_update_scan_mode);
+
+static irqreturn_t adis_trigger_handler(int irq, void *p)
+{
+       struct iio_poll_func *pf = p;
+       struct iio_dev *indio_dev = pf->indio_dev;
+       struct adis *adis = iio_device_get_drvdata(indio_dev);
+       int ret;
+
+       if (!adis->buffer)
+               return -ENOMEM;
+
+       if (adis->data->has_paging) {
+               mutex_lock(&adis->txrx_lock);
+               if (adis->current_page != 0) {
+                       adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID);
+                       adis->tx[1] = 0;
+                       spi_write(adis->spi, adis->tx, 2);
+               }
+       }
+
+       ret = spi_sync(adis->spi, &adis->msg);
+       if (ret)
+               dev_err(&adis->spi->dev, "Failed to read data: %d", ret);
+
+
+       if (adis->data->has_paging) {
+               adis->current_page = 0;
+               mutex_unlock(&adis->txrx_lock);
+       }
+
+       /* Guaranteed to be aligned with 8 byte boundary */
+       if (indio_dev->scan_timestamp) {
+               void *b = adis->buffer + indio_dev->scan_bytes - sizeof(s64);
+               *(s64 *)b = pf->timestamp;
+       }
+
+       iio_push_to_buffers(indio_dev, adis->buffer);
+
+       iio_trigger_notify_done(indio_dev->trig);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * adis_setup_buffer_and_trigger() - Sets up buffer and trigger for the adis device
+ * @adis: The adis device.
+ * @indio_dev: The IIO device.
+ * @trigger_handler: Optional trigger handler, may be NULL.
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * This function sets up the buffer and trigger for a adis devices.  If
+ * 'trigger_handler' is NULL the default trigger handler will be used. The
+ * default trigger handler will simply read the registers assigned to the
+ * currently active channels.
+ *
+ * adis_cleanup_buffer_and_trigger() should be called to free the resources
+ * allocated by this function.
+ */
+int adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev,
+       irqreturn_t (*trigger_handler)(int, void *))
+{
+       int ret;
+
+       if (!trigger_handler)
+               trigger_handler = adis_trigger_handler;
+
+       ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+               trigger_handler, NULL);
+       if (ret)
+               return ret;
+
+       if (adis->spi->irq) {
+               ret = adis_probe_trigger(adis, indio_dev);
+               if (ret)
+                       goto error_buffer_cleanup;
+       }
+       return 0;
+
+error_buffer_cleanup:
+       iio_triggered_buffer_cleanup(indio_dev);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(adis_setup_buffer_and_trigger);
+
+/**
+ * adis_cleanup_buffer_and_trigger() - Free buffer and trigger resources
+ * @adis: The adis device.
+ * @indio_dev: The IIO device.
+ *
+ * Frees resources allocated by adis_setup_buffer_and_trigger()
+ */
+void adis_cleanup_buffer_and_trigger(struct adis *adis,
+       struct iio_dev *indio_dev)
+{
+       if (adis->spi->irq)
+               adis_remove_trigger(adis);
+       kfree(adis->buffer);
+       kfree(adis->xfer);
+       iio_triggered_buffer_cleanup(indio_dev);
+}
+EXPORT_SYMBOL_GPL(adis_cleanup_buffer_and_trigger);
diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c
new file mode 100644 (file)
index 0000000..5a24c9c
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Common library for ADIS16XXX devices
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *   Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/export.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/imu/adis.h>
+
+static int adis_data_rdy_trigger_set_state(struct iio_trigger *trig,
+                                               bool state)
+{
+       struct adis *adis = trig->private_data;
+
+       return adis_enable_irq(adis, state);
+}
+
+static const struct iio_trigger_ops adis_trigger_ops = {
+       .owner = THIS_MODULE,
+       .set_trigger_state = &adis_data_rdy_trigger_set_state,
+};
+
+/**
+ * adis_probe_trigger() - Sets up trigger for a adis device
+ * @adis: The adis device
+ * @indio_dev: The IIO device
+ *
+ * Returns 0 on success or a negative error code
+ *
+ * adis_remove_trigger() should be used to free the trigger.
+ */
+int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
+{
+       int ret;
+
+       adis->trig = iio_trigger_alloc("%s-dev%d", indio_dev->name,
+                                       indio_dev->id);
+       if (adis->trig == NULL)
+               return -ENOMEM;
+
+       ret = request_irq(adis->spi->irq,
+                         &iio_trigger_generic_data_rdy_poll,
+                         IRQF_TRIGGER_RISING,
+                         indio_dev->name,
+                         adis->trig);
+       if (ret)
+               goto error_free_trig;
+
+       adis->trig->dev.parent = &adis->spi->dev;
+       adis->trig->ops = &adis_trigger_ops;
+       adis->trig->private_data = adis;
+       ret = iio_trigger_register(adis->trig);
+
+       indio_dev->trig = adis->trig;
+       if (ret)
+               goto error_free_irq;
+
+       return 0;
+
+error_free_irq:
+       free_irq(adis->spi->irq, adis->trig);
+error_free_trig:
+       iio_trigger_free(adis->trig);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(adis_probe_trigger);
+
+/**
+ * adis_remove_trigger() - Remove trigger for a adis devices
+ * @adis: The adis device
+ *
+ * Removes the trigger previously registered with adis_probe_trigger().
+ */
+void adis_remove_trigger(struct adis *adis)
+{
+       iio_trigger_unregister(adis->trig);
+       free_irq(adis->spi->irq, adis->trig);
+       iio_trigger_free(adis->trig);
+}
+EXPORT_SYMBOL_GPL(adis_remove_trigger);
index 060a4045be85e00536f9a018524bcf03b3b72af6..8848f16c547b07a44e2de1f1834283b8f88e8fb5 100644 (file)
@@ -65,6 +65,7 @@ static const char * const iio_chan_type_name_spec[] = {
        [IIO_CAPACITANCE] = "capacitance",
        [IIO_ALTVOLTAGE] = "altvoltage",
        [IIO_CCT] = "cct",
+       [IIO_PRESSURE] = "pressure",
 };
 
 static const char * const iio_modifier_names[] = {
@@ -407,6 +408,64 @@ static ssize_t iio_read_channel_info(struct device *dev,
        }
 }
 
+/**
+ * iio_str_to_fixpoint() - Parse a fixed-point number from a string
+ * @str: The string to parse
+ * @fract_mult: Multiplier for the first decimal place, should be a power of 10
+ * @integer: The integer part of the number
+ * @fract: The fractional part of the number
+ *
+ * Returns 0 on success, or a negative error code if the string could not be
+ * parsed.
+ */
+int iio_str_to_fixpoint(const char *str, int fract_mult,
+       int *integer, int *fract)
+{
+       int i = 0, f = 0;
+       bool integer_part = true, negative = false;
+
+       if (str[0] == '-') {
+               negative = true;
+               str++;
+       } else if (str[0] == '+') {
+               str++;
+       }
+
+       while (*str) {
+               if ('0' <= *str && *str <= '9') {
+                       if (integer_part) {
+                               i = i * 10 + *str - '0';
+                       } else {
+                               f += fract_mult * (*str - '0');
+                               fract_mult /= 10;
+                       }
+               } else if (*str == '\n') {
+                       if (*(str + 1) == '\0')
+                               break;
+                       else
+                               return -EINVAL;
+               } else if (*str == '.' && integer_part) {
+                       integer_part = false;
+               } else {
+                       return -EINVAL;
+               }
+               str++;
+       }
+
+       if (negative) {
+               if (i)
+                       i = -i;
+               else
+                       f = -f;
+       }
+
+       *integer = i;
+       *fract = f;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(iio_str_to_fixpoint);
+
 static ssize_t iio_write_channel_info(struct device *dev,
                                      struct device_attribute *attr,
                                      const char *buf,
@@ -414,8 +473,8 @@ static ssize_t iio_write_channel_info(struct device *dev,
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-       int ret, integer = 0, fract = 0, fract_mult = 100000;
-       bool integer_part = true, negative = false;
+       int ret, fract_mult = 100000;
+       int integer, fract;
 
        /* Assumes decimal - precision based on number of digits */
        if (!indio_dev->info->write_raw)
@@ -434,39 +493,9 @@ static ssize_t iio_write_channel_info(struct device *dev,
                        return -EINVAL;
                }
 
-       if (buf[0] == '-') {
-               negative = true;
-               buf++;
-       } else if (buf[0] == '+') {
-               buf++;
-       }
-
-       while (*buf) {
-               if ('0' <= *buf && *buf <= '9') {
-                       if (integer_part)
-                               integer = integer*10 + *buf - '0';
-                       else {
-                               fract += fract_mult*(*buf - '0');
-                               fract_mult /= 10;
-                       }
-               } else if (*buf == '\n') {
-                       if (*(buf + 1) == '\0')
-                               break;
-                       else
-                               return -EINVAL;
-               } else if (*buf == '.' && integer_part) {
-                       integer_part = false;
-               } else {
-                       return -EINVAL;
-               }
-               buf++;
-       }
-       if (negative) {
-               if (integer)
-                       integer = -integer;
-               else
-                       fract = -fract;
-       }
+       ret = iio_str_to_fixpoint(buf, fract_mult, &integer, &fract);
+       if (ret)
+               return ret;
 
        ret = indio_dev->info->write_raw(indio_dev, this_attr->c,
                                         integer, fract, this_attr->address);
index 857e6306c5c335560b30dfda06148b39c275ea32..261cae00557e06f98c029d18c432ec14cb1b15e4 100644 (file)
@@ -350,15 +350,10 @@ static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev)
                ret = iio_device_add_event_sysfs(indio_dev,
                                                 &indio_dev->channels[j]);
                if (ret < 0)
-                       goto error_clear_attrs;
+                       return ret;
                attrcount += ret;
        }
        return attrcount;
-
-error_clear_attrs:
-       __iio_remove_event_config_attrs(indio_dev);
-
-       return ret;
 }
 
 static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev)
index 8e1f69844eea796da357ac67aded7959a7c70557..23eeeef64e84b93e656ccb07a21dfd57c90a8190 100644 (file)
@@ -272,10 +272,9 @@ static int __devinit hid_als_probe(struct platform_device *pdev)
                goto error_free_dev;
        }
 
-       channels = kmemdup(als_channels,
-                                       sizeof(als_channels),
-                                       GFP_KERNEL);
+       channels = kmemdup(als_channels, sizeof(als_channels), GFP_KERNEL);
        if (!channels) {
+               ret = -ENOMEM;
                dev_err(&pdev->dev, "failed to duplicate channels\n");
                goto error_free_dev;
        }
index d1b5fb74b9bf1b92091287223f2cd0e8a28e5882..8e75eb76ccd992729785c340e7eaea801026ec89 100644 (file)
@@ -307,10 +307,10 @@ static int __devinit hid_magn_3d_probe(struct platform_device *pdev)
                goto error_free_dev;
        }
 
-       channels = kmemdup(magn_3d_channels,
-                                       sizeof(magn_3d_channels),
-                                       GFP_KERNEL);
+       channels = kmemdup(magn_3d_channels, sizeof(magn_3d_channels),
+                          GFP_KERNEL);
        if (!channels) {
+               ret = -ENOMEM;
                dev_err(&pdev->dev, "failed to duplicate channels\n");
                goto error_free_dev;
        }
index 5ab71670b70f1f7ddb10009df8e2c3b1a5ac78ec..2b54430f2d994aa5ec9c3b38ab54b2623daa1ec6 100644 (file)
@@ -6,8 +6,8 @@ menu "Accelerometers"
 config ADIS16201
        tristate "Analog Devices ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer"
        depends on SPI
-       select IIO_TRIGGER if IIO_BUFFER
-       select IIO_SW_RING if IIO_BUFFER
+       select IIO_ADIS_LIB
+       select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
        help
          Say yes here to build support for Analog Devices adis16201 dual-axis
          digital inclinometer and accelerometer.
@@ -15,8 +15,8 @@ config ADIS16201
 config ADIS16203
        tristate "Analog Devices ADIS16203 Programmable 360 Degrees Inclinometer"
        depends on SPI
-       select IIO_TRIGGER if IIO_BUFFER
-       select IIO_SW_RING if IIO_BUFFER
+       select IIO_ADIS_LIB
+       select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
        help
          Say yes here to build support for Analog Devices adis16203 Programmable
          360 Degrees Inclinometer.
@@ -24,8 +24,8 @@ config ADIS16203
 config ADIS16204
        tristate "Analog Devices ADIS16204 Programmable High-g Digital Impact Sensor and Recorder"
        depends on SPI
-       select IIO_TRIGGER if IIO_BUFFER
-       select IIO_SW_RING if IIO_BUFFER
+       select IIO_ADIS_LIB
+       select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
        help
          Say yes here to build support for Analog Devices adis16204 Programmable
          High-g Digital Impact Sensor and Recorder.
@@ -33,8 +33,8 @@ config ADIS16204
 config ADIS16209
        tristate "Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer"
        depends on SPI
-       select IIO_TRIGGER if IIO_BUFFER
-       select IIO_SW_RING if IIO_BUFFER
+       select IIO_ADIS_LIB
+       select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
        help
          Say yes here to build support for Analog Devices adis16209 dual-axis digital inclinometer
          and accelerometer.
@@ -42,6 +42,7 @@ config ADIS16209
 config ADIS16220
        tristate "Analog Devices ADIS16220 Programmable Digital Vibration Sensor"
        depends on SPI
+       select IIO_ADIS_LIB
        help
          Say yes here to build support for Analog Devices adis16220 programmable
          digital vibration sensor.
@@ -49,8 +50,8 @@ config ADIS16220
 config ADIS16240
        tristate "Analog Devices ADIS16240 Programmable Impact Sensor and Recorder"
        depends on SPI
-       select IIO_TRIGGER if IIO_BUFFER
-       select IIO_SW_RING if IIO_BUFFER
+       select IIO_ADIS_LIB
+       select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
        help
          Say yes here to build support for Analog Devices adis16240 programmable
          impact Sensor and recorder.
index 95c66661e70200d83904281656b45e23171ec827..8e7ee0368519c7836e77f75bab145d28748b42f5 100644 (file)
@@ -3,26 +3,21 @@
 #
 
 adis16201-y             := adis16201_core.o
-adis16201-$(CONFIG_IIO_BUFFER) += adis16201_ring.o adis16201_trigger.o
 obj-$(CONFIG_ADIS16201) += adis16201.o
 
 adis16203-y             := adis16203_core.o
-adis16203-$(CONFIG_IIO_BUFFER) += adis16203_ring.o adis16203_trigger.o
 obj-$(CONFIG_ADIS16203) += adis16203.o
 
 adis16204-y             := adis16204_core.o
-adis16204-$(CONFIG_IIO_BUFFER) += adis16204_ring.o adis16204_trigger.o
 obj-$(CONFIG_ADIS16204) += adis16204.o
 
 adis16209-y             := adis16209_core.o
-adis16209-$(CONFIG_IIO_BUFFER) += adis16209_ring.o adis16209_trigger.o
 obj-$(CONFIG_ADIS16209) += adis16209.o
 
 adis16220-y             := adis16220_core.o
 obj-$(CONFIG_ADIS16220) += adis16220.o
 
 adis16240-y             := adis16240_core.o
-adis16240-$(CONFIG_IIO_BUFFER) += adis16240_ring.o adis16240_trigger.o
 obj-$(CONFIG_ADIS16240) += adis16240.o
 
 obj-$(CONFIG_KXSD9)    += kxsd9.o
index 72750f7f3a81c3940e3bd07529017844a81f98a1..8747de5a98055b9bba8fdda9b18146bfd51beea1 100644 (file)
@@ -3,9 +3,6 @@
 
 #define ADIS16201_STARTUP_DELAY        220 /* ms */
 
-#define ADIS16201_READ_REG(a)    a
-#define ADIS16201_WRITE_REG(a) ((a) | 0x80)
-
 #define ADIS16201_FLASH_CNT      0x00 /* Flash memory write count */
 #define ADIS16201_SUPPLY_OUT     0x02 /* Output, power supply */
 #define ADIS16201_XACCL_OUT      0x04 /* Output, x-axis accelerometer */
@@ -36,8 +33,6 @@
 #define ADIS16201_DIAG_STAT      0x3C /* Diagnostics, system status register */
 #define ADIS16201_GLOB_CMD       0x3E /* Operation, system command register */
 
-#define ADIS16201_OUTPUTS        7
-
 /* MSC_CTRL */
 #define ADIS16201_MSC_CTRL_SELF_TEST_EN                (1 << 8)  /* Self-test enable */
 #define ADIS16201_MSC_CTRL_DATA_RDY_EN         (1 << 2)  /* Data-ready enable: 1 = enabled, 0 = disabled */
 /* DIAG_STAT */
 #define ADIS16201_DIAG_STAT_ALARM2        (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
 #define ADIS16201_DIAG_STAT_ALARM1        (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
-#define ADIS16201_DIAG_STAT_SPI_FAIL     (1<<3) /* SPI communications failure */
-#define ADIS16201_DIAG_STAT_FLASH_UPT    (1<<2) /* Flash update failure */
-#define ADIS16201_DIAG_STAT_POWER_HIGH   (1<<1) /* Power supply above 3.625 V */
-#define ADIS16201_DIAG_STAT_POWER_LOW    (1<<0) /* Power supply below 3.15 V */
+#define ADIS16201_DIAG_STAT_SPI_FAIL_BIT   3 /* SPI communications failure */
+#define ADIS16201_DIAG_STAT_FLASH_UPT_BIT  2 /* Flash update failure */
+#define ADIS16201_DIAG_STAT_POWER_HIGH_BIT 1 /* Power supply above 3.625 V */
+#define ADIS16201_DIAG_STAT_POWER_LOW_BIT  0 /* Power supply below 3.15 V */
 
 /* GLOB_CMD */
 #define ADIS16201_GLOB_CMD_SW_RESET    (1<<7)
 #define ADIS16201_GLOB_CMD_FACTORY_CAL (1<<1)
 
-#define ADIS16201_MAX_TX 14
-#define ADIS16201_MAX_RX 14
-
 #define ADIS16201_ERROR_ACTIVE          (1<<14)
 
-/**
- * struct adis16201_state - device instance specific data
- * @us:                        actual spi_device
- * @trig:              data ready trigger registered with iio
- * @tx:                        transmit buffer
- * @rx:                        receive buffer
- * @buf_lock:          mutex to protect tx and rx
- **/
-struct adis16201_state {
-       struct spi_device       *us;
-       struct iio_trigger      *trig;
-       struct mutex            buf_lock;
-       u8                      tx[14] ____cacheline_aligned;
-       u8                      rx[14];
-};
-
-int adis16201_set_irq(struct iio_dev *indio_dev, bool enable);
-
 enum adis16201_scan {
-       ADIS16201_SCAN_SUPPLY,
        ADIS16201_SCAN_ACC_X,
        ADIS16201_SCAN_ACC_Y,
-       ADIS16201_SCAN_AUX_ADC,
-       ADIS16201_SCAN_TEMP,
        ADIS16201_SCAN_INCLI_X,
        ADIS16201_SCAN_INCLI_Y,
+       ADIS16201_SCAN_SUPPLY,
+       ADIS16201_SCAN_AUX_ADC,
+       ADIS16201_SCAN_TEMP,
 };
 
-#ifdef CONFIG_IIO_BUFFER
-void adis16201_remove_trigger(struct iio_dev *indio_dev);
-int adis16201_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16201_read_data_from_ring(struct device *dev,
-                                     struct device_attribute *attr,
-                                     char *buf);
-
-int adis16201_configure_ring(struct iio_dev *indio_dev);
-void adis16201_unconfigure_ring(struct iio_dev *indio_dev);
-
-#else /* CONFIG_IIO_BUFFER */
-
-static inline void adis16201_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16201_probe_trigger(struct iio_dev *indio_dev)
-{
-       return 0;
-}
-
-static inline ssize_t
-adis16201_read_data_from_ring(struct device *dev,
-                             struct device_attribute *attr,
-                             char *buf)
-{
-       return 0;
-}
-
-static int adis16201_configure_ring(struct iio_dev *indio_dev)
-{
-       return 0;
-}
-
-static inline void adis16201_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16201_initialize_ring(struct iio_ring_buffer *ring)
-{
-       return 0;
-}
-
-static inline void adis16201_uninitialize_ring(struct iio_ring_buffer *ring)
-{
-}
-
-#endif /* CONFIG_IIO_BUFFER */
 #endif /* SPI_ADIS16201_H_ */
index d2a203a583afe6360dbbd2ea434d16edbf8fbe96..ccdc8d23f6a383a336613cdc15091263e7bb4470 100644 (file)
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
 
 #include "adis16201.h"
 
-enum adis16201_chan {
-       in_supply,
-       temp,
-       accel_x,
-       accel_y,
-       incli_x,
-       incli_y,
-       in_aux,
-};
-
-/**
- * adis16201_spi_write_reg_8() - write single byte to a register
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-static int adis16201_spi_write_reg_8(struct iio_dev *indio_dev,
-               u8 reg_address,
-               u8 val)
-{
-       int ret;
-       struct adis16201_state *st = iio_priv(indio_dev);
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16201_WRITE_REG(reg_address);
-       st->tx[1] = val;
-
-       ret = spi_write(st->us, st->tx, 2);
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/**
- * adis16201_spi_write_reg_16() - write 2 bytes to a pair of registers
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: value to be written
- **/
-static int adis16201_spi_write_reg_16(struct iio_dev *indio_dev,
-                                     u8 lower_reg_address,
-                                     u16 value)
-{
-       int ret;
-       struct spi_message msg;
-       struct adis16201_state *st = iio_priv(indio_dev);
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = st->tx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-               }, {
-                       .tx_buf = st->tx + 2,
-                       .bits_per_word = 8,
-                       .len = 2,
-               },
-       };
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16201_WRITE_REG(lower_reg_address);
-       st->tx[1] = value & 0xFF;
-       st->tx[2] = ADIS16201_WRITE_REG(lower_reg_address + 1);
-       st->tx[3] = (value >> 8) & 0xFF;
-
-       spi_message_init(&msg);
-       spi_message_add_tail(&xfers[0], &msg);
-       spi_message_add_tail(&xfers[1], &msg);
-       ret = spi_sync(st->us, &msg);
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/**
- * adis16201_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int adis16201_spi_read_reg_16(struct iio_dev *indio_dev,
-               u8 lower_reg_address,
-               u16 *val)
-{
-       struct spi_message msg;
-       struct adis16201_state *st = iio_priv(indio_dev);
-       int ret;
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = st->tx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-                       .delay_usecs = 20,
-               }, {
-                       .rx_buf = st->rx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .delay_usecs = 20,
-               },
-       };
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16201_READ_REG(lower_reg_address);
-       st->tx[1] = 0;
-
-       spi_message_init(&msg);
-       spi_message_add_tail(&xfers[0], &msg);
-       spi_message_add_tail(&xfers[1], &msg);
-       ret = spi_sync(st->us, &msg);
-       if (ret) {
-               dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
-                               lower_reg_address);
-               goto error_ret;
-       }
-       *val = (st->rx[0] << 8) | st->rx[1];
-
-error_ret:
-       mutex_unlock(&st->buf_lock);
-       return ret;
-}
-
-static int adis16201_reset(struct iio_dev *indio_dev)
-{
-       int ret;
-       struct adis16201_state *st = iio_priv(indio_dev);
-
-       ret = adis16201_spi_write_reg_8(indio_dev,
-                       ADIS16201_GLOB_CMD,
-                       ADIS16201_GLOB_CMD_SW_RESET);
-       if (ret)
-               dev_err(&st->us->dev, "problem resetting device");
-
-       return ret;
-}
-
-int adis16201_set_irq(struct iio_dev *indio_dev, bool enable)
-{
-       int ret = 0;
-       u16 msc;
-
-       ret = adis16201_spi_read_reg_16(indio_dev, ADIS16201_MSC_CTRL, &msc);
-       if (ret)
-               goto error_ret;
-
-       msc |= ADIS16201_MSC_CTRL_ACTIVE_HIGH;
-       msc &= ~ADIS16201_MSC_CTRL_DATA_RDY_DIO1;
-       if (enable)
-               msc |= ADIS16201_MSC_CTRL_DATA_RDY_EN;
-       else
-               msc &= ~ADIS16201_MSC_CTRL_DATA_RDY_EN;
-
-       ret = adis16201_spi_write_reg_16(indio_dev, ADIS16201_MSC_CTRL, msc);
-
-error_ret:
-       return ret;
-}
-
-static int adis16201_check_status(struct iio_dev *indio_dev)
-{
-       u16 status;
-       int ret;
-
-       ret = adis16201_spi_read_reg_16(indio_dev,
-                                       ADIS16201_DIAG_STAT, &status);
-       if (ret < 0) {
-               dev_err(&indio_dev->dev, "Reading status failed\n");
-               goto error_ret;
-       }
-       ret = status & 0xF;
-       if (ret)
-               ret = -EFAULT;
-
-       if (status & ADIS16201_DIAG_STAT_SPI_FAIL)
-               dev_err(&indio_dev->dev, "SPI failure\n");
-       if (status & ADIS16201_DIAG_STAT_FLASH_UPT)
-               dev_err(&indio_dev->dev, "Flash update failed\n");
-       if (status & ADIS16201_DIAG_STAT_POWER_HIGH)
-               dev_err(&indio_dev->dev, "Power supply above 3.625V\n");
-       if (status & ADIS16201_DIAG_STAT_POWER_LOW)
-               dev_err(&indio_dev->dev, "Power supply below 3.15V\n");
-
-error_ret:
-       return ret;
-}
-
-static int adis16201_self_test(struct iio_dev *indio_dev)
-{
-       int ret;
-       ret = adis16201_spi_write_reg_16(indio_dev,
-                       ADIS16201_MSC_CTRL,
-                       ADIS16201_MSC_CTRL_SELF_TEST_EN);
-       if (ret) {
-               dev_err(&indio_dev->dev, "problem starting self test");
-               goto err_ret;
-       }
-
-       ret = adis16201_check_status(indio_dev);
-
-err_ret:
-       return ret;
-}
-
-static int adis16201_initial_setup(struct iio_dev *indio_dev)
-{
-       int ret;
-       struct device *dev = &indio_dev->dev;
-
-       /* Disable IRQ */
-       ret = adis16201_set_irq(indio_dev, false);
-       if (ret) {
-               dev_err(dev, "disable irq failed");
-               goto err_ret;
-       }
-
-       /* Do self test */
-       ret = adis16201_self_test(indio_dev);
-       if (ret) {
-               dev_err(dev, "self test failure");
-               goto err_ret;
-       }
-
-       /* Read status register to check the result */
-       ret = adis16201_check_status(indio_dev);
-       if (ret) {
-               adis16201_reset(indio_dev);
-               dev_err(dev, "device not playing ball -> reset");
-               msleep(ADIS16201_STARTUP_DELAY);
-               ret = adis16201_check_status(indio_dev);
-               if (ret) {
-                       dev_err(dev, "giving up");
-                       goto err_ret;
-               }
-       }
-
-err_ret:
-       return ret;
-}
-
-static u8 adis16201_addresses[7][2] = {
-       [in_supply] = { ADIS16201_SUPPLY_OUT, },
-       [temp] = { ADIS16201_TEMP_OUT },
-       [accel_x] = { ADIS16201_XACCL_OUT, ADIS16201_XACCL_OFFS },
-       [accel_y] = { ADIS16201_YACCL_OUT, ADIS16201_YACCL_OFFS },
-       [in_aux] = { ADIS16201_AUX_ADC },
-       [incli_x] = { ADIS16201_XINCL_OUT },
-       [incli_y] = { ADIS16201_YINCL_OUT },
+static const u8 adis16201_addresses[] = {
+       [ADIS16201_SCAN_ACC_X] = ADIS16201_XACCL_OFFS,
+       [ADIS16201_SCAN_ACC_Y] = ADIS16201_YACCL_OFFS,
+       [ADIS16201_SCAN_INCLI_X] = ADIS16201_XINCL_OFFS,
+       [ADIS16201_SCAN_INCLI_Y] = ADIS16201_YINCL_OFFS,
 };
 
 static int adis16201_read_raw(struct iio_dev *indio_dev,
@@ -277,6 +34,7 @@ static int adis16201_read_raw(struct iio_dev *indio_dev,
                              int *val, int *val2,
                              long mask)
 {
+       struct adis *st = iio_priv(indio_dev);
        int ret;
        int bits;
        u8 addr;
@@ -284,29 +42,8 @@ static int adis16201_read_raw(struct iio_dev *indio_dev,
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               mutex_lock(&indio_dev->mlock);
-               addr = adis16201_addresses[chan->address][0];
-               ret = adis16201_spi_read_reg_16(indio_dev, addr, &val16);
-               if (ret) {
-                       mutex_unlock(&indio_dev->mlock);
-                       return ret;
-               }
-
-               if (val16 & ADIS16201_ERROR_ACTIVE) {
-                       ret = adis16201_check_status(indio_dev);
-                       if (ret) {
-                               mutex_unlock(&indio_dev->mlock);
-                               return ret;
-                       }
-               }
-               val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
-               if (chan->scan_type.sign == 's')
-                       val16 = (s16)(val16 <<
-                                     (16 - chan->scan_type.realbits)) >>
-                               (16 - chan->scan_type.realbits);
-               *val = val16;
-               mutex_unlock(&indio_dev->mlock);
-               return IIO_VAL_INT;
+               return adis_single_conversion(indio_dev, chan,
+                               ADIS16201_ERROR_ACTIVE, val);
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
@@ -349,8 +86,8 @@ static int adis16201_read_raw(struct iio_dev *indio_dev,
                        return -EINVAL;
                }
                mutex_lock(&indio_dev->mlock);
-               addr = adis16201_addresses[chan->address][1];
-               ret = adis16201_spi_read_reg_16(indio_dev, addr, &val16);
+               addr = adis16201_addresses[chan->scan_index];
+               ret = adis_read_reg_16(st, addr, &val16);
                if (ret) {
                        mutex_unlock(&indio_dev->mlock);
                        return ret;
@@ -370,6 +107,7 @@ static int adis16201_write_raw(struct iio_dev *indio_dev,
                               int val2,
                               long mask)
 {
+       struct adis *st = iio_priv(indio_dev);
        int bits;
        s16 val16;
        u8 addr;
@@ -386,124 +124,61 @@ static int adis16201_write_raw(struct iio_dev *indio_dev,
                        return -EINVAL;
                }
                val16 = val & ((1 << bits) - 1);
-               addr = adis16201_addresses[chan->address][1];
-               return adis16201_spi_write_reg_16(indio_dev, addr, val16);
+               addr = adis16201_addresses[chan->scan_index];
+               return adis_write_reg_16(st, addr, val16);
        }
        return -EINVAL;
 }
 
 static const struct iio_chan_spec adis16201_channels[] = {
-       {
-               .type = IIO_VOLTAGE,
-               .indexed = 1,
-               .channel = 0,
-               .extend_name = "supply",
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-                IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-               .address = in_supply,
-               .scan_index = ADIS16201_SCAN_SUPPLY,
-               .scan_type = {
-                       .sign = 'u',
-                       .realbits = 12,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_TEMP,
-               .indexed = 1,
-               .channel = 0,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-                IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
-                IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
-               .address = temp,
-               .scan_index = ADIS16201_SCAN_TEMP,
-               .scan_type = {
-                       .sign = 'u',
-                       .realbits = 12,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_ACCEL,
-               .modified = 1,
-               .channel2 = IIO_MOD_X,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-                IIO_CHAN_INFO_SCALE_SHARED_BIT |
-                IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
-               .address = accel_x,
-               .scan_index = ADIS16201_SCAN_ACC_X,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 14,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_ACCEL,
-               .modified = 1,
-               .channel2 = IIO_MOD_Y,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-                IIO_CHAN_INFO_SCALE_SHARED_BIT |
-                IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
-               .address = accel_y,
-               .scan_index = ADIS16201_SCAN_ACC_Y,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 14,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_VOLTAGE,
-               .indexed = 1,
-               .channel = 1,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-                IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-               .address = in_aux,
-               .scan_index = ADIS16201_SCAN_AUX_ADC,
-               .scan_type = {
-                       .sign = 'u',
-                       .realbits = 12,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_INCLI,
-               .modified = 1,
-               .channel2 = IIO_MOD_X,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-                IIO_CHAN_INFO_SCALE_SHARED_BIT |
-                IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
-               .address = incli_x,
-               .scan_index = ADIS16201_SCAN_INCLI_X,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 14,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_INCLI,
-               .modified = 1,
-               .channel2 = IIO_MOD_Y,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-                IIO_CHAN_INFO_SCALE_SHARED_BIT |
-                IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
-               .address = incli_y,
-               .scan_index = ADIS16201_SCAN_INCLI_Y,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 14,
-                       .storagebits = 16,
-               },
-       },
+       ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 12),
+       ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 12),
+       ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT, ADIS16201_SCAN_ACC_X,
+               IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+       ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT, ADIS16201_SCAN_ACC_Y,
+               IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+       ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC, ADIS16201_SCAN_AUX_ADC, 12),
+       ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT, ADIS16201_SCAN_INCLI_X,
+               IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+       ADIS_INCLI_CHAN(X, ADIS16201_YINCL_OUT, ADIS16201_SCAN_INCLI_Y,
+               IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
        IIO_CHAN_SOFT_TIMESTAMP(7)
 };
 
 static const struct iio_info adis16201_info = {
        .read_raw = &adis16201_read_raw,
        .write_raw = &adis16201_write_raw,
+       .update_scan_mode = adis_update_scan_mode,
        .driver_module = THIS_MODULE,
 };
 
+static const char * const adis16201_status_error_msgs[] = {
+       [ADIS16201_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
+       [ADIS16201_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
+       [ADIS16201_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
+       [ADIS16201_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V",
+};
+
+static const struct adis_data adis16201_data = {
+       .read_delay = 20,
+       .msc_ctrl_reg = ADIS16201_MSC_CTRL,
+       .glob_cmd_reg = ADIS16201_GLOB_CMD,
+       .diag_stat_reg = ADIS16201_DIAG_STAT,
+
+       .self_test_mask = ADIS16201_MSC_CTRL_SELF_TEST_EN,
+       .startup_delay = ADIS16201_STARTUP_DELAY,
+
+       .status_error_msgs = adis16201_status_error_msgs,
+       .status_error_mask = BIT(ADIS16201_DIAG_STAT_SPI_FAIL_BIT) |
+               BIT(ADIS16201_DIAG_STAT_FLASH_UPT_BIT) |
+               BIT(ADIS16201_DIAG_STAT_POWER_HIGH_BIT) |
+               BIT(ADIS16201_DIAG_STAT_POWER_LOW_BIT),
+};
+
 static int __devinit adis16201_probe(struct spi_device *spi)
 {
        int ret;
-       struct adis16201_state *st;
+       struct adis *st;
        struct iio_dev *indio_dev;
 
        /* setup the industrialio driver allocated elements */
@@ -516,9 +191,6 @@ static int __devinit adis16201_probe(struct spi_device *spi)
        /* this is only used for removal purposes */
        spi_set_drvdata(spi, indio_dev);
 
-       st->us = spi;
-       mutex_init(&st->buf_lock);
-
        indio_dev->name = spi->dev.driver->name;
        indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &adis16201_info;
@@ -527,40 +199,25 @@ static int __devinit adis16201_probe(struct spi_device *spi)
        indio_dev->num_channels = ARRAY_SIZE(adis16201_channels);
        indio_dev->modes = INDIO_DIRECT_MODE;
 
-       ret = adis16201_configure_ring(indio_dev);
+       ret = adis_init(st, indio_dev, spi, &adis16201_data);
+       if (ret)
+               goto error_free_dev;
+       ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL);
        if (ret)
                goto error_free_dev;
-
-       ret = iio_buffer_register(indio_dev,
-                                 adis16201_channels,
-                                 ARRAY_SIZE(adis16201_channels));
-       if (ret) {
-               printk(KERN_ERR "failed to initialize the ring\n");
-               goto error_unreg_ring_funcs;
-       }
-
-       if (spi->irq) {
-               ret = adis16201_probe_trigger(indio_dev);
-               if (ret)
-                       goto error_uninitialize_ring;
-       }
 
        /* Get the device into a sane initial state */
-       ret = adis16201_initial_setup(indio_dev);
+       ret = adis_initial_startup(st);
        if (ret)
-               goto error_remove_trigger;
+               goto error_cleanup_buffer_trigger;
 
        ret = iio_device_register(indio_dev);
        if (ret < 0)
-               goto error_remove_trigger;
+               goto error_cleanup_buffer_trigger;
        return 0;
 
-error_remove_trigger:
-       adis16201_remove_trigger(indio_dev);
-error_uninitialize_ring:
-       iio_buffer_unregister(indio_dev);
-error_unreg_ring_funcs:
-       adis16201_unconfigure_ring(indio_dev);
+error_cleanup_buffer_trigger:
+       adis_cleanup_buffer_and_trigger(st, indio_dev);
 error_free_dev:
        iio_device_free(indio_dev);
 error_ret:
@@ -570,11 +227,10 @@ error_ret:
 static int __devexit adis16201_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
+       struct adis *st = iio_priv(indio_dev);
 
        iio_device_unregister(indio_dev);
-       adis16201_remove_trigger(indio_dev);
-       iio_buffer_unregister(indio_dev);
-       adis16201_unconfigure_ring(indio_dev);
+       adis_cleanup_buffer_and_trigger(st, indio_dev);
        iio_device_free(indio_dev);
 
        return 0;
diff --git a/drivers/staging/iio/accel/adis16201_ring.c b/drivers/staging/iio/accel/adis16201_ring.c
deleted file mode 100644 (file)
index e14ca60..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16201.h"
-
-
-/**
- * adis16201_read_ring_data() read data registers which will be placed into ring
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @rx: somewhere to pass back the value read
- **/
-static int adis16201_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-       struct spi_message msg;
-       struct adis16201_state *st = iio_priv(indio_dev);
-       struct spi_transfer xfers[ADIS16201_OUTPUTS + 1];
-       int ret;
-       int i;
-
-       mutex_lock(&st->buf_lock);
-
-       spi_message_init(&msg);
-
-       memset(xfers, 0, sizeof(xfers));
-       for (i = 0; i <= ADIS16201_OUTPUTS; i++) {
-               xfers[i].bits_per_word = 8;
-               xfers[i].cs_change = 1;
-               xfers[i].len = 2;
-               xfers[i].delay_usecs = 20;
-               if (i < ADIS16201_OUTPUTS) {
-                       xfers[i].tx_buf = st->tx + 2 * i;
-                       st->tx[2 * i] = ADIS16201_READ_REG(ADIS16201_SUPPLY_OUT +
-                                                          2 * i);
-                       st->tx[2 * i + 1] = 0;
-               }
-               if (i >= 1)
-                       xfers[i].rx_buf = rx + 2 * (i - 1);
-               spi_message_add_tail(&xfers[i], &msg);
-       }
-
-       ret = spi_sync(st->us, &msg);
-       if (ret)
-               dev_err(&st->us->dev, "problem when burst reading");
-
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
- * specific to be rolled into the core.
- */
-static irqreturn_t adis16201_trigger_handler(int irq, void *p)
-{
-       struct iio_poll_func *pf = p;
-       struct iio_dev *indio_dev = pf->indio_dev;
-       struct adis16201_state *st = iio_priv(indio_dev);
-
-       int i = 0;
-       s16 *data;
-
-       data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-       if (data == NULL) {
-               dev_err(&st->us->dev, "memory alloc failed in ring bh");
-               goto done;
-       }
-
-       if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)
-           && adis16201_read_ring_data(indio_dev, st->rx) >= 0)
-               for (; i < bitmap_weight(indio_dev->active_scan_mask,
-                                        indio_dev->masklength); i++)
-                       data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-       /* Guaranteed to be aligned with 8 byte boundary */
-       if (indio_dev->scan_timestamp)
-               *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-       iio_push_to_buffers(indio_dev, (u8 *)data);
-
-       kfree(data);
-done:
-       iio_trigger_notify_done(indio_dev->trig);
-
-       return IRQ_HANDLED;
-}
-
-void adis16201_unconfigure_ring(struct iio_dev *indio_dev)
-{
-       iio_dealloc_pollfunc(indio_dev->pollfunc);
-       iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16201_ring_setup_ops = {
-       .preenable = &iio_sw_buffer_preenable,
-       .postenable = &iio_triggered_buffer_postenable,
-       .predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16201_configure_ring(struct iio_dev *indio_dev)
-{
-       int ret = 0;
-       struct iio_buffer *ring;
-
-       ring = iio_sw_rb_allocate(indio_dev);
-       if (!ring) {
-               ret = -ENOMEM;
-               return ret;
-       }
-       indio_dev->buffer = ring;
-       ring->scan_timestamp = true;
-       indio_dev->setup_ops = &adis16201_ring_setup_ops;
-
-       indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-                                                &adis16201_trigger_handler,
-                                                IRQF_ONESHOT,
-                                                indio_dev,
-                                                "adis16201_consumer%d",
-                                                indio_dev->id);
-       if (indio_dev->pollfunc == NULL) {
-               ret = -ENOMEM;
-               goto error_iio_sw_rb_free;
-       }
-
-       indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-       return 0;
-error_iio_sw_rb_free:
-       iio_sw_rb_free(indio_dev->buffer);
-       return ret;
-}
diff --git a/drivers/staging/iio/accel/adis16201_trigger.c b/drivers/staging/iio/accel/adis16201_trigger.c
deleted file mode 100644 (file)
index 96fdabb..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16201.h"
-
-/**
- * adis16201_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16201_data_rdy_trigger_set_state(struct iio_trigger *trig,
-                                               bool state)
-{
-       struct iio_dev *indio_dev = trig->private_data;
-
-       dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-       return adis16201_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16201_trigger_ops = {
-       .owner = THIS_MODULE,
-       .set_trigger_state = &adis16201_data_rdy_trigger_set_state,
-};
-
-int adis16201_probe_trigger(struct iio_dev *indio_dev)
-{
-       int ret;
-       struct adis16201_state *st = iio_priv(indio_dev);
-
-       st->trig = iio_trigger_alloc("adis16201-dev%d", indio_dev->id);
-       if (st->trig == NULL) {
-               ret = -ENOMEM;
-               goto error_ret;
-       }
-       ret = request_irq(st->us->irq,
-                         &iio_trigger_generic_data_rdy_poll,
-                         IRQF_TRIGGER_RISING,
-                         "adis16201",
-                         st->trig);
-       if (ret)
-               goto error_free_trig;
-       st->trig->dev.parent = &st->us->dev;
-       st->trig->ops = &adis16201_trigger_ops;
-       st->trig->private_data = indio_dev;
-       ret = iio_trigger_register(st->trig);
-
-       /* select default trigger */
-       indio_dev->trig = st->trig;
-       if (ret)
-               goto error_free_irq;
-
-       return 0;
-
-error_free_irq:
-       free_irq(st->us->irq, st->trig);
-error_free_trig:
-       iio_trigger_free(st->trig);
-error_ret:
-       return ret;
-}
-
-void adis16201_remove_trigger(struct iio_dev *indio_dev)
-{
-       struct adis16201_state *state = iio_priv(indio_dev);
-
-       iio_trigger_unregister(state->trig);
-       free_irq(state->us->irq, state->trig);
-       iio_trigger_free(state->trig);
-}
index 3f96ad3bbd66ede89430360682a4c8a6fdfbb906..acc688d7ea9eda68a72a33f1d032a46fe05ffd13 100644 (file)
@@ -3,9 +3,6 @@
 
 #define ADIS16203_STARTUP_DELAY        220 /* ms */
 
-#define ADIS16203_READ_REG(a)    a
-#define ADIS16203_WRITE_REG(a) ((a) | 0x80)
-
 #define ADIS16203_FLASH_CNT      0x00 /* Flash memory write count */
 #define ADIS16203_SUPPLY_OUT     0x02 /* Output, power supply */
 #define ADIS16203_AUX_ADC        0x08 /* Output, auxiliary ADC input */
@@ -27,8 +24,6 @@
 #define ADIS16203_DIAG_STAT      0x3C /* Diagnostics, system status register */
 #define ADIS16203_GLOB_CMD       0x3E /* Operation, system command register */
 
-#define ADIS16203_OUTPUTS        5
-
 /* MSC_CTRL */
 #define ADIS16203_MSC_CTRL_PWRUP_SELF_TEST     (1 << 10) /* Self-test at power-on: 1 = disabled, 0 = enabled */
 #define ADIS16203_MSC_CTRL_REVERSE_ROT_EN      (1 << 9)  /* Reverses rotation of both inclination outputs */
 /* DIAG_STAT */
 #define ADIS16203_DIAG_STAT_ALARM2        (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
 #define ADIS16203_DIAG_STAT_ALARM1        (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
-#define ADIS16203_DIAG_STAT_SELFTEST_FAIL (1<<5) /* Self-test diagnostic error flag */
-#define ADIS16203_DIAG_STAT_SPI_FAIL     (1<<3) /* SPI communications failure */
-#define ADIS16203_DIAG_STAT_FLASH_UPT    (1<<2) /* Flash update failure */
-#define ADIS16203_DIAG_STAT_POWER_HIGH   (1<<1) /* Power supply above 3.625 V */
-#define ADIS16203_DIAG_STAT_POWER_LOW    (1<<0) /* Power supply below 3.15 V */
+#define ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT 5 /* Self-test diagnostic error flag */
+#define ADIS16203_DIAG_STAT_SPI_FAIL_BIT      3 /* SPI communications failure */
+#define ADIS16203_DIAG_STAT_FLASH_UPT_BIT     2 /* Flash update failure */
+#define ADIS16203_DIAG_STAT_POWER_HIGH_BIT    1 /* Power supply above 3.625 V */
+#define ADIS16203_DIAG_STAT_POWER_LOW_BIT     0 /* Power supply below 3.15 V */
 
 /* GLOB_CMD */
 #define ADIS16203_GLOB_CMD_SW_RESET    (1<<7)
 #define ADIS16203_GLOB_CMD_CLEAR_STAT  (1<<4)
 #define ADIS16203_GLOB_CMD_FACTORY_CAL (1<<1)
 
-#define ADIS16203_MAX_TX 12
-#define ADIS16203_MAX_RX 10
-
 #define ADIS16203_ERROR_ACTIVE          (1<<14)
 
-/**
- * struct adis16203_state - device instance specific data
- * @us:                        actual spi_device
- * @trig:              data ready trigger registered with iio
- * @tx:                        transmit buffer
- * @rx:                        receive buffer
- * @buf_lock:          mutex to protect tx and rx
- **/
-struct adis16203_state {
-       struct spi_device       *us;
-       struct iio_trigger      *trig;
-       struct mutex            buf_lock;
-       u8                      tx[ADIS16203_MAX_TX] ____cacheline_aligned;
-       u8                      rx[ADIS16203_MAX_RX];
-};
-
-int adis16203_set_irq(struct iio_dev *indio_dev, bool enable);
-
 enum adis16203_scan {
+       ADIS16203_SCAN_INCLI_X,
+       ADIS16203_SCAN_INCLI_Y,
        ADIS16203_SCAN_SUPPLY,
        ADIS16203_SCAN_AUX_ADC,
        ADIS16203_SCAN_TEMP,
-       ADIS16203_SCAN_INCLI_X,
-       ADIS16203_SCAN_INCLI_Y,
 };
 
-#ifdef CONFIG_IIO_BUFFER
-void adis16203_remove_trigger(struct iio_dev *indio_dev);
-int adis16203_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16203_read_data_from_ring(struct device *dev,
-                                     struct device_attribute *attr,
-                                     char *buf);
-
-int adis16203_configure_ring(struct iio_dev *indio_dev);
-void adis16203_unconfigure_ring(struct iio_dev *indio_dev);
-
-#else /* CONFIG_IIO_BUFFER */
-
-static inline void adis16203_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16203_probe_trigger(struct iio_dev *indio_dev)
-{
-       return 0;
-}
-
-static inline ssize_t
-adis16203_read_data_from_ring(struct device *dev,
-                             struct device_attribute *attr,
-                             char *buf)
-{
-       return 0;
-}
-
-static int adis16203_configure_ring(struct iio_dev *indio_dev)
-{
-       return 0;
-}
-
-static inline void adis16203_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-#endif /* CONFIG_IIO_BUFFER */
 #endif /* SPI_ADIS16203_H_ */
index 7d7c4d28f6f080675455decad901ccb62f329af1..202985ea3531ffe99a2cc739f7a39182cf5cf37e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ADIS16203 Programmable Digital Vibration Sensor driver
  *
- * Copyright 2010 Analog Devices Inc.
+ * Copyright 2030 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
 
 #include "adis16203.h"
 
-/**
- * adis16203_spi_write_reg_8() - write single byte to a register
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-static int adis16203_spi_write_reg_8(struct iio_dev *indio_dev,
-                                    u8 reg_address,
-                                    u8 val)
-{
-       int ret;
-       struct adis16203_state *st = iio_priv(indio_dev);
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16203_WRITE_REG(reg_address);
-       st->tx[1] = val;
-
-       ret = spi_write(st->us, st->tx, 2);
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/**
- * adis16203_spi_write_reg_16() - write 2 bytes to a pair of registers
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: value to be written
- **/
-static int adis16203_spi_write_reg_16(struct iio_dev *indio_dev,
-                                     u8 lower_reg_address,
-                                     u16 value)
-{
-       int ret;
-       struct spi_message msg;
-       struct adis16203_state *st = iio_priv(indio_dev);
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = st->tx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-               }, {
-                       .tx_buf = st->tx + 2,
-                       .bits_per_word = 8,
-                       .len = 2,
-               },
-       };
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16203_WRITE_REG(lower_reg_address);
-       st->tx[1] = value & 0xFF;
-       st->tx[2] = ADIS16203_WRITE_REG(lower_reg_address + 1);
-       st->tx[3] = (value >> 8) & 0xFF;
-
-       spi_message_init(&msg);
-       spi_message_add_tail(&xfers[0], &msg);
-       spi_message_add_tail(&xfers[1], &msg);
-       ret = spi_sync(st->us, &msg);
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/**
- * adis16203_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int adis16203_spi_read_reg_16(struct iio_dev *indio_dev,
-               u8 lower_reg_address,
-               u16 *val)
-{
-       struct spi_message msg;
-       struct adis16203_state *st = iio_priv(indio_dev);
-       int ret;
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = st->tx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-                       .delay_usecs = 20,
-               }, {
-                       .rx_buf = st->rx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .delay_usecs = 20,
-               },
-       };
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16203_READ_REG(lower_reg_address);
-       st->tx[1] = 0;
-
-       spi_message_init(&msg);
-       spi_message_add_tail(&xfers[0], &msg);
-       spi_message_add_tail(&xfers[1], &msg);
-       ret = spi_sync(st->us, &msg);
-       if (ret) {
-               dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
-                               lower_reg_address);
-               goto error_ret;
-       }
-       *val = (st->rx[0] << 8) | st->rx[1];
-
-error_ret:
-       mutex_unlock(&st->buf_lock);
-       return ret;
-}
-
-static int adis16203_check_status(struct iio_dev *indio_dev)
-{
-       u16 status;
-       int ret;
-
-       ret = adis16203_spi_read_reg_16(indio_dev,
-                                       ADIS16203_DIAG_STAT,
-                                       &status);
-       if (ret < 0) {
-               dev_err(&indio_dev->dev, "Reading status failed\n");
-               goto error_ret;
-       }
-       ret = status & 0x1F;
-
-       if (status & ADIS16203_DIAG_STAT_SELFTEST_FAIL)
-               dev_err(&indio_dev->dev, "Self test failure\n");
-       if (status & ADIS16203_DIAG_STAT_SPI_FAIL)
-               dev_err(&indio_dev->dev, "SPI failure\n");
-       if (status & ADIS16203_DIAG_STAT_FLASH_UPT)
-               dev_err(&indio_dev->dev, "Flash update failed\n");
-       if (status & ADIS16203_DIAG_STAT_POWER_HIGH)
-               dev_err(&indio_dev->dev, "Power supply above 3.625V\n");
-       if (status & ADIS16203_DIAG_STAT_POWER_LOW)
-               dev_err(&indio_dev->dev, "Power supply below 3.15V\n");
-
-error_ret:
-       return ret;
-}
-
-static int adis16203_reset(struct iio_dev *indio_dev)
-{
-       int ret;
-       ret = adis16203_spi_write_reg_8(indio_dev,
-                       ADIS16203_GLOB_CMD,
-                       ADIS16203_GLOB_CMD_SW_RESET);
-       if (ret)
-               dev_err(&indio_dev->dev, "problem resetting device");
-
-       return ret;
-}
-
-int adis16203_set_irq(struct iio_dev *indio_dev, bool enable)
-{
-       int ret = 0;
-       u16 msc;
-
-       ret = adis16203_spi_read_reg_16(indio_dev, ADIS16203_MSC_CTRL, &msc);
-       if (ret)
-               goto error_ret;
-
-       msc |= ADIS16203_MSC_CTRL_ACTIVE_HIGH;
-       msc &= ~ADIS16203_MSC_CTRL_DATA_RDY_DIO1;
-       if (enable)
-               msc |= ADIS16203_MSC_CTRL_DATA_RDY_EN;
-       else
-               msc &= ~ADIS16203_MSC_CTRL_DATA_RDY_EN;
+#define DRIVER_NAME            "adis16203"
 
-       ret = adis16203_spi_write_reg_16(indio_dev, ADIS16203_MSC_CTRL, msc);
-
-error_ret:
-       return ret;
-}
-
-static int adis16203_self_test(struct iio_dev *indio_dev)
-{
-       int ret;
-       ret = adis16203_spi_write_reg_16(indio_dev,
-                       ADIS16203_MSC_CTRL,
-                       ADIS16203_MSC_CTRL_SELF_TEST_EN);
-       if (ret) {
-               dev_err(&indio_dev->dev, "problem starting self test");
-               goto err_ret;
-       }
-
-       adis16203_check_status(indio_dev);
-
-err_ret:
-       return ret;
-}
-
-static int adis16203_initial_setup(struct iio_dev *indio_dev)
-{
-       int ret;
-
-       /* Disable IRQ */
-       ret = adis16203_set_irq(indio_dev, false);
-       if (ret) {
-               dev_err(&indio_dev->dev, "disable irq failed");
-               goto err_ret;
-       }
-
-       /* Do self test */
-       ret = adis16203_self_test(indio_dev);
-       if (ret) {
-               dev_err(&indio_dev->dev, "self test failure");
-               goto err_ret;
-       }
-
-       /* Read status register to check the result */
-       ret = adis16203_check_status(indio_dev);
-       if (ret) {
-               adis16203_reset(indio_dev);
-               dev_err(&indio_dev->dev, "device not playing ball -> reset");
-               msleep(ADIS16203_STARTUP_DELAY);
-               ret = adis16203_check_status(indio_dev);
-               if (ret) {
-                       dev_err(&indio_dev->dev, "giving up");
-                       goto err_ret;
-               }
-       }
-
-err_ret:
-       return ret;
-}
-
-enum adis16203_chan {
-       in_supply,
-       in_aux,
-       incli_x,
-       incli_y,
-       temp,
-};
-
-static u8 adis16203_addresses[5][2] = {
-       [in_supply] = { ADIS16203_SUPPLY_OUT },
-       [in_aux] = { ADIS16203_AUX_ADC },
-       [incli_x] = { ADIS16203_XINCL_OUT, ADIS16203_INCL_NULL},
-       [incli_y] = { ADIS16203_YINCL_OUT },
-       [temp] = { ADIS16203_TEMP_OUT }
+static const u8 adis16203_addresses[] = {
+       [ADIS16203_SCAN_INCLI_X] = ADIS16203_INCL_NULL,
 };
 
 static int adis16203_write_raw(struct iio_dev *indio_dev,
@@ -272,9 +34,10 @@ static int adis16203_write_raw(struct iio_dev *indio_dev,
                               int val2,
                               long mask)
 {
+       struct adis *st = iio_priv(indio_dev);
        /* currently only one writable parameter which keeps this simple */
-       u8 addr = adis16203_addresses[chan->address][1];
-       return adis16203_spi_write_reg_16(indio_dev, addr, val & 0x3FFF);
+       u8 addr = adis16203_addresses[chan->scan_index];
+       return adis_write_reg_16(st, addr, val & 0x3FFF);
 }
 
 static int adis16203_read_raw(struct iio_dev *indio_dev,
@@ -282,35 +45,15 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
                              int *val, int *val2,
                              long mask)
 {
+       struct adis *st = iio_priv(indio_dev);
        int ret;
        int bits;
        u8 addr;
        s16 val16;
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               mutex_lock(&indio_dev->mlock);
-               addr = adis16203_addresses[chan->address][0];
-               ret = adis16203_spi_read_reg_16(indio_dev, addr, &val16);
-               if (ret) {
-                       mutex_unlock(&indio_dev->mlock);
-                       return ret;
-               }
-
-               if (val16 & ADIS16203_ERROR_ACTIVE) {
-                       ret = adis16203_check_status(indio_dev);
-                       if (ret) {
-                               mutex_unlock(&indio_dev->mlock);
-                               return ret;
-                       }
-               }
-               val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
-               if (chan->scan_type.sign == 's')
-                       val16 = (s16)(val16 <<
-                                     (16 - chan->scan_type.realbits)) >>
-                               (16 - chan->scan_type.realbits);
-               *val = val16;
-               mutex_unlock(&indio_dev->mlock);
-               return IIO_VAL_INT;
+               return adis_single_conversion(indio_dev, chan,
+                               ADIS16203_ERROR_ACTIVE, val);
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
@@ -339,8 +82,8 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_CALIBBIAS:
                bits = 14;
                mutex_lock(&indio_dev->mlock);
-               addr = adis16203_addresses[chan->address][1];
-               ret = adis16203_spi_read_reg_16(indio_dev, addr, &val16);
+               addr = adis16203_addresses[chan->scan_index];
+               ret = adis_read_reg_16(st, addr, &val16);
                if (ret) {
                        mutex_unlock(&indio_dev->mlock);
                        return ret;
@@ -356,89 +99,53 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
 }
 
 static const struct iio_chan_spec adis16203_channels[] = {
-       {
-               .type = IIO_VOLTAGE,
-               .indexed = 1,
-               .channel = 0,
-               .extend_name = "supply",
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-               .address = in_supply,
-               .scan_index = ADIS16203_SCAN_SUPPLY,
-               .scan_type = {
-                       .sign = 'u',
-                       .realbits = 12,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_VOLTAGE,
-               .indexed = 1,
-               .channel = 1,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-               .address = in_aux,
-               .scan_index = ADIS16203_SCAN_AUX_ADC,
-               .scan_type = {
-                       .sign = 'u',
-                       .realbits = 12,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_INCLI,
-               .modified = 1,
-               .channel2 = IIO_MOD_X,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SHARED_BIT |
-               IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
-               .address = incli_x,
-               .scan_index = ADIS16203_SCAN_INCLI_X,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 14,
-                       .storagebits = 16,
-               },
-       }, { /* Fixme: Not what it appears to be - see data sheet */
-               .type = IIO_INCLI,
-               .modified = 1,
-               .channel2 = IIO_MOD_Y,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SHARED_BIT,
-               .address = incli_y,
-               .scan_index = ADIS16203_SCAN_INCLI_Y,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 14,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_TEMP,
-               .indexed = 1,
-               .channel = 0,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
-               IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
-               .address = temp,
-               .scan_index = ADIS16203_SCAN_TEMP,
-               .scan_type = {
-                       .sign = 'u',
-                       .realbits = 12,
-                       .storagebits = 16,
-               },
-       },
+       ADIS_SUPPLY_CHAN(ADIS16203_SUPPLY_OUT, ADIS16203_SCAN_SUPPLY, 12),
+       ADIS_AUX_ADC_CHAN(ADIS16203_AUX_ADC, ADIS16203_SCAN_AUX_ADC, 12),
+       ADIS_INCLI_CHAN(X, ADIS16203_XINCL_OUT, ADIS16203_SCAN_INCLI_X,
+               IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+       /* Fixme: Not what it appears to be - see data sheet */
+       ADIS_INCLI_CHAN(Y, ADIS16203_YINCL_OUT, ADIS16203_SCAN_INCLI_Y, 0, 14),
+       ADIS_TEMP_CHAN(ADIS16203_TEMP_OUT, ADIS16203_SCAN_TEMP, 12),
        IIO_CHAN_SOFT_TIMESTAMP(5),
 };
 
 static const struct iio_info adis16203_info = {
        .read_raw = &adis16203_read_raw,
        .write_raw = &adis16203_write_raw,
+       .update_scan_mode = adis_update_scan_mode,
        .driver_module = THIS_MODULE,
 };
 
+static const char * const adis16203_status_error_msgs[] = {
+       [ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT] = "Self test failure",
+       [ADIS16203_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
+       [ADIS16203_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
+       [ADIS16203_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
+       [ADIS16203_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V",
+};
+
+static const struct adis_data adis16203_data = {
+       .read_delay = 20,
+       .msc_ctrl_reg = ADIS16203_MSC_CTRL,
+       .glob_cmd_reg = ADIS16203_GLOB_CMD,
+       .diag_stat_reg = ADIS16203_DIAG_STAT,
+
+       .self_test_mask = ADIS16203_MSC_CTRL_SELF_TEST_EN,
+       .startup_delay = ADIS16203_STARTUP_DELAY,
+
+       .status_error_msgs = adis16203_status_error_msgs,
+       .status_error_mask = BIT(ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT) |
+               BIT(ADIS16203_DIAG_STAT_SPI_FAIL_BIT) |
+               BIT(ADIS16203_DIAG_STAT_FLASH_UPT_BIT) |
+               BIT(ADIS16203_DIAG_STAT_POWER_HIGH_BIT) |
+               BIT(ADIS16203_DIAG_STAT_POWER_LOW_BIT),
+};
+
 static int __devinit adis16203_probe(struct spi_device *spi)
 {
        int ret;
        struct iio_dev *indio_dev;
-       struct adis16203_state *st;
+       struct adis *st;
 
        /* setup the industrialio driver allocated elements */
        indio_dev = iio_device_alloc(sizeof(*st));
@@ -449,8 +156,6 @@ static int __devinit adis16203_probe(struct spi_device *spi)
        st = iio_priv(indio_dev);
        /* this is only used for removal purposes */
        spi_set_drvdata(spi, indio_dev);
-       st->us = spi;
-       mutex_init(&st->buf_lock);
 
        indio_dev->name = spi->dev.driver->name;
        indio_dev->dev.parent = &spi->dev;
@@ -459,41 +164,27 @@ static int __devinit adis16203_probe(struct spi_device *spi)
        indio_dev->info = &adis16203_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
-       ret = adis16203_configure_ring(indio_dev);
+       ret = adis_init(st, indio_dev, spi, &adis16203_data);
        if (ret)
                goto error_free_dev;
 
-       ret = iio_buffer_register(indio_dev,
-                                 adis16203_channels,
-                                 ARRAY_SIZE(adis16203_channels));
-       if (ret) {
-               printk(KERN_ERR "failed to initialize the ring\n");
-               goto error_unreg_ring_funcs;
-       }
-
-       if (spi->irq) {
-               ret = adis16203_probe_trigger(indio_dev);
-               if (ret)
-                       goto error_uninitialize_ring;
-       }
+       ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL);
+       if (ret)
+               goto error_free_dev;
 
        /* Get the device into a sane initial state */
-       ret = adis16203_initial_setup(indio_dev);
+       ret = adis_initial_startup(st);
        if (ret)
-               goto error_remove_trigger;
+               goto error_cleanup_buffer_trigger;
 
        ret = iio_device_register(indio_dev);
        if (ret)
-               goto error_remove_trigger;
+               goto error_cleanup_buffer_trigger;
 
        return 0;
 
-error_remove_trigger:
-       adis16203_remove_trigger(indio_dev);
-error_uninitialize_ring:
-       iio_buffer_unregister(indio_dev);
-error_unreg_ring_funcs:
-       adis16203_unconfigure_ring(indio_dev);
+error_cleanup_buffer_trigger:
+       adis_cleanup_buffer_and_trigger(st, indio_dev);
 error_free_dev:
        iio_device_free(indio_dev);
 error_ret:
@@ -503,11 +194,10 @@ error_ret:
 static int __devexit adis16203_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
+       struct adis *st = iio_priv(indio_dev);
 
        iio_device_unregister(indio_dev);
-       adis16203_remove_trigger(indio_dev);
-       iio_buffer_unregister(indio_dev);
-       adis16203_unconfigure_ring(indio_dev);
+       adis_cleanup_buffer_and_trigger(st, indio_dev);
        iio_device_free(indio_dev);
 
        return 0;
diff --git a/drivers/staging/iio/accel/adis16203_ring.c b/drivers/staging/iio/accel/adis16203_ring.c
deleted file mode 100644 (file)
index eba2e28..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16203.h"
-
-/**
- * adis16203_read_ring_data() read data registers which will be placed into ring
- * @indio_dev: the IIO device
- * @rx: somewhere to pass back the value read
- **/
-static int adis16203_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-       struct spi_message msg;
-       struct adis16203_state *st = iio_priv(indio_dev);
-       struct spi_transfer xfers[ADIS16203_OUTPUTS + 1];
-       int ret;
-       int i;
-
-       mutex_lock(&st->buf_lock);
-
-       spi_message_init(&msg);
-
-       memset(xfers, 0, sizeof(xfers));
-       for (i = 0; i <= ADIS16203_OUTPUTS; i++) {
-               xfers[i].bits_per_word = 8;
-               xfers[i].cs_change = 1;
-               xfers[i].len = 2;
-               xfers[i].delay_usecs = 20;
-               xfers[i].tx_buf = st->tx + 2 * i;
-               if (i < 1) /* SUPPLY_OUT: 0x02, AUX_ADC: 0x08 */
-                       st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i);
-               else
-                       st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i + 6);
-               st->tx[2 * i + 1] = 0;
-               if (i >= 1)
-                       xfers[i].rx_buf = rx + 2 * (i - 1);
-               spi_message_add_tail(&xfers[i], &msg);
-       }
-
-       ret = spi_sync(st->us, &msg);
-       if (ret)
-               dev_err(&st->us->dev, "problem when burst reading");
-
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
- * specific to be rolled into the core.
- */
-static irqreturn_t adis16203_trigger_handler(int irq, void *p)
-{
-       struct iio_poll_func *pf = p;
-       struct iio_dev *indio_dev = pf->indio_dev;
-       struct adis16203_state *st = iio_priv(indio_dev);
-
-       int i = 0;
-       s16 *data;
-
-       data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-       if (data == NULL) {
-               dev_err(&st->us->dev, "memory alloc failed in ring bh");
-               goto done;
-       }
-
-       if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
-           adis16203_read_ring_data(indio_dev, st->rx) >= 0)
-               for (; i < bitmap_weight(indio_dev->active_scan_mask,
-                                        indio_dev->masklength); i++)
-                       data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-       /* Guaranteed to be aligned with 8 byte boundary */
-       if (indio_dev->scan_timestamp)
-               *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-       iio_push_to_buffers(indio_dev, (u8 *)data);
-
-       kfree(data);
-done:
-       iio_trigger_notify_done(indio_dev->trig);
-
-       return IRQ_HANDLED;
-}
-
-void adis16203_unconfigure_ring(struct iio_dev *indio_dev)
-{
-       iio_dealloc_pollfunc(indio_dev->pollfunc);
-       iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16203_ring_setup_ops = {
-       .preenable = &iio_sw_buffer_preenable,
-       .postenable = &iio_triggered_buffer_postenable,
-       .predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16203_configure_ring(struct iio_dev *indio_dev)
-{
-       int ret = 0;
-       struct iio_buffer *ring;
-
-       ring = iio_sw_rb_allocate(indio_dev);
-       if (!ring) {
-               ret = -ENOMEM;
-               return ret;
-       }
-       indio_dev->buffer = ring;
-       ring->scan_timestamp = true;
-       indio_dev->setup_ops = &adis16203_ring_setup_ops;
-
-       indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-                                                &adis16203_trigger_handler,
-                                                IRQF_ONESHOT,
-                                                indio_dev,
-                                                "adis16203_consumer%d",
-                                                indio_dev->id);
-       if (indio_dev->pollfunc == NULL) {
-               ret = -ENOMEM;
-               goto error_iio_sw_rb_free;
-       }
-
-       indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-       return 0;
-
-error_iio_sw_rb_free:
-       iio_sw_rb_free(indio_dev->buffer);
-       return ret;
-}
diff --git a/drivers/staging/iio/accel/adis16203_trigger.c b/drivers/staging/iio/accel/adis16203_trigger.c
deleted file mode 100644 (file)
index b8a0407..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16203.h"
-
-/**
- * adis16203_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16203_data_rdy_trigger_set_state(struct iio_trigger *trig,
-                                               bool state)
-{
-       struct iio_dev *indio_dev = trig->private_data;
-
-       dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-       return adis16203_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16203_trigger_ops = {
-       .owner = THIS_MODULE,
-       .set_trigger_state = &adis16203_data_rdy_trigger_set_state,
-};
-
-int adis16203_probe_trigger(struct iio_dev *indio_dev)
-{
-       int ret;
-       struct adis16203_state *st = iio_priv(indio_dev);
-
-       st->trig = iio_trigger_alloc("adis16203-dev%d", indio_dev->id);
-       if (st->trig == NULL) {
-               ret = -ENOMEM;
-               goto error_ret;
-       }
-
-       ret = request_irq(st->us->irq,
-                         &iio_trigger_generic_data_rdy_poll,
-                         IRQF_TRIGGER_RISING,
-                         "adis16203",
-                         st->trig);
-       if (ret)
-               goto error_free_trig;
-
-       st->trig->dev.parent = &st->us->dev;
-       st->trig->ops = &adis16203_trigger_ops;
-       st->trig->private_data = indio_dev;
-       ret = iio_trigger_register(st->trig);
-
-       /* select default trigger */
-       indio_dev->trig = st->trig;
-       if (ret)
-               goto error_free_irq;
-
-       return 0;
-
-error_free_irq:
-       free_irq(st->us->irq, st->trig);
-error_free_trig:
-       iio_trigger_free(st->trig);
-error_ret:
-       return ret;
-}
-
-void adis16203_remove_trigger(struct iio_dev *indio_dev)
-{
-       struct adis16203_state *st = iio_priv(indio_dev);
-
-       iio_trigger_unregister(st->trig);
-       free_irq(st->us->irq, st->trig);
-       iio_trigger_free(st->trig);
-}
index 7cf4e91f83adf19e6997bfca7eac38eaa032104e..9ff950c1e8dbff21a5400892db375ea45a8e4463 100644 (file)
@@ -3,9 +3,6 @@
 
 #define ADIS16204_STARTUP_DELAY        220 /* ms */
 
-#define ADIS16204_READ_REG(a)    a
-#define ADIS16204_WRITE_REG(a) ((a) | 0x80)
-
 #define ADIS16204_FLASH_CNT      0x00 /* Flash memory write count */
 #define ADIS16204_SUPPLY_OUT     0x02 /* Output, power supply */
 #define ADIS16204_XACCL_OUT      0x04 /* Output, x-axis accelerometer */
@@ -35,8 +32,6 @@
 #define ADIS16204_DIAG_STAT      0x3C /* Diagnostics, system status register */
 #define ADIS16204_GLOB_CMD       0x3E /* Operation, system command register */
 
-#define ADIS16204_OUTPUTS        5
-
 /* MSC_CTRL */
 #define ADIS16204_MSC_CTRL_PWRUP_SELF_TEST     (1 << 10) /* Self-test at power-on: 1 = disabled, 0 = enabled */
 #define ADIS16204_MSC_CTRL_SELF_TEST_EN                (1 << 8)  /* Self-test enable */
 /* DIAG_STAT */
 #define ADIS16204_DIAG_STAT_ALARM2        (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
 #define ADIS16204_DIAG_STAT_ALARM1        (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
-#define ADIS16204_DIAG_STAT_SELFTEST_FAIL (1<<5) /* Self-test diagnostic error flag: 1 = error condition,
+#define ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT 5 /* Self-test diagnostic error flag: 1 = error condition,
                                                0 = normal operation */
-#define ADIS16204_DIAG_STAT_SPI_FAIL     (1<<3) /* SPI communications failure */
-#define ADIS16204_DIAG_STAT_FLASH_UPT    (1<<2) /* Flash update failure */
-#define ADIS16204_DIAG_STAT_POWER_HIGH   (1<<1) /* Power supply above 3.625 V */
-#define ADIS16204_DIAG_STAT_POWER_LOW    (1<<0) /* Power supply below 2.975 V */
+#define ADIS16204_DIAG_STAT_SPI_FAIL_BIT      3 /* SPI communications failure */
+#define ADIS16204_DIAG_STAT_FLASH_UPT_BIT     2 /* Flash update failure */
+#define ADIS16204_DIAG_STAT_POWER_HIGH_BIT    1 /* Power supply above 3.625 V */
+#define ADIS16204_DIAG_STAT_POWER_LOW_BIT     0 /* Power supply below 2.975 V */
 
 /* GLOB_CMD */
 #define ADIS16204_GLOB_CMD_SW_RESET    (1<<7)
 #define ADIS16204_GLOB_CMD_CLEAR_STAT  (1<<4)
 #define ADIS16204_GLOB_CMD_FACTORY_CAL (1<<1)
 
-#define ADIS16204_MAX_TX 24
-#define ADIS16204_MAX_RX 24
-
 #define ADIS16204_ERROR_ACTIVE          (1<<14)
 
-/**
- * struct adis16204_state - device instance specific data
- * @us:                        actual spi_device
- * @trig:              data ready trigger registered with iio
- * @tx:                        transmit buffer
- * @rx:                        receive buffer
- * @buf_lock:          mutex to protect tx and rx
- **/
-struct adis16204_state {
-       struct spi_device       *us;
-       struct iio_trigger      *trig;
-       struct mutex            buf_lock;
-       u8                      tx[ADIS16204_MAX_TX] ____cacheline_aligned;
-       u8                      rx[ADIS16204_MAX_RX];
-};
-
-int adis16204_set_irq(struct iio_dev *indio_dev, bool enable);
-
 enum adis16204_scan {
-       ADIS16204_SCAN_SUPPLY,
        ADIS16204_SCAN_ACC_X,
        ADIS16204_SCAN_ACC_Y,
+       ADIS16204_SCAN_ACC_XY,
+       ADIS16204_SCAN_SUPPLY,
        ADIS16204_SCAN_AUX_ADC,
        ADIS16204_SCAN_TEMP,
 };
 
-#ifdef CONFIG_IIO_BUFFER
-void adis16204_remove_trigger(struct iio_dev *indio_dev);
-int adis16204_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16204_read_data_from_ring(struct device *dev,
-                                     struct device_attribute *attr,
-                                     char *buf);
-
-int adis16204_configure_ring(struct iio_dev *indio_dev);
-void adis16204_unconfigure_ring(struct iio_dev *indio_dev);
-
-#else /* CONFIG_IIO_BUFFER */
-
-static inline void adis16204_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16204_probe_trigger(struct iio_dev *indio_dev)
-{
-       return 0;
-}
-
-static inline ssize_t
-adis16204_read_data_from_ring(struct device *dev,
-                             struct device_attribute *attr,
-                             char *buf)
-{
-       return 0;
-}
-
-static int adis16204_configure_ring(struct iio_dev *indio_dev)
-{
-       return 0;
-}
-
-static inline void adis16204_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-#endif /* CONFIG_IIO_BUFFER */
 #endif /* SPI_ADIS16204_H_ */
index 9b75a2bc8cbe1fa0fe80eba36ffb4a606714633c..6dafad67cd239da86c0a5321bcb625a041817916 100644 (file)
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
 
 #include "adis16204.h"
 
-/**
- * adis16204_spi_write_reg_8() - write single byte to a register
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-static int adis16204_spi_write_reg_8(struct iio_dev *indio_dev,
-               u8 reg_address,
-               u8 val)
-{
-       int ret;
-       struct adis16204_state *st = iio_priv(indio_dev);
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16204_WRITE_REG(reg_address);
-       st->tx[1] = val;
-
-       ret = spi_write(st->us, st->tx, 2);
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/**
- * adis16204_spi_write_reg_16() - write 2 bytes to a pair of registers
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: value to be written
- **/
-static int adis16204_spi_write_reg_16(struct iio_dev *indio_dev,
-               u8 lower_reg_address,
-               u16 value)
-{
-       int ret;
-       struct spi_message msg;
-       struct adis16204_state *st = iio_priv(indio_dev);
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = st->tx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-               }, {
-                       .tx_buf = st->tx + 2,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-               },
-       };
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16204_WRITE_REG(lower_reg_address);
-       st->tx[1] = value & 0xFF;
-       st->tx[2] = ADIS16204_WRITE_REG(lower_reg_address + 1);
-       st->tx[3] = (value >> 8) & 0xFF;
-
-       spi_message_init(&msg);
-       spi_message_add_tail(&xfers[0], &msg);
-       spi_message_add_tail(&xfers[1], &msg);
-       ret = spi_sync(st->us, &msg);
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/**
- * adis16204_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int adis16204_spi_read_reg_16(struct iio_dev *indio_dev,
-                                    u8 lower_reg_address,
-                                    u16 *val)
-{
-       struct spi_message msg;
-       struct adis16204_state *st = iio_priv(indio_dev);
-       int ret;
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = st->tx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-                       .delay_usecs = 20,
-               }, {
-                       .rx_buf = st->rx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .delay_usecs = 20,
-               },
-       };
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16204_READ_REG(lower_reg_address);
-       st->tx[1] = 0;
-
-       spi_message_init(&msg);
-       spi_message_add_tail(&xfers[0], &msg);
-       spi_message_add_tail(&xfers[1], &msg);
-       ret = spi_sync(st->us, &msg);
-       if (ret) {
-               dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
-                               lower_reg_address);
-               goto error_ret;
-       }
-       *val = (st->rx[0] << 8) | st->rx[1];
-
-error_ret:
-       mutex_unlock(&st->buf_lock);
-       return ret;
-}
-
-static int adis16204_check_status(struct iio_dev *indio_dev)
-{
-       u16 status;
-       int ret;
-
-       ret = adis16204_spi_read_reg_16(indio_dev,
-                                       ADIS16204_DIAG_STAT, &status);
-       if (ret < 0) {
-               dev_err(&indio_dev->dev, "Reading status failed\n");
-               goto error_ret;
-       }
-       ret = status & 0x1F;
-
-       if (status & ADIS16204_DIAG_STAT_SELFTEST_FAIL)
-               dev_err(&indio_dev->dev, "Self test failure\n");
-       if (status & ADIS16204_DIAG_STAT_SPI_FAIL)
-               dev_err(&indio_dev->dev, "SPI failure\n");
-       if (status & ADIS16204_DIAG_STAT_FLASH_UPT)
-               dev_err(&indio_dev->dev, "Flash update failed\n");
-       if (status & ADIS16204_DIAG_STAT_POWER_HIGH)
-               dev_err(&indio_dev->dev, "Power supply above 3.625V\n");
-       if (status & ADIS16204_DIAG_STAT_POWER_LOW)
-               dev_err(&indio_dev->dev, "Power supply below 2.975V\n");
-
-error_ret:
-       return ret;
-}
-
-static int adis16204_reset(struct iio_dev *indio_dev)
-{
-       int ret;
-       ret = adis16204_spi_write_reg_8(indio_dev,
-                       ADIS16204_GLOB_CMD,
-                       ADIS16204_GLOB_CMD_SW_RESET);
-       if (ret)
-               dev_err(&indio_dev->dev, "problem resetting device");
-
-       return ret;
-}
-
-int adis16204_set_irq(struct iio_dev *indio_dev, bool enable)
-{
-       int ret = 0;
-       u16 msc;
-
-       ret = adis16204_spi_read_reg_16(indio_dev, ADIS16204_MSC_CTRL, &msc);
-       if (ret)
-               goto error_ret;
-
-       msc |= ADIS16204_MSC_CTRL_ACTIVE_HIGH;
-       msc &= ~ADIS16204_MSC_CTRL_DATA_RDY_DIO2;
-       if (enable)
-               msc |= ADIS16204_MSC_CTRL_DATA_RDY_EN;
-       else
-               msc &= ~ADIS16204_MSC_CTRL_DATA_RDY_EN;
-
-       ret = adis16204_spi_write_reg_16(indio_dev, ADIS16204_MSC_CTRL, msc);
-
-error_ret:
-       return ret;
-}
-
-static int adis16204_self_test(struct iio_dev *indio_dev)
-{
-       int ret;
-       ret = adis16204_spi_write_reg_16(indio_dev,
-                       ADIS16204_MSC_CTRL,
-                       ADIS16204_MSC_CTRL_SELF_TEST_EN);
-       if (ret) {
-               dev_err(&indio_dev->dev, "problem starting self test");
-               goto err_ret;
-       }
-
-       adis16204_check_status(indio_dev);
-
-err_ret:
-       return ret;
-}
-
-static int adis16204_initial_setup(struct iio_dev *indio_dev)
-{
-       int ret;
-
-       /* Disable IRQ */
-       ret = adis16204_set_irq(indio_dev, false);
-       if (ret) {
-               dev_err(&indio_dev->dev, "disable irq failed");
-               goto err_ret;
-       }
-
-       /* Do self test */
-       ret = adis16204_self_test(indio_dev);
-       if (ret) {
-               dev_err(&indio_dev->dev, "self test failure");
-               goto err_ret;
-       }
-
-       /* Read status register to check the result */
-       ret = adis16204_check_status(indio_dev);
-       if (ret) {
-               adis16204_reset(indio_dev);
-               dev_err(&indio_dev->dev, "device not playing ball -> reset");
-               msleep(ADIS16204_STARTUP_DELAY);
-               ret = adis16204_check_status(indio_dev);
-               if (ret) {
-                       dev_err(&indio_dev->dev, "giving up");
-                       goto err_ret;
-               }
-       }
-
-err_ret:
-       return ret;
-}
-
 /* Unique to this driver currently */
 
-enum adis16204_channel {
-       in_supply,
-       in_aux,
-       temp,
-       accel_x,
-       accel_y,
-       accel_xy,
-};
-
-static u8 adis16204_addresses[6][3] = {
-       [in_supply] = { ADIS16204_SUPPLY_OUT },
-       [in_aux] = { ADIS16204_AUX_ADC },
-       [temp] = { ADIS16204_TEMP_OUT },
-       [accel_x] = { ADIS16204_XACCL_OUT, ADIS16204_XACCL_NULL,
-                     ADIS16204_X_PEAK_OUT },
-       [accel_y] = { ADIS16204_XACCL_OUT, ADIS16204_YACCL_NULL,
-                     ADIS16204_Y_PEAK_OUT },
-       [accel_xy] = { ADIS16204_XY_RSS_OUT, 0,
-                      ADIS16204_XY_PEAK_OUT },
+static const u8 adis16204_addresses[][2] = {
+       [ADIS16204_SCAN_ACC_X] = { ADIS16204_XACCL_NULL, ADIS16204_X_PEAK_OUT },
+       [ADIS16204_SCAN_ACC_Y] = { ADIS16204_YACCL_NULL, ADIS16204_Y_PEAK_OUT },
+       [ADIS16204_SCAN_ACC_XY] = { 0, ADIS16204_XY_PEAK_OUT },
 };
 
 static int adis16204_read_raw(struct iio_dev *indio_dev,
@@ -281,6 +38,7 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
                              int *val, int *val2,
                              long mask)
 {
+       struct adis *st = iio_priv(indio_dev);
        int ret;
        int bits;
        u8 addr;
@@ -289,29 +47,8 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               mutex_lock(&indio_dev->mlock);
-               addr = adis16204_addresses[chan->address][0];
-               ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16);
-               if (ret) {
-                       mutex_unlock(&indio_dev->mlock);
-                       return ret;
-               }
-
-               if (val16 & ADIS16204_ERROR_ACTIVE) {
-                       ret = adis16204_check_status(indio_dev);
-                       if (ret) {
-                               mutex_unlock(&indio_dev->mlock);
-                               return ret;
-                       }
-               }
-               val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
-               if (chan->scan_type.sign == 's')
-                       val16 = (s16)(val16 <<
-                                     (16 - chan->scan_type.realbits)) >>
-                               (16 - chan->scan_type.realbits);
-               *val = val16;
-               mutex_unlock(&indio_dev->mlock);
-               return IIO_VAL_INT;
+               return adis_single_conversion(indio_dev, chan,
+                               ADIS16204_ERROR_ACTIVE, val);
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
@@ -351,14 +88,14 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_PEAK:
                if (mask == IIO_CHAN_INFO_CALIBBIAS) {
                        bits = 12;
-                       addrind = 1;
+                       addrind = 0;
                } else { /* PEAK_SEPARATE */
                        bits = 14;
-                       addrind = 2;
+                       addrind = 1;
                }
                mutex_lock(&indio_dev->mlock);
-               addr = adis16204_addresses[chan->address][addrind];
-               ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16);
+               addr = adis16204_addresses[chan->scan_index][addrind];
+               ret = adis_read_reg_16(st, addr, &val16);
                if (ret) {
                        mutex_unlock(&indio_dev->mlock);
                        return ret;
@@ -378,6 +115,7 @@ static int adis16204_write_raw(struct iio_dev *indio_dev,
                               int val2,
                               long mask)
 {
+       struct adis *st = iio_priv(indio_dev);
        int bits;
        s16 val16;
        u8 addr;
@@ -391,112 +129,63 @@ static int adis16204_write_raw(struct iio_dev *indio_dev,
                        return -EINVAL;
                }
                val16 = val & ((1 << bits) - 1);
-               addr = adis16204_addresses[chan->address][1];
-               return adis16204_spi_write_reg_16(indio_dev, addr, val16);
+               addr = adis16204_addresses[chan->scan_index][1];
+               return adis_write_reg_16(st, addr, val16);
        }
        return -EINVAL;
 }
 
 static const struct iio_chan_spec adis16204_channels[] = {
-       {
-               .type = IIO_VOLTAGE,
-               .indexed = 1, /* Note was not previously indexed */
-               .channel = 0,
-               .extend_name = "supply",
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-               .address = in_supply,
-               .scan_index = ADIS16204_SCAN_SUPPLY,
-               .scan_type = {
-                       .sign = 'u',
-                       .realbits = 12,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_VOLTAGE,
-               .indexed = 1,
-               .channel = 1,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-               .address = in_aux,
-               .scan_index = ADIS16204_SCAN_AUX_ADC,
-               .scan_type = {
-                       .sign = 'u',
-                       .realbits = 12,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_TEMP,
-               .indexed = 1,
-               .channel = 0,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
-               IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
-               .address = temp,
-               .scan_index = ADIS16204_SCAN_TEMP,
-               .scan_type = {
-                       .sign = 'u',
-                       .realbits = 12,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_ACCEL,
-               .modified = 1,
-               .channel2 = IIO_MOD_X,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+       ADIS_SUPPLY_CHAN(ADIS16204_SUPPLY_OUT, ADIS16204_SCAN_SUPPLY, 12),
+       ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 12),
+       ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 12),
+       ADIS_ACCEL_CHAN(X, ADIS16204_XACCL_OUT, ADIS16204_SCAN_ACC_X,
                IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-               IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
-               .address = accel_x,
-               .scan_index = ADIS16204_SCAN_ACC_X,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 14,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_ACCEL,
-               .modified = 1,
-               .channel2 = IIO_MOD_Y,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+               IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 14),
+       ADIS_ACCEL_CHAN(Y, ADIS16204_YACCL_OUT, ADIS16204_SCAN_ACC_Y,
                IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-               IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
-               .address = accel_y,
-               .scan_index = ADIS16204_SCAN_ACC_Y,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 14,
-                       .storagebits = 16,
-               },
-       },
+               IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 14),
+       ADIS_ACCEL_CHAN(ROOT_SUM_SQUARED_X_Y, ADIS16204_XY_RSS_OUT,
+               ADIS16204_SCAN_ACC_XY, IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 14),
        IIO_CHAN_SOFT_TIMESTAMP(5),
-       {
-               .type = IIO_ACCEL,
-               .modified = 1,
-               .channel2 = IIO_MOD_ROOT_SUM_SQUARED_X_Y,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
-               IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
-               .address = accel_xy,
-               .scan_type = {
-                       .sign = 'u',
-                       .realbits = 14,
-                       .storagebits = 16,
-               },
-       }
 };
 
 static const struct iio_info adis16204_info = {
        .read_raw = &adis16204_read_raw,
        .write_raw = &adis16204_write_raw,
+       .update_scan_mode = adis_update_scan_mode,
        .driver_module = THIS_MODULE,
 };
 
+static const char * const adis16204_status_error_msgs[] = {
+       [ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT] = "Self test failure",
+       [ADIS16204_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
+       [ADIS16204_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
+       [ADIS16204_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
+       [ADIS16204_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.975V",
+};
+
+static const struct adis_data adis16204_data = {
+       .read_delay = 20,
+       .msc_ctrl_reg = ADIS16204_MSC_CTRL,
+       .glob_cmd_reg = ADIS16204_GLOB_CMD,
+       .diag_stat_reg = ADIS16204_DIAG_STAT,
+
+       .self_test_mask = ADIS16204_MSC_CTRL_SELF_TEST_EN,
+       .startup_delay = ADIS16204_STARTUP_DELAY,
+
+       .status_error_msgs = adis16204_status_error_msgs,
+       .status_error_mask = BIT(ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT) |
+               BIT(ADIS16204_DIAG_STAT_SPI_FAIL_BIT) |
+               BIT(ADIS16204_DIAG_STAT_FLASH_UPT_BIT) |
+               BIT(ADIS16204_DIAG_STAT_POWER_HIGH_BIT) |
+               BIT(ADIS16204_DIAG_STAT_POWER_LOW_BIT),
+};
+
 static int __devinit adis16204_probe(struct spi_device *spi)
 {
        int ret;
-       struct adis16204_state *st;
+       struct adis *st;
        struct iio_dev *indio_dev;
 
        /* setup the industrialio driver allocated elements */
@@ -508,8 +197,6 @@ static int __devinit adis16204_probe(struct spi_device *spi)
        st = iio_priv(indio_dev);
        /* this is only used for removal purposes */
        spi_set_drvdata(spi, indio_dev);
-       st->us = spi;
-       mutex_init(&st->buf_lock);
 
        indio_dev->name = spi->dev.driver->name;
        indio_dev->dev.parent = &spi->dev;
@@ -518,40 +205,26 @@ static int __devinit adis16204_probe(struct spi_device *spi)
        indio_dev->num_channels = ARRAY_SIZE(adis16204_channels);
        indio_dev->modes = INDIO_DIRECT_MODE;
 
-       ret = adis16204_configure_ring(indio_dev);
+       ret = adis_init(st, indio_dev, spi, &adis16204_data);
        if (ret)
                goto error_free_dev;
 
-       ret = iio_buffer_register(indio_dev,
-                                 adis16204_channels,
-                                 6);
-       if (ret) {
-               printk(KERN_ERR "failed to initialize the ring\n");
-               goto error_unreg_ring_funcs;
-       }
-
-       if (spi->irq) {
-               ret = adis16204_probe_trigger(indio_dev);
-               if (ret)
-                       goto error_uninitialize_ring;
-       }
+       ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL);
+       if (ret)
+               goto error_free_dev;
 
        /* Get the device into a sane initial state */
-       ret = adis16204_initial_setup(indio_dev);
+       ret = adis_initial_startup(st);
        if (ret)
-               goto error_remove_trigger;
+               goto error_cleanup_buffer_trigger;
        ret = iio_device_register(indio_dev);
        if (ret)
-               goto error_remove_trigger;
+               goto error_cleanup_buffer_trigger;
 
        return 0;
 
-error_remove_trigger:
-       adis16204_remove_trigger(indio_dev);
-error_uninitialize_ring:
-       iio_buffer_unregister(indio_dev);
-error_unreg_ring_funcs:
-       adis16204_unconfigure_ring(indio_dev);
+error_cleanup_buffer_trigger:
+       adis_cleanup_buffer_and_trigger(st, indio_dev);
 error_free_dev:
        iio_device_free(indio_dev);
 error_ret:
@@ -561,11 +234,10 @@ error_ret:
 static int __devexit adis16204_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
+       struct adis *st = iio_priv(indio_dev);
 
        iio_device_unregister(indio_dev);
-       adis16204_remove_trigger(indio_dev);
-       iio_buffer_unregister(indio_dev);
-       adis16204_unconfigure_ring(indio_dev);
+       adis_cleanup_buffer_and_trigger(st, indio_dev);
        iio_device_free(indio_dev);
 
        return 0;
diff --git a/drivers/staging/iio/accel/adis16204_ring.c b/drivers/staging/iio/accel/adis16204_ring.c
deleted file mode 100644 (file)
index 3611a13..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16204.h"
-
-/**
- * adis16204_read_ring_data() read data registers which will be placed into ring
- * @indio_dev: the IIO device
- * @rx: somewhere to pass back the value read
- **/
-static int adis16204_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-       struct spi_message msg;
-       struct adis16204_state *st = iio_priv(indio_dev);
-       struct spi_transfer xfers[ADIS16204_OUTPUTS + 1];
-       int ret;
-       int i;
-
-       mutex_lock(&st->buf_lock);
-
-       spi_message_init(&msg);
-
-       memset(xfers, 0, sizeof(xfers));
-       for (i = 0; i <= ADIS16204_OUTPUTS; i++) {
-               xfers[i].bits_per_word = 8;
-               xfers[i].cs_change = 1;
-               xfers[i].len = 2;
-               xfers[i].delay_usecs = 20;
-               xfers[i].tx_buf = st->tx + 2 * i;
-               st->tx[2 * i]
-                       = ADIS16204_READ_REG(ADIS16204_SUPPLY_OUT + 2 * i);
-               st->tx[2 * i + 1] = 0;
-               if (i >= 1)
-                       xfers[i].rx_buf = rx + 2 * (i - 1);
-               spi_message_add_tail(&xfers[i], &msg);
-       }
-
-       ret = spi_sync(st->us, &msg);
-       if (ret)
-               dev_err(&st->us->dev, "problem when burst reading");
-
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
- * specific to be rolled into the core.
- */
-static irqreturn_t adis16204_trigger_handler(int irq, void *p)
-{
-       struct iio_poll_func *pf = p;
-       struct iio_dev *indio_dev = pf->indio_dev;
-       struct adis16204_state *st = iio_priv(indio_dev);
-       int i = 0;
-       s16 *data;
-
-       data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-       if (data == NULL) {
-               dev_err(&st->us->dev, "memory alloc failed in ring bh");
-               goto done;
-       }
-
-       if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
-           adis16204_read_ring_data(indio_dev, st->rx) >= 0)
-               for (; i < bitmap_weight(indio_dev->active_scan_mask,
-                                        indio_dev->masklength); i++)
-                       data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-       /* Guaranteed to be aligned with 8 byte boundary */
-       if (indio_dev->scan_timestamp)
-               *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-       iio_push_to_buffers(indio_dev, (u8 *)data);
-
-       kfree(data);
-done:
-       iio_trigger_notify_done(indio_dev->trig);
-
-       return IRQ_HANDLED;
-}
-
-void adis16204_unconfigure_ring(struct iio_dev *indio_dev)
-{
-       iio_dealloc_pollfunc(indio_dev->pollfunc);
-       iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16204_ring_setup_ops = {
-       .preenable = &iio_sw_buffer_preenable,
-       .postenable = &iio_triggered_buffer_postenable,
-       .predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16204_configure_ring(struct iio_dev *indio_dev)
-{
-       int ret = 0;
-       struct iio_buffer *ring;
-
-       ring = iio_sw_rb_allocate(indio_dev);
-       if (!ring) {
-               ret = -ENOMEM;
-               return ret;
-       }
-       indio_dev->buffer = ring;
-       ring->scan_timestamp = true;
-       indio_dev->setup_ops = &adis16204_ring_setup_ops;
-
-       indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-                                                &adis16204_trigger_handler,
-                                                IRQF_ONESHOT,
-                                                indio_dev,
-                                                "%s_consumer%d",
-                                                indio_dev->name,
-                                                indio_dev->id);
-       if (indio_dev->pollfunc == NULL) {
-               ret = -ENOMEM;
-               goto error_iio_sw_rb_free;
-       }
-
-       indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-       return 0;
-
-error_iio_sw_rb_free:
-       iio_sw_rb_free(indio_dev->buffer);
-       return ret;
-}
diff --git a/drivers/staging/iio/accel/adis16204_trigger.c b/drivers/staging/iio/accel/adis16204_trigger.c
deleted file mode 100644 (file)
index 408a168..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16204.h"
-
-/**
- * adis16204_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16204_data_rdy_trigger_set_state(struct iio_trigger *trig,
-                                               bool state)
-{
-       struct iio_dev *indio_dev = trig->private_data;
-
-       dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-       return adis16204_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16204_trigger_ops = {
-       .owner = THIS_MODULE,
-       .set_trigger_state = &adis16204_data_rdy_trigger_set_state,
-};
-
-int adis16204_probe_trigger(struct iio_dev *indio_dev)
-{
-       int ret;
-       struct adis16204_state *st = iio_priv(indio_dev);
-
-       st->trig = iio_trigger_alloc("adis16204-dev%d", indio_dev->id);
-       if (st->trig == NULL) {
-               ret = -ENOMEM;
-               goto error_ret;
-       }
-
-       ret = request_irq(st->us->irq,
-                         &iio_trigger_generic_data_rdy_poll,
-                         IRQF_TRIGGER_RISING,
-                         "adis16204",
-                         st->trig);
-       if (ret)
-               goto error_free_trig;
-
-       st->trig->dev.parent = &st->us->dev;
-       st->trig->ops = &adis16204_trigger_ops;
-       st->trig->private_data = indio_dev;
-       ret = iio_trigger_register(st->trig);
-
-       /* select default trigger */
-       indio_dev->trig = st->trig;
-       if (ret)
-               goto error_free_irq;
-
-       return 0;
-
-error_free_irq:
-       free_irq(st->us->irq, st->trig);
-error_free_trig:
-       iio_trigger_free(st->trig);
-error_ret:
-       return ret;
-}
-
-void adis16204_remove_trigger(struct iio_dev *indio_dev)
-{
-       struct adis16204_state *state = iio_priv(indio_dev);
-
-       iio_trigger_unregister(state->trig);
-       free_irq(state->us->irq, state->trig);
-       iio_trigger_free(state->trig);
-}
index 3c88b86e7b81a7d29ca98dc3bb3dd8c0ab9b3537..ad3945a06292f98259943e0bc83f9d56a3e06212 100644 (file)
@@ -3,9 +3,6 @@
 
 #define ADIS16209_STARTUP_DELAY        220 /* ms */
 
-#define ADIS16209_READ_REG(a)    a
-#define ADIS16209_WRITE_REG(a) ((a) | 0x80)
-
 /* Flash memory write count */
 #define ADIS16209_FLASH_CNT      0x00
 /* Output, power supply */
@@ -61,8 +58,6 @@
 /* Operation, system command register */
 #define ADIS16209_GLOB_CMD       0x3E
 
-#define ADIS16209_OUTPUTS        8
-
 /* MSC_CTRL */
 /* Self-test at power-on: 1 = disabled, 0 = enabled */
 #define ADIS16209_MSC_CTRL_PWRUP_SELF_TEST     (1 << 10)
 /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
 #define ADIS16209_DIAG_STAT_ALARM1        (1<<8)
 /* Self-test diagnostic error flag: 1 = error condition, 0 = normal operation */
-#define ADIS16209_DIAG_STAT_SELFTEST_FAIL (1<<5)
+#define ADIS16209_DIAG_STAT_SELFTEST_FAIL_BIT  5
 /* SPI communications failure */
-#define ADIS16209_DIAG_STAT_SPI_FAIL     (1<<3)
+#define ADIS16209_DIAG_STAT_SPI_FAIL_BIT       3
 /* Flash update failure */
-#define ADIS16209_DIAG_STAT_FLASH_UPT    (1<<2)
+#define ADIS16209_DIAG_STAT_FLASH_UPT_BIT      2
 /* Power supply above 3.625 V */
-#define ADIS16209_DIAG_STAT_POWER_HIGH   (1<<1)
+#define ADIS16209_DIAG_STAT_POWER_HIGH_BIT     1
 /* Power supply below 3.15 V */
-#define ADIS16209_DIAG_STAT_POWER_LOW    (1<<0)
+#define ADIS16209_DIAG_STAT_POWER_LOW_BIT      0
 
 /* GLOB_CMD */
 #define ADIS16209_GLOB_CMD_SW_RESET    (1<<7)
 #define ADIS16209_GLOB_CMD_CLEAR_STAT  (1<<4)
 #define ADIS16209_GLOB_CMD_FACTORY_CAL (1<<1)
 
-#define ADIS16209_MAX_TX 24
-#define ADIS16209_MAX_RX 24
-
 #define ADIS16209_ERROR_ACTIVE          (1<<14)
 
-/**
- * struct adis16209_state - device instance specific data
- * @us:                        actual spi_device
- * @trig:              data ready trigger registered with iio
- * @tx:                        transmit buffer
- * @rx:                        receive buffer
- * @buf_lock:          mutex to protect tx and rx
- **/
-struct adis16209_state {
-       struct spi_device       *us;
-       struct iio_trigger      *trig;
-       struct mutex            buf_lock;
-       u8                      tx[ADIS16209_MAX_TX] ____cacheline_aligned;
-       u8                      rx[ADIS16209_MAX_RX];
-};
-
-int adis16209_set_irq(struct iio_dev *indio_dev, bool enable);
-
 #define ADIS16209_SCAN_SUPPLY  0
 #define ADIS16209_SCAN_ACC_X   1
 #define ADIS16209_SCAN_ACC_Y   2
@@ -128,45 +102,4 @@ int adis16209_set_irq(struct iio_dev *indio_dev, bool enable);
 #define ADIS16209_SCAN_INCLI_Y 6
 #define ADIS16209_SCAN_ROT     7
 
-#ifdef CONFIG_IIO_BUFFER
-
-void adis16209_remove_trigger(struct iio_dev *indio_dev);
-int adis16209_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16209_read_data_from_ring(struct device *dev,
-                                     struct device_attribute *attr,
-                                     char *buf);
-
-int adis16209_configure_ring(struct iio_dev *indio_dev);
-void adis16209_unconfigure_ring(struct iio_dev *indio_dev);
-
-#else /* CONFIG_IIO_BUFFER */
-
-static inline void adis16209_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16209_probe_trigger(struct iio_dev *indio_dev)
-{
-       return 0;
-}
-
-static inline ssize_t
-adis16209_read_data_from_ring(struct device *dev,
-                             struct device_attribute *attr,
-                             char *buf)
-{
-       return 0;
-}
-
-static int adis16209_configure_ring(struct iio_dev *indio_dev)
-{
-       return 0;
-}
-
-static inline void adis16209_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-#endif /* CONFIG_IIO_BUFFER */
 #endif /* SPI_ADIS16209_H_ */
index b7a0d5c2bbd40d764a13d56c86b0c7e78c43f88a..d2921c30a8bb1f9f05dc02352de9a5c13fff3984 100644 (file)
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
 
 #include "adis16209.h"
 
-/**
- * adis16209_spi_write_reg_8() - write single byte to a register
- * @indio_dev: iio device associated with actual device
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-static int adis16209_spi_write_reg_8(struct iio_dev *indio_dev,
-                                    u8 reg_address,
-                                    u8 val)
-{
-       int ret;
-       struct adis16209_state *st = iio_priv(indio_dev);
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16209_WRITE_REG(reg_address);
-       st->tx[1] = val;
-
-       ret = spi_write(st->us, st->tx, 2);
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/**
- * adis16209_spi_write_reg_16() - write 2 bytes to a pair of registers
- * @indio_dev: iio device associated actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: value to be written
- **/
-static int adis16209_spi_write_reg_16(struct iio_dev *indio_dev,
-                                     u8 lower_reg_address,
-                                     u16 value)
-{
-       int ret;
-       struct spi_message msg;
-       struct adis16209_state *st = iio_priv(indio_dev);
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = st->tx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-                       .delay_usecs = 30,
-               }, {
-                       .tx_buf = st->tx + 2,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .delay_usecs = 30,
-               },
-       };
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16209_WRITE_REG(lower_reg_address);
-       st->tx[1] = value & 0xFF;
-       st->tx[2] = ADIS16209_WRITE_REG(lower_reg_address + 1);
-       st->tx[3] = (value >> 8) & 0xFF;
-
-       spi_message_init(&msg);
-       spi_message_add_tail(&xfers[0], &msg);
-       spi_message_add_tail(&xfers[1], &msg);
-       ret = spi_sync(st->us, &msg);
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/**
- * adis16209_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @indio_dev: iio device associated with device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int adis16209_spi_read_reg_16(struct iio_dev *indio_dev,
-                                    u8 lower_reg_address,
-                                    u16 *val)
-{
-       struct spi_message msg;
-       struct adis16209_state *st = iio_priv(indio_dev);
-       int ret;
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = st->tx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-                       .delay_usecs = 30,
-               }, {
-                       .rx_buf = st->rx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .delay_usecs = 30,
-               },
-       };
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16209_READ_REG(lower_reg_address);
-       st->tx[1] = 0;
-
-       spi_message_init(&msg);
-       spi_message_add_tail(&xfers[0], &msg);
-       spi_message_add_tail(&xfers[1], &msg);
-       ret = spi_sync(st->us, &msg);
-       if (ret) {
-               dev_err(&st->us->dev,
-                       "problem when reading 16 bit register 0x%02X",
-                       lower_reg_address);
-               goto error_ret;
-       }
-       *val = (st->rx[0] << 8) | st->rx[1];
-
-error_ret:
-       mutex_unlock(&st->buf_lock);
-       return ret;
-}
-
-static int adis16209_reset(struct iio_dev *indio_dev)
-{
-       int ret;
-       ret = adis16209_spi_write_reg_8(indio_dev,
-                       ADIS16209_GLOB_CMD,
-                       ADIS16209_GLOB_CMD_SW_RESET);
-       if (ret)
-               dev_err(&indio_dev->dev, "problem resetting device");
-
-       return ret;
-}
-
-int adis16209_set_irq(struct iio_dev *indio_dev, bool enable)
-{
-       int ret = 0;
-       u16 msc;
-
-       ret = adis16209_spi_read_reg_16(indio_dev, ADIS16209_MSC_CTRL, &msc);
-       if (ret)
-               goto error_ret;
-
-       msc |= ADIS16209_MSC_CTRL_ACTIVE_HIGH;
-       msc &= ~ADIS16209_MSC_CTRL_DATA_RDY_DIO2;
-       if (enable)
-               msc |= ADIS16209_MSC_CTRL_DATA_RDY_EN;
-       else
-               msc &= ~ADIS16209_MSC_CTRL_DATA_RDY_EN;
-
-       ret = adis16209_spi_write_reg_16(indio_dev, ADIS16209_MSC_CTRL, msc);
-
-error_ret:
-       return ret;
-}
-
-static int adis16209_check_status(struct iio_dev *indio_dev)
-{
-       u16 status;
-       int ret;
-
-       ret = adis16209_spi_read_reg_16(indio_dev,
-                                       ADIS16209_DIAG_STAT, &status);
-       if (ret < 0) {
-               dev_err(&indio_dev->dev, "Reading status failed\n");
-               goto error_ret;
-       }
-       ret = status & 0x1F;
-
-       if (status & ADIS16209_DIAG_STAT_SELFTEST_FAIL)
-               dev_err(&indio_dev->dev, "Self test failure\n");
-       if (status & ADIS16209_DIAG_STAT_SPI_FAIL)
-               dev_err(&indio_dev->dev, "SPI failure\n");
-       if (status & ADIS16209_DIAG_STAT_FLASH_UPT)
-               dev_err(&indio_dev->dev, "Flash update failed\n");
-       if (status & ADIS16209_DIAG_STAT_POWER_HIGH)
-               dev_err(&indio_dev->dev, "Power supply above 3.625V\n");
-       if (status & ADIS16209_DIAG_STAT_POWER_LOW)
-               dev_err(&indio_dev->dev, "Power supply below 3.15V\n");
-
-error_ret:
-       return ret;
-}
-
-static int adis16209_self_test(struct iio_dev *indio_dev)
-{
-       int ret;
-       ret = adis16209_spi_write_reg_16(indio_dev,
-                       ADIS16209_MSC_CTRL,
-                       ADIS16209_MSC_CTRL_SELF_TEST_EN);
-       if (ret) {
-               dev_err(&indio_dev->dev, "problem starting self test");
-               goto err_ret;
-       }
-
-       adis16209_check_status(indio_dev);
-
-err_ret:
-       return ret;
-}
-
-static int adis16209_initial_setup(struct iio_dev *indio_dev)
-{
-       int ret;
-
-       /* Disable IRQ */
-       ret = adis16209_set_irq(indio_dev, false);
-       if (ret) {
-               dev_err(&indio_dev->dev, "disable irq failed");
-               goto err_ret;
-       }
-
-       /* Do self test */
-       ret = adis16209_self_test(indio_dev);
-       if (ret) {
-               dev_err(&indio_dev->dev, "self test failure");
-               goto err_ret;
-       }
-
-       /* Read status register to check the result */
-       ret = adis16209_check_status(indio_dev);
-       if (ret) {
-               adis16209_reset(indio_dev);
-               dev_err(&indio_dev->dev, "device not playing ball -> reset");
-               msleep(ADIS16209_STARTUP_DELAY);
-               ret = adis16209_check_status(indio_dev);
-               if (ret) {
-                       dev_err(&indio_dev->dev, "giving up");
-                       goto err_ret;
-               }
-       }
-
-err_ret:
-       return ret;
-}
-
-enum adis16209_chan {
-       in_supply,
-       temp,
-       accel_x,
-       accel_y,
-       incli_x,
-       incli_y,
-       in_aux,
-       rot,
-};
-
-static const u8 adis16209_addresses[8][2] = {
-       [in_supply] = { ADIS16209_SUPPLY_OUT },
-       [in_aux] = { ADIS16209_AUX_ADC },
-       [accel_x] = { ADIS16209_XACCL_OUT, ADIS16209_XACCL_NULL },
-       [accel_y] = { ADIS16209_YACCL_OUT, ADIS16209_YACCL_NULL },
-       [incli_x] = { ADIS16209_XINCL_OUT, ADIS16209_XINCL_NULL },
-       [incli_y] = { ADIS16209_YINCL_OUT, ADIS16209_YINCL_NULL },
-       [rot] = { ADIS16209_ROT_OUT },
-       [temp] = { ADIS16209_TEMP_OUT },
+static const u8 adis16209_addresses[8][1] = {
+       [ADIS16209_SCAN_SUPPLY] = { },
+       [ADIS16209_SCAN_AUX_ADC] = { },
+       [ADIS16209_SCAN_ACC_X] = { ADIS16209_XACCL_NULL },
+       [ADIS16209_SCAN_ACC_Y] = { ADIS16209_YACCL_NULL },
+       [ADIS16209_SCAN_INCLI_X] = { ADIS16209_XINCL_NULL },
+       [ADIS16209_SCAN_INCLI_Y] = { ADIS16209_YINCL_NULL },
+       [ADIS16209_SCAN_ROT] = { },
+       [ADIS16209_SCAN_TEMP] = { },
 };
 
 static int adis16209_write_raw(struct iio_dev *indio_dev,
@@ -281,6 +40,7 @@ static int adis16209_write_raw(struct iio_dev *indio_dev,
                               int val2,
                               long mask)
 {
+       struct adis *st = iio_priv(indio_dev);
        int bits;
        s16 val16;
        u8 addr;
@@ -295,8 +55,8 @@ static int adis16209_write_raw(struct iio_dev *indio_dev,
                        return -EINVAL;
                }
                val16 = val & ((1 << bits) - 1);
-               addr = adis16209_addresses[chan->address][1];
-               return adis16209_spi_write_reg_16(indio_dev, addr, val16);
+               addr = adis16209_addresses[chan->scan_index][0];
+               return adis_write_reg_16(st, addr, val16);
        }
        return -EINVAL;
 }
@@ -306,6 +66,7 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
                              int *val, int *val2,
                              long mask)
 {
+       struct adis *st = iio_priv(indio_dev);
        int ret;
        int bits;
        u8 addr;
@@ -313,29 +74,8 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               mutex_lock(&indio_dev->mlock);
-               addr = adis16209_addresses[chan->address][0];
-               ret = adis16209_spi_read_reg_16(indio_dev, addr, &val16);
-               if (ret) {
-                       mutex_unlock(&indio_dev->mlock);
-                       return ret;
-               }
-
-               if (val16 & ADIS16209_ERROR_ACTIVE) {
-                       ret = adis16209_check_status(indio_dev);
-                       if (ret) {
-                               mutex_unlock(&indio_dev->mlock);
-                               return ret;
-                       }
-               }
-               val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
-               if (chan->scan_type.sign == 's')
-                       val16 = (s16)(val16 <<
-                                     (16 - chan->scan_type.realbits)) >>
-                               (16 - chan->scan_type.realbits);
-               *val = val16;
-               mutex_unlock(&indio_dev->mlock);
-               return IIO_VAL_INT;
+               return adis_single_conversion(indio_dev, chan,
+                       ADIS16209_ERROR_ACTIVE, val);
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
@@ -374,8 +114,8 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
                        return -EINVAL;
                }
                mutex_lock(&indio_dev->mlock);
-               addr = adis16209_addresses[chan->address][1];
-               ret = adis16209_spi_read_reg_16(indio_dev, addr, &val16);
+               addr = adis16209_addresses[chan->scan_index][0];
+               ret = adis_read_reg_16(st, addr, &val16);
                if (ret) {
                        mutex_unlock(&indio_dev->mlock);
                        return ret;
@@ -390,128 +130,56 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
 }
 
 static const struct iio_chan_spec adis16209_channels[] = {
-       {
-               .type = IIO_VOLTAGE,
-               .indexed = 1,
-               .channel = 0,
-               .extend_name = "supply",
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-               .address = in_supply,
-               .scan_index = ADIS16209_SCAN_SUPPLY,
-               .scan_type = {
-                       .sign = 'u',
-                       .realbits = 14,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_TEMP,
-               .indexed = 0,
-               .channel = 0,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
-               IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
-               .address = temp,
-               .scan_index = ADIS16209_SCAN_TEMP,
-               .scan_type = {
-                       .sign = 'u',
-                       .realbits = 12,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_ACCEL,
-               .modified = 1,
-               .channel2 = IIO_MOD_X,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SHARED_BIT |
-               IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
-               .address = accel_x,
-               .scan_index = ADIS16209_SCAN_ACC_X,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 14,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_ACCEL,
-               .modified = 1,
-               .channel2 = IIO_MOD_Y,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SHARED_BIT |
-               IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
-               .address = accel_y,
-               .scan_index = ADIS16209_SCAN_ACC_Y,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 14,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_VOLTAGE,
-               .indexed = 1,
-               .channel = 1,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-               .address = in_aux,
-               .scan_index = ADIS16209_SCAN_AUX_ADC,
-               .scan_type = {
-                       .sign = 'u',
-                       .realbits = 12,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_INCLI,
-               .modified = 1,
-               .channel2 = IIO_MOD_X,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SHARED_BIT,
-               .address = incli_x,
-               .scan_index = ADIS16209_SCAN_INCLI_X,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 14,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_INCLI,
-               .modified = 1,
-               .channel2 = IIO_MOD_Y,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SHARED_BIT,
-               .address = incli_y,
-               .scan_index = ADIS16209_SCAN_INCLI_Y,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 14,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_ROT,
-               .modified = 1,
-               .channel2 = IIO_MOD_X,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-               IIO_CHAN_INFO_SCALE_SHARED_BIT,
-               .address = rot,
-               .scan_index = ADIS16209_SCAN_ROT,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 14,
-                       .storagebits = 16,
-               },
-       },
+       ADIS_SUPPLY_CHAN(ADIS16209_SUPPLY_OUT, ADIS16209_SCAN_SUPPLY, 14),
+       ADIS_TEMP_CHAN(ADIS16209_TEMP_OUT, ADIS16209_SCAN_TEMP, 12),
+       ADIS_ACCEL_CHAN(X, ADIS16209_XACCL_OUT, ADIS16209_SCAN_ACC_X,
+               IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+       ADIS_ACCEL_CHAN(Y, ADIS16209_YACCL_OUT, ADIS16209_SCAN_ACC_Y,
+               IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+       ADIS_AUX_ADC_CHAN(ADIS16209_AUX_ADC, ADIS16209_SCAN_AUX_ADC, 12),
+       ADIS_INCLI_CHAN(X, ADIS16209_XINCL_OUT, ADIS16209_SCAN_INCLI_X, 0, 14),
+       ADIS_INCLI_CHAN(Y, ADIS16209_YINCL_OUT, ADIS16209_SCAN_INCLI_Y, 0, 14),
+       ADIS_ROT_CHAN(X, ADIS16209_ROT_OUT, ADIS16209_SCAN_ROT, 0, 14),
        IIO_CHAN_SOFT_TIMESTAMP(8)
 };
 
 static const struct iio_info adis16209_info = {
        .read_raw = &adis16209_read_raw,
        .write_raw = &adis16209_write_raw,
+       .update_scan_mode = adis_update_scan_mode,
        .driver_module = THIS_MODULE,
 };
 
+static const char * const adis16209_status_error_msgs[] = {
+       [ADIS16209_DIAG_STAT_SELFTEST_FAIL_BIT] = "Self test failure",
+       [ADIS16209_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
+       [ADIS16209_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
+       [ADIS16209_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
+       [ADIS16209_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V",
+};
+
+static const struct adis_data adis16209_data = {
+       .read_delay = 30,
+       .msc_ctrl_reg = ADIS16209_MSC_CTRL,
+       .glob_cmd_reg = ADIS16209_GLOB_CMD,
+       .diag_stat_reg = ADIS16209_DIAG_STAT,
+
+       .self_test_mask = ADIS16209_MSC_CTRL_SELF_TEST_EN,
+       .startup_delay = ADIS16209_STARTUP_DELAY,
+
+       .status_error_msgs = adis16209_status_error_msgs,
+       .status_error_mask = BIT(ADIS16209_DIAG_STAT_SELFTEST_FAIL_BIT) |
+               BIT(ADIS16209_DIAG_STAT_SPI_FAIL_BIT) |
+               BIT(ADIS16209_DIAG_STAT_FLASH_UPT_BIT) |
+               BIT(ADIS16209_DIAG_STAT_POWER_HIGH_BIT) |
+               BIT(ADIS16209_DIAG_STAT_POWER_LOW_BIT),
+};
+
+
 static int __devinit adis16209_probe(struct spi_device *spi)
 {
        int ret;
-       struct adis16209_state *st;
+       struct adis *st;
        struct iio_dev *indio_dev;
 
        /* setup the industrialio driver allocated elements */
@@ -523,8 +191,6 @@ static int __devinit adis16209_probe(struct spi_device *spi)
        st = iio_priv(indio_dev);
        /* this is only used for removal purposes */
        spi_set_drvdata(spi, indio_dev);
-       st->us = spi;
-       mutex_init(&st->buf_lock);
 
        indio_dev->name = spi->dev.driver->name;
        indio_dev->dev.parent = &spi->dev;
@@ -533,40 +199,25 @@ static int __devinit adis16209_probe(struct spi_device *spi)
        indio_dev->num_channels = ARRAY_SIZE(adis16209_channels);
        indio_dev->modes = INDIO_DIRECT_MODE;
 
-       ret = adis16209_configure_ring(indio_dev);
+       ret = adis_init(st, indio_dev, spi, &adis16209_data);
+       if (ret)
+               goto error_free_dev;
+       ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL);
        if (ret)
                goto error_free_dev;
-
-       ret = iio_buffer_register(indio_dev,
-                                 adis16209_channels,
-                                 ARRAY_SIZE(adis16209_channels));
-       if (ret) {
-               printk(KERN_ERR "failed to initialize the ring\n");
-               goto error_unreg_ring_funcs;
-       }
-
-       if (spi->irq) {
-               ret = adis16209_probe_trigger(indio_dev);
-               if (ret)
-                       goto error_uninitialize_ring;
-       }
 
        /* Get the device into a sane initial state */
-       ret = adis16209_initial_setup(indio_dev);
+       ret = adis_initial_startup(st);
        if (ret)
-               goto error_remove_trigger;
+               goto error_cleanup_buffer_trigger;
        ret = iio_device_register(indio_dev);
        if (ret)
-               goto error_remove_trigger;
+               goto error_cleanup_buffer_trigger;
 
        return 0;
 
-error_remove_trigger:
-       adis16209_remove_trigger(indio_dev);
-error_uninitialize_ring:
-       iio_buffer_unregister(indio_dev);
-error_unreg_ring_funcs:
-       adis16209_unconfigure_ring(indio_dev);
+error_cleanup_buffer_trigger:
+       adis_cleanup_buffer_and_trigger(st, indio_dev);
 error_free_dev:
        iio_device_free(indio_dev);
 error_ret:
@@ -576,11 +227,10 @@ error_ret:
 static int __devexit adis16209_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
+       struct adis *st = iio_priv(indio_dev);
 
        iio_device_unregister(indio_dev);
-       adis16209_remove_trigger(indio_dev);
-       iio_buffer_unregister(indio_dev);
-       adis16209_unconfigure_ring(indio_dev);
+       adis_cleanup_buffer_and_trigger(st, indio_dev);
        iio_device_free(indio_dev);
 
        return 0;
diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c
deleted file mode 100644 (file)
index 6af9a5d..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16209.h"
-
-/**
- * adis16209_read_ring_data() read data registers which will be placed into ring
- * @indio_dev: the IIO device
- * @rx: somewhere to pass back the value read
- **/
-static int adis16209_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-       struct spi_message msg;
-       struct adis16209_state *st = iio_priv(indio_dev);
-       struct spi_transfer xfers[ADIS16209_OUTPUTS + 1];
-       int ret;
-       int i;
-
-       mutex_lock(&st->buf_lock);
-
-       spi_message_init(&msg);
-
-       memset(xfers, 0, sizeof(xfers));
-       for (i = 0; i <= ADIS16209_OUTPUTS; i++) {
-               xfers[i].bits_per_word = 8;
-               xfers[i].cs_change = 1;
-               xfers[i].len = 2;
-               xfers[i].delay_usecs = 30;
-               xfers[i].tx_buf = st->tx + 2 * i;
-               st->tx[2 * i]
-                       = ADIS16209_READ_REG(ADIS16209_SUPPLY_OUT + 2 * i);
-               st->tx[2 * i + 1] = 0;
-               if (i >= 1)
-                       xfers[i].rx_buf = rx + 2 * (i - 1);
-               spi_message_add_tail(&xfers[i], &msg);
-       }
-
-       ret = spi_sync(st->us, &msg);
-       if (ret)
-               dev_err(&st->us->dev, "problem when burst reading");
-
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
- * specific to be rolled into the core.
- */
-static irqreturn_t adis16209_trigger_handler(int irq, void *p)
-{
-       struct iio_poll_func *pf = p;
-       struct iio_dev *indio_dev = pf->indio_dev;
-       struct adis16209_state *st = iio_priv(indio_dev);
-       int i = 0;
-       s16 *data;
-
-       data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-       if (data == NULL) {
-               dev_err(&st->us->dev, "memory alloc failed in ring bh");
-               goto done;
-       }
-
-       if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
-           adis16209_read_ring_data(indio_dev, st->rx) >= 0)
-               for (; i < bitmap_weight(indio_dev->active_scan_mask,
-                                        indio_dev->masklength); i++)
-                       data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-       /* Guaranteed to be aligned with 8 byte boundary */
-       if (indio_dev->scan_timestamp)
-               *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-       iio_push_to_buffers(indio_dev, (u8 *)data);
-
-       kfree(data);
-done:
-       iio_trigger_notify_done(indio_dev->trig);
-
-       return IRQ_HANDLED;
-}
-
-void adis16209_unconfigure_ring(struct iio_dev *indio_dev)
-{
-       iio_dealloc_pollfunc(indio_dev->pollfunc);
-       iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16209_ring_setup_ops = {
-       .preenable = &iio_sw_buffer_preenable,
-       .postenable = &iio_triggered_buffer_postenable,
-       .predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16209_configure_ring(struct iio_dev *indio_dev)
-{
-       int ret = 0;
-       struct iio_buffer *ring;
-
-       ring = iio_sw_rb_allocate(indio_dev);
-       if (!ring) {
-               ret = -ENOMEM;
-               return ret;
-       }
-       indio_dev->buffer = ring;
-       ring->scan_timestamp = true;
-       indio_dev->setup_ops = &adis16209_ring_setup_ops;
-
-       indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-                                                &adis16209_trigger_handler,
-                                                IRQF_ONESHOT,
-                                                indio_dev,
-                                                "%s_consumer%d",
-                                                indio_dev->name,
-                                                indio_dev->id);
-       if (indio_dev->pollfunc == NULL) {
-               ret = -ENOMEM;
-               goto error_iio_sw_rb_free;
-       }
-
-       indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-       return 0;
-
-error_iio_sw_rb_free:
-       iio_sw_rb_free(indio_dev->buffer);
-       return ret;
-}
diff --git a/drivers/staging/iio/accel/adis16209_trigger.c b/drivers/staging/iio/accel/adis16209_trigger.c
deleted file mode 100644 (file)
index 1122803..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16209.h"
-
-/**
- * adis16209_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16209_data_rdy_trigger_set_state(struct iio_trigger *trig,
-                                               bool state)
-{
-       struct iio_dev *indio_dev = trig->private_data;
-
-       dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-       return adis16209_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16209_trigger_ops = {
-       .owner = THIS_MODULE,
-       .set_trigger_state = &adis16209_data_rdy_trigger_set_state,
-};
-
-int adis16209_probe_trigger(struct iio_dev *indio_dev)
-{
-       int ret;
-       struct adis16209_state *st = iio_priv(indio_dev);
-
-       st->trig = iio_trigger_alloc("adis16209-dev%d", indio_dev->id);
-       if (st->trig == NULL) {
-               ret = -ENOMEM;
-               goto error_ret;
-       }
-
-       ret = request_irq(st->us->irq,
-                         iio_trigger_generic_data_rdy_poll,
-                         IRQF_TRIGGER_RISING,
-                         "adis16209",
-                         st->trig);
-       if (ret)
-               goto error_free_trig;
-       st->trig->dev.parent = &st->us->dev;
-       st->trig->ops = &adis16209_trigger_ops;
-       st->trig->private_data = indio_dev;
-       ret = iio_trigger_register(st->trig);
-
-       /* select default trigger */
-       indio_dev->trig = st->trig;
-       if (ret)
-               goto error_free_irq;
-
-       return 0;
-
-error_free_irq:
-       free_irq(st->us->irq, st->trig);
-error_free_trig:
-       iio_trigger_free(st->trig);
-error_ret:
-       return ret;
-}
-
-void adis16209_remove_trigger(struct iio_dev *indio_dev)
-{
-       struct adis16209_state *st = iio_priv(indio_dev);
-
-       iio_trigger_unregister(st->trig);
-       free_irq(st->us->irq, st->trig);
-       iio_trigger_free(st->trig);
-}
index 024313cf5cf0cbbc03a95c97877af26be30ef145..a894ad7fb26dc7d21ad6278969855f9ec19028ad 100644 (file)
@@ -1,10 +1,9 @@
 #ifndef SPI_ADIS16220_H_
 #define SPI_ADIS16220_H_
 
-#define ADIS16220_STARTUP_DELAY        220 /* ms */
+#include <linux/iio/imu/adis.h>
 
-#define ADIS16220_READ_REG(a)    a
-#define ADIS16220_WRITE_REG(a) ((a) | 0x80)
+#define ADIS16220_STARTUP_DELAY        220 /* ms */
 
 /* Flash memory write count */
 #define ADIS16220_FLASH_CNT     0x00
 #define ADIS16220_DIAG_STAT_FLASH_CHK  (1<<6)
 #define ADIS16220_DIAG_STAT_SELF_TEST  (1<<5)
 /* Capture period violation/interruption */
-#define ADIS16220_DIAG_STAT_VIOLATION  (1<<4)
+#define ADIS16220_DIAG_STAT_VIOLATION_BIT      4
 /* SPI communications failure */
-#define ADIS16220_DIAG_STAT_SPI_FAIL   (1<<3)
+#define ADIS16220_DIAG_STAT_SPI_FAIL_BIT       3
 /* Flash update failure */
-#define ADIS16220_DIAG_STAT_FLASH_UPT  (1<<2)
+#define ADIS16220_DIAG_STAT_FLASH_UPT_BIT      2
 /* Power supply above 3.625 V */
-#define ADIS16220_DIAG_STAT_POWER_HIGH (1<<1)
+#define ADIS16220_DIAG_STAT_POWER_HIGH_BIT     1
 /* Power supply below 3.15 V */
-#define ADIS16220_DIAG_STAT_POWER_LOW  (1<<0)
+#define ADIS16220_DIAG_STAT_POWER_LOW_BIT      0
 
 /* GLOB_CMD */
 #define ADIS16220_GLOB_CMD_SW_RESET    (1<<7)
 
 /**
  * struct adis16220_state - device instance specific data
- * @us:                        actual spi_device
+ * @adis:              adis device
  * @tx:                        transmit buffer
  * @rx:                        receive buffer
  * @buf_lock:          mutex to protect tx and rx
  **/
 struct adis16220_state {
-       struct spi_device       *us;
+       struct adis adis;
+
        struct mutex            buf_lock;
        u8                      tx[ADIS16220_MAX_TX] ____cacheline_aligned;
        u8                      rx[ADIS16220_MAX_RX];
index 22807ac8e8f88892fbe2a196e3b7af4f8aaabc3e..c39ce622eb62ba69b2c777d48cd59731411d93b8 100644 (file)
 
 #include "adis16220.h"
 
-/**
- * adis16220_spi_write_reg_8() - write single byte to a register
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-static int adis16220_spi_write_reg_8(struct iio_dev *indio_dev,
-               u8 reg_address,
-               u8 val)
-{
-       int ret;
-       struct adis16220_state *st = iio_priv(indio_dev);
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16220_WRITE_REG(reg_address);
-       st->tx[1] = val;
-
-       ret = spi_write(st->us, st->tx, 2);
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/**
- * adis16220_spi_write_reg_16() - write 2 bytes to a pair of registers
- * @indio_dev:  iio device associated with child of actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: value to be written
- **/
-static int adis16220_spi_write_reg_16(struct iio_dev *indio_dev,
-               u8 lower_reg_address,
-               u16 value)
-{
-       int ret;
-       struct spi_message msg;
-       struct adis16220_state *st = iio_priv(indio_dev);
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = st->tx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-                       .delay_usecs = 35,
-               }, {
-                       .tx_buf = st->tx + 2,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .delay_usecs = 35,
-               },
-       };
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16220_WRITE_REG(lower_reg_address);
-       st->tx[1] = value & 0xFF;
-       st->tx[2] = ADIS16220_WRITE_REG(lower_reg_address + 1);
-       st->tx[3] = (value >> 8) & 0xFF;
-
-       spi_message_init(&msg);
-       spi_message_add_tail(&xfers[0], &msg);
-       spi_message_add_tail(&xfers[1], &msg);
-       ret = spi_sync(st->us, &msg);
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/**
- * adis16220_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int adis16220_spi_read_reg_16(struct iio_dev *indio_dev,
-                                    u8 lower_reg_address,
-                                    u16 *val)
-{
-       struct spi_message msg;
-       struct adis16220_state *st = iio_priv(indio_dev);
-       int ret;
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = st->tx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-                       .delay_usecs = 35,
-               }, {
-                       .rx_buf = st->rx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-                       .delay_usecs = 35,
-               },
-       };
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16220_READ_REG(lower_reg_address);
-       st->tx[1] = 0;
-
-       spi_message_init(&msg);
-       spi_message_add_tail(&xfers[0], &msg);
-       spi_message_add_tail(&xfers[1], &msg);
-       ret = spi_sync(st->us, &msg);
-       if (ret) {
-               dev_err(&st->us->dev,
-                       "problem when reading 16 bit register 0x%02X",
-                       lower_reg_address);
-               goto error_ret;
-       }
-       *val = (st->rx[0] << 8) | st->rx[1];
-
-error_ret:
-       mutex_unlock(&st->buf_lock);
-       return ret;
-}
-
 static ssize_t adis16220_read_16bit(struct device *dev,
                struct device_attribute *attr,
                char *buf)
 {
        struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct adis16220_state *st = iio_priv(indio_dev);
        ssize_t ret;
        s16 val = 0;
 
        /* Take the iio_dev status lock */
        mutex_lock(&indio_dev->mlock);
-       ret = adis16220_spi_read_reg_16(indio_dev, this_attr->address,
+       ret = adis_read_reg_16(&st->adis, this_attr->address,
                                        (u16 *)&val);
        mutex_unlock(&indio_dev->mlock);
        if (ret)
@@ -164,13 +47,14 @@ static ssize_t adis16220_write_16bit(struct device *dev,
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+       struct adis16220_state *st = iio_priv(indio_dev);
        int ret;
        u16 val;
 
        ret = kstrtou16(buf, 10, &val);
        if (ret)
                goto error_ret;
-       ret = adis16220_spi_write_reg_16(indio_dev, this_attr->address, val);
+       ret = adis_write_reg_16(&st->adis, this_attr->address, val);
 
 error_ret:
        return ret ? ret : len;
@@ -178,10 +62,11 @@ error_ret:
 
 static int adis16220_capture(struct iio_dev *indio_dev)
 {
+       struct adis16220_state *st = iio_priv(indio_dev);
        int ret;
-       ret = adis16220_spi_write_reg_16(indio_dev,
-                       ADIS16220_GLOB_CMD,
-                       0xBF08); /* initiates a manual data capture */
+
+        /* initiates a manual data capture */
+       ret = adis_write_reg_16(&st->adis, ADIS16220_GLOB_CMD, 0xBF08);
        if (ret)
                dev_err(&indio_dev->dev, "problem beginning capture");
 
@@ -190,18 +75,6 @@ static int adis16220_capture(struct iio_dev *indio_dev)
        return ret;
 }
 
-static int adis16220_reset(struct iio_dev *indio_dev)
-{
-       int ret;
-       ret = adis16220_spi_write_reg_8(indio_dev,
-                       ADIS16220_GLOB_CMD,
-                       ADIS16220_GLOB_CMD_SW_RESET);
-       if (ret)
-               dev_err(&indio_dev->dev, "problem resetting device");
-
-       return ret;
-}
-
 static ssize_t adis16220_write_capture(struct device *dev,
                struct device_attribute *attr,
                const char *buf, size_t len)
@@ -222,81 +95,6 @@ static ssize_t adis16220_write_capture(struct device *dev,
        return len;
 }
 
-static int adis16220_check_status(struct iio_dev *indio_dev)
-{
-       u16 status;
-       int ret;
-
-       ret = adis16220_spi_read_reg_16(indio_dev, ADIS16220_DIAG_STAT,
-                                       &status);
-
-       if (ret < 0) {
-               dev_err(&indio_dev->dev, "Reading status failed\n");
-               goto error_ret;
-       }
-       ret = status & 0x7F;
-
-       if (status & ADIS16220_DIAG_STAT_VIOLATION)
-               dev_err(&indio_dev->dev,
-                       "Capture period violation/interruption\n");
-       if (status & ADIS16220_DIAG_STAT_SPI_FAIL)
-               dev_err(&indio_dev->dev, "SPI failure\n");
-       if (status & ADIS16220_DIAG_STAT_FLASH_UPT)
-               dev_err(&indio_dev->dev, "Flash update failed\n");
-       if (status & ADIS16220_DIAG_STAT_POWER_HIGH)
-               dev_err(&indio_dev->dev, "Power supply above 3.625V\n");
-       if (status & ADIS16220_DIAG_STAT_POWER_LOW)
-               dev_err(&indio_dev->dev, "Power supply below 3.15V\n");
-
-error_ret:
-       return ret;
-}
-
-static int adis16220_self_test(struct iio_dev *indio_dev)
-{
-       int ret;
-       ret = adis16220_spi_write_reg_16(indio_dev,
-                       ADIS16220_MSC_CTRL,
-                       ADIS16220_MSC_CTRL_SELF_TEST_EN);
-       if (ret) {
-               dev_err(&indio_dev->dev, "problem starting self test");
-               goto err_ret;
-       }
-
-       adis16220_check_status(indio_dev);
-
-err_ret:
-       return ret;
-}
-
-static int adis16220_initial_setup(struct iio_dev *indio_dev)
-{
-       int ret;
-
-       /* Do self test */
-       ret = adis16220_self_test(indio_dev);
-       if (ret) {
-               dev_err(&indio_dev->dev, "self test failure");
-               goto err_ret;
-       }
-
-       /* Read status register to check the result */
-       ret = adis16220_check_status(indio_dev);
-       if (ret) {
-               adis16220_reset(indio_dev);
-               dev_err(&indio_dev->dev, "device not playing ball -> reset");
-               msleep(ADIS16220_STARTUP_DELAY);
-               ret = adis16220_check_status(indio_dev);
-               if (ret) {
-                       dev_err(&indio_dev->dev, "giving up");
-                       goto err_ret;
-               }
-       }
-
-err_ret:
-       return ret;
-}
-
 static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
                                        char *buf,
                                        loff_t off,
@@ -333,7 +131,7 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
                count = ADIS16220_CAPTURE_SIZE - off;
 
        /* write the begin position of capture buffer */
-       ret = adis16220_spi_write_reg_16(indio_dev,
+       ret = adis_write_reg_16(&st->adis,
                                        ADIS16220_CAPT_PNTR,
                                        off > 1);
        if (ret)
@@ -342,8 +140,9 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
        /* read count/2 values from capture buffer */
        mutex_lock(&st->buf_lock);
 
+
        for (i = 0; i < count; i += 2) {
-               st->tx[i] = ADIS16220_READ_REG(addr);
+               st->tx[i] = ADIS_READ_REG(addr);
                st->tx[i + 1] = 0;
        }
        xfers[1].len = count;
@@ -351,7 +150,7 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
        spi_message_init(&msg);
        spi_message_add_tail(&xfers[0], &msg);
        spi_message_add_tail(&xfers[1], &msg);
-       ret = spi_sync(st->us, &msg);
+       ret = spi_sync(st->adis.spi, &msg);
        if (ret) {
 
                mutex_unlock(&st->buf_lock);
@@ -472,6 +271,8 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
                              int *val, int *val2,
                              long mask)
 {
+       struct adis16220_state *st = iio_priv(indio_dev);
+       const struct adis16220_address_spec *addr;
        int ret = -EINVAL;
        int addrind = 0;
        u16 uval;
@@ -516,28 +317,21 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
        default:
                return -EINVAL;
        }
-       if (adis16220_addresses[chan->address][addrind].sign) {
-               ret = adis16220_spi_read_reg_16(indio_dev,
-                                               adis16220_addresses[chan
-                                                                   ->address]
-                                               [addrind].addr,
-                                               &sval);
+       addr = &adis16220_addresses[chan->address][addrind];
+       if (addr->sign) {
+               ret = adis_read_reg_16(&st->adis, addr->addr, &sval);
                if (ret)
                        return ret;
-               bits = adis16220_addresses[chan->address][addrind].bits;
+               bits = addr->bits;
                sval &= (1 << bits) - 1;
                sval = (s16)(sval << (16 - bits)) >> (16 - bits);
                *val = sval;
                return IIO_VAL_INT;
        } else {
-               ret = adis16220_spi_read_reg_16(indio_dev,
-                                               adis16220_addresses[chan
-                                                                   ->address]
-                                               [addrind].addr,
-                                               &uval);
+               ret = adis_read_reg_16(&st->adis, addr->addr, &uval);
                if (ret)
                        return ret;
-               bits = adis16220_addresses[chan->address][addrind].bits;
+               bits = addr->bits;
                uval &= (1 << bits) - 1;
                *val = uval;
                return IIO_VAL_INT;
@@ -601,6 +395,32 @@ static const struct iio_info adis16220_info = {
        .read_raw = &adis16220_read_raw,
 };
 
+static const char * const adis16220_status_error_msgs[] = {
+       [ADIS16220_DIAG_STAT_VIOLATION_BIT] = "Capture period violation/interruption",
+       [ADIS16220_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
+       [ADIS16220_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
+       [ADIS16220_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
+       [ADIS16220_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V",
+};
+
+static const struct adis_data adis16220_data = {
+       .read_delay = 35,
+       .write_delay = 35,
+       .msc_ctrl_reg = ADIS16220_MSC_CTRL,
+       .glob_cmd_reg = ADIS16220_GLOB_CMD,
+       .diag_stat_reg = ADIS16220_DIAG_STAT,
+
+       .self_test_mask = ADIS16220_MSC_CTRL_SELF_TEST_EN,
+       .startup_delay = ADIS16220_STARTUP_DELAY,
+
+       .status_error_msgs = adis16220_status_error_msgs,
+       .status_error_mask = BIT(ADIS16220_DIAG_STAT_VIOLATION_BIT) |
+               BIT(ADIS16220_DIAG_STAT_SPI_FAIL_BIT) |
+               BIT(ADIS16220_DIAG_STAT_FLASH_UPT_BIT) |
+               BIT(ADIS16220_DIAG_STAT_POWER_HIGH_BIT) |
+               BIT(ADIS16220_DIAG_STAT_POWER_LOW_BIT),
+};
+
 static int __devinit adis16220_probe(struct spi_device *spi)
 {
        int ret;
@@ -618,9 +438,6 @@ static int __devinit adis16220_probe(struct spi_device *spi)
        /* this is only used for removal purposes */
        spi_set_drvdata(spi, indio_dev);
 
-       st->us = spi;
-       mutex_init(&st->buf_lock);
-
        indio_dev->name = spi->dev.driver->name;
        indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &adis16220_info;
@@ -644,8 +461,11 @@ static int __devinit adis16220_probe(struct spi_device *spi)
        if (ret)
                goto error_rm_adc1_bin;
 
+       ret = adis_init(&st->adis, indio_dev, spi, &adis16220_data);
+       if (ret)
+               goto error_rm_adc2_bin;
        /* Get the device into a sane initial state */
-       ret = adis16220_initial_setup(indio_dev);
+       ret = adis_initial_startup(&st->adis);
        if (ret)
                goto error_rm_adc2_bin;
        return 0;
index 3fabcc0b3471ea7fe415936a6137f3ac965dcd92..d442d49f51f4a5a1280a3b5d66eb5cb5aa19c8be 100644 (file)
@@ -3,9 +3,6 @@
 
 #define ADIS16240_STARTUP_DELAY        220 /* ms */
 
-#define ADIS16240_READ_REG(a)    a
-#define ADIS16240_WRITE_REG(a) ((a) | 0x80)
-
 /* Flash memory write count */
 #define ADIS16240_FLASH_CNT      0x00
 /* Output, power supply */
@@ -75,8 +72,6 @@
 /* System command */
 #define ADIS16240_GLOB_CMD       0x4A
 
-#define ADIS16240_OUTPUTS        6
-
 /* MSC_CTRL */
 /* Enables sum-of-squares output (XYZPEAK_OUT) */
 #define ADIS16240_MSC_CTRL_XYZPEAK_OUT_EN      (1 << 15)
 /* Flash test, checksum flag: 1 = mismatch, 0 = match */
 #define ADIS16240_DIAG_STAT_CHKSUM      (1<<6)
 /* Power-on, self-test flag: 1 = failure, 0 = pass */
-#define ADIS16240_DIAG_STAT_PWRON_FAIL  (1<<5)
+#define ADIS16240_DIAG_STAT_PWRON_FAIL_BIT  5
 /* Power-on self-test: 1 = in-progress, 0 = complete */
 #define ADIS16240_DIAG_STAT_PWRON_BUSY  (1<<4)
 /* SPI communications failure */
-#define ADIS16240_DIAG_STAT_SPI_FAIL   (1<<3)
+#define ADIS16240_DIAG_STAT_SPI_FAIL_BIT       3
 /* Flash update failure */
-#define ADIS16240_DIAG_STAT_FLASH_UPT  (1<<2)
+#define ADIS16240_DIAG_STAT_FLASH_UPT_BIT      2
 /* Power supply above 3.625 V */
-#define ADIS16240_DIAG_STAT_POWER_HIGH (1<<1)
+#define ADIS16240_DIAG_STAT_POWER_HIGH_BIT     1
  /* Power supply below 3.15 V */
-#define ADIS16240_DIAG_STAT_POWER_LOW  (1<<0)
+#define ADIS16240_DIAG_STAT_POWER_LOW_BIT      0
 
 /* GLOB_CMD */
 #define ADIS16240_GLOB_CMD_RESUME      (1<<8)
 
 #define ADIS16240_ERROR_ACTIVE          (1<<14)
 
-#define ADIS16240_MAX_TX 24
-#define ADIS16240_MAX_RX 24
-
-/**
- * struct adis16240_state - device instance specific data
- * @us:                        actual spi_device
- * @trig:              data ready trigger registered with iio
- * @tx:                        transmit buffer
- * @rx:                        receive buffer
- * @buf_lock:          mutex to protect tx and rx
- **/
-struct adis16240_state {
-       struct spi_device       *us;
-       struct iio_trigger      *trig;
-       struct mutex            buf_lock;
-       u8                      tx[ADIS16240_MAX_TX] ____cacheline_aligned;
-       u8                      rx[ADIS16240_MAX_RX];
-};
-
-int adis16240_set_irq(struct iio_dev *indio_dev, bool enable);
-
 /* At the moment triggers are only used for ring buffer
  * filling. This may change!
  */
 
-#define ADIS16240_SCAN_SUPPLY  0
-#define ADIS16240_SCAN_ACC_X   1
-#define ADIS16240_SCAN_ACC_Y   2
-#define ADIS16240_SCAN_ACC_Z   3
+#define ADIS16240_SCAN_ACC_X   0
+#define ADIS16240_SCAN_ACC_Y   1
+#define ADIS16240_SCAN_ACC_Z   2
+#define ADIS16240_SCAN_SUPPLY  3
 #define ADIS16240_SCAN_AUX_ADC 4
 #define ADIS16240_SCAN_TEMP    5
 
-#ifdef CONFIG_IIO_BUFFER
-void adis16240_remove_trigger(struct iio_dev *indio_dev);
-int adis16240_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16240_read_data_from_ring(struct device *dev,
-                                     struct device_attribute *attr,
-                                     char *buf);
-
-
-int adis16240_configure_ring(struct iio_dev *indio_dev);
-void adis16240_unconfigure_ring(struct iio_dev *indio_dev);
-
-#else /* CONFIG_IIO_BUFFER */
-
-static inline void adis16240_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16240_probe_trigger(struct iio_dev *indio_dev)
-{
-       return 0;
-}
-
-static inline ssize_t
-adis16240_read_data_from_ring(struct device *dev,
-                             struct device_attribute *attr,
-                             char *buf)
-{
-       return 0;
-}
-
-static int adis16240_configure_ring(struct iio_dev *indio_dev)
-{
-       return 0;
-}
-
-static inline void adis16240_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-#endif /* CONFIG_IIO_BUFFER */
 #endif /* SPI_ADIS16240_H_ */
index 289f81963c82d00a8a5ca223e2b71465082d8a91..d098b49cc18b99ecc163486b871e14d94097ca32 100644 (file)
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
 
 #include "adis16240.h"
 
-static int adis16240_check_status(struct iio_dev *indio_dev);
-
-/**
- * adis16240_spi_write_reg_8() - write single byte to a register
- * @indio_dev: iio_dev associated with device
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-static int adis16240_spi_write_reg_8(struct iio_dev *indio_dev,
-                                    u8 reg_address,
-                                    u8 val)
-{
-       int ret;
-       struct adis16240_state *st = iio_priv(indio_dev);
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16240_WRITE_REG(reg_address);
-       st->tx[1] = val;
-
-       ret = spi_write(st->us, st->tx, 2);
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/**
- * adis16240_spi_write_reg_16() - write 2 bytes to a pair of registers
- * @indio_dev: iio_dev for this device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: value to be written
- **/
-static int adis16240_spi_write_reg_16(struct iio_dev *indio_dev,
-                                     u8 lower_reg_address,
-                                     u16 value)
-{
-       int ret;
-       struct spi_message msg;
-       struct adis16240_state *st = iio_priv(indio_dev);
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = st->tx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-                       .delay_usecs = 35,
-               }, {
-                       .tx_buf = st->tx + 2,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .delay_usecs = 35,
-               },
-       };
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16240_WRITE_REG(lower_reg_address);
-       st->tx[1] = value & 0xFF;
-       st->tx[2] = ADIS16240_WRITE_REG(lower_reg_address + 1);
-       st->tx[3] = (value >> 8) & 0xFF;
-
-       spi_message_init(&msg);
-       spi_message_add_tail(&xfers[0], &msg);
-       spi_message_add_tail(&xfers[1], &msg);
-       ret = spi_sync(st->us, &msg);
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/**
- * adis16240_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @indio_dev: iio_dev for this device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int adis16240_spi_read_reg_16(struct iio_dev *indio_dev,
-               u8 lower_reg_address,
-               u16 *val)
-{
-       struct spi_message msg;
-       struct adis16240_state *st = iio_priv(indio_dev);
-       int ret;
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = st->tx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-                       .delay_usecs = 35,
-               }, {
-                       .rx_buf = st->rx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-                       .delay_usecs = 35,
-               },
-       };
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16240_READ_REG(lower_reg_address);
-       st->tx[1] = 0;
-       st->tx[2] = 0;
-       st->tx[3] = 0;
-
-       spi_message_init(&msg);
-       spi_message_add_tail(&xfers[0], &msg);
-       spi_message_add_tail(&xfers[1], &msg);
-       ret = spi_sync(st->us, &msg);
-       if (ret) {
-               dev_err(&st->us->dev,
-                       "problem when reading 16 bit register 0x%02X",
-                       lower_reg_address);
-               goto error_ret;
-       }
-       *val = (st->rx[0] << 8) | st->rx[1];
-
-error_ret:
-       mutex_unlock(&st->buf_lock);
-       return ret;
-}
-
 static ssize_t adis16240_spi_read_signed(struct device *dev,
                struct device_attribute *attr,
                char *buf,
                unsigned bits)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct adis *st = iio_priv(indio_dev);
        int ret;
        s16 val = 0;
        unsigned shift = 16 - bits;
        struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
-       ret = adis16240_spi_read_reg_16(indio_dev,
+       ret = adis_read_reg_16(st,
                                        this_attr->address, (u16 *)&val);
        if (ret)
                return ret;
 
        if (val & ADIS16240_ERROR_ACTIVE)
-               adis16240_check_status(indio_dev);
+               adis_check_status(st);
 
        val = ((s16)(val << shift) >> shift);
        return sprintf(buf, "%d\n", val);
@@ -185,152 +65,16 @@ static ssize_t adis16240_read_12bit_signed(struct device *dev,
        return ret;
 }
 
-static int adis16240_reset(struct iio_dev *indio_dev)
-{
-       int ret;
-       ret = adis16240_spi_write_reg_8(indio_dev,
-                       ADIS16240_GLOB_CMD,
-                       ADIS16240_GLOB_CMD_SW_RESET);
-       if (ret)
-               dev_err(&indio_dev->dev, "problem resetting device");
-
-       return ret;
-}
-
-int adis16240_set_irq(struct iio_dev *indio_dev, bool enable)
-{
-       int ret = 0;
-       u16 msc;
-
-       ret = adis16240_spi_read_reg_16(indio_dev,
-                                       ADIS16240_MSC_CTRL, &msc);
-       if (ret)
-               goto error_ret;
-
-       msc |= ADIS16240_MSC_CTRL_ACTIVE_HIGH;
-       msc &= ~ADIS16240_MSC_CTRL_DATA_RDY_DIO2;
-       if (enable)
-               msc |= ADIS16240_MSC_CTRL_DATA_RDY_EN;
-       else
-               msc &= ~ADIS16240_MSC_CTRL_DATA_RDY_EN;
-
-       ret = adis16240_spi_write_reg_16(indio_dev,
-                                        ADIS16240_MSC_CTRL, msc);
-
-error_ret:
-       return ret;
-}
-
-static int adis16240_self_test(struct iio_dev *indio_dev)
-{
-       int ret;
-       ret = adis16240_spi_write_reg_16(indio_dev,
-                       ADIS16240_MSC_CTRL,
-                       ADIS16240_MSC_CTRL_SELF_TEST_EN);
-       if (ret) {
-               dev_err(&indio_dev->dev, "problem starting self test");
-               goto err_ret;
-       }
-
-       msleep(ADIS16240_STARTUP_DELAY);
-
-       adis16240_check_status(indio_dev);
-
-err_ret:
-       return ret;
-}
-
-static int adis16240_check_status(struct iio_dev *indio_dev)
-{
-       u16 status;
-       int ret;
-       struct device *dev = &indio_dev->dev;
-
-       ret = adis16240_spi_read_reg_16(indio_dev,
-                                       ADIS16240_DIAG_STAT, &status);
-
-       if (ret < 0) {
-               dev_err(dev, "Reading status failed\n");
-               goto error_ret;
-       }
-
-       ret = status & 0x2F;
-       if (status & ADIS16240_DIAG_STAT_PWRON_FAIL)
-               dev_err(dev, "Power-on, self-test fail\n");
-       if (status & ADIS16240_DIAG_STAT_SPI_FAIL)
-               dev_err(dev, "SPI failure\n");
-       if (status & ADIS16240_DIAG_STAT_FLASH_UPT)
-               dev_err(dev, "Flash update failed\n");
-       if (status & ADIS16240_DIAG_STAT_POWER_HIGH)
-               dev_err(dev, "Power supply above 3.625V\n");
-       if (status & ADIS16240_DIAG_STAT_POWER_LOW)
-               dev_err(dev, "Power supply below 2.225V\n");
-
-error_ret:
-       return ret;
-}
-
-static int adis16240_initial_setup(struct iio_dev *indio_dev)
-{
-       int ret;
-       struct device *dev = &indio_dev->dev;
-
-       /* Disable IRQ */
-       ret = adis16240_set_irq(indio_dev, false);
-       if (ret) {
-               dev_err(dev, "disable irq failed");
-               goto err_ret;
-       }
-
-       /* Do self test */
-       ret = adis16240_self_test(indio_dev);
-       if (ret) {
-               dev_err(dev, "self test failure");
-               goto err_ret;
-       }
-
-       /* Read status register to check the result */
-       ret = adis16240_check_status(indio_dev);
-       if (ret) {
-               adis16240_reset(indio_dev);
-               dev_err(dev, "device not playing ball -> reset");
-               msleep(ADIS16240_STARTUP_DELAY);
-               ret = adis16240_check_status(indio_dev);
-               if (ret) {
-                       dev_err(dev, "giving up");
-                       goto err_ret;
-               }
-       }
-
-err_ret:
-       return ret;
-}
-
 static IIO_DEVICE_ATTR(in_accel_xyz_squared_peak_raw, S_IRUGO,
                       adis16240_read_12bit_signed, NULL,
                       ADIS16240_XYZPEAK_OUT);
 
 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("4096");
 
-enum adis16240_chan {
-       in_supply,
-       in_aux,
-       accel_x,
-       accel_y,
-       accel_z,
-       temp,
-};
-
-static const u8 adis16240_addresses[6][3] = {
-       [in_supply] = { ADIS16240_SUPPLY_OUT },
-       [in_aux] = { ADIS16240_AUX_ADC },
-       [accel_x] = { ADIS16240_XACCL_OUT, ADIS16240_XACCL_OFF,
-                     ADIS16240_XPEAK_OUT },
-       [accel_y] = { ADIS16240_YACCL_OUT, ADIS16240_YACCL_OFF,
-                     ADIS16240_YPEAK_OUT },
-       [accel_z] = { ADIS16240_ZACCL_OUT, ADIS16240_ZACCL_OFF,
-                     ADIS16240_ZPEAK_OUT },
-       [temp] = { ADIS16240_TEMP_OUT },
+static const u8 adis16240_addresses[][2] = {
+       [ADIS16240_SCAN_ACC_X] = { ADIS16240_XACCL_OFF, ADIS16240_XPEAK_OUT },
+       [ADIS16240_SCAN_ACC_Y] = { ADIS16240_YACCL_OFF, ADIS16240_YPEAK_OUT },
+       [ADIS16240_SCAN_ACC_Z] = { ADIS16240_ZACCL_OFF, ADIS16240_ZPEAK_OUT },
 };
 
 static int adis16240_read_raw(struct iio_dev *indio_dev,
@@ -338,6 +82,7 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
                              int *val, int *val2,
                              long mask)
 {
+       struct adis *st = iio_priv(indio_dev);
        int ret;
        int bits;
        u8 addr;
@@ -345,29 +90,8 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               mutex_lock(&indio_dev->mlock);
-               addr = adis16240_addresses[chan->address][0];
-               ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16);
-               if (ret) {
-                       mutex_unlock(&indio_dev->mlock);
-                       return ret;
-               }
-
-               if (val16 & ADIS16240_ERROR_ACTIVE) {
-                       ret = adis16240_check_status(indio_dev);
-                       if (ret) {
-                               mutex_unlock(&indio_dev->mlock);
-                               return ret;
-                       }
-               }
-               val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
-               if (chan->scan_type.sign == 's')
-                       val16 = (s16)(val16 <<
-                                     (16 - chan->scan_type.realbits)) >>
-                               (16 - chan->scan_type.realbits);
-               *val = val16;
-               mutex_unlock(&indio_dev->mlock);
-               return IIO_VAL_INT;
+               return adis_single_conversion(indio_dev, chan,
+                               ADIS16240_ERROR_ACTIVE, val);
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
@@ -400,8 +124,8 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_CALIBBIAS:
                bits = 10;
                mutex_lock(&indio_dev->mlock);
-               addr = adis16240_addresses[chan->address][1];
-               ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16);
+               addr = adis16240_addresses[chan->scan_index][0];
+               ret = adis_read_reg_16(st, addr, &val16);
                if (ret) {
                        mutex_unlock(&indio_dev->mlock);
                        return ret;
@@ -414,8 +138,8 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_PEAK:
                bits = 10;
                mutex_lock(&indio_dev->mlock);
-               addr = adis16240_addresses[chan->address][2];
-               ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16);
+               addr = adis16240_addresses[chan->scan_index][1];
+               ret = adis_read_reg_16(st, addr, &val16);
                if (ret) {
                        mutex_unlock(&indio_dev->mlock);
                        return ret;
@@ -435,104 +159,32 @@ static int adis16240_write_raw(struct iio_dev *indio_dev,
                               int val2,
                               long mask)
 {
+       struct adis *st = iio_priv(indio_dev);
        int bits = 10;
        s16 val16;
        u8 addr;
        switch (mask) {
        case IIO_CHAN_INFO_CALIBBIAS:
                val16 = val & ((1 << bits) - 1);
-               addr = adis16240_addresses[chan->address][1];
-               return adis16240_spi_write_reg_16(indio_dev, addr, val16);
+               addr = adis16240_addresses[chan->scan_index][0];
+               return adis_write_reg_16(st, addr, val16);
        }
        return -EINVAL;
 }
 
 static const struct iio_chan_spec adis16240_channels[] = {
-       {
-               .type = IIO_VOLTAGE,
-               .indexed = 1,
-               .channel = 0,
-               .extend_name = "supply",
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-               .address = in_supply,
-               .scan_index = ADIS16240_SCAN_SUPPLY,
-               .scan_type = {
-                       .sign = 'u',
-                       .realbits = 10,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_VOLTAGE,
-               .indexed = 1,
-               .channel = 1,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-               .address = in_aux,
-               .scan_index = ADIS16240_SCAN_AUX_ADC,
-               .scan_type = {
-                       .sign = 'u',
-                       .realbits = 10,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_ACCEL,
-               .modified = 1,
-               .channel2 = IIO_MOD_X,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SHARED_BIT |
+       ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 10),
+       ADIS_AUX_ADC_CHAN(ADIS16240_AUX_ADC, ADIS16240_SCAN_AUX_ADC, 10),
+       ADIS_ACCEL_CHAN(X, ADIS16240_XACCL_OUT, ADIS16240_SCAN_ACC_X,
                IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-               IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
-               .address = accel_x,
-               .scan_index = ADIS16240_SCAN_ACC_X,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 10,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_ACCEL,
-               .modified = 1,
-               .channel2 = IIO_MOD_Y,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SHARED_BIT |
+               IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 10),
+       ADIS_ACCEL_CHAN(Y, ADIS16240_YACCL_OUT, ADIS16240_SCAN_ACC_Y,
                IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-               IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
-               .address = accel_y,
-               .scan_index = ADIS16240_SCAN_ACC_Y,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 10,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_ACCEL,
-               .modified = 1,
-               .channel2 = IIO_MOD_Z,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SHARED_BIT |
+               IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 10),
+       ADIS_ACCEL_CHAN(Z, ADIS16240_ZACCL_OUT, ADIS16240_SCAN_ACC_Z,
                IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-               IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
-               .address = accel_z,
-               .scan_index = ADIS16240_SCAN_ACC_Z,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 10,
-                       .storagebits = 16,
-               },
-       }, {
-               .type = IIO_TEMP,
-               .indexed = 1,
-               .channel = 0,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-               .address = temp,
-               .scan_index = ADIS16240_SCAN_TEMP,
-               .scan_type = {
-                       .sign = 'u',
-                       .realbits = 10,
-                       .storagebits = 16,
-               },
-       },
+               IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 10),
+       ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 10),
        IIO_CHAN_SOFT_TIMESTAMP(6)
 };
 
@@ -550,13 +202,40 @@ static const struct iio_info adis16240_info = {
        .attrs = &adis16240_attribute_group,
        .read_raw = &adis16240_read_raw,
        .write_raw = &adis16240_write_raw,
+       .update_scan_mode = adis_update_scan_mode,
        .driver_module = THIS_MODULE,
 };
 
+static const char * const adis16240_status_error_msgs[] = {
+       [ADIS16240_DIAG_STAT_PWRON_FAIL_BIT] = "Power on, self-test failed",
+       [ADIS16240_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
+       [ADIS16240_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
+       [ADIS16240_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
+       [ADIS16240_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.225V",
+};
+
+static const struct adis_data adis16240_data = {
+       .write_delay = 35,
+       .read_delay = 35,
+       .msc_ctrl_reg = ADIS16240_MSC_CTRL,
+       .glob_cmd_reg = ADIS16240_GLOB_CMD,
+       .diag_stat_reg = ADIS16240_DIAG_STAT,
+
+       .self_test_mask = ADIS16240_MSC_CTRL_SELF_TEST_EN,
+       .startup_delay = ADIS16240_STARTUP_DELAY,
+
+       .status_error_msgs = adis16240_status_error_msgs,
+       .status_error_mask = BIT(ADIS16240_DIAG_STAT_PWRON_FAIL_BIT) |
+               BIT(ADIS16240_DIAG_STAT_SPI_FAIL_BIT) |
+               BIT(ADIS16240_DIAG_STAT_FLASH_UPT_BIT) |
+               BIT(ADIS16240_DIAG_STAT_POWER_HIGH_BIT) |
+               BIT(ADIS16240_DIAG_STAT_POWER_LOW_BIT),
+};
+
 static int __devinit adis16240_probe(struct spi_device *spi)
 {
        int ret;
-       struct adis16240_state *st;
+       struct adis *st;
        struct iio_dev *indio_dev;
 
        /* setup the industrialio driver allocated elements */
@@ -569,9 +248,6 @@ static int __devinit adis16240_probe(struct spi_device *spi)
        /* this is only used for removal purposes */
        spi_set_drvdata(spi, indio_dev);
 
-       st->us = spi;
-       mutex_init(&st->buf_lock);
-
        indio_dev->name = spi->dev.driver->name;
        indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &adis16240_info;
@@ -579,39 +255,24 @@ static int __devinit adis16240_probe(struct spi_device *spi)
        indio_dev->num_channels = ARRAY_SIZE(adis16240_channels);
        indio_dev->modes = INDIO_DIRECT_MODE;
 
-       ret = adis16240_configure_ring(indio_dev);
+       ret = adis_init(st, indio_dev, spi, &adis16240_data);
+       if (ret)
+               goto error_free_dev;
+       ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL);
        if (ret)
                goto error_free_dev;
-
-       ret = iio_buffer_register(indio_dev,
-                                 adis16240_channels,
-                                 ARRAY_SIZE(adis16240_channels));
-       if (ret) {
-               printk(KERN_ERR "failed to initialize the ring\n");
-               goto error_unreg_ring_funcs;
-       }
-
-       if (spi->irq) {
-               ret = adis16240_probe_trigger(indio_dev);
-               if (ret)
-                       goto error_uninitialize_ring;
-       }
 
        /* Get the device into a sane initial state */
-       ret = adis16240_initial_setup(indio_dev);
+       ret = adis_initial_startup(st);
        if (ret)
-               goto error_remove_trigger;
+               goto error_cleanup_buffer_trigger;
        ret = iio_device_register(indio_dev);
        if (ret)
-               goto error_remove_trigger;
+               goto error_cleanup_buffer_trigger;
        return 0;
 
-error_remove_trigger:
-       adis16240_remove_trigger(indio_dev);
-error_uninitialize_ring:
-       iio_buffer_unregister(indio_dev);
-error_unreg_ring_funcs:
-       adis16240_unconfigure_ring(indio_dev);
+error_cleanup_buffer_trigger:
+       adis_cleanup_buffer_and_trigger(st, indio_dev);
 error_free_dev:
        iio_device_free(indio_dev);
 error_ret:
@@ -620,13 +281,11 @@ error_ret:
 
 static int __devexit adis16240_remove(struct spi_device *spi)
 {
-
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
+       struct adis *st = iio_priv(indio_dev);
 
        iio_device_unregister(indio_dev);
-       adis16240_remove_trigger(indio_dev);
-       iio_buffer_unregister(indio_dev);
-       adis16240_unconfigure_ring(indio_dev);
+       adis_cleanup_buffer_and_trigger(st, indio_dev);
        iio_device_free(indio_dev);
 
        return 0;
diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c
deleted file mode 100644 (file)
index e2ac8a8..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16240.h"
-
-/**
- * adis16240_read_ring_data() read data registers which will be placed into ring
- * @indio_dev: the IIO device
- * @rx: somewhere to pass back the value read
- **/
-static int adis16240_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-       struct spi_message msg;
-       struct adis16240_state *st = iio_priv(indio_dev);
-       struct spi_transfer xfers[ADIS16240_OUTPUTS + 1];
-       int ret;
-       int i;
-
-       mutex_lock(&st->buf_lock);
-
-       spi_message_init(&msg);
-
-       memset(xfers, 0, sizeof(xfers));
-       for (i = 0; i <= ADIS16240_OUTPUTS; i++) {
-               xfers[i].bits_per_word = 8;
-               xfers[i].cs_change = 1;
-               xfers[i].len = 2;
-               xfers[i].delay_usecs = 30;
-               xfers[i].tx_buf = st->tx + 2 * i;
-               st->tx[2 * i]
-                       = ADIS16240_READ_REG(ADIS16240_SUPPLY_OUT + 2 * i);
-               st->tx[2 * i + 1] = 0;
-               if (i >= 1)
-                       xfers[i].rx_buf = rx + 2 * (i - 1);
-               spi_message_add_tail(&xfers[i], &msg);
-       }
-
-       ret = spi_sync(st->us, &msg);
-       if (ret)
-               dev_err(&st->us->dev, "problem when burst reading");
-
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-static irqreturn_t adis16240_trigger_handler(int irq, void *p)
-{
-       struct iio_poll_func *pf = p;
-       struct iio_dev *indio_dev = pf->indio_dev;
-       struct adis16240_state *st = iio_priv(indio_dev);
-
-       int i = 0;
-       s16 *data;
-
-       data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-       if (data == NULL) {
-               dev_err(&st->us->dev, "memory alloc failed in ring bh");
-               goto done;
-       }
-
-       if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
-           adis16240_read_ring_data(indio_dev, st->rx) >= 0)
-               for (; i < bitmap_weight(indio_dev->active_scan_mask,
-                                        indio_dev->masklength); i++)
-                       data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-       /* Guaranteed to be aligned with 8 byte boundary */
-       if (indio_dev->scan_timestamp)
-               *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-       iio_push_to_buffers(indio_dev, (u8 *)data);
-
-       kfree(data);
-done:
-       iio_trigger_notify_done(indio_dev->trig);
-
-       return IRQ_HANDLED;
-}
-
-void adis16240_unconfigure_ring(struct iio_dev *indio_dev)
-{
-       iio_dealloc_pollfunc(indio_dev->pollfunc);
-       iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16240_ring_setup_ops = {
-       .preenable = &iio_sw_buffer_preenable,
-       .postenable = &iio_triggered_buffer_postenable,
-       .predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16240_configure_ring(struct iio_dev *indio_dev)
-{
-       int ret = 0;
-       struct iio_buffer *ring;
-
-       ring = iio_sw_rb_allocate(indio_dev);
-       if (!ring) {
-               ret = -ENOMEM;
-               return ret;
-       }
-       indio_dev->buffer = ring;
-       ring->scan_timestamp = true;
-       indio_dev->setup_ops = &adis16240_ring_setup_ops;
-
-       indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-                                                &adis16240_trigger_handler,
-                                                IRQF_ONESHOT,
-                                                indio_dev,
-                                                "%s_consumer%d",
-                                                indio_dev->name,
-                                                indio_dev->id);
-       if (indio_dev->pollfunc == NULL) {
-               ret = -ENOMEM;
-               goto error_iio_sw_rb_free;
-       }
-
-       indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-       return 0;
-
-error_iio_sw_rb_free:
-       iio_sw_rb_free(indio_dev->buffer);
-       return ret;
-}
diff --git a/drivers/staging/iio/accel/adis16240_trigger.c b/drivers/staging/iio/accel/adis16240_trigger.c
deleted file mode 100644 (file)
index f3caf09..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16240.h"
-
-/**
- * adis16240_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16240_data_rdy_trigger_set_state(struct iio_trigger *trig,
-                                               bool state)
-{
-       struct iio_dev *indio_dev = trig->private_data;
-
-       dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-       return adis16240_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16240_trigger_ops = {
-       .owner = THIS_MODULE,
-       .set_trigger_state = &adis16240_data_rdy_trigger_set_state,
-};
-
-int adis16240_probe_trigger(struct iio_dev *indio_dev)
-{
-       int ret;
-       struct adis16240_state *st = iio_priv(indio_dev);
-
-       st->trig = iio_trigger_alloc("adis16240-dev%d", indio_dev->id);
-       if (st->trig == NULL) {
-               ret = -ENOMEM;
-               goto error_ret;
-       }
-
-       ret = request_irq(st->us->irq,
-                         iio_trigger_generic_data_rdy_poll,
-                         IRQF_TRIGGER_RISING,
-                         "adis16240",
-                         st->trig);
-       if (ret)
-               goto error_free_trig;
-
-       st->trig->dev.parent = &st->us->dev;
-       st->trig->ops = &adis16240_trigger_ops;
-       st->trig->private_data = indio_dev;
-       ret = iio_trigger_register(st->trig);
-
-       /* select default trigger */
-       indio_dev->trig = st->trig;
-       if (ret)
-               goto error_free_irq;
-
-       return 0;
-
-error_free_irq:
-       free_irq(st->us->irq, st->trig);
-error_free_trig:
-       iio_trigger_free(st->trig);
-error_ret:
-       return ret;
-}
-
-void adis16240_remove_trigger(struct iio_dev *indio_dev)
-{
-       struct adis16240_state *st = iio_priv(indio_dev);
-
-       iio_trigger_unregister(st->trig);
-       free_irq(st->us->irq, st->trig);
-       iio_trigger_free(st->trig);
-}
index 0177f1e023000f86e72dc96f9294626c06f4d1b6..dc8582b95b613ca24e1d9a440d4dc54d41524a03 100644 (file)
@@ -10,17 +10,6 @@ config AD7291
          Say yes here to build support for Analog Devices AD7291
          8 Channel ADC with temperature sensor.
 
-config AD7298
-       tristate "Analog Devices AD7298 ADC driver"
-       depends on SPI
-       select IIO_TRIGGERED_BUFFER if IIO_BUFFER
-       help
-         Say yes here to build support for Analog Devices AD7298
-         8 Channel ADC with temperature sensor.
-
-         To compile this driver as a module, choose M here: the
-         module will be called ad7298.
-
 config AD7606
        tristate "Analog Devices AD7606 ADC driver"
        depends on GPIOLIB
index 12b4bd32437fd2ee644793375916f94465efb532..7281451a613aca4a021e7675b4864f5ea2ee0c36 100644 (file)
@@ -12,10 +12,6 @@ ad799x-y := ad799x_core.o
 ad799x-$(CONFIG_AD799X_RING_BUFFER) += ad799x_ring.o
 obj-$(CONFIG_AD799X) += ad799x.o
 
-ad7298-y := ad7298_core.o
-ad7298-$(CONFIG_IIO_BUFFER) += ad7298_ring.o
-obj-$(CONFIG_AD7298) += ad7298.o
-
 obj-$(CONFIG_AD7291) += ad7291.o
 obj-$(CONFIG_AD7780) += ad7780.o
 obj-$(CONFIG_AD7793) += ad7793.o
diff --git a/drivers/staging/iio/adc/ad7298.h b/drivers/staging/iio/adc/ad7298.h
deleted file mode 100644 (file)
index 18f2787..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * AD7298 SPI ADC driver
- *
- * Copyright 2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
- */
-
-#ifndef IIO_ADC_AD7298_H_
-#define IIO_ADC_AD7298_H_
-
-#define AD7298_WRITE   (1 << 15) /* write to the control register */
-#define AD7298_REPEAT  (1 << 14) /* repeated conversion enable */
-#define AD7298_CH(x)   (1 << (13 - (x))) /* channel select */
-#define AD7298_TSENSE  (1 << 5) /* temperature conversion enable */
-#define AD7298_EXTREF  (1 << 2) /* external reference enable */
-#define AD7298_TAVG    (1 << 1) /* temperature sensor averaging enable */
-#define AD7298_PDD     (1 << 0) /* partial power down enable */
-
-#define AD7298_MAX_CHAN                8
-#define AD7298_BITS            12
-#define AD7298_STORAGE_BITS    16
-#define AD7298_INTREF_mV       2500
-
-#define AD7298_CH_TEMP         9
-
-#define RES_MASK(bits) ((1 << (bits)) - 1)
-
-/*
- * TODO: struct ad7298_platform_data needs to go into include/linux/iio
- */
-
-struct ad7298_platform_data {
-       /* External Vref voltage applied */
-       u16                             vref_mv;
-};
-
-struct ad7298_state {
-       struct spi_device               *spi;
-       struct regulator                *reg;
-       u16                             int_vref_mv;
-       unsigned                        ext_ref;
-       struct spi_transfer             ring_xfer[10];
-       struct spi_transfer             scan_single_xfer[3];
-       struct spi_message              ring_msg;
-       struct spi_message              scan_single_msg;
-       /*
-        * DMA (thus cache coherency maintenance) requires the
-        * transfer buffers to live in their own cache lines.
-        */
-       unsigned short                  rx_buf[8] ____cacheline_aligned;
-       unsigned short                  tx_buf[2];
-};
-
-#ifdef CONFIG_IIO_BUFFER
-int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev);
-void ad7298_ring_cleanup(struct iio_dev *indio_dev);
-int ad7298_update_scan_mode(struct iio_dev *indio_dev,
-       const unsigned long *active_scan_mask);
-#else /* CONFIG_IIO_BUFFER */
-
-static inline int
-ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
-       return 0;
-}
-
-static inline void ad7298_ring_cleanup(struct iio_dev *indio_dev)
-{
-}
-
-#define ad7298_update_scan_mode NULL
-
-#endif /* CONFIG_IIO_BUFFER */
-#endif /* IIO_ADC_AD7298_H_ */
diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/staging/iio/adc/ad7298_core.c
deleted file mode 100644 (file)
index 4c75114..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * AD7298 SPI ADC driver
- *
- * Copyright 2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
- */
-
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/spi/spi.h>
-#include <linux/regulator/consumer.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/buffer.h>
-
-#include "ad7298.h"
-
-#define AD7298_V_CHAN(index)                                           \
-       {                                                               \
-               .type = IIO_VOLTAGE,                                    \
-               .indexed = 1,                                           \
-               .channel = index,                                       \
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |           \
-               IIO_CHAN_INFO_SCALE_SHARED_BIT,                         \
-               .address = index,                                       \
-               .scan_index = index,                                    \
-               .scan_type = {                                          \
-                       .sign = 'u',                                    \
-                       .realbits = 12,                                 \
-                       .storagebits = 16,                              \
-               },                                                      \
-       }
-
-static const struct iio_chan_spec ad7298_channels[] = {
-       {
-               .type = IIO_TEMP,
-               .indexed = 1,
-               .channel = 0,
-               .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-               .address = AD7298_CH_TEMP,
-               .scan_index = -1,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 32,
-                       .storagebits = 32,
-               },
-       },
-       AD7298_V_CHAN(0),
-       AD7298_V_CHAN(1),
-       AD7298_V_CHAN(2),
-       AD7298_V_CHAN(3),
-       AD7298_V_CHAN(4),
-       AD7298_V_CHAN(5),
-       AD7298_V_CHAN(6),
-       AD7298_V_CHAN(7),
-       IIO_CHAN_SOFT_TIMESTAMP(8),
-};
-
-static int ad7298_scan_direct(struct ad7298_state *st, unsigned ch)
-{
-       int ret;
-       st->tx_buf[0] = cpu_to_be16(AD7298_WRITE | st->ext_ref |
-                                  (AD7298_CH(0) >> ch));
-
-       ret = spi_sync(st->spi, &st->scan_single_msg);
-       if (ret)
-               return ret;
-
-       return be16_to_cpu(st->rx_buf[0]);
-}
-
-static int ad7298_scan_temp(struct ad7298_state *st, int *val)
-{
-       int tmp, ret;
-       __be16 buf;
-
-       buf = cpu_to_be16(AD7298_WRITE | AD7298_TSENSE |
-                         AD7298_TAVG | st->ext_ref);
-
-       ret = spi_write(st->spi, (u8 *)&buf, 2);
-       if (ret)
-               return ret;
-
-       buf = cpu_to_be16(0);
-
-       ret = spi_write(st->spi, (u8 *)&buf, 2);
-       if (ret)
-               return ret;
-
-       usleep_range(101, 1000); /* sleep > 100us */
-
-       ret = spi_read(st->spi, (u8 *)&buf, 2);
-       if (ret)
-               return ret;
-
-       tmp = be16_to_cpu(buf) & RES_MASK(AD7298_BITS);
-
-       /*
-        * One LSB of the ADC corresponds to 0.25 deg C.
-        * The temperature reading is in 12-bit twos complement format
-        */
-
-       if (tmp & (1 << (AD7298_BITS - 1))) {
-               tmp = (4096 - tmp) * 250;
-               tmp -= (2 * tmp);
-
-       } else {
-               tmp *= 250; /* temperature in milli degrees Celsius */
-       }
-
-       *val = tmp;
-
-       return 0;
-}
-
-static int ad7298_read_raw(struct iio_dev *indio_dev,
-                          struct iio_chan_spec const *chan,
-                          int *val,
-                          int *val2,
-                          long m)
-{
-       int ret;
-       struct ad7298_state *st = iio_priv(indio_dev);
-       unsigned int scale_uv;
-
-       switch (m) {
-       case IIO_CHAN_INFO_RAW:
-               mutex_lock(&indio_dev->mlock);
-               if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
-                       ret = -EBUSY;
-               } else {
-                       if (chan->address == AD7298_CH_TEMP)
-                               ret = ad7298_scan_temp(st, val);
-                       else
-                               ret = ad7298_scan_direct(st, chan->address);
-               }
-               mutex_unlock(&indio_dev->mlock);
-
-               if (ret < 0)
-                       return ret;
-
-               if (chan->address != AD7298_CH_TEMP)
-                       *val = ret & RES_MASK(AD7298_BITS);
-
-               return IIO_VAL_INT;
-       case IIO_CHAN_INFO_SCALE:
-               switch (chan->type) {
-               case IIO_VOLTAGE:
-                       scale_uv = (st->int_vref_mv * 1000) >> AD7298_BITS;
-                       *val =  scale_uv / 1000;
-                       *val2 = (scale_uv % 1000) * 1000;
-                       return IIO_VAL_INT_PLUS_MICRO;
-               case IIO_TEMP:
-                       *val =  1;
-                       *val2 = 0;
-                       return IIO_VAL_INT_PLUS_MICRO;
-               default:
-                       return -EINVAL;
-               }
-       }
-       return -EINVAL;
-}
-
-static const struct iio_info ad7298_info = {
-       .read_raw = &ad7298_read_raw,
-       .update_scan_mode = ad7298_update_scan_mode,
-       .driver_module = THIS_MODULE,
-};
-
-static int __devinit ad7298_probe(struct spi_device *spi)
-{
-       struct ad7298_platform_data *pdata = spi->dev.platform_data;
-       struct ad7298_state *st;
-       int ret;
-       struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
-
-       if (indio_dev == NULL)
-               return -ENOMEM;
-
-       st = iio_priv(indio_dev);
-
-       st->reg = regulator_get(&spi->dev, "vcc");
-       if (!IS_ERR(st->reg)) {
-               ret = regulator_enable(st->reg);
-               if (ret)
-                       goto error_put_reg;
-       }
-
-       spi_set_drvdata(spi, indio_dev);
-
-       st->spi = spi;
-
-       indio_dev->name = spi_get_device_id(spi)->name;
-       indio_dev->dev.parent = &spi->dev;
-       indio_dev->modes = INDIO_DIRECT_MODE;
-       indio_dev->channels = ad7298_channels;
-       indio_dev->num_channels = ARRAY_SIZE(ad7298_channels);
-       indio_dev->info = &ad7298_info;
-
-       /* Setup default message */
-
-       st->scan_single_xfer[0].tx_buf = &st->tx_buf[0];
-       st->scan_single_xfer[0].len = 2;
-       st->scan_single_xfer[0].cs_change = 1;
-       st->scan_single_xfer[1].tx_buf = &st->tx_buf[1];
-       st->scan_single_xfer[1].len = 2;
-       st->scan_single_xfer[1].cs_change = 1;
-       st->scan_single_xfer[2].rx_buf = &st->rx_buf[0];
-       st->scan_single_xfer[2].len = 2;
-
-       spi_message_init(&st->scan_single_msg);
-       spi_message_add_tail(&st->scan_single_xfer[0], &st->scan_single_msg);
-       spi_message_add_tail(&st->scan_single_xfer[1], &st->scan_single_msg);
-       spi_message_add_tail(&st->scan_single_xfer[2], &st->scan_single_msg);
-
-       if (pdata && pdata->vref_mv) {
-               st->int_vref_mv = pdata->vref_mv;
-               st->ext_ref = AD7298_EXTREF;
-       } else {
-               st->int_vref_mv = AD7298_INTREF_mV;
-       }
-
-       ret = ad7298_register_ring_funcs_and_init(indio_dev);
-       if (ret)
-               goto error_disable_reg;
-
-       ret = iio_device_register(indio_dev);
-       if (ret)
-               goto error_cleanup_ring;
-
-       return 0;
-
-error_cleanup_ring:
-       ad7298_ring_cleanup(indio_dev);
-error_disable_reg:
-       if (!IS_ERR(st->reg))
-               regulator_disable(st->reg);
-error_put_reg:
-       if (!IS_ERR(st->reg))
-               regulator_put(st->reg);
-       iio_device_free(indio_dev);
-
-       return ret;
-}
-
-static int __devexit ad7298_remove(struct spi_device *spi)
-{
-       struct iio_dev *indio_dev = spi_get_drvdata(spi);
-       struct ad7298_state *st = iio_priv(indio_dev);
-
-       iio_device_unregister(indio_dev);
-       ad7298_ring_cleanup(indio_dev);
-       if (!IS_ERR(st->reg)) {
-               regulator_disable(st->reg);
-               regulator_put(st->reg);
-       }
-       iio_device_free(indio_dev);
-
-       return 0;
-}
-
-static const struct spi_device_id ad7298_id[] = {
-       {"ad7298", 0},
-       {}
-};
-MODULE_DEVICE_TABLE(spi, ad7298_id);
-
-static struct spi_driver ad7298_driver = {
-       .driver = {
-               .name   = "ad7298",
-               .owner  = THIS_MODULE,
-       },
-       .probe          = ad7298_probe,
-       .remove         = __devexit_p(ad7298_remove),
-       .id_table       = ad7298_id,
-};
-module_spi_driver(ad7298_driver);
-
-MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("Analog Devices AD7298 ADC");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c
deleted file mode 100644 (file)
index b3dd514..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * AD7298 SPI ADC driver
- *
- * Copyright 2011-2012 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
- */
-
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/spi/spi.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/triggered_buffer.h>
-
-#include "ad7298.h"
-
-/**
- * ad7298_update_scan_mode() setup the spi transfer buffer for the new scan mask
- **/
-int ad7298_update_scan_mode(struct iio_dev *indio_dev,
-       const unsigned long *active_scan_mask)
-{
-       struct ad7298_state *st = iio_priv(indio_dev);
-       int i, m;
-       unsigned short command;
-       int scan_count;
-
-       /* Now compute overall size */
-       scan_count = bitmap_weight(active_scan_mask, indio_dev->masklength);
-
-       command = AD7298_WRITE | st->ext_ref;
-
-       for (i = 0, m = AD7298_CH(0); i < AD7298_MAX_CHAN; i++, m >>= 1)
-               if (test_bit(i, active_scan_mask))
-                       command |= m;
-
-       st->tx_buf[0] = cpu_to_be16(command);
-
-       /* build spi ring message */
-       st->ring_xfer[0].tx_buf = &st->tx_buf[0];
-       st->ring_xfer[0].len = 2;
-       st->ring_xfer[0].cs_change = 1;
-       st->ring_xfer[1].tx_buf = &st->tx_buf[1];
-       st->ring_xfer[1].len = 2;
-       st->ring_xfer[1].cs_change = 1;
-
-       spi_message_init(&st->ring_msg);
-       spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg);
-       spi_message_add_tail(&st->ring_xfer[1], &st->ring_msg);
-
-       for (i = 0; i < scan_count; i++) {
-               st->ring_xfer[i + 2].rx_buf = &st->rx_buf[i];
-               st->ring_xfer[i + 2].len = 2;
-               st->ring_xfer[i + 2].cs_change = 1;
-               spi_message_add_tail(&st->ring_xfer[i + 2], &st->ring_msg);
-       }
-       /* make sure last transfer cs_change is not set */
-       st->ring_xfer[i + 1].cs_change = 0;
-
-       return 0;
-}
-
-/**
- * ad7298_trigger_handler() bh of trigger launched polling to ring buffer
- *
- * Currently there is no option in this driver to disable the saving of
- * timestamps within the ring.
- **/
-static irqreturn_t ad7298_trigger_handler(int irq, void *p)
-{
-       struct iio_poll_func *pf = p;
-       struct iio_dev *indio_dev = pf->indio_dev;
-       struct ad7298_state *st = iio_priv(indio_dev);
-       s64 time_ns = 0;
-       __u16 buf[16];
-       int b_sent, i;
-
-       b_sent = spi_sync(st->spi, &st->ring_msg);
-       if (b_sent)
-               goto done;
-
-       if (indio_dev->scan_timestamp) {
-               time_ns = iio_get_time_ns();
-               memcpy((u8 *)buf + indio_dev->scan_bytes - sizeof(s64),
-                       &time_ns, sizeof(time_ns));
-       }
-
-       for (i = 0; i < bitmap_weight(indio_dev->active_scan_mask,
-                                                indio_dev->masklength); i++)
-               buf[i] = be16_to_cpu(st->rx_buf[i]);
-
-       iio_push_to_buffers(indio_dev, (u8 *)buf);
-
-done:
-       iio_trigger_notify_done(indio_dev->trig);
-
-       return IRQ_HANDLED;
-}
-
-int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
-       return iio_triggered_buffer_setup(indio_dev, NULL,
-                       &ad7298_trigger_handler, NULL);
-}
-
-void ad7298_ring_cleanup(struct iio_dev *indio_dev)
-{
-       iio_triggered_buffer_cleanup(indio_dev);
-}
index 5e93d868b3feffd872c810431d6b4ff0a6067b2d..6493cd0a48dd9a425cd990bd12c006926da076a6 100644 (file)
@@ -181,7 +181,7 @@ static ssize_t adt7410_store_mode(struct device *dev,
 
        chip->config = config;
 
-       return ret;
+       return len;
 }
 
 static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
index 9ba5ec151705f7e88713898f27177028f3a1dd75..1303569e5c8a9c56b7be5195dc41ff994d1238b8 100644 (file)
@@ -12,7 +12,6 @@ adis16130-y             := adis16130_core.o
 obj-$(CONFIG_ADIS16130) += adis16130.o
 
 adis16260-y             := adis16260_core.o
-adis16260-$(CONFIG_IIO_BUFFER) += adis16260_ring.o adis16260_trigger.o
 obj-$(CONFIG_ADIS16260) += adis16260.o
 
 adis16251-y             := adis16251_core.o
index 4c4b25129c6cbd00dd33ae21a8daad16e495c322..df3c0b7e954a79c7b7616203eb60f2fd8b55013d 100644 (file)
@@ -1,12 +1,11 @@
 #ifndef SPI_ADIS16260_H_
 #define SPI_ADIS16260_H_
+
 #include "adis16260_platform_data.h"
+#include <linux/iio/imu/adis.h>
 
 #define ADIS16260_STARTUP_DELAY        220 /* ms */
 
-#define ADIS16260_READ_REG(a)    a
-#define ADIS16260_WRITE_REG(a) ((a) | 0x80)
-
 #define ADIS16260_FLASH_CNT  0x00 /* Flash memory write count */
 #define ADIS16260_SUPPLY_OUT 0x02 /* Power supply measurement */
 #define ADIS16260_GYRO_OUT   0x04 /* X-axis gyroscope output */
@@ -34,8 +33,6 @@
                                   * convert to decimal = 16,265/16,260 */
 #define ADIS16260_SERIAL_NUM 0x58 /* Serial number */
 
-#define ADIS16260_OUTPUTS    5
-
 #define ADIS16260_ERROR_ACTIVE                 (1<<14)
 #define ADIS16260_NEW_DATA                     (1<<15)
 
 /* DIAG_STAT */
 #define ADIS16260_DIAG_STAT_ALARM2     (1<<9)
 #define ADIS16260_DIAG_STAT_ALARM1     (1<<8)
-#define ADIS16260_DIAG_STAT_FLASH_CHK  (1<<6)
-#define ADIS16260_DIAG_STAT_SELF_TEST  (1<<5)
-#define ADIS16260_DIAG_STAT_OVERFLOW   (1<<4)
-#define ADIS16260_DIAG_STAT_SPI_FAIL   (1<<3)
-#define ADIS16260_DIAG_STAT_FLASH_UPT  (1<<2)
-#define ADIS16260_DIAG_STAT_POWER_HIGH (1<<1)
-#define ADIS16260_DIAG_STAT_POWER_LOW  (1<<0)
+#define ADIS16260_DIAG_STAT_FLASH_CHK_BIT      6
+#define ADIS16260_DIAG_STAT_SELF_TEST_BIT      5
+#define ADIS16260_DIAG_STAT_OVERFLOW_BIT       4
+#define ADIS16260_DIAG_STAT_SPI_FAIL_BIT       3
+#define ADIS16260_DIAG_STAT_FLASH_UPT_BIT      2
+#define ADIS16260_DIAG_STAT_POWER_HIGH_BIT     1
+#define ADIS16260_DIAG_STAT_POWER_LOW_BIT      0
 
 /* GLOB_CMD */
 #define ADIS16260_GLOB_CMD_SW_RESET    (1<<7)
 #define ADIS16260_GLOB_CMD_FAC_CALIB   (1<<1)
 #define ADIS16260_GLOB_CMD_AUTO_NULL   (1<<0)
 
-#define ADIS16260_MAX_TX 24
-#define ADIS16260_MAX_RX 24
-
 #define ADIS16260_SPI_SLOW     (u32)(300 * 1000)
 #define ADIS16260_SPI_BURST    (u32)(1000 * 1000)
 #define ADIS16260_SPI_FAST     (u32)(2000 * 1000)
 
 /**
  * struct adis16260_state - device instance specific data
- * @us:                        actual spi_device
- * @trig:              data ready trigger registered with iio
- * @buf_lock:          mutex to protect tx and rx
  * @negate:            negate the scale parameter
- * @tx:                        transmit buffer
- * @rx:                        receive buffer
  **/
 struct adis16260_state {
-       struct spi_device       *us;
-       struct iio_trigger      *trig;
-       struct mutex            buf_lock;
-       unsigned                negate:1;
-       u8                      tx[ADIS16260_MAX_TX] ____cacheline_aligned;
-       u8                      rx[ADIS16260_MAX_RX];
+       unsigned        negate:1;
+       struct adis     adis;
 };
 
-int adis16260_set_irq(struct iio_dev *indio_dev, bool enable);
-
 /* At the moment triggers are only used for ring buffer
  * filling. This may change!
  */
 
-#define ADIS16260_SCAN_SUPPLY  0
-#define ADIS16260_SCAN_GYRO    1
+#define ADIS16260_SCAN_GYRO    0
+#define ADIS16260_SCAN_SUPPLY  1
 #define ADIS16260_SCAN_AUX_ADC 2
 #define ADIS16260_SCAN_TEMP    3
 #define ADIS16260_SCAN_ANGL    4
 
-#ifdef CONFIG_IIO_BUFFER
-void adis16260_remove_trigger(struct iio_dev *indio_dev);
-int adis16260_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16260_read_data_from_ring(struct device *dev,
-                                     struct device_attribute *attr,
-                                     char *buf);
-
-
-int adis16260_configure_ring(struct iio_dev *indio_dev);
-void adis16260_unconfigure_ring(struct iio_dev *indio_dev);
-
-#else /* CONFIG_IIO_BUFFER */
-
-static inline void adis16260_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16260_probe_trigger(struct iio_dev *indio_dev)
-{
-       return 0;
-}
-
-static inline ssize_t
-adis16260_read_data_from_ring(struct device *dev,
-                             struct device_attribute *attr,
-                             char *buf)
-{
-       return 0;
-}
-
-static int adis16260_configure_ring(struct iio_dev *indio_dev)
-{
-       return 0;
-}
-
-static inline void adis16260_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-#endif /* CONFIG_IIO_BUFFER */
 #endif /* SPI_ADIS16260_H_ */
index e822460502be4b665674360f62a277e67f05febd..b988b4f5bdda7be7e3c7a4f8856d976ba6e7dbb5 100644 (file)
 
 #include "adis16260.h"
 
-static int adis16260_check_status(struct iio_dev *indio_dev);
-
-/**
- * adis16260_spi_write_reg_8() - write single byte to a register
- * @indio_dev: iio_dev for the device
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-static int adis16260_spi_write_reg_8(struct iio_dev *indio_dev,
-               u8 reg_address,
-               u8 val)
-{
-       int ret;
-       struct adis16260_state *st = iio_priv(indio_dev);
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16260_WRITE_REG(reg_address);
-       st->tx[1] = val;
-
-       ret = spi_write(st->us, st->tx, 2);
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/**
- * adis16260_spi_write_reg_16() - write 2 bytes to a pair of registers
- * @indio_dev: iio_dev for the device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: value to be written
- **/
-static int adis16260_spi_write_reg_16(struct iio_dev *indio_dev,
-               u8 lower_reg_address,
-               u16 value)
-{
-       int ret;
-       struct spi_message msg;
-       struct adis16260_state *st = iio_priv(indio_dev);
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = st->tx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-                       .delay_usecs = 20,
-               }, {
-                       .tx_buf = st->tx + 2,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .delay_usecs = 20,
-               },
-       };
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16260_WRITE_REG(lower_reg_address);
-       st->tx[1] = value & 0xFF;
-       st->tx[2] = ADIS16260_WRITE_REG(lower_reg_address + 1);
-       st->tx[3] = (value >> 8) & 0xFF;
-
-       spi_message_init(&msg);
-       spi_message_add_tail(&xfers[0], &msg);
-       spi_message_add_tail(&xfers[1], &msg);
-       ret = spi_sync(st->us, &msg);
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-/**
- * adis16260_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @indio_dev: iio_dev for the device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int adis16260_spi_read_reg_16(struct iio_dev *indio_dev,
-               u8 lower_reg_address,
-               u16 *val)
-{
-       struct spi_message msg;
-       struct adis16260_state *st = iio_priv(indio_dev);
-       int ret;
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = st->tx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-                       .delay_usecs = 30,
-               }, {
-                       .rx_buf = st->rx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .delay_usecs = 30,
-               },
-       };
-
-       mutex_lock(&st->buf_lock);
-       st->tx[0] = ADIS16260_READ_REG(lower_reg_address);
-       st->tx[1] = 0;
-
-       spi_message_init(&msg);
-       spi_message_add_tail(&xfers[0], &msg);
-       spi_message_add_tail(&xfers[1], &msg);
-       ret = spi_sync(st->us, &msg);
-       if (ret) {
-               dev_err(&st->us->dev,
-                       "problem when reading 16 bit register 0x%02X",
-                       lower_reg_address);
-               goto error_ret;
-       }
-       *val = (st->rx[0] << 8) | st->rx[1];
-
-error_ret:
-       mutex_unlock(&st->buf_lock);
-       return ret;
-}
-
 static ssize_t adis16260_read_frequency_available(struct device *dev,
                                                  struct device_attribute *attr,
                                                  char *buf)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct adis16260_state *st = iio_priv(indio_dev);
-       if (spi_get_device_id(st->us)->driver_data)
+       if (spi_get_device_id(st->adis.spi)->driver_data)
                return sprintf(buf, "%s\n", "0.129 ~ 256");
        else
                return sprintf(buf, "%s\n", "256 2048");
@@ -164,13 +45,11 @@ static ssize_t adis16260_read_frequency(struct device *dev,
        int ret, len = 0;
        u16 t;
        int sps;
-       ret = adis16260_spi_read_reg_16(indio_dev,
-                       ADIS16260_SMPL_PRD,
-                       &t);
+       ret = adis_read_reg_16(&st->adis, ADIS16260_SMPL_PRD, &t);
        if (ret)
                return ret;
 
-       if (spi_get_device_id(st->us)->driver_data) /* If an adis16251 */
+       if (spi_get_device_id(st->adis.spi)->driver_data) /* If an adis16251 */
                sps =  (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 8 : 256;
        else
                sps =  (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 66 : 2048;
@@ -197,7 +76,7 @@ static ssize_t adis16260_write_frequency(struct device *dev,
                return -EINVAL;
 
        mutex_lock(&indio_dev->mlock);
-       if (spi_get_device_id(st->us)) {
+       if (spi_get_device_id(st->adis.spi)->driver_data) {
                t = (256 / val);
                if (t > 0)
                        t--;
@@ -209,10 +88,10 @@ static ssize_t adis16260_write_frequency(struct device *dev,
                t &= ADIS16260_SMPL_PRD_DIV_MASK;
        }
        if ((t & ADIS16260_SMPL_PRD_DIV_MASK) >= 0x0A)
-               st->us->max_speed_hz = ADIS16260_SPI_SLOW;
+               st->adis.spi->max_speed_hz = ADIS16260_SPI_SLOW;
        else
-               st->us->max_speed_hz = ADIS16260_SPI_FAST;
-       ret = adis16260_spi_write_reg_8(indio_dev,
+               st->adis.spi->max_speed_hz = ADIS16260_SPI_FAST;
+       ret = adis_write_reg_8(&st->adis,
                        ADIS16260_SMPL_PRD,
                        t);
 
@@ -221,140 +100,20 @@ static ssize_t adis16260_write_frequency(struct device *dev,
        return ret ? ret : len;
 }
 
-static int adis16260_reset(struct iio_dev *indio_dev)
-{
-       int ret;
-       ret = adis16260_spi_write_reg_8(indio_dev,
-                       ADIS16260_GLOB_CMD,
-                       ADIS16260_GLOB_CMD_SW_RESET);
-       if (ret)
-               dev_err(&indio_dev->dev, "problem resetting device");
-
-       return ret;
-}
-
-int adis16260_set_irq(struct iio_dev *indio_dev, bool enable)
-{
-       int ret;
-       u16 msc;
-       ret = adis16260_spi_read_reg_16(indio_dev, ADIS16260_MSC_CTRL, &msc);
-       if (ret)
-               goto error_ret;
-
-       msc |= ADIS16260_MSC_CTRL_DATA_RDY_POL_HIGH;
-       if (enable)
-               msc |= ADIS16260_MSC_CTRL_DATA_RDY_EN;
-       else
-               msc &= ~ADIS16260_MSC_CTRL_DATA_RDY_EN;
-
-       ret = adis16260_spi_write_reg_16(indio_dev, ADIS16260_MSC_CTRL, msc);
-       if (ret)
-               goto error_ret;
-
-error_ret:
-       return ret;
-}
-
 /* Power down the device */
 static int adis16260_stop_device(struct iio_dev *indio_dev)
 {
+       struct adis16260_state *st = iio_priv(indio_dev);
        int ret;
        u16 val = ADIS16260_SLP_CNT_POWER_OFF;
 
-       ret = adis16260_spi_write_reg_16(indio_dev, ADIS16260_SLP_CNT, val);
+       ret = adis_write_reg_16(&st->adis, ADIS16260_SLP_CNT, val);
        if (ret)
                dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");
 
        return ret;
 }
 
-static int adis16260_self_test(struct iio_dev *indio_dev)
-{
-       int ret;
-       ret = adis16260_spi_write_reg_16(indio_dev,
-                       ADIS16260_MSC_CTRL,
-                       ADIS16260_MSC_CTRL_MEM_TEST);
-       if (ret) {
-               dev_err(&indio_dev->dev, "problem starting self test");
-               goto err_ret;
-       }
-
-       adis16260_check_status(indio_dev);
-
-err_ret:
-       return ret;
-}
-
-static int adis16260_check_status(struct iio_dev *indio_dev)
-{
-       u16 status;
-       int ret;
-       struct device *dev = &indio_dev->dev;
-
-       ret = adis16260_spi_read_reg_16(indio_dev,
-                                       ADIS16260_DIAG_STAT,
-                                       &status);
-
-       if (ret < 0) {
-               dev_err(dev, "Reading status failed\n");
-               goto error_ret;
-       }
-       ret = status & 0x7F;
-       if (status & ADIS16260_DIAG_STAT_FLASH_CHK)
-               dev_err(dev, "Flash checksum error\n");
-       if (status & ADIS16260_DIAG_STAT_SELF_TEST)
-               dev_err(dev, "Self test error\n");
-       if (status & ADIS16260_DIAG_STAT_OVERFLOW)
-               dev_err(dev, "Sensor overrange\n");
-       if (status & ADIS16260_DIAG_STAT_SPI_FAIL)
-               dev_err(dev, "SPI failure\n");
-       if (status & ADIS16260_DIAG_STAT_FLASH_UPT)
-               dev_err(dev, "Flash update failed\n");
-       if (status & ADIS16260_DIAG_STAT_POWER_HIGH)
-               dev_err(dev, "Power supply above 5.25V\n");
-       if (status & ADIS16260_DIAG_STAT_POWER_LOW)
-               dev_err(dev, "Power supply below 4.75V\n");
-
-error_ret:
-       return ret;
-}
-
-static int adis16260_initial_setup(struct iio_dev *indio_dev)
-{
-       int ret;
-       struct device *dev = &indio_dev->dev;
-
-       /* Disable IRQ */
-       ret = adis16260_set_irq(indio_dev, false);
-       if (ret) {
-               dev_err(dev, "disable irq failed");
-               goto err_ret;
-       }
-
-       /* Do self test */
-       ret = adis16260_self_test(indio_dev);
-       if (ret) {
-               dev_err(dev, "self test failure");
-               goto err_ret;
-       }
-
-       /* Read status register to check the result */
-       ret = adis16260_check_status(indio_dev);
-       if (ret) {
-               adis16260_reset(indio_dev);
-               dev_err(dev, "device not playing ball -> reset");
-               msleep(ADIS16260_STARTUP_DELAY);
-               ret = adis16260_check_status(indio_dev);
-               if (ret) {
-                       dev_err(dev, "giving up");
-                       goto err_ret;
-               }
-       }
-
-err_ret:
-       return ret;
-}
-
 static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
                adis16260_read_frequency,
                adis16260_write_frequency);
@@ -362,100 +121,26 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
 static IIO_DEVICE_ATTR(sampling_frequency_available,
                       S_IRUGO, adis16260_read_frequency_available, NULL, 0);
 
-enum adis16260_channel {
-       gyro,
-       temp,
-       in_supply,
-       in_aux,
-       angle,
-};
 #define ADIS16260_GYRO_CHANNEL_SET(axis, mod)                          \
-       struct iio_chan_spec adis16260_channels_##axis[] = {            \
-               {                                                       \
-                       .type = IIO_ANGL_VEL,                           \
-                       .modified = 1,                                  \
-                       .channel2 = mod,                                \
-                       .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |   \
-                       IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |          \
-                       IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |         \
-                       IIO_CHAN_INFO_SCALE_SEPARATE_BIT,               \
-                       .address = gyro,                                \
-                       .scan_index = ADIS16260_SCAN_GYRO,              \
-                       .scan_type = {                                  \
-                               .sign = 's',                            \
-                               .realbits = 14,                         \
-                               .storagebits = 16,                      \
-                       },                                              \
-               }, {                                                    \
-                       .type = IIO_ANGL,                               \
-                       .modified = 1,                                  \
-                       .channel2 = mod,                                \
-                       .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,    \
-                       .address = angle,                               \
-                       .scan_index = ADIS16260_SCAN_ANGL,              \
-                       .scan_type = {                                  \
-                               .sign = 'u',                            \
-                               .realbits = 14,                         \
-                               .storagebits = 16,                      \
-                       },                                              \
-               }, {                                                    \
-                       .type = IIO_TEMP,                               \
-                       .indexed = 1,                                   \
-                       .channel = 0,                                   \
-                       .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |   \
-                       IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |             \
-                       IIO_CHAN_INFO_SCALE_SEPARATE_BIT,               \
-                       .address = temp,                                \
-                       .scan_index = ADIS16260_SCAN_TEMP,              \
-                       .scan_type = {                                  \
-                               .sign = 'u',                            \
-                               .realbits = 12,                         \
-                               .storagebits = 16,                      \
-                       },                                              \
-               }, {                                                    \
-                       .type = IIO_VOLTAGE,                            \
-                       .indexed = 1,                                   \
-                       .channel = 0,                                   \
-                       .extend_name = "supply",                        \
-                       .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |   \
-                       IIO_CHAN_INFO_SCALE_SEPARATE_BIT,               \
-                       .address = in_supply,                           \
-                       .scan_index = ADIS16260_SCAN_SUPPLY,            \
-                       .scan_type = {                                  \
-                               .sign = 'u',                            \
-                               .realbits = 12,                         \
-                               .storagebits = 16,                      \
-                       },                                              \
-               }, {                                                    \
-                       .type = IIO_VOLTAGE,                            \
-                       .indexed = 1,                                   \
-                       .channel = 1,                                   \
-                       .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |   \
-                       IIO_CHAN_INFO_SCALE_SEPARATE_BIT,               \
-                       .address = in_aux,                              \
-                       .scan_index = ADIS16260_SCAN_AUX_ADC,           \
-                       .scan_type = {                                  \
-                               .sign = 'u',                            \
-                               .realbits = 12,                         \
-                               .storagebits = 16,                      \
-                       },                                              \
-               },                                                      \
-               IIO_CHAN_SOFT_TIMESTAMP(5),                             \
-       }
+struct iio_chan_spec adis16260_channels_##axis[] = {           \
+       ADIS_GYRO_CHAN(mod, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO, \
+               IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
+               IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, 14), \
+       ADIS_INCLI_CHAN(mod, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0, 14), \
+       ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP, 12), \
+       ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY, 12), \
+       ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC, 12), \
+       IIO_CHAN_SOFT_TIMESTAMP(5),                             \
+}
 
-static const ADIS16260_GYRO_CHANNEL_SET(x, IIO_MOD_X);
-static const ADIS16260_GYRO_CHANNEL_SET(y, IIO_MOD_Y);
-static const ADIS16260_GYRO_CHANNEL_SET(z, IIO_MOD_Z);
-
-static const u8 adis16260_addresses[5][3] = {
-       [gyro] = { ADIS16260_GYRO_OUT,
-                  ADIS16260_GYRO_OFF,
-                  ADIS16260_GYRO_SCALE },
-       [angle] = { ADIS16260_ANGL_OUT },
-       [in_supply] = { ADIS16260_SUPPLY_OUT },
-       [in_aux] = { ADIS16260_AUX_ADC },
-       [temp] = { ADIS16260_TEMP_OUT },
+static const ADIS16260_GYRO_CHANNEL_SET(x, X);
+static const ADIS16260_GYRO_CHANNEL_SET(y, Y);
+static const ADIS16260_GYRO_CHANNEL_SET(z, Z);
+
+static const u8 adis16260_addresses[][2] = {
+       [ADIS16260_SCAN_GYRO] = { ADIS16260_GYRO_OFF, ADIS16260_GYRO_SCALE },
 };
+
 static int adis16260_read_raw(struct iio_dev *indio_dev,
                              struct iio_chan_spec const *chan,
                              int *val, int *val2,
@@ -469,34 +154,13 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               mutex_lock(&indio_dev->mlock);
-               addr = adis16260_addresses[chan->address][0];
-               ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16);
-               if (ret) {
-                       mutex_unlock(&indio_dev->mlock);
-                       return ret;
-               }
-
-               if (val16 & ADIS16260_ERROR_ACTIVE) {
-                       ret = adis16260_check_status(indio_dev);
-                       if (ret) {
-                               mutex_unlock(&indio_dev->mlock);
-                               return ret;
-                       }
-               }
-               val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
-               if (chan->scan_type.sign == 's')
-                       val16 = (s16)(val16 <<
-                                     (16 - chan->scan_type.realbits)) >>
-                               (16 - chan->scan_type.realbits);
-               *val = val16;
-               mutex_unlock(&indio_dev->mlock);
-               return IIO_VAL_INT;
+               return adis_single_conversion(indio_dev, chan,
+                               ADIS16260_ERROR_ACTIVE, val);
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_ANGL_VEL:
                        *val = 0;
-                       if (spi_get_device_id(st->us)->driver_data) {
+                       if (spi_get_device_id(st->adis.spi)->driver_data) {
                                /* 0.01832 degree / sec */
                                *val2 = IIO_DEGREE_TO_RAD(18320);
                        } else {
@@ -533,8 +197,8 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
                        return -EINVAL;
                }
                mutex_lock(&indio_dev->mlock);
-               addr = adis16260_addresses[chan->address][1];
-               ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16);
+               addr = adis16260_addresses[chan->scan_index][0];
+               ret = adis_read_reg_16(&st->adis, addr, &val16);
                if (ret) {
                        mutex_unlock(&indio_dev->mlock);
                        return ret;
@@ -553,8 +217,8 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
                        return -EINVAL;
                }
                mutex_lock(&indio_dev->mlock);
-               addr = adis16260_addresses[chan->address][2];
-               ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16);
+               addr = adis16260_addresses[chan->scan_index][1];
+               ret = adis_read_reg_16(&st->adis, addr, &val16);
                if (ret) {
                        mutex_unlock(&indio_dev->mlock);
                        return ret;
@@ -572,18 +236,19 @@ static int adis16260_write_raw(struct iio_dev *indio_dev,
                               int val2,
                               long mask)
 {
+       struct adis16260_state *st = iio_priv(indio_dev);
        int bits = 12;
        s16 val16;
        u8 addr;
        switch (mask) {
        case IIO_CHAN_INFO_CALIBBIAS:
                val16 = val & ((1 << bits) - 1);
-               addr = adis16260_addresses[chan->address][1];
-               return adis16260_spi_write_reg_16(indio_dev, addr, val16);
+               addr = adis16260_addresses[chan->scan_index][0];
+               return adis_write_reg_16(&st->adis, addr, val16);
        case IIO_CHAN_INFO_CALIBSCALE:
                val16 = val & ((1 << bits) - 1);
-               addr = adis16260_addresses[chan->address][2];
-               return adis16260_spi_write_reg_16(indio_dev, addr, val16);
+               addr = adis16260_addresses[chan->scan_index][1];
+               return adis_write_reg_16(&st->adis, addr, val16);
        }
        return -EINVAL;
 }
@@ -602,9 +267,40 @@ static const struct iio_info adis16260_info = {
        .attrs = &adis16260_attribute_group,
        .read_raw = &adis16260_read_raw,
        .write_raw = &adis16260_write_raw,
+       .update_scan_mode = adis_update_scan_mode,
        .driver_module = THIS_MODULE,
 };
 
+static const char * const adis1620_status_error_msgs[] = {
+       [ADIS16260_DIAG_STAT_FLASH_CHK_BIT] = "Flash checksum error",
+       [ADIS16260_DIAG_STAT_SELF_TEST_BIT] = "Self test error",
+       [ADIS16260_DIAG_STAT_OVERFLOW_BIT] = "Sensor overrange",
+       [ADIS16260_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
+       [ADIS16260_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
+       [ADIS16260_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 5.25",
+       [ADIS16260_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 4.75",
+};
+
+static const struct adis_data adis16260_data = {
+       .write_delay = 30,
+       .read_delay = 30,
+       .msc_ctrl_reg = ADIS16260_MSC_CTRL,
+       .glob_cmd_reg = ADIS16260_GLOB_CMD,
+       .diag_stat_reg = ADIS16260_DIAG_STAT,
+
+       .self_test_mask = ADIS16260_MSC_CTRL_MEM_TEST,
+       .startup_delay = ADIS16260_STARTUP_DELAY,
+
+       .status_error_msgs = adis1620_status_error_msgs,
+       .status_error_mask = BIT(ADIS16260_DIAG_STAT_FLASH_CHK_BIT) |
+               BIT(ADIS16260_DIAG_STAT_SELF_TEST_BIT) |
+               BIT(ADIS16260_DIAG_STAT_OVERFLOW_BIT) |
+               BIT(ADIS16260_DIAG_STAT_SPI_FAIL_BIT) |
+               BIT(ADIS16260_DIAG_STAT_FLASH_UPT_BIT) |
+               BIT(ADIS16260_DIAG_STAT_POWER_HIGH_BIT) |
+               BIT(ADIS16260_DIAG_STAT_POWER_LOW_BIT),
+};
+
 static int __devinit adis16260_probe(struct spi_device *spi)
 {
        int ret;
@@ -624,10 +320,7 @@ static int __devinit adis16260_probe(struct spi_device *spi)
        /* this is only used for removal purposes */
        spi_set_drvdata(spi, indio_dev);
 
-       st->us = spi;
-       mutex_init(&st->buf_lock);
-
-       indio_dev->name = spi_get_device_id(st->us)->name;
+       indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &adis16260_info;
        indio_dev->num_channels
@@ -651,17 +344,14 @@ static int __devinit adis16260_probe(struct spi_device *spi)
        indio_dev->num_channels = ARRAY_SIZE(adis16260_channels_x);
        indio_dev->modes = INDIO_DIRECT_MODE;
 
-       ret = adis16260_configure_ring(indio_dev);
+       ret = adis_init(&st->adis, indio_dev, spi, &adis16260_data);
+       if (ret)
+               goto error_free_dev;
+
+       ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL);
        if (ret)
                goto error_free_dev;
 
-       ret = iio_buffer_register(indio_dev,
-                                 indio_dev->channels,
-                                 ARRAY_SIZE(adis16260_channels_x));
-       if (ret) {
-               printk(KERN_ERR "failed to initialize the ring\n");
-               goto error_unreg_ring_funcs;
-       }
        if (indio_dev->buffer) {
                /* Set default scan mode */
                iio_scan_mask_set(indio_dev, indio_dev->buffer,
@@ -675,28 +365,19 @@ static int __devinit adis16260_probe(struct spi_device *spi)
                iio_scan_mask_set(indio_dev, indio_dev->buffer,
                                  ADIS16260_SCAN_ANGL);
        }
-       if (spi->irq) {
-               ret = adis16260_probe_trigger(indio_dev);
-               if (ret)
-                       goto error_uninitialize_ring;
-       }
 
        /* Get the device into a sane initial state */
-       ret = adis16260_initial_setup(indio_dev);
+       ret = adis_initial_startup(&st->adis);
        if (ret)
-               goto error_remove_trigger;
+               goto error_cleanup_buffer_trigger;
        ret = iio_device_register(indio_dev);
        if (ret)
-               goto error_remove_trigger;
+               goto error_cleanup_buffer_trigger;
 
        return 0;
 
-error_remove_trigger:
-       adis16260_remove_trigger(indio_dev);
-error_uninitialize_ring:
-       iio_buffer_unregister(indio_dev);
-error_unreg_ring_funcs:
-       adis16260_unconfigure_ring(indio_dev);
+error_cleanup_buffer_trigger:
+       adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
 error_free_dev:
        iio_device_free(indio_dev);
 error_ret:
@@ -706,12 +387,11 @@ error_ret:
 static int __devexit adis16260_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
+       struct adis16260_state *st = iio_priv(indio_dev);
 
        iio_device_unregister(indio_dev);
        adis16260_stop_device(indio_dev);
-       adis16260_remove_trigger(indio_dev);
-       iio_buffer_unregister(indio_dev);
-       adis16260_unconfigure_ring(indio_dev);
+       adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
        iio_device_free(indio_dev);
 
        return 0;
diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c
deleted file mode 100644 (file)
index d6c48f8..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16260.h"
-
-/**
- * adis16260_read_ring_data() read data registers which will be placed into ring
- * @indio_dev: the IIO device
- * @rx: somewhere to pass back the value read
- **/
-static int adis16260_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-       struct spi_message msg;
-       struct adis16260_state *st = iio_priv(indio_dev);
-       struct spi_transfer xfers[ADIS16260_OUTPUTS + 1];
-       int ret;
-       int i;
-
-       mutex_lock(&st->buf_lock);
-
-       spi_message_init(&msg);
-
-       memset(xfers, 0, sizeof(xfers));
-       for (i = 0; i <= ADIS16260_OUTPUTS; i++) {
-               xfers[i].bits_per_word = 8;
-               xfers[i].cs_change = 1;
-               xfers[i].len = 2;
-               xfers[i].delay_usecs = 30;
-               xfers[i].tx_buf = st->tx + 2 * i;
-               if (i < 2) /* SUPPLY_OUT:0x02 GYRO_OUT:0x04 */
-                       st->tx[2 * i]
-                               = ADIS16260_READ_REG(ADIS16260_SUPPLY_OUT
-                                               + 2 * i);
-               else /* 0x06 to 0x09 is reserved */
-                       st->tx[2 * i]
-                               = ADIS16260_READ_REG(ADIS16260_SUPPLY_OUT
-                                               + 2 * i + 4);
-               st->tx[2 * i + 1] = 0;
-               if (i >= 1)
-                       xfers[i].rx_buf = rx + 2 * (i - 1);
-               spi_message_add_tail(&xfers[i], &msg);
-       }
-
-       ret = spi_sync(st->us, &msg);
-       if (ret)
-               dev_err(&st->us->dev, "problem when burst reading");
-
-       mutex_unlock(&st->buf_lock);
-
-       return ret;
-}
-
-static irqreturn_t adis16260_trigger_handler(int irq, void *p)
-{
-       struct iio_poll_func *pf = p;
-       struct iio_dev *indio_dev = pf->indio_dev;
-       struct adis16260_state *st = iio_priv(indio_dev);
-       int i = 0;
-       s16 *data;
-
-       data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-       if (data == NULL) {
-               dev_err(&st->us->dev, "memory alloc failed in ring bh");
-               goto done;
-       }
-
-       if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
-           adis16260_read_ring_data(indio_dev, st->rx) >= 0)
-               for (; i < bitmap_weight(indio_dev->active_scan_mask,
-                                        indio_dev->masklength); i++)
-                       data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-       /* Guaranteed to be aligned with 8 byte boundary */
-       if (indio_dev->scan_timestamp)
-               *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-       iio_push_to_buffers(indio_dev, (u8 *)data);
-
-       kfree(data);
-done:
-       iio_trigger_notify_done(indio_dev->trig);
-
-       return IRQ_HANDLED;
-}
-
-void adis16260_unconfigure_ring(struct iio_dev *indio_dev)
-{
-       iio_dealloc_pollfunc(indio_dev->pollfunc);
-       iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16260_ring_setup_ops = {
-       .preenable = &iio_sw_buffer_preenable,
-       .postenable = &iio_triggered_buffer_postenable,
-       .predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16260_configure_ring(struct iio_dev *indio_dev)
-{
-       int ret = 0;
-       struct iio_buffer *ring;
-
-       ring = iio_sw_rb_allocate(indio_dev);
-       if (!ring) {
-               ret = -ENOMEM;
-               return ret;
-       }
-       indio_dev->buffer = ring;
-       ring->scan_timestamp = true;
-       indio_dev->setup_ops = &adis16260_ring_setup_ops;
-
-       indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-                                                &adis16260_trigger_handler,
-                                                IRQF_ONESHOT,
-                                                indio_dev,
-                                                "adis16260_consumer%d",
-                                                indio_dev->id);
-       if (indio_dev->pollfunc == NULL) {
-               ret = -ENOMEM;
-               goto error_iio_sw_rb_free;
-       }
-
-       indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-       return 0;
-
-error_iio_sw_rb_free:
-       iio_sw_rb_free(indio_dev->buffer);
-       return ret;
-}
diff --git a/drivers/staging/iio/gyro/adis16260_trigger.c b/drivers/staging/iio/gyro/adis16260_trigger.c
deleted file mode 100644 (file)
index 034559e..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16260.h"
-
-/**
- * adis16260_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16260_data_rdy_trigger_set_state(struct iio_trigger *trig,
-                                               bool state)
-{
-       struct iio_dev *indio_dev = trig->private_data;
-
-       dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-       return adis16260_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16260_trigger_ops = {
-       .owner = THIS_MODULE,
-       .set_trigger_state = &adis16260_data_rdy_trigger_set_state,
-};
-
-int adis16260_probe_trigger(struct iio_dev *indio_dev)
-{
-       int ret;
-       struct adis16260_state *st = iio_priv(indio_dev);
-
-       st->trig = iio_trigger_alloc("%s-dev%d",
-                                       spi_get_device_id(st->us)->name,
-                                       indio_dev->id);
-       if (st->trig == NULL) {
-               ret = -ENOMEM;
-               goto error_ret;
-       }
-
-       ret = request_irq(st->us->irq,
-                         &iio_trigger_generic_data_rdy_poll,
-                         IRQF_TRIGGER_RISING,
-                         "adis16260",
-                         st->trig);
-       if (ret)
-               goto error_free_trig;
-
-       st->trig->dev.parent = &st->us->dev;
-       st->trig->ops = &adis16260_trigger_ops;
-       st->trig->private_data = indio_dev;
-       ret = iio_trigger_register(st->trig);
-
-       /* select default trigger */
-       indio_dev->trig = st->trig;
-       if (ret)
-               goto error_free_irq;
-
-       return 0;
-
-error_free_irq:
-       free_irq(st->us->irq, st->trig);
-error_free_trig:
-       iio_trigger_free(st->trig);
-error_ret:
-       return ret;
-}
-
-void adis16260_remove_trigger(struct iio_dev *indio_dev)
-{
-       struct adis16260_state *st = iio_priv(indio_dev);
-
-       iio_trigger_unregister(st->trig);
-       free_irq(st->us->irq, st->trig);
-       iio_trigger_free(st->trig);
-}
index 3b03f6f5c40cb55ad684923a2811db7e851105b9..1d5b294d6e6104c94b0cdec9b9bd3c48d991ea31 100644 (file)
@@ -356,7 +356,7 @@ static int isl29018_write_raw(struct iio_dev *indio_dev,
        }
        mutex_unlock(&chip->lock);
 
-       return 0;
+       return ret;
 }
 
 static int isl29018_read_raw(struct iio_dev *indio_dev,
index 954ca2c172c6414f55088cfb647404f96f8863f3..3f72543b188f504313d1c6cd65032d240f351ec2 100644 (file)
@@ -652,7 +652,7 @@ static int tsl2563_write_interrupt_config(struct iio_dev *indio_dev,
        }
 
        if (!state && (chip->intr & 0x30)) {
-               chip->intr |= ~0x30;
+               chip->intr &= ~0x30;
                ret = i2c_smbus_write_byte_data(chip->client,
                                                TSL2563_CMD | TSL2563_REG_INT,
                                                chip->intr);
@@ -814,7 +814,7 @@ static int __devexit tsl2563_remove(struct i2c_client *client)
        if (!chip->int_enabled)
                cancel_delayed_work(&chip->poweroff_work);
        /* Ensure that interrupts are disabled - then flush any bottom halves */
-       chip->intr |= ~0x30;
+       chip->intr &= ~0x30;
        i2c_smbus_write_byte_data(chip->client, TSL2563_CMD | TSL2563_REG_INT,
                                  chip->intr);
        flush_scheduled_work();
index 0270405691803339f143879cd6a1a7eb1b933141..f3eea18fdf469eae212fed06af0f84496cc94324 100644 (file)
@@ -195,7 +195,7 @@ bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev,
 #else /* CONFIG_IIO_BUFFER */
 
 static inline int iio_buffer_register(struct iio_dev *indio_dev,
-                                          struct iio_chan_spec *channels,
+                                          const struct iio_chan_spec *channels,
                                           int num_channels)
 {
        return 0;
index adca93a999a747329ed0e3aaa497f9eea4a3cdd9..da8c776ba0bdd0415bb6714903275d9e1baac362 100644 (file)
@@ -620,6 +620,9 @@ static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev)
 };
 #endif
 
+int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer,
+       int *fract);
+
 /**
  * IIO_DEGREE_TO_RAD() - Convert degree to rad
  * @deg: A value in degree
diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h
new file mode 100644 (file)
index 0000000..ff781dc
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Common library for ADIS16XXX devices
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *   Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __IIO_ADIS_H__
+#define __IIO_ADIS_H__
+
+#include <linux/spi/spi.h>
+#include <linux/interrupt.h>
+#include <linux/iio/types.h>
+
+#define ADIS_WRITE_REG(reg) ((0x80 | (reg)))
+#define ADIS_READ_REG(reg) ((reg) & 0x7f)
+
+#define ADIS_PAGE_SIZE 0x80
+#define ADIS_REG_PAGE_ID 0x00
+
+struct adis;
+
+/**
+ * struct adis_data - ADIS chip variant specific data
+ * @read_delay: SPI delay for read operations in us
+ * @write_delay: SPI delay for write operations in us
+ * @glob_cmd_reg: Register address of the GLOB_CMD register
+ * @msc_ctrl_reg: Register address of the MSC_CTRL register
+ * @diag_stat_reg: Register address of the DIAG_STAT register
+ * @status_error_msgs: Array of error messgaes
+ * @status_error_mask:
+ */
+struct adis_data {
+       unsigned int read_delay;
+       unsigned int write_delay;
+
+       unsigned int glob_cmd_reg;
+       unsigned int msc_ctrl_reg;
+       unsigned int diag_stat_reg;
+
+       unsigned int self_test_mask;
+       unsigned int startup_delay;
+
+       const char * const *status_error_msgs;
+       unsigned int status_error_mask;
+
+       int (*enable_irq)(struct adis *adis, bool enable);
+
+       bool has_paging;
+};
+
+struct adis {
+       struct spi_device       *spi;
+       struct iio_trigger      *trig;
+
+       const struct adis_data  *data;
+
+       struct mutex            txrx_lock;
+       struct spi_message      msg;
+       struct spi_transfer     *xfer;
+       unsigned int            current_page;
+       void                    *buffer;
+
+       uint8_t                 tx[10] ____cacheline_aligned;
+       uint8_t                 rx[4];
+};
+
+int adis_init(struct adis *adis, struct iio_dev *indio_dev,
+       struct spi_device *spi, const struct adis_data *data);
+int adis_reset(struct adis *adis);
+
+int adis_write_reg(struct adis *adis, unsigned int reg,
+       unsigned int val, unsigned int size);
+int adis_read_reg(struct adis *adis, unsigned int reg,
+       unsigned int *val, unsigned int size);
+
+/**
+ * adis_write_reg_8() - Write single byte to a register
+ * @adis: The adis device
+ * @reg: The address of the register to be written
+ * @value: The value to write
+ */
+static inline int adis_write_reg_8(struct adis *adis, unsigned int reg,
+       uint8_t val)
+{
+       return adis_write_reg(adis, reg, val, 1);
+}
+
+/**
+ * adis_write_reg_16() - Write 2 bytes to a pair of registers
+ * @adis: The adis device
+ * @reg: The address of the lower of the two registers
+ * @value: Value to be written
+ */
+static inline int adis_write_reg_16(struct adis *adis, unsigned int reg,
+       uint16_t val)
+{
+       return adis_write_reg(adis, reg, val, 2);
+}
+
+/**
+ * adis_write_reg_32() - write 4 bytes to four registers
+ * @adis: The adis device
+ * @reg: The address of the lower of the four register
+ * @value: Value to be written
+ */
+static inline int adis_write_reg_32(struct adis *adis, unsigned int reg,
+       uint32_t val)
+{
+       return adis_write_reg(adis, reg, val, 4);
+}
+
+/**
+ * adis_read_reg_16() - read 2 bytes from a 16-bit register
+ * @adis: The adis device
+ * @reg: The address of the lower of the two registers
+ * @val: The value read back from the device
+ */
+static inline int adis_read_reg_16(struct adis *adis, unsigned int reg,
+       uint16_t *val)
+{
+       unsigned int tmp;
+       int ret;
+
+       ret = adis_read_reg(adis, reg, &tmp, 2);
+       *val = tmp;
+
+       return ret;
+}
+
+/**
+ * adis_read_reg_32() - read 4 bytes from a 32-bit register
+ * @adis: The adis device
+ * @reg: The address of the lower of the two registers
+ * @val: The value read back from the device
+ */
+static inline int adis_read_reg_32(struct adis *adis, unsigned int reg,
+       uint32_t *val)
+{
+       unsigned int tmp;
+       int ret;
+
+       ret = adis_read_reg(adis, reg, &tmp, 4);
+       *val = tmp;
+
+       return ret;
+}
+
+int adis_enable_irq(struct adis *adis, bool enable);
+int adis_check_status(struct adis *adis);
+
+int adis_initial_startup(struct adis *adis);
+
+int adis_single_conversion(struct iio_dev *indio_dev,
+       const struct iio_chan_spec *chan, unsigned int error_mask,
+       int *val);
+
+#define ADIS_VOLTAGE_CHAN(addr, si, chan, name, bits) { \
+       .type = IIO_VOLTAGE, \
+       .indexed = 1, \
+       .channel = (chan), \
+       .extend_name = name, \
+       .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+               IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+       .address = (addr), \
+       .scan_index = (si), \
+       .scan_type = { \
+               .sign = 'u', \
+               .realbits = (bits), \
+               .storagebits = 16, \
+               .endianness = IIO_BE, \
+       }, \
+}
+
+#define ADIS_SUPPLY_CHAN(addr, si, bits) \
+       ADIS_VOLTAGE_CHAN(addr, si, 0, "supply", bits)
+
+#define ADIS_AUX_ADC_CHAN(addr, si, bits) \
+       ADIS_VOLTAGE_CHAN(addr, si, 1, NULL, bits)
+
+#define ADIS_TEMP_CHAN(addr, si, bits) { \
+       .type = IIO_TEMP, \
+       .indexed = 1, \
+       .channel = 0, \
+       .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+               IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
+               IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, \
+       .address = (addr), \
+       .scan_index = (si), \
+       .scan_type = { \
+               .sign = 'u', \
+               .realbits = (bits), \
+               .storagebits = 16, \
+               .endianness = IIO_BE, \
+       }, \
+}
+
+#define ADIS_MOD_CHAN(_type, mod, addr, si, info, bits) { \
+       .type = (_type), \
+       .modified = 1, \
+       .channel2 = IIO_MOD_ ## mod, \
+       .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+                IIO_CHAN_INFO_SCALE_SHARED_BIT | \
+                info, \
+       .address = (addr), \
+       .scan_index = (si), \
+       .scan_type = { \
+               .sign = 's', \
+               .realbits = (bits), \
+               .storagebits = 16, \
+               .endianness = IIO_BE, \
+       }, \
+}
+
+#define ADIS_ACCEL_CHAN(mod, addr, si, info, bits) \
+       ADIS_MOD_CHAN(IIO_ACCEL, mod, addr, si, info, bits)
+
+#define ADIS_GYRO_CHAN(mod, addr, si, info, bits) \
+       ADIS_MOD_CHAN(IIO_ANGL_VEL, mod, addr, si, info, bits)
+
+#define ADIS_INCLI_CHAN(mod, addr, si, info, bits) \
+       ADIS_MOD_CHAN(IIO_INCLI, mod, addr, si, info, bits)
+
+#define ADIS_ROT_CHAN(mod, addr, si, info, bits) \
+       ADIS_MOD_CHAN(IIO_ROT, mod, addr, si, info, bits)
+
+#ifdef CONFIG_IIO_ADIS_LIB_BUFFER
+
+int adis_setup_buffer_and_trigger(struct adis *adis,
+       struct iio_dev *indio_dev, irqreturn_t (*trigger_handler)(int, void *));
+void adis_cleanup_buffer_and_trigger(struct adis *adis,
+       struct iio_dev *indio_dev);
+
+int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev);
+void adis_remove_trigger(struct adis *adis);
+
+int adis_update_scan_mode(struct iio_dev *indio_dev,
+       const unsigned long *scan_mask);
+
+#else /* CONFIG_IIO_BUFFER */
+
+static inline int adis_setup_buffer_and_trigger(struct adis *adis,
+       struct iio_dev *indio_dev, irqreturn_t (*trigger_handler)(int, void *))
+{
+       return 0;
+}
+
+static inline void adis_cleanup_buffer_and_trigger(struct adis *adis,
+       struct iio_dev *indio_dev)
+{
+}
+
+static inline int adis_probe_trigger(struct adis *adis,
+       struct iio_dev *indio_dev)
+{
+       return 0;
+}
+
+static inline void adis_remove_trigger(struct adis *adis)
+{
+}
+
+#define adis_update_scan_mode NULL
+
+#endif /* CONFIG_IIO_BUFFER */
+
+#ifdef CONFIG_DEBUG_FS
+
+int adis_debugfs_reg_access(struct iio_dev *indio_dev,
+       unsigned int reg, unsigned int writeval, unsigned int *readval);
+
+#else
+
+#define adis_debugfs_reg_access NULL
+
+#endif
+
+#endif
index 87b196a2d69839ac5a5e2b2cf40d44877bb42fa4..88bf0f0d27b4a973b6b211b06ececfd294c82c4c 100644 (file)
@@ -28,6 +28,7 @@ enum iio_chan_type {
        IIO_CAPACITANCE,
        IIO_ALTVOLTAGE,
        IIO_CCT,
+       IIO_PRESSURE,
 };
 
 enum iio_modifier {
diff --git a/include/linux/platform_data/ad7298.h b/include/linux/platform_data/ad7298.h
new file mode 100644 (file)
index 0000000..fbf8adf
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * AD7298 SPI ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef __LINUX_PLATFORM_DATA_AD7298_H__
+#define __LINUX_PLATFORM_DATA_AD7298_H__
+
+/**
+ * struct ad7298_platform_data - Platform data for the ad7298 ADC driver
+ * @ext_ref: Whether to use an external reference voltage.
+ **/
+struct ad7298_platform_data {
+       bool ext_ref;
+};
+
+#endif /* IIO_ADC_AD7298_H_ */