All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/11] staging:iio: Add common ADIS library
@ 2012-11-13 13:28 Lars-Peter Clausen
  2012-11-13 13:28 ` [PATCH 02/11] staging:iio:adis16201: Use adis library Lars-Peter Clausen
                   ` (10 more replies)
  0 siblings, 11 replies; 13+ messages in thread
From: Lars-Peter Clausen @ 2012-11-13 13:28 UTC (permalink / raw)
  To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen

A lot of the devices from the ADIS family use the same methods for accessing
registers, sampling data and trigger handling. They also have similar register
layout for the control registers.

This patch adds a common library for these devices. The library implements
functions for reading and writing registers as buffer and trigger management. It
also provides a set functions for accessing the control registers and for
running the devices internal self-test. Having this common library code will
allow us to remove a lot of duplicated code.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/staging/iio/imu/Kconfig        |  13 ++
 drivers/staging/iio/imu/Makefile       |   5 +
 drivers/staging/iio/imu/adis.c         | 338 +++++++++++++++++++++++++++++++++
 drivers/staging/iio/imu/adis.h         | 178 +++++++++++++++++
 drivers/staging/iio/imu/adis_buffer.c  | 200 +++++++++++++++++++
 drivers/staging/iio/imu/adis_trigger.c |  90 +++++++++
 6 files changed, 824 insertions(+)
 create mode 100644 drivers/staging/iio/imu/adis.c
 create mode 100644 drivers/staging/iio/imu/adis.h
 create mode 100644 drivers/staging/iio/imu/adis_buffer.c
 create mode 100644 drivers/staging/iio/imu/adis_trigger.c

diff --git a/drivers/staging/iio/imu/Kconfig b/drivers/staging/iio/imu/Kconfig
index 2c2f47d..89b9f25 100644
--- a/drivers/staging/iio/imu/Kconfig
+++ b/drivers/staging/iio/imu/Kconfig
@@ -15,3 +15,16 @@ config ADIS16400
 	  (adis16400 series also have magnetometers).
 
 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_TRIGGER
+	select IIO_SW_RING
+	help
+	  A set of buffer helper functions for the Analog Devices ADIS* device
+	  family.
diff --git a/drivers/staging/iio/imu/Makefile b/drivers/staging/iio/imu/Makefile
index 3400a13..65dafba 100644
--- a/drivers/staging/iio/imu/Makefile
+++ b/drivers/staging/iio/imu/Makefile
@@ -5,3 +5,8 @@
 adis16400-y             := adis16400_core.o
 adis16400-$(CONFIG_IIO_BUFFER) += adis16400_ring.o adis16400_trigger.o
 obj-$(CONFIG_ADIS16400) += adis16400.o
+
+adis_lib-y += adis.o
+adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o
+adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
+obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
diff --git a/drivers/staging/iio/imu/adis.c b/drivers/staging/iio/imu/adis.c
new file mode 100644
index 0000000..0bd21022
--- /dev/null
+++ b/drivers/staging/iio/imu/adis.c
@@ -0,0 +1,338 @@
+/*
+ * 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 "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)
+
+/**
+ * adis_write_reg_8() - Write single byte to a register
+ * @adis: The adis device
+ * @reg: The address of the register to be written
+ * @val: The value to write
+ */
+int adis_write_reg_8(struct adis *adis, unsigned int reg, uint8_t val)
+{
+	int ret;
+
+	mutex_lock(&adis->txrx_lock);
+	adis->tx[0] = ADIS_WRITE_REG(reg);
+	adis->tx[1] = val;
+
+	ret = spi_write(adis->spi, adis->tx, 2);
+	mutex_unlock(&adis->txrx_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(adis_write_reg_8);
+
+/**
+ * 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
+ * @val: Value to be written
+ */
+int adis_write_reg_16(struct adis *adis, unsigned int reg, uint16_t value)
+{
+	int ret;
+	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,
+			.delay_usecs = adis->data->write_delay,
+		},
+	};
+
+	mutex_lock(&adis->txrx_lock);
+	adis->tx[0] = ADIS_WRITE_REG(reg);
+	adis->tx[1] = value & 0xff;
+	adis->tx[2] = ADIS_WRITE_REG(reg + 1);
+	adis->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(adis->spi, &msg);
+	mutex_unlock(&adis->txrx_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(adis_write_reg_16);
+
+/**
+ * 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
+ */
+int adis_read_reg_16(struct adis *adis, unsigned int reg, uint16_t *val)
+{
+	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->read_delay,
+		}, {
+			.rx_buf = adis->rx,
+			.bits_per_word = 8,
+			.len = 2,
+			.delay_usecs = adis->data->read_delay,
+		},
+	};
+
+	mutex_lock(&adis->txrx_lock);
+	adis->tx[0] = ADIS_READ_REG(reg);
+	adis->tx[1] = 0;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfers[0], &msg);
+	spi_message_add_tail(&xfers[1], &msg);
+	ret = spi_sync(adis->spi, &msg);
+	if (ret) {
+		dev_err(&adis->spi->dev, "Failed to read 16 bit register 0x%02X: %d\n",
+				reg, ret);
+		goto error_ret;
+	}
+	*val = get_unaligned_be16(adis->rx);
+
+error_ret:
+	mutex_unlock(&adis->txrx_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(adis_read_reg_16);
+
+/**
+ * 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;
+
+	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);
+	uint16_t val16;
+	int ret;
+
+	mutex_lock(&indio_dev->mlock);
+
+	ret = adis_read_reg_16(adis, chan->address, &val16);
+	if (ret)
+		goto err_unlock;
+
+	if (val16 & error_mask) {
+		ret = adis_check_status(adis);
+		if (ret)
+			goto err_unlock;
+	}
+
+	if (chan->scan_type.sign == 's')
+		*val = sign_extend32(val16, chan->scan_type.realbits - 1);
+	else
+		*val = val16 & ((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);
+
+	return adis_enable_irq(adis, false);
+}
+EXPORT_SYMBOL_GPL(adis_init);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Common library code for ADIS16XXX devices");
diff --git a/drivers/staging/iio/imu/adis.h b/drivers/staging/iio/imu/adis.h
new file mode 100644
index 0000000..c84da7a
--- /dev/null
+++ b/drivers/staging/iio/imu/adis.h
@@ -0,0 +1,178 @@
+/*
+ * 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)
+
+/**
+ * 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;
+};
+
+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;
+	void			*buffer;
+
+	uint8_t			tx[8] ____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_8(struct adis *adis, unsigned int reg, uint8_t val);
+int adis_write_reg_16(struct adis *adis, unsigned int reg, uint16_t val);
+int adis_read_reg_16(struct adis *adis, unsigned int reg, uint16_t *val);
+
+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, \
+	}, \
+}
+
+#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, \
+	}, \
+}
+
+#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, \
+	}, \
+}
+
+#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);
+
+#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)
+{
+}
+
+#endif /* CONFIG_IIO_BUFFER */
+
+#endif
diff --git a/drivers/staging/iio/imu/adis_buffer.c b/drivers/staging/iio/imu/adis_buffer.c
new file mode 100644
index 0000000..47bdea0
--- /dev/null
+++ b/drivers/staging/iio/imu/adis_buffer.c
@@ -0,0 +1,200 @@
+#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 "../ring_sw.h"
+#include <linux/iio/trigger_consumer.h>
+
+#include  "adis.h"
+
+#define ADIS_MAX_OUTPUTS 12
+
+static int adis_read_buffer_data(struct adis *adis, struct iio_dev *indio_dev)
+{
+	int n_outputs = indio_dev->num_channels;
+	struct spi_transfer xfers[ADIS_MAX_OUTPUTS + 1];
+	struct spi_message msg;
+	int ret;
+	int i;
+
+	mutex_lock(&adis->txrx_lock);
+
+	spi_message_init(&msg);
+
+	memset(xfers, 0, sizeof(xfers));
+	for (i = 0; i <= n_outputs; i++) {
+		xfers[i].bits_per_word = 8;
+		xfers[i].cs_change = 1;
+		xfers[i].len = 2;
+		xfers[i].delay_usecs = adis->data->read_delay;
+		if (i < n_outputs) {
+			xfers[i].tx_buf = adis->tx + 2 * i;
+			adis->tx[2 * i] = indio_dev->channels[i].address;
+			adis->tx[2 * i + 1] = 0;
+		}
+		if (i >= 1)
+			xfers[i].rx_buf = adis->rx + 2 * (i - 1);
+		spi_message_add_tail(&xfers[i], &msg);
+	}
+
+	ret = spi_sync(adis->spi, &msg);
+	if (ret)
+		dev_err(&adis->spi->dev, "Failed to read data: %d", ret);
+
+	mutex_unlock(&adis->txrx_lock);
+
+	return ret;
+}
+
+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);
+	u16 *data;
+	int i = 0;
+
+	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+	if (data == NULL) {
+		dev_err(&adis->spi->dev, "Failed to allocate memory.");
+		return -ENOMEM;
+	}
+
+	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)
+	    && adis_read_buffer_data(adis, indio_dev) >= 0)
+		for (; i < bitmap_weight(indio_dev->active_scan_mask,
+					 indio_dev->masklength); i++)
+			data[i] = be16_to_cpup((__be16 *)&(adis->rx[i*2]));
+
+	/* Guaranteed to be aligned with 8 byte boundary */
+	if (indio_dev->scan_timestamp)
+		*((s64 *)(PTR_ALIGN(data, sizeof(s64)))) = pf->timestamp;
+
+	iio_push_to_buffers(indio_dev, (u8 *)data);
+
+	iio_trigger_notify_done(indio_dev->trig);
+	kfree(data);
+
+	return IRQ_HANDLED;
+}
+
+static const struct iio_buffer_setup_ops adis_buffer_setup_ops = {
+	.preenable = &iio_sw_buffer_preenable,
+	.postenable = &iio_triggered_buffer_postenable,
+	.predisable = &iio_triggered_buffer_predisable,
+};
+
+static int adis_buffer_setup(struct iio_dev *indio_dev,
+	irqreturn_t (*trigger_handler)(int, void *))
+{
+	int ret = 0;
+	struct iio_buffer *buffer;
+
+	if (!trigger_handler)
+		trigger_handler = &adis_trigger_handler;
+
+	buffer = iio_sw_rb_allocate(indio_dev);
+	if (!buffer) {
+		ret = -ENOMEM;
+		return ret;
+	}
+
+	indio_dev->buffer = buffer;
+	indio_dev->setup_ops = &adis_buffer_setup_ops;
+
+	indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
+						 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;
+}
+
+static void adis_buffer_cleanup(struct iio_dev *indio_dev)
+{
+	iio_dealloc_pollfunc(indio_dev->pollfunc);
+	iio_sw_rb_free(indio_dev->buffer);
+}
+
+/**
+ * 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;
+
+	ret = adis_buffer_setup(indio_dev, trigger_handler);
+	if (ret)
+		return ret;
+
+	ret = iio_buffer_register(indio_dev,
+				  indio_dev->channels,
+				  indio_dev->num_channels);
+	if (ret) {
+		dev_err(&adis->spi->dev, "Failed to initialize buffer %d\n",
+			ret);
+		goto error_unreg_buffer_funcs;
+	}
+
+	if (adis->spi->irq) {
+		ret = adis_probe_trigger(adis, indio_dev);
+		if (ret)
+			goto error_uninitialize_buffer;
+	}
+	return 0;
+
+error_uninitialize_buffer:
+	iio_buffer_unregister(indio_dev);
+error_unreg_buffer_funcs:
+	adis_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);
+	iio_buffer_unregister(indio_dev);
+	adis_buffer_cleanup(indio_dev);
+}
+EXPORT_SYMBOL_GPL(adis_cleanup_buffer_and_trigger);
diff --git a/drivers/staging/iio/imu/adis_trigger.c b/drivers/staging/iio/imu/adis_trigger.c
new file mode 100644
index 0000000..3e89b2e
--- /dev/null
+++ b/drivers/staging/iio/imu/adis_trigger.c
@@ -0,0 +1,90 @@
+/*
+ * 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 "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);
-- 
1.8.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 02/11] staging:iio:adis16201: Use adis library
  2012-11-13 13:28 [PATCH 01/11] staging:iio: Add common ADIS library Lars-Peter Clausen
@ 2012-11-13 13:28 ` Lars-Peter Clausen
  2012-11-13 13:28 ` [PATCH 03/11] staging:iio:adis16203: " Lars-Peter Clausen
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Lars-Peter Clausen @ 2012-11-13 13:28 UTC (permalink / raw)
  To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen

Use the new adis library for the adis16201 driver. This allows us to completely
scrap the adis16201 buffer and trigger code and more than half of the core
driver code.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/staging/iio/accel/Kconfig             |   4 +-
 drivers/staging/iio/accel/Makefile            |   1 -
 drivers/staging/iio/accel/adis16201.h         |  89 +----
 drivers/staging/iio/accel/adis16201_core.c    | 465 ++++----------------------
 drivers/staging/iio/accel/adis16201_ring.c    | 136 --------
 drivers/staging/iio/accel/adis16201_trigger.c |  71 ----
 6 files changed, 69 insertions(+), 697 deletions(-)
 delete mode 100644 drivers/staging/iio/accel/adis16201_ring.c
 delete mode 100644 drivers/staging/iio/accel/adis16201_trigger.c

diff --git a/drivers/staging/iio/accel/Kconfig b/drivers/staging/iio/accel/Kconfig
index 5ab7167..0e965e5 100644
--- a/drivers/staging/iio/accel/Kconfig
+++ b/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.
diff --git a/drivers/staging/iio/accel/Makefile b/drivers/staging/iio/accel/Makefile
index 95c6666..22dbebd 100644
--- a/drivers/staging/iio/accel/Makefile
+++ b/drivers/staging/iio/accel/Makefile
@@ -3,7 +3,6 @@
 #
 
 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
diff --git a/drivers/staging/iio/accel/adis16201.h b/drivers/staging/iio/accel/adis16201.h
index 72750f7..8747de5 100644
--- a/drivers/staging/iio/accel/adis16201.h
+++ b/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_ */
diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c
index d2a203a..0121501 100644
--- a/drivers/staging/iio/accel/adis16201_core.c
+++ b/drivers/staging/iio/accel/adis16201_core.c
@@ -20,256 +20,13 @@
 #include <linux/iio/buffer.h>
 
 #include "adis16201.h"
+#include "../imu/adis.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,111 +124,24 @@ 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)
 };
 
