Browse Source

Merge tag 'iio-for-3.8e' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next

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!"
Greg Kroah-Hartman 12 years ago
parent
commit
3ce14acb90
64 changed files with 3366 additions and 4649 deletions
  1. 24 0
      Documentation/ABI/testing/sysfs-bus-iio
  2. 4 3
      drivers/iio/Kconfig
  3. 4 3
      drivers/iio/Makefile
  4. 3 3
      drivers/iio/accel/hid-sensor-accel-3d.c
  5. 12 0
      drivers/iio/adc/Kconfig
  6. 1 0
      drivers/iio/adc/Makefile
  7. 160 41
      drivers/iio/adc/ad7298.c
  8. 1 1
      drivers/iio/common/hid-sensors/Kconfig
  9. 2 4
      drivers/iio/common/hid-sensors/hid-sensor-trigger.c
  10. 9 0
      drivers/iio/gyro/Kconfig
  11. 1 0
      drivers/iio/gyro/Makefile
  12. 581 0
      drivers/iio/gyro/adis16136.c
  13. 3 3
      drivers/iio/gyro/hid-sensor-gyro-3d.c
  14. 27 0
      drivers/iio/imu/Kconfig
  15. 10 0
      drivers/iio/imu/Makefile
  16. 440 0
      drivers/iio/imu/adis.c
  17. 925 0
      drivers/iio/imu/adis16480.c
  18. 176 0
      drivers/iio/imu/adis_buffer.c
  19. 89 0
      drivers/iio/imu/adis_trigger.c
  20. 64 35
      drivers/iio/industrialio-core.c
  21. 1 6
      drivers/iio/industrialio-event.c
  22. 2 3
      drivers/iio/light/hid-sensor-als.c
  23. 3 3
      drivers/iio/magnetometer/hid-sensor-magn-3d.c
  24. 11 10
      drivers/staging/iio/accel/Kconfig
  25. 0 5
      drivers/staging/iio/accel/Makefile
  26. 7 82
      drivers/staging/iio/accel/adis16201.h
  27. 61 405
      drivers/staging/iio/accel/adis16201_core.c
  28. 0 136
      drivers/staging/iio/accel/adis16201_ring.c
  29. 0 71
      drivers/staging/iio/accel/adis16201_trigger.c
  30. 7 73
      drivers/staging/iio/accel/adis16203.h
  31. 58 368
      drivers/staging/iio/accel/adis16203_core.c
  32. 0 136
      drivers/staging/iio/accel/adis16203_ring.c
  33. 0 73
      drivers/staging/iio/accel/adis16203_trigger.c
  34. 7 72
      drivers/staging/iio/accel/adis16204.h
  35. 62 390
      drivers/staging/iio/accel/adis16204_core.c
  36. 0 134
      drivers/staging/iio/accel/adis16204_ring.c
  37. 0 73
      drivers/staging/iio/accel/adis16204_trigger.c
  38. 5 72
      drivers/staging/iio/accel/adis16209.h
  39. 67 417
      drivers/staging/iio/accel/adis16209_core.c
  40. 0 134
      drivers/staging/iio/accel/adis16209_ring.c
  41. 0 72
      drivers/staging/iio/accel/adis16209_trigger.c
  42. 10 10
      drivers/staging/iio/accel/adis16220.h
  43. 50 230
      drivers/staging/iio/accel/adis16220_core.c
  44. 9 76
      drivers/staging/iio/accel/adis16240.h
  45. 66 407
      drivers/staging/iio/accel/adis16240_core.c
  46. 0 132
      drivers/staging/iio/accel/adis16240_ring.c
  47. 0 73
      drivers/staging/iio/accel/adis16240_trigger.c
  48. 0 11
      drivers/staging/iio/adc/Kconfig
  49. 0 4
      drivers/staging/iio/adc/Makefile
  50. 0 75
      drivers/staging/iio/adc/ad7298.h
  51. 0 113
      drivers/staging/iio/adc/ad7298_ring.c
  52. 1 1
      drivers/staging/iio/adc/adt7410.c
  53. 0 1
      drivers/staging/iio/gyro/Makefile
  54. 13 71
      drivers/staging/iio/gyro/adis16260.h
  55. 82 402
      drivers/staging/iio/gyro/adis16260_core.c
  56. 0 136
      drivers/staging/iio/gyro/adis16260_ring.c
  57. 0 75
      drivers/staging/iio/gyro/adis16260_trigger.c
  58. 1 1
      drivers/staging/iio/light/isl29018.c
  59. 2 2
      drivers/staging/iio/light/tsl2563.c
  60. 1 1
      include/linux/iio/buffer.h
  61. 3 0
      include/linux/iio/iio.h
  62. 280 0
      include/linux/iio/imu/adis.h
  63. 1 0
      include/linux/iio/types.h
  64. 20 0
      include/linux/platform_data/ad7298.h