@@ -500,10 +151,33 @@ static const struct iio_info adis16201_info = {
 	.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 +190,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 +198,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 +226,10 @@ error_ret:
 static int __devexit adis16201_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct adis *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	adis16201_remove_trigger(indio_dev);
-	iio_buffer_unregister(indio_dev);
-	adis16201_unconfigure_ring(indio_dev);
+	adis_cleanup_buffer_and_trigger(st, indio_dev);
 	iio_device_free(indio_dev);
 
 	return 0;
diff --git a/drivers/staging/iio/accel/adis16201_ring.c b/drivers/staging/iio/accel/adis16201_ring.c
deleted file mode 100644
index e14ca60..0000000
--- a/drivers/staging/iio/accel/adis16201_ring.c
+++ /dev/null
@@ -1,136 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16201.h"
-
-
-/**
- * adis16201_read_ring_data() read data registers which will be placed into ring
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @rx: somewhere to pass back the value read
- **/
-static int adis16201_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-	struct spi_message msg;
-	struct adis16201_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[ADIS16201_OUTPUTS + 1];
-	int ret;
-	int i;
-
-	mutex_lock(&st->buf_lock);
-
-	spi_message_init(&msg);
-
-	memset(xfers, 0, sizeof(xfers));
-	for (i = 0; i <= ADIS16201_OUTPUTS; i++) {
-		xfers[i].bits_per_word = 8;
-		xfers[i].cs_change = 1;
-		xfers[i].len = 2;
-		xfers[i].delay_usecs = 20;
-		if (i < ADIS16201_OUTPUTS) {
-			xfers[i].tx_buf = st->tx + 2 * i;
-			st->tx[2 * i] = ADIS16201_READ_REG(ADIS16201_SUPPLY_OUT +
-							   2 * i);
-			st->tx[2 * i + 1] = 0;
-		}
-		if (i >= 1)
-			xfers[i].rx_buf = rx + 2 * (i - 1);
-		spi_message_add_tail(&xfers[i], &msg);
-	}
-
-	ret = spi_sync(st->us, &msg);
-	if (ret)
-		dev_err(&st->us->dev, "problem when burst reading");
-
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
- * specific to be rolled into the core.
- */
-static irqreturn_t adis16201_trigger_handler(int irq, void *p)
-{
-	struct iio_poll_func *pf = p;
-	struct iio_dev *indio_dev = pf->indio_dev;
-	struct adis16201_state *st = iio_priv(indio_dev);
-
-	int i = 0;
-	s16 *data;
-
-	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-	if (data == NULL) {
-		dev_err(&st->us->dev, "memory alloc failed in ring bh");
-		goto done;
-	}
-
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)
-	    && adis16201_read_ring_data(indio_dev, st->rx) >= 0)
-		for (; i < bitmap_weight(indio_dev->active_scan_mask,
-					 indio_dev->masklength); i++)
-			data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-	/* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp)
-		*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-	iio_push_to_buffers(indio_dev, (u8 *)data);
-
-	kfree(data);
-done:
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
-void adis16201_unconfigure_ring(struct iio_dev *indio_dev)
-{
-	iio_dealloc_pollfunc(indio_dev->pollfunc);
-	iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16201_ring_setup_ops = {
-	.preenable = &iio_sw_buffer_preenable,
-	.postenable = &iio_triggered_buffer_postenable,
-	.predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16201_configure_ring(struct iio_dev *indio_dev)
-{
-	int ret = 0;
-	struct iio_buffer *ring;
-
-	ring = iio_sw_rb_allocate(indio_dev);
-	if (!ring) {
-		ret = -ENOMEM;
-		return ret;
-	}
-	indio_dev->buffer = ring;
-	ring->scan_timestamp = true;
-	indio_dev->setup_ops = &adis16201_ring_setup_ops;
-
-	indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-						 &adis16201_trigger_handler,
-						 IRQF_ONESHOT,
-						 indio_dev,
-						 "adis16201_consumer%d",
-						 indio_dev->id);
-	if (indio_dev->pollfunc == NULL) {
-		ret = -ENOMEM;
-		goto error_iio_sw_rb_free;
-	}
-
-	indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-	return 0;
-error_iio_sw_rb_free:
-	iio_sw_rb_free(indio_dev->buffer);
-	return ret;
-}
diff --git a/drivers/staging/iio/accel/adis16201_trigger.c b/drivers/staging/iio/accel/adis16201_trigger.c
deleted file mode 100644
index 96fdabb..0000000
--- a/drivers/staging/iio/accel/adis16201_trigger.c
+++ /dev/null
@@ -1,71 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16201.h"
-
-/**
- * adis16201_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16201_data_rdy_trigger_set_state(struct iio_trigger *trig,
-						bool state)
-{
-	struct iio_dev *indio_dev = trig->private_data;
-
-	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	return adis16201_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16201_trigger_ops = {
-	.owner = THIS_MODULE,
-	.set_trigger_state = &adis16201_data_rdy_trigger_set_state,
-};
-
-int adis16201_probe_trigger(struct iio_dev *indio_dev)
-{
-	int ret;
-	struct adis16201_state *st = iio_priv(indio_dev);
-
-	st->trig = iio_trigger_alloc("adis16201-dev%d", indio_dev->id);
-	if (st->trig == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-	ret = request_irq(st->us->irq,
-			  &iio_trigger_generic_data_rdy_poll,
-			  IRQF_TRIGGER_RISING,
-			  "adis16201",
-			  st->trig);
-	if (ret)
-		goto error_free_trig;
-	st->trig->dev.parent = &st->us->dev;
-	st->trig->ops = &adis16201_trigger_ops;
-	st->trig->private_data = indio_dev;
-	ret = iio_trigger_register(st->trig);
-
-	/* select default trigger */
-	indio_dev->trig = st->trig;
-	if (ret)
-		goto error_free_irq;
-
-	return 0;
-
-error_free_irq:
-	free_irq(st->us->irq, st->trig);
-error_free_trig:
-	iio_trigger_free(st->trig);
-error_ret:
-	return ret;
-}
-
-void adis16201_remove_trigger(struct iio_dev *indio_dev)
-{
-	struct adis16201_state *state = iio_priv(indio_dev);
-
-	iio_trigger_unregister(state->trig);
-	free_irq(state->us->irq, state->trig);
-	iio_trigger_free(state->trig);
-}
-- 
1.8.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 03/11] staging:iio:adis16203: Use adis library
  2012-11-13 13:28 [PATCH 01/11] staging:iio: Add common ADIS library Lars-Peter Clausen
  2012-11-13 13:28 ` [PATCH 02/11] staging:iio:adis16201: Use adis library Lars-Peter Clausen
@ 2012-11-13 13:28 ` Lars-Peter Clausen
  2012-11-13 13:28 ` [PATCH 04/11] staging:iio:adis16204: " Lars-Peter Clausen
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Lars-Peter Clausen @ 2012-11-13 13:28 UTC (permalink / raw)
  To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen

Use the new adis library for the adis16203 driver. This allows us to completely
scrap the adis16203 buffer and trigger code and more than half of the core
driver code.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/staging/iio/accel/Kconfig             |   4 +-
 drivers/staging/iio/accel/Makefile            |   1 -
 drivers/staging/iio/accel/adis16203.h         |  80 +----
 drivers/staging/iio/accel/adis16203_core.c    | 425 ++++----------------------
 drivers/staging/iio/accel/adis16203_ring.c    | 136 ---------
 drivers/staging/iio/accel/adis16203_trigger.c |  73 -----
 6 files changed, 66 insertions(+), 653 deletions(-)
 delete mode 100644 drivers/staging/iio/accel/adis16203_ring.c
 delete mode 100644 drivers/staging/iio/accel/adis16203_trigger.c

diff --git a/drivers/staging/iio/accel/Kconfig b/drivers/staging/iio/accel/Kconfig
index 0e965e5..48755a2 100644
--- a/drivers/staging/iio/accel/Kconfig
+++ b/drivers/staging/iio/accel/Kconfig
@@ -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.
diff --git a/drivers/staging/iio/accel/Makefile b/drivers/staging/iio/accel/Makefile
index 22dbebd..28746b8 100644
--- a/drivers/staging/iio/accel/Makefile
+++ b/drivers/staging/iio/accel/Makefile
@@ -6,7 +6,6 @@ adis16201-y             := adis16201_core.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
diff --git a/drivers/staging/iio/accel/adis16203.h b/drivers/staging/iio/accel/adis16203.h
index 3f96ad3..acc688d 100644
--- a/drivers/staging/iio/accel/adis16203.h
+++ b/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_ */
diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c
index 7d7c4d2..326b106 100644
--- a/drivers/staging/iio/accel/adis16203_core.c
+++ b/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.
  */
@@ -20,250 +20,12 @@
 #include <linux/iio/buffer.h>
 
 #include "adis16203.h"
+#include "../imu/adis.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,75 +99,13 @@ 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),
 };
 
@@ -434,11 +115,36 @@ static const struct iio_info adis16203_info = {
 	.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 +155,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 +163,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 +193,10 @@ error_ret:
 static int __devexit adis16203_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct adis *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	adis16203_remove_trigger(indio_dev);
-	iio_buffer_unregister(indio_dev);
-	adis16203_unconfigure_ring(indio_dev);
+	adis_cleanup_buffer_and_trigger(st, indio_dev);
 	iio_device_free(indio_dev);
 
 	return 0;
diff --git a/drivers/staging/iio/accel/adis16203_ring.c b/drivers/staging/iio/accel/adis16203_ring.c
deleted file mode 100644
index eba2e28..0000000
--- a/drivers/staging/iio/accel/adis16203_ring.c
+++ /dev/null
@@ -1,136 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16203.h"
-
-/**
- * adis16203_read_ring_data() read data registers which will be placed into ring
- * @indio_dev: the IIO device
- * @rx: somewhere to pass back the value read
- **/
-static int adis16203_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-	struct spi_message msg;
-	struct adis16203_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[ADIS16203_OUTPUTS + 1];
-	int ret;
-	int i;
-
-	mutex_lock(&st->buf_lock);
-
-	spi_message_init(&msg);
-
-	memset(xfers, 0, sizeof(xfers));
-	for (i = 0; i <= ADIS16203_OUTPUTS; i++) {
-		xfers[i].bits_per_word = 8;
-		xfers[i].cs_change = 1;
-		xfers[i].len = 2;
-		xfers[i].delay_usecs = 20;
-		xfers[i].tx_buf = st->tx + 2 * i;
-		if (i < 1) /* SUPPLY_OUT: 0x02, AUX_ADC: 0x08 */
-			st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i);
-		else
-			st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i + 6);
-		st->tx[2 * i + 1] = 0;
-		if (i >= 1)
-			xfers[i].rx_buf = rx + 2 * (i - 1);
-		spi_message_add_tail(&xfers[i], &msg);
-	}
-
-	ret = spi_sync(st->us, &msg);
-	if (ret)
-		dev_err(&st->us->dev, "problem when burst reading");
-
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
- * specific to be rolled into the core.
- */
-static irqreturn_t adis16203_trigger_handler(int irq, void *p)
-{
-	struct iio_poll_func *pf = p;
-	struct iio_dev *indio_dev = pf->indio_dev;
-	struct adis16203_state *st = iio_priv(indio_dev);
-
-	int i = 0;
-	s16 *data;
-
-	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-	if (data == NULL) {
-		dev_err(&st->us->dev, "memory alloc failed in ring bh");
-		goto done;
-	}
-
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
-	    adis16203_read_ring_data(indio_dev, st->rx) >= 0)
-		for (; i < bitmap_weight(indio_dev->active_scan_mask,
-					 indio_dev->masklength); i++)
-			data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-	/* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp)
-		*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-	iio_push_to_buffers(indio_dev, (u8 *)data);
-
-	kfree(data);
-done:
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
-void adis16203_unconfigure_ring(struct iio_dev *indio_dev)
-{
-	iio_dealloc_pollfunc(indio_dev->pollfunc);
-	iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16203_ring_setup_ops = {
-	.preenable = &iio_sw_buffer_preenable,
-	.postenable = &iio_triggered_buffer_postenable,
-	.predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16203_configure_ring(struct iio_dev *indio_dev)
-{
-	int ret = 0;
-	struct iio_buffer *ring;
-
-	ring = iio_sw_rb_allocate(indio_dev);
-	if (!ring) {
-		ret = -ENOMEM;
-		return ret;
-	}
-	indio_dev->buffer = ring;
-	ring->scan_timestamp = true;
-	indio_dev->setup_ops = &adis16203_ring_setup_ops;
-
-	indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-						 &adis16203_trigger_handler,
-						 IRQF_ONESHOT,
-						 indio_dev,
-						 "adis16203_consumer%d",
-						 indio_dev->id);
-	if (indio_dev->pollfunc == NULL) {
-		ret = -ENOMEM;
-		goto error_iio_sw_rb_free;
-	}
-
-	indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-	return 0;
-
-error_iio_sw_rb_free:
-	iio_sw_rb_free(indio_dev->buffer);
-	return ret;
-}
diff --git a/drivers/staging/iio/accel/adis16203_trigger.c b/drivers/staging/iio/accel/adis16203_trigger.c
deleted file mode 100644
index b8a0407..0000000
--- a/drivers/staging/iio/accel/adis16203_trigger.c
+++ /dev/null
@@ -1,73 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16203.h"
-
-/**
- * adis16203_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16203_data_rdy_trigger_set_state(struct iio_trigger *trig,
-						bool state)
-{
-	struct iio_dev *indio_dev = trig->private_data;
-
-	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	return adis16203_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16203_trigger_ops = {
-	.owner = THIS_MODULE,
-	.set_trigger_state = &adis16203_data_rdy_trigger_set_state,
-};
-
-int adis16203_probe_trigger(struct iio_dev *indio_dev)
-{
-	int ret;
-	struct adis16203_state *st = iio_priv(indio_dev);
-
-	st->trig = iio_trigger_alloc("adis16203-dev%d", indio_dev->id);
-	if (st->trig == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-
-	ret = request_irq(st->us->irq,
-			  &iio_trigger_generic_data_rdy_poll,
-			  IRQF_TRIGGER_RISING,
-			  "adis16203",
-			  st->trig);
-	if (ret)
-		goto error_free_trig;
-
-	st->trig->dev.parent = &st->us->dev;
-	st->trig->ops = &adis16203_trigger_ops;
-	st->trig->private_data = indio_dev;
-	ret = iio_trigger_register(st->trig);
-
-	/* select default trigger */
-	indio_dev->trig = st->trig;
-	if (ret)
-		goto error_free_irq;
-
-	return 0;
-
-error_free_irq:
-	free_irq(st->us->irq, st->trig);
-error_free_trig:
-	iio_trigger_free(st->trig);
-error_ret:
-	return ret;
-}
-
-void adis16203_remove_trigger(struct iio_dev *indio_dev)
-{
-	struct adis16203_state *st = iio_priv(indio_dev);
-
-	iio_trigger_unregister(st->trig);
-	free_irq(st->us->irq, st->trig);
-	iio_trigger_free(st->trig);
-}
-- 
1.8.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 04/11] staging:iio:adis16204: Use adis library
  2012-11-13 13:28 [PATCH 01/11] staging:iio: Add common ADIS library Lars-Peter Clausen
  2012-11-13 13:28 ` [PATCH 02/11] staging:iio:adis16201: Use adis library Lars-Peter Clausen
  2012-11-13 13:28 ` [PATCH 03/11] staging:iio:adis16203: " Lars-Peter Clausen
@ 2012-11-13 13:28 ` Lars-Peter Clausen
  2012-11-13 13:28 ` [PATCH 05/11] staging:iio:adis16209: " Lars-Peter Clausen
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Lars-Peter Clausen @ 2012-11-13 13:28 UTC (permalink / raw)
  To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen

Use the new adis library for the adis16204 driver. This allows us to completely
scrap the adis16204 buffer and trigger code and more than half of the core
driver code.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/staging/iio/accel/Kconfig             |   4 +-
 drivers/staging/iio/accel/Makefile            |   1 -
 drivers/staging/iio/accel/adis16204.h         |  79 +----
 drivers/staging/iio/accel/adis16204_core.c    | 451 ++++----------------------
 drivers/staging/iio/accel/adis16204_ring.c    | 134 --------
 drivers/staging/iio/accel/adis16204_trigger.c |  73 -----
 6 files changed, 70 insertions(+), 672 deletions(-)
 delete mode 100644 drivers/staging/iio/accel/adis16204_ring.c
 delete mode 100644 drivers/staging/iio/accel/adis16204_trigger.c

diff --git a/drivers/staging/iio/accel/Kconfig b/drivers/staging/iio/accel/Kconfig
index 48755a2..85f8db9 100644
--- a/drivers/staging/iio/accel/Kconfig
+++ b/drivers/staging/iio/accel/Kconfig
@@ -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.
diff --git a/drivers/staging/iio/accel/Makefile b/drivers/staging/iio/accel/Makefile
index 28746b8..581a48b 100644
--- a/drivers/staging/iio/accel/Makefile
+++ b/drivers/staging/iio/accel/Makefile
@@ -9,7 +9,6 @@ adis16203-y             := adis16203_core.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
diff --git a/drivers/staging/iio/accel/adis16204.h b/drivers/staging/iio/accel/adis16204.h
index 7cf4e91..9ff950c 100644
--- a/drivers/staging/iio/accel/adis16204.h
+++ b/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_ */
diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c
index 9b75a2b..4f69ead 100644
--- a/drivers/staging/iio/accel/adis16204_core.c
+++ b/drivers/staging/iio/accel/adis16204_core.c
@@ -23,257 +23,14 @@
 #include <linux/iio/buffer.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;
-}
+#include "../imu/adis.h"
 
 /* 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,100 +129,25 @@ 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 = {
@@ -493,10 +156,35 @@ static const struct iio_info adis16204_info = {
 	.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 +196,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 +204,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 +233,10 @@ error_ret:
 static int __devexit adis16204_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct adis *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	adis16204_remove_trigger(indio_dev);
-	iio_buffer_unregister(indio_dev);
-	adis16204_unconfigure_ring(indio_dev);
+	adis_cleanup_buffer_and_trigger(st, indio_dev);
 	iio_device_free(indio_dev);
 
 	return 0;
diff --git a/drivers/staging/iio/accel/adis16204_ring.c b/drivers/staging/iio/accel/adis16204_ring.c
deleted file mode 100644
index 3611a13..0000000
--- a/drivers/staging/iio/accel/adis16204_ring.c
+++ /dev/null
@@ -1,134 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16204.h"
-
-/**
- * adis16204_read_ring_data() read data registers which will be placed into ring
- * @indio_dev: the IIO device
- * @rx: somewhere to pass back the value read
- **/
-static int adis16204_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-	struct spi_message msg;
-	struct adis16204_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[ADIS16204_OUTPUTS + 1];
-	int ret;
-	int i;
-
-	mutex_lock(&st->buf_lock);
-
-	spi_message_init(&msg);
-
-	memset(xfers, 0, sizeof(xfers));
-	for (i = 0; i <= ADIS16204_OUTPUTS; i++) {
-		xfers[i].bits_per_word = 8;
-		xfers[i].cs_change = 1;
-		xfers[i].len = 2;
-		xfers[i].delay_usecs = 20;
-		xfers[i].tx_buf = st->tx + 2 * i;
-		st->tx[2 * i]
-			= ADIS16204_READ_REG(ADIS16204_SUPPLY_OUT + 2 * i);
-		st->tx[2 * i + 1] = 0;
-		if (i >= 1)
-			xfers[i].rx_buf = rx + 2 * (i - 1);
-		spi_message_add_tail(&xfers[i], &msg);
-	}
-
-	ret = spi_sync(st->us, &msg);
-	if (ret)
-		dev_err(&st->us->dev, "problem when burst reading");
-
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
- * specific to be rolled into the core.
- */
-static irqreturn_t adis16204_trigger_handler(int irq, void *p)
-{
-	struct iio_poll_func *pf = p;
-	struct iio_dev *indio_dev = pf->indio_dev;
-	struct adis16204_state *st = iio_priv(indio_dev);
-	int i = 0;
-	s16 *data;
-
-	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-	if (data == NULL) {
-		dev_err(&st->us->dev, "memory alloc failed in ring bh");
-		goto done;
-	}
-
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
-	    adis16204_read_ring_data(indio_dev, st->rx) >= 0)
-		for (; i < bitmap_weight(indio_dev->active_scan_mask,
-					 indio_dev->masklength); i++)
-			data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-	/* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp)
-		*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-	iio_push_to_buffers(indio_dev, (u8 *)data);
-
-	kfree(data);
-done:
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
-void adis16204_unconfigure_ring(struct iio_dev *indio_dev)
-{
-	iio_dealloc_pollfunc(indio_dev->pollfunc);
-	iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16204_ring_setup_ops = {
-	.preenable = &iio_sw_buffer_preenable,
-	.postenable = &iio_triggered_buffer_postenable,
-	.predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16204_configure_ring(struct iio_dev *indio_dev)
-{
-	int ret = 0;
-	struct iio_buffer *ring;
-
-	ring = iio_sw_rb_allocate(indio_dev);
-	if (!ring) {
-		ret = -ENOMEM;
-		return ret;
-	}
-	indio_dev->buffer = ring;
-	ring->scan_timestamp = true;
-	indio_dev->setup_ops = &adis16204_ring_setup_ops;
-
-	indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-						 &adis16204_trigger_handler,
-						 IRQF_ONESHOT,
-						 indio_dev,
-						 "%s_consumer%d",
-						 indio_dev->name,
-						 indio_dev->id);
-	if (indio_dev->pollfunc == NULL) {
-		ret = -ENOMEM;
-		goto error_iio_sw_rb_free;
-	}
-
-	indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-	return 0;
-
-error_iio_sw_rb_free:
-	iio_sw_rb_free(indio_dev->buffer);
-	return ret;
-}
diff --git a/drivers/staging/iio/accel/adis16204_trigger.c b/drivers/staging/iio/accel/adis16204_trigger.c
deleted file mode 100644
index 408a168..0000000
--- a/drivers/staging/iio/accel/adis16204_trigger.c
+++ /dev/null
@@ -1,73 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16204.h"
-
-/**
- * adis16204_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16204_data_rdy_trigger_set_state(struct iio_trigger *trig,
-						bool state)
-{
-	struct iio_dev *indio_dev = trig->private_data;
-
-	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	return adis16204_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16204_trigger_ops = {
-	.owner = THIS_MODULE,
-	.set_trigger_state = &adis16204_data_rdy_trigger_set_state,
-};
-
-int adis16204_probe_trigger(struct iio_dev *indio_dev)
-{
-	int ret;
-	struct adis16204_state *st = iio_priv(indio_dev);
-
-	st->trig = iio_trigger_alloc("adis16204-dev%d", indio_dev->id);
-	if (st->trig == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-
-	ret = request_irq(st->us->irq,
-			  &iio_trigger_generic_data_rdy_poll,
-			  IRQF_TRIGGER_RISING,
-			  "adis16204",
-			  st->trig);
-	if (ret)
-		goto error_free_trig;
-
-	st->trig->dev.parent = &st->us->dev;
-	st->trig->ops = &adis16204_trigger_ops;
-	st->trig->private_data = indio_dev;
-	ret = iio_trigger_register(st->trig);
-
-	/* select default trigger */
-	indio_dev->trig = st->trig;
-	if (ret)
-		goto error_free_irq;
-
-	return 0;
-
-error_free_irq:
-	free_irq(st->us->irq, st->trig);
-error_free_trig:
-	iio_trigger_free(st->trig);
-error_ret:
-	return ret;
-}
-
-void adis16204_remove_trigger(struct iio_dev *indio_dev)
-{
-	struct adis16204_state *state = iio_priv(indio_dev);
-
-	iio_trigger_unregister(state->trig);
-	free_irq(state->us->irq, state->trig);
-	iio_trigger_free(state->trig);
-}
-- 
1.8.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 05/11] staging:iio:adis16209: Use adis library
  2012-11-13 13:28 [PATCH 01/11] staging:iio: Add common ADIS library Lars-Peter Clausen
                   ` (2 preceding siblings ...)
  2012-11-13 13:28 ` [PATCH 04/11] staging:iio:adis16204: " Lars-Peter Clausen
@ 2012-11-13 13:28 ` Lars-Peter Clausen
  2012-11-13 13:28 ` [PATCH 06/11] staging:iio:adis16220: " Lars-Peter Clausen
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Lars-Peter Clausen @ 2012-11-13 13:28 UTC (permalink / raw)
  To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen

Use the new adis library for the adis16209 driver. This allows us to completely
scrap the adis16209 buffer and trigger code and more than half of the core
driver code.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/staging/iio/accel/Kconfig             |   4 +-
 drivers/staging/iio/accel/Makefile            |   1 -
 drivers/staging/iio/accel/adis16209.h         |  77 +---
 drivers/staging/iio/accel/adis16209_core.c    | 485 ++++----------------------
 drivers/staging/iio/accel/adis16209_ring.c    | 134 -------
 drivers/staging/iio/accel/adis16209_trigger.c |  72 ----
 6 files changed, 74 insertions(+), 699 deletions(-)
 delete mode 100644 drivers/staging/iio/accel/adis16209_ring.c
 delete mode 100644 drivers/staging/iio/accel/adis16209_trigger.c

diff --git a/drivers/staging/iio/accel/Kconfig b/drivers/staging/iio/accel/Kconfig
index 85f8db9..affa732 100644
--- a/drivers/staging/iio/accel/Kconfig
+++ b/drivers/staging/iio/accel/Kconfig
@@ -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.
diff --git a/drivers/staging/iio/accel/Makefile b/drivers/staging/iio/accel/Makefile
index 581a48b..3cb9c67 100644
--- a/drivers/staging/iio/accel/Makefile
+++ b/drivers/staging/iio/accel/Makefile
@@ -12,7 +12,6 @@ adis16204-y             := adis16204_core.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
diff --git a/drivers/staging/iio/accel/adis16209.h b/drivers/staging/iio/accel/adis16209.h
index 3c88b86..ad3945a 100644
--- a/drivers/staging/iio/accel/adis16209.h
+++ b/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_ */
diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c
index b7a0d5c..e203e96 100644
--- a/drivers/staging/iio/accel/adis16209_core.c
+++ b/drivers/staging/iio/accel/adis16209_core.c
@@ -21,258 +21,17 @@
 #include <linux/iio/buffer.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 },
+#include "../imu/adis.h"
+
+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,115 +130,16 @@ 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)
 };
 
@@ -508,10 +149,36 @@ static const struct iio_info adis16209_info = {
 	.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 +190,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 +198,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 +226,10 @@ error_ret:
 static int __devexit adis16209_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct adis *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	adis16209_remove_trigger(indio_dev);
-	iio_buffer_unregister(indio_dev);
-	adis16209_unconfigure_ring(indio_dev);
+	adis_cleanup_buffer_and_trigger(st, indio_dev);
 	iio_device_free(indio_dev);
 
 	return 0;
diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c
deleted file mode 100644
index 6af9a5d..0000000
--- a/drivers/staging/iio/accel/adis16209_ring.c
+++ /dev/null
@@ -1,134 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16209.h"
-
-/**
- * adis16209_read_ring_data() read data registers which will be placed into ring
- * @indio_dev: the IIO device
- * @rx: somewhere to pass back the value read
- **/
-static int adis16209_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-	struct spi_message msg;
-	struct adis16209_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[ADIS16209_OUTPUTS + 1];
-	int ret;
-	int i;
-
-	mutex_lock(&st->buf_lock);
-
-	spi_message_init(&msg);
-
-	memset(xfers, 0, sizeof(xfers));
-	for (i = 0; i <= ADIS16209_OUTPUTS; i++) {
-		xfers[i].bits_per_word = 8;
-		xfers[i].cs_change = 1;
-		xfers[i].len = 2;
-		xfers[i].delay_usecs = 30;
-		xfers[i].tx_buf = st->tx + 2 * i;
-		st->tx[2 * i]
-			= ADIS16209_READ_REG(ADIS16209_SUPPLY_OUT + 2 * i);
-		st->tx[2 * i + 1] = 0;
-		if (i >= 1)
-			xfers[i].rx_buf = rx + 2 * (i - 1);
-		spi_message_add_tail(&xfers[i], &msg);
-	}
-
-	ret = spi_sync(st->us, &msg);
-	if (ret)
-		dev_err(&st->us->dev, "problem when burst reading");
-
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
- * specific to be rolled into the core.
- */
-static irqreturn_t adis16209_trigger_handler(int irq, void *p)
-{
-	struct iio_poll_func *pf = p;
-	struct iio_dev *indio_dev = pf->indio_dev;
-	struct adis16209_state *st = iio_priv(indio_dev);
-	int i = 0;
-	s16 *data;
-
-	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-	if (data == NULL) {
-		dev_err(&st->us->dev, "memory alloc failed in ring bh");
-		goto done;
-	}
-
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
-	    adis16209_read_ring_data(indio_dev, st->rx) >= 0)
-		for (; i < bitmap_weight(indio_dev->active_scan_mask,
-					 indio_dev->masklength); i++)
-			data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-	/* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp)
-		*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-	iio_push_to_buffers(indio_dev, (u8 *)data);
-
-	kfree(data);
-done:
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
-void adis16209_unconfigure_ring(struct iio_dev *indio_dev)
-{
-	iio_dealloc_pollfunc(indio_dev->pollfunc);
-	iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16209_ring_setup_ops = {
-	.preenable = &iio_sw_buffer_preenable,
-	.postenable = &iio_triggered_buffer_postenable,
-	.predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16209_configure_ring(struct iio_dev *indio_dev)
-{
-	int ret = 0;
-	struct iio_buffer *ring;
-
-	ring = iio_sw_rb_allocate(indio_dev);
-	if (!ring) {
-		ret = -ENOMEM;
-		return ret;
-	}
-	indio_dev->buffer = ring;
-	ring->scan_timestamp = true;
-	indio_dev->setup_ops = &adis16209_ring_setup_ops;
-
-	indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-						 &adis16209_trigger_handler,
-						 IRQF_ONESHOT,
-						 indio_dev,
-						 "%s_consumer%d",
-						 indio_dev->name,
-						 indio_dev->id);
-	if (indio_dev->pollfunc == NULL) {
-		ret = -ENOMEM;
-		goto error_iio_sw_rb_free;
-	}
-
-	indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-	return 0;
-
-error_iio_sw_rb_free:
-	iio_sw_rb_free(indio_dev->buffer);
-	return ret;
-}
diff --git a/drivers/staging/iio/accel/adis16209_trigger.c b/drivers/staging/iio/accel/adis16209_trigger.c
deleted file mode 100644
index 1122803..0000000
--- a/drivers/staging/iio/accel/adis16209_trigger.c
+++ /dev/null
@@ -1,72 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16209.h"
-
-/**
- * adis16209_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16209_data_rdy_trigger_set_state(struct iio_trigger *trig,
-						bool state)
-{
-	struct iio_dev *indio_dev = trig->private_data;
-
-	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	return adis16209_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16209_trigger_ops = {
-	.owner = THIS_MODULE,
-	.set_trigger_state = &adis16209_data_rdy_trigger_set_state,
-};
-
-int adis16209_probe_trigger(struct iio_dev *indio_dev)
-{
-	int ret;
-	struct adis16209_state *st = iio_priv(indio_dev);
-
-	st->trig = iio_trigger_alloc("adis16209-dev%d", indio_dev->id);
-	if (st->trig == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-
-	ret = request_irq(st->us->irq,
-			  iio_trigger_generic_data_rdy_poll,
-			  IRQF_TRIGGER_RISING,
-			  "adis16209",
-			  st->trig);
-	if (ret)
-		goto error_free_trig;
-	st->trig->dev.parent = &st->us->dev;
-	st->trig->ops = &adis16209_trigger_ops;
-	st->trig->private_data = indio_dev;
-	ret = iio_trigger_register(st->trig);
-
-	/* select default trigger */
-	indio_dev->trig = st->trig;
-	if (ret)
-		goto error_free_irq;
-
-	return 0;
-
-error_free_irq:
-	free_irq(st->us->irq, st->trig);
-error_free_trig:
-	iio_trigger_free(st->trig);
-error_ret:
-	return ret;
-}
-
-void adis16209_remove_trigger(struct iio_dev *indio_dev)
-{
-	struct adis16209_state *st = iio_priv(indio_dev);
-
-	iio_trigger_unregister(st->trig);
-	free_irq(st->us->irq, st->trig);
-	iio_trigger_free(st->trig);
-}
-- 
1.8.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 06/11] staging:iio:adis16220: Use adis library
  2012-11-13 13:28 [PATCH 01/11] staging:iio: Add common ADIS library Lars-Peter Clausen
                   ` (3 preceding siblings ...)
  2012-11-13 13:28 ` [PATCH 05/11] staging:iio:adis16209: " Lars-Peter Clausen
@ 2012-11-13 13:28 ` Lars-Peter Clausen
  2012-11-13 13:28 ` [PATCH 07/11] staging:iio:adis16240: " Lars-Peter Clausen
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Lars-Peter Clausen @ 2012-11-13 13:28 UTC (permalink / raw)
  To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen

Use the new adis library for the adis16220 driver. The adis16220 driver is a bit
special and so we can only make use of the generic register access and control
functions for now.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/staging/iio/accel/adis16220.h      |  20 +--
 drivers/staging/iio/accel/adis16220_core.c | 280 ++++++-----------------------
 2 files changed, 60 insertions(+), 240 deletions(-)

diff --git a/drivers/staging/iio/accel/adis16220.h b/drivers/staging/iio/accel/adis16220.h
index 024313c..7cc4d2f 100644
--- a/drivers/staging/iio/accel/adis16220.h
+++ b/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 "../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];
diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c
index 22807ac..c39ce62 100644
--- a/drivers/staging/iio/accel/adis16220_core.c
+++ b/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;
-- 
1.8.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 07/11] staging:iio:adis16240: Use adis library
  2012-11-13 13:28 [PATCH 01/11] staging:iio: Add common ADIS library Lars-Peter Clausen
                   ` (4 preceding siblings ...)
  2012-11-13 13:28 ` [PATCH 06/11] staging:iio:adis16220: " Lars-Peter Clausen
@ 2012-11-13 13:28 ` Lars-Peter Clausen
  2012-11-13 13:28 ` [PATCH 08/11] staging:iio:adis16260: " Lars-Peter Clausen
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Lars-Peter Clausen @ 2012-11-13 13:28 UTC (permalink / raw)
  To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen

Use the new adis library for the adis16240 driver. This allows us to completely
scrap the adis16240 buffer and trigger code and more than half of the core
driver code.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/staging/iio/accel/Kconfig             |   5 +-
 drivers/staging/iio/accel/Makefile            |   1 -
 drivers/staging/iio/accel/adis16240.h         |  85 +----
 drivers/staging/iio/accel/adis16240_core.c    | 472 ++++----------------------
 drivers/staging/iio/accel/adis16240_ring.c    | 132 -------
 drivers/staging/iio/accel/adis16240_trigger.c |  73 ----
 6 files changed, 77 insertions(+), 691 deletions(-)
 delete mode 100644 drivers/staging/iio/accel/adis16240_ring.c
 delete mode 100644 drivers/staging/iio/accel/adis16240_trigger.c

diff --git a/drivers/staging/iio/accel/Kconfig b/drivers/staging/iio/accel/Kconfig
index affa732..2b54430 100644
--- a/drivers/staging/iio/accel/Kconfig
+++ b/drivers/staging/iio/accel/Kconfig
@@ -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.
diff --git a/drivers/staging/iio/accel/Makefile b/drivers/staging/iio/accel/Makefile
index 3cb9c67..8e7ee03 100644
--- a/drivers/staging/iio/accel/Makefile
+++ b/drivers/staging/iio/accel/Makefile
@@ -18,7 +18,6 @@ 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
diff --git a/drivers/staging/iio/accel/adis16240.h b/drivers/staging/iio/accel/adis16240.h
index 3fabcc0..d442d49 100644
--- a/drivers/staging/iio/accel/adis16240.h
+++ b/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_ */
diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c
index 289f819..019a31e 100644
--- a/drivers/staging/iio/accel/adis16240_core.c
+++ b/drivers/staging/iio/accel/adis16240_core.c
@@ -24,128 +24,7 @@
 #include <linux/iio/buffer.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;
-}
+#include "../imu/adis.h"
 
 static ssize_t adis16240_spi_read_signed(struct device *dev,
 		struct device_attribute *attr,
@@ -153,18 +32,19 @@ static ssize_t adis16240_spi_read_signed(struct device *dev,
 		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)
 };
 
@@ -553,10 +205,36 @@ static const struct iio_info adis16240_info = {
 	.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 +247,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 +254,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 +280,11 @@ error_ret:
 
 static int __devexit adis16240_remove(struct spi_device *spi)
 {
-
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct adis *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	adis16240_remove_trigger(indio_dev);
-	iio_buffer_unregister(indio_dev);
-	adis16240_unconfigure_ring(indio_dev);
+	adis_cleanup_buffer_and_trigger(st, indio_dev);
 	iio_device_free(indio_dev);
 
 	return 0;
diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c
deleted file mode 100644
index e2ac8a8..0000000
--- a/drivers/staging/iio/accel/adis16240_ring.c
+++ /dev/null
@@ -1,132 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16240.h"
-
-/**
- * adis16240_read_ring_data() read data registers which will be placed into ring
- * @indio_dev: the IIO device
- * @rx: somewhere to pass back the value read
- **/
-static int adis16240_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-	struct spi_message msg;
-	struct adis16240_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[ADIS16240_OUTPUTS + 1];
-	int ret;
-	int i;
-
-	mutex_lock(&st->buf_lock);
-
-	spi_message_init(&msg);
-
-	memset(xfers, 0, sizeof(xfers));
-	for (i = 0; i <= ADIS16240_OUTPUTS; i++) {
-		xfers[i].bits_per_word = 8;
-		xfers[i].cs_change = 1;
-		xfers[i].len = 2;
-		xfers[i].delay_usecs = 30;
-		xfers[i].tx_buf = st->tx + 2 * i;
-		st->tx[2 * i]
-			= ADIS16240_READ_REG(ADIS16240_SUPPLY_OUT + 2 * i);
-		st->tx[2 * i + 1] = 0;
-		if (i >= 1)
-			xfers[i].rx_buf = rx + 2 * (i - 1);
-		spi_message_add_tail(&xfers[i], &msg);
-	}
-
-	ret = spi_sync(st->us, &msg);
-	if (ret)
-		dev_err(&st->us->dev, "problem when burst reading");
-
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-static irqreturn_t adis16240_trigger_handler(int irq, void *p)
-{
-	struct iio_poll_func *pf = p;
-	struct iio_dev *indio_dev = pf->indio_dev;
-	struct adis16240_state *st = iio_priv(indio_dev);
-
-	int i = 0;
-	s16 *data;
-
-	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-	if (data == NULL) {
-		dev_err(&st->us->dev, "memory alloc failed in ring bh");
-		goto done;
-	}
-
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
-	    adis16240_read_ring_data(indio_dev, st->rx) >= 0)
-		for (; i < bitmap_weight(indio_dev->active_scan_mask,
-					 indio_dev->masklength); i++)
-			data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-	/* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp)
-		*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-	iio_push_to_buffers(indio_dev, (u8 *)data);
-
-	kfree(data);
-done:
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
-void adis16240_unconfigure_ring(struct iio_dev *indio_dev)
-{
-	iio_dealloc_pollfunc(indio_dev->pollfunc);
-	iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16240_ring_setup_ops = {
-	.preenable = &iio_sw_buffer_preenable,
-	.postenable = &iio_triggered_buffer_postenable,
-	.predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16240_configure_ring(struct iio_dev *indio_dev)
-{
-	int ret = 0;
-	struct iio_buffer *ring;
-
-	ring = iio_sw_rb_allocate(indio_dev);
-	if (!ring) {
-		ret = -ENOMEM;
-		return ret;
-	}
-	indio_dev->buffer = ring;
-	ring->scan_timestamp = true;
-	indio_dev->setup_ops = &adis16240_ring_setup_ops;
-
-	indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-						 &adis16240_trigger_handler,
-						 IRQF_ONESHOT,
-						 indio_dev,
-						 "%s_consumer%d",
-						 indio_dev->name,
-						 indio_dev->id);
-	if (indio_dev->pollfunc == NULL) {
-		ret = -ENOMEM;
-		goto error_iio_sw_rb_free;
-	}
-
-	indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-	return 0;
-
-error_iio_sw_rb_free:
-	iio_sw_rb_free(indio_dev->buffer);
-	return ret;
-}
diff --git a/drivers/staging/iio/accel/adis16240_trigger.c b/drivers/staging/iio/accel/adis16240_trigger.c
deleted file mode 100644
index f3caf09..0000000
--- a/drivers/staging/iio/accel/adis16240_trigger.c
+++ /dev/null
@@ -1,73 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16240.h"
-
-/**
- * adis16240_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16240_data_rdy_trigger_set_state(struct iio_trigger *trig,
-						bool state)
-{
-	struct iio_dev *indio_dev = trig->private_data;
-
-	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	return adis16240_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16240_trigger_ops = {
-	.owner = THIS_MODULE,
-	.set_trigger_state = &adis16240_data_rdy_trigger_set_state,
-};
-
-int adis16240_probe_trigger(struct iio_dev *indio_dev)
-{
-	int ret;
-	struct adis16240_state *st = iio_priv(indio_dev);
-
-	st->trig = iio_trigger_alloc("adis16240-dev%d", indio_dev->id);
-	if (st->trig == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-
-	ret = request_irq(st->us->irq,
-			  iio_trigger_generic_data_rdy_poll,
-			  IRQF_TRIGGER_RISING,
-			  "adis16240",
-			  st->trig);
-	if (ret)
-		goto error_free_trig;
-
-	st->trig->dev.parent = &st->us->dev;
-	st->trig->ops = &adis16240_trigger_ops;
-	st->trig->private_data = indio_dev;
-	ret = iio_trigger_register(st->trig);
-
-	/* select default trigger */
-	indio_dev->trig = st->trig;
-	if (ret)
-		goto error_free_irq;
-
-	return 0;
-
-error_free_irq:
-	free_irq(st->us->irq, st->trig);
-error_free_trig:
-	iio_trigger_free(st->trig);
-error_ret:
-	return ret;
-}
-
-void adis16240_remove_trigger(struct iio_dev *indio_dev)
-{
-	struct adis16240_state *st = iio_priv(indio_dev);
-
-	iio_trigger_unregister(st->trig);
-	free_irq(st->us->irq, st->trig);
-	iio_trigger_free(st->trig);
-}
-- 
1.8.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 08/11] staging:iio:adis16260: Use adis library
  2012-11-13 13:28 [PATCH 01/11] staging:iio: Add common ADIS library Lars-Peter Clausen
                   ` (5 preceding siblings ...)
  2012-11-13 13:28 ` [PATCH 07/11] staging:iio:adis16240: " Lars-Peter Clausen
@ 2012-11-13 13:28 ` Lars-Peter Clausen
  2012-11-13 13:28 ` [PATCH 09/11] staging:iio:adis_lib: Use triggered buffer setup helper function Lars-Peter Clausen
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Lars-Peter Clausen @ 2012-11-13 13:28 UTC (permalink / raw)
  To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen

Use the new adis library for the adis16260 driver. This allows us to completely
scrap the adis16260 buffer and trigger code and about half of the core driver
code.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/staging/iio/gyro/Makefile            |   1 -
 drivers/staging/iio/gyro/adis16260.h         |  84 +----
 drivers/staging/iio/gyro/adis16260_core.c    | 483 +++++----------------------
 drivers/staging/iio/gyro/adis16260_ring.c    | 136 --------
 drivers/staging/iio/gyro/adis16260_trigger.c |  75 -----
 5 files changed, 94 insertions(+), 685 deletions(-)
 delete mode 100644 drivers/staging/iio/gyro/adis16260_ring.c
 delete mode 100644 drivers/staging/iio/gyro/adis16260_trigger.c

diff --git a/drivers/staging/iio/gyro/Makefile b/drivers/staging/iio/gyro/Makefile
index 9ba5ec1..1303569 100644
--- a/drivers/staging/iio/gyro/Makefile
+++ b/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
diff --git a/drivers/staging/iio/gyro/adis16260.h b/drivers/staging/iio/gyro/adis16260.h
index 4c4b251..ea5eba2 100644
--- a/drivers/staging/iio/gyro/adis16260.h
+++ b/drivers/staging/iio/gyro/adis16260.h
@@ -1,12 +1,11 @@
 #ifndef SPI_ADIS16260_H_
 #define SPI_ADIS16260_H_
+
 #include "adis16260_platform_data.h"
+#include "../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_ */
diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c
index e822460..820547b 100644
--- a/drivers/staging/iio/gyro/adis16260_core.c
+++ b/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;
 }
@@ -605,6 +270,36 @@ static const struct iio_info adis16260_info = {
 	.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 +319,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 +343,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 +364,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 +386,11 @@ error_ret:
 static int __devexit adis16260_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct adis16260_state *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
 	adis16260_stop_device(indio_dev);
-	adis16260_remove_trigger(indio_dev);
-	iio_buffer_unregister(indio_dev);
-	adis16260_unconfigure_ring(indio_dev);
+	adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
 	iio_device_free(indio_dev);
 
 	return 0;
diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c
deleted file mode 100644
index d6c48f8..0000000
--- a/drivers/staging/iio/gyro/adis16260_ring.c
+++ /dev/null
@@ -1,136 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16260.h"
-
-/**
- * adis16260_read_ring_data() read data registers which will be placed into ring
- * @indio_dev: the IIO device
- * @rx: somewhere to pass back the value read
- **/
-static int adis16260_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-	struct spi_message msg;
-	struct adis16260_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[ADIS16260_OUTPUTS + 1];
-	int ret;
-	int i;
-
-	mutex_lock(&st->buf_lock);
-
-	spi_message_init(&msg);
-
-	memset(xfers, 0, sizeof(xfers));
-	for (i = 0; i <= ADIS16260_OUTPUTS; i++) {
-		xfers[i].bits_per_word = 8;
-		xfers[i].cs_change = 1;
-		xfers[i].len = 2;
-		xfers[i].delay_usecs = 30;
-		xfers[i].tx_buf = st->tx + 2 * i;
-		if (i < 2) /* SUPPLY_OUT:0x02 GYRO_OUT:0x04 */
-			st->tx[2 * i]
-				= ADIS16260_READ_REG(ADIS16260_SUPPLY_OUT
-						+ 2 * i);
-		else /* 0x06 to 0x09 is reserved */
-			st->tx[2 * i]
-				= ADIS16260_READ_REG(ADIS16260_SUPPLY_OUT
-						+ 2 * i + 4);
-		st->tx[2 * i + 1] = 0;
-		if (i >= 1)
-			xfers[i].rx_buf = rx + 2 * (i - 1);
-		spi_message_add_tail(&xfers[i], &msg);
-	}
-
-	ret = spi_sync(st->us, &msg);
-	if (ret)
-		dev_err(&st->us->dev, "problem when burst reading");
-
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-static irqreturn_t adis16260_trigger_handler(int irq, void *p)
-{
-	struct iio_poll_func *pf = p;
-	struct iio_dev *indio_dev = pf->indio_dev;
-	struct adis16260_state *st = iio_priv(indio_dev);
-	int i = 0;
-	s16 *data;
-
-	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-	if (data == NULL) {
-		dev_err(&st->us->dev, "memory alloc failed in ring bh");
-		goto done;
-	}
-
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
-	    adis16260_read_ring_data(indio_dev, st->rx) >= 0)
-		for (; i < bitmap_weight(indio_dev->active_scan_mask,
-					 indio_dev->masklength); i++)
-			data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-	/* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp)
-		*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-	iio_push_to_buffers(indio_dev, (u8 *)data);
-
-	kfree(data);
-done:
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
-void adis16260_unconfigure_ring(struct iio_dev *indio_dev)
-{
-	iio_dealloc_pollfunc(indio_dev->pollfunc);
-	iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16260_ring_setup_ops = {
-	.preenable = &iio_sw_buffer_preenable,
-	.postenable = &iio_triggered_buffer_postenable,
-	.predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16260_configure_ring(struct iio_dev *indio_dev)
-{
-	int ret = 0;
-	struct iio_buffer *ring;
-
-	ring = iio_sw_rb_allocate(indio_dev);
-	if (!ring) {
-		ret = -ENOMEM;
-		return ret;
-	}
-	indio_dev->buffer = ring;
-	ring->scan_timestamp = true;
-	indio_dev->setup_ops = &adis16260_ring_setup_ops;
-
-	indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-						 &adis16260_trigger_handler,
-						 IRQF_ONESHOT,
-						 indio_dev,
-						 "adis16260_consumer%d",
-						 indio_dev->id);
-	if (indio_dev->pollfunc == NULL) {
-		ret = -ENOMEM;
-		goto error_iio_sw_rb_free;
-	}
-
-	indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-	return 0;
-
-error_iio_sw_rb_free:
-	iio_sw_rb_free(indio_dev->buffer);
-	return ret;
-}
diff --git a/drivers/staging/iio/gyro/adis16260_trigger.c b/drivers/staging/iio/gyro/adis16260_trigger.c
deleted file mode 100644
index 034559e..0000000
--- a/drivers/staging/iio/gyro/adis16260_trigger.c
+++ /dev/null
@@ -1,75 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16260.h"
-
-/**
- * adis16260_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16260_data_rdy_trigger_set_state(struct iio_trigger *trig,
-						bool state)
-{
-	struct iio_dev *indio_dev = trig->private_data;
-
-	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	return adis16260_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16260_trigger_ops = {
-	.owner = THIS_MODULE,
-	.set_trigger_state = &adis16260_data_rdy_trigger_set_state,
-};
-
-int adis16260_probe_trigger(struct iio_dev *indio_dev)
-{
-	int ret;
-	struct adis16260_state *st = iio_priv(indio_dev);
-
-	st->trig = iio_trigger_alloc("%s-dev%d",
-					spi_get_device_id(st->us)->name,
-					indio_dev->id);
-	if (st->trig == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-
-	ret = request_irq(st->us->irq,
-			  &iio_trigger_generic_data_rdy_poll,
-			  IRQF_TRIGGER_RISING,
-			  "adis16260",
-			  st->trig);
-	if (ret)
-		goto error_free_trig;
-
-	st->trig->dev.parent = &st->us->dev;
-	st->trig->ops = &adis16260_trigger_ops;
-	st->trig->private_data = indio_dev;
-	ret = iio_trigger_register(st->trig);
-
-	/* select default trigger */
-	indio_dev->trig = st->trig;
-	if (ret)
-		goto error_free_irq;
-
-	return 0;
-
-error_free_irq:
-	free_irq(st->us->irq, st->trig);
-error_free_trig:
-	iio_trigger_free(st->trig);
-error_ret:
-	return ret;
-}
-
-void adis16260_remove_trigger(struct iio_dev *indio_dev)
-{
-	struct adis16260_state *st = iio_priv(indio_dev);
-
-	iio_trigger_unregister(st->trig);
-	free_irq(st->us->irq, st->trig);
-	iio_trigger_free(st->trig);
-}
-- 
1.8.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 09/11] staging:iio:adis_lib: Use triggered buffer setup helper function
  2012-11-13 13:28 [PATCH 01/11] staging:iio: Add common ADIS library Lars-Peter Clausen
                   ` (6 preceding siblings ...)
  2012-11-13 13:28 ` [PATCH 08/11] staging:iio:adis16260: " Lars-Peter Clausen
@ 2012-11-13 13:28 ` Lars-Peter Clausen
  2012-11-13 13:28 ` [PATCH 10/11] staging:iio:adis: Preallocate transfer message Lars-Peter Clausen
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Lars-Peter Clausen @ 2012-11-13 13:28 UTC (permalink / raw)
  To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen

Use the triggered buffer helper functions to setup and tear down the buffer for
the adis library instead of doing this manually. This also means that we switch
away from the deprecated sw_ring buffer and use the kfifo buffer now instead.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/staging/iio/imu/Kconfig       |  3 +-
 drivers/staging/iio/imu/adis_buffer.c | 78 +++++------------------------------
 2 files changed, 11 insertions(+), 70 deletions(-)

diff --git a/drivers/staging/iio/imu/Kconfig b/drivers/staging/iio/imu/Kconfig
index 89b9f25..2c564ed 100644
--- a/drivers/staging/iio/imu/Kconfig
+++ b/drivers/staging/iio/imu/Kconfig
@@ -23,8 +23,7 @@ config IIO_ADIS_LIB
 
 config IIO_ADIS_LIB_BUFFER
 	bool
-	select IIO_TRIGGER
-	select IIO_SW_RING
+	select IIO_TRIGGERED_BUFFER
 	help
 	  A set of buffer helper functions for the Analog Devices ADIS* device
 	  family.
diff --git a/drivers/staging/iio/imu/adis_buffer.c b/drivers/staging/iio/imu/adis_buffer.c
index 47bdea0..0fa8e80a 100644
--- a/drivers/staging/iio/imu/adis_buffer.c
+++ b/drivers/staging/iio/imu/adis_buffer.c
@@ -7,8 +7,8 @@
 
 #include <linux/iio/iio.h>
 #include <linux/iio/buffer.h>
-#include "../ring_sw.h"
 #include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
 
 #include  "adis.h"
 
@@ -83,56 +83,6 @@ static irqreturn_t adis_trigger_handler(int irq, void *p)
 	return IRQ_HANDLED;
 }
 
-static const struct iio_buffer_setup_ops adis_buffer_setup_ops = {
-	.preenable = &iio_sw_buffer_preenable,
-	.postenable = &iio_triggered_buffer_postenable,
-	.predisable = &iio_triggered_buffer_predisable,
-};
-
-static int adis_buffer_setup(struct iio_dev *indio_dev,
-	irqreturn_t (*trigger_handler)(int, void *))
-{
-	int ret = 0;
-	struct iio_buffer *buffer;
-
-	if (!trigger_handler)
-		trigger_handler = &adis_trigger_handler;
-
-	buffer = iio_sw_rb_allocate(indio_dev);
-	if (!buffer) {
-		ret = -ENOMEM;
-		return ret;
-	}
-
-	indio_dev->buffer = buffer;
-	indio_dev->setup_ops = &adis_buffer_setup_ops;
-
-	indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-						 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;
-}
-
-static void adis_buffer_cleanup(struct iio_dev *indio_dev)
-{
-	iio_dealloc_pollfunc(indio_dev->pollfunc);
-	iio_sw_rb_free(indio_dev->buffer);
-}
-
 /**
  * adis_setup_buffer_and_trigger() - Sets up buffer and trigger for the adis device
  * @adis: The adis device.
@@ -154,30 +104,23 @@ int adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev,
 {
 	int ret;
 
-	ret = adis_buffer_setup(indio_dev, trigger_handler);
+	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;
 
-	ret = iio_buffer_register(indio_dev,
-				  indio_dev->channels,
-				  indio_dev->num_channels);
-	if (ret) {
-		dev_err(&adis->spi->dev, "Failed to initialize buffer %d\n",
-			ret);
-		goto error_unreg_buffer_funcs;
-	}
-
 	if (adis->spi->irq) {
 		ret = adis_probe_trigger(adis, indio_dev);
 		if (ret)
-			goto error_uninitialize_buffer;
+			goto error_buffer_cleanup;
 	}
 	return 0;
 
-error_uninitialize_buffer:
-	iio_buffer_unregister(indio_dev);
-error_unreg_buffer_funcs:
-	adis_buffer_cleanup(indio_dev);
+error_buffer_cleanup:
+	iio_triggered_buffer_cleanup(indio_dev);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(adis_setup_buffer_and_trigger);
@@ -194,7 +137,6 @@ void adis_cleanup_buffer_and_trigger(struct adis *adis,
 {
 	if (adis->spi->irq)
 		adis_remove_trigger(adis);
-	iio_buffer_unregister(indio_dev);
-	adis_buffer_cleanup(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
 }
 EXPORT_SYMBOL_GPL(adis_cleanup_buffer_and_trigger);
-- 
1.8.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 10/11] staging:iio:adis: Preallocate transfer message
  2012-11-13 13:28 [PATCH 01/11] staging:iio: Add common ADIS library Lars-Peter Clausen
                   ` (7 preceding siblings ...)
  2012-11-13 13:28 ` [PATCH 09/11] staging:iio:adis_lib: Use triggered buffer setup helper function Lars-Peter Clausen
@ 2012-11-13 13:28 ` Lars-Peter Clausen
  2012-11-13 13:28 ` [PATCH 11/11] staging:iio: Move adis library out of staging Lars-Peter Clausen
  2012-11-17 11:01 ` [PATCH 01/11] staging:iio: Add common ADIS library Jonathan Cameron
  10 siblings, 0 replies; 13+ messages in thread
From: Lars-Peter Clausen @ 2012-11-13 13:28 UTC (permalink / raw)
  To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen

Currently the driver reads out all sample registers of the device and throws
away those which it does not need. Furthermore the SPI message is constructed
each time the trigger handler is run, although it will be the same each time.
This patch preallocates and pre-constructs the SPI message in the
"update_scan_mode" callback. Only those register which are actually selected for
sampling are included in the message. The patch also gets rid of the conversion
of the sample data from big endian to the native endianness and instead marks
the channel as big endian in its scan type. This allows to directly push the
SPI transfer buffer to the IIO buffer without the need to post-process it.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/staging/iio/accel/adis16201_core.c |   1 +
 drivers/staging/iio/accel/adis16203_core.c |   1 +
 drivers/staging/iio/accel/adis16204_core.c |   1 +
 drivers/staging/iio/accel/adis16209_core.c |   1 +
 drivers/staging/iio/accel/adis16240_core.c |   1 +
 drivers/staging/iio/gyro/adis16260_core.c  |   1 +
 drivers/staging/iio/imu/adis.h             |   8 ++
 drivers/staging/iio/imu/adis_buffer.c      | 114 +++++++++++++++++------------
 8 files changed, 80 insertions(+), 48 deletions(-)

diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c
index 0121501..833dd6b 100644
--- a/drivers/staging/iio/accel/adis16201_core.c
+++ b/drivers/staging/iio/accel/adis16201_core.c
@@ -148,6 +148,7 @@ static const struct iio_chan_spec adis16201_channels[] = {
 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,
 };
 
diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c
index 326b106..f631e57 100644
--- a/drivers/staging/iio/accel/adis16203_core.c
+++ b/drivers/staging/iio/accel/adis16203_core.c
@@ -112,6 +112,7 @@ static const struct iio_chan_spec adis16203_channels[] = {
 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,
 };
 
diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c
index 4f69ead..dbec841 100644
--- a/drivers/staging/iio/accel/adis16204_core.c
+++ b/drivers/staging/iio/accel/adis16204_core.c
@@ -153,6 +153,7 @@ static const struct iio_chan_spec adis16204_channels[] = {
 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,
 };
 
diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c
index e203e96..f9f9d58 100644
--- a/drivers/staging/iio/accel/adis16209_core.c
+++ b/drivers/staging/iio/accel/adis16209_core.c
@@ -146,6 +146,7 @@ static const struct iio_chan_spec adis16209_channels[] = {
 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,
 };
 
diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c
index 019a31e..3d1a8a9 100644
--- a/drivers/staging/iio/accel/adis16240_core.c
+++ b/drivers/staging/iio/accel/adis16240_core.c
@@ -202,6 +202,7 @@ 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,
 };
 
diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c
index 820547b..b988b4f 100644
--- a/drivers/staging/iio/gyro/adis16260_core.c
+++ b/drivers/staging/iio/gyro/adis16260_core.c
@@ -267,6 +267,7 @@ 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,
 };
 