+ 24 - 0
Documentation/ABI/testing/sysfs-bus-iio

@@ -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:

+ 4 - 3
drivers/iio/Kconfig

@@ -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

+ 4 - 3
drivers/iio/Makefile

@@ -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/

+ 3 - 3
drivers/iio/accel/hid-sensor-accel-3d.c

@@ -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;
 	}

+ 12 - 0
drivers/iio/adc/Kconfig

@@ -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

+ 1 - 0
drivers/iio/adc/Makefile

@@ -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

+ 160 - 41
drivers/staging/iio/adc/ad7298_core.c → drivers/iio/adc/ad7298.c

@@ -15,12 +15,48 @@
 #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 "ad7298.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)						\
 	{								\
@@ -35,6 +71,7 @@
 			.sign = 'u',					\
 			.realbits = 12,					\
 			.storagebits = 16,				\
+			.endianness = IIO_BE,				\
 		},							\
 	}
 
@@ -44,7 +81,8 @@ static const struct iio_chan_spec ad7298_channels[] = {
 		.indexed = 1,
 		.channel = 0,
 		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+			IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+			IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
 		.address = AD7298_CH_TEMP,
 		.scan_index = -1,
 		.scan_type = {
@@ -64,6 +102,84 @@ static const struct iio_chan_spec ad7298_channels[] = {
 	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;
@@ -79,7 +195,7 @@ static int ad7298_scan_direct(struct ad7298_state *st, unsigned ch)
 
 static int ad7298_scan_temp(struct ad7298_state *st, int *val)
 {
-	int tmp, ret;
+	int ret;
 	__be16 buf;
 
 	buf = cpu_to_be16(AD7298_WRITE | AD7298_TSENSE |
@@ -101,24 +217,24 @@ static int ad7298_scan_temp(struct ad7298_state *st, int *val)
 	if (ret)
 		return ret;
 
-	tmp = be16_to_cpu(buf) & RES_MASK(AD7298_BITS);
+	*val = sign_extend32(be16_to_cpu(buf), 11);
 
-	/*
-	 * One LSB of the ADC corresponds to 0.25 deg C.
-	 * The temperature reading is in 12-bit twos complement format
-	 */
+	return 0;
+}
 
-	if (tmp & (1 << (AD7298_BITS - 1))) {
-		tmp = (4096 - tmp) * 250;
-		tmp -= (2 * tmp);
+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 {
-		tmp *= 250; /* temperature in milli degrees Celsius */
+		return AD7298_INTREF_mV;
 	}
-
-	*val = tmp;
-
-	return 0;
 }
 
 static int ad7298_read_raw(struct iio_dev *indio_dev,
@@ -129,7 +245,6 @@ static int ad7298_read_raw(struct iio_dev *indio_dev,
 {
 	int ret;
 	struct ad7298_state *st = iio_priv(indio_dev);
-	unsigned int scale_uv;
 
 	switch (m) {
 	case IIO_CHAN_INFO_RAW:
@@ -154,17 +269,19 @@ static int ad7298_read_raw(struct iio_dev *indio_dev,
 	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;
+			*val = ad7298_get_ref_voltage(st);
+			*val2 = chan->scan_type.realbits;
+			return IIO_VAL_FRACTIONAL_LOG2;
 		case IIO_TEMP:
-			*val =  1;
-			*val2 = 0;
-			return IIO_VAL_INT_PLUS_MICRO;
+			*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;
 }
@@ -179,16 +296,23 @@ 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));
+	int ret;
 
 	if (indio_dev == NULL)
 		return -ENOMEM;
 
 	st = iio_priv(indio_dev);
 
-	st->reg = regulator_get(&spi->dev, "vcc");
-	if (!IS_ERR(st->reg)) {
+	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;
@@ -221,14 +345,8 @@ static int __devinit ad7298_probe(struct spi_device *spi)
 	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);
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+			&ad7298_trigger_handler, NULL);
 	if (ret)
 		goto error_disable_reg;
 
@@ -239,13 +357,14 @@ static int __devinit ad7298_probe(struct spi_device *spi)
 	return 0;
 
 error_cleanup_ring:
-	ad7298_ring_cleanup(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
 error_disable_reg:
-	if (!IS_ERR(st->reg))
+	if (st->ext_ref)
 		regulator_disable(st->reg);
 error_put_reg:
-	if (!IS_ERR(st->reg))
+	if (st->ext_ref)
 		regulator_put(st->reg);
+error_free:
 	iio_device_free(indio_dev);
 
 	return ret;
@@ -257,8 +376,8 @@ static int __devexit ad7298_remove(struct spi_device *spi)
 	struct ad7298_state *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	ad7298_ring_cleanup(indio_dev);
-	if (!IS_ERR(st->reg)) {
+	iio_triggered_buffer_cleanup(indio_dev);
+	if (st->ext_ref) {
 		regulator_disable(st->reg);
 		regulator_put(st->reg);
 	}

+ 1 - 1
drivers/iio/common/hid-sensors/Kconfig

@@ -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

+ 2 - 4
drivers/iio/common/hid-sensors/hid-sensor-trigger.c

@@ -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,

+ 9 - 0
drivers/iio/gyro/Kconfig

@@ -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

+ 1 - 0
drivers/iio/gyro/Makefile

@@ -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

+ 581 - 0
drivers/iio/gyro/adis16136.c

@@ -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");

+ 3 - 3
drivers/iio/gyro/hid-sensor-gyro-3d.c

@@ -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;
 	}

+ 27 - 0
drivers/iio/imu/Kconfig

@@ -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.

+ 10 - 0
drivers/iio/imu/Makefile

@@ -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

+ 440 - 0
drivers/iio/imu/adis.c

@@ -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");

+ 925 - 0
drivers/iio/imu/adis16480.c

@@ -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");

+ 176 - 0
drivers/iio/imu/adis_buffer.c

@@ -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);

+ 89 - 0
drivers/iio/imu/adis_trigger.c

@@ -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);

+ 64 - 35
drivers/iio/industrialio-core.c

@@ -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);

+ 1 - 6
drivers/iio/industrialio-event.c

@@ -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)

+ 2 - 3
drivers/iio/light/hid-sensor-als.c

@@ -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;
 	}

+ 3 - 3
drivers/iio/magnetometer/hid-sensor-magn-3d.c

@@ -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;
 	}

+ 11 - 10
drivers/staging/iio/accel/Kconfig

@@ -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.

+ 0 - 5
drivers/staging/iio/accel/Makefile

@@ -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

+ 7 - 82
drivers/staging/iio/accel/adis16201.h

@@ -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 */
@@ -47,95 +42,25 @@
 /* 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_ */

+ 61 - 405
drivers/staging/iio/accel/adis16201_core.c

@@ -18,258 +18,15 @@
 #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;

+ 0 - 136
drivers/staging/iio/accel/adis16201_ring.c

@@ -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;
-}

+ 0 - 71
drivers/staging/iio/accel/adis16201_trigger.c

@@ -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);
-}

+ 7 - 73
drivers/staging/iio/accel/adis16203.h

@@ -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 */
@@ -40,86 +35,25 @@
 /* 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_ */

+ 58 - 368
drivers/staging/iio/accel/adis16203_core.c

@@ -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.
  */
@@ -18,252 +18,14 @@
 #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;

+ 0 - 136
drivers/staging/iio/accel/adis16203_ring.c

@@ -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;
-}

+ 0 - 73
drivers/staging/iio/accel/adis16203_trigger.c

@@ -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);
-}

+ 7 - 72
drivers/staging/iio/accel/adis16204.h

@@ -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 */
@@ -47,87 +42,27 @@
 /* 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_ */