diff --git a/drivers/staging/iio/imu/adis.h b/drivers/staging/iio/imu/adis.h
index c84da7a..8c3304d 100644
--- a/drivers/staging/iio/imu/adis.h
+++ b/drivers/staging/iio/imu/adis.h
@@ -87,6 +87,7 @@ int adis_single_conversion(struct iio_dev *indio_dev,
 		.sign = 'u', \
 		.realbits = (bits), \
 		.storagebits = 16, \
+		.endianness = IIO_BE, \
 	}, \
 }
 
@@ -109,6 +110,7 @@ int adis_single_conversion(struct iio_dev *indio_dev,
 		.sign = 'u', \
 		.realbits = (bits), \
 		.storagebits = 16, \
+		.endianness = IIO_BE, \
 	}, \
 }
 
@@ -125,6 +127,7 @@ int adis_single_conversion(struct iio_dev *indio_dev,
 		.sign = 's', \
 		.realbits = (bits), \
 		.storagebits = 16, \
+		.endianness = IIO_BE, \
 	}, \
 }
 
@@ -150,6 +153,9 @@ void adis_cleanup_buffer_and_trigger(struct adis *adis,
 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,
@@ -173,6 +179,8 @@ static inline void adis_remove_trigger(struct adis *adis)
 {
 }
 
+#define adis_update_scan_mode NULL
+
 #endif /* CONFIG_IIO_BUFFER */
 
 #endif
diff --git a/drivers/staging/iio/imu/adis_buffer.c b/drivers/staging/iio/imu/adis_buffer.c
index 0fa8e80a..342758c 100644
--- a/drivers/staging/iio/imu/adis_buffer.c
+++ b/drivers/staging/iio/imu/adis_buffer.c
@@ -1,3 +1,12 @@
+/*
+ * 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>
@@ -12,73 +21,80 @@
 
 #include  "adis.h"
 
-#define ADIS_MAX_OUTPUTS 12
-
-static int adis_read_buffer_data(struct adis *adis, struct iio_dev *indio_dev)
+int adis_update_scan_mode(struct iio_dev *indio_dev,
+	const unsigned long *scan_mask)
 {
-	int n_outputs = indio_dev->num_channels;
-	struct spi_transfer xfers[ADIS_MAX_OUTPUTS + 1];
-	struct spi_message msg;
-	int ret;
-	int i;
-
-	mutex_lock(&adis->txrx_lock);
-
-	spi_message_init(&msg);
-
-	memset(xfers, 0, sizeof(xfers));
-	for (i = 0; i <= n_outputs; i++) {
-		xfers[i].bits_per_word = 8;
-		xfers[i].cs_change = 1;
-		xfers[i].len = 2;
-		xfers[i].delay_usecs = adis->data->read_delay;
-		if (i < n_outputs) {
-			xfers[i].tx_buf = adis->tx + 2 * i;
-			adis->tx[2 * i] = indio_dev->channels[i].address;
-			adis->tx[2 * i + 1] = 0;
-		}
-		if (i >= 1)
-			xfers[i].rx_buf = adis->rx + 2 * (i - 1);
-		spi_message_add_tail(&xfers[i], &msg);
-	}
+	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;
 
-	ret = spi_sync(adis->spi, &msg);
-	if (ret)
-		dev_err(&adis->spi->dev, "Failed to read data: %d", ret);
+	kfree(adis->xfer);
+	kfree(adis->buffer);
 
-	mutex_unlock(&adis->txrx_lock);
+	scan_count = indio_dev->scan_bytes / 2;
 
-	return ret;
+	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;
+		*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);
-	u16 *data;
-	int i = 0;
+	int ret;
 
-	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-	if (data == NULL) {
-		dev_err(&adis->spi->dev, "Failed to allocate memory.");
+	if (!adis->buffer)
 		return -ENOMEM;
-	}
 
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)
-	    && adis_read_buffer_data(adis, indio_dev) >= 0)
-		for (; i < bitmap_weight(indio_dev->active_scan_mask,
-					 indio_dev->masklength); i++)
-			data[i] = be16_to_cpup((__be16 *)&(adis->rx[i*2]));
+	ret = spi_sync(adis->spi, &adis->msg);
+	if (ret)
+		dev_err(&adis->spi->dev, "Failed to read data: %d", ret);
 
 	/* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp)
-		*((s64 *)(PTR_ALIGN(data, sizeof(s64)))) = pf->timestamp;
+	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, (u8 *)data);
+	iio_push_to_buffers(indio_dev, adis->buffer);
 
 	iio_trigger_notify_done(indio_dev->trig);
-	kfree(data);
 
 	return IRQ_HANDLED;
 }
@@ -137,6 +153,8 @@ void adis_cleanup_buffer_and_trigger(struct adis *adis,
 {
 	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);
-- 
1.8.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 11/11] staging:iio: Move adis library out of staging
  2012-11-13 13:28 [PATCH 01/11] staging:iio: Add common ADIS library Lars-Peter Clausen
                   ` (8 preceding siblings ...)
  2012-11-13 13:28 ` [PATCH 10/11] staging:iio:adis: Preallocate transfer message Lars-Peter Clausen
@ 2012-11-13 13:28 ` Lars-Peter Clausen
  2012-11-17 11:00   ` Jonathan Cameron
  2012-11-17 11:01 ` [PATCH 01/11] staging:iio: Add common ADIS library Jonathan Cameron
  10 siblings, 1 reply; 13+ messages in thread
From: Lars-Peter Clausen @ 2012-11-13 13:28 UTC (permalink / raw)
  To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen

Now that the adis library no longer depends on the sw_ring buffer implementation
we can move it out of staging.

While we are at it also sort the entries in the iio Kconfig and Makefile to be
in alphabetical order.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/iio/Kconfig                               |  7 ++++---
 drivers/iio/Makefile                              |  7 ++++---
 drivers/iio/imu/Kconfig                           | 11 +++++++++++
 drivers/iio/imu/Makefile                          |  8 ++++++++
 drivers/{staging => }/iio/imu/adis.c              |  3 +--
 drivers/{staging => }/iio/imu/adis_buffer.c       |  3 +--
 drivers/{staging => }/iio/imu/adis_trigger.c      |  3 +--
 drivers/staging/iio/accel/adis16201_core.c        |  2 +-
 drivers/staging/iio/accel/adis16203_core.c        |  2 +-
 drivers/staging/iio/accel/adis16204_core.c        |  2 +-
 drivers/staging/iio/accel/adis16209_core.c        |  2 +-
 drivers/staging/iio/accel/adis16220.h             |  2 +-
 drivers/staging/iio/accel/adis16240_core.c        |  2 +-
 drivers/staging/iio/gyro/adis16260.h              |  2 +-
 drivers/staging/iio/imu/Kconfig                   | 12 ------------
 drivers/staging/iio/imu/Makefile                  |  5 -----
 {drivers/staging => include/linux}/iio/imu/adis.h |  0
 17 files changed, 37 insertions(+), 36 deletions(-)
 create mode 100644 drivers/iio/imu/Kconfig
 create mode 100644 drivers/iio/imu/Makefile
 rename drivers/{staging => }/iio/imu/adis.c (99%)
 rename drivers/{staging => }/iio/imu/adis_buffer.c (99%)
 rename drivers/{staging => }/iio/imu/adis_trigger.c (98%)
 rename {drivers/staging => include/linux}/iio/imu/adis.h (100%)

diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index 65ae734..b2f963b 100644
--- a/drivers/iio/Kconfig
+++ b/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
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index 31d76a0..a0e8cdd 100644
--- a/drivers/iio/Makefile
+++ b/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/
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
new file mode 100644
index 0000000..9e4bc1a
--- /dev/null
+++ b/drivers/iio/imu/Kconfig
@@ -0,0 +1,11 @@
+config IIO_ADIS_LIB
+	tristate
+	help
+	  A set of IO helper functions for the Analog Devices ADIS* device family.
+
+config IIO_ADIS_LIB_BUFFER
+	bool
+	select IIO_TRIGGERED_BUFFER
+	help
+	  A set of buffer helper functions for the Analog Devices ADIS* device
+	  family.
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
new file mode 100644
index 0000000..97676ab
--- /dev/null
+++ b/drivers/iio/imu/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for Inertial Measurement Units
+#
+
+adis_lib-y += adis.o
+adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o
+adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
+obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
diff --git a/drivers/staging/iio/imu/adis.c b/drivers/iio/imu/adis.c
similarity index 99%
rename from drivers/staging/iio/imu/adis.c
rename to drivers/iio/imu/adis.c
index 0bd21022..8259b77 100644
--- a/drivers/staging/iio/imu/adis.c
+++ b/drivers/iio/imu/adis.c
@@ -20,8 +20,7 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
-
-#include "adis.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)
diff --git a/drivers/staging/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c
similarity index 99%
rename from drivers/staging/iio/imu/adis_buffer.c
rename to drivers/iio/imu/adis_buffer.c
index 342758c..a91b4cb 100644
--- a/drivers/staging/iio/imu/adis_buffer.c
+++ b/drivers/iio/imu/adis_buffer.c
@@ -18,8 +18,7 @@
 #include <linux/iio/buffer.h>
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/triggered_buffer.h>
-
-#include  "adis.h"
+#include <linux/iio/imu/adis.h>
 
 int adis_update_scan_mode(struct iio_dev *indio_dev,
 	const unsigned long *scan_mask)
diff --git a/drivers/staging/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c
similarity index 98%
rename from drivers/staging/iio/imu/adis_trigger.c
rename to drivers/iio/imu/adis_trigger.c
index 3e89b2e..5a24c9c 100644
--- a/drivers/staging/iio/imu/adis_trigger.c
+++ b/drivers/iio/imu/adis_trigger.c
@@ -14,8 +14,7 @@
 
 #include <linux/iio/iio.h>
 #include <linux/iio/trigger.h>
-
-#include "adis.h"
+#include <linux/iio/imu/adis.h>
 
 static int adis_data_rdy_trigger_set_state(struct iio_trigger *trig,
 						bool state)
diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c
index 833dd6b..ccdc8d2 100644
--- a/drivers/staging/iio/accel/adis16201_core.c
+++ b/drivers/staging/iio/accel/adis16201_core.c
@@ -18,9 +18,9 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
 
 #include "adis16201.h"
-#include "../imu/adis.h"
 
 static const u8 adis16201_addresses[] = {
 	[ADIS16201_SCAN_ACC_X] = ADIS16201_XACCL_OFFS,
diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c
index f631e57..202985e 100644
--- a/drivers/staging/iio/accel/adis16203_core.c
+++ b/drivers/staging/iio/accel/adis16203_core.c
@@ -18,9 +18,9 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
 
 #include "adis16203.h"
-#include "../imu/adis.h"
 
 #define DRIVER_NAME		"adis16203"
 
diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c
index dbec841..6dafad6 100644
--- a/drivers/staging/iio/accel/adis16204_core.c
+++ b/drivers/staging/iio/accel/adis16204_core.c
@@ -21,9 +21,9 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
 
 #include "adis16204.h"
-#include "../imu/adis.h"
 
 /* Unique to this driver currently */
 
diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c
index f9f9d58..d2921c3 100644
--- a/drivers/staging/iio/accel/adis16209_core.c
+++ b/drivers/staging/iio/accel/adis16209_core.c
@@ -19,9 +19,9 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
 
 #include "adis16209.h"
-#include "../imu/adis.h"
 
 static const u8 adis16209_addresses[8][1] = {
 	[ADIS16209_SCAN_SUPPLY] = { },
diff --git a/drivers/staging/iio/accel/adis16220.h b/drivers/staging/iio/accel/adis16220.h
index 7cc4d2f..a894ad7 100644
--- a/drivers/staging/iio/accel/adis16220.h
+++ b/drivers/staging/iio/accel/adis16220.h
@@ -1,7 +1,7 @@
 #ifndef SPI_ADIS16220_H_
 #define SPI_ADIS16220_H_
 
-#include "../imu/adis.h"
+#include <linux/iio/imu/adis.h>
 
 #define ADIS16220_STARTUP_DELAY	220 /* ms */
 
diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c
index 3d1a8a9..d098b49 100644
--- a/drivers/staging/iio/accel/adis16240_core.c
+++ b/drivers/staging/iio/accel/adis16240_core.c
@@ -22,9 +22,9 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
 
 #include "adis16240.h"
-#include "../imu/adis.h"
 
 static ssize_t adis16240_spi_read_signed(struct device *dev,
 		struct device_attribute *attr,
diff --git a/drivers/staging/iio/gyro/adis16260.h b/drivers/staging/iio/gyro/adis16260.h
index ea5eba2..df3c0b7 100644
--- a/drivers/staging/iio/gyro/adis16260.h
+++ b/drivers/staging/iio/gyro/adis16260.h
@@ -2,7 +2,7 @@
 #define SPI_ADIS16260_H_
 
 #include "adis16260_platform_data.h"
-#include "../imu/adis.h"
+#include <linux/iio/imu/adis.h>
 
 #define ADIS16260_STARTUP_DELAY	220 /* ms */
 
diff --git a/drivers/staging/iio/imu/Kconfig b/drivers/staging/iio/imu/Kconfig
index 2c564ed..2c2f47d 100644
--- a/drivers/staging/iio/imu/Kconfig
+++ b/drivers/staging/iio/imu/Kconfig
@@ -15,15 +15,3 @@ config ADIS16400
 	  (adis16400 series also have magnetometers).
 
 endmenu
-
-config IIO_ADIS_LIB
-	tristate
-	help
-	  A set of IO helper functions for the Analog Devices ADIS* device family.
-
-config IIO_ADIS_LIB_BUFFER
-	bool
-	select IIO_TRIGGERED_BUFFER
-	help
-	  A set of buffer helper functions for the Analog Devices ADIS* device
-	  family.
diff --git a/drivers/staging/iio/imu/Makefile b/drivers/staging/iio/imu/Makefile
index 65dafba..3400a13 100644
--- a/drivers/staging/iio/imu/Makefile
+++ b/drivers/staging/iio/imu/Makefile
@@ -5,8 +5,3 @@
 adis16400-y             := adis16400_core.o
 adis16400-$(CONFIG_IIO_BUFFER) += adis16400_ring.o adis16400_trigger.o
 obj-$(CONFIG_ADIS16400) += adis16400.o
-
-adis_lib-y += adis.o
-adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o
-adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
-obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
diff --git a/drivers/staging/iio/imu/adis.h b/include/linux/iio/imu/adis.h
similarity index 100%
rename from drivers/staging/iio/imu/adis.h
rename to include/linux/iio/imu/adis.h
-- 
1.8.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 11/11] staging:iio: Move adis library out of staging
  2012-11-13 13:28 ` [PATCH 11/11] staging:iio: Move adis library out of staging Lars-Peter Clausen
@ 2012-11-17 11:00   ` Jonathan Cameron
  0 siblings, 0 replies; 13+ messages in thread
From: Jonathan Cameron @ 2012-11-17 11:00 UTC (permalink / raw)
  To: Lars-Peter Clausen; +Cc: Jonathan Cameron, linux-iio, drivers

On 11/13/2012 01:28 PM, Lars-Peter Clausen wrote:
> Now that the adis library no longer depends on the sw_ring buffer implementation
> we can move it out of staging.
> 
> While we are at it also sort the entries in the iio Kconfig and Makefile to be
> in alphabetical order.
hmm.. slight moan here.  Would have prefered a separate precursor patch to fix
the ordering in kconfig and make file...

> 
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Merged with the rest into iio.git to greg branch.

Thanks,

Jonathan
> ---
>  drivers/iio/Kconfig                               |  7 ++++---
>  drivers/iio/Makefile                              |  7 ++++---
>  drivers/iio/imu/Kconfig                           | 11 +++++++++++
>  drivers/iio/imu/Makefile                          |  8 ++++++++
>  drivers/{staging => }/iio/imu/adis.c              |  3 +--
>  drivers/{staging => }/iio/imu/adis_buffer.c       |  3 +--
>  drivers/{staging => }/iio/imu/adis_trigger.c      |  3 +--
>  drivers/staging/iio/accel/adis16201_core.c        |  2 +-
>  drivers/staging/iio/accel/adis16203_core.c        |  2 +-
>  drivers/staging/iio/accel/adis16204_core.c        |  2 +-
>  drivers/staging/iio/accel/adis16209_core.c        |  2 +-
>  drivers/staging/iio/accel/adis16220.h             |  2 +-
>  drivers/staging/iio/accel/adis16240_core.c        |  2 +-
>  drivers/staging/iio/gyro/adis16260.h              |  2 +-
>  drivers/staging/iio/imu/Kconfig                   | 12 ------------
>  drivers/staging/iio/imu/Makefile                  |  5 -----
>  {drivers/staging => include/linux}/iio/imu/adis.h |  0
>  17 files changed, 37 insertions(+), 36 deletions(-)
>  create mode 100644 drivers/iio/imu/Kconfig
>  create mode 100644 drivers/iio/imu/Makefile
>  rename drivers/{staging => }/iio/imu/adis.c (99%)
>  rename drivers/{staging => }/iio/imu/adis_buffer.c (99%)
>  rename drivers/{staging => }/iio/imu/adis_trigger.c (98%)
>  rename {drivers/staging => include/linux}/iio/imu/adis.h (100%)
> 
> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
> index 65ae734..b2f963b 100644
> --- a/drivers/iio/Kconfig
> +++ b/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
> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
> index 31d76a0..a0e8cdd 100644
> --- a/drivers/iio/Makefile
> +++ b/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/
> diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
> new file mode 100644
> index 0000000..9e4bc1a
> --- /dev/null
> +++ b/drivers/iio/imu/Kconfig
> @@ -0,0 +1,11 @@
> +config IIO_ADIS_LIB
> +	tristate
> +	help
> +	  A set of IO helper functions for the Analog Devices ADIS* device family.
> +
> +config IIO_ADIS_LIB_BUFFER
> +	bool
> +	select IIO_TRIGGERED_BUFFER
> +	help
> +	  A set of buffer helper functions for the Analog Devices ADIS* device
> +	  family.
> diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
> new file mode 100644
> index 0000000..97676ab
> --- /dev/null
> +++ b/drivers/iio/imu/Makefile
> @@ -0,0 +1,8 @@
> +#
> +# Makefile for Inertial Measurement Units
> +#
> +
> +adis_lib-y += adis.o
> +adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o
> +adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
> +obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
> diff --git a/drivers/staging/iio/imu/adis.c b/drivers/iio/imu/adis.c
> similarity index 99%
> rename from drivers/staging/iio/imu/adis.c
> rename to drivers/iio/imu/adis.c
> index 0bd21022..8259b77 100644
> --- a/drivers/staging/iio/imu/adis.c
> +++ b/drivers/iio/imu/adis.c
> @@ -20,8 +20,7 @@
>  #include <linux/iio/iio.h>
>  #include <linux/iio/sysfs.h>
>  #include <linux/iio/buffer.h>
> -
> -#include "adis.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)
> diff --git a/drivers/staging/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c
> similarity index 99%
> rename from drivers/staging/iio/imu/adis_buffer.c
> rename to drivers/iio/imu/adis_buffer.c
> index 342758c..a91b4cb 100644
> --- a/drivers/staging/iio/imu/adis_buffer.c
> +++ b/drivers/iio/imu/adis_buffer.c
> @@ -18,8 +18,7 @@
>  #include <linux/iio/buffer.h>
>  #include <linux/iio/trigger_consumer.h>
>  #include <linux/iio/triggered_buffer.h>
> -
> -#include  "adis.h"
> +#include <linux/iio/imu/adis.h>
>  
>  int adis_update_scan_mode(struct iio_dev *indio_dev,
>  	const unsigned long *scan_mask)
> diff --git a/drivers/staging/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c
> similarity index 98%
> rename from drivers/staging/iio/imu/adis_trigger.c
> rename to drivers/iio/imu/adis_trigger.c
> index 3e89b2e..5a24c9c 100644
> --- a/drivers/staging/iio/imu/adis_trigger.c
> +++ b/drivers/iio/imu/adis_trigger.c
> @@ -14,8 +14,7 @@
>  
>  #include <linux/iio/iio.h>
>  #include <linux/iio/trigger.h>
> -
> -#include "adis.h"
> +#include <linux/iio/imu/adis.h>
>  
>  static int adis_data_rdy_trigger_set_state(struct iio_trigger *trig,
>  						bool state)
> diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c
> index 833dd6b..ccdc8d2 100644
> --- a/drivers/staging/iio/accel/adis16201_core.c
> +++ b/drivers/staging/iio/accel/adis16201_core.c
> @@ -18,9 +18,9 @@
>  #include <linux/iio/iio.h>
>  #include <linux/iio/sysfs.h>
>  #include <linux/iio/buffer.h>
> +#include <linux/iio/imu/adis.h>
>  
>  #include "adis16201.h"
> -#include "../imu/adis.h"
>  
>  static const u8 adis16201_addresses[] = {
>  	[ADIS16201_SCAN_ACC_X] = ADIS16201_XACCL_OFFS,
> diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c
> index f631e57..202985e 100644
> --- a/drivers/staging/iio/accel/adis16203_core.c
> +++ b/drivers/staging/iio/accel/adis16203_core.c
> @@ -18,9 +18,9 @@
>  #include <linux/iio/iio.h>
>  #include <linux/iio/sysfs.h>
>  #include <linux/iio/buffer.h>
> +#include <linux/iio/imu/adis.h>
>  
>  #include "adis16203.h"
> -#include "../imu/adis.h"
>  
>  #define DRIVER_NAME		"adis16203"
>  
> diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c
> index dbec841..6dafad6 100644
> --- a/drivers/staging/iio/accel/adis16204_core.c
> +++ b/drivers/staging/iio/accel/adis16204_core.c
> @@ -21,9 +21,9 @@
>  #include <linux/iio/iio.h>
>  #include <linux/iio/sysfs.h>
>  #include <linux/iio/buffer.h>
> +#include <linux/iio/imu/adis.h>
>  
>  #include "adis16204.h"
> -#include "../imu/adis.h"
>  
>  /* Unique to this driver currently */
>  
> diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c
> index f9f9d58..d2921c3 100644
> --- a/drivers/staging/iio/accel/adis16209_core.c
> +++ b/drivers/staging/iio/accel/adis16209_core.c
> @@ -19,9 +19,9 @@
>  #include <linux/iio/iio.h>
>  #include <linux/iio/sysfs.h>
>  #include <linux/iio/buffer.h>
> +#include <linux/iio/imu/adis.h>
>  
>  #include "adis16209.h"
> -#include "../imu/adis.h"
>  
>  static const u8 adis16209_addresses[8][1] = {
>  	[ADIS16209_SCAN_SUPPLY] = { },
> diff --git a/drivers/staging/iio/accel/adis16220.h b/drivers/staging/iio/accel/adis16220.h
> index 7cc4d2f..a894ad7 100644
> --- a/drivers/staging/iio/accel/adis16220.h
> +++ b/drivers/staging/iio/accel/adis16220.h
> @@ -1,7 +1,7 @@
>  #ifndef SPI_ADIS16220_H_
>  #define SPI_ADIS16220_H_
>  
> -#include "../imu/adis.h"
> +#include <linux/iio/imu/adis.h>
>  
>  #define ADIS16220_STARTUP_DELAY	220 /* ms */
>  
> diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c
> index 3d1a8a9..d098b49 100644
> --- a/drivers/staging/iio/accel/adis16240_core.c
> +++ b/drivers/staging/iio/accel/adis16240_core.c
> @@ -22,9 +22,9 @@
>  #include <linux/iio/iio.h>
>  #include <linux/iio/sysfs.h>
>  #include <linux/iio/buffer.h>
> +#include <linux/iio/imu/adis.h>
>  
>  #include "adis16240.h"
> -#include "../imu/adis.h"
>  
>  static ssize_t adis16240_spi_read_signed(struct device *dev,
>  		struct device_attribute *attr,
> diff --git a/drivers/staging/iio/gyro/adis16260.h b/drivers/staging/iio/gyro/adis16260.h
> index ea5eba2..df3c0b7 100644
> --- a/drivers/staging/iio/gyro/adis16260.h
> +++ b/drivers/staging/iio/gyro/adis16260.h
> @@ -2,7 +2,7 @@
>  #define SPI_ADIS16260_H_
>  
>  #include "adis16260_platform_data.h"
> -#include "../imu/adis.h"
> +#include <linux/iio/imu/adis.h>
>  
>  #define ADIS16260_STARTUP_DELAY	220 /* ms */
>  
> diff --git a/drivers/staging/iio/imu/Kconfig b/drivers/staging/iio/imu/Kconfig
> index 2c564ed..2c2f47d 100644
> --- a/drivers/staging/iio/imu/Kconfig
> +++ b/drivers/staging/iio/imu/Kconfig
> @@ -15,15 +15,3 @@ config ADIS16400
>  	  (adis16400 series also have magnetometers).
>  
>  endmenu
> -
> -config IIO_ADIS_LIB
> -	tristate
> -	help
> -	  A set of IO helper functions for the Analog Devices ADIS* device family.
> -
> -config IIO_ADIS_LIB_BUFFER
> -	bool
> -	select IIO_TRIGGERED_BUFFER
> -	help
> -	  A set of buffer helper functions for the Analog Devices ADIS* device
> -	  family.
> diff --git a/drivers/staging/iio/imu/Makefile b/drivers/staging/iio/imu/Makefile
> index 65dafba..3400a13 100644
> --- a/drivers/staging/iio/imu/Makefile
> +++ b/drivers/staging/iio/imu/Makefile
> @@ -5,8 +5,3 @@
>  adis16400-y             := adis16400_core.o
>  adis16400-$(CONFIG_IIO_BUFFER) += adis16400_ring.o adis16400_trigger.o
>  obj-$(CONFIG_ADIS16400) += adis16400.o
> -
> -adis_lib-y += adis.o
> -adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o
> -adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
> -obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
> diff --git a/drivers/staging/iio/imu/adis.h b/include/linux/iio/imu/adis.h
> similarity index 100%
> rename from drivers/staging/iio/imu/adis.h
> rename to include/linux/iio/imu/adis.h
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 01/11] staging:iio: Add common ADIS library
  2012-11-13 13:28 [PATCH 01/11] staging:iio: Add common ADIS library Lars-Peter Clausen
                   ` (9 preceding siblings ...)
  2012-11-13 13:28 ` [PATCH 11/11] staging:iio: Move adis library out of staging Lars-Peter Clausen
@ 2012-11-17 11:01 ` Jonathan Cameron
  10 siblings, 0 replies; 13+ messages in thread
From: Jonathan Cameron @ 2012-11-17 11:01 UTC (permalink / raw)
  To: Lars-Peter Clausen; +Cc: Jonathan Cameron, linux-iio, drivers

On 11/13/2012 01:28 PM, Lars-Peter Clausen wrote:
> A lot of the devices from the ADIS family use the same methods for accessing
> registers, sampling data and trigger handling. They also have similar register
> layout for the control registers.
> 
> This patch adds a common library for these devices. The library implements
> functions for reading and writing registers as buffer and trigger management. It
> also provides a set functions for accessing the control registers and for
> running the devices internal self-test. Having this common library code will
> allow us to remove a lot of duplicated code.

Excellent work. This series is exactly what I like to see. Nicely broken up with
one step per patch.  I kept reading this and thinking 'why is he still using that?'
only to notice the drivers you are working with are using the old methods / buffer,
and that you change over to the more recent method with the cleanup patches at the end.
(exactly as it should be done even if I am usually too lazy to do it myself sometimes ;)

So far all I've found is an 'a' where it should be an 'an'.  I think I'll just
ignore that ;)


> 
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
>  drivers/staging/iio/imu/Kconfig        |  13 ++
>  drivers/staging/iio/imu/Makefile       |   5 +
>  drivers/staging/iio/imu/adis.c         | 338 +++++++++++++++++++++++++++++++++
>  drivers/staging/iio/imu/adis.h         | 178 +++++++++++++++++
>  drivers/staging/iio/imu/adis_buffer.c  | 200 +++++++++++++++++++
>  drivers/staging/iio/imu/adis_trigger.c |  90 +++++++++
>  6 files changed, 824 insertions(+)
>  create mode 100644 drivers/staging/iio/imu/adis.c
>  create mode 100644 drivers/staging/iio/imu/adis.h
>  create mode 100644 drivers/staging/iio/imu/adis_buffer.c
>  create mode 100644 drivers/staging/iio/imu/adis_trigger.c
> 
> diff --git a/drivers/staging/iio/imu/Kconfig b/drivers/staging/iio/imu/Kconfig
> index 2c2f47d..89b9f25 100644
> --- a/drivers/staging/iio/imu/Kconfig
> +++ b/drivers/staging/iio/imu/Kconfig
> @@ -15,3 +15,16 @@ config ADIS16400
>  	  (adis16400 series also have magnetometers).
>  
>  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_TRIGGER
> +	select IIO_SW_RING
> +	help
> +	  A set of buffer helper functions for the Analog Devices ADIS* device
> +	  family.
> diff --git a/drivers/staging/iio/imu/Makefile b/drivers/staging/iio/imu/Makefile
> index 3400a13..65dafba 100644
> --- a/drivers/staging/iio/imu/Makefile
> +++ b/drivers/staging/iio/imu/Makefile
> @@ -5,3 +5,8 @@
>  adis16400-y             := adis16400_core.o
>  adis16400-$(CONFIG_IIO_BUFFER) += adis16400_ring.o adis16400_trigger.o
>  obj-$(CONFIG_ADIS16400) += adis16400.o
> +
> +adis_lib-y += adis.o
> +adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o
> +adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
> +obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
> diff --git a/drivers/staging/iio/imu/adis.c b/drivers/staging/iio/imu/adis.c
> new file mode 100644
> index 0000000..0bd21022
> --- /dev/null
> +++ b/drivers/staging/iio/imu/adis.c
> @@ -0,0 +1,338 @@
> +/*
> + * 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 "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)
> +
> +/**
> + * adis_write_reg_8() - Write single byte to a register
> + * @adis: The adis device
> + * @reg: The address of the register to be written
> + * @val: The value to write
> + */
> +int adis_write_reg_8(struct adis *adis, unsigned int reg, uint8_t val)
> +{
> +	int ret;
> +
> +	mutex_lock(&adis->txrx_lock);
> +	adis->tx[0] = ADIS_WRITE_REG(reg);
> +	adis->tx[1] = val;
> +
> +	ret = spi_write(adis->spi, adis->tx, 2);
> +	mutex_unlock(&adis->txrx_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(adis_write_reg_8);
> +
> +/**
> + * 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
> + * @val: Value to be written
> + */
> +int adis_write_reg_16(struct adis *adis, unsigned int reg, uint16_t value)
> +{
> +	int ret;
> +	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,
> +			.delay_usecs = adis->data->write_delay,
> +		},
> +	};
> +
> +	mutex_lock(&adis->txrx_lock);
> +	adis->tx[0] = ADIS_WRITE_REG(reg);
> +	adis->tx[1] = value & 0xff;
> +	adis->tx[2] = ADIS_WRITE_REG(reg + 1);
> +	adis->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(adis->spi, &msg);
> +	mutex_unlock(&adis->txrx_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(adis_write_reg_16);
> +
> +/**
> + * 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
> + */
> +int adis_read_reg_16(struct adis *adis, unsigned int reg, uint16_t *val)
> +{
> +	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->read_delay,
> +		}, {
> +			.rx_buf = adis->rx,
> +			.bits_per_word = 8,
> +			.len = 2,
> +			.delay_usecs = adis->data->read_delay,
> +		},
> +	};
> +
> +	mutex_lock(&adis->txrx_lock);
> +	adis->tx[0] = ADIS_READ_REG(reg);
> +	adis->tx[1] = 0;
> +
> +	spi_message_init(&msg);
> +	spi_message_add_tail(&xfers[0], &msg);
> +	spi_message_add_tail(&xfers[1], &msg);
> +	ret = spi_sync(adis->spi, &msg);
> +	if (ret) {
> +		dev_err(&adis->spi->dev, "Failed to read 16 bit register 0x%02X: %d\n",
> +				reg, ret);
> +		goto error_ret;
> +	}
> +	*val = get_unaligned_be16(adis->rx);
> +
> +error_ret:
> +	mutex_unlock(&adis->txrx_lock);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(adis_read_reg_16);
> +
> +/**
> + * 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;
> +
> +	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);
> +	uint16_t val16;
> +	int ret;
> +
> +	mutex_lock(&indio_dev->mlock);
> +
> +	ret = adis_read_reg_16(adis, chan->address, &val16);
> +	if (ret)
> +		goto err_unlock;
> +
> +	if (val16 & error_mask) {
> +		ret = adis_check_status(adis);
> +		if (ret)
> +			goto err_unlock;
> +	}
> +
> +	if (chan->scan_type.sign == 's')
> +		*val = sign_extend32(val16, chan->scan_type.realbits - 1);
> +	else
> +		*val = val16 & ((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);
> +
> +	return adis_enable_irq(adis, false);
> +}
> +EXPORT_SYMBOL_GPL(adis_init);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
> +MODULE_DESCRIPTION("Common library code for ADIS16XXX devices");
> diff --git a/drivers/staging/iio/imu/adis.h b/drivers/staging/iio/imu/adis.h
> new file mode 100644
> index 0000000..c84da7a
> --- /dev/null
> +++ b/drivers/staging/iio/imu/adis.h
> @@ -0,0 +1,178 @@
> +/*
> + * 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)
> +
> +/**
> + * 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;
> +};
> +
> +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;
> +	void			*buffer;
> +
> +	uint8_t			tx[8] ____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_8(struct adis *adis, unsigned int reg, uint8_t val);
> +int adis_write_reg_16(struct adis *adis, unsigned int reg, uint16_t val);
> +int adis_read_reg_16(struct adis *adis, unsigned int reg, uint16_t *val);
> +
> +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, \
> +	}, \
> +}
> +
> +#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, \
> +	}, \
> +}
> +
> +#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, \
> +	}, \
> +}
> +
> +#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);
> +
> +#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)
> +{
> +}
> +
> +#endif /* CONFIG_IIO_BUFFER */
> +
> +#endif
> diff --git a/drivers/staging/iio/imu/adis_buffer.c b/drivers/staging/iio/imu/adis_buffer.c
> new file mode 100644
> index 0000000..47bdea0
> --- /dev/null
> +++ b/drivers/staging/iio/imu/adis_buffer.c
> @@ -0,0 +1,200 @@
> +#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 "../ring_sw.h"
> +#include <linux/iio/trigger_consumer.h>
> +
> +#include  "adis.h"
> +
> +#define ADIS_MAX_OUTPUTS 12
> +
> +static int adis_read_buffer_data(struct adis *adis, struct iio_dev *indio_dev)
> +{
> +	int n_outputs = indio_dev->num_channels;
> +	struct spi_transfer xfers[ADIS_MAX_OUTPUTS + 1];
> +	struct spi_message msg;
> +	int ret;
> +	int i;
> +
> +	mutex_lock(&adis->txrx_lock);
> +
> +	spi_message_init(&msg);
> +
> +	memset(xfers, 0, sizeof(xfers));
> +	for (i = 0; i <= n_outputs; i++) {
> +		xfers[i].bits_per_word = 8;
> +		xfers[i].cs_change = 1;
> +		xfers[i].len = 2;
> +		xfers[i].delay_usecs = adis->data->read_delay;
> +		if (i < n_outputs) {
> +			xfers[i].tx_buf = adis->tx + 2 * i;
> +			adis->tx[2 * i] = indio_dev->channels[i].address;
> +			adis->tx[2 * i + 1] = 0;
> +		}
> +		if (i >= 1)
> +			xfers[i].rx_buf = adis->rx + 2 * (i - 1);
> +		spi_message_add_tail(&xfers[i], &msg);
> +	}
> +
> +	ret = spi_sync(adis->spi, &msg);
> +	if (ret)
> +		dev_err(&adis->spi->dev, "Failed to read data: %d", ret);
> +
> +	mutex_unlock(&adis->txrx_lock);
> +
> +	return ret;
> +}
> +
> +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);
> +	u16 *data;
> +	int i = 0;
> +
> +	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
> +	if (data == NULL) {
> +		dev_err(&adis->spi->dev, "Failed to allocate memory.");
> +		return -ENOMEM;
> +	}
> +
> +	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)
> +	    && adis_read_buffer_data(adis, indio_dev) >= 0)
> +		for (; i < bitmap_weight(indio_dev->active_scan_mask,
> +					 indio_dev->masklength); i++)
> +			data[i] = be16_to_cpup((__be16 *)&(adis->rx[i*2]));
> +
> +	/* Guaranteed to be aligned with 8 byte boundary */
> +	if (indio_dev->scan_timestamp)
> +		*((s64 *)(PTR_ALIGN(data, sizeof(s64)))) = pf->timestamp;
> +
> +	iio_push_to_buffers(indio_dev, (u8 *)data);
> +
> +	iio_trigger_notify_done(indio_dev->trig);
> +	kfree(data);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static const struct iio_buffer_setup_ops adis_buffer_setup_ops = {
> +	.preenable = &iio_sw_buffer_preenable,
> +	.postenable = &iio_triggered_buffer_postenable,
> +	.predisable = &iio_triggered_buffer_predisable,
> +};
> +
> +static int adis_buffer_setup(struct iio_dev *indio_dev,
> +	irqreturn_t (*trigger_handler)(int, void *))
> +{
> +	int ret = 0;
> +	struct iio_buffer *buffer;
> +
> +	if (!trigger_handler)
> +		trigger_handler = &adis_trigger_handler;
> +
> +	buffer = iio_sw_rb_allocate(indio_dev);
> +	if (!buffer) {
> +		ret = -ENOMEM;
> +		return ret;
> +	}
> +
> +	indio_dev->buffer = buffer;
> +	indio_dev->setup_ops = &adis_buffer_setup_ops;
> +
> +	indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
> +						 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;
> +}
> +
> +static void adis_buffer_cleanup(struct iio_dev *indio_dev)
> +{
> +	iio_dealloc_pollfunc(indio_dev->pollfunc);
> +	iio_sw_rb_free(indio_dev->buffer);
> +}
> +
> +/**
> + * 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;
> +
> +	ret = adis_buffer_setup(indio_dev, trigger_handler);
> +	if (ret)
> +		return ret;
> +
> +	ret = iio_buffer_register(indio_dev,
> +				  indio_dev->channels,
> +				  indio_dev->num_channels);
> +	if (ret) {
> +		dev_err(&adis->spi->dev, "Failed to initialize buffer %d\n",
> +			ret);
> +		goto error_unreg_buffer_funcs;
> +	}
> +
> +	if (adis->spi->irq) {
> +		ret = adis_probe_trigger(adis, indio_dev);
> +		if (ret)
> +			goto error_uninitialize_buffer;
> +	}
> +	return 0;
> +
> +error_uninitialize_buffer:
> +	iio_buffer_unregister(indio_dev);
> +error_unreg_buffer_funcs:
> +	adis_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);
> +	iio_buffer_unregister(indio_dev);
> +	adis_buffer_cleanup(indio_dev);
> +}
> +EXPORT_SYMBOL_GPL(adis_cleanup_buffer_and_trigger);
> diff --git a/drivers/staging/iio/imu/adis_trigger.c b/drivers/staging/iio/imu/adis_trigger.c
> new file mode 100644
> index 0000000..3e89b2e
> --- /dev/null
> +++ b/drivers/staging/iio/imu/adis_trigger.c
> @@ -0,0 +1,90 @@
> +/*
> + * 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 "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);
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2012-11-17 11:01 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-13 13:28 [PATCH 01/11] staging:iio: Add common ADIS library Lars-Peter Clausen
2012-11-13 13:28 ` [PATCH 02/11] staging:iio:adis16201: Use adis library Lars-Peter Clausen
2012-11-13 13:28 ` [PATCH 03/11] staging:iio:adis16203: " Lars-Peter Clausen
2012-11-13 13:28 ` [PATCH 04/11] staging:iio:adis16204: " Lars-Peter Clausen
2012-11-13 13:28 ` [PATCH 05/11] staging:iio:adis16209: " Lars-Peter Clausen
2012-11-13 13:28 ` [PATCH 06/11] staging:iio:adis16220: " Lars-Peter Clausen
2012-11-13 13:28 ` [PATCH 07/11] staging:iio:adis16240: " Lars-Peter Clausen
2012-11-13 13:28 ` [PATCH 08/11] staging:iio:adis16260: " Lars-Peter Clausen
2012-11-13 13:28 ` [PATCH 09/11] staging:iio:adis_lib: Use triggered buffer setup helper function Lars-Peter Clausen
2012-11-13 13:28 ` [PATCH 10/11] staging:iio:adis: Preallocate transfer message Lars-Peter Clausen
2012-11-13 13:28 ` [PATCH 11/11] staging:iio: Move adis library out of staging Lars-Peter Clausen
2012-11-17 11:00   ` Jonathan Cameron
2012-11-17 11:01 ` [PATCH 01/11] staging:iio: Add common ADIS library Jonathan Cameron

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.