+ 62 - 390
drivers/staging/iio/accel/adis16204_core.c

@@ -21,259 +21,16 @@
 #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;

+ 0 - 134
drivers/staging/iio/accel/adis16204_ring.c

@@ -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;
-}

+ 0 - 73
drivers/staging/iio/accel/adis16204_trigger.c

@@ -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);
-}

+ 5 - 72
drivers/staging/iio/accel/adis16209.h

@@ -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)
@@ -81,44 +76,23 @@
 /* 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_ */

+ 67 - 417
drivers/staging/iio/accel/adis16209_core.c

@@ -19,260 +19,19 @@
 #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;

+ 0 - 134
drivers/staging/iio/accel/adis16209_ring.c

@@ -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;
-}

+ 0 - 72
drivers/staging/iio/accel/adis16209_trigger.c

@@ -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);
-}

+ 10 - 10
drivers/staging/iio/accel/adis16220.h

@@ -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
@@ -102,15 +101,15 @@
 #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)
@@ -125,13 +124,14 @@
 
 /**
  * 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];

+ 50 - 230
drivers/staging/iio/accel/adis16220_core.c

@@ -20,136 +20,19 @@
 
 #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;

+ 9 - 76
drivers/staging/iio/accel/adis16240.h

@@ -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)
@@ -101,17 +96,17 @@
 /* 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)
@@ -120,77 +115,15 @@
 
 #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_ */

+ 66 - 407
drivers/staging/iio/accel/adis16240_core.c

@@ -22,149 +22,29 @@
 #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;

+ 0 - 132
drivers/staging/iio/accel/adis16240_ring.c

@@ -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;
-}

+ 0 - 73
drivers/staging/iio/accel/adis16240_trigger.c

@@ -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);
-}

+ 0 - 11
drivers/staging/iio/adc/Kconfig

@@ -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

+ 0 - 4
drivers/staging/iio/adc/Makefile

@@ -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

+ 0 - 75
drivers/staging/iio/adc/ad7298.h

@@ -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_ */

+ 0 - 113
drivers/staging/iio/adc/ad7298_ring.c

@@ -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);
-}

+ 1 - 1
drivers/staging/iio/adc/adt7410.c

@@ -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,

+ 0 - 1
drivers/staging/iio/gyro/Makefile

@@ -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

+ 13 - 71
drivers/staging/iio/gyro/adis16260.h

@@ -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)
 
@@ -60,13 +57,13 @@
 /* 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)
@@ -75,82 +72,27 @@
 #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_ */

+ 82 - 402
drivers/staging/iio/gyro/adis16260_core.c

@@ -24,132 +24,13 @@
 
 #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;

+ 0 - 136
drivers/staging/iio/gyro/adis16260_ring.c

@@ -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;
-}

+ 0 - 75
drivers/staging/iio/gyro/adis16260_trigger.c

@@ -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);
-}

+ 1 - 1
drivers/staging/iio/light/isl29018.c

@@ -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,

+ 2 - 2
drivers/staging/iio/light/tsl2563.c

@@ -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();

+ 1 - 1
include/linux/iio/buffer.h

@@ -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;

+ 3 - 0
include/linux/iio/iio.h

@@ -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

+ 280 - 0
include/linux/iio/imu/adis.h

@@ -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

+ 1 - 0
include/linux/iio/types.h

@@ -28,6 +28,7 @@ enum iio_chan_type {
 	IIO_CAPACITANCE,
 	IIO_ALTVOLTAGE,
 	IIO_CCT,
+	IIO_PRESSURE,
 };
 
 enum iio_modifier {

+ 20 - 0
include/linux/platform_data/ad7298.h

@@ -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_ */