All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/20] staging:iio updates Abi changes and new drivers
@ 2010-05-04 13:42 Jonathan Cameron
  2010-05-04 13:42 ` [PATCH 01/20] staging:iio: Add new in_raw definitions for adc channels Jonathan Cameron
  2010-05-04 20:48 ` [PATCH 00/20] staging:iio updates Abi changes and new drivers Greg KH
  0 siblings, 2 replies; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:42 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Dear Greg,

The following set is based upon your staging-next tree as of Sunday.
When the caching updates they should be available on:

git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio-new-abi.git master

so if it is easier for you, pull from there.

The two Analog devices drivers are from the blackfin tree (where numerous
other iio drivers exist). 
git://sources.blackfin.uclinux.org/git/readonly-mirrors/linux-kernel.git

For Barry, I fixed up a couple of dependency issues in imu/Kconfig whilst
merging your drivers.

Minor changes were made to get them to work with the abi changes.  An
incremental patch will follow to fix remaining non conforming abi elements.

The rest are, up to a few typo and merge related fixes, as per V2 posted
widely so this set isn't going to lkml this time round.

I'm guessing everyone who is developing iio drivers is actually on linux-iio.
This will break your drivers if they aren't in mainline, but only in easily
fixed ways (I hope!)

Jonathan


Barry Song (2):
  staging:iio:imu ADIS16300 driver
  staging:iio:imu ADIS16400 and ADIS16405 driver

Jonathan Cameron (18):
  staging:iio: Add new in_raw definitions for adc channels.
  staging:iio: Add new attrs for sampling frequency available and
    temp_raw
  iio:staging:accelerometers move towards the new abi
  staging:iio: Support functions for scan mask matching
  staging: iio: Move from class to bus
  staging:iio: Move event attributes into the event[n] device in sysfs
  staging:iio: Clean out unused IIO_SCAN_EL and add IIO_SCAN_NAMED_EL_C
  staging:iio:max1363 move to new abi.
  staging:iio: Documentation, update iio_utils.h for the move to a bus
  staging:iio: ABI documentation (partial)
  staging:iio: Directory name changes to match new ABI.
  staging:iio:tsl2563: change lux to illuminance0_input to match new
    abi
  staging:iio: Remove naming via IDR's where no longer necessary under
    new abi.
  staging:iio:max1363 add support for max11606-max11617
  staging:iio:max1363 add support for 8 bit equivalent devices,
    max1036-9, max11600-5
  staging:iio:ring_sw: Fix incorrect test on successful read of last
    value, causes infinite loop
  staging:iio:tsl2563 add a name attribute under the iio
  staging:iio:Documentation: Rewrite example for new abi.

 drivers/staging/iio/Documentation/iio_utils.h      |  266 +++--
 .../iio/Documentation/lis3l02dqbuffersimple.c      |  234 +++--
 drivers/staging/iio/Documentation/sysfs-class-iio  |  285 +++++
 drivers/staging/iio/Kconfig                        |    1 +
 drivers/staging/iio/Makefile                       |    1 +
 drivers/staging/iio/accel/accel.h                  |    8 +-
 drivers/staging/iio/accel/kxsd9.c                  |   88 +-
 drivers/staging/iio/accel/lis3l02dq.h              |    4 -
 drivers/staging/iio/accel/lis3l02dq_core.c         |  175 ++--
 drivers/staging/iio/accel/lis3l02dq_ring.c         |   10 +-
 drivers/staging/iio/accel/sca3000.h                |    2 +
 drivers/staging/iio/accel/sca3000_core.c           |  174 ++--
 drivers/staging/iio/accel/sca3000_ring.c           |   33 +-
 drivers/staging/iio/adc/Kconfig                    |   11 +-
 drivers/staging/iio/adc/Makefile                   |    2 +-
 drivers/staging/iio/adc/adc.h                      |   15 +
 drivers/staging/iio/adc/max1363.h                  |  122 +--
 drivers/staging/iio/adc/max1363_core.c             | 1109 ++++++++++++++------
 drivers/staging/iio/adc/max1363_ring.c             |   80 +-
 drivers/staging/iio/chrdev.h                       |    2 +-
 drivers/staging/iio/gyro/gyro.h                    |   76 ++
 drivers/staging/iio/iio.h                          |   47 +-
 drivers/staging/iio/imu/Kconfig                    |   24 +
 drivers/staging/iio/imu/Makefile                   |   10 +
 drivers/staging/iio/imu/adis16300.h                |  203 ++++
 drivers/staging/iio/imu/adis16300_core.c           |  833 +++++++++++++++
 drivers/staging/iio/imu/adis16300_ring.c           |  233 ++++
 drivers/staging/iio/imu/adis16300_trigger.c        |  127 +++
 drivers/staging/iio/imu/adis16400.h                |  238 +++++
 drivers/staging/iio/imu/adis16400_core.c           |  849 +++++++++++++++
 drivers/staging/iio/imu/adis16400_ring.c           |  245 +++++
 drivers/staging/iio/imu/adis16400_trigger.c        |  127 +++
 drivers/staging/iio/industrialio-core.c            |   58 +-
 drivers/staging/iio/industrialio-ring.c            |   63 +-
 drivers/staging/iio/industrialio-trigger.c         |    2 +-
 drivers/staging/iio/light/tsl2563.c                |   16 +-
 drivers/staging/iio/magnetometer/magnet.h          |   31 +
 drivers/staging/iio/ring_generic.h                 |   42 +-
 drivers/staging/iio/ring_sw.c                      |    4 +-
 drivers/staging/iio/sysfs.h                        |   15 +-
 40 files changed, 4936 insertions(+), 929 deletions(-)
 create mode 100644 drivers/staging/iio/Documentation/sysfs-class-iio
 create mode 100644 drivers/staging/iio/gyro/gyro.h
 create mode 100644 drivers/staging/iio/imu/Kconfig
 create mode 100644 drivers/staging/iio/imu/Makefile
 create mode 100644 drivers/staging/iio/imu/adis16300.h
 create mode 100644 drivers/staging/iio/imu/adis16300_core.c
 create mode 100644 drivers/staging/iio/imu/adis16300_ring.c
 create mode 100644 drivers/staging/iio/imu/adis16300_trigger.c
 create mode 100644 drivers/staging/iio/imu/adis16400.h
 create mode 100644 drivers/staging/iio/imu/adis16400_core.c
 create mode 100644 drivers/staging/iio/imu/adis16400_ring.c
 create mode 100644 drivers/staging/iio/imu/adis16400_trigger.c
 create mode 100644 drivers/staging/iio/magnetometer/magnet.h

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

* [PATCH 01/20] staging:iio: Add new in_raw definitions for adc channels.
  2010-05-04 13:42 [PATCH 00/20] staging:iio updates Abi changes and new drivers Jonathan Cameron
@ 2010-05-04 13:42 ` Jonathan Cameron
  2010-05-04 13:42   ` [PATCH 02/20] staging:iio: Add new attrs for sampling frequency available and temp_raw Jonathan Cameron
  2010-05-04 20:48 ` [PATCH 00/20] staging:iio updates Abi changes and new drivers Greg KH
  1 sibling, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:42 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/adc/adc.h |   12 ++++++++++++
 drivers/staging/iio/sysfs.h   |    3 +++
 2 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/iio/adc/adc.h b/drivers/staging/iio/adc/adc.h
index d925b2c..46f0d08 100644
--- a/drivers/staging/iio/adc/adc.h
+++ b/drivers/staging/iio/adc/adc.h
@@ -9,5 +9,17 @@
  *
  */
 
+/* Deprecated */
 #define IIO_DEV_ATTR_ADC(_num, _show, _addr)			\
   IIO_DEVICE_ATTR(adc_##_num, S_IRUGO, _show, NULL, _addr)
+
+#define IIO_DEV_ATTR_IN_RAW(_num, _show, _addr)				\
+	IIO_DEVICE_ATTR(in##_num##_raw, S_IRUGO, _show, NULL, _addr)
+
+#define IIO_DEV_ATTR_IN_DIFF_RAW(_nump, _numn, _show, _addr)		\
+	IIO_DEVICE_ATTR_NAMED(in##_nump##min##_numn##_raw,		\
+			      in##_nump-in##_numn##_raw,		\
+			      S_IRUGO,					\
+			      _show,					\
+			      NULL,					\
+			      _addr)
diff --git a/drivers/staging/iio/sysfs.h b/drivers/staging/iio/sysfs.h
index e501e13..d8fe0e2 100644
--- a/drivers/staging/iio/sysfs.h
+++ b/drivers/staging/iio/sysfs.h
@@ -98,6 +98,9 @@ struct iio_const_attr {
 	struct iio_dev_attr iio_dev_attr_##_name		\
 	= IIO_ATTR(_name, _mode, _show, _store, _addr)
 
+#define IIO_DEVICE_ATTR_NAMED(_vname, _name, _mode, _show, _store, _addr) \
+	struct iio_dev_attr iio_dev_attr_##_vname			\
+	= IIO_ATTR(_name, _mode, _show, _store, _addr)
 
 #define IIO_DEVICE_ATTR_2(_name, _mode, _show, _store, _addr, _val2)	\
 	struct iio_dev_attr iio_dev_attr_##_name			\
-- 
1.6.4.4


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

* [PATCH 02/20] staging:iio: Add new attrs for sampling frequency available and temp_raw
  2010-05-04 13:42 ` [PATCH 01/20] staging:iio: Add new in_raw definitions for adc channels Jonathan Cameron
@ 2010-05-04 13:42   ` Jonathan Cameron
  2010-05-04 13:42     ` [PATCH 03/20] iio:staging:accelerometers move towards the new abi Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:42 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/sysfs.h |   12 +++++++++++-
 1 files changed, 11 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/iio/sysfs.h b/drivers/staging/iio/sysfs.h
index d8fe0e2..afcf5ab 100644
--- a/drivers/staging/iio/sysfs.h
+++ b/drivers/staging/iio/sysfs.h
@@ -144,18 +144,25 @@ struct iio_const_attr {
  *
  * May be mode dependent on some devices
  **/
+/* Deprecated */
 #define IIO_DEV_ATTR_AVAIL_SAMP_FREQ(_show)				\
 	IIO_DEVICE_ATTR(available_sampling_frequency, S_IRUGO, _show, NULL, 0)
 
+#define IIO_DEV_ATTR_SAMP_FREQ_AVAIL(_show)				\
+	IIO_DEVICE_ATTR(sampling_frequency_available, S_IRUGO, _show, NULL, 0)
 /**
  * IIO_CONST_ATTR_AVAIL_SAMP_FREQ - list available sampling frequencies
  * @_string: frequency string for the attribute
  *
  * Constant version
  **/
-#define IIO_CONST_ATTR_AVAIL_SAMP_FREQ(_string)	\
+/* Deprecated */
+#define IIO_CONST_ATTR_AVAIL_SAMP_FREQ(_string)			\
 	IIO_CONST_ATTR(available_sampling_frequency, _string)
 
+#define IIO_CONST_ATTR_SAMP_FREQ_AVAIL(_string)			\
+	IIO_CONST_ATTR(sampling_frequency_available, _string)
+
 /**
  * IIO_DEV_ATTR_SCAN_MODE - select a scan mode
  * @_mode: sysfs file mode/permissions
@@ -234,6 +241,9 @@ struct iio_const_attr {
 #define IIO_DEV_ATTR_TEMP(_show)			\
 	IIO_DEVICE_ATTR(temp, S_IRUGO, _show, NULL, 0)
 
+#define IIO_DEV_ATTR_TEMP_RAW(_show)			\
+	IIO_DEVICE_ATTR(temp_raw, S_IRUGO, _show, NULL, 0)
+
 /**
  * IIO_EVENT_SH - generic shared event handler
  * @_name: event name
-- 
1.6.4.4


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

* [PATCH 03/20] iio:staging:accelerometers move towards the new abi
  2010-05-04 13:42   ` [PATCH 02/20] staging:iio: Add new attrs for sampling frequency available and temp_raw Jonathan Cameron
@ 2010-05-04 13:42     ` Jonathan Cameron
  2010-05-04 13:42       ` [PATCH 04/20] staging:iio: Support functions for scan mask matching Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:42 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/accel/accel.h          |    8 +-
 drivers/staging/iio/accel/kxsd9.c          |   88 ++++++++------
 drivers/staging/iio/accel/lis3l02dq.h      |    4 -
 drivers/staging/iio/accel/lis3l02dq_core.c |  175 ++++++++++++++-------------
 drivers/staging/iio/accel/lis3l02dq_ring.c |    8 +-
 drivers/staging/iio/accel/sca3000.h        |    2 +
 drivers/staging/iio/accel/sca3000_core.c   |  172 +++++++++++++--------------
 drivers/staging/iio/accel/sca3000_ring.c   |   33 ++++--
 drivers/staging/iio/ring_generic.h         |    4 +-
 9 files changed, 262 insertions(+), 232 deletions(-)

diff --git a/drivers/staging/iio/accel/accel.h b/drivers/staging/iio/accel/accel.h
index d7fc7f9..059209c 100644
--- a/drivers/staging/iio/accel/accel.h
+++ b/drivers/staging/iio/accel/accel.h
@@ -2,7 +2,6 @@
 #include "../sysfs.h"
 
 /* Accelerometer types of attribute */
-
 #define IIO_DEV_ATTR_ACCEL_X_OFFSET(_mode, _show, _store, _addr)	\
 	IIO_DEVICE_ATTR(accel_x_offset, _mode, _show, _store, _addr)
 
@@ -22,13 +21,13 @@
 	IIO_DEVICE_ATTR(accel_z_gain, _mode, _show, _store, _addr)
 
 #define IIO_DEV_ATTR_ACCEL_X(_show, _addr)			\
-	IIO_DEVICE_ATTR(accel_x, S_IRUGO, _show, NULL, _addr)
+	IIO_DEVICE_ATTR(accel_x_raw, S_IRUGO, _show, NULL, _addr)
 
 #define IIO_DEV_ATTR_ACCEL_Y(_show, _addr)			\
-	IIO_DEVICE_ATTR(accel_y, S_IRUGO, _show, NULL, _addr)
+	IIO_DEVICE_ATTR(accel_y_raw, S_IRUGO, _show, NULL, _addr)
 
 #define IIO_DEV_ATTR_ACCEL_Z(_show, _addr)			\
-	IIO_DEVICE_ATTR(accel_z, S_IRUGO, _show, NULL, _addr)
+	IIO_DEVICE_ATTR(accel_z_raw, S_IRUGO, _show, NULL, _addr)
 
 /* Thresholds are somewhat chip dependent - may need quite a few defs here */
 /* For unified thresholds (shared across all directions */
@@ -61,7 +60,6 @@
 #define IIO_DEV_ATTR_ACCEL_THRESH_Z(_mode, _show, _store, _addr)	\
 	IIO_DEVICE_ATTR(thresh_accel_z, _mode, _show, _store, _addr)
 
-
 /**
  * IIO_EVENT_ATTR_ACCEL_X_HIGH: threshold event, x acceleration
  * @_show: read x acceleration high threshold
diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c
index db2dd53..ae7ffe1 100644
--- a/drivers/staging/iio/accel/kxsd9.c
+++ b/drivers/staging/iio/accel/kxsd9.c
@@ -26,6 +26,7 @@
 #include <linux/rtc.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 
 #include "../iio.h"
 #include "../sysfs.h"
@@ -51,8 +52,10 @@
 #define KXSD9_READ(a) (0x80 | (a))
 #define KXSD9_WRITE(a) (a)
 
-#define IIO_DEV_ATTR_ACCEL_SET_RANGE(_mode, _show, _store)	\
-	IIO_DEVICE_ATTR(accel_range, _mode, _show, _store, 0)
+#define KXSD9_SCALE_2G "0.011978"
+#define KXSD9_SCALE_4G "0.023927"
+#define KXSD9_SCALE_6G "0.035934"
+#define KXSD9_SCALE_8G "0.047853"
 
 #define KXSD9_STATE_RX_SIZE 2
 #define KXSD9_STATE_TX_SIZE 4
@@ -73,9 +76,9 @@ struct kxsd9_state {
 };
 
 /* This may want to move to mili g to allow for non integer ranges */
-static ssize_t kxsd9_read_accel_range(struct device *dev,
-				      struct device_attribute *attr,
-				      char *buf)
+static ssize_t kxsd9_read_scale(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
 {
 	int ret;
 	ssize_t len = 0;
@@ -101,16 +104,16 @@ static ssize_t kxsd9_read_accel_range(struct device *dev,
 
 	switch (st->rx[1] & KXSD9_FS_MASK) {
 	case KXSD9_FS_8:
-		len += sprintf(buf, "8\n");
+		len += sprintf(buf, "%s\n", KXSD9_SCALE_8G);
 		break;
 	case KXSD9_FS_6:
-		len += sprintf(buf, "6\n");
+		len += sprintf(buf, "%s\n", KXSD9_SCALE_6G);
 		break;
 	case KXSD9_FS_4:
-		len += sprintf(buf, "4\n");
+		len += sprintf(buf, "%s\n", KXSD9_SCALE_4G);
 		break;
 	case KXSD9_FS_2:
-		len += sprintf(buf, "2\n");
+		len += sprintf(buf, "%s\n", KXSD9_SCALE_2G);
 		break;
 	}
 
@@ -119,12 +122,12 @@ error_ret:
 
 	return ret ? ret : len;
 }
-static ssize_t kxsd9_write_accel_range(struct device *dev,
-				      struct device_attribute *attr,
-				      const char *buf,
-				      size_t len)
+static ssize_t kxsd9_write_scale(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf,
+				 size_t len)
 {
-	long readin;
+
 	struct spi_message msg;
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
@@ -145,25 +148,25 @@ static ssize_t kxsd9_write_accel_range(struct device *dev,
 		},
 	};
 
-	ret = strict_strtol(buf, 10, &readin);
-	if (ret)
-		return ret;
-	switch (readin) {
-	case 8:
+	if (!strncmp(buf, KXSD9_SCALE_8G,
+		     strlen(buf) < strlen(KXSD9_SCALE_8G)
+		     ? strlen(buf) : strlen(KXSD9_SCALE_8G)))
 		val = KXSD9_FS_8;
-		break;
-	case 6:
+	else if (!strncmp(buf, KXSD9_SCALE_6G,
+			  strlen(buf) < strlen(KXSD9_SCALE_6G)
+			  ? strlen(buf) : strlen(KXSD9_SCALE_6G)))
 		val = KXSD9_FS_6;
-		break;
-	case 4:
+	else if (!strncmp(buf, KXSD9_SCALE_4G,
+			  strlen(buf) < strlen(KXSD9_SCALE_4G)
+			  ? strlen(buf) : strlen(KXSD9_SCALE_4G)))
 		val = KXSD9_FS_4;
-		break;
-	case 2:
+	else if (!strncmp(buf, KXSD9_SCALE_2G,
+			  strlen(buf) < strlen(KXSD9_SCALE_2G)
+			  ? strlen(buf) : strlen(KXSD9_SCALE_2G)))
 		val = KXSD9_FS_2;
-		break;
-	default:
+	else
 		return -EINVAL;
-	}
+
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = KXSD9_READ(KXSD9_REG_CTRL_C);
 	st->tx[1] = 0;
@@ -182,6 +185,7 @@ error_ret:
 	mutex_unlock(&st->buf_lock);
 	return ret ? ret : len;
 }
+
 static ssize_t kxsd9_read_accel(struct device *dev,
 				struct device_attribute *attr,
 				char *buf)
@@ -227,17 +231,27 @@ error_ret:
 static IIO_DEV_ATTR_ACCEL_X(kxsd9_read_accel, KXSD9_REG_X);
 static IIO_DEV_ATTR_ACCEL_Y(kxsd9_read_accel, KXSD9_REG_Y);
 static IIO_DEV_ATTR_ACCEL_Z(kxsd9_read_accel, KXSD9_REG_Z);
-static IIO_DEV_ATTR_ADC(0, kxsd9_read_accel, KXSD9_REG_AUX);
-static IIO_DEV_ATTR_ACCEL_SET_RANGE(S_IRUGO | S_IWUSR,
-				    kxsd9_read_accel_range,
-				    kxsd9_write_accel_range);
+static IIO_DEV_ATTR_IN_RAW(0, kxsd9_read_accel, KXSD9_REG_AUX);
+
+static IIO_DEVICE_ATTR(accel_scale,
+		S_IRUGO | S_IWUSR,
+		kxsd9_read_scale,
+		kxsd9_write_scale,
+		0);
+
+static IIO_CONST_ATTR(accel_scale_available,
+		KXSD9_SCALE_2G " "
+		KXSD9_SCALE_4G " "
+		KXSD9_SCALE_6G " "
+		KXSD9_SCALE_8G);
 
 static struct attribute *kxsd9_attributes[] = {
-	&iio_dev_attr_accel_x.dev_attr.attr,
-	&iio_dev_attr_accel_y.dev_attr.attr,
-	&iio_dev_attr_accel_z.dev_attr.attr,
-	&iio_dev_attr_adc_0.dev_attr.attr,
-	&iio_dev_attr_accel_range.dev_attr.attr,
+	&iio_dev_attr_accel_x_raw.dev_attr.attr,
+	&iio_dev_attr_accel_y_raw.dev_attr.attr,
+	&iio_dev_attr_accel_z_raw.dev_attr.attr,
+	&iio_dev_attr_in0_raw.dev_attr.attr,
+	&iio_dev_attr_accel_scale.dev_attr.attr,
+	&iio_const_attr_accel_scale_available.dev_attr.attr,
 	NULL,
 };
 
diff --git a/drivers/staging/iio/accel/lis3l02dq.h b/drivers/staging/iio/accel/lis3l02dq.h
index 91a5375..e76a979 100644
--- a/drivers/staging/iio/accel/lis3l02dq.h
+++ b/drivers/staging/iio/accel/lis3l02dq.h
@@ -179,10 +179,6 @@ int lis3l02dq_spi_read_reg_8(struct device *dev,
 int lis3l02dq_spi_write_reg_8(struct device *dev,
 			      u8 reg_address,
 			      u8 *val);
-#define LIS3L02DQ_SCAN_ACC_X 0
-#define LIS3L02DQ_SCAN_ACC_Y 1
-#define LIS3L02DQ_SCAN_ACC_Z 2
-
 
 #ifdef CONFIG_IIO_RING_BUFFER
 /* At the moment triggers are only used for ring buffer
diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c
index ea76902..6b5577d 100644
--- a/drivers/staging/iio/accel/lis3l02dq_core.c
+++ b/drivers/staging/iio/accel/lis3l02dq_core.c
@@ -458,41 +458,39 @@ err_ret:
 	return ret;
 }
 
-static IIO_DEV_ATTR_ACCEL_X_OFFSET(S_IWUSR | S_IRUGO,
-				   lis3l02dq_read_signed,
-				   lis3l02dq_write_signed,
-				   LIS3L02DQ_REG_OFFSET_X_ADDR);
-
-static IIO_DEV_ATTR_ACCEL_Y_OFFSET(S_IWUSR | S_IRUGO,
-				   lis3l02dq_read_signed,
-				   lis3l02dq_write_signed,
-				   LIS3L02DQ_REG_OFFSET_Y_ADDR);
-
-static IIO_DEV_ATTR_ACCEL_Z_OFFSET(S_IWUSR | S_IRUGO,
-				   lis3l02dq_read_signed,
-				   lis3l02dq_write_signed,
-				   LIS3L02DQ_REG_OFFSET_Z_ADDR);
-
-static IIO_DEV_ATTR_ACCEL_X_GAIN(S_IWUSR | S_IRUGO,
-				 lis3l02dq_read_unsigned,
-				 lis3l02dq_write_unsigned,
-				 LIS3L02DQ_REG_GAIN_X_ADDR);
-
-static IIO_DEV_ATTR_ACCEL_Y_GAIN(S_IWUSR | S_IRUGO,
-				 lis3l02dq_read_unsigned,
-				 lis3l02dq_write_unsigned,
-				 LIS3L02DQ_REG_GAIN_Y_ADDR);
-
-static IIO_DEV_ATTR_ACCEL_Z_GAIN(S_IWUSR | S_IRUGO,
-				 lis3l02dq_read_unsigned,
-				 lis3l02dq_write_unsigned,
-				 LIS3L02DQ_REG_GAIN_Z_ADDR);
-
-static IIO_DEV_ATTR_ACCEL_THRESH(S_IWUSR | S_IRUGO,
-				 lis3l02dq_read_16bit_signed,
-				 lis3l02dq_write_16bit_signed,
-				 LIS3L02DQ_REG_THS_L_ADDR);
-
+#define LIS3L02DQ_SIGNED_ATTR(name, reg)	\
+	IIO_DEVICE_ATTR(name,			\
+			S_IWUSR | S_IRUGO,	\
+			lis3l02dq_read_signed,	\
+			lis3l02dq_write_signed, \
+			reg);
+
+#define LIS3L02DQ_UNSIGNED_ATTR(name, reg)		\
+	IIO_DEVICE_ATTR(name,				\
+			S_IWUSR | S_IRUGO,		\
+			lis3l02dq_read_unsigned,	\
+			lis3l02dq_write_unsigned,	\
+			reg);
+
+static LIS3L02DQ_SIGNED_ATTR(accel_x_calibbias,
+			     LIS3L02DQ_REG_OFFSET_X_ADDR);
+static LIS3L02DQ_SIGNED_ATTR(accel_y_calibbias,
+			     LIS3L02DQ_REG_OFFSET_Y_ADDR);
+static LIS3L02DQ_SIGNED_ATTR(accel_z_calibbias,
+			     LIS3L02DQ_REG_OFFSET_Z_ADDR);
+
+static LIS3L02DQ_UNSIGNED_ATTR(accel_x_calibscale,
+			       LIS3L02DQ_REG_GAIN_X_ADDR);
+static LIS3L02DQ_UNSIGNED_ATTR(accel_y_calibscale,
+			       LIS3L02DQ_REG_GAIN_Y_ADDR);
+static LIS3L02DQ_UNSIGNED_ATTR(accel_z_calibscale,
+			       LIS3L02DQ_REG_GAIN_Z_ADDR);
+
+static IIO_DEVICE_ATTR(accel_mag_either_rising_value,
+		       S_IWUSR | S_IRUGO,
+		       lis3l02dq_read_16bit_signed,
+		       lis3l02dq_write_16bit_signed,
+		       LIS3L02DQ_REG_THS_L_ADDR);
 /* RFC The reading method for these will change depending on whether
  * ring buffer capture is in use. Is it worth making these take two
  * functions and let the core handle which to call, or leave as in this
@@ -512,7 +510,7 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
 			      lis3l02dq_read_frequency,
 			      lis3l02dq_write_frequency);
 
-static IIO_CONST_ATTR_AVAIL_SAMP_FREQ("280 560 1120 4480");
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("280 560 1120 4480");
 
 static ssize_t lis3l02dq_read_interrupt_config(struct device *dev,
 					       struct device_attribute *attr,
@@ -522,7 +520,7 @@ static ssize_t lis3l02dq_read_interrupt_config(struct device *dev,
 	s8 val;
 	struct iio_event_attr *this_attr = to_iio_event_attr(attr);
 
-	ret = lis3l02dq_spi_read_reg_8(dev,
+	ret = lis3l02dq_spi_read_reg_8(dev->parent,
 				       LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
 				       (u8 *)&val);
 
@@ -545,7 +543,7 @@ static ssize_t lis3l02dq_write_interrupt_config(struct device *dev,
 
 	mutex_lock(&indio_dev->mlock);
 	/* read current value */
-	ret = lis3l02dq_spi_read_reg_8(dev,
+	ret = lis3l02dq_spi_read_reg_8(dev->parent,
 				       LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
 				       &valold);
 	if (ret)
@@ -618,7 +616,7 @@ static int lis3l02dq_thresh_handler_th(struct iio_dev *dev_info,
 static void lis3l02dq_thresh_handler_bh_no_check(struct work_struct *work_s)
 {
 	struct iio_work_cont *wc
-		= container_of(work_s, struct iio_work_cont, ws_nocheck);
+		= container_of(work_s, struct iio_work_cont, ws);
 	struct lis3l02dq_state *st = wc->st;
 	u8 t;
 
@@ -668,43 +666,51 @@ static void lis3l02dq_thresh_handler_bh_no_check(struct work_struct *work_s)
 /* A shared handler for a number of threshold types */
 IIO_EVENT_SH(threshold, &lis3l02dq_thresh_handler_th);
 
-IIO_EVENT_ATTR_ACCEL_X_HIGH_SH(iio_event_threshold,
-			       lis3l02dq_read_interrupt_config,
-			       lis3l02dq_write_interrupt_config,
-			       LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_X_HIGH);
-
-IIO_EVENT_ATTR_ACCEL_Y_HIGH_SH(iio_event_threshold,
-			       lis3l02dq_read_interrupt_config,
-			       lis3l02dq_write_interrupt_config,
-			       LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Y_HIGH);
-
-IIO_EVENT_ATTR_ACCEL_Z_HIGH_SH(iio_event_threshold,
-			       lis3l02dq_read_interrupt_config,
-			       lis3l02dq_write_interrupt_config,
-			       LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_HIGH);
-
-IIO_EVENT_ATTR_ACCEL_X_LOW_SH(iio_event_threshold,
-			      lis3l02dq_read_interrupt_config,
-			      lis3l02dq_write_interrupt_config,
-			      LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_X_LOW);
-
-IIO_EVENT_ATTR_ACCEL_Y_LOW_SH(iio_event_threshold,
-			      lis3l02dq_read_interrupt_config,
-			      lis3l02dq_write_interrupt_config,
-			      LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Y_LOW);
+IIO_EVENT_ATTR_SH(accel_x_mag_pos_rising_en,
+		  iio_event_threshold,
+		  lis3l02dq_read_interrupt_config,
+		  lis3l02dq_write_interrupt_config,
+		  LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_X_HIGH);
+
+IIO_EVENT_ATTR_SH(accel_y_mag_pos_rising_en,
+		  iio_event_threshold,
+		  lis3l02dq_read_interrupt_config,
+		  lis3l02dq_write_interrupt_config,
+		  LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Y_HIGH);
+
+IIO_EVENT_ATTR_SH(accel_z_mag_pos_rising_en,
+		  iio_event_threshold,
+		  lis3l02dq_read_interrupt_config,
+		  lis3l02dq_write_interrupt_config,
+		  LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_HIGH);
+
+IIO_EVENT_ATTR_SH(accel_x_mag_neg_rising_en,
+		  iio_event_threshold,
+		  lis3l02dq_read_interrupt_config,
+		  lis3l02dq_write_interrupt_config,
+		  LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_X_LOW);
+
+IIO_EVENT_ATTR_SH(accel_y_mag_neg_rising_en,
+		  iio_event_threshold,
+		  lis3l02dq_read_interrupt_config,
+		  lis3l02dq_write_interrupt_config,
+		  LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Y_LOW);
+
+IIO_EVENT_ATTR_SH(accel_z_mag_neg_rising_en,
+		  iio_event_threshold,
+		  lis3l02dq_read_interrupt_config,
+		  lis3l02dq_write_interrupt_config,
+		  LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_LOW);
 
-IIO_EVENT_ATTR_ACCEL_Z_LOW_SH(iio_event_threshold,
-			      lis3l02dq_read_interrupt_config,
-			      lis3l02dq_write_interrupt_config,
-			      LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_LOW);
 
 static struct attribute *lis3l02dq_event_attributes[] = {
-	&iio_event_attr_accel_x_high.dev_attr.attr,
-	&iio_event_attr_accel_y_high.dev_attr.attr,
-	&iio_event_attr_accel_z_high.dev_attr.attr,
-	&iio_event_attr_accel_x_low.dev_attr.attr,
-	&iio_event_attr_accel_y_low.dev_attr.attr,
-	&iio_event_attr_accel_z_low.dev_attr.attr,
+	&iio_event_attr_accel_x_mag_pos_rising_en.dev_attr.attr,
+	&iio_event_attr_accel_y_mag_pos_rising_en.dev_attr.attr,
+	&iio_event_attr_accel_z_mag_pos_rising_en.dev_attr.attr,
+	&iio_event_attr_accel_x_mag_neg_rising_en.dev_attr.attr,
+	&iio_event_attr_accel_y_mag_neg_rising_en.dev_attr.attr,
+	&iio_event_attr_accel_z_mag_neg_rising_en.dev_attr.attr,
+	&iio_dev_attr_accel_mag_either_rising_value.dev_attr.attr,
 	NULL
 };
 
@@ -713,20 +719,21 @@ static struct attribute_group lis3l02dq_event_attribute_group = {
 };
 
 static IIO_CONST_ATTR(name, "lis3l02dq");
+static IIO_CONST_ATTR(accel_scale, "0.00958");
 
 static struct attribute *lis3l02dq_attributes[] = {
-	&iio_dev_attr_accel_x_offset.dev_attr.attr,
-	&iio_dev_attr_accel_y_offset.dev_attr.attr,
-	&iio_dev_attr_accel_z_offset.dev_attr.attr,
-	&iio_dev_attr_accel_x_gain.dev_attr.attr,
-	&iio_dev_attr_accel_y_gain.dev_attr.attr,
-	&iio_dev_attr_accel_z_gain.dev_attr.attr,
-	&iio_dev_attr_thresh.dev_attr.attr,
-	&iio_dev_attr_accel_x.dev_attr.attr,
-	&iio_dev_attr_accel_y.dev_attr.attr,
-	&iio_dev_attr_accel_z.dev_attr.attr,
+	&iio_dev_attr_accel_x_calibbias.dev_attr.attr,
+	&iio_dev_attr_accel_y_calibbias.dev_attr.attr,
+	&iio_dev_attr_accel_z_calibbias.dev_attr.attr,
+	&iio_dev_attr_accel_x_calibscale.dev_attr.attr,
+	&iio_dev_attr_accel_y_calibscale.dev_attr.attr,
+	&iio_dev_attr_accel_z_calibscale.dev_attr.attr,
+	&iio_const_attr_accel_scale.dev_attr.attr,
+	&iio_dev_attr_accel_x_raw.dev_attr.attr,
+	&iio_dev_attr_accel_y_raw.dev_attr.attr,
+	&iio_dev_attr_accel_z_raw.dev_attr.attr,
 	&iio_dev_attr_sampling_frequency.dev_attr.attr,
-	&iio_const_attr_available_sampling_frequency.dev_attr.attr,
+	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
 	&iio_const_attr_name.dev_attr.attr,
 	NULL
 };
diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c
index 9371243..bba4b09 100644
--- a/drivers/staging/iio/accel/lis3l02dq_ring.c
+++ b/drivers/staging/iio/accel/lis3l02dq_ring.c
@@ -75,16 +75,16 @@ error_ret:
 	return ret;
 
 }
-static IIO_SCAN_EL_C(accel_x, LIS3L02DQ_SCAN_ACC_X, IIO_SIGNED(16),
+static IIO_SCAN_EL_C(accel_x, 0, IIO_SIGNED(16),
 		     LIS3L02DQ_REG_OUT_X_L_ADDR,
 		     &lis3l02dq_scan_el_set_state);
-static IIO_SCAN_EL_C(accel_y, LIS3L02DQ_SCAN_ACC_Y, IIO_SIGNED(16),
+static IIO_SCAN_EL_C(accel_y, 1, IIO_SIGNED(16),
 		     LIS3L02DQ_REG_OUT_Y_L_ADDR,
 		     &lis3l02dq_scan_el_set_state);
-static IIO_SCAN_EL_C(accel_z, LIS3L02DQ_SCAN_ACC_Z, IIO_SIGNED(16),
+static IIO_SCAN_EL_C(accel_z, 2, IIO_SIGNED(16),
 		     LIS3L02DQ_REG_OUT_Z_L_ADDR,
 		     &lis3l02dq_scan_el_set_state);
-static IIO_SCAN_EL_TIMESTAMP;
+static IIO_SCAN_EL_TIMESTAMP(3);
 
 static struct attribute *lis3l02dq_scan_el_attrs[] = {
 	&iio_scan_el_accel_x.dev_attr.attr,
diff --git a/drivers/staging/iio/accel/sca3000.h b/drivers/staging/iio/accel/sca3000.h
index da7d3cb..e532199 100644
--- a/drivers/staging/iio/accel/sca3000.h
+++ b/drivers/staging/iio/accel/sca3000.h
@@ -187,6 +187,7 @@ struct sca3000_state {
 /**
  * struct sca3000_chip_info - model dependant parameters
  * @name: 			model identification
+ * @scale:			string containing floating point scale factor
  * @temp_output:		some devices have temperature sensors.
  * @measurement_mode_freq:	normal mode sampling frequency
  * @option_mode_1:		first optional mode. Not all models have one
@@ -199,6 +200,7 @@ struct sca3000_state {
  **/
 struct sca3000_chip_info {
 	const char		*name;
+	const char		*scale;
 	bool			temp_output;
 	int			measurement_mode_freq;
 	int			option_mode_1;
diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
index 1c22986..45e4777 100644
--- a/drivers/staging/iio/accel/sca3000_core.c
+++ b/drivers/staging/iio/accel/sca3000_core.c
@@ -27,11 +27,9 @@
 
 enum sca3000_variant {
 	d01,
-	d03,
 	e02,
 	e04,
 	e05,
-	l01,
 };
 
 /* Note where option modes are not defined, the chip simply does not
@@ -44,21 +42,20 @@ enum sca3000_variant {
 static const struct sca3000_chip_info sca3000_spi_chip_info_tbl[] = {
 	{
 		.name = "sca3000-d01",
+		.scale = " 0.0073575",
 		.temp_output = true,
 		.measurement_mode_freq = 250,
 		.option_mode_1 = SCA3000_OP_MODE_BYPASS,
 		.option_mode_1_freq = 250,
 	}, {
-		/* No data sheet available - may be the same as the 3100-d03?*/
-		.name = "sca3000-d03",
-		.temp_output = true,
-	}, {
 		.name = "sca3000-e02",
+		.scale = "0.00981",
 		.measurement_mode_freq = 125,
 		.option_mode_1 = SCA3000_OP_MODE_NARROW,
 		.option_mode_1_freq = 63,
 	}, {
 		.name = "sca3000-e04",
+		.scale = "0.01962",
 		.measurement_mode_freq = 100,
 		.option_mode_1 = SCA3000_OP_MODE_NARROW,
 		.option_mode_1_freq = 50,
@@ -66,18 +63,12 @@ static const struct sca3000_chip_info sca3000_spi_chip_info_tbl[] = {
 		.option_mode_2_freq = 400,
 	}, {
 		.name = "sca3000-e05",
+		.scale = "0.0613125",
 		.measurement_mode_freq = 200,
 		.option_mode_1 = SCA3000_OP_MODE_NARROW,
 		.option_mode_1_freq = 50,
 		.option_mode_2 = SCA3000_OP_MODE_WIDE,
 		.option_mode_2_freq = 400,
-	}, {
-		/* No data sheet available.
-		 * Frequencies are unknown.
-		 */
-		.name = "sca3000-l01",
-		.temp_output = true,
-		.option_mode_1 = SCA3000_OP_MODE_BYPASS,
 	},
 };
 
@@ -327,6 +318,14 @@ error_ret:
 	return ret ? ret : len;
 }
 
+static ssize_t sca3000_show_scale(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct sca3000_state *st = dev_info->dev_data;
+	return sprintf(buf, "%s\n", st->info->scale);
+}
 
 static ssize_t sca3000_show_name(struct device *dev,
 				 struct device_attribute *attr,
@@ -495,7 +494,7 @@ error_ret:
 /* Not even vaguely standard attributes so defined here rather than
  * in the relevant IIO core headers
  */
-static IIO_DEVICE_ATTR(available_measurement_modes, S_IRUGO,
+static IIO_DEVICE_ATTR(measurement_mode_available, S_IRUGO,
 		       sca3000_show_available_measurement_modes,
 		       NULL, 0);
 
@@ -508,6 +507,8 @@ static IIO_DEVICE_ATTR(measurement_mode, S_IRUGO | S_IWUSR,
 
 static IIO_DEV_ATTR_NAME(sca3000_show_name);
 static IIO_DEV_ATTR_REV(sca3000_show_rev);
+static IIO_DEVICE_ATTR(accel_scale, S_IRUGO, sca3000_show_scale,
+		       NULL, 0);
 
 static IIO_DEV_ATTR_ACCEL_X(sca3000_read_13bit_signed,
 			    SCA3000_REG_ADDR_X_MSB);
@@ -683,7 +684,7 @@ error_free_lock:
 /* Should only really be registered if ring buffer support is compiled in.
  * Does no harm however and doing it right would add a fair bit of complexity
  */
-static IIO_DEV_ATTR_AVAIL_SAMP_FREQ(sca3000_read_av_freq);
+static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq);
 
 static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
 			      sca3000_read_frequency,
@@ -718,7 +719,10 @@ static ssize_t sca3000_read_temp(struct device *dev,
 error_ret:
 	return ret;
 }
-static IIO_DEV_ATTR_TEMP(sca3000_read_temp);
+static IIO_DEV_ATTR_TEMP_RAW(sca3000_read_temp);
+
+static IIO_CONST_ATTR(temp_scale, "0.555556");
+static IIO_CONST_ATTR(temp_offset, "-214.6");
 
 /**
  * sca3000_show_thresh() sysfs query of a threshold
@@ -770,31 +774,34 @@ static ssize_t sca3000_write_thresh(struct device *dev,
 	return ret ? ret : len;
 }
 
-static IIO_DEV_ATTR_ACCEL_THRESH_X(S_IRUGO | S_IWUSR,
-				   sca3000_show_thresh,
-				   sca3000_write_thresh,
-				   SCA3000_REG_CTRL_SEL_MD_X_TH);
-static IIO_DEV_ATTR_ACCEL_THRESH_Y(S_IRUGO | S_IWUSR,
-				   sca3000_show_thresh,
-				   sca3000_write_thresh,
-				   SCA3000_REG_CTRL_SEL_MD_Y_TH);
-static IIO_DEV_ATTR_ACCEL_THRESH_Z(S_IRUGO | S_IWUSR,
-				   sca3000_show_thresh,
-				   sca3000_write_thresh,
-				   SCA3000_REG_CTRL_SEL_MD_Z_TH);
+static IIO_DEVICE_ATTR(accel_x_mag_either_rising_value,
+		S_IRUGO | S_IWUSR,
+		sca3000_show_thresh,
+		sca3000_write_thresh,
+		SCA3000_REG_CTRL_SEL_MD_X_TH);
+
+static IIO_DEVICE_ATTR(accel_y_mag_either_rising_value,
+		S_IRUGO | S_IWUSR,
+		sca3000_show_thresh,
+		sca3000_write_thresh,
+		SCA3000_REG_CTRL_SEL_MD_Y_TH);
+
+static IIO_DEVICE_ATTR(accel_z_mag_either_rising_value,
+		S_IRUGO | S_IWUSR,
+		sca3000_show_thresh,
+		sca3000_write_thresh,
+		SCA3000_REG_CTRL_SEL_MD_Z_TH);
 
 static struct attribute *sca3000_attributes[] = {
 	&iio_dev_attr_name.dev_attr.attr,
 	&iio_dev_attr_revision.dev_attr.attr,
-	&iio_dev_attr_accel_x.dev_attr.attr,
-	&iio_dev_attr_accel_y.dev_attr.attr,
-	&iio_dev_attr_accel_z.dev_attr.attr,
-	&iio_dev_attr_thresh_accel_x.dev_attr.attr,
-	&iio_dev_attr_thresh_accel_y.dev_attr.attr,
-	&iio_dev_attr_thresh_accel_z.dev_attr.attr,
-	&iio_dev_attr_available_measurement_modes.dev_attr.attr,
+	&iio_dev_attr_accel_scale.dev_attr.attr,
+	&iio_dev_attr_accel_x_raw.dev_attr.attr,
+	&iio_dev_attr_accel_y_raw.dev_attr.attr,
+	&iio_dev_attr_accel_z_raw.dev_attr.attr,
+	&iio_dev_attr_measurement_mode_available.dev_attr.attr,
 	&iio_dev_attr_measurement_mode.dev_attr.attr,
-	&iio_dev_attr_available_sampling_frequency.dev_attr.attr,
+	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
 	&iio_dev_attr_sampling_frequency.dev_attr.attr,
 	NULL,
 };
@@ -802,18 +809,18 @@ static struct attribute *sca3000_attributes[] = {
 static struct attribute *sca3000_attributes_with_temp[] = {
 	&iio_dev_attr_name.dev_attr.attr,
 	&iio_dev_attr_revision.dev_attr.attr,
-	&iio_dev_attr_accel_x.dev_attr.attr,
-	&iio_dev_attr_accel_y.dev_attr.attr,
-	&iio_dev_attr_accel_z.dev_attr.attr,
-	&iio_dev_attr_thresh_accel_x.dev_attr.attr,
-	&iio_dev_attr_thresh_accel_y.dev_attr.attr,
-	&iio_dev_attr_thresh_accel_z.dev_attr.attr,
-	&iio_dev_attr_available_measurement_modes.dev_attr.attr,
+	&iio_dev_attr_accel_scale.dev_attr.attr,
+	&iio_dev_attr_accel_x_raw.dev_attr.attr,
+	&iio_dev_attr_accel_y_raw.dev_attr.attr,
+	&iio_dev_attr_accel_z_raw.dev_attr.attr,
+	&iio_dev_attr_measurement_mode_available.dev_attr.attr,
 	&iio_dev_attr_measurement_mode.dev_attr.attr,
-	&iio_dev_attr_available_sampling_frequency.dev_attr.attr,
+	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
 	&iio_dev_attr_sampling_frequency.dev_attr.attr,
 	/* Only present if temp sensor is */
-	&iio_dev_attr_temp.dev_attr.attr,
+	&iio_dev_attr_temp_raw.dev_attr.attr,
+	&iio_const_attr_temp_offset.dev_attr.attr,
+	&iio_const_attr_temp_scale.dev_attr.attr,
 	NULL,
 };
 
@@ -910,7 +917,7 @@ static ssize_t sca3000_query_mo_det(struct device *dev,
 				    struct device_attribute *attr,
 				    char *buf)
 {
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct iio_dev *indio_dev = dev_get_drvdata(dev->parent);
 	struct sca3000_state *st = indio_dev->dev_data;
 	struct iio_event_attr *this_attr = to_iio_event_attr(attr);
 	int ret, len = 0;
@@ -975,7 +982,7 @@ static ssize_t sca3000_query_ring_int(struct device *dev,
 	struct iio_event_attr *this_attr = to_iio_event_attr(attr);
 	int ret, len;
 	u8 *rx;
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct iio_dev *indio_dev = dev_get_drvdata(dev->parent);
 	struct sca3000_state *st = indio_dev->dev_data;
 	mutex_lock(&st->lock);
 	ret = sca3000_read_data(st, SCA3000_REG_ADDR_INT_MASK, &rx, 1);
@@ -995,7 +1002,7 @@ static ssize_t sca3000_set_ring_int(struct device *dev,
 				      const char *buf,
 				      size_t len)
 {
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct iio_dev *indio_dev = dev_get_drvdata(dev->parent);
 	struct sca3000_state *st = indio_dev->dev_data;
 	struct iio_event_attr *this_attr = to_iio_event_attr(attr);
 
@@ -1085,7 +1092,7 @@ static ssize_t sca3000_set_mo_det(struct device *dev,
 				  const char *buf,
 				  size_t len)
 {
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct iio_dev *indio_dev = dev_get_drvdata(dev->parent);
 	struct sca3000_state *st = indio_dev->dev_data;
 	struct iio_event_attr *this_attr = to_iio_event_attr(attr);
 	long val;
@@ -1155,20 +1162,23 @@ IIO_EVENT_ATTR_FREE_FALL_DETECT_SH(iio_event_all,
 				   0)
 
 /* Motion detector related event attributes */
-IIO_EVENT_ATTR_ACCEL_X_HIGH_SH(iio_event_all,
-			       sca3000_query_mo_det,
-			       sca3000_set_mo_det,
-			       SCA3000_MD_CTRL_OR_X);
-
-IIO_EVENT_ATTR_ACCEL_Y_HIGH_SH(iio_event_all,
-			       sca3000_query_mo_det,
-			       sca3000_set_mo_det,
-			       SCA3000_MD_CTRL_OR_Y);
-
-IIO_EVENT_ATTR_ACCEL_Z_HIGH_SH(iio_event_all,
-			       sca3000_query_mo_det,
-			       sca3000_set_mo_det,
-			       SCA3000_MD_CTRL_OR_Z);
+IIO_EVENT_ATTR_SH(accel_x_mag_either_rising_en,
+		  iio_event_all,
+		  sca3000_query_mo_det,
+		  sca3000_set_mo_det,
+		  SCA3000_MD_CTRL_OR_X);
+
+IIO_EVENT_ATTR_SH(accel_y_mag_either_rising_en,
+		  iio_event_all,
+		  sca3000_query_mo_det,
+		  sca3000_set_mo_det,
+		  SCA3000_MD_CTRL_OR_Y);
+
+IIO_EVENT_ATTR_SH(accel_z_mag_either_rising_en,
+		  iio_event_all,
+		  sca3000_query_mo_det,
+		  sca3000_set_mo_det,
+		  SCA3000_MD_CTRL_OR_Z);
 
 /* Hardware ring buffer related event attributes */
 IIO_EVENT_ATTR_RING_50_FULL_SH(iio_event_all,
@@ -1183,11 +1193,14 @@ IIO_EVENT_ATTR_RING_75_FULL_SH(iio_event_all,
 
 static struct attribute *sca3000_event_attributes[] = {
 	&iio_event_attr_free_fall.dev_attr.attr,
-	&iio_event_attr_accel_x_high.dev_attr.attr,
-	&iio_event_attr_accel_y_high.dev_attr.attr,
-	&iio_event_attr_accel_z_high.dev_attr.attr,
+	&iio_event_attr_accel_x_mag_either_rising_en.dev_attr.attr,
+	&iio_event_attr_accel_y_mag_either_rising_en.dev_attr.attr,
+	&iio_event_attr_accel_z_mag_either_rising_en.dev_attr.attr,
 	&iio_event_attr_ring_50_full.dev_attr.attr,
 	&iio_event_attr_ring_75_full.dev_attr.attr,
+	&iio_dev_attr_accel_x_mag_either_rising_value.dev_attr.attr,
+	&iio_dev_attr_accel_y_mag_either_rising_value.dev_attr.attr,
+	&iio_dev_attr_accel_z_mag_either_rising_value.dev_attr.attr,
 	NULL,
 };
 
@@ -1344,9 +1357,10 @@ static int __devinit __sca3000_probe(struct spi_device *spi,
 		 * is overkill.  At very least a simpler registration method
 		 * might be worthwhile.
 		 */
-		iio_add_event_to_list(iio_event_attr_accel_z_high.listel,
-					    &st->indio_dev
-					    ->interrupts[0]->ev_list);
+		iio_add_event_to_list(
+			iio_event_attr_accel_z_mag_either_rising_en.listel,
+			&st->indio_dev
+			->interrupts[0]->ev_list);
 	}
 	sca3000_register_ring_funcs(st->indio_dev);
 	ret = sca3000_clean_setup(st);
@@ -1437,9 +1451,6 @@ static int sca3000_remove(struct spi_device *spi)
 SCA3000_VARIANT_PROBE(d01);
 static SCA3000_VARIANT_SPI_DRIVER(d01);
 
-SCA3000_VARIANT_PROBE(d03);
-static SCA3000_VARIANT_SPI_DRIVER(d03);
-
 SCA3000_VARIANT_PROBE(e02);
 static SCA3000_VARIANT_SPI_DRIVER(e02);
 
@@ -1449,9 +1460,6 @@ static SCA3000_VARIANT_SPI_DRIVER(e04);
 SCA3000_VARIANT_PROBE(e05);
 static SCA3000_VARIANT_SPI_DRIVER(e05);
 
-SCA3000_VARIANT_PROBE(l01);
-static SCA3000_VARIANT_SPI_DRIVER(l01);
-
 static __init int sca3000_init(void)
 {
 	int ret;
@@ -1459,32 +1467,22 @@ static __init int sca3000_init(void)
 	ret = spi_register_driver(&sca3000_d01_driver);
 	if (ret)
 		goto error_ret;
-	ret = spi_register_driver(&sca3000_d03_driver);
-	if (ret)
-		goto error_unreg_d01;
 	ret = spi_register_driver(&sca3000_e02_driver);
 	if (ret)
-		goto error_unreg_d03;
+		goto error_unreg_d01;
 	ret = spi_register_driver(&sca3000_e04_driver);
 	if (ret)
 		goto error_unreg_e02;
 	ret = spi_register_driver(&sca3000_e05_driver);
 	if (ret)
 		goto error_unreg_e04;
-	ret = spi_register_driver(&sca3000_l01_driver);
-	if (ret)
-		goto error_unreg_e05;
 
 	return 0;
 
-error_unreg_e05:
-	spi_unregister_driver(&sca3000_e05_driver);
 error_unreg_e04:
 	spi_unregister_driver(&sca3000_e04_driver);
 error_unreg_e02:
 	spi_unregister_driver(&sca3000_e02_driver);
-error_unreg_d03:
-	spi_unregister_driver(&sca3000_d03_driver);
 error_unreg_d01:
 	spi_unregister_driver(&sca3000_d01_driver);
 error_ret:
@@ -1494,11 +1492,9 @@ error_ret:
 
 static __exit void sca3000_exit(void)
 {
-	spi_unregister_driver(&sca3000_l01_driver);
 	spi_unregister_driver(&sca3000_e05_driver);
 	spi_unregister_driver(&sca3000_e04_driver);
 	spi_unregister_driver(&sca3000_e02_driver);
-	spi_unregister_driver(&sca3000_d03_driver);
 	spi_unregister_driver(&sca3000_d01_driver);
 }
 
diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c
index 40cbab2..2b39e6f 100644
--- a/drivers/staging/iio/accel/sca3000_ring.c
+++ b/drivers/staging/iio/accel/sca3000_ring.c
@@ -186,11 +186,29 @@ static ssize_t sca3000_store_ring_bpse(struct device *dev,
 	return ret ? ret : len;
 }
 
-static IIO_CONST_ATTR(bpse_available, "8 11");
+static IIO_SCAN_EL_C(accel_x, 0, 0, 0, 0);
+static IIO_SCAN_EL_C(accel_y, 1, 0, 0, 0);
+static IIO_SCAN_EL_C(accel_z, 2, 0, 0, 0);
+static IIO_CONST_ATTR(accel_precision_available, "8 11");
+static IIO_DEVICE_ATTR(accel_precision,
+		       S_IRUGO | S_IWUSR,
+		       sca3000_show_ring_bpse,
+		       sca3000_store_ring_bpse,
+		       0);
+
+static struct attribute *sca3000_scan_el_attrs[] = {
+	&iio_scan_el_accel_x.dev_attr.attr,
+	&iio_scan_el_accel_y.dev_attr.attr,
+	&iio_scan_el_accel_z.dev_attr.attr,
+	&iio_const_attr_accel_precision_available.dev_attr.attr,
+	&iio_dev_attr_accel_precision.dev_attr.attr,
+	NULL
+};
 
-static IIO_DEV_ATTR_BPSE(S_IRUGO | S_IWUSR,
-			      sca3000_show_ring_bpse,
-			      sca3000_store_ring_bpse);
+static struct attribute_group sca3000_scan_el_group = {
+	.attrs = sca3000_scan_el_attrs,
+	.name = "scan_elements",
+};
 
 /*
  * Ring buffer attributes
@@ -198,17 +216,15 @@ static IIO_DEV_ATTR_BPSE(S_IRUGO | S_IWUSR,
  * only apply to the ring buffer.  At all times full rate and accuracy
  * is available via direct reading from registers.
  */
-static struct attribute *iio_ring_attributes[] = {
+static struct attribute *sca3000_ring_attributes[] = {
 	&dev_attr_length.attr,
 	&dev_attr_bps.attr,
 	&dev_attr_ring_enable.attr,
-	&iio_dev_attr_bpse.dev_attr.attr,
-	&iio_const_attr_bpse_available.dev_attr.attr,
 	NULL,
 };
 
 static struct attribute_group sca3000_ring_attr = {
-	.attrs = iio_ring_attributes,
+	.attrs = sca3000_ring_attributes,
 };
 
 static const struct attribute_group *sca3000_ring_attr_groups[] = {
@@ -248,6 +264,7 @@ static inline void sca3000_rb_free(struct iio_ring_buffer *r)
 
 int sca3000_configure_ring(struct iio_dev *indio_dev)
 {
+	indio_dev->scan_el_attrs = &sca3000_scan_el_group;
 	indio_dev->ring = sca3000_rb_allocate(indio_dev);
 	if (indio_dev->ring == NULL)
 		return -ENOMEM;
diff --git a/drivers/staging/iio/ring_generic.h b/drivers/staging/iio/ring_generic.h
index 75e0fc0..c482074 100644
--- a/drivers/staging/iio/ring_generic.h
+++ b/drivers/staging/iio/ring_generic.h
@@ -248,9 +248,9 @@ ssize_t iio_scan_el_ts_show(struct device *dev, struct device_attribute *attr,
  *
  * Odd one out. Handled slightly differently from other scan elements.
  **/
-#define IIO_SCAN_EL_TIMESTAMP					\
+#define IIO_SCAN_EL_TIMESTAMP(number)				\
 	struct iio_scan_el iio_scan_el_timestamp = {		\
-		.dev_attr = __ATTR(scan_en_timestamp,		\
+		.dev_attr = __ATTR(number##_timestamp_en,	\
 				   S_IRUGO | S_IWUSR,		\
 				   iio_scan_el_ts_show,		\
 				   iio_scan_el_ts_store),	\
-- 
1.6.4.4

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

* [PATCH 04/20] staging:iio: Support functions for scan mask matching
  2010-05-04 13:42     ` [PATCH 03/20] iio:staging:accelerometers move towards the new abi Jonathan Cameron
@ 2010-05-04 13:42       ` Jonathan Cameron
  2010-05-04 13:43         ` [PATCH 05/20] staging: iio: Move from class to bus Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:42 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/iio.h |   45 +++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h
index 71dbfe1..a12072a 100644
--- a/drivers/staging/iio/iio.h
+++ b/drivers/staging/iio/iio.h
@@ -96,6 +96,7 @@ void iio_remove_event_from_list(struct iio_event_handler_list *el,
  *			control method is used
  * @scan_count:	[INTERN] the number of elements in the current scan mode
  * @scan_mask:		[INTERN] bitmask used in masking scan mode elements
+ * @available_scan_masks: [DRIVER] optional array of allowed bitmasks
  * @scan_timestamp:	[INTERN] does the scan mode include a timestamp
  * @trig:		[INTERN] current device trigger (ring buffer modes)
  * @pollfunc:		[DRIVER] function run on trigger being recieved
@@ -122,7 +123,8 @@ struct iio_dev {
 	struct attribute_group		*scan_el_attrs;
 	int				scan_count;
 
-	u16				scan_mask;
+	u32				scan_mask;
+	u32				*available_scan_masks;
 	bool				scan_timestamp;
 	struct iio_trigger		*trig;
 	struct iio_poll_func		*pollfunc;
@@ -132,22 +134,57 @@ struct iio_dev {
  * These are mainly provided to allow for a change of implementation if a device
  * has a large number of scan elements
  */
-#define IIO_MAX_SCAN_LENGTH 15
+#define IIO_MAX_SCAN_LENGTH 31
+
+/* note 0 used as error indicator as it doesn't make sense. */
+static inline u32 iio_scan_mask_match(u32 *av_masks, u32 mask)
+{
+	while (*av_masks) {
+		if (!(~*av_masks & mask))
+			return *av_masks;
+		av_masks++;
+	}
+	return 0;
+}
 
 static inline int iio_scan_mask_query(struct iio_dev *dev_info, int bit)
 {
+	u32 mask;
+
 	if (bit > IIO_MAX_SCAN_LENGTH)
 		return -EINVAL;
+
+	if (!dev_info->scan_mask)
+		return 0;
+
+	if (dev_info->available_scan_masks)
+		mask = iio_scan_mask_match(dev_info->available_scan_masks,
+					dev_info->scan_mask);
 	else
-		return !!(dev_info->scan_mask & (1 << bit));
+		mask = dev_info->scan_mask;
+
+	if (!mask)
+		return -EINVAL;
+
+	return !!(mask & (1 << bit));
 };
 
 static inline int iio_scan_mask_set(struct iio_dev *dev_info, int bit)
 {
+	u32 mask;
+	u32 trialmask = dev_info->scan_mask | (1 << bit);
+
 	if (bit > IIO_MAX_SCAN_LENGTH)
 		return -EINVAL;
-	dev_info->scan_mask |= (1 << bit);
+	if (dev_info->available_scan_masks) {
+		mask = iio_scan_mask_match(dev_info->available_scan_masks,
+					trialmask);
+		if (!mask)
+			return -EINVAL;
+	}
+	dev_info->scan_mask = trialmask;
 	dev_info->scan_count++;
+
 	return 0;
 };
 
-- 
1.6.4.4

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

* [PATCH 05/20] staging: iio: Move from class to bus
  2010-05-04 13:42       ` [PATCH 04/20] staging:iio: Support functions for scan mask matching Jonathan Cameron
@ 2010-05-04 13:43         ` Jonathan Cameron
  2010-05-04 13:43           ` [PATCH 06/20] staging:iio: Move event attributes into the event[n] device in sysfs Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:43 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/iio.h                  |    2 +-
 drivers/staging/iio/industrialio-core.c    |   28 +++++++++++-----------------
 drivers/staging/iio/industrialio-ring.c    |    2 +-
 drivers/staging/iio/industrialio-trigger.c |    2 +-
 drivers/staging/iio/ring_sw.c              |    2 +-
 5 files changed, 15 insertions(+), 21 deletions(-)

diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h
index a12072a..fcee47c 100644
--- a/drivers/staging/iio/iio.h
+++ b/drivers/staging/iio/iio.h
@@ -377,7 +377,7 @@ void iio_deallocate_chrdev(struct iio_handler *handler);
 #define IIO_UNSIGNED(a) (a)
 
 extern dev_t iio_devt;
-extern struct class iio_class;
+extern struct bus_type iio_bus_type;
 
 /**
  * iio_put_device() - reference counted deallocation of struct device
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index 7c9a12e..ad830b6 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -42,16 +42,10 @@ dev_t iio_devt;
 EXPORT_SYMBOL(iio_devt);
 
 #define IIO_DEV_MAX 256
-static char *iio_devnode(struct device *dev, mode_t *mode)
-{
-	return kasprintf(GFP_KERNEL, "iio/%s", dev_name(dev));
-}
-
-struct class iio_class = {
+struct bus_type iio_bus_type = {
 	.name = "iio",
-	.devnode = iio_devnode,
 };
-EXPORT_SYMBOL(iio_class);
+EXPORT_SYMBOL(iio_bus_type);
 
 void __iio_change_event(struct iio_detected_event_list *ev,
 			int ev_code,
@@ -405,7 +399,7 @@ int iio_setup_ev_int(struct iio_event_interface *ev_int,
 {
 	int ret, minor;
 
-	ev_int->dev.class = &iio_class;
+	ev_int->dev.bus = &iio_bus_type;
 	ev_int->dev.parent = dev;
 	ev_int->dev.type = &iio_event_type;
 	device_initialize(&ev_int->dev);
@@ -478,23 +472,23 @@ static int __init iio_init(void)
 {
 	int ret;
 
-	/* Create sysfs class */
-	ret  = class_register(&iio_class);
+	/* Register sysfs bus */
+	ret  = bus_register(&iio_bus_type);
 	if (ret < 0) {
 		printk(KERN_ERR
-		       "%s could not create sysfs class\n",
+		       "%s could not register bus type\n",
 			__FILE__);
 		goto error_nothing;
 	}
 
 	ret = iio_dev_init();
 	if (ret < 0)
-		goto error_unregister_class;
+		goto error_unregister_bus_type;
 
 	return 0;
 
-error_unregister_class:
-	class_unregister(&iio_class);
+error_unregister_bus_type:
+	bus_unregister(&iio_bus_type);
 error_nothing:
 	return ret;
 }
@@ -502,7 +496,7 @@ error_nothing:
 static void __exit iio_exit(void)
 {
 	iio_dev_exit();
-	class_unregister(&iio_class);
+	bus_unregister(&iio_bus_type);
 }
 
 static int iio_device_register_sysfs(struct iio_dev *dev_info)
@@ -768,7 +762,7 @@ struct iio_dev *iio_allocate_device(void)
 
 	if (dev) {
 		dev->dev.type = &iio_dev_type;
-		dev->dev.class = &iio_class;
+		dev->dev.bus = &iio_bus_type;
 		device_initialize(&dev->dev);
 		dev_set_drvdata(&dev->dev, (void *)dev);
 		mutex_init(&dev->mlock);
diff --git a/drivers/staging/iio/industrialio-ring.c b/drivers/staging/iio/industrialio-ring.c
index 5f48632..690df91 100644
--- a/drivers/staging/iio/industrialio-ring.c
+++ b/drivers/staging/iio/industrialio-ring.c
@@ -210,7 +210,7 @@ __iio_request_ring_buffer_access_chrdev(struct iio_ring_buffer *buf,
 	buf->access_handler.flags = 0;
 
 	buf->access_dev.parent = &buf->dev;
-	buf->access_dev.class = &iio_class;
+	buf->access_dev.bus = &iio_bus_type;
 	buf->access_dev.type = &iio_ring_access_type;
 	device_initialize(&buf->access_dev);
 
diff --git a/drivers/staging/iio/industrialio-trigger.c b/drivers/staging/iio/industrialio-trigger.c
index 3c8f6ff..918b0fd 100644
--- a/drivers/staging/iio/industrialio-trigger.c
+++ b/drivers/staging/iio/industrialio-trigger.c
@@ -365,7 +365,7 @@ struct iio_trigger *iio_allocate_trigger(void)
 	trig = kzalloc(sizeof *trig, GFP_KERNEL);
 	if (trig) {
 		trig->dev.type = &iio_trig_type;
-		trig->dev.class = &iio_class;
+		trig->dev.bus = &iio_bus_type;
 		device_initialize(&trig->dev);
 		dev_set_drvdata(&trig->dev, (void *)trig);
 		spin_lock_init(&trig->pollfunc_list_lock);
diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c
index e9570e3..f8de45d 100644
--- a/drivers/staging/iio/ring_sw.c
+++ b/drivers/staging/iio/ring_sw.c
@@ -419,7 +419,7 @@ struct iio_ring_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev)
 	buf->dev.type = &iio_sw_ring_type;
 	device_initialize(&buf->dev);
 	buf->dev.parent = &indio_dev->dev;
-	buf->dev.class = &iio_class;
+	buf->dev.bus = &iio_bus_type;
 	dev_set_drvdata(&buf->dev, (void *)buf);
 
 	return buf;
-- 
1.6.4.4

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

* [PATCH 06/20] staging:iio: Move event attributes into the event[n] device in sysfs
  2010-05-04 13:43         ` [PATCH 05/20] staging: iio: Move from class to bus Jonathan Cameron
@ 2010-05-04 13:43           ` Jonathan Cameron
  2010-05-04 13:43             ` [PATCH 07/20] staging:iio: Clean out unused IIO_SCAN_EL and add IIO_SCAN_NAMED_EL_C Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:43 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/industrialio-core.c |   25 ++++++++++++-------------
 1 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index ad830b6..a4ce221 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -676,16 +676,14 @@ static int iio_device_register_eventset(struct iio_dev *dev_info)
 					 dev_info->event_interfaces[i].id);
 			goto error_free_setup_ev_ints;
 		}
-	}
 
-	for (i = 0; i < dev_info->num_interrupt_lines; i++) {
-		snprintf(dev_info->event_interfaces[i]._attrname, 20,
-			"event_line%d_sources", i);
-		dev_info->event_attrs[i].name
-			= (const char *)
-			(dev_info->event_interfaces[i]._attrname);
-		ret = sysfs_create_group(&dev_info->dev.kobj,
-					 &dev_info->event_attrs[i]);
+		dev_set_drvdata(&dev_info->event_interfaces[i].dev,
+				(void *)dev_info);
+		ret = sysfs_create_group(&dev_info
+					->event_interfaces[i]
+					.dev.kobj,
+					&dev_info->event_attrs[i]);
+
 		if (ret) {
 			dev_err(&dev_info->dev,
 				"Failed to register sysfs for event attrs");
@@ -707,13 +705,13 @@ error_unregister_config_attrs:
 	i = dev_info->num_interrupt_lines - 1;
 error_remove_sysfs_interfaces:
 	for (j = 0; j < i; j++)
-		sysfs_remove_group(&dev_info->dev.kobj,
+		sysfs_remove_group(&dev_info
+				   ->event_interfaces[j].dev.kobj,
 				   &dev_info->event_attrs[j]);
-	i = dev_info->num_interrupt_lines - 1;
 error_free_setup_ev_ints:
 	for (j = 0; j < i; j++) {
 		iio_free_idr_val(&iio_event_idr,
-				 dev_info->event_interfaces[i].id);
+				 dev_info->event_interfaces[j].id);
 		iio_free_ev_int(&dev_info->event_interfaces[j]);
 	}
 	kfree(dev_info->interrupts);
@@ -731,7 +729,8 @@ static void iio_device_unregister_eventset(struct iio_dev *dev_info)
 	if (dev_info->num_interrupt_lines == 0)
 		return;
 	for (i = 0; i < dev_info->num_interrupt_lines; i++)
-		sysfs_remove_group(&dev_info->dev.kobj,
+		sysfs_remove_group(&dev_info
+				   ->event_interfaces[i].dev.kobj,
 				   &dev_info->event_attrs[i]);
 
 	for (i = 0; i < dev_info->num_interrupt_lines; i++) {
-- 
1.6.4.4

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

* [PATCH 07/20] staging:iio: Clean out unused IIO_SCAN_EL and add IIO_SCAN_NAMED_EL_C
  2010-05-04 13:43           ` [PATCH 06/20] staging:iio: Move event attributes into the event[n] device in sysfs Jonathan Cameron
@ 2010-05-04 13:43             ` Jonathan Cameron
  2010-05-04 13:43               ` [PATCH 08/20] staging:iio:max1363 move to new abi Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:43 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/ring_generic.h |   36 +++++++++++++++---------------------
 1 files changed, 15 insertions(+), 21 deletions(-)

diff --git a/drivers/staging/iio/ring_generic.h b/drivers/staging/iio/ring_generic.h
index c482074..d74b5ae 100644
--- a/drivers/staging/iio/ring_generic.h
+++ b/drivers/staging/iio/ring_generic.h
@@ -196,25 +196,6 @@ ssize_t iio_scan_el_store(struct device *dev, struct device_attribute *attr,
  **/
 ssize_t iio_scan_el_show(struct device *dev, struct device_attribute *attr,
 			 char *buf);
-/**
- * IIO_SCAN_EL - declare and initialize a scan element without control func
- * @_name:	identifying name. Resulting struct is iio_scan_el_##_name,
- *		sysfs element, scan_en_##_name.
- * @_number:	unique id number for the scan element.
- * @_bits:	number of bits in the scan element result (used in mixed bit
- *		length devices).
- * @_label:	indentification variable used by drivers.  Often a reg address.
- **/
-#define IIO_SCAN_EL(_name, _number, _bits, _label)			\
-	struct iio_scan_el iio_scan_el_##_name = {			\
-		.dev_attr = __ATTR(scan_en_##_name,			\
-				   S_IRUGO | S_IWUSR,			\
-				   iio_scan_el_show,			\
-				   iio_scan_el_store),			\
-		.mask = (1 << _number),					\
-		.bit_count = _bits,					\
-		.label = _label,					\
-	}
 
 ssize_t iio_scan_el_ts_store(struct device *dev, struct device_attribute *attr,
 			     const char *buf, size_t len);
@@ -225,7 +206,7 @@ ssize_t iio_scan_el_ts_show(struct device *dev, struct device_attribute *attr,
  * IIO_SCAN_EL_C - declare and initialize a scan element with a control func
  *
  * @_name:	identifying name. Resulting struct is iio_scan_el_##_name,
- *		sysfs element, scan_en_##_name.
+ *		sysfs element, _name##_en.
  * @_number:	unique id number for the scan element.
  * @_bits:	number of bits in the scan element result (used in mixed bit
  *		length devices).
@@ -234,7 +215,7 @@ ssize_t iio_scan_el_ts_show(struct device *dev, struct device_attribute *attr,
  **/
 #define IIO_SCAN_EL_C(_name, _number, _bits, _label, _controlfunc)	\
 	struct iio_scan_el iio_scan_el_##_name = {			\
-		.dev_attr = __ATTR(scan_en_##_name,			\
+		.dev_attr = __ATTR(_number##_##_name##_en,		\
 				   S_IRUGO | S_IWUSR,			\
 				   iio_scan_el_show,			\
 				   iio_scan_el_store),			\
@@ -243,6 +224,19 @@ ssize_t iio_scan_el_ts_show(struct device *dev, struct device_attribute *attr,
 		.label = _label,					\
 		.set_state = _controlfunc,				\
 	}
+
+#define IIO_SCAN_NAMED_EL_C(_name, _string, _number, _bits, _label, _cf) \
+	struct iio_scan_el iio_scan_el_##_name = {			\
+		.dev_attr = __ATTR(_number##_##_string##_en,		\
+				   S_IRUGO | S_IWUSR,			\
+				   iio_scan_el_show,			\
+				   iio_scan_el_store),			\
+		.number =  _number,					\
+		.bit_count = _bits,					\
+		.label = _label,					\
+		.set_state = _cf,					\
+	}
+
 /**
  * IIO_SCAN_EL_TIMESTAMP - declare a special scan element for timestamps
  *
-- 
1.6.4.4

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

* [PATCH 08/20] staging:iio:max1363 move to new abi.
  2010-05-04 13:43             ` [PATCH 07/20] staging:iio: Clean out unused IIO_SCAN_EL and add IIO_SCAN_NAMED_EL_C Jonathan Cameron
@ 2010-05-04 13:43               ` Jonathan Cameron
  2010-05-04 13:43                 ` [PATCH 09/20] staging:iio: Documentation, update iio_utils.h for the move to a bus Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:43 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/adc/Kconfig        |    1 +
 drivers/staging/iio/adc/Makefile       |    2 +-
 drivers/staging/iio/adc/max1363.h      |  122 +++---
 drivers/staging/iio/adc/max1363_core.c |  762 +++++++++++++++++++-------------
 drivers/staging/iio/adc/max1363_ring.c |   65 ++-
 5 files changed, 548 insertions(+), 404 deletions(-)

diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index 3989c0c..101ea4b 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -7,6 +7,7 @@ config MAX1363
 	tristate "MAXIM max1363 ADC driver"
 	depends on I2C
 	select IIO_TRIGGER if IIO_RING_BUFFER
+	select MAX1363_RING_BUFFER
 	help
 	  Say yes here to build support for many MAXIM i2c analog to digital
 	  convertors (ADC). (max1361, max1362, max1363, max1364, max1136,
diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
index 08cee5c..18c9376 100644
--- a/drivers/staging/iio/adc/Makefile
+++ b/drivers/staging/iio/adc/Makefile
@@ -3,6 +3,6 @@
 #
 
 max1363-y := max1363_core.o
-max1363-$(CONFIG_MAX1363_RING_BUFFER) += max1363_ring.o
+max1363-y += max1363_ring.o
 
 obj-$(CONFIG_MAX1363) += max1363.o
diff --git a/drivers/staging/iio/adc/max1363.h b/drivers/staging/iio/adc/max1363.h
index c112fbe..72cf367 100644
--- a/drivers/staging/iio/adc/max1363.h
+++ b/drivers/staging/iio/adc/max1363.h
@@ -72,77 +72,54 @@
  * @numvals:	The number of values returned by a single scan
  */
 struct max1363_mode {
-	const char	*name;
 	int8_t		conf;
-	int		numvals;
+	long		modemask;
 };
 
-#define MAX1363_MODE_SINGLE(_num) {					\
-		.name = #_num,						\
-			.conf = MAX1363_CHANNEL_SEL(_num)		\
+#define MAX1363_MODE_SINGLE(_num, _mask) {				\
+		.conf = MAX1363_CHANNEL_SEL(_num)			\
 			| MAX1363_CONFIG_SCAN_SINGLE_1			\
 			| MAX1363_CONFIG_SE,				\
-			.numvals = 1,					\
+			.modemask = _mask,				\
 			}
 
-#define MAX1363_MODE_SINGLE_TIMES_8(_num) {				\
-		.name = #_num"x8",					\
-			.conf = MAX1363_CHANNEL_SEL(_num)		\
-			| MAX1363_CONFIG_SCAN_SINGLE_8			\
-			| MAX1363_CONFIG_SE,				\
-			.numvals = 8,					\
-			}
-
-#define MAX1363_MODE_SCAN_TO_CHANNEL(_num) {				\
-		.name = "0..."#_num,					\
-			.conf = MAX1363_CHANNEL_SEL(_num)		\
+#define MAX1363_MODE_SCAN_TO_CHANNEL(_num, _mask) {			\
+		.conf = MAX1363_CHANNEL_SEL(_num)			\
 			| MAX1363_CONFIG_SCAN_TO_CS			\
 			| MAX1363_CONFIG_SE,				\
-			.numvals = _num + 1,				\
+			.modemask = _mask,				\
 			}
 
 
 /* note not available for max1363 hence naming */
-#define MAX1236_MODE_SCAN_MID_TO_CHANNEL(_mid, _num) {			\
-		.name = #_mid"..."#_num,				\
-			.conf = MAX1363_CHANNEL_SEL(_num)		\
+#define MAX1236_MODE_SCAN_MID_TO_CHANNEL(_mid, _num, _mask) {		\
+		.conf = MAX1363_CHANNEL_SEL(_num)			\
 			| MAX1236_SCAN_MID_TO_CHANNEL			\
 			| MAX1363_CONFIG_SE,				\
-			.numvals = _num - _mid + 1			\
+			.modemask = _mask				\
 }
 
-#define MAX1363_MODE_DIFF_SINGLE(_nump, _numm) {			\
-		.name = #_nump"-"#_numm,				\
-			.conf = MAX1363_CHANNEL_SEL(_nump)		\
+#define MAX1363_MODE_DIFF_SINGLE(_nump, _numm, _mask) {			\
+		.conf = MAX1363_CHANNEL_SEL(_nump)			\
 			| MAX1363_CONFIG_SCAN_SINGLE_1			\
 			| MAX1363_CONFIG_DE,				\
-			.numvals = 1,					\
-			}
-
-#define MAX1363_MODE_DIFF_SINGLE_TIMES_8(_nump, _numm) {		\
-		.name = #_nump"-"#_numm,				\
-			.conf = MAX1363_CHANNEL_SEL(_nump)		\
-			| MAX1363_CONFIG_SCAN_SINGLE_8			\
-			| MAX1363_CONFIG_DE,				\
-			.numvals = 1,					\
+			.modemask = _mask				\
 			}
 
 /* Can't think how to automate naming so specify for now */
-#define MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(_name, _num, _numvals) { \
-		.name = #_name,						\
-			.conf = MAX1363_CHANNEL_SEL(_num)		\
+#define MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(_num, _numvals, _mask) { \
+		.conf = MAX1363_CHANNEL_SEL(_num)			\
 			| MAX1363_CONFIG_SCAN_TO_CS			\
 			| MAX1363_CONFIG_DE,				\
-			.numvals = _numvals,				\
+			.modemask = _mask				\
 			}
 
 /* note only available for max1363 hence naming */
-#define MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL_NAMED(_name, _num, _numvals) { \
-    .name = #_name,							\
-			.conf = MAX1363_CHANNEL_SEL(_num)		\
+#define MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(_num, _numvals, _mask) { \
+		.conf = MAX1363_CHANNEL_SEL(_num)			\
 			| MAX1236_SCAN_MID_TO_CHANNEL			\
 			| MAX1363_CONFIG_SE,				\
-			.numvals = _numvals,				\
+			.modemask = _mask				\
 }
 
 /* Not currently handled */
@@ -158,35 +135,43 @@ struct max1363_mode {
  * clear what all the various options actually do. Alternative suggestions
  * that don't require user to have intimate knowledge of the chip welcomed.
  */
+enum max1363_channels {
+	max1363_in0, max1363_in1, max1363_in2, max1363_in3,
+	max1363_in4, max1363_in5, max1363_in6, max1363_in7,
+	max1363_in8, max1363_in9, max1363_in10, max1363_in11,
+
+	max1363_in0min1, max1363_in2min3,
+	max1363_in4min5, max1363_in6min7,
+	max1363_in8min9, max1363_in10min11,
+
+	max1363_in1min0, max1363_in3min2,
+	max1363_in5min4, max1363_in7min6,
+	max1363_in9min8, max1363_in11min10,
+	};
 
 /* This must be maintained along side the max1363_mode_table in max1363_core */
 enum max1363_modes {
 	/* Single read of a single channel */
 	_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11,
-	/* Eight reads of a single channel */
-	se0, se1, se2, se3, se4, se5, se6, se7, se8, se9, se10, se11,
-	/* Scan to channel */
-	s0to1, s0to2, s0to3, s0to4, s0to5, s0to6,
-	s0to7, s0to8, s0to9, s0to10, s0to11,
 	/* Differential single read */
 	d0m1, d2m3, d4m5, d6m7, d8m9, d10m11,
 	d1m0, d3m2, d5m4, d7m6, d9m8, d11m10,
-	/* Differential single read 8 times */
-	de0m1, de2m3, de4m5, de6m7, de8m9, de10m11,
-	de1m0, de3m2, de5m4, de7m6, de9m8, de11m10,
-	/* Differential scan to channel */
-	d0m1to2m3, d0m1to4m5, d0m1to6m7, d0m1to8m9, d0m1to10m11,
-	d1m0to3m2, d1m0to5m4, d1m0to7m6, d1m0to9m8, d1m0to11m10,
-	/* Scan mid to channel max123{6-9} only */
-	s2to3, s6to7, s6to8, s6to9, s6to10, s6to11,
-	/* Differential scan mid to channel */
-	s6m7to8m9, s6m7to10m11, s7m6to9m8, s7m6to11m10,
+	/* Scan to channel and mid to channel where overlapping */
+	s0to1, s0to2, s2to3, s0to3, s0to4, s0to5, s0to6,
+	s6to7, s0to7, s6to8, s0to8, s6to9,
+	s0to9, s6to10, s0to10, s6to11, s0to11,
+	/* Differential scan to channel and mid to channel where overlapping */
+	d0m1to2m3, d0m1to4m5, d0m1to6m7, d6m7to8m9,
+	d0m1to8m9, d6m7to10m11, d0m1to10m11, d1m0to3m2,
+	d1m0to5m4, d1m0to7m6, d7m6to9m8, d1m0to9m8,
+	d7m6to11m10, d1m0to11m10,
 };
 
 /**
  * struct max1363_chip_info - chip specifc information
  * @name:		indentification string for chip
  * @num_inputs:		number of physical inputs on chip
+ * @bits:		accuracy of the adc in bits
  * @int_vref_mv:	the internal reference voltage
  * @monitor_mode:	whether the chip supports monitor interrupts
  * @mode_list:		array of available scan modes
@@ -196,11 +181,14 @@ enum max1363_modes {
 struct max1363_chip_info {
 	const char			*name;
 	u8				num_inputs;
+	u8				bits;
 	u16				int_vref_mv;
 	bool				monitor_mode;
 	const enum max1363_modes	*mode_list;
 	int				num_modes;
 	enum max1363_modes		default_mode;
+	struct attribute_group		*dev_attrs;
+	struct attribute_group		*scan_attrs;
 };
 
 
@@ -212,6 +200,7 @@ struct max1363_chip_info {
  * @configbyte:		cache of current device config byte
  * @chip_info:		chip model specific constants, available modes etc
  * @current_mode:	the scan mode of this chip
+ * @requestedmask:	a valid requested set of channels
  * @poll_work:		bottom half of polling interrupt handler
  * @protect_ring:	used to ensure only one polling bh running at a time
  * @reg:		supply regulator
@@ -223,16 +212,21 @@ struct max1363_state {
 	char				configbyte;
 	const struct max1363_chip_info	*chip_info;
 	const struct max1363_mode	*current_mode;
+	u32				requestedmask;
 	struct work_struct		poll_work;
 	atomic_t			protect_ring;
 	struct iio_trigger		*trig;
 	struct regulator		*reg;
 };
+
+const struct max1363_mode
+*max1363_match_mode(u32 mask, const struct max1363_chip_info *ci);
+
+int max1363_set_scan_mode(struct max1363_state *st);
+
 #ifdef CONFIG_MAX1363_RING_BUFFER
 
-ssize_t max1363_scan_from_ring(struct device *dev,
-			       struct device_attribute *attr,
-			       char *buf);
+int max1363_single_channel_from_ring(long mask, struct max1363_state *st);
 int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev);
 void max1363_ring_cleanup(struct iio_dev *indio_dev);
 
@@ -250,14 +244,12 @@ static inline int max1363_initialize_ring(struct iio_ring_buffer *ring)
 	return 0;
 };
 
-
-static inline ssize_t max1363_scan_from_ring(struct device *dev,
-					     struct device_attribute *attr,
-					     char *buf)
+int max1363_single_channel_from_ring(long mask, struct max1363_state *st)
 {
-	return 0;
+	return -EINVAL;
 };
 
+
 static inline int
 max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev)
 {
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c
index 790d1cc..e82f3e7 100644
--- a/drivers/staging/iio/adc/max1363_core.c
+++ b/drivers/staging/iio/adc/max1363_core.c
@@ -1,27 +1,26 @@
  /*
- * linux/drivers/industrialio/adc/max1363.c
- * Copyright (C) 2008 Jonathan Cameron
- *
- * based on linux/drivers/i2c/chips/max123x
- * Copyright (C) 2002-2004 Stefan Eletzhofer
- *
- * based on linux/drivers/acron/char/pcf8583.c
- * Copyright (C) 2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * max1363.c
- *
- * Partial support for max1363 and similar chips.
- *
- * Not currently implemented.
- *
- * - Monitor interrrupt generation.
- * - Control of internal reference.
- * - Sysfs scan interface currently assumes unipolar mode.
- */
+  * iio/adc/max1363.c
+  * Copyright (C) 2008-2010 Jonathan Cameron
+  *
+  * based on linux/drivers/i2c/chips/max123x
+  * Copyright (C) 2002-2004 Stefan Eletzhofer
+  *
+  * based on linux/drivers/acron/char/pcf8583.c
+  * Copyright (C) 2000 Russell King
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+  *
+  * max1363.c
+  *
+  * Partial support for max1363 and similar chips.
+  *
+  * Not currently implemented.
+  *
+  * - Monitor interrrupt generation.
+  * - Control of internal reference.
+  */
 
 #include <linux/interrupt.h>
 #include <linux/gpio.h>
@@ -38,118 +37,318 @@
 #include "../iio.h"
 #include "../sysfs.h"
 
+#include "../ring_generic.h"
+#include "adc.h"
 #include "max1363.h"
 
-/* Available scan modes.
- * Awkwardly the associated enum is in the header so it is available to
- * the ring buffer code.
- */
-static const struct  max1363_mode max1363_mode_table[] = {
-	MAX1363_MODE_SINGLE(0),
-	MAX1363_MODE_SINGLE(1),
-	MAX1363_MODE_SINGLE(2),
-	MAX1363_MODE_SINGLE(3),
-	MAX1363_MODE_SINGLE(4),
-	MAX1363_MODE_SINGLE(5),
-	MAX1363_MODE_SINGLE(6),
-	MAX1363_MODE_SINGLE(7),
-	MAX1363_MODE_SINGLE(8),
-	MAX1363_MODE_SINGLE(9),
-	MAX1363_MODE_SINGLE(10),
-	MAX1363_MODE_SINGLE(11),
-
-	MAX1363_MODE_SINGLE_TIMES_8(0),
-	MAX1363_MODE_SINGLE_TIMES_8(1),
-	MAX1363_MODE_SINGLE_TIMES_8(2),
-	MAX1363_MODE_SINGLE_TIMES_8(3),
-	MAX1363_MODE_SINGLE_TIMES_8(4),
-	MAX1363_MODE_SINGLE_TIMES_8(5),
-	MAX1363_MODE_SINGLE_TIMES_8(6),
-	MAX1363_MODE_SINGLE_TIMES_8(7),
-	MAX1363_MODE_SINGLE_TIMES_8(8),
-	MAX1363_MODE_SINGLE_TIMES_8(9),
-	MAX1363_MODE_SINGLE_TIMES_8(10),
-	MAX1363_MODE_SINGLE_TIMES_8(11),
-
-	MAX1363_MODE_SCAN_TO_CHANNEL(1),
-	MAX1363_MODE_SCAN_TO_CHANNEL(2),
-	MAX1363_MODE_SCAN_TO_CHANNEL(3),
-	MAX1363_MODE_SCAN_TO_CHANNEL(4),
-	MAX1363_MODE_SCAN_TO_CHANNEL(5),
-	MAX1363_MODE_SCAN_TO_CHANNEL(6),
-	MAX1363_MODE_SCAN_TO_CHANNEL(7),
-	MAX1363_MODE_SCAN_TO_CHANNEL(8),
-	MAX1363_MODE_SCAN_TO_CHANNEL(9),
-	MAX1363_MODE_SCAN_TO_CHANNEL(10),
-	MAX1363_MODE_SCAN_TO_CHANNEL(11),
-
-	MAX1363_MODE_DIFF_SINGLE(0, 1),
-	MAX1363_MODE_DIFF_SINGLE(2, 3),
-	MAX1363_MODE_DIFF_SINGLE(4, 5),
-	MAX1363_MODE_DIFF_SINGLE(6, 7),
-	MAX1363_MODE_DIFF_SINGLE(8, 9),
-	MAX1363_MODE_DIFF_SINGLE(10, 11),
-	MAX1363_MODE_DIFF_SINGLE(1, 0),
-	MAX1363_MODE_DIFF_SINGLE(3, 2),
-	MAX1363_MODE_DIFF_SINGLE(5, 4),
-	MAX1363_MODE_DIFF_SINGLE(7, 6),
-	MAX1363_MODE_DIFF_SINGLE(9, 8),
-	MAX1363_MODE_DIFF_SINGLE(11, 10),
-
-	MAX1363_MODE_DIFF_SINGLE_TIMES_8(0, 1),
-	MAX1363_MODE_DIFF_SINGLE_TIMES_8(2, 3),
-	MAX1363_MODE_DIFF_SINGLE_TIMES_8(4, 5),
-	MAX1363_MODE_DIFF_SINGLE_TIMES_8(6, 7),
-	MAX1363_MODE_DIFF_SINGLE_TIMES_8(8, 9),
-	MAX1363_MODE_DIFF_SINGLE_TIMES_8(10, 11),
-	MAX1363_MODE_DIFF_SINGLE_TIMES_8(1, 0),
-	MAX1363_MODE_DIFF_SINGLE_TIMES_8(3, 2),
-	MAX1363_MODE_DIFF_SINGLE_TIMES_8(5, 4),
-	MAX1363_MODE_DIFF_SINGLE_TIMES_8(7, 6),
-	MAX1363_MODE_DIFF_SINGLE_TIMES_8(9, 8),
-	MAX1363_MODE_DIFF_SINGLE_TIMES_8(11, 10),
-
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(0-1...2-3, 2, 2),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(0-1...4-5, 4, 3),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(0-1...6-7, 6, 4),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(0-1...8-9, 8, 5),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(0-1...10-11, 10, 6),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(1-0...3-2, 3, 2),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(1-0...5-4, 5, 3),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(1-0...7-6, 7, 4),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(1-0...9-8, 9, 5),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(1-0...11-10, 11, 6),
-
-	MAX1236_MODE_SCAN_MID_TO_CHANNEL(2, 3),
-	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 7),
-	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 8),
-	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 9),
-	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 10),
-	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 11),
-
-	MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL_NAMED(6-7...8-9, 8, 2),
-	MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL_NAMED(6-7...10-11, 10, 3),
-	MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL_NAMED(7-6...9-8, 9, 2),
-	MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL_NAMED(7-6...11-10, 11, 3),
+/* Here we claim all are 16 bits. This currently does no harm and saves
+ * us a lot of scan element listings */
+
+#define MAX1363_SCAN_EL(number)						\
+	IIO_SCAN_EL_C(in##number, number, IIO_UNSIGNED(16), 0, NULL);
+#define MAX1363_SCAN_EL_D(p, n, number)					\
+	IIO_SCAN_NAMED_EL_C(in##p##m##in##n, in##p-in##n,		\
+			number, IIO_SIGNED(16), 0 , NULL);
+
+static MAX1363_SCAN_EL(0);
+static MAX1363_SCAN_EL(1);
+static MAX1363_SCAN_EL(2);
+static MAX1363_SCAN_EL(3);
+static MAX1363_SCAN_EL(4);
+static MAX1363_SCAN_EL(5);
+static MAX1363_SCAN_EL(6);
+static MAX1363_SCAN_EL(7);
+static MAX1363_SCAN_EL(8);
+static MAX1363_SCAN_EL(9);
+static MAX1363_SCAN_EL(10);
+static MAX1363_SCAN_EL(11);
+static MAX1363_SCAN_EL_D(0, 1, 12);
+static MAX1363_SCAN_EL_D(2, 3, 13);
+static MAX1363_SCAN_EL_D(4, 5, 14);
+static MAX1363_SCAN_EL_D(6, 7, 15);
+static MAX1363_SCAN_EL_D(8, 9, 16);
+static MAX1363_SCAN_EL_D(10, 11, 17);
+static MAX1363_SCAN_EL_D(1, 0, 18);
+static MAX1363_SCAN_EL_D(3, 2, 19);
+static MAX1363_SCAN_EL_D(5, 4, 20);
+static MAX1363_SCAN_EL_D(7, 6, 21);
+static MAX1363_SCAN_EL_D(9, 8, 22);
+static MAX1363_SCAN_EL_D(11, 10, 23);
+
+static const struct max1363_mode max1363_mode_table[] = {
+	/* All of the single channel options first */
+	MAX1363_MODE_SINGLE(0, 1 << 0),
+	MAX1363_MODE_SINGLE(1, 1 << 1),
+	MAX1363_MODE_SINGLE(2, 1 << 2),
+	MAX1363_MODE_SINGLE(3, 1 << 3),
+	MAX1363_MODE_SINGLE(4, 1 << 4),
+	MAX1363_MODE_SINGLE(5, 1 << 5),
+	MAX1363_MODE_SINGLE(6, 1 << 6),
+	MAX1363_MODE_SINGLE(7, 1 << 7),
+	MAX1363_MODE_SINGLE(8, 1 << 8),
+	MAX1363_MODE_SINGLE(9, 1 << 9),
+	MAX1363_MODE_SINGLE(10, 1 << 10),
+	MAX1363_MODE_SINGLE(11, 1 << 11),
+
+	MAX1363_MODE_DIFF_SINGLE(0, 1, 1 << 12),
+	MAX1363_MODE_DIFF_SINGLE(2, 3, 1 << 13),
+	MAX1363_MODE_DIFF_SINGLE(4, 5, 1 << 14),
+	MAX1363_MODE_DIFF_SINGLE(6, 7, 1 << 15),
+	MAX1363_MODE_DIFF_SINGLE(8, 9, 1 << 16),
+	MAX1363_MODE_DIFF_SINGLE(10, 11, 1 << 17),
+	MAX1363_MODE_DIFF_SINGLE(1, 0, 1 << 18),
+	MAX1363_MODE_DIFF_SINGLE(3, 2, 1 << 19),
+	MAX1363_MODE_DIFF_SINGLE(5, 4, 1 << 20),
+	MAX1363_MODE_DIFF_SINGLE(7, 6, 1 << 21),
+	MAX1363_MODE_DIFF_SINGLE(9, 8, 1 << 22),
+	MAX1363_MODE_DIFF_SINGLE(11, 10, 1 << 23),
+
+	/* The multichannel scans next */
+	MAX1363_MODE_SCAN_TO_CHANNEL(1, 0x003),
+	MAX1363_MODE_SCAN_TO_CHANNEL(2, 0x007),
+	MAX1236_MODE_SCAN_MID_TO_CHANNEL(2, 3, 0x00C),
+	MAX1363_MODE_SCAN_TO_CHANNEL(3, 0x00F),
+	MAX1363_MODE_SCAN_TO_CHANNEL(4, 0x01F),
+	MAX1363_MODE_SCAN_TO_CHANNEL(5, 0x03F),
+	MAX1363_MODE_SCAN_TO_CHANNEL(6, 0x07F),
+	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 7, 0x0C0),
+	MAX1363_MODE_SCAN_TO_CHANNEL(7, 0x0FF),
+	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 8, 0x1C0),
+	MAX1363_MODE_SCAN_TO_CHANNEL(8, 0x1FF),
+	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 9, 0x3C0),
+	MAX1363_MODE_SCAN_TO_CHANNEL(9, 0x3FF),
+	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 10, 0x7C0),
+	MAX1363_MODE_SCAN_TO_CHANNEL(10, 0x7FF),
+	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 11, 0xFC0),
+	MAX1363_MODE_SCAN_TO_CHANNEL(11, 0xFFF),
+
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(2, 2, 0x003000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(4, 3, 0x007000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(6, 4, 0x00F000),
+	MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(8, 2, 0x018000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(8, 5, 0x01F000),
+	MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(10, 3, 0x038000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(10, 6, 0x3F000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(3, 2, 0x0C0000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(5, 3, 0x1C0000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(7, 4, 0x3C0000),
+	MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(9, 2, 0x600000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(9, 5, 0x7C0000),
+	MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(11, 3, 0xE00000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(11, 6, 0xFC0000),
 };
 
+const struct max1363_mode
+*max1363_match_mode(u32 mask, const struct max1363_chip_info *ci) {
+	int i;
+	if (mask)
+		for (i = 0; i < ci->num_modes; i++)
+			if (!((~max1363_mode_table[ci->mode_list[i]]
+			       .modemask) &
+			      mask))
+				return &max1363_mode_table[ci
+							   ->mode_list[i]];
+	return 0;
+};
+
+static ssize_t max1363_show_precision(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct max1363_state *st = iio_dev_get_devdata(dev_info);
+	return sprintf(buf, "%d\n", st->chip_info->bits);
+}
+
+static IIO_DEVICE_ATTR(in_precision, S_IRUGO, max1363_show_precision,
+		       NULL, 0);
+
+static int max1363_write_basic_config(struct i2c_client *client,
+				      unsigned char d1,
+				      unsigned char d2)
+{
+	int ret;
+	u8 *tx_buf = kmalloc(2 , GFP_KERNEL);
+
+	if (!tx_buf)
+		return -ENOMEM;
+	tx_buf[0] = d1;
+	tx_buf[1] = d2;
+
+	ret = i2c_master_send(client, tx_buf, 2);
+	kfree(tx_buf);
+
+	return (ret > 0) ? 0 : ret;
+}
+
+int max1363_set_scan_mode(struct max1363_state *st)
+{
+	st->configbyte &= ~(MAX1363_CHANNEL_SEL_MASK
+			    | MAX1363_SCAN_MASK
+			    | MAX1363_SE_DE_MASK);
+	st->configbyte |= st->current_mode->conf;
+
+	return max1363_write_basic_config(st->client,
+					  st->setupbyte,
+					  st->configbyte);
+}
+
+static ssize_t max1363_read_single_channel(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buf)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct max1363_state *st = iio_dev_get_devdata(dev_info);
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+	struct i2c_client *client = st->client;
+	int ret = 0, len = 0;
+	s32 data ;
+	char rxbuf[2];
+	long mask;
+
+	mutex_lock(&dev_info->mlock);
+	/* If ring buffer capture is occuring, query the buffer */
+	if (iio_ring_enabled(dev_info)) {
+		mask = max1363_mode_table[this_attr->address].modemask;
+		data = max1363_single_channel_from_ring(mask, st);
+		if (data < 0) {
+			ret = data;
+			goto error_ret;
+		}
+	} else {
+		/* Check to see if current scan mode is correct */
+		if (st->current_mode !=
+		    &max1363_mode_table[this_attr->address]) {
+			/* Update scan mode if needed */
+			st->current_mode
+				= &max1363_mode_table[this_attr->address];
+			ret = max1363_set_scan_mode(st);
+			if (ret)
+				goto error_ret;
+		}
+		/* Get reading */
+		data = i2c_master_recv(client, rxbuf, 2);
+		if (data < 0) {
+			ret = data;
+			goto error_ret;
+		}
+		data = (s32)(rxbuf[1]) | ((s32)(rxbuf[0] & 0x0F)) << 8;
+	}
+	/* Pretty print the result */
+	len = sprintf(buf, "%u\n", data);
+
+error_ret:
+	mutex_unlock(&dev_info->mlock);
+	return ret ? ret : len;
+}
+
+/* Direct read attribtues */
+static IIO_DEV_ATTR_IN_RAW(0, max1363_read_single_channel, _s0);
+static IIO_DEV_ATTR_IN_RAW(1, max1363_read_single_channel, _s1);
+static IIO_DEV_ATTR_IN_RAW(2, max1363_read_single_channel, _s2);
+static IIO_DEV_ATTR_IN_RAW(3, max1363_read_single_channel, _s3);
+static IIO_DEV_ATTR_IN_RAW(4, max1363_read_single_channel, _s4);
+static IIO_DEV_ATTR_IN_RAW(5, max1363_read_single_channel, _s5);
+static IIO_DEV_ATTR_IN_RAW(6, max1363_read_single_channel, _s6);
+static IIO_DEV_ATTR_IN_RAW(7, max1363_read_single_channel, _s7);
+static IIO_DEV_ATTR_IN_RAW(8, max1363_read_single_channel, _s8);
+static IIO_DEV_ATTR_IN_RAW(9, max1363_read_single_channel, _s9);
+static IIO_DEV_ATTR_IN_RAW(10, max1363_read_single_channel, _s10);
+static IIO_DEV_ATTR_IN_RAW(11, max1363_read_single_channel, _s11);
+
+static IIO_DEV_ATTR_IN_DIFF_RAW(0, 1, max1363_read_single_channel, d0m1);
+static IIO_DEV_ATTR_IN_DIFF_RAW(2, 3, max1363_read_single_channel, d2m3);
+static IIO_DEV_ATTR_IN_DIFF_RAW(4, 5, max1363_read_single_channel, d4m5);
+static IIO_DEV_ATTR_IN_DIFF_RAW(6, 7, max1363_read_single_channel, d6m7);
+static IIO_DEV_ATTR_IN_DIFF_RAW(8, 9, max1363_read_single_channel, d8m9);
+static IIO_DEV_ATTR_IN_DIFF_RAW(10, 11, max1363_read_single_channel, d10m11);
+static IIO_DEV_ATTR_IN_DIFF_RAW(1, 0, max1363_read_single_channel, d1m0);
+static IIO_DEV_ATTR_IN_DIFF_RAW(3, 2, max1363_read_single_channel, d3m2);
+static IIO_DEV_ATTR_IN_DIFF_RAW(5, 4, max1363_read_single_channel, d5m4);
+static IIO_DEV_ATTR_IN_DIFF_RAW(7, 6, max1363_read_single_channel, d7m6);
+static IIO_DEV_ATTR_IN_DIFF_RAW(9, 8, max1363_read_single_channel, d9m8);
+static IIO_DEV_ATTR_IN_DIFF_RAW(11, 10, max1363_read_single_channel, d11m10);
+
+
+static ssize_t max1363_show_scale(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	/* Driver currently only support internal vref */
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct max1363_state *st = iio_dev_get_devdata(dev_info);
+	/* Corresponds to Vref / 2^(bits) */
+
+	if ((1 << (st->chip_info->bits + 1))
+	    > st->chip_info->int_vref_mv)
+		return sprintf(buf, "0.5\n");
+	else
+		return sprintf(buf, "%d\n",
+			st->chip_info->int_vref_mv >> st->chip_info->bits);
+}
+
+IIO_DEVICE_ATTR(in_scale, S_IRUGO, max1363_show_scale, NULL, 0);
+
+static ssize_t max1363_show_name(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct max1363_state *st = iio_dev_get_devdata(dev_info);
+	return sprintf(buf, "%s\n", st->chip_info->name);
+}
+
+IIO_DEVICE_ATTR(name, S_IRUGO, max1363_show_name, NULL, 0);
+
 /* Applies to max1363 */
 static const enum max1363_modes max1363_mode_list[] = {
 	_s0, _s1, _s2, _s3,
-	se0, se1, se2, se3,
 	s0to1, s0to2, s0to3,
 	d0m1, d2m3, d1m0, d3m2,
-	de0m1, de2m3, de1m0, de3m2,
 	d0m1to2m3, d1m0to3m2,
 };
 
+static struct attribute *max1363_device_attrs[] = {
+	&iio_dev_attr_in0_raw.dev_attr.attr,
+	&iio_dev_attr_in1_raw.dev_attr.attr,
+	&iio_dev_attr_in2_raw.dev_attr.attr,
+	&iio_dev_attr_in3_raw.dev_attr.attr,
+	&iio_dev_attr_in0min1_raw.dev_attr.attr,
+	&iio_dev_attr_in2min3_raw.dev_attr.attr,
+	&iio_dev_attr_in1min0_raw.dev_attr.attr,
+	&iio_dev_attr_in3min2_raw.dev_attr.attr,
+	&iio_dev_attr_name.dev_attr.attr,
+	&iio_dev_attr_in_scale.dev_attr.attr,
+	NULL
+};
+
+static struct attribute_group max1363_dev_attr_group = {
+	.attrs = max1363_device_attrs,
+};
+
+static struct attribute *max1363_scan_el_attrs[] = {
+	&iio_scan_el_in0.dev_attr.attr,
+	&iio_scan_el_in1.dev_attr.attr,
+	&iio_scan_el_in2.dev_attr.attr,
+	&iio_scan_el_in3.dev_attr.attr,
+	&iio_scan_el_in0min1.dev_attr.attr,
+	&iio_scan_el_in2min3.dev_attr.attr,
+	&iio_scan_el_in1min0.dev_attr.attr,
+	&iio_scan_el_in3min2.dev_attr.attr,
+	&iio_dev_attr_in_precision.dev_attr.attr,
+	NULL,
+};
+
+static struct attribute_group max1363_scan_el_group = {
+	.name = "scan_elements",
+	.attrs = max1363_scan_el_attrs,
+};
+
 /* Appies to max1236, max1237 */
 static const enum max1363_modes max1236_mode_list[] = {
 	_s0, _s1, _s2, _s3,
-	se0, se1, se2, se3,
 	s0to1, s0to2, s0to3,
 	d0m1, d2m3, d1m0, d3m2,
-	de0m1, de2m3, de1m0, de3m2,
 	d0m1to2m3, d1m0to3m2,
 	s2to3,
 };
@@ -157,19 +356,83 @@ static const enum max1363_modes max1236_mode_list[] = {
 /* Applies to max1238, max1239 */
 static const enum max1363_modes max1238_mode_list[] = {
 	_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11,
-	se0, se1, se2, se3, se4, se5, se6, se7, se8, se9, se10, se11,
 	s0to1, s0to2, s0to3, s0to4, s0to5, s0to6,
 	s0to7, s0to8, s0to9, s0to10, s0to11,
 	d0m1, d2m3, d4m5, d6m7, d8m9, d10m11,
 	d1m0, d3m2, d5m4, d7m6, d9m8, d11m10,
-	de0m1, de2m3, de4m5, de6m7, de8m9, de10m11,
-	de1m0, de3m2, de5m4, de7m6, de9m8, de11m10,
 	d0m1to2m3, d0m1to4m5, d0m1to6m7, d0m1to8m9, d0m1to10m11,
 	d1m0to3m2, d1m0to5m4, d1m0to7m6, d1m0to9m8, d1m0to11m10,
 	s6to7, s6to8, s6to9, s6to10, s6to11,
-	s6m7to8m9, s6m7to10m11, s7m6to9m8, s7m6to11m10,
+	d6m7to8m9, d6m7to10m11, d7m6to9m8, d7m6to11m10,
 };
 
+static struct attribute *max1238_device_attrs[] = {
+	&iio_dev_attr_in0_raw.dev_attr.attr,
+	&iio_dev_attr_in1_raw.dev_attr.attr,
+	&iio_dev_attr_in2_raw.dev_attr.attr,
+	&iio_dev_attr_in3_raw.dev_attr.attr,
+	&iio_dev_attr_in4_raw.dev_attr.attr,
+	&iio_dev_attr_in5_raw.dev_attr.attr,
+	&iio_dev_attr_in6_raw.dev_attr.attr,
+	&iio_dev_attr_in7_raw.dev_attr.attr,
+	&iio_dev_attr_in8_raw.dev_attr.attr,
+	&iio_dev_attr_in9_raw.dev_attr.attr,
+	&iio_dev_attr_in10_raw.dev_attr.attr,
+	&iio_dev_attr_in11_raw.dev_attr.attr,
+	&iio_dev_attr_in0min1_raw.dev_attr.attr,
+	&iio_dev_attr_in2min3_raw.dev_attr.attr,
+	&iio_dev_attr_in4min5_raw.dev_attr.attr,
+	&iio_dev_attr_in6min7_raw.dev_attr.attr,
+	&iio_dev_attr_in8min9_raw.dev_attr.attr,
+	&iio_dev_attr_in10min11_raw.dev_attr.attr,
+	&iio_dev_attr_in1min0_raw.dev_attr.attr,
+	&iio_dev_attr_in3min2_raw.dev_attr.attr,
+	&iio_dev_attr_in5min4_raw.dev_attr.attr,
+	&iio_dev_attr_in7min6_raw.dev_attr.attr,
+	&iio_dev_attr_in9min8_raw.dev_attr.attr,
+	&iio_dev_attr_in11min10_raw.dev_attr.attr,
+	&iio_dev_attr_name.dev_attr.attr,
+	&iio_dev_attr_in_scale.dev_attr.attr,
+	NULL
+};
+
+static struct attribute_group max1238_dev_attr_group = {
+	.attrs = max1238_device_attrs,
+};
+
+static struct attribute *max1238_scan_el_attrs[] = {
+	&iio_scan_el_in0.dev_attr.attr,
+	&iio_scan_el_in1.dev_attr.attr,
+	&iio_scan_el_in2.dev_attr.attr,
+	&iio_scan_el_in3.dev_attr.attr,
+	&iio_scan_el_in4.dev_attr.attr,
+	&iio_scan_el_in5.dev_attr.attr,
+	&iio_scan_el_in6.dev_attr.attr,
+	&iio_scan_el_in7.dev_attr.attr,
+	&iio_scan_el_in8.dev_attr.attr,
+	&iio_scan_el_in9.dev_attr.attr,
+	&iio_scan_el_in10.dev_attr.attr,
+	&iio_scan_el_in11.dev_attr.attr,
+	&iio_scan_el_in0min1.dev_attr.attr,
+	&iio_scan_el_in2min3.dev_attr.attr,
+	&iio_scan_el_in4min5.dev_attr.attr,
+	&iio_scan_el_in6min7.dev_attr.attr,
+	&iio_scan_el_in8min9.dev_attr.attr,
+	&iio_scan_el_in10min11.dev_attr.attr,
+	&iio_scan_el_in1min0.dev_attr.attr,
+	&iio_scan_el_in3min2.dev_attr.attr,
+	&iio_scan_el_in5min4.dev_attr.attr,
+	&iio_scan_el_in7min6.dev_attr.attr,
+	&iio_scan_el_in9min8.dev_attr.attr,
+	&iio_scan_el_in11min10.dev_attr.attr,
+	&iio_dev_attr_in_precision.dev_attr.attr,
+	NULL,
+};
+
+static struct attribute_group max1238_scan_el_group = {
+	.name = "scan_elements",
+	.attrs = max1238_scan_el_attrs,
+};
 
 enum { max1361,
        max1362,
@@ -190,118 +453,130 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
 	{
 		.name = "max1361",
 		.num_inputs = 4,
+		.bits = 10,
+		.int_vref_mv = 2048,
 		.monitor_mode = 1,
 		.mode_list = max1363_mode_list,
 		.num_modes = ARRAY_SIZE(max1363_mode_list),
 		.default_mode = s0to3,
+		.dev_attrs = &max1363_dev_attr_group,
+		.scan_attrs = &max1363_scan_el_group,
 	}, {
 		.name = "max1362",
 		.num_inputs = 4,
+		.bits = 10,
+		.int_vref_mv = 4096,
 		.monitor_mode = 1,
 		.mode_list = max1363_mode_list,
 		.num_modes = ARRAY_SIZE(max1363_mode_list),
 		.default_mode = s0to3,
+		.dev_attrs = &max1363_dev_attr_group,
+		.scan_attrs = &max1363_scan_el_group,
 	}, {
 		.name = "max1363",
 		.num_inputs = 4,
+		.bits = 12,
+		.int_vref_mv = 2048,
 		.monitor_mode = 1,
 		.mode_list = max1363_mode_list,
 		.num_modes = ARRAY_SIZE(max1363_mode_list),
 		.default_mode = s0to3,
+		.dev_attrs = &max1363_dev_attr_group,
+		.scan_attrs = &max1363_scan_el_group,
 	}, {
 		.name = "max1364",
 		.num_inputs = 4,
+		.bits = 12,
+		.int_vref_mv = 4096,
 		.monitor_mode = 1,
 		.mode_list = max1363_mode_list,
 		.num_modes = ARRAY_SIZE(max1363_mode_list),
 		.default_mode = s0to3,
+		.dev_attrs = &max1363_dev_attr_group,
+		.scan_attrs = &max1363_scan_el_group,
 	}, {
 		.name = "max1136",
 		.num_inputs = 4,
+		.bits = 10,
 		.int_vref_mv = 4096,
 		.mode_list = max1236_mode_list,
 		.num_modes = ARRAY_SIZE(max1236_mode_list),
 		.default_mode = s0to3,
+		.dev_attrs = &max1363_dev_attr_group,
+		.scan_attrs = &max1363_scan_el_group,
 	}, {
 		.name = "max1137",
 		.num_inputs = 4,
+		.bits = 10,
 		.int_vref_mv = 2048,
 		.mode_list = max1236_mode_list,
 		.num_modes = ARRAY_SIZE(max1236_mode_list),
 		.default_mode = s0to3,
+		.dev_attrs = &max1363_dev_attr_group,
+		.scan_attrs = &max1363_scan_el_group,
 	}, {
 		.name = "max1138",
 		.num_inputs = 12,
+		.bits = 10,
 		.int_vref_mv = 4096,
 		.mode_list = max1238_mode_list,
 		.num_modes = ARRAY_SIZE(max1238_mode_list),
 		.default_mode = s0to11,
+		.dev_attrs = &max1238_dev_attr_group,
+		.scan_attrs = &max1238_scan_el_group,
 	}, {
 		.name = "max1139",
 		.num_inputs = 12,
+		.bits = 10,
 		.int_vref_mv = 2048,
 		.mode_list = max1238_mode_list,
 		.num_modes = ARRAY_SIZE(max1238_mode_list),
 		.default_mode = s0to11,
+		.dev_attrs = &max1238_dev_attr_group,
+		.scan_attrs = &max1238_scan_el_group,
 	}, {
 		.name = "max1236",
 		.num_inputs = 4,
+		.bits = 12,
 		.int_vref_mv = 4096,
 		.mode_list = max1236_mode_list,
 		.num_modes = ARRAY_SIZE(max1236_mode_list),
 		.default_mode = s0to3,
+		.dev_attrs = &max1363_dev_attr_group,
+		.scan_attrs = &max1363_scan_el_group,
 	}, {
 		.name = "max1237",
 		.num_inputs = 4,
+		.bits = 12,
 		.int_vref_mv = 2048,
 		.mode_list = max1236_mode_list,
 		.num_modes = ARRAY_SIZE(max1236_mode_list),
 		.default_mode = s0to3,
+		.dev_attrs = &max1363_dev_attr_group,
+		.scan_attrs = &max1363_scan_el_group,
 	}, {
 		.name = "max1238",
 		.num_inputs = 12,
+		.bits = 12,
 		.int_vref_mv = 4096,
 		.mode_list = max1238_mode_list,
 		.num_modes = ARRAY_SIZE(max1238_mode_list),
 		.default_mode = s0to11,
+		.dev_attrs = &max1238_dev_attr_group,
+		.scan_attrs = &max1238_scan_el_group,
 	}, {
 		.name = "max1239",
 		.num_inputs = 12,
+		.bits = 12,
 		.int_vref_mv = 2048,
 		.mode_list = max1238_mode_list,
 		.num_modes = ARRAY_SIZE(max1238_mode_list),
 		.default_mode = s0to11,
+		.dev_attrs = &max1238_dev_attr_group,
+		.scan_attrs = &max1238_scan_el_group,
 	},
 };
 
-static int max1363_write_basic_config(struct i2c_client *client,
-				      unsigned char d1,
-				      unsigned char d2)
-{
-	int ret;
-	u8 *tx_buf = kmalloc(2 , GFP_KERNEL);
-	if (!tx_buf)
-		return -ENOMEM;
-	tx_buf[0] = d1;
-	tx_buf[1] = d2;
-
-	ret = i2c_master_send(client, tx_buf, 2);
-	kfree(tx_buf);
-	return (ret > 0) ? 0 : ret;
-}
-
-static int max1363_set_scan_mode(struct max1363_state *st)
-{
-	st->configbyte &= ~(MAX1363_CHANNEL_SEL_MASK
-			    | MAX1363_SCAN_MASK
-			    | MAX1363_SE_DE_MASK);
-	st->configbyte |= st->current_mode->conf;
-
-	return max1363_write_basic_config(st->client,
-					  st->setupbyte,
-					  st->configbyte);
-}
-
 static int max1363_initial_setup(struct max1363_state *st)
 {
 	st->setupbyte = MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD
@@ -318,167 +593,6 @@ static int max1363_initial_setup(struct max1363_state *st)
 	return max1363_set_scan_mode(st);
 }
 
-static ssize_t max1363_show_av_scan_modes(struct device *dev,
-					  struct device_attribute *attr,
-					  char *buf)
-{
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct max1363_state *st = dev_info->dev_data;
-	int i, len = 0;
-
-	for (i = 0; i < st->chip_info->num_modes; i++)
-		len += sprintf(buf + len, "%s ",
-			       max1363_mode_table[st->chip_info
-						  ->mode_list[i]].name);
-	len += sprintf(buf + len, "\n");
-
-	return len;
-}
-
-
-/* The dev here is the sysfs related one, not the underlying i2c one */
-static ssize_t max1363_scan_direct(struct device *dev,
-				   struct device_attribute *attr,
-				   char *buf)
-{
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct max1363_state *st = dev_info->dev_data;
-	int len = 0, ret, i;
-	struct i2c_client *client = st->client;
-	char *rxbuf;
-
-	if (st->current_mode->numvals == 0)
-		return 0;
-	rxbuf = kmalloc(st->current_mode->numvals*2, GFP_KERNEL);
-	if (rxbuf == NULL)
-		return -ENOMEM;
-
-	/* Interpretation depends on whether these are signed or not!*/
-	/* Assume not for now */
-	ret = i2c_master_recv(client, rxbuf, st->current_mode->numvals*2);
-
-	if (ret < 0)
-		return ret;
-	for (i = 0; i < st->current_mode->numvals; i++)
-		len += sprintf(buf+len, "%d ",
-			       ((int)(rxbuf[i*2+0]&0x0F) << 8)
-			       + ((int)(rxbuf[i*2+1])));
-	kfree(rxbuf);
-	len += sprintf(buf + len, "\n");
-
-	return len;
-}
-
-static ssize_t max1363_scan(struct device *dev,
-			    struct device_attribute *attr,
-			    char *buf)
-{
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	int ret;
-
-	mutex_lock(&dev_info->mlock);
-	if (dev_info->currentmode == INDIO_RING_TRIGGERED)
-		ret = max1363_scan_from_ring(dev, attr, buf);
-	else
-		ret = max1363_scan_direct(dev, attr, buf);
-	mutex_unlock(&dev_info->mlock);
-
-	return ret;
-}
-
-/* Cannot query the device, so use local copy of state */
-static ssize_t max1363_show_scan_mode(struct device *dev,
-				      struct device_attribute *attr,
-				      char *buf)
-{
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct max1363_state *st = dev_info->dev_data;
-
-	return sprintf(buf, "%s\n", st->current_mode->name);
-}
-
-static const struct max1363_mode
-*__max1363_find_mode_in_ci(const struct max1363_chip_info *info,
-				  const char *buf)
-{
-	int i;
-	for (i = 0; i <  info->num_modes; i++)
-		if (strcmp(max1363_mode_table[info->mode_list[i]].name, buf)
-		    == 0)
-			return &max1363_mode_table[info->mode_list[i]];
-	return NULL;
-}
-
-static ssize_t max1363_store_scan_mode(struct device *dev,
-				       struct device_attribute *attr,
-				       const char *buf,
-				       size_t len)
-{
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct max1363_state *st = dev_info->dev_data;
-	const struct max1363_mode *new_mode;
-	int ret;
-
-	mutex_lock(&dev_info->mlock);
-	new_mode = NULL;
-	/* Avoid state changes if a ring buffer is enabled */
-	if (!iio_ring_enabled(dev_info)) {
-		new_mode
-			= __max1363_find_mode_in_ci(st->chip_info, buf);
-		if (!new_mode) {
-			ret = -EINVAL;
-			goto error_ret;
-		}
-		st->current_mode = new_mode;
-		ret =  max1363_set_scan_mode(st);
-		if (ret)
-			goto error_ret;
-	} else {
-		ret = -EBUSY;
-		goto error_ret;
-	}
-	mutex_unlock(&dev_info->mlock);
-
-	return len;
-
-error_ret:
-	mutex_unlock(&dev_info->mlock);
-
-	return ret;
-}
-
-IIO_DEV_ATTR_AVAIL_SCAN_MODES(max1363_show_av_scan_modes);
-IIO_DEV_ATTR_SCAN_MODE(S_IRUGO | S_IWUSR,
-		       max1363_show_scan_mode,
-		       max1363_store_scan_mode);
-
-IIO_DEV_ATTR_SCAN(max1363_scan);
-
-static ssize_t max1363_show_name(struct device *dev,
-				 struct device_attribute *attr,
-				 char *buf)
-{
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct max1363_state *st = dev_info->dev_data;
-	return sprintf(buf, "%s\n", st->chip_info->name);
-}
-
-IIO_DEVICE_ATTR(name, S_IRUGO, max1363_show_name, NULL, 0);
-
-/*name export */
-
-static struct attribute *max1363_attributes[] = {
-	&iio_dev_attr_available_scan_modes.dev_attr.attr,
-	&iio_dev_attr_scan_mode.dev_attr.attr,
-	&iio_dev_attr_scan.dev_attr.attr,
-	&iio_dev_attr_name.dev_attr.attr,
-	NULL,
-};
-
-static const struct attribute_group max1363_attribute_group = {
-	.attrs = max1363_attributes,
-};
-
 static int __devinit max1363_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
@@ -506,6 +620,7 @@ static int __devinit max1363_probe(struct i2c_client *client,
 		ret = -ENODEV;
 		goto error_free_st;
 	}
+
 	st->reg = regulator_get(&client->dev, "vcc");
 	if (!IS_ERR(st->reg)) {
 		ret = regulator_enable(st->reg);
@@ -520,20 +635,36 @@ static int __devinit max1363_probe(struct i2c_client *client,
 		goto error_disable_reg;
 	}
 
+	st->indio_dev->available_scan_masks
+		= kzalloc(GFP_KERNEL,
+			sizeof(*st->indio_dev->available_scan_masks)*
+			(st->chip_info->num_modes + 1));
+	if (!st->indio_dev->available_scan_masks) {
+		ret = -ENOMEM;
+		goto error_free_device;
+	}
+
+	for (i = 0; i < st->chip_info->num_modes; i++)
+		st->indio_dev->available_scan_masks[i] =
+			max1363_mode_table[st->chip_info->mode_list[i]]
+			.modemask;
 	/* Estabilish that the iio_dev is a child of the i2c device */
 	st->indio_dev->dev.parent = &client->dev;
-	st->indio_dev->attrs = &max1363_attribute_group;
+	st->indio_dev->attrs = st->chip_info->dev_attrs;
+
+	/* Todo: this shouldn't be here. */
+	st->indio_dev->scan_el_attrs = st->chip_info->scan_attrs;
 	st->indio_dev->dev_data = (void *)(st);
 	st->indio_dev->driver_module = THIS_MODULE;
 	st->indio_dev->modes = INDIO_DIRECT_MODE;
 
 	ret = max1363_initial_setup(st);
 	if (ret)
-		goto error_free_device;
+		goto error_free_available_scan_masks;
 
 	ret = max1363_register_ring_funcs_and_init(st->indio_dev);
 	if (ret)
-		goto error_free_device;
+		goto error_free_available_scan_masks;
 
 	ret = iio_device_register(st->indio_dev);
 	if (ret)
@@ -545,6 +676,8 @@ static int __devinit max1363_probe(struct i2c_client *client,
 	return 0;
 error_cleanup_ring:
 	max1363_ring_cleanup(st->indio_dev);
+error_free_available_scan_masks:
+	kfree(st->indio_dev->available_scan_masks);
 error_free_device:
 	if (!regdone)
 		iio_free_device(st->indio_dev);
@@ -569,6 +702,7 @@ static int max1363_remove(struct i2c_client *client)
 	struct iio_dev *indio_dev = st->indio_dev;
 	max1363_uninitialize_ring(indio_dev->ring);
 	max1363_ring_cleanup(indio_dev);
+	kfree(st->indio_dev->available_scan_masks);
 	iio_device_unregister(indio_dev);
 	if (!IS_ERR(st->reg)) {
 		regulator_disable(st->reg);
diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c
index f94fe2d..6003f7e 100644
--- a/drivers/staging/iio/adc/max1363_ring.c
+++ b/drivers/staging/iio/adc/max1363_ring.c
@@ -17,6 +17,7 @@
 #include <linux/sysfs.h>
 #include <linux/list.h>
 #include <linux/i2c.h>
+#include <linux/bitops.h>
 
 #include "../iio.h"
 #include "../ring_generic.h"
@@ -26,32 +27,36 @@
 
 #include "max1363.h"
 
-ssize_t max1363_scan_from_ring(struct device *dev,
-			       struct device_attribute *attr,
-			       char *buf)
+/* Todo: test this */
+int max1363_single_channel_from_ring(long mask, struct max1363_state *st)
 {
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct max1363_state *info = dev_info->dev_data;
-	int i, ret, len = 0;
-	char *ring_data;
+	unsigned long numvals;
+	int count = 0, ret;
+	u8 *ring_data;
+	if (!(st->current_mode->modemask & mask)) {
+		ret = -EBUSY;
+		goto error_ret;
+	}
+	numvals = hweight_long(st->current_mode->modemask);
 
-	ring_data = kmalloc(info->current_mode->numvals*2, GFP_KERNEL);
+	ring_data = kmalloc(numvals*2, GFP_KERNEL);
 	if (ring_data == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
-	ret = dev_info->ring->access.read_last(dev_info->ring, ring_data);
+	ret = st->indio_dev->ring->access.read_last(st->indio_dev->ring,
+						ring_data);
 	if (ret)
 		goto error_free_ring_data;
-	len += sprintf(buf+len, "ring ");
-	for (i = 0; i < info->current_mode->numvals; i++)
-		len += sprintf(buf + len, "%d ",
-			       ((int)(ring_data[i*2 + 0] & 0x0F) << 8)
-			       + ((int)(ring_data[i*2 + 1])));
-	len += sprintf(buf + len, "\n");
-	kfree(ring_data);
-
-	return len;
+	/* Need a count of channels prior to this one */
+	mask >>= 1;
+	while (mask) {
+		if (mask && st->current_mode->modemask)
+			count++;
+		mask >>= 1;
+	}
+	return ((int)(ring_data[count*2 + 0] & 0x0F) << 8)
+		+ (int)(ring_data[count*2 + 1]);
 
 error_free_ring_data:
 	kfree(ring_data);
@@ -70,9 +75,22 @@ static int max1363_ring_preenable(struct iio_dev *indio_dev)
 {
 	struct max1363_state *st = indio_dev->dev_data;
 	size_t d_size;
+	unsigned long numvals;
+
+	/*
+	 * Need to figure out the current mode based upon the requested
+	 * scan mask in iio_dev
+	 */
+	st->current_mode = max1363_match_mode(st->indio_dev->scan_mask,
+					st->chip_info);
+	if (!st->current_mode)
+		return -EINVAL;
+
+	max1363_set_scan_mode(st);
 
+	numvals = hweight_long(st->current_mode->modemask);
 	if (indio_dev->ring->access.set_bpd) {
-		d_size = st->current_mode->numvals*2 + sizeof(s64);
+		d_size = numvals*2 + sizeof(s64);
 		if (d_size % 8)
 			d_size += 8 - (d_size % 8);
 		indio_dev->ring->access.set_bpd(indio_dev->ring, d_size);
@@ -145,9 +163,10 @@ static void max1363_poll_bh_to_ring(struct work_struct *work_s)
 	__u8 *rxbuf;
 	int b_sent;
 	size_t d_size;
+	unsigned long numvals = hweight_long(st->current_mode->modemask);
 
 	/* Ensure the timestamp is 8 byte aligned */
-	d_size = st->current_mode->numvals*2 + sizeof(s64);
+	d_size = numvals*2 + sizeof(s64);
 	if (d_size % sizeof(s64))
 		d_size += sizeof(s64) - (d_size % sizeof(s64));
 
@@ -159,16 +178,14 @@ static void max1363_poll_bh_to_ring(struct work_struct *work_s)
 	 * might as well have this test in here in the meantime as it does
 	 * no harm.
 	 */
-	if (st->current_mode->numvals == 0)
+	if (numvals == 0)
 		return;
 
 	rxbuf = kmalloc(d_size,	GFP_KERNEL);
 	if (rxbuf == NULL)
 		return;
 
-	b_sent = i2c_master_recv(st->client,
-				 rxbuf,
-				 st->current_mode->numvals*2);
+	b_sent = i2c_master_recv(st->client, rxbuf, numvals*2);
 	if (b_sent < 0)
 		goto done;
 
-- 
1.6.4.4

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

* [PATCH 09/20] staging:iio: Documentation, update iio_utils.h for the move to a bus
  2010-05-04 13:43               ` [PATCH 08/20] staging:iio:max1363 move to new abi Jonathan Cameron
@ 2010-05-04 13:43                 ` Jonathan Cameron
  2010-05-04 13:43                   ` [PATCH 10/20] staging:iio: ABI documentation (partial) Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:43 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/Documentation/iio_utils.h |   31 ++++++++++++++++++++++++-
 1 files changed, 30 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h
index 74d3124..d24006a 100644
--- a/drivers/staging/iio/Documentation/iio_utils.h
+++ b/drivers/staging/iio/Documentation/iio_utils.h
@@ -47,7 +47,7 @@ inline char *find_ring_subelement(const char *directory, const char *subelement)
 
 char *find_type_by_name(const char *name, const char *type)
 {
-	const char *iio_dir = "/sys/class/iio/";
+	const char *iio_dir = "/sys/bus/iio/devices/";
 	const struct dirent *ent;
 	int cnt, pos, pos2;
 
@@ -112,6 +112,35 @@ int write_sysfs_int(char *filename, char *basedir, int val)
 	return 0;
 }
 
+int write_sysfs_int_and_verify(char *filename, char *basedir, int val)
+{
+	int ret;
+	FILE  *sysfsfp;
+	char temp[100];
+	int test;
+
+	sprintf(temp, "%s%s", basedir, filename);
+	sysfsfp = fopen(temp, "w");
+	if (sysfsfp == NULL)
+		return -1;
+	fprintf(sysfsfp, "%d", val);
+	fclose(sysfsfp);
+
+	sysfsfp = fopen(temp, "r");
+	if (sysfsfp == NULL)
+		return -1;
+	fscanf(sysfsfp, "%d", &test);
+	if (test != val) {
+		printf("Possible failure in int write %d to %s%s\n",
+		       val,
+		       basedir,
+		       filename);
+		return -1;
+	}
+
+	return 0;
+}
+
 /**
  * write_sysfs_string_and_verify() - string write, readback and verify
  * @filename: name of file to write to
-- 
1.6.4.4


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

* [PATCH 10/20] staging:iio: ABI documentation (partial)
  2010-05-04 13:43                 ` [PATCH 09/20] staging:iio: Documentation, update iio_utils.h for the move to a bus Jonathan Cameron
@ 2010-05-04 13:43                   ` Jonathan Cameron
  2010-05-04 13:43                     ` [PATCH 11/20] staging:iio: Directory name changes to match new ABI Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:43 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/Documentation/sysfs-class-iio |  285 +++++++++++++++++++++
 1 files changed, 285 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/iio/Documentation/sysfs-class-iio b/drivers/staging/iio/Documentation/sysfs-class-iio
new file mode 100644
index 0000000..7238582
--- /dev/null
+++ b/drivers/staging/iio/Documentation/sysfs-class-iio
@@ -0,0 +1,285 @@
+
+What:		/sys/bus/iio/devices/device[n]
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Hardware chip or device accessed by on communication port.
+		Corresponds to a grouping of sensor channels.
+
+What:		/sys/bus/iio/devices/trigger[n]
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		An event driven driver of data capture to an in kernel buffer.
+		May be provided by a device driver that also has an IIO device
+		based on hardware generated events (e.g. data ready) or
+		provided by a separate driver for other hardware (e.g.
+		periodic timer, gpio or high resolution timer).
+		Contains trigger type specific elements. These do not
+		generalize well and hence are not documented in this file.
+
+What:		/sys/bus/iio/devices/device[n]:buffer
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+	        Link to /sys/class/iio/device[n]/device[n]:buffer. n indicates the
+		device with which this buffer buffer is associated.
+
+What:		/sys/.../device[n]/name
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Description of the physical chip / device. Typically a part
+		number.
+
+What:		/sys/.../device[n]/sampling_frequency
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Some devices have internal clocks.  This parameter sets the
+		resulting sampling frequency.  In many devices this
+		parameter has an effect on input filters etc rather than
+		simply controlling when the input is sampled.  As this
+		effects datardy triggers, hardware buffers and the sysfs
+		direct access interfaces, it may be found in any of the
+		relevant directories.  If it effects all of the above
+		then it is to be found in the base device directory as here.
+
+What:		/sys/.../device[n]/sampling_frequency_available
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		When the internal sampling clock can only take a small
+		discrete set of values, this file lists those availale.
+
+What:		/sys/.../device[n]/in[_name][m]_raw
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Raw (unscaled no bias removal etc) voltage measurement from
+		channel m. name is used in special cases where this does
+		not correspond to externally available input (e.g. supply
+		voltage monitoring in which case the file is in_supply_raw).
+
+What:		/sys/.../device[n]/in[_name][m]_offset
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		If known for a device, offset to be added to in[m]_raw prior
+		to scaling by volt[m]_scale in order to obtain voltage in
+		millivolts.  Not present if the offset is always 0 or unknown.
+		If m is not present, then voltage offset applies to all in
+		channels. May be writable if a variable offset is controlled
+		by the device. Note that this is different to calibbias which
+		is for devices that apply offsets to compensate for variation
+		between different instances of the part, typically adjusted by
+		using some hardware supported calibration procedure.
+
+What:		/sys/.../device[n]/in[_name][m]_offset_available
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		If a small number of discrete offset values are available, this
+		will be a space separated list.  If these are independant (but
+		options the same) for individual offsets then m should not be
+		present.
+
+What:		/sys/.../device[n]/in[_name][m]_offset_[min|max]
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		If a more or less continuous range of voltage offsets are supported
+		then these specify the minimum and maximum.  If shared by all
+		in channels then m is not present.
+
+What:		/sys/.../device[n]/in[_name][m]_calibbias
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Hardware applied calibration offset. (assumed to fix production
+		inaccuracies)
+
+What		/sys/.../device[n]/in[_name][m]_calibscale
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Hardware applied calibration scale factor. (assumed to fix production
+		inaccuracies)
+
+What:		/sys/.../device[n]/in[_name][m]_scale
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		If known for a device, scale to be applied to volt[m]_raw post
+		addition of volt[m]_offset in order to obtain the measured voltage
+		in millivolts.  If shared across all in channels then m is not present.
+
+What:		/sys/.../device[n]/in[m]-in[o]_raw
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Raw (unscaled) differential voltage measurement equivalent to
+		channel m - channel o where these channel numbers apply to the physically
+		equivalent inputs when non differential readings are separately available.
+		In differential only parts, then all that is required is a consistent
+		labelling.
+
+What:		/sys/.../device[n]/accel[_x|_y|_z][m]_raw
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Acceleration in direction x, y or z (may be arbitrarily assigned
+		but should match other such assignments on device)
+		channel m (not present if only one accelerometer channel at
+		this orientation). Has all of the equivalent parameters as per in[m].
+		Units after application of scale and offset are m/s^2.
+
+What:		/sys/.../device[n]/gyro[_x|_y|_z][m]_raw
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Angular velocity about axis x, y or z (may be arbitrarily assigned)
+		channel m (not present if only one gyroscope at this orientation).
+		Data converted by application of offset then scale to
+		radians per second. Has all the equivalent parameters as per in[m].
+
+What:		/sys/.../device[n]/mag[_x|_y|_z][m]_raw
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Magnetic field along axis x, y or z (may be arbitrarily assigned)
+		channel m (not present if only one magnetometer at this orientation).
+		Data converted by application of offset then scale to Gauss
+		Has all the equivalent modifiers as per in[m].
+
+What:		/sys/.../device[n]/device[n]:event[m]
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Configuration of which hardware generated events are passed up to
+		userspace. Some of these are a bit complex to generalize so this
+		section is a work in progress.
+
+What:		/sys/.../device[n]:event[m]/dev
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		major:minor character device numbers for the event line.
+
+Taking accel_x0 as an example
+
+What:		/sys/.../device[n]:event[m]/accel_x0_thresh[_high|_low]_en
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Event generated when accel_x0 passes a threshold in correction direction
+		(or stays beyond one). If direction isn't specified, either triggers it.
+		Note driver will assume last p events requested are enabled where p is
+		however many it supports.  So if you want to be sure you have
+		set what you think you have, check the contents of these. Drivers
+		may have to buffer any parameters so that they are consistent when a
+		given event type is enabled a future point (and not those for whatever
+		alarm was previously enabled).
+
+What:		/sys/.../device[n]:event[m]/accel_x0_roc[_high|_low]_en
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Same as above but based on the first differential of the value.
+
+
+What:		/sys/.../device[n]:event[m]/accel_x0[_thresh|_roc][_high|_low]_period
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		A period of time (microsecs) for which the condition must be broken
+		before an interrupt is triggered. Applies to all alarms if type is not
+		specified.
+
+What:		/sys/.../device[n]:event[m]/accel_x0[_thresh|_roc][_high|_low]_value
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		The actual value of the threshold in raw device units obtained by
+		 reverse application of scale and offfset to the acceleration in m/s^2.
+
+What:		/sys/.../device[n]/scan_elements
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Directory containing interfaces for elements that will be captured
+		for a single triggered sample set in the buffer.
+
+What:		/sys/.../device[n]/scan_elements/[m]_accel_x0_en
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Scan element control for triggered data capture. m implies the
+		ordering within the buffer. Next the type is specified with
+		modifier and channel number as per the sysfs single channel
+		access above.
+
+What:		/sys/.../device[n]/scan_elements/accel[_x0]_precision
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Scan element precision within the buffer. Note that the
+		data alignment must restrictions must be read from within
+		buffer to work out full data alignment for data read
+		via buffer_access chrdev. _x0 dropped if shared across all
+		acceleration channels.
+
+What:		/sys/.../device[n]/scan_elements/accel[_x0]_shift
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		A bit shift (to right) that must be applied prior to
+		extracting the bits specified by accel[_x0]_precision.
+
+What:		/sys/.../device[n]/device[n]:buffer:event/dev
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Buffer for device n event character device major:minor numbers.
+
+What:		/sys/.../device[n]/device[n]:buffer:access/dev
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Buffer for device n access character device o major:minor numbers.
+
+What:		/sys/.../device[n]:buffer/trigger
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		The name of the trigger source being used, as per string given
+		in /sys/class/iio/trigger[n]/name.
+
+What:		/sys/.../device[n]:buffer/length
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Number of scans contained by the buffer.
+
+What:		/sys/.../device[n]:buffer/bps
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Bytes per scan.  Due to alignment fun, the scan may be larger
+		than implied directly by the scan_element parameters.
+
+What:		/sys/.../device[n]:buffer/enable
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Actually start the buffer capture up.  Will start trigger
+		if first device and appropriate.
+
+What:		/sys/.../device[n]:buffer/alignment
+KernelVersion:	2.6.35
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Minimum data alignment.  Scan elements larger than this are aligned
+		to the nearest power of 2 times this.  (may not be true in weird
+		hardware buffers that pack data well)
+
-- 
1.6.4.4


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

* [PATCH 11/20] staging:iio: Directory name changes to match new ABI.
  2010-05-04 13:43                   ` [PATCH 10/20] staging:iio: ABI documentation (partial) Jonathan Cameron
@ 2010-05-04 13:43                     ` Jonathan Cameron
  2010-05-04 13:43                       ` [PATCH 12/20] staging:iio:tsl2563: change lux to illuminance0_input to match new abi Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:43 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/chrdev.h            |    2 +-
 drivers/staging/iio/industrialio-core.c |    5 +++--
 drivers/staging/iio/industrialio-ring.c |   13 +++++++++----
 3 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/iio/chrdev.h b/drivers/staging/iio/chrdev.h
index f42bafb..3f96f86 100644
--- a/drivers/staging/iio/chrdev.h
+++ b/drivers/staging/iio/chrdev.h
@@ -94,7 +94,7 @@ struct iio_event_interface {
 	struct iio_chrdev_minor_attr		attr;
 	struct module				*owner;
 	void					*private;
-	char					_name[20];
+	char					_name[35];
 	char					_attrname[20];
 };
 
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index a4ce221..c55d0f3 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -660,8 +660,9 @@ static int iio_device_register_eventset(struct iio_dev *dev_info)
 			dev_info->event_interfaces[i].id = ret;
 
 		snprintf(dev_info->event_interfaces[i]._name, 20,
-			 "event_line%d",
-			dev_info->event_interfaces[i].id);
+			 "%s:event%d",
+			 dev_name(&dev_info->dev),
+			 dev_info->event_interfaces[i].id);
 
 		ret = iio_setup_ev_int(&dev_info->event_interfaces[i],
 				       (const char *)(dev_info
diff --git a/drivers/staging/iio/industrialio-ring.c b/drivers/staging/iio/industrialio-ring.c
index 690df91..0f19bd1 100644
--- a/drivers/staging/iio/industrialio-ring.c
+++ b/drivers/staging/iio/industrialio-ring.c
@@ -164,8 +164,9 @@ __iio_request_ring_buffer_event_chrdev(struct iio_ring_buffer *buf,
 	else
 		buf->ev_int.id = ret;
 
-	snprintf(buf->ev_int._name, 20,
-		 "ring_event_line%d",
+	snprintf(buf->ev_int._name, sizeof(buf->ev_int._name),
+		 "%s:event%d",
+		 dev_name(&buf->dev),
 		 buf->ev_int.id);
 	ret = iio_setup_ev_int(&(buf->ev_int),
 			       buf->ev_int._name,
@@ -226,7 +227,9 @@ __iio_request_ring_buffer_access_chrdev(struct iio_ring_buffer *buf,
 		goto error_device_put;
 	else
 		buf->access_id = ret;
-	dev_set_name(&buf->access_dev, "ring_access%d", buf->access_id);
+	dev_set_name(&buf->access_dev, "%s:access%d",
+		     dev_name(&buf->dev),
+		     buf->access_id);
 	ret = device_add(&buf->access_dev);
 	if (ret < 0) {
 		printk(KERN_ERR "failed to add the ring access dev\n");
@@ -280,7 +283,9 @@ int iio_ring_buffer_register(struct iio_ring_buffer *ring)
 	else
 		ring->id = ret;
 
-	dev_set_name(&ring->dev, "ring_buffer%d", ring->id);
+	dev_set_name(&ring->dev, "%s:buffer%d",
+		     dev_name(ring->dev.parent),
+		     ring->id);
 	ret = device_add(&ring->dev);
 	if (ret)
 		goto error_free_id;
-- 
1.6.4.4

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

* [PATCH 12/20] staging:iio:tsl2563: change lux to illuminance0_input to match new abi
  2010-05-04 13:43                     ` [PATCH 11/20] staging:iio: Directory name changes to match new ABI Jonathan Cameron
@ 2010-05-04 13:43                       ` Jonathan Cameron
  2010-05-04 13:43                         ` [PATCH 13/20] staging:iio: Remove naming via IDR's where no longer necessary under " Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:43 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/light/tsl2563.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c
index 1ba4aa3..911c898 100644
--- a/drivers/staging/iio/light/tsl2563.c
+++ b/drivers/staging/iio/light/tsl2563.c
@@ -592,7 +592,7 @@ static ssize_t tsl2563_calib1_store(struct device *dev,
  * once I understand what they mean */
 static DEVICE_ATTR(adc0, S_IRUGO, tsl2563_adc0_show, NULL);
 static DEVICE_ATTR(adc1, S_IRUGO, tsl2563_adc1_show, NULL);
-static DEVICE_ATTR(lux, S_IRUGO, tsl2563_lux_show, NULL);
+static DEVICE_ATTR(illuminance0_input, S_IRUGO, tsl2563_lux_show, NULL);
 static DEVICE_ATTR(calib0, S_IRUGO | S_IWUSR,
 		   tsl2563_calib0_show, tsl2563_calib0_store);
 static DEVICE_ATTR(calib1, S_IRUGO | S_IWUSR,
@@ -601,7 +601,7 @@ static DEVICE_ATTR(calib1, S_IRUGO | S_IWUSR,
 static struct attribute *tsl2563_attributes[] = {
 	&dev_attr_adc0.attr,
 	&dev_attr_adc1.attr,
-	&dev_attr_lux.attr,
+	&dev_attr_illuminance0_input.attr,
 	&dev_attr_calib0.attr,
 	&dev_attr_calib1.attr,
 	NULL
-- 
1.6.4.4


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

* [PATCH 13/20] staging:iio: Remove naming via IDR's where no longer necessary under new abi.
  2010-05-04 13:43                       ` [PATCH 12/20] staging:iio:tsl2563: change lux to illuminance0_input to match new abi Jonathan Cameron
@ 2010-05-04 13:43                         ` Jonathan Cameron
  2010-05-04 13:43                           ` [PATCH 14/20] staging:iio:max1363 add support for max11606-max11617 Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:43 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/accel/lis3l02dq_ring.c |    2 +-
 drivers/staging/iio/accel/sca3000_core.c   |    2 +-
 drivers/staging/iio/adc/max1363_ring.c     |    2 +-
 drivers/staging/iio/industrialio-ring.c    |   48 +++++++---------------------
 drivers/staging/iio/ring_generic.h         |    2 +-
 5 files changed, 16 insertions(+), 40 deletions(-)

diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c
index bba4b09..7617da8 100644
--- a/drivers/staging/iio/accel/lis3l02dq_ring.c
+++ b/drivers/staging/iio/accel/lis3l02dq_ring.c
@@ -581,7 +581,7 @@ error_iio_sw_rb_free:
 
 int lis3l02dq_initialize_ring(struct iio_ring_buffer *ring)
 {
-	return iio_ring_buffer_register(ring);
+	return iio_ring_buffer_register(ring, 0);
 }
 
 void lis3l02dq_uninitialize_ring(struct iio_ring_buffer *ring)
diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
index 45e4777..9485b13 100644
--- a/drivers/staging/iio/accel/sca3000_core.c
+++ b/drivers/staging/iio/accel/sca3000_core.c
@@ -1338,7 +1338,7 @@ static int __devinit __sca3000_probe(struct spi_device *spi,
 	if (ret < 0)
 		goto error_free_dev;
 	regdone = 1;
-	ret = iio_ring_buffer_register(st->indio_dev->ring);
+	ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
 	if (ret < 0)
 		goto error_unregister_dev;
 	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) {
diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c
index 6003f7e..f1e37f2 100644
--- a/drivers/staging/iio/adc/max1363_ring.c
+++ b/drivers/staging/iio/adc/max1363_ring.c
@@ -255,5 +255,5 @@ void max1363_uninitialize_ring(struct iio_ring_buffer *ring)
 
 int max1363_initialize_ring(struct iio_ring_buffer *ring)
 {
-	return iio_ring_buffer_register(ring);
+	return iio_ring_buffer_register(ring, 0);
 };
diff --git a/drivers/staging/iio/industrialio-ring.c b/drivers/staging/iio/industrialio-ring.c
index 0f19bd1..fc27d22 100644
--- a/drivers/staging/iio/industrialio-ring.c
+++ b/drivers/staging/iio/industrialio-ring.c
@@ -20,19 +20,11 @@
 #include <linux/poll.h>
 #include <linux/module.h>
 #include <linux/cdev.h>
-#include <linux/idr.h>
 #include <linux/slab.h>
 
 #include "iio.h"
 #include "ring_generic.h"
 
-/* IDR for ring buffer identifier */
-static DEFINE_IDR(iio_ring_idr);
-/* IDR for ring event identifier */
-static DEFINE_IDR(iio_ring_event_idr);
-/* IDR for ring access identifier */
-static DEFINE_IDR(iio_ring_access_idr);
-
 int iio_push_ring_event(struct iio_ring_buffer *ring_buf,
 		       int event_code,
 		       s64 timestamp)
@@ -158,11 +150,8 @@ __iio_request_ring_buffer_event_chrdev(struct iio_ring_buffer *buf,
 				       struct device *dev)
 {
 	int ret;
-	ret = iio_get_new_idr_val(&iio_ring_event_idr);
-	if (ret < 0)
-		goto error_ret;
-	else
-		buf->ev_int.id = ret;
+
+	buf->ev_int.id = id;
 
 	snprintf(buf->ev_int._name, sizeof(buf->ev_int._name),
 		 "%s:event%d",
@@ -173,11 +162,9 @@ __iio_request_ring_buffer_event_chrdev(struct iio_ring_buffer *buf,
 			       owner,
 			       dev);
 	if (ret)
-		goto error_free_id;
+		goto error_ret;
 	return 0;
 
-error_free_id:
-	iio_free_idr_val(&iio_ring_event_idr, buf->ev_int.id);
 error_ret:
 	return ret;
 }
@@ -186,7 +173,6 @@ static inline void
 __iio_free_ring_buffer_event_chrdev(struct iio_ring_buffer *buf)
 {
 	iio_free_ev_int(&(buf->ev_int));
-	iio_free_idr_val(&iio_ring_event_idr, buf->ev_int.id);
 }
 
 static void iio_ring_access_release(struct device *dev)
@@ -222,18 +208,16 @@ __iio_request_ring_buffer_access_chrdev(struct iio_ring_buffer *buf,
 	}
 	buf->access_dev.devt = MKDEV(MAJOR(iio_devt), minor);
 
-	ret = iio_get_new_idr_val(&iio_ring_access_idr);
-	if (ret < 0)
-		goto error_device_put;
-	else
-		buf->access_id = ret;
+
+	buf->access_id = id;
+
 	dev_set_name(&buf->access_dev, "%s:access%d",
 		     dev_name(&buf->dev),
 		     buf->access_id);
 	ret = device_add(&buf->access_dev);
 	if (ret < 0) {
 		printk(KERN_ERR "failed to add the ring access dev\n");
-		goto error_free_idr;
+		goto error_device_put;
 	}
 
 	cdev_init(&buf->access_handler.chrdev, &iio_ring_fileops);
@@ -245,10 +229,9 @@ __iio_request_ring_buffer_access_chrdev(struct iio_ring_buffer *buf,
 		goto error_device_unregister;
 	}
 	return 0;
+
 error_device_unregister:
 	device_unregister(&buf->access_dev);
-error_free_idr:
-	iio_free_idr_val(&iio_ring_access_idr, buf->access_id);
 error_device_put:
 	put_device(&buf->access_dev);
 
@@ -257,7 +240,6 @@ error_device_put:
 
 static void __iio_free_ring_buffer_access_chrdev(struct iio_ring_buffer *buf)
 {
-	iio_free_idr_val(&iio_ring_access_idr, buf->access_id);
 	device_unregister(&buf->access_dev);
 }
 
@@ -274,21 +256,18 @@ void iio_ring_buffer_init(struct iio_ring_buffer *ring,
 }
 EXPORT_SYMBOL(iio_ring_buffer_init);
 
-int iio_ring_buffer_register(struct iio_ring_buffer *ring)
+int iio_ring_buffer_register(struct iio_ring_buffer *ring, int id)
 {
 	int ret;
-	ret = iio_get_new_idr_val(&iio_ring_idr);
-	if (ret < 0)
-		goto error_ret;
-	else
-		ring->id = ret;
+
+	ring->id = id;
 
 	dev_set_name(&ring->dev, "%s:buffer%d",
 		     dev_name(ring->dev.parent),
 		     ring->id);
 	ret = device_add(&ring->dev);
 	if (ret)
-		goto error_free_id;
+		goto error_ret;
 
 	ret = __iio_request_ring_buffer_event_chrdev(ring,
 						     0,
@@ -309,8 +288,6 @@ error_free_ring_buffer_event_chrdev:
 	__iio_free_ring_buffer_event_chrdev(ring);
 error_remove_device:
 	device_del(&ring->dev);
-error_free_id:
-	iio_free_idr_val(&iio_ring_idr, ring->id);
 error_ret:
 	return ret;
 }
@@ -321,7 +298,6 @@ void iio_ring_buffer_unregister(struct iio_ring_buffer *ring)
 	__iio_free_ring_buffer_access_chrdev(ring);
 	__iio_free_ring_buffer_event_chrdev(ring);
 	device_del(&ring->dev);
-	iio_free_idr_val(&iio_ring_idr, ring->id);
 }
 EXPORT_SYMBOL(iio_ring_buffer_unregister);
 
diff --git a/drivers/staging/iio/ring_generic.h b/drivers/staging/iio/ring_generic.h
index d74b5ae..0e44375 100644
--- a/drivers/staging/iio/ring_generic.h
+++ b/drivers/staging/iio/ring_generic.h
@@ -259,7 +259,7 @@ static inline void iio_put_ring_buffer(struct iio_ring_buffer *ring)
 	container_of(d, struct iio_ring_buffer, dev)
 #define access_dev_to_iio_ring_buffer(d)			\
 	container_of(d, struct iio_ring_buffer, access_dev)
-int iio_ring_buffer_register(struct iio_ring_buffer *ring);
+int iio_ring_buffer_register(struct iio_ring_buffer *ring, int id);
 void iio_ring_buffer_unregister(struct iio_ring_buffer *ring);
 
 ssize_t iio_read_ring_length(struct device *dev,
-- 
1.6.4.4

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

* [PATCH 14/20] staging:iio:max1363 add support for max11606-max11617
  2010-05-04 13:43                         ` [PATCH 13/20] staging:iio: Remove naming via IDR's where no longer necessary under " Jonathan Cameron
@ 2010-05-04 13:43                           ` Jonathan Cameron
  2010-05-04 13:43                             ` [PATCH 15/20] staging:iio:max1363 add support for 8 bit equivalent devices, max1036-9, max11600-5 Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:43 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/adc/Kconfig        |    4 +-
 drivers/staging/iio/adc/max1363_core.c |  216 +++++++++++++++++++++++++++++++-
 2 files changed, 218 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index 101ea4b..afc8318 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -12,7 +12,9 @@ config MAX1363
 	  Say yes here to build support for many MAXIM i2c analog to digital
 	  convertors (ADC). (max1361, max1362, max1363, max1364, max1136,
 	  max1136, max1137, max1138, max1139, max1236, max1237, max11238,
-	  max1239) Provides direct access via sysfs.
+	  max1239, max11606, max11607, max11608, max11609, max11610,
+	  max11611, max11612, max11613, max11614, max11615, max11616,
+	  max11617) Provides direct access via sysfs.
 
 config MAX1363_RING_BUFFER
 	bool "MAXIM max1363: use ring buffer"
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c
index e82f3e7..c53bf6d 100644
--- a/drivers/staging/iio/adc/max1363_core.c
+++ b/drivers/staging/iio/adc/max1363_core.c
@@ -434,6 +434,76 @@ static struct attribute_group max1238_scan_el_group = {
 	.attrs = max1238_scan_el_attrs,
 };
 
+
+static const enum max1363_modes max11607_mode_list[] = {
+	_s0, _s1, _s2, _s3,
+	s0to1, s0to2, s0to3,
+	s2to3,
+	d0m1, d2m3, d1m0, d3m2,
+	d0m1to2m3, d1m0to3m2,
+};
+
+static const enum max1363_modes max11608_mode_list[] = {
+	_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7,
+	s0to1, s0to2, s0to3, s0to4, s0to5, s0to6, s0to7,
+	s6to7,
+	d0m1, d2m3, d4m5, d6m7,
+	d1m0, d3m2, d5m4, d7m6,
+	d0m1to2m3, d0m1to4m5, d0m1to6m7,
+	d1m0to3m2, d1m0to5m4, d1m0to7m6,
+};
+
+static struct attribute *max11608_device_attrs[] = {
+	&iio_dev_attr_in0_raw.dev_attr.attr,
+	&iio_dev_attr_in1_raw.dev_attr.attr,
+	&iio_dev_attr_in2_raw.dev_attr.attr,
+	&iio_dev_attr_in3_raw.dev_attr.attr,
+	&iio_dev_attr_in4_raw.dev_attr.attr,
+	&iio_dev_attr_in5_raw.dev_attr.attr,
+	&iio_dev_attr_in6_raw.dev_attr.attr,
+	&iio_dev_attr_in7_raw.dev_attr.attr,
+	&iio_dev_attr_in0min1_raw.dev_attr.attr,
+	&iio_dev_attr_in2min3_raw.dev_attr.attr,
+	&iio_dev_attr_in4min5_raw.dev_attr.attr,
+	&iio_dev_attr_in6min7_raw.dev_attr.attr,
+	&iio_dev_attr_in1min0_raw.dev_attr.attr,
+	&iio_dev_attr_in3min2_raw.dev_attr.attr,
+	&iio_dev_attr_in5min4_raw.dev_attr.attr,
+	&iio_dev_attr_in7min6_raw.dev_attr.attr,
+	&iio_dev_attr_name.dev_attr.attr,
+	&iio_dev_attr_in_scale.dev_attr.attr,
+	NULL
+};
+
+static struct attribute_group max11608_dev_attr_group = {
+	.attrs = max11608_device_attrs,
+};
+
+static struct attribute *max11608_scan_el_attrs[] = {
+	&iio_scan_el_in0.dev_attr.attr,
+	&iio_scan_el_in1.dev_attr.attr,
+	&iio_scan_el_in2.dev_attr.attr,
+	&iio_scan_el_in3.dev_attr.attr,
+	&iio_scan_el_in4.dev_attr.attr,
+	&iio_scan_el_in5.dev_attr.attr,
+	&iio_scan_el_in6.dev_attr.attr,
+	&iio_scan_el_in7.dev_attr.attr,
+	&iio_scan_el_in0min1.dev_attr.attr,
+	&iio_scan_el_in2min3.dev_attr.attr,
+	&iio_scan_el_in4min5.dev_attr.attr,
+	&iio_scan_el_in6min7.dev_attr.attr,
+	&iio_scan_el_in1min0.dev_attr.attr,
+	&iio_scan_el_in3min2.dev_attr.attr,
+	&iio_scan_el_in5min4.dev_attr.attr,
+	&iio_scan_el_in7min6.dev_attr.attr,
+	&iio_dev_attr_in_precision.dev_attr.attr,
+};
+
+static struct attribute_group max11608_scan_el_group = {
+	.name = "scan_elements",
+	.attrs = max11608_scan_el_attrs,
+};
+
 enum { max1361,
        max1362,
        max1363,
@@ -446,6 +516,18 @@ enum { max1361,
        max1237,
        max1238,
        max1239,
+       max11606,
+       max11607,
+       max11608,
+       max11609,
+       max11610,
+       max11611,
+       max11612,
+       max11613,
+       max11614,
+       max11615,
+       max11616,
+       max11617,
 };
 
 /* max1363 and max1368 tested - rest from data sheet */
@@ -574,7 +656,127 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
 		.default_mode = s0to11,
 		.dev_attrs = &max1238_dev_attr_group,
 		.scan_attrs = &max1238_scan_el_group,
-	},
+	}, {
+		.name = "max11606",
+		.num_inputs = 4,
+		.bits = 10,
+		.int_vref_mv = 4096,
+		.mode_list = max11607_mode_list,
+		.num_modes = ARRAY_SIZE(max11607_mode_list),
+		.default_mode = s0to3,
+		.dev_attrs = &max1363_dev_attr_group,
+		.scan_attrs = &max1363_scan_el_group,
+	}, {
+		.name = "max11607",
+		.num_inputs = 4,
+		.bits = 10,
+		.int_vref_mv = 2048,
+		.mode_list = max11607_mode_list,
+		.num_modes = ARRAY_SIZE(max11607_mode_list),
+		.default_mode = s0to3,
+		.dev_attrs = &max1363_dev_attr_group,
+		.scan_attrs = &max1363_scan_el_group,
+	}, {
+		.name = "max11608",
+		.num_inputs = 8,
+		.bits = 10,
+		.int_vref_mv = 4096,
+		.mode_list = max11608_mode_list,
+		.num_modes = ARRAY_SIZE(max11608_mode_list),
+		.default_mode = s0to7,
+		.dev_attrs = &max11608_dev_attr_group,
+		.scan_attrs = &max11608_scan_el_group,
+	}, {
+		.name = "max11609",
+		.num_inputs = 8,
+		.bits = 10,
+		.int_vref_mv = 2048,
+		.mode_list = max11608_mode_list,
+		.num_modes = ARRAY_SIZE(max11608_mode_list),
+		.default_mode = s0to7,
+		.dev_attrs = &max11608_dev_attr_group,
+		.scan_attrs = &max11608_scan_el_group,
+	}, {
+		.name = "max11610",
+		.num_inputs = 12,
+		.bits = 10,
+		.int_vref_mv = 4098,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.dev_attrs = &max1238_dev_attr_group,
+		.scan_attrs = &max1238_scan_el_group,
+	}, {
+		.name = "max11611",
+		.num_inputs = 12,
+		.bits = 10,
+		.int_vref_mv = 2048,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.dev_attrs = &max1238_dev_attr_group,
+		.scan_attrs = &max1238_scan_el_group,
+	}, {
+		.name = "max11612",
+		.num_inputs = 4,
+		.bits = 12,
+		.int_vref_mv = 4096,
+		.mode_list = max11607_mode_list,
+		.num_modes = ARRAY_SIZE(max11607_mode_list),
+		.default_mode = s0to3,
+		.dev_attrs = &max1363_dev_attr_group,
+		.scan_attrs = &max1363_scan_el_group,
+	}, {
+		.name = "max11613",
+		.num_inputs = 4,
+		.bits = 12,
+		.int_vref_mv = 2048,
+		.mode_list = max11607_mode_list,
+		.num_modes = ARRAY_SIZE(max11607_mode_list),
+		.default_mode = s0to3,
+		.dev_attrs = &max1363_dev_attr_group,
+		.scan_attrs = &max1363_scan_el_group,
+	}, {
+		.name = "max11614",
+		.num_inputs = 8,
+		.bits = 12,
+		.int_vref_mv = 4096,
+		.mode_list = max11608_mode_list,
+		.num_modes = ARRAY_SIZE(max11608_mode_list),
+		.default_mode = s0to7,
+		.dev_attrs = &max11608_dev_attr_group,
+		.scan_attrs = &max11608_scan_el_group,
+	}, {
+		.name = "max11615",
+		.num_inputs = 8,
+		.bits = 12,
+		.int_vref_mv = 2048,
+		.mode_list = max11608_mode_list,
+		.num_modes = ARRAY_SIZE(max11608_mode_list),
+		.default_mode = s0to7,
+		.dev_attrs = &max11608_dev_attr_group,
+		.scan_attrs = &max11608_scan_el_group,
+	}, {
+		.name = "max11616",
+		.num_inputs = 12,
+		.bits = 12,
+		.int_vref_mv = 4098,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.dev_attrs = &max1238_dev_attr_group,
+		.scan_attrs = &max1238_scan_el_group,
+	}, {
+		.name = "max11617",
+		.num_inputs = 12,
+		.bits = 12,
+		.int_vref_mv = 2048,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.dev_attrs = &max1238_dev_attr_group,
+		.scan_attrs = &max1238_scan_el_group,
+	}
 };
 
 static int max1363_initial_setup(struct max1363_state *st)
@@ -726,6 +928,18 @@ static const struct i2c_device_id max1363_id[] = {
 	{ "max1237", max1237 },
 	{ "max1238", max1238 },
 	{ "max1239", max1239 },
+	{ "max11606", max11606 },
+	{ "max11607", max11607 },
+	{ "max11608", max11608 },
+	{ "max11609", max11609 },
+	{ "max11610", max11610 },
+	{ "max11611", max11611 },
+	{ "max11612", max11612 },
+	{ "max11613", max11613 },
+	{ "max11614", max11614 },
+	{ "max11615", max11615 },
+	{ "max11616", max11616 },
+	{ "max11617", max11617 },
 	{}
 };
 
-- 
1.6.4.4

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

* [PATCH 15/20] staging:iio:max1363 add support for 8 bit equivalent devices, max1036-9, max11600-5
  2010-05-04 13:43                           ` [PATCH 14/20] staging:iio:max1363 add support for max11606-max11617 Jonathan Cameron
@ 2010-05-04 13:43                             ` Jonathan Cameron
  2010-05-04 13:43                               ` [PATCH 16/20] staging:iio:ring_sw: Fix incorrect test on successful read of last value, causes infinite loop Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:43 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/adc/Kconfig        |   12 ++-
 drivers/staging/iio/adc/max1363_core.c |  143 ++++++++++++++++++++++++++++++--
 drivers/staging/iio/adc/max1363_ring.c |   23 ++++--
 3 files changed, 161 insertions(+), 17 deletions(-)

diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index afc8318..0835fbc 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -10,11 +10,13 @@ config MAX1363
 	select MAX1363_RING_BUFFER
 	help
 	  Say yes here to build support for many MAXIM i2c analog to digital
-	  convertors (ADC). (max1361, max1362, max1363, max1364, max1136,
-	  max1136, max1137, max1138, max1139, max1236, max1237, max11238,
-	  max1239, max11606, max11607, max11608, max11609, max11610,
-	  max11611, max11612, max11613, max11614, max11615, max11616,
-	  max11617) Provides direct access via sysfs.
+	  convertors (ADC). (max1361, max1362, max1363, max1364, max1036,
+	  max1037, max1038, max1039, max1136, max1136, max1137, max1138,
+	  max1139, max1236, max1237, max11238, max1239, max11600, max11601,
+	  max11602, max11603, max11604, max11605, max11606, max11607,
+	  max11608, max11609, max11610, max11611, max11612, max11613,
+	  max11614, max11615, max11616, max11617) Provides direct access
+	  via sysfs.
 
 config MAX1363_RING_BUFFER
 	bool "MAXIM max1363: use ring buffer"
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c
index c53bf6d..fa91cc1 100644
--- a/drivers/staging/iio/adc/max1363_core.c
+++ b/drivers/staging/iio/adc/max1363_core.c
@@ -226,13 +226,24 @@ static ssize_t max1363_read_single_channel(struct device *dev,
 			if (ret)
 				goto error_ret;
 		}
-		/* Get reading */
-		data = i2c_master_recv(client, rxbuf, 2);
-		if (data < 0) {
-			ret = data;
-			goto error_ret;
+		if (st->chip_info->bits != 8) {
+			/* Get reading */
+			data = i2c_master_recv(client, rxbuf, 2);
+			if (data < 0) {
+				ret = data;
+				goto error_ret;
+			}
+
+			data = (s32)(rxbuf[1]) | ((s32)(rxbuf[0] & 0x0F)) << 8;
+		} else {
+			/* Get reading */
+			data = i2c_master_recv(client, rxbuf, 1);
+			if (data < 0) {
+				ret = data;
+				goto error_ret;
+			}
+			data = rxbuf[0];
 		}
-		data = (s32)(rxbuf[1]) | ((s32)(rxbuf[0] & 0x0F)) << 8;
 	}
 	/* Pretty print the result */
 	len = sprintf(buf, "%u\n", data);
@@ -508,6 +519,10 @@ enum { max1361,
        max1362,
        max1363,
        max1364,
+       max1036,
+       max1037,
+       max1038,
+       max1039,
        max1136,
        max1137,
        max1138,
@@ -516,6 +531,12 @@ enum { max1361,
        max1237,
        max1238,
        max1239,
+       max11600,
+       max11601,
+       max11602,
+       max11603,
+       max11604,
+       max11605,
        max11606,
        max11607,
        max11608,
@@ -577,6 +598,46 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
 		.dev_attrs = &max1363_dev_attr_group,
 		.scan_attrs = &max1363_scan_el_group,
 	}, {
+		.name = "max1036",
+		.num_inputs = 4,
+		.bits = 8,
+		.int_vref_mv = 4096,
+		.mode_list = max1236_mode_list,
+		.num_modes = ARRAY_SIZE(max1236_mode_list),
+		.default_mode = s0to3,
+		.dev_attrs = &max1363_dev_attr_group,
+		.scan_attrs = &max1363_scan_el_group,
+	}, {
+		.name = "max1037",
+		.num_inputs = 4,
+		.bits = 8,
+		.int_vref_mv = 2048,
+		.mode_list = max1236_mode_list,
+		.num_modes = ARRAY_SIZE(max1236_mode_list),
+		.default_mode = s0to3,
+		.dev_attrs = &max1363_dev_attr_group,
+		.scan_attrs = &max1363_scan_el_group,
+	}, {
+		.name = "max1038",
+		.num_inputs = 12,
+		.bits = 8,
+		.int_vref_mv = 4096,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.dev_attrs = &max1238_dev_attr_group,
+		.scan_attrs = &max1238_scan_el_group,
+	}, {
+		.name = "max1039",
+		.num_inputs = 12,
+		.bits = 8,
+		.int_vref_mv = 2048,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.dev_attrs = &max1238_dev_attr_group,
+		.scan_attrs = &max1238_scan_el_group,
+	}, {
 		.name = "max1136",
 		.num_inputs = 4,
 		.bits = 10,
@@ -657,6 +718,66 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
 		.dev_attrs = &max1238_dev_attr_group,
 		.scan_attrs = &max1238_scan_el_group,
 	}, {
+		.name = "max11600",
+		.num_inputs = 4,
+		.bits = 8,
+		.int_vref_mv = 4096,
+		.mode_list = max11607_mode_list,
+		.num_modes = ARRAY_SIZE(max11607_mode_list),
+		.default_mode = s0to3,
+		.dev_attrs = &max1363_dev_attr_group,
+		.scan_attrs = &max1363_scan_el_group,
+	}, {
+		.name = "max11601",
+		.num_inputs = 4,
+		.bits = 8,
+		.int_vref_mv = 2048,
+		.mode_list = max11607_mode_list,
+		.num_modes = ARRAY_SIZE(max11607_mode_list),
+		.default_mode = s0to3,
+		.dev_attrs = &max1363_dev_attr_group,
+		.scan_attrs = &max1363_scan_el_group,
+	}, {
+		.name = "max11602",
+		.num_inputs = 8,
+		.bits = 8,
+		.int_vref_mv = 4096,
+		.mode_list = max11608_mode_list,
+		.num_modes = ARRAY_SIZE(max11608_mode_list),
+		.default_mode = s0to7,
+		.dev_attrs = &max11608_dev_attr_group,
+		.scan_attrs = &max11608_scan_el_group,
+	}, {
+		.name = "max11603",
+		.num_inputs = 8,
+		.bits = 8,
+		.int_vref_mv = 2048,
+		.mode_list = max11608_mode_list,
+		.num_modes = ARRAY_SIZE(max11608_mode_list),
+		.default_mode = s0to7,
+		.dev_attrs = &max11608_dev_attr_group,
+		.scan_attrs = &max11608_scan_el_group,
+	}, {
+		.name = "max11604",
+		.num_inputs = 12,
+		.bits = 8,
+		.int_vref_mv = 4098,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.dev_attrs = &max1238_dev_attr_group,
+		.scan_attrs = &max1238_scan_el_group,
+	}, {
+		.name = "max11605",
+		.num_inputs = 12,
+		.bits = 8,
+		.int_vref_mv = 2048,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.dev_attrs = &max1238_dev_attr_group,
+		.scan_attrs = &max1238_scan_el_group,
+	}, {
 		.name = "max11606",
 		.num_inputs = 4,
 		.bits = 10,
@@ -920,6 +1041,10 @@ static const struct i2c_device_id max1363_id[] = {
 	{ "max1362", max1362 },
 	{ "max1363", max1363 },
 	{ "max1364", max1364 },
+	{ "max1036", max1036 },
+	{ "max1037", max1037 },
+	{ "max1038", max1038 },
+	{ "max1039", max1039 },
 	{ "max1136", max1136 },
 	{ "max1137", max1137 },
 	{ "max1138", max1138 },
@@ -928,6 +1053,12 @@ static const struct i2c_device_id max1363_id[] = {
 	{ "max1237", max1237 },
 	{ "max1238", max1238 },
 	{ "max1239", max1239 },
+	{ "max11600", max11600 },
+	{ "max11601", max11601 },
+	{ "max11602", max11602 },
+	{ "max11603", max11603 },
+	{ "max11604", max11604 },
+	{ "max11605", max11605 },
 	{ "max11606", max11606 },
 	{ "max11607", max11607 },
 	{ "max11608", max11608 },
diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c
index f1e37f2..85fde75 100644
--- a/drivers/staging/iio/adc/max1363_ring.c
+++ b/drivers/staging/iio/adc/max1363_ring.c
@@ -55,8 +55,11 @@ int max1363_single_channel_from_ring(long mask, struct max1363_state *st)
 			count++;
 		mask >>= 1;
 	}
-	return ((int)(ring_data[count*2 + 0] & 0x0F) << 8)
-		+ (int)(ring_data[count*2 + 1]);
+	if (st->chip_info->bits != 8)
+		return ((int)(ring_data[count*2 + 0] & 0x0F) << 8)
+			+ (int)(ring_data[count*2 + 1]);
+	else
+		return ring_data[count];
 
 error_free_ring_data:
 	kfree(ring_data);
@@ -90,7 +93,10 @@ static int max1363_ring_preenable(struct iio_dev *indio_dev)
 
 	numvals = hweight_long(st->current_mode->modemask);
 	if (indio_dev->ring->access.set_bpd) {
-		d_size = numvals*2 + sizeof(s64);
+		if (st->chip_info->bits != 8)
+			d_size = numvals*2 + sizeof(s64);
+		else
+			d_size = numvals + sizeof(s64);
 		if (d_size % 8)
 			d_size += 8 - (d_size % 8);
 		indio_dev->ring->access.set_bpd(indio_dev->ring, d_size);
@@ -166,7 +172,10 @@ static void max1363_poll_bh_to_ring(struct work_struct *work_s)
 	unsigned long numvals = hweight_long(st->current_mode->modemask);
 
 	/* Ensure the timestamp is 8 byte aligned */
-	d_size = numvals*2 + sizeof(s64);
+	if (st->chip_info->bits != 8)
+		d_size = numvals*2 + sizeof(s64);
+	else
+		d_size = numvals + sizeof(s64);
 	if (d_size % sizeof(s64))
 		d_size += sizeof(s64) - (d_size % sizeof(s64));
 
@@ -184,8 +193,10 @@ static void max1363_poll_bh_to_ring(struct work_struct *work_s)
 	rxbuf = kmalloc(d_size,	GFP_KERNEL);
 	if (rxbuf == NULL)
 		return;
-
-	b_sent = i2c_master_recv(st->client, rxbuf, numvals*2);
+	if (st->chip_info->bits != 8)
+		b_sent = i2c_master_recv(st->client, rxbuf, numvals*2);
+	else
+		b_sent = i2c_master_recv(st->client, rxbuf, numvals);
 	if (b_sent < 0)
 		goto done;
 
-- 
1.6.4.4

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

* [PATCH 16/20] staging:iio:ring_sw: Fix incorrect test on successful read of last value, causes infinite loop
  2010-05-04 13:43                             ` [PATCH 15/20] staging:iio:max1363 add support for 8 bit equivalent devices, max1036-9, max11600-5 Jonathan Cameron
@ 2010-05-04 13:43                               ` Jonathan Cameron
  2010-05-04 13:43                                 ` [PATCH 17/20] staging:iio:tsl2563 add a name attribute under the iio Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:43 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/ring_sw.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c
index f8de45d..5ee3e45 100644
--- a/drivers/staging/iio/ring_sw.c
+++ b/drivers/staging/iio/ring_sw.c
@@ -295,7 +295,7 @@ again:
 		return -EAGAIN;
 	memcpy(data, last_written_p_copy, ring->buf.bpd);
 
-	if (unlikely(ring->last_written_p >= last_written_p_copy))
+	if (unlikely(ring->last_written_p != last_written_p_copy))
 		goto again;
 
 	iio_unmark_sw_rb_in_use(&ring->buf);
-- 
1.6.4.4

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

* [PATCH 17/20] staging:iio:tsl2563 add a name attribute under the iio
  2010-05-04 13:43                               ` [PATCH 16/20] staging:iio:ring_sw: Fix incorrect test on successful read of last value, causes infinite loop Jonathan Cameron
@ 2010-05-04 13:43                                 ` Jonathan Cameron
  2010-05-04 13:43                                   ` [PATCH 18/20] staging:iio:Documentation: Rewrite example for new abi Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:43 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/light/tsl2563.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c
index 911c898..da3d51c 100644
--- a/drivers/staging/iio/light/tsl2563.c
+++ b/drivers/staging/iio/light/tsl2563.c
@@ -598,12 +598,24 @@ static DEVICE_ATTR(calib0, S_IRUGO | S_IWUSR,
 static DEVICE_ATTR(calib1, S_IRUGO | S_IWUSR,
 		   tsl2563_calib1_show, tsl2563_calib1_store);
 
+static ssize_t tsl2563_show_name(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct tsl2563_chip *chip = indio_dev->dev_data;
+	return sprintf(buf, "%s\n", chip->client->name);
+}
+
+DEVICE_ATTR(name, S_IRUGO, tsl2563_show_name, NULL);
+
 static struct attribute *tsl2563_attributes[] = {
 	&dev_attr_adc0.attr,
 	&dev_attr_adc1.attr,
 	&dev_attr_illuminance0_input.attr,
 	&dev_attr_calib0.attr,
 	&dev_attr_calib1.attr,
+	&dev_attr_name.attr,
 	NULL
 };
 
-- 
1.6.4.4

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

* [PATCH 18/20] staging:iio:Documentation: Rewrite example for new abi.
  2010-05-04 13:43                                 ` [PATCH 17/20] staging:iio:tsl2563 add a name attribute under the iio Jonathan Cameron
@ 2010-05-04 13:43                                   ` Jonathan Cameron
  2010-05-04 13:43                                     ` [PATCH 19/20] staging:iio:imu ADIS16300 driver Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:43 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/Documentation/iio_utils.h      |  277 ++++++++++++--------
 .../iio/Documentation/lis3l02dqbuffersimple.c      |  234 +++++++++++------
 2 files changed, 313 insertions(+), 198 deletions(-)

diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h
index d24006a..a4555e6 100644
--- a/drivers/staging/iio/Documentation/iio_utils.h
+++ b/drivers/staging/iio/Documentation/iio_utils.h
@@ -7,140 +7,173 @@
  * the Free Software Foundation.
  */
 
+/* Made up value to limit allocation sizes */
+#include <string.h>
+#include <stdlib.h>
+
+#define IIO_MAX_NAME_LENGTH 30
+
 #define IIO_EVENT_CODE_RING_50_FULL 200
 #define IIO_EVENT_CODE_RING_75_FULL 201
 #define IIO_EVENT_CODE_RING_100_FULL 202
 
+const char *iio_dir = "/sys/bus/iio/devices/";
+
 struct iio_event_data {
 	int id;
 	__s64 timestamp;
 };
 
-
-inline char *find_ring_subelement(const char *directory, const char *subelement)
-{
-	DIR *dp;
-	const struct dirent *ent;
-	int pos;
-	char temp[100];
-	char *returnstring;
-	dp = opendir(directory);
-	if (dp == NULL) {
-		printf("could not directory: %s\n", directory);
-		return NULL;
-	}
-	while (ent = readdir(dp), ent != NULL) {
-		if (strcmp(ent->d_name, ".") != 0 &&
-		    strcmp(ent->d_name, "..") != 0)  {
-			if (strncmp(ent->d_name, subelement, strlen(subelement)) == 0) {
-				int length = sprintf(temp, "%s%s%s", directory, ent->d_name, "/");
-				returnstring = malloc(length+1);
-				strncpy(returnstring, temp, length+1);
-				return returnstring;
-
-			}
-		}
-	}
-	return 0;
-}
-
-
-char *find_type_by_name(const char *name, const char *type)
+/**
+ * find_type_by_name() - function to match top level types by name
+ * @name: top level type instance name
+ * @type: the type of top level instance being sort
+ *
+ * Typical types this is used for are device and trigger.
+ **/
+inline int find_type_by_name(const char *name, const char *type)
 {
-	const char *iio_dir = "/sys/bus/iio/devices/";
 	const struct dirent *ent;
-	int cnt, pos, pos2;
+	int number, numstrlen;
 
 	FILE *nameFile;
 	DIR *dp;
-	char thisname[100];
-	char temp[100];
-
-	char *returnstring = NULL;
+	char thisname[IIO_MAX_NAME_LENGTH];
+	char *filename;
 	struct stat Stat;
-	pos = sprintf(temp, "%s", iio_dir);
+
 	dp = opendir(iio_dir);
 	if (dp == NULL) {
 		printf("No industrialio devices available");
-		return NULL;
+		return -ENODEV;
 	}
+
 	while (ent = readdir(dp), ent != NULL) {
-		cnt++;
-		/*reject . and .. */
 		if (strcmp(ent->d_name, ".") != 0 &&
-		    strcmp(ent->d_name, "..") != 0)  {
-			/*make sure it isn't a trigger!*/
-			if (strncmp(ent->d_name, type, strlen(type)) == 0) {
-				/* build full path to new file */
-				pos2 = pos + sprintf(temp + pos, "%s/", ent->d_name);
-				sprintf(temp + pos2, "name");
-				printf("search location %s\n", temp);
-				nameFile = fopen(temp, "r");
-				if (!nameFile) {
-					sprintf(temp + pos2, "modalias", ent->d_name);
-					nameFile = fopen(temp, "r");
-					if (!nameFile) {
-						printf("Failed to find a name for device\n");
-						return NULL;
-					}
-				}
+			strcmp(ent->d_name, "..") != 0 &&
+			strlen(ent->d_name) > strlen(type) &&
+			strncmp(ent->d_name, type, strlen(type)) == 0) {
+			numstrlen = sscanf(ent->d_name + strlen(type),
+					   "%d",
+					   &number);
+			/* verify the next character is not a colon */
+			if (strncmp(ent->d_name + strlen(type) + numstrlen,
+					":",
+					1) != 0) {
+				filename = malloc(strlen(iio_dir)
+						+ strlen(type)
+						+ 1
+						+ numstrlen
+						+ 1);
+				if (filename == NULL)
+					return -ENOMEM;
+				sprintf(filename, "%s%s%d/name",
+					iio_dir,
+					type,
+					number);
+				nameFile = fopen(filename, "r");
+				if (!nameFile)
+					continue;
+				free(filename);
 				fscanf(nameFile, "%s", thisname);
-				if (strcmp(name, thisname) == 0) {
-					returnstring = malloc(strlen(temp) + 1);
-					sprintf(temp + pos2, "");
-					strcpy(returnstring, temp);
-					return returnstring;
-				}
+				if (strcmp(name, thisname) == 0)
+					return number;
 				fclose(nameFile);
-
 			}
 		}
 	}
+	return -ENODEV;
 }
 
-int write_sysfs_int(char *filename, char *basedir, int val)
+inline int _write_sysfs_int(char *filename, char *basedir, int val, int verify)
 {
 	int ret;
-	FILE  *sysfsfp;
-	char temp[100];
-	sprintf(temp, "%s%s", basedir, filename);
+	FILE *sysfsfp;
+	int test;
+	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
+	if (temp == NULL)
+		return -ENOMEM;
+	sprintf(temp, "%s/%s", basedir, filename);
 	sysfsfp = fopen(temp, "w");
-	if (sysfsfp == NULL)
-		return -1;
+	if (sysfsfp == NULL) {
+		printf("failed to open %s\n", temp);
+		ret = -errno;
+		goto error_free;
+	}
 	fprintf(sysfsfp, "%d", val);
 	fclose(sysfsfp);
-	return 0;
+	if (verify) {
+		sysfsfp = fopen(temp, "r");
+		if (sysfsfp == NULL) {
+			printf("failed to open %s\n", temp);
+			ret = -errno;
+			goto error_free;
+		}
+		fscanf(sysfsfp, "%d", &test);
+		if (test != val) {
+			printf("Possible failure in int write %d to %s%s\n",
+				val,
+				basedir,
+				filename);
+			ret = -1;
+		}
+	}
+error_free:
+	free(temp);
+	return ret;
+}
+
+int write_sysfs_int(char *filename, char *basedir, int val)
+{
+	return _write_sysfs_int(filename, basedir, val, 0);
 }
 
 int write_sysfs_int_and_verify(char *filename, char *basedir, int val)
 {
+	return _write_sysfs_int(filename, basedir, val, 1);
+}
+
+int _write_sysfs_string(char *filename, char *basedir, char *val, int verify)
+{
 	int ret;
 	FILE  *sysfsfp;
-	char temp[100];
-	int test;
-
-	sprintf(temp, "%s%s", basedir, filename);
+	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
+	if (temp == NULL) {
+		printf("Memory allocation failed\n");
+		return -ENOMEM;
+	}
+	sprintf(temp, "%s/%s", basedir, filename);
 	sysfsfp = fopen(temp, "w");
-	if (sysfsfp == NULL)
-		return -1;
-	fprintf(sysfsfp, "%d", val);
+	if (sysfsfp == NULL) {
+		printf("Could not open %s\n", temp);
+		ret = -errno;
+		goto error_free;
+	}
+	fprintf(sysfsfp, "%s", val);
 	fclose(sysfsfp);
-
-	sysfsfp = fopen(temp, "r");
-	if (sysfsfp == NULL)
-		return -1;
-	fscanf(sysfsfp, "%d", &test);
-	if (test != val) {
-		printf("Possible failure in int write %d to %s%s\n",
-		       val,
-		       basedir,
-		       filename);
-		return -1;
+	if (verify) {
+		sysfsfp = fopen(temp, "r");
+		if (sysfsfp == NULL) {
+			ret = -errno;
+			goto error_free;
+		}
+		fscanf(sysfsfp, "%s", temp);
+		if (strcmp(temp, val) != 0) {
+			printf("Possible failure in string write of %s "
+				"Should be %s "
+				"writen to %s\%s\n",
+				temp,
+				val,
+				basedir,
+				filename);
+			ret = -1;
+		}
 	}
+error_free:
+	free(temp);
 
-	return 0;
+	return ret;
 }
-
 /**
  * write_sysfs_string_and_verify() - string write, readback and verify
  * @filename: name of file to write to
@@ -149,40 +182,54 @@ int write_sysfs_int_and_verify(char *filename, char *basedir, int val)
  **/
 int write_sysfs_string_and_verify(char *filename, char *basedir, char *val)
 {
-	int ret;
-	FILE  *sysfsfp;
-	char temp[100];
-	sprintf(temp, "%s%s", basedir, filename);
-	sysfsfp = fopen(temp, "w");
-	if (sysfsfp == NULL)
-		return -1;
-	fprintf(sysfsfp, "%s", val);
-	fclose(sysfsfp);
+	return _write_sysfs_string(filename, basedir, val, 1);
+}
 
-	sysfsfp = fopen(temp, "r");
-	if (sysfsfp == NULL)
-		return -1;
-	fscanf(sysfsfp, "%s", temp);
-	if (strcmp(temp, val) != 0) {
-		printf("Possible failure in string write %s to %s%s \n",
-		       val,
-		       basedir,
-		       filename);
-		return -1;
-	}
-	return 0;
+int write_sysfs_string(char *filename, char *basedir, char *val)
+{
+	return _write_sysfs_string(filename, basedir, val, 0);
 }
 
 int read_sysfs_posint(char *filename, char *basedir)
 {
 	int ret;
 	FILE  *sysfsfp;
-	char temp[100];
-	sprintf(temp, "%s%s", basedir, filename);
+	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
+	if (temp == NULL) {
+		printf("Memory allocation failed");
+		return -ENOMEM;
+	}
+	sprintf(temp, "%s/%s", basedir, filename);
 	sysfsfp = fopen(temp, "r");
-	if (sysfsfp == NULL)
-		return -1;
+	if (sysfsfp == NULL) {
+		ret = -errno;
+		goto error_free;
+	}
 	fscanf(sysfsfp, "%d\n", &ret);
 	fclose(sysfsfp);
+error_free:
+	free(temp);
+	return ret;
+}
+
+int read_sysfs_float(char *filename, char *basedir, float *val)
+{
+	float ret = 0;
+	FILE  *sysfsfp;
+	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
+	if (temp == NULL) {
+		printf("Memory allocation failed");
+		return -ENOMEM;
+	}
+	sprintf(temp, "%s/%s", basedir, filename);
+	sysfsfp = fopen(temp, "r");
+	if (sysfsfp == NULL) {
+		ret = -errno;
+		goto error_free;
+	}
+	fscanf(sysfsfp, "%f\n", val);
+	fclose(sysfsfp);
+error_free:
+	free(temp);
 	return ret;
 }
diff --git a/drivers/staging/iio/Documentation/lis3l02dqbuffersimple.c b/drivers/staging/iio/Documentation/lis3l02dqbuffersimple.c
index 08e012f..3a58028 100644
--- a/drivers/staging/iio/Documentation/lis3l02dqbuffersimple.c
+++ b/drivers/staging/iio/Documentation/lis3l02dqbuffersimple.c
@@ -1,4 +1,4 @@
-/* Industrialio test ring buffer with a lis3l02dq acceleromter
+/* Industrialio ring buffer with a lis3l02dq accelerometer
  *
  * Copyright (c) 2008 Jonathan Cameron
  *
@@ -6,125 +6,181 @@
  * under the terms of the GNU General Public License version 2 as published by
  * the Free Software Foundation.
  *
- * Assumes suitable udev rules are used to create the dev nodes as named here.
+ * This program is primarily intended as an example application.
  */
 
 #include <dirent.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <errno.h>
-#include <stdint.h>
-#include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/dir.h>
-
 #include <linux/types.h>
 #include "iio_utils.h"
 
-static const char *ring_access = "/dev/iio/lis3l02dq_ring_access";
-static const char *ring_event = "/dev/iio/lis3l02dq_ring_event";
-static const char *device_name = "lis3l02dq";
-static const char *trigger_name = "lis3l02dq-dev0";
-static int NumVals = 3;
-static int scan_ts = 1;
-static int RingLength = 128;
+const char *device_name = "lis3l02dq";
+const char *trigger_name_base = "lis3l02dq-dev";
+const int num_vals = 3;
+const int scan_ts = 1;
+const int buf_len = 128;
+const int num_loops = 10;
 
 /*
  * Could get this from ring bps, but only after starting the ring
- * which is a bit late for it to be useful
+ * which is a bit late for it to be useful.
+ *
+ * Todo: replace with much more generic version based on scan_elements
+ * directory.
  */
-int size_from_scanmode(int numVals, int timestamp)
+int size_from_scanmode(int num_vals, int timestamp)
 {
-	if (numVals && timestamp)
+	if (num_vals && timestamp)
 		return 16;
 	else if (timestamp)
 		return 8;
 	else
-		return numVals*2;
+		return num_vals*2;
 }
 
 int main(int argc, char **argv)
 {
+	int ret;
 	int i, j, k, toread;
 	FILE *fp_ev;
 	int fp;
+
+	char *trigger_name, *dev_dir_name, *buf_dir_name;
 	char *data;
 	size_t read_size;
 	struct iio_event_data dat;
+	int dev_num, trig_num;
+
+	char *buffer_access, *buffer_event;
+	const char *iio_dir = "/sys/bus/iio/devices/";
+	int scan_size;
+	float gain = 1;
 
-	char	*BaseDirectoryName,
-		*TriggerDirectoryName,
-		*RingBufferDirectoryName;
 
-	BaseDirectoryName = find_type_by_name(device_name, "device");
-	if (BaseDirectoryName == NULL) {
-		printf("Failed to find the %s \n", device_name);
-		return -1;
+	/* Find out which iio device is the accelerometer. */
+	dev_num = find_type_by_name(device_name, "device");
+	if (dev_num < 0) {
+		printf("Failed to find the %s\n", device_name);
+		ret = -ENODEV;
+		goto error_ret;
 	}
-	TriggerDirectoryName = find_type_by_name(trigger_name, "trigger");
-	if (TriggerDirectoryName == NULL) {
+	printf("iio device number being used is %d\n", dev_num);
+	asprintf(&dev_dir_name, "%sdevice%d", iio_dir, dev_num);
+
+	/*
+	 * Build the trigger name.
+	 * In this case we want the lis3l02dq's data ready trigger
+	 * for this lis3l02dq. The naming is lis3l02dq_dev[n], where
+	 * n matches the device number found above.
+	 */
+	ret = asprintf(&trigger_name, "%s%d", trigger_name_base, dev_num);
+	if (ret < 0) {
+		ret = -ENOMEM;
+		goto error_free_dev_dir_name;
+	}
+
+	/*
+	 * Find the trigger by name.
+	 * This is techically unecessary here as we only need to
+	 * refer to the trigger by name and that name is already
+	 * known.
+	 */
+	trig_num = find_type_by_name(trigger_name, "trigger");
+	if (trig_num < 0) {
 		printf("Failed to find the %s\n", trigger_name);
-		return -1;
+		ret = -ENODEV;
+		goto error_free_triggername;
 	}
-	RingBufferDirectoryName = find_ring_subelement(BaseDirectoryName,
-						       "ring_buffer");
-	if (RingBufferDirectoryName == NULL) {
-		printf("Failed to find ring buffer\n");
-		return -1;
+	printf("iio trigger number being used is %d\n", trig_num);
+
+	/*
+	 * Read in the scale value - in a more generic case, first
+	 * check for accel_scale, then the indivual channel scales
+	 */
+	ret = read_sysfs_float("accel_scale", dev_dir_name, &gain);
+	if (ret)
+		goto error_free_triggername;;
+
+	/*
+	 * Construct the directory name for the associated buffer.
+	 * As we know that the lis3l02dq has only one buffer this may
+	 * be built rather than found.
+	 */
+	ret = asprintf(&buf_dir_name, "%sdevice%d:buffer0", iio_dir, dev_num);
+	if (ret < 0) {
+		ret = -ENOMEM;
+		goto error_free_triggername;
 	}
-
-	if (write_sysfs_string_and_verify("trigger/current_trigger",
-					  BaseDirectoryName,
-					  (char *)trigger_name) < 0) {
-		printf("Failed to write current_trigger file \n");
-		return -1;
+	/* Set the device trigger to be the data rdy trigger found above */
+	ret = write_sysfs_string_and_verify("trigger/current_trigger",
+					dev_dir_name,
+					trigger_name);
+	if (ret < 0) {
+		printf("Failed to write current_trigger file\n");
+		goto error_free_buf_dir_name;
 	}
 
 	/* Setup ring buffer parameters */
-	if (write_sysfs_int("length", RingBufferDirectoryName,
-			    RingLength) < 0) {
-		printf("Failed to open the ring buffer length file \n");
-		return -1;
-	}
+	ret = write_sysfs_int("length", buf_dir_name, buf_len);
+	if (ret < 0)
+		goto error_free_buf_dir_name;
 
-	/* Enable the ring buffer */
-	if (write_sysfs_int("ring_enable", RingBufferDirectoryName, 1) < 0) {
-		printf("Failed to open the ring buffer control file \n");
-		return -1;
-	};
+	/* Enable the buffer */
+	ret = write_sysfs_int("ring_enable", buf_dir_name, 1);
+	if (ret < 0)
+		goto error_free_buf_dir_name;
 
-	data = malloc(size_from_scanmode(NumVals, scan_ts)*RingLength);
+	data = malloc(size_from_scanmode(num_vals, scan_ts)*buf_len);
 	if (!data) {
-		printf("Could not allocate space for usespace data store\n");
-		return -1;
+		ret = -ENOMEM;
+		goto error_free_buf_dir_name;
+	}
+
+	ret = asprintf(&buffer_access,
+		       "/dev/device%d:buffer0:access0",
+		       dev_num);
+	if (ret < 0) {
+		ret = -ENOMEM;
+		goto error_free_data;
 	}
 
+	ret = asprintf(&buffer_event, "/dev/device%d:buffer0:event0", dev_num);
+	if (ret < 0) {
+		ret = -ENOMEM;
+		goto error_free_data;
+	}
 	/* Attempt to open non blocking the access dev */
-	fp = open(ring_access, O_RDONLY | O_NONBLOCK);
+	fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
 	if (fp == -1) { /*If it isn't there make the node */
-		printf("Failed to open %s\n", ring_access);
-		return -1;
+		printf("Failed to open %s\n", buffer_access);
+		ret = -errno;
+		goto error_free_buffer_event;
 	}
 	/* Attempt to open the event access dev (blocking this time) */
-	fp_ev = fopen(ring_event, "rb");
+	fp_ev = fopen(buffer_event, "rb");
 	if (fp_ev == NULL) {
-		printf("Failed to open %s\n", ring_event);
-		return -1;
+		printf("Failed to open %s\n", buffer_event);
+		ret = -errno;
+		goto error_close_buffer_access;
 	}
 
 	/* Wait for events 10 times */
-	for (j = 0; j < 10; j++) {
+	for (j = 0; j < num_loops; j++) {
 		read_size = fread(&dat, 1, sizeof(struct iio_event_data),
 				  fp_ev);
 		switch (dat.id) {
 		case IIO_EVENT_CODE_RING_100_FULL:
-			toread = RingLength;
+			toread = buf_len;
 			break;
 		case IIO_EVENT_CODE_RING_75_FULL:
-			toread = RingLength*3/4;
+			toread = buf_len*3/4;
 			break;
 		case IIO_EVENT_CODE_RING_50_FULL:
-			toread = RingLength/2;
+			toread = buf_len/2;
 			break;
 		default:
 			printf("Unexpecteded event code\n");
@@ -132,39 +188,51 @@ int main(int argc, char **argv)
 		}
 		read_size = read(fp,
 				 data,
-				 toread*size_from_scanmode(NumVals, scan_ts));
+				 toread*size_from_scanmode(num_vals, scan_ts));
 		if (read_size == -EAGAIN) {
-			printf("nothing available \n");
+			printf("nothing available\n");
 			continue;
 		}
-
-		for (i = 0;
-		     i < read_size/size_from_scanmode(NumVals, scan_ts);
-		     i++) {
-			for (k = 0; k < NumVals; k++) {
-				__s16 val = *(__s16 *)(&data[i*size_from_scanmode(NumVals, scan_ts)
+		scan_size = size_from_scanmode(num_vals, scan_ts);
+		for (i = 0; i < read_size/scan_size; i++) {
+			for (k = 0; k < num_vals; k++) {
+				__s16 val = *(__s16 *)(&data[i*scan_size
 							     + (k)*2]);
-				printf("%05d ", val);
+				printf("%05f ", (float)val*gain);
 			}
 			printf(" %lld\n",
-			       *(__s64 *)(&data[(i+1)*size_from_scanmode(NumVals, scan_ts)
+			       *(__s64 *)(&data[(i + 1)
+						*size_from_scanmode(num_vals,
+								    scan_ts)
 						- sizeof(__s64)]));
 		}
 	}
 
 	/* Stop the ring buffer */
-	if (write_sysfs_int("ring_enable", RingBufferDirectoryName, 0) < 0) {
-		printf("Failed to open the ring buffer control file \n");
-		return -1;
-	};
-
-	/* Disconnect from the trigger - writing something that doesn't exist.*/
-	write_sysfs_string_and_verify("trigger/current_trigger",
-				      BaseDirectoryName, "NULL");
-	free(BaseDirectoryName);
-	free(TriggerDirectoryName);
-	free(RingBufferDirectoryName);
+	ret = write_sysfs_int("ring_enable", buf_dir_name, 0);
+	if (ret < 0)
+		goto error_close_buffer_event;
+
+	/* Disconnect from the trigger - just write a dummy name.*/
+	write_sysfs_string("trigger/current_trigger",
+			dev_dir_name, "NULL");
+
+error_close_buffer_event:
+	fclose(fp_ev);
+error_close_buffer_access:
+	close(fp);
+error_free_data:
 	free(data);
-
-	return 0;
+error_free_buffer_access:
+	free(buffer_access);
+error_free_buffer_event:
+	free(buffer_event);
+error_free_buf_dir_name:
+	free(buf_dir_name);
+error_free_triggername:
+	free(trigger_name);
+error_free_dev_dir_name:
+	free(dev_dir_name);
+error_ret:
+	return ret;
 }
-- 
1.6.4.4

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

* [PATCH 19/20] staging:iio:imu ADIS16300 driver
  2010-05-04 13:43                                   ` [PATCH 18/20] staging:iio:Documentation: Rewrite example for new abi Jonathan Cameron
@ 2010-05-04 13:43                                     ` Jonathan Cameron
  2010-05-04 13:43                                       ` [PATCH 20/20] staging:iio:imu ADIS16400 and ADIS16405 driver Jonathan Cameron
  0 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:43 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Barry Song

From: Barry Song <Barry.Song@analog.com>

Signed-off-by: Barry Song <Barry.Song@analog.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/Kconfig                 |    1 +
 drivers/staging/iio/Makefile                |    1 +
 drivers/staging/iio/adc/adc.h               |    3 +
 drivers/staging/iio/gyro/gyro.h             |   76 +++
 drivers/staging/iio/imu/Kconfig             |   14 +
 drivers/staging/iio/imu/Makefile            |    6 +
 drivers/staging/iio/imu/adis16300.h         |  203 +++++++
 drivers/staging/iio/imu/adis16300_core.c    |  833 +++++++++++++++++++++++++++
 drivers/staging/iio/imu/adis16300_ring.c    |  233 ++++++++
 drivers/staging/iio/imu/adis16300_trigger.c |  127 ++++
 10 files changed, 1497 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig
index ace99f6..ed38ef4 100644
--- a/drivers/staging/iio/Kconfig
+++ b/drivers/staging/iio/Kconfig
@@ -41,6 +41,7 @@ config IIO_TRIGGER
 
 source "drivers/staging/iio/accel/Kconfig"
 source "drivers/staging/iio/adc/Kconfig"
+source "drivers/staging/iio/imu/Kconfig"
 source "drivers/staging/iio/light/Kconfig"
 
 source "drivers/staging/iio/trigger/Kconfig"
diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile
index 7ec0218..92b81c2 100644
--- a/drivers/staging/iio/Makefile
+++ b/drivers/staging/iio/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_IIO_SW_RING) += ring_sw.o
 
 obj-y += accel/
 obj-y += adc/
+obj-y += imu/
 obj-y += light/
 
 obj-y += trigger/
\ No newline at end of file
diff --git a/drivers/staging/iio/adc/adc.h b/drivers/staging/iio/adc/adc.h
index 46f0d08..04eb16f 100644
--- a/drivers/staging/iio/adc/adc.h
+++ b/drivers/staging/iio/adc/adc.h
@@ -16,6 +16,9 @@
 #define IIO_DEV_ATTR_IN_RAW(_num, _show, _addr)				\
 	IIO_DEVICE_ATTR(in##_num##_raw, S_IRUGO, _show, NULL, _addr)
 
+#define IIO_DEV_ATTR_IN_NAMED_RAW(_name, _show, _addr)			\
+	IIO_DEVICE_ATTR(in_##_name##_raw, S_IRUGO, _show, NULL, _addr)
+
 #define IIO_DEV_ATTR_IN_DIFF_RAW(_nump, _numn, _show, _addr)		\
 	IIO_DEVICE_ATTR_NAMED(in##_nump##min##_numn##_raw,		\
 			      in##_nump-in##_numn##_raw,		\
diff --git a/drivers/staging/iio/gyro/gyro.h b/drivers/staging/iio/gyro/gyro.h
new file mode 100644
index 0000000..7c4dcf2
--- /dev/null
+++ b/drivers/staging/iio/gyro/gyro.h
@@ -0,0 +1,76 @@
+
+#include "../sysfs.h"
+
+/* Gyroscope types of attribute */
+
+#define IIO_DEV_ATTR_GYRO_OFFSET(_mode, _show, _store, _addr)	\
+	IIO_DEVICE_ATTR(gyro_offset, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO_X_OFFSET(_mode, _show, _store, _addr)	\
+	IIO_DEVICE_ATTR(gyro_x_offset, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO_Y_OFFSET(_mode, _show, _store, _addr)	\
+	IIO_DEVICE_ATTR(gyro_y_offset, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO_Z_OFFSET(_mode, _show, _store, _addr)	\
+	IIO_DEVICE_ATTR(gyro_z_offset, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO_X_GAIN(_mode, _show, _store, _addr)		\
+	IIO_DEVICE_ATTR(gyro_x_gain, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO_Y_GAIN(_mode, _show, _store, _addr)		\
+	IIO_DEVICE_ATTR(gyro_y_gain, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO_Z_GAIN(_mode, _show, _store, _addr)		\
+	IIO_DEVICE_ATTR(gyro_z_gain, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO_SCALE(_mode, _show, _store, _addr)		\
+	IIO_DEVICE_ATTR(gyro_scale, S_IRUGO, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO(_show, _addr)			\
+	IIO_DEVICE_ATTR(gyro, S_IRUGO, _show, NULL, _addr)
+
+#define IIO_DEV_ATTR_GYRO_X(_show, _addr)			\
+	IIO_DEVICE_ATTR(gyro_x, S_IRUGO, _show, NULL, _addr)
+
+#define IIO_DEV_ATTR_GYRO_Y(_show, _addr)			\
+	IIO_DEVICE_ATTR(gyro_y, S_IRUGO, _show, NULL, _addr)
+
+#define IIO_DEV_ATTR_GYRO_Z(_show, _addr)			\
+	IIO_DEVICE_ATTR(gyro_z, S_IRUGO, _show, NULL, _addr)
+
+#define IIO_DEV_ATTR_TEMP_X(_show, _addr)			\
+	IIO_DEVICE_ATTR(temp_x, S_IRUGO, _show, NULL, _addr)
+
+#define IIO_DEV_ATTR_TEMP_Y(_show, _addr)			\
+	IIO_DEVICE_ATTR(temp_y, S_IRUGO, _show, NULL, _addr)
+
+#define IIO_DEV_ATTR_TEMP_Z(_show, _addr)			\
+	IIO_DEVICE_ATTR(temp_z, S_IRUGO, _show, NULL, _addr)
+
+#define IIO_DEV_ATTR_INCLI_X(_show, _addr)			\
+	IIO_DEVICE_ATTR(incli_x, S_IRUGO, _show, NULL, _addr)
+
+#define IIO_DEV_ATTR_INCLI_Y(_show, _addr)			\
+	IIO_DEVICE_ATTR(incli_y, S_IRUGO, _show, NULL, _addr)
+
+#define IIO_DEV_ATTR_INCLI_Z(_show, _addr)			\
+	IIO_DEVICE_ATTR(incli_z, S_IRUGO, _show, NULL, _addr)
+
+#define IIO_DEV_ATTR_INCLI_X_OFFSET(_mode, _show, _store, _addr) \
+	IIO_DEVICE_ATTR(incli_x_offset, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_INCLI_Y_OFFSET(_mode, _show, _store, _addr) \
+	IIO_DEVICE_ATTR(incli_y_offset, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_INCLI_Z_OFFSET(_mode, _show, _store, _addr) \
+	IIO_DEVICE_ATTR(incli_z_offset, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_ROT(_show, _addr)                    \
+	IIO_DEVICE_ATTR(rot, S_IRUGO, _show, NULL, _addr)
+
+#define IIO_DEV_ATTR_ROT_OFFSET(_mode, _show, _store, _addr) \
+	IIO_DEVICE_ATTR(rot_offset, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_ANGL(_show, _addr)                         \
+	IIO_DEVICE_ATTR(angl, S_IRUGO, _show, NULL, _addr)
diff --git a/drivers/staging/iio/imu/Kconfig b/drivers/staging/iio/imu/Kconfig
new file mode 100644
index 0000000..3fe4716
--- /dev/null
+++ b/drivers/staging/iio/imu/Kconfig
@@ -0,0 +1,14 @@
+#
+# IIO imu drivers configuration
+#
+comment "Inertial measurement units"
+
+config ADIS16300
+	tristate "Analog Devices ADIS16300 IMU SPI driver"
+	depends on SPI
+	select IIO_SW_RING
+	select IIO_RING_BUFFER
+	select IIO_TRIGGER
+	help
+	  Say yes here to build support for Analog Devices adis16300 four degrees
+	  of freedom inertial sensor.
diff --git a/drivers/staging/iio/imu/Makefile b/drivers/staging/iio/imu/Makefile
new file mode 100644
index 0000000..4cd5984
--- /dev/null
+++ b/drivers/staging/iio/imu/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for Inertial Measurement Units
+#
+adis16300-y             := adis16300_core.o
+adis16300-$(CONFIG_IIO_RING_BUFFER) += adis16300_ring.o adis16300_trigger.o
+obj-$(CONFIG_ADIS16300) += adis16300.o
diff --git a/drivers/staging/iio/imu/adis16300.h b/drivers/staging/iio/imu/adis16300.h
new file mode 100644
index 0000000..77d890d
--- /dev/null
+++ b/drivers/staging/iio/imu/adis16300.h
@@ -0,0 +1,203 @@
+#ifndef SPI_ADIS16300_H_
+#define SPI_ADIS16300_H_
+
+#define ADIS16300_STARTUP_DELAY	220 /* ms */
+
+#define ADIS16300_READ_REG(a)    a
+#define ADIS16300_WRITE_REG(a) ((a) | 0x80)
+
+#define ADIS16300_FLASH_CNT  0x00 /* Flash memory write count */
+#define ADIS16300_SUPPLY_OUT 0x02 /* Power supply measurement */
+#define ADIS16300_XGYRO_OUT 0x04 /* X-axis gyroscope output */
+#define ADIS16300_XACCL_OUT 0x0A /* X-axis accelerometer output */
+#define ADIS16300_YACCL_OUT 0x0C /* Y-axis accelerometer output */
+#define ADIS16300_ZACCL_OUT 0x0E /* Z-axis accelerometer output */
+#define ADIS16300_TEMP_OUT  0x10 /* Temperature output */
+#define ADIS16300_XINCLI_OUT 0x12 /* X-axis inclinometer output measurement */
+#define ADIS16300_YINCLI_OUT 0x14 /* Y-axis inclinometer output measurement */
+#define ADIS16300_AUX_ADC   0x16 /* Auxiliary ADC measurement */
+
+/* Calibration parameters */
+#define ADIS16300_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */
+#define ADIS16300_XACCL_OFF 0x20 /* X-axis acceleration bias offset factor */
+#define ADIS16300_YACCL_OFF 0x22 /* Y-axis acceleration bias offset factor */
+#define ADIS16300_ZACCL_OFF 0x24 /* Z-axis acceleration bias offset factor */
+
+#define ADIS16300_GPIO_CTRL 0x32 /* Auxiliary digital input/output control */
+#define ADIS16300_MSC_CTRL  0x34 /* Miscellaneous control */
+#define ADIS16300_SMPL_PRD  0x36 /* Internal sample period (rate) control */
+#define ADIS16300_SENS_AVG  0x38 /* Dynamic range and digital filter control */
+#define ADIS16300_SLP_CNT   0x3A /* Sleep mode control */
+#define ADIS16300_DIAG_STAT 0x3C /* System status */
+
+/* Alarm functions */
+#define ADIS16300_GLOB_CMD  0x3E /* System command */
+#define ADIS16300_ALM_MAG1  0x26 /* Alarm 1 amplitude threshold */
+#define ADIS16300_ALM_MAG2  0x28 /* Alarm 2 amplitude threshold */
+#define ADIS16300_ALM_SMPL1 0x2A /* Alarm 1 sample size */
+#define ADIS16300_ALM_SMPL2 0x2C /* Alarm 2 sample size */
+#define ADIS16300_ALM_CTRL  0x2E /* Alarm control */
+#define ADIS16300_AUX_DAC   0x30 /* Auxiliary DAC data */
+
+#define ADIS16300_ERROR_ACTIVE			(1<<14)
+#define ADIS16300_NEW_DATA			(1<<15)
+
+/* MSC_CTRL */
+#define ADIS16300_MSC_CTRL_MEM_TEST		(1<<11)
+#define ADIS16300_MSC_CTRL_INT_SELF_TEST	(1<<10)
+#define ADIS16300_MSC_CTRL_NEG_SELF_TEST	(1<<9)
+#define ADIS16300_MSC_CTRL_POS_SELF_TEST	(1<<8)
+#define ADIS16300_MSC_CTRL_GYRO_BIAS		(1<<7)
+#define ADIS16300_MSC_CTRL_ACCL_ALIGN		(1<<6)
+#define ADIS16300_MSC_CTRL_DATA_RDY_EN		(1<<2)
+#define ADIS16300_MSC_CTRL_DATA_RDY_POL_HIGH	(1<<1)
+#define ADIS16300_MSC_CTRL_DATA_RDY_DIO2	(1<<0)
+
+/* SMPL_PRD */
+#define ADIS16300_SMPL_PRD_TIME_BASE	(1<<7)
+#define ADIS16300_SMPL_PRD_DIV_MASK	0x7F
+
+/* DIAG_STAT */
+#define ADIS16300_DIAG_STAT_ZACCL_FAIL	(1<<15)
+#define ADIS16300_DIAG_STAT_YACCL_FAIL	(1<<14)
+#define ADIS16300_DIAG_STAT_XACCL_FAIL	(1<<13)
+#define ADIS16300_DIAG_STAT_XGYRO_FAIL	(1<<10)
+#define ADIS16300_DIAG_STAT_ALARM2	(1<<9)
+#define ADIS16300_DIAG_STAT_ALARM1	(1<<8)
+#define ADIS16300_DIAG_STAT_FLASH_CHK	(1<<6)
+#define ADIS16300_DIAG_STAT_SELF_TEST	(1<<5)
+#define ADIS16300_DIAG_STAT_OVERFLOW	(1<<4)
+#define ADIS16300_DIAG_STAT_SPI_FAIL	(1<<3)
+#define ADIS16300_DIAG_STAT_FLASH_UPT	(1<<2)
+#define ADIS16300_DIAG_STAT_POWER_HIGH	(1<<1)
+#define ADIS16300_DIAG_STAT_POWER_LOW	(1<<0)
+
+/* GLOB_CMD */
+#define ADIS16300_GLOB_CMD_SW_RESET	(1<<7)
+#define ADIS16300_GLOB_CMD_P_AUTO_NULL	(1<<4)
+#define ADIS16300_GLOB_CMD_FLASH_UPD	(1<<3)
+#define ADIS16300_GLOB_CMD_DAC_LATCH	(1<<2)
+#define ADIS16300_GLOB_CMD_FAC_CALIB	(1<<1)
+#define ADIS16300_GLOB_CMD_AUTO_NULL	(1<<0)
+
+/* SLP_CNT */
+#define ADIS16300_SLP_CNT_POWER_OFF	(1<<8)
+
+#define ADIS16300_MAX_TX 18
+#define ADIS16300_MAX_RX 18
+
+#define ADIS16300_SPI_SLOW	(u32)(300 * 1000)
+#define ADIS16300_SPI_BURST	(u32)(1000 * 1000)
+#define ADIS16300_SPI_FAST	(u32)(2000 * 1000)
+
+/**
+ * struct adis16300_state - device instance specific data
+ * @us:			actual spi_device
+ * @work_trigger_to_ring: bh for triggered event handling
+ * @work_cont_thresh: CLEAN
+ * @inter:		used to check if new interrupt has been triggered
+ * @last_timestamp:	passing timestamp from th to bh of interrupt handler
+ * @indio_dev:		industrial I/O device structure
+ * @trig:		data ready trigger registered with iio
+ * @tx:			transmit buffer
+ * @rx:			recieve buffer
+ * @buf_lock:		mutex to protect tx and rx
+ **/
+struct adis16300_state {
+	struct spi_device		*us;
+	struct work_struct		work_trigger_to_ring;
+	struct iio_work_cont		work_cont_thresh;
+	s64				last_timestamp;
+	struct iio_dev			*indio_dev;
+	struct iio_trigger		*trig;
+	u8				*tx;
+	u8				*rx;
+	struct mutex			buf_lock;
+};
+
+int adis16300_spi_write_reg_8(struct device *dev,
+			      u8 reg_address,
+			      u8 val);
+
+int adis16300_spi_read_burst(struct device *dev, u8 *rx);
+
+int adis16300_spi_read_sequence(struct device *dev,
+				      u8 *tx, u8 *rx, int num);
+
+int adis16300_set_irq(struct device *dev, bool enable);
+
+int adis16300_reset(struct device *dev);
+
+int adis16300_stop_device(struct device *dev);
+
+int adis16300_check_status(struct device *dev);
+
+#ifdef CONFIG_IIO_RING_BUFFER
+/* At the moment triggers are only used for ring buffer
+ * filling. This may change!
+ */
+
+enum adis16300_scan {
+	ADIS16300_SCAN_SUPPLY,
+	ADIS16300_SCAN_GYRO_X,
+	ADIS16300_SCAN_ACC_X,
+	ADIS16300_SCAN_ACC_Y,
+	ADIS16300_SCAN_ACC_Z,
+	ADIS16300_SCAN_TEMP,
+	ADIS16300_SCAN_ADC_0,
+	ADIS16300_SCAN_INCLI_X,
+	ADIS16300_SCAN_INCLI_Y,
+};
+
+void adis16300_remove_trigger(struct iio_dev *indio_dev);
+int adis16300_probe_trigger(struct iio_dev *indio_dev);
+
+ssize_t adis16300_read_data_from_ring(struct device *dev,
+				      struct device_attribute *attr,
+				      char *buf);
+
+
+int adis16300_configure_ring(struct iio_dev *indio_dev);
+void adis16300_unconfigure_ring(struct iio_dev *indio_dev);
+
+int adis16300_initialize_ring(struct iio_ring_buffer *ring);
+void adis16300_uninitialize_ring(struct iio_ring_buffer *ring);
+#else /* CONFIG_IIO_RING_BUFFER */
+
+static inline void adis16300_remove_trigger(struct iio_dev *indio_dev)
+{
+}
+
+static inline int adis16300_probe_trigger(struct iio_dev *indio_dev)
+{
+	return 0;
+}
+
+static inline ssize_t
+adis16300_read_data_from_ring(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	return 0;
+}
+
+static int adis16300_configure_ring(struct iio_dev *indio_dev)
+{
+	return 0;
+}
+
+static inline void adis16300_unconfigure_ring(struct iio_dev *indio_dev)
+{
+}
+
+static inline int adis16300_initialize_ring(struct iio_ring_buffer *ring)
+{
+	return 0;
+}
+
+static inline void adis16300_uninitialize_ring(struct iio_ring_buffer *ring)
+{
+}
+
+#endif /* CONFIG_IIO_RING_BUFFER */
+#endif /* SPI_ADIS16300_H_ */
diff --git a/drivers/staging/iio/imu/adis16300_core.c b/drivers/staging/iio/imu/adis16300_core.c
new file mode 100644
index 0000000..9f5f8cb
--- /dev/null
+++ b/drivers/staging/iio/imu/adis16300_core.c
@@ -0,0 +1,833 @@
+/*
+ * ADIS16300 Four Degrees of Freedom Inertial Sensor Driver
+ *
+ * Copyright 2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+
+#include <linux/sysfs.h>
+#include <linux/list.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "../accel/accel.h"
+#include "../gyro/gyro.h"
+#include "../adc/adc.h"
+
+#include "adis16300.h"
+
+#define DRIVER_NAME		"adis16300"
+
+/* At the moment the spi framework doesn't allow global setting of cs_change.
+ * It's in the likely to be added comment at the top of spi.h.
+ * This means that use cannot be made of spi_write etc.
+ */
+
+/**
+ * adis16300_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
+ **/
+int adis16300_spi_write_reg_8(struct device *dev,
+		u8 reg_address,
+		u8 val)
+{
+	int ret;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct adis16300_state *st = iio_dev_get_devdata(indio_dev);
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = ADIS16300_WRITE_REG(reg_address);
+	st->tx[1] = val;
+
+	ret = spi_write(st->us, st->tx, 2);
+	mutex_unlock(&st->buf_lock);
+
+	return ret;
+}
+
+/**
+ * adis16300_spi_write_reg_16() - write 2 bytes to a pair of registers
+ * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @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 adis16300_spi_write_reg_16(struct device *dev,
+		u8 lower_reg_address,
+		u16 value)
+{
+	int ret;
+	struct spi_message msg;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct adis16300_state *st = iio_dev_get_devdata(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] = ADIS16300_WRITE_REG(lower_reg_address);
+	st->tx[1] = value & 0xFF;
+	st->tx[2] = ADIS16300_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;
+}
+
+/**
+ * adis16300_spi_read_reg_16() - read 2 bytes from a 16-bit register
+ * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @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 adis16300_spi_read_reg_16(struct device *dev,
+		u8 lower_reg_address,
+		u16 *val)
+{
+	struct spi_message msg;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct adis16300_state *st = iio_dev_get_devdata(indio_dev);
+	int ret;
+	struct spi_transfer xfers[] = {
+		{
+			.tx_buf = st->tx,
+			.bits_per_word = 8,
+			.len = 2,
+			.cs_change = 0,
+		}, {
+			.rx_buf = st->rx,
+			.bits_per_word = 8,
+			.len = 2,
+			.cs_change = 0,
+		},
+	};
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = ADIS16300_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;
+}
+
+/**
+ * adis16300_spi_read_burst() - read all data registers
+ * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @rx: somewhere to pass back the value read (min size is 24 bytes)
+ **/
+int adis16300_spi_read_burst(struct device *dev, u8 *rx)
+{
+	struct spi_message msg;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct adis16300_state *st = iio_dev_get_devdata(indio_dev);
+	u32 old_speed_hz = st->us->max_speed_hz;
+	int ret;
+
+	struct spi_transfer xfers[] = {
+		{
+			.tx_buf = st->tx,
+			.bits_per_word = 8,
+			.len = 2,
+			.cs_change = 0,
+		}, {
+			.rx_buf = rx,
+			.bits_per_word = 8,
+			.len = 18,
+			.cs_change = 0,
+		},
+	};
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = ADIS16300_READ_REG(ADIS16300_GLOB_CMD);
+	st->tx[1] = 0;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfers[0], &msg);
+	spi_message_add_tail(&xfers[1], &msg);
+
+	st->us->max_speed_hz = min(ADIS16300_SPI_BURST, old_speed_hz);
+	spi_setup(st->us);
+
+	ret = spi_sync(st->us, &msg);
+	if (ret)
+		dev_err(&st->us->dev, "problem when burst reading");
+
+	st->us->max_speed_hz = old_speed_hz;
+	spi_setup(st->us);
+	mutex_unlock(&st->buf_lock);
+	return ret;
+}
+
+/**
+ * adis16300_spi_read_sequence() - read a sequence of 16-bit registers
+ * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @tx: register addresses in bytes 0,2,4,6... (min size is 2*num bytes)
+ * @rx: somewhere to pass back the value read (min size is 2*num bytes)
+ **/
+int adis16300_spi_read_sequence(struct device *dev,
+		u8 *tx, u8 *rx, int num)
+{
+	struct spi_message msg;
+	struct spi_transfer *xfers;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct adis16300_state *st = iio_dev_get_devdata(indio_dev);
+	int ret, i;
+
+	xfers = kzalloc(num + 1, GFP_KERNEL);
+	if (xfers == NULL) {
+		dev_err(&st->us->dev, "memory alloc failed");
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+
+	/* tx: |add1|addr2|addr3|...|addrN |zero|
+	 * rx: |zero|res1 |res2 |...|resN-1|resN| */
+	spi_message_init(&msg);
+	for (i = 0; i < num + 1; i++) {
+		if (i > 0)
+			xfers[i].rx_buf = st->rx + 2*(i - 1);
+		if (i < num)
+			xfers[i].tx_buf = st->tx + 2*i;
+		xfers[i].bits_per_word = 8;
+		xfers[i].len = 2;
+		xfers[i].cs_change = 1;
+		spi_message_add_tail(&xfers[i], &msg);
+	}
+
+	mutex_lock(&st->buf_lock);
+
+	ret = spi_sync(st->us, &msg);
+	if (ret)
+		dev_err(&st->us->dev, "problem when reading sequence");
+
+	mutex_unlock(&st->buf_lock);
+	kfree(xfers);
+
+error_ret:
+	return ret;
+}
+
+static ssize_t adis16300_spi_read_signed(struct device *dev,
+		struct device_attribute *attr,
+		char *buf,
+		unsigned bits)
+{
+	int ret;
+	s16 val = 0;
+	unsigned shift = 16 - bits;
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+
+	ret = adis16300_spi_read_reg_16(dev, this_attr->address, (u16 *)&val);
+	if (ret)
+		return ret;
+
+	if (val & ADIS16300_ERROR_ACTIVE)
+		adis16300_check_status(dev);
+	val = ((s16)(val << shift) >> shift);
+	return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t adis16300_read_12bit_unsigned(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	int ret;
+	u16 val = 0;
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+
+	ret = adis16300_spi_read_reg_16(dev, this_attr->address, &val);
+	if (ret)
+		return ret;
+
+	if (val & ADIS16300_ERROR_ACTIVE)
+		adis16300_check_status(dev);
+
+	return sprintf(buf, "%u\n", val & 0x0FFF);
+}
+
+static ssize_t adis16300_read_14bit_signed(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	ssize_t ret;
+
+	/* Take the iio_dev status lock */
+	mutex_lock(&indio_dev->mlock);
+	ret =  adis16300_spi_read_signed(dev, attr, buf, 14);
+	mutex_unlock(&indio_dev->mlock);
+
+	return ret;
+}
+
+static ssize_t adis16300_read_12bit_signed(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	ssize_t ret;
+
+	/* Take the iio_dev status lock */
+	mutex_lock(&indio_dev->mlock);
+	ret =  adis16300_spi_read_signed(dev, attr, buf, 12);
+	mutex_unlock(&indio_dev->mlock);
+
+	return ret;
+}
+
+static ssize_t adis16300_read_13bit_signed(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	ssize_t ret;
+
+	/* Take the iio_dev status lock */
+	mutex_lock(&indio_dev->mlock);
+	ret =  adis16300_spi_read_signed(dev, attr, buf, 13);
+	mutex_unlock(&indio_dev->mlock);
+
+	return ret;
+}
+
+static ssize_t adis16300_write_16bit(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t len)
+{
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+	int ret;
+	long val;
+
+	ret = strict_strtol(buf, 10, &val);
+	if (ret)
+		goto error_ret;
+	ret = adis16300_spi_write_reg_16(dev, this_attr->address, val);
+
+error_ret:
+	return ret ? ret : len;
+}
+
+static ssize_t adis16300_read_frequency(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	int ret, len = 0;
+	u16 t;
+	int sps;
+	ret = adis16300_spi_read_reg_16(dev,
+			ADIS16300_SMPL_PRD,
+			&t);
+	if (ret)
+		return ret;
+	sps =  (t & ADIS16300_SMPL_PRD_TIME_BASE) ? 53 : 1638;
+	sps /= (t & ADIS16300_SMPL_PRD_DIV_MASK) + 1;
+	len = sprintf(buf, "%d SPS\n", sps);
+	return len;
+}
+
+static ssize_t adis16300_write_frequency(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t len)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct adis16300_state *st = iio_dev_get_devdata(indio_dev);
+	long val;
+	int ret;
+	u8 t;
+
+	ret = strict_strtol(buf, 10, &val);
+	if (ret)
+		return ret;
+
+	mutex_lock(&indio_dev->mlock);
+
+	t = (1638 / val);
+	if (t > 0)
+		t--;
+	t &= ADIS16300_SMPL_PRD_DIV_MASK;
+	if ((t & ADIS16300_SMPL_PRD_DIV_MASK) >= 0x0A)
+		st->us->max_speed_hz = ADIS16300_SPI_SLOW;
+	else
+		st->us->max_speed_hz = ADIS16300_SPI_FAST;
+
+	ret = adis16300_spi_write_reg_8(dev,
+			ADIS16300_SMPL_PRD,
+			t);
+
+	mutex_unlock(&indio_dev->mlock);
+
+	return ret ? ret : len;
+}
+
+static ssize_t adis16300_write_reset(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t len)
+{
+	if (len < 1)
+		return -1;
+	switch (buf[0]) {
+	case '1':
+	case 'y':
+	case 'Y':
+		return adis16300_reset(dev);
+	}
+	return -1;
+}
+
+
+
+int adis16300_set_irq(struct device *dev, bool enable)
+{
+	int ret;
+	u16 msc;
+	ret = adis16300_spi_read_reg_16(dev, ADIS16300_MSC_CTRL, &msc);
+	if (ret)
+		goto error_ret;
+
+	msc |= ADIS16300_MSC_CTRL_DATA_RDY_POL_HIGH;
+	msc &= ~ADIS16300_MSC_CTRL_DATA_RDY_DIO2;
+	if (enable)
+		msc |= ADIS16300_MSC_CTRL_DATA_RDY_EN;
+	else
+		msc &= ~ADIS16300_MSC_CTRL_DATA_RDY_EN;
+
+	ret = adis16300_spi_write_reg_16(dev, ADIS16300_MSC_CTRL, msc);
+	if (ret)
+		goto error_ret;
+
+error_ret:
+	return ret;
+}
+
+int adis16300_reset(struct device *dev)
+{
+	int ret;
+	ret = adis16300_spi_write_reg_8(dev,
+			ADIS16300_GLOB_CMD,
+			ADIS16300_GLOB_CMD_SW_RESET);
+	if (ret)
+		dev_err(dev, "problem resetting device");
+
+	return ret;
+}
+
+/* Power down the device */
+int adis16300_stop_device(struct device *dev)
+{
+	int ret;
+	u16 val = ADIS16300_SLP_CNT_POWER_OFF;
+
+	ret = adis16300_spi_write_reg_16(dev, ADIS16300_SLP_CNT, val);
+	if (ret)
+		dev_err(dev, "problem with turning device off: SLP_CNT");
+
+	return ret;
+}
+
+int adis16300_self_test(struct device *dev)
+{
+	int ret;
+	ret = adis16300_spi_write_reg_16(dev,
+			ADIS16300_MSC_CTRL,
+			ADIS16300_MSC_CTRL_MEM_TEST);
+	if (ret) {
+		dev_err(dev, "problem starting self test");
+		goto err_ret;
+	}
+
+	adis16300_check_status(dev);
+
+err_ret:
+	return ret;
+}
+
+int adis16300_check_status(struct device *dev)
+{
+	u16 status;
+	int ret;
+
+	ret = adis16300_spi_read_reg_16(dev, ADIS16300_DIAG_STAT, &status);
+
+	if (ret < 0) {
+		dev_err(dev, "Reading status failed\n");
+		goto error_ret;
+	}
+	ret = status;
+	if (status & ADIS16300_DIAG_STAT_ZACCL_FAIL)
+		dev_err(dev, "Z-axis accelerometer self-test failure\n");
+	if (status & ADIS16300_DIAG_STAT_YACCL_FAIL)
+		dev_err(dev, "Y-axis accelerometer self-test failure\n");
+	if (status & ADIS16300_DIAG_STAT_XACCL_FAIL)
+		dev_err(dev, "X-axis accelerometer self-test failure\n");
+	if (status & ADIS16300_DIAG_STAT_XGYRO_FAIL)
+		dev_err(dev, "X-axis gyroscope self-test failure\n");
+	if (status & ADIS16300_DIAG_STAT_ALARM2)
+		dev_err(dev, "Alarm 2 active\n");
+	if (status & ADIS16300_DIAG_STAT_ALARM1)
+		dev_err(dev, "Alarm 1 active\n");
+	if (status & ADIS16300_DIAG_STAT_FLASH_CHK)
+		dev_err(dev, "Flash checksum error\n");
+	if (status & ADIS16300_DIAG_STAT_SELF_TEST)
+		dev_err(dev, "Self test error\n");
+	if (status & ADIS16300_DIAG_STAT_OVERFLOW)
+		dev_err(dev, "Sensor overrange\n");
+	if (status & ADIS16300_DIAG_STAT_SPI_FAIL)
+		dev_err(dev, "SPI failure\n");
+	if (status & ADIS16300_DIAG_STAT_FLASH_UPT)
+		dev_err(dev, "Flash update failed\n");
+	if (status & ADIS16300_DIAG_STAT_POWER_HIGH)
+		dev_err(dev, "Power supply above 5.25V\n");
+	if (status & ADIS16300_DIAG_STAT_POWER_LOW)
+		dev_err(dev, "Power supply below 4.75V\n");
+
+error_ret:
+	return ret;
+}
+
+static int adis16300_initial_setup(struct adis16300_state *st)
+{
+	int ret;
+	u16 smp_prd;
+	struct device *dev = &st->indio_dev->dev;
+
+	/* use low spi speed for init */
+	st->us->max_speed_hz = ADIS16300_SPI_SLOW;
+	st->us->mode = SPI_MODE_3;
+	spi_setup(st->us);
+
+	/* Disable IRQ */
+	ret = adis16300_set_irq(dev, false);
+	if (ret) {
+		dev_err(dev, "disable irq failed");
+		goto err_ret;
+	}
+
+	/* Do self test */
+
+	/* Read status register to check the result */
+	ret = adis16300_check_status(dev);
+	if (ret) {
+		adis16300_reset(dev);
+		dev_err(dev, "device not playing ball -> reset");
+		msleep(ADIS16300_STARTUP_DELAY);
+		ret = adis16300_check_status(dev);
+		if (ret) {
+			dev_err(dev, "giving up");
+			goto err_ret;
+		}
+	}
+
+	printk(KERN_INFO DRIVER_NAME ": at CS%d (irq %d)\n",
+			st->us->chip_select, st->us->irq);
+
+	/* use high spi speed if possible */
+	ret = adis16300_spi_read_reg_16(dev, ADIS16300_SMPL_PRD, &smp_prd);
+	if (!ret && (smp_prd & ADIS16300_SMPL_PRD_DIV_MASK) < 0x0A) {
+		st->us->max_speed_hz = ADIS16300_SPI_SLOW;
+		spi_setup(st->us);
+	}
+
+err_ret:
+	return ret;
+}
+
+static IIO_DEV_ATTR_ACCEL_X_OFFSET(S_IWUSR | S_IRUGO,
+		adis16300_read_12bit_signed,
+		adis16300_write_16bit,
+		ADIS16300_XACCL_OFF);
+
+static IIO_DEV_ATTR_ACCEL_Y_OFFSET(S_IWUSR | S_IRUGO,
+		adis16300_read_12bit_signed,
+		adis16300_write_16bit,
+		ADIS16300_YACCL_OFF);
+
+static IIO_DEV_ATTR_ACCEL_Z_OFFSET(S_IWUSR | S_IRUGO,
+		adis16300_read_12bit_signed,
+		adis16300_write_16bit,
+		ADIS16300_ZACCL_OFF);
+
+static IIO_DEV_ATTR_IN_NAMED_RAW(supply, adis16300_read_14bit_signed,
+			   ADIS16300_SUPPLY_OUT);
+static IIO_CONST_ATTR(in_supply_scale, "0.00242");
+
+static IIO_DEV_ATTR_GYRO_X(adis16300_read_14bit_signed,
+		ADIS16300_XGYRO_OUT);
+static IIO_CONST_ATTR(gyro_scale, "0.05 deg/s");
+
+static IIO_DEV_ATTR_ACCEL_X(adis16300_read_14bit_signed,
+		ADIS16300_XACCL_OUT);
+static IIO_DEV_ATTR_ACCEL_Y(adis16300_read_14bit_signed,
+		ADIS16300_YACCL_OUT);
+static IIO_DEV_ATTR_ACCEL_Z(adis16300_read_14bit_signed,
+		ADIS16300_ZACCL_OUT);
+static IIO_CONST_ATTR(accel_scale, "0.0006 g");
+
+static IIO_DEV_ATTR_INCLI_X(adis16300_read_13bit_signed,
+		ADIS16300_XINCLI_OUT);
+static IIO_DEV_ATTR_INCLI_Y(adis16300_read_13bit_signed,
+		ADIS16300_YINCLI_OUT);
+static IIO_CONST_ATTR(incli_scale, "0.044 d");
+
+static IIO_DEV_ATTR_TEMP(adis16300_read_12bit_signed);
+static IIO_CONST_ATTR(temp_offset, "198.16 K");
+static IIO_CONST_ATTR(temp_scale, "0.14 K");
+
+static IIO_DEV_ATTR_IN_RAW(0, adis16300_read_12bit_unsigned,
+		ADIS16300_AUX_ADC);
+static IIO_CONST_ATTR(in0_scale, "0.000806");
+
+static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
+		adis16300_read_frequency,
+		adis16300_write_frequency);
+
+static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16300_write_reset, 0);
+
+static IIO_CONST_ATTR_AVAIL_SAMP_FREQ("409 546 819 1638");
+
+static IIO_CONST_ATTR(name, "adis16300");
+
+static struct attribute *adis16300_event_attributes[] = {
+	NULL
+};
+
+static struct attribute_group adis16300_event_attribute_group = {
+	.attrs = adis16300_event_attributes,
+};
+
+static struct attribute *adis16300_attributes[] = {
+	&iio_dev_attr_accel_x_offset.dev_attr.attr,
+	&iio_dev_attr_accel_y_offset.dev_attr.attr,
+	&iio_dev_attr_accel_z_offset.dev_attr.attr,
+	&iio_dev_attr_in_supply_raw.dev_attr.attr,
+	&iio_const_attr_in_supply_scale.dev_attr.attr,
+	&iio_dev_attr_gyro_x.dev_attr.attr,
+	&iio_const_attr_gyro_scale.dev_attr.attr,
+	&iio_dev_attr_accel_x_raw.dev_attr.attr,
+	&iio_dev_attr_accel_y_raw.dev_attr.attr,
+	&iio_dev_attr_accel_z_raw.dev_attr.attr,
+	&iio_const_attr_accel_scale.dev_attr.attr,
+	&iio_dev_attr_incli_x.dev_attr.attr,
+	&iio_dev_attr_incli_y.dev_attr.attr,
+	&iio_const_attr_incli_scale.dev_attr.attr,
+	&iio_dev_attr_temp.dev_attr.attr,
+	&iio_const_attr_temp_offset.dev_attr.attr,
+	&iio_const_attr_temp_scale.dev_attr.attr,
+	&iio_dev_attr_in0_raw.dev_attr.attr,
+	&iio_const_attr_in0_scale.dev_attr.attr,
+	&iio_dev_attr_sampling_frequency.dev_attr.attr,
+	&iio_const_attr_available_sampling_frequency.dev_attr.attr,
+	&iio_dev_attr_reset.dev_attr.attr,
+	&iio_const_attr_name.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group adis16300_attribute_group = {
+	.attrs = adis16300_attributes,
+};
+
+static int __devinit adis16300_probe(struct spi_device *spi)
+{
+	int ret, regdone = 0;
+	struct adis16300_state *st = kzalloc(sizeof *st, GFP_KERNEL);
+	if (!st) {
+		ret =  -ENOMEM;
+		goto error_ret;
+	}
+	/* this is only used for removal purposes */
+	spi_set_drvdata(spi, st);
+
+	/* Allocate the comms buffers */
+	st->rx = kzalloc(sizeof(*st->rx)*ADIS16300_MAX_RX, GFP_KERNEL);
+	if (st->rx == NULL) {
+		ret = -ENOMEM;
+		goto error_free_st;
+	}
+	st->tx = kzalloc(sizeof(*st->tx)*ADIS16300_MAX_TX, GFP_KERNEL);
+	if (st->tx == NULL) {
+		ret = -ENOMEM;
+		goto error_free_rx;
+	}
+	st->us = spi;
+	mutex_init(&st->buf_lock);
+	/* setup the industrialio driver allocated elements */
+	st->indio_dev = iio_allocate_device();
+	if (st->indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_free_tx;
+	}
+
+	st->indio_dev->dev.parent = &spi->dev;
+	st->indio_dev->num_interrupt_lines = 1;
+	st->indio_dev->event_attrs = &adis16300_event_attribute_group;
+	st->indio_dev->attrs = &adis16300_attribute_group;
+	st->indio_dev->dev_data = (void *)(st);
+	st->indio_dev->driver_module = THIS_MODULE;
+	st->indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = adis16300_configure_ring(st->indio_dev);
+	if (ret)
+		goto error_free_dev;
+
+	ret = iio_device_register(st->indio_dev);
+	if (ret)
+		goto error_unreg_ring_funcs;
+	regdone = 1;
+
+	ret = adis16300_initialize_ring(st->indio_dev->ring);
+	if (ret) {
+		printk(KERN_ERR "failed to initialize the ring\n");
+		goto error_unreg_ring_funcs;
+	}
+
+	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) {
+#if 0 /* fixme: here we should support */
+		iio_init_work_cont(&st->work_cont_thresh,
+				NULL,
+				adis16300_thresh_handler_bh_no_check,
+				0,
+				0,
+				st);
+#endif
+		ret = iio_register_interrupt_line(spi->irq,
+				st->indio_dev,
+				0,
+				IRQF_TRIGGER_RISING,
+				"adis16300");
+		if (ret)
+			goto error_uninitialize_ring;
+
+		ret = adis16300_probe_trigger(st->indio_dev);
+		if (ret)
+			goto error_unregister_line;
+	}
+
+	/* Get the device into a sane initial state */
+	ret = adis16300_initial_setup(st);
+	if (ret)
+		goto error_remove_trigger;
+	return 0;
+
+error_remove_trigger:
+	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
+		adis16300_remove_trigger(st->indio_dev);
+error_unregister_line:
+	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
+		iio_unregister_interrupt_line(st->indio_dev, 0);
+error_uninitialize_ring:
+	adis16300_uninitialize_ring(st->indio_dev->ring);
+error_unreg_ring_funcs:
+	adis16300_unconfigure_ring(st->indio_dev);
+error_free_dev:
+	if (regdone)
+		iio_device_unregister(st->indio_dev);
+	else
+		iio_free_device(st->indio_dev);
+error_free_tx:
+	kfree(st->tx);
+error_free_rx:
+	kfree(st->rx);
+error_free_st:
+	kfree(st);
+error_ret:
+	return ret;
+}
+
+/* fixme, confirm ordering in this function */
+static int adis16300_remove(struct spi_device *spi)
+{
+	int ret;
+	struct adis16300_state *st = spi_get_drvdata(spi);
+	struct iio_dev *indio_dev = st->indio_dev;
+
+	ret = adis16300_stop_device(&(indio_dev->dev));
+	if (ret)
+		goto err_ret;
+
+	flush_scheduled_work();
+
+	adis16300_remove_trigger(indio_dev);
+	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
+		iio_unregister_interrupt_line(indio_dev, 0);
+
+	adis16300_uninitialize_ring(indio_dev->ring);
+	adis16300_unconfigure_ring(indio_dev);
+	iio_device_unregister(indio_dev);
+	kfree(st->tx);
+	kfree(st->rx);
+	kfree(st);
+
+	return 0;
+
+err_ret:
+	return ret;
+}
+
+static struct spi_driver adis16300_driver = {
+	.driver = {
+		.name = "adis16300",
+		.owner = THIS_MODULE,
+	},
+	.probe = adis16300_probe,
+	.remove = __devexit_p(adis16300_remove),
+};
+
+static __init int adis16300_init(void)
+{
+	return spi_register_driver(&adis16300_driver);
+}
+module_init(adis16300_init);
+
+static __exit void adis16300_exit(void)
+{
+	spi_unregister_driver(&adis16300_driver);
+}
+module_exit(adis16300_exit);
+
+MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
+MODULE_DESCRIPTION("Analog Devices ADIS16300 IMU SPI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/imu/adis16300_ring.c b/drivers/staging/iio/imu/adis16300_ring.c
new file mode 100644
index 0000000..76cf8a6
--- /dev/null
+++ b/drivers/staging/iio/imu/adis16300_ring.c
@@ -0,0 +1,233 @@
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/sysfs.h>
+#include <linux/list.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "../ring_sw.h"
+#include "../accel/accel.h"
+#include "../trigger.h"
+#include "adis16300.h"
+
+/**
+ * combine_8_to_16() utility function to munge to u8s into u16
+ **/
+static inline u16 combine_8_to_16(u8 lower, u8 upper)
+{
+	u16 _lower = lower;
+	u16 _upper = upper;
+	return _lower | (_upper << 8);
+}
+
+static IIO_SCAN_EL_C(supply, ADIS16300_SCAN_SUPPLY, IIO_SIGNED(14),
+		     ADIS16300_SUPPLY_OUT, NULL);
+
+static IIO_SCAN_EL_C(gyro_x, ADIS16300_SCAN_GYRO_X, IIO_SIGNED(14),
+		     ADIS16300_XGYRO_OUT, NULL);
+
+static IIO_SCAN_EL_C(accel_x, ADIS16300_SCAN_ACC_X, IIO_SIGNED(14),
+		     ADIS16300_XACCL_OUT, NULL);
+static IIO_SCAN_EL_C(accel_y, ADIS16300_SCAN_ACC_Y, IIO_SIGNED(14),
+		     ADIS16300_YACCL_OUT, NULL);
+static IIO_SCAN_EL_C(accel_z, ADIS16300_SCAN_ACC_Z, IIO_SIGNED(14),
+		     ADIS16300_ZACCL_OUT, NULL);
+
+static IIO_SCAN_EL_C(temp, ADIS16300_SCAN_TEMP, IIO_SIGNED(12),
+		     ADIS16300_TEMP_OUT, NULL);
+static IIO_SCAN_EL_C(adc_0, ADIS16300_SCAN_ADC_0, IIO_SIGNED(12),
+		     ADIS16300_AUX_ADC, NULL);
+
+static IIO_SCAN_EL_C(incli_x, ADIS16300_SCAN_INCLI_X, IIO_SIGNED(12),
+		     ADIS16300_XINCLI_OUT, NULL);
+static IIO_SCAN_EL_C(incli_y, ADIS16300_SCAN_INCLI_Y, IIO_SIGNED(12),
+		     ADIS16300_YINCLI_OUT, NULL);
+
+static IIO_SCAN_EL_TIMESTAMP(9);
+
+static struct attribute *adis16300_scan_el_attrs[] = {
+	&iio_scan_el_supply.dev_attr.attr,
+	&iio_scan_el_gyro_x.dev_attr.attr,
+	&iio_scan_el_temp.dev_attr.attr,
+	&iio_scan_el_accel_x.dev_attr.attr,
+	&iio_scan_el_accel_y.dev_attr.attr,
+	&iio_scan_el_accel_z.dev_attr.attr,
+	&iio_scan_el_incli_x.dev_attr.attr,
+	&iio_scan_el_incli_y.dev_attr.attr,
+	&iio_scan_el_adc_0.dev_attr.attr,
+	&iio_scan_el_timestamp.dev_attr.attr,
+	NULL,
+};
+
+static struct attribute_group adis16300_scan_el_group = {
+	.attrs = adis16300_scan_el_attrs,
+	.name = "scan_elements",
+};
+
+/**
+ * adis16300_poll_func_th() top half interrupt handler called by trigger
+ * @private_data:	iio_dev
+ **/
+static void adis16300_poll_func_th(struct iio_dev *indio_dev)
+{
+	struct adis16300_state *st = iio_dev_get_devdata(indio_dev);
+	st->last_timestamp = indio_dev->trig->timestamp;
+	schedule_work(&st->work_trigger_to_ring);
+	/* Indicate that this interrupt is being handled */
+
+	/* Technically this is trigger related, but without this
+	 * handler running there is currently no way for the interrupt
+	 * to clear.
+	 */
+}
+
+/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
+ * specific to be rolled into the core.
+ */
+static void adis16300_trigger_bh_to_ring(struct work_struct *work_s)
+{
+	struct adis16300_state *st
+		= container_of(work_s, struct adis16300_state,
+			       work_trigger_to_ring);
+
+	int i = 0;
+	s16 *data;
+	size_t datasize = st->indio_dev
+		->ring->access.get_bpd(st->indio_dev->ring);
+
+	data = kmalloc(datasize , GFP_KERNEL);
+	if (data == NULL) {
+		dev_err(&st->us->dev, "memory alloc failed in ring bh");
+		return;
+	}
+
+	if (st->indio_dev->scan_count)
+		if (adis16300_spi_read_burst(&st->indio_dev->dev, st->rx) >= 0)
+			for (; i < st->indio_dev->scan_count; i++) {
+				data[i] = combine_8_to_16(st->rx[i*2+1],
+							  st->rx[i*2]);
+			}
+
+	/* Guaranteed to be aligned with 8 byte boundary */
+	if (st->indio_dev->scan_timestamp)
+		*((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
+
+	st->indio_dev->ring->access.store_to(st->indio_dev->ring,
+					    (u8 *)data,
+					    st->last_timestamp);
+
+	iio_trigger_notify_done(st->indio_dev->trig);
+	kfree(data);
+
+	return;
+}
+/* in these circumstances is it better to go with unaligned packing and
+ * deal with the cost?*/
+static int adis16300_data_rdy_ring_preenable(struct iio_dev *indio_dev)
+{
+	size_t size;
+	dev_dbg(&indio_dev->dev, "%s\n", __func__);
+	/* Check if there are any scan elements enabled, if not fail*/
+	if (!(indio_dev->scan_count || indio_dev->scan_timestamp))
+		return -EINVAL;
+
+	if (indio_dev->ring->access.set_bpd) {
+		if (indio_dev->scan_timestamp)
+			if (indio_dev->scan_count) /* Timestamp and data */
+				size = 4*sizeof(s64);
+			else /* Timestamp only  */
+				size = sizeof(s64);
+		else /* Data only */
+			size = indio_dev->scan_count*sizeof(s16);
+		indio_dev->ring->access.set_bpd(indio_dev->ring, size);
+	}
+
+	return 0;
+}
+
+static int adis16300_data_rdy_ring_postenable(struct iio_dev *indio_dev)
+{
+	return indio_dev->trig
+		? iio_trigger_attach_poll_func(indio_dev->trig,
+					       indio_dev->pollfunc)
+		: 0;
+}
+
+static int adis16300_data_rdy_ring_predisable(struct iio_dev *indio_dev)
+{
+	return indio_dev->trig
+		? iio_trigger_dettach_poll_func(indio_dev->trig,
+						indio_dev->pollfunc)
+		: 0;
+}
+
+void adis16300_unconfigure_ring(struct iio_dev *indio_dev)
+{
+	kfree(indio_dev->pollfunc);
+	iio_sw_rb_free(indio_dev->ring);
+}
+
+int adis16300_configure_ring(struct iio_dev *indio_dev)
+{
+	int ret = 0;
+	struct adis16300_state *st = indio_dev->dev_data;
+	struct iio_ring_buffer *ring;
+	INIT_WORK(&st->work_trigger_to_ring, adis16300_trigger_bh_to_ring);
+	/* Set default scan mode */
+
+	iio_scan_mask_set(indio_dev, iio_scan_el_supply.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_gyro_x.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_accel_x.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_accel_y.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_accel_z.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_temp.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_adc_0.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_incli_x.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_incli_y.number);
+	indio_dev->scan_timestamp = true;
+
+	indio_dev->scan_el_attrs = &adis16300_scan_el_group;
+
+	ring = iio_sw_rb_allocate(indio_dev);
+	if (!ring) {
+		ret = -ENOMEM;
+		return ret;
+	}
+	indio_dev->ring = ring;
+	/* Effectively select the ring buffer implementation */
+	iio_ring_sw_register_funcs(&ring->access);
+	ring->preenable = &adis16300_data_rdy_ring_preenable;
+	ring->postenable = &adis16300_data_rdy_ring_postenable;
+	ring->predisable = &adis16300_data_rdy_ring_predisable;
+	ring->owner = THIS_MODULE;
+
+	indio_dev->pollfunc = kzalloc(sizeof(*indio_dev->pollfunc), GFP_KERNEL);
+	if (indio_dev->pollfunc == NULL) {
+		ret = -ENOMEM;
+		goto error_iio_sw_rb_free;;
+	}
+	indio_dev->pollfunc->poll_func_main = &adis16300_poll_func_th;
+	indio_dev->pollfunc->private_data = indio_dev;
+	indio_dev->modes |= INDIO_RING_TRIGGERED;
+	return 0;
+
+error_iio_sw_rb_free:
+	iio_sw_rb_free(indio_dev->ring);
+	return ret;
+}
+
+int adis16300_initialize_ring(struct iio_ring_buffer *ring)
+{
+	return iio_ring_buffer_register(ring, 0);
+}
+
+void adis16300_uninitialize_ring(struct iio_ring_buffer *ring)
+{
+	iio_ring_buffer_unregister(ring);
+}
diff --git a/drivers/staging/iio/imu/adis16300_trigger.c b/drivers/staging/iio/imu/adis16300_trigger.c
new file mode 100644
index 0000000..54edb20
--- /dev/null
+++ b/drivers/staging/iio/imu/adis16300_trigger.c
@@ -0,0 +1,127 @@
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/sysfs.h>
+#include <linux/list.h>
+#include <linux/spi/spi.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "../trigger.h"
+#include "adis16300.h"
+
+/**
+ * adis16300_data_rdy_trig_poll() the event handler for the data rdy trig
+ **/
+static int adis16300_data_rdy_trig_poll(struct iio_dev *dev_info,
+				       int index,
+				       s64 timestamp,
+				       int no_test)
+{
+	struct adis16300_state *st = iio_dev_get_devdata(dev_info);
+	struct iio_trigger *trig = st->trig;
+
+	trig->timestamp = timestamp;
+	iio_trigger_poll(trig);
+
+	return IRQ_HANDLED;
+}
+
+IIO_EVENT_SH(data_rdy_trig, &adis16300_data_rdy_trig_poll);
+
+static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
+
+static struct attribute *adis16300_trigger_attrs[] = {
+	&dev_attr_name.attr,
+	NULL,
+};
+
+static const struct attribute_group adis16300_trigger_attr_group = {
+	.attrs = adis16300_trigger_attrs,
+};
+
+/**
+ * adis16300_data_rdy_trigger_set_state() set datardy interrupt state
+ **/
+static int adis16300_data_rdy_trigger_set_state(struct iio_trigger *trig,
+						bool state)
+{
+	struct adis16300_state *st = trig->private_data;
+	struct iio_dev *indio_dev = st->indio_dev;
+	int ret = 0;
+
+	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
+	ret = adis16300_set_irq(&st->indio_dev->dev, state);
+	if (state == false) {
+		iio_remove_event_from_list(&iio_event_data_rdy_trig,
+					   &indio_dev->interrupts[0]
+					   ->ev_list);
+		/* possible quirk with handler currently worked around
+		   by ensuring the work queue is empty */
+		flush_scheduled_work();
+	} else {
+		iio_add_event_to_list(&iio_event_data_rdy_trig,
+				      &indio_dev->interrupts[0]->ev_list);
+	}
+	return ret;
+}
+
+/**
+ * adis16300_trig_try_reen() try renabling irq for data rdy trigger
+ * @trig:	the datardy trigger
+ **/
+static int adis16300_trig_try_reen(struct iio_trigger *trig)
+{
+	struct adis16300_state *st = trig->private_data;
+	enable_irq(st->us->irq);
+	/* irq reenabled so success! */
+	return 0;
+}
+
+int adis16300_probe_trigger(struct iio_dev *indio_dev)
+{
+	int ret;
+	struct adis16300_state *st = indio_dev->dev_data;
+
+	st->trig = iio_allocate_trigger();
+	st->trig->name = kmalloc(IIO_TRIGGER_NAME_LENGTH, GFP_KERNEL);
+	if (!st->trig->name) {
+		ret = -ENOMEM;
+		goto error_free_trig;
+	}
+	snprintf((char *)st->trig->name,
+		 IIO_TRIGGER_NAME_LENGTH,
+		 "adis16300-dev%d", indio_dev->id);
+	st->trig->dev.parent = &st->us->dev;
+	st->trig->owner = THIS_MODULE;
+	st->trig->private_data = st;
+	st->trig->set_trigger_state = &adis16300_data_rdy_trigger_set_state;
+	st->trig->try_reenable = &adis16300_trig_try_reen;
+	st->trig->control_attrs = &adis16300_trigger_attr_group;
+	ret = iio_trigger_register(st->trig);
+
+	/* select default trigger */
+	indio_dev->trig = st->trig;
+	if (ret)
+		goto error_free_trig_name;
+
+	return 0;
+
+error_free_trig_name:
+	kfree(st->trig->name);
+error_free_trig:
+	iio_free_trigger(st->trig);
+
+	return ret;
+}
+
+void adis16300_remove_trigger(struct iio_dev *indio_dev)
+{
+	struct adis16300_state *state = indio_dev->dev_data;
+
+	iio_trigger_unregister(state->trig);
+	kfree(state->trig->name);
+	iio_free_trigger(state->trig);
+}
-- 
1.6.4.4


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

* [PATCH 20/20] staging:iio:imu ADIS16400 and ADIS16405 driver
  2010-05-04 13:43                                     ` [PATCH 19/20] staging:iio:imu ADIS16300 driver Jonathan Cameron
@ 2010-05-04 13:43                                       ` Jonathan Cameron
  0 siblings, 0 replies; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 13:43 UTC (permalink / raw)
  To: gregkh; +Cc: linux-iio, Barry Song, Manuel Stahl

From: Barry Song <Barry.Song@analog.com>

Signed-off-by: Manuel Stahl <manuel.stahl@iis.fraunhofer.de>
Signed-off-by: Barry Song <Barry.Song@analog.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/imu/Kconfig             |   10 +
 drivers/staging/iio/imu/Makefile            |    4 +
 drivers/staging/iio/imu/adis16400.h         |  238 ++++++++
 drivers/staging/iio/imu/adis16400_core.c    |  849 +++++++++++++++++++++++++++
 drivers/staging/iio/imu/adis16400_ring.c    |  245 ++++++++
 drivers/staging/iio/imu/adis16400_trigger.c |  127 ++++
 drivers/staging/iio/magnetometer/magnet.h   |   31 +
 7 files changed, 1504 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/iio/imu/Kconfig b/drivers/staging/iio/imu/Kconfig
index 3fe4716..411804f 100644
--- a/drivers/staging/iio/imu/Kconfig
+++ b/drivers/staging/iio/imu/Kconfig
@@ -12,3 +12,13 @@ config ADIS16300
 	help
 	  Say yes here to build support for Analog Devices adis16300 four degrees
 	  of freedom inertial sensor.
+
+config ADIS16400
+	tristate "Analog Devices ADIS16400/5 IMU SPI driver"
+ 	depends on SPI
+	select IIO_SW_RING
+	select IIO_RING_BUFFER
+	select IIO_TRIGGER
+ 	help
+ 	  Say yes here to build support for Analog Devices adis16400/5 triaxial
+ 	  inertial sensor with Magnetometer.
\ No newline at end of file
diff --git a/drivers/staging/iio/imu/Makefile b/drivers/staging/iio/imu/Makefile
index 4cd5984..de454dd 100644
--- a/drivers/staging/iio/imu/Makefile
+++ b/drivers/staging/iio/imu/Makefile
@@ -4,3 +4,7 @@
 adis16300-y             := adis16300_core.o
 adis16300-$(CONFIG_IIO_RING_BUFFER) += adis16300_ring.o adis16300_trigger.o
 obj-$(CONFIG_ADIS16300) += adis16300.o
+
+adis16400-y             := adis16400_core.o
+adis16400-$(CONFIG_IIO_RING_BUFFER) += adis16400_ring.o adis16400_trigger.o
+obj-$(CONFIG_ADIS16400) += adis16400.o
\ No newline at end of file
diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h
new file mode 100644
index 0000000..a8062f6
--- /dev/null
+++ b/drivers/staging/iio/imu/adis16400.h
@@ -0,0 +1,238 @@
+/*
+ * adis16400.h	support Analog Devices ADIS16400
+ *		3d 18g accelerometers,
+ *		3d gyroscopes,
+ *		3d 2.5gauss magnetometers via SPI
+ *
+ * Copyright (c) 2009 Manuel Stahl <manuel.stahl@iis.fraunhofer.de>
+ * Copyright (c) 2007 Jonathan Cameron <jic23@cam.ac.uk>
+ *
+ * Loosely based upon lis3l02dq.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef SPI_ADIS16400_H_
+#define SPI_ADIS16400_H_
+
+#define ADIS16400_STARTUP_DELAY	220 /* ms */
+
+#define ADIS16400_READ_REG(a)    a
+#define ADIS16400_WRITE_REG(a) ((a) | 0x80)
+
+#define ADIS16400_FLASH_CNT  0x00 /* Flash memory write count */
+#define ADIS16400_SUPPLY_OUT 0x02 /* Power supply measurement */
+#define ADIS16400_XGYRO_OUT 0x04 /* X-axis gyroscope output */
+#define ADIS16400_YGYRO_OUT 0x06 /* Y-axis gyroscope output */
+#define ADIS16400_ZGYRO_OUT 0x08 /* Z-axis gyroscope output */
+#define ADIS16400_XACCL_OUT 0x0A /* X-axis accelerometer output */
+#define ADIS16400_YACCL_OUT 0x0C /* Y-axis accelerometer output */
+#define ADIS16400_ZACCL_OUT 0x0E /* Z-axis accelerometer output */
+#define ADIS16400_XMAGN_OUT 0x10 /* X-axis magnetometer measurement */
+#define ADIS16400_YMAGN_OUT 0x12 /* Y-axis magnetometer measurement */
+#define ADIS16400_ZMAGN_OUT 0x14 /* Z-axis magnetometer measurement */
+#define ADIS16400_TEMP_OUT  0x16 /* Temperature output */
+#define ADIS16400_AUX_ADC   0x18 /* Auxiliary ADC measurement */
+
+/* Calibration parameters */
+#define ADIS16400_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */
+#define ADIS16400_YGYRO_OFF 0x1C /* Y-axis gyroscope bias offset factor */
+#define ADIS16400_ZGYRO_OFF 0x1E /* Z-axis gyroscope bias offset factor */
+#define ADIS16400_XACCL_OFF 0x20 /* X-axis acceleration bias offset factor */
+#define ADIS16400_YACCL_OFF 0x22 /* Y-axis acceleration bias offset factor */
+#define ADIS16400_ZACCL_OFF 0x24 /* Z-axis acceleration bias offset factor */
+#define ADIS16400_XMAGN_HIF 0x26 /* X-axis magnetometer, hard-iron factor */
+#define ADIS16400_YMAGN_HIF 0x28 /* Y-axis magnetometer, hard-iron factor */
+#define ADIS16400_ZMAGN_HIF 0x2A /* Z-axis magnetometer, hard-iron factor */
+#define ADIS16400_XMAGN_SIF 0x2C /* X-axis magnetometer, soft-iron factor */
+#define ADIS16400_YMAGN_SIF 0x2E /* Y-axis magnetometer, soft-iron factor */
+#define ADIS16400_ZMAGN_SIF 0x30 /* Z-axis magnetometer, soft-iron factor */
+
+#define ADIS16400_GPIO_CTRL 0x32 /* Auxiliary digital input/output control */
+#define ADIS16400_MSC_CTRL  0x34 /* Miscellaneous control */
+#define ADIS16400_SMPL_PRD  0x36 /* Internal sample period (rate) control */
+#define ADIS16400_SENS_AVG  0x38 /* Dynamic range and digital filter control */
+#define ADIS16400_SLP_CNT   0x3A /* Sleep mode control */
+#define ADIS16400_DIAG_STAT 0x3C /* System status */
+
+/* Alarm functions */
+#define ADIS16400_GLOB_CMD  0x3E /* System command */
+#define ADIS16400_ALM_MAG1  0x40 /* Alarm 1 amplitude threshold */
+#define ADIS16400_ALM_MAG2  0x42 /* Alarm 2 amplitude threshold */
+#define ADIS16400_ALM_SMPL1 0x44 /* Alarm 1 sample size */
+#define ADIS16400_ALM_SMPL2 0x46 /* Alarm 2 sample size */
+#define ADIS16400_ALM_CTRL  0x48 /* Alarm control */
+#define ADIS16400_AUX_DAC   0x4A /* Auxiliary DAC data */
+
+#define ADIS16400_PRODUCT_ID 0x56 /* Product identifier */
+#define ADIS16400_PRODUCT_ID_DEFAULT 0x4015	/* Datasheet says 0x4105, I get 0x4015 */
+
+#define ADIS16400_ERROR_ACTIVE			(1<<14)
+#define ADIS16400_NEW_DATA			(1<<14)
+
+/* MSC_CTRL */
+#define ADIS16400_MSC_CTRL_MEM_TEST		(1<<11)
+#define ADIS16400_MSC_CTRL_INT_SELF_TEST	(1<<10)
+#define ADIS16400_MSC_CTRL_NEG_SELF_TEST	(1<<9)
+#define ADIS16400_MSC_CTRL_POS_SELF_TEST	(1<<8)
+#define ADIS16400_MSC_CTRL_GYRO_BIAS		(1<<7)
+#define ADIS16400_MSC_CTRL_ACCL_ALIGN		(1<<6)
+#define ADIS16400_MSC_CTRL_DATA_RDY_EN		(1<<2)
+#define ADIS16400_MSC_CTRL_DATA_RDY_POL_HIGH	(1<<1)
+#define ADIS16400_MSC_CTRL_DATA_RDY_DIO2	(1<<0)
+
+/* SMPL_PRD */
+#define ADIS16400_SMPL_PRD_TIME_BASE	(1<<7)
+#define ADIS16400_SMPL_PRD_DIV_MASK	0x7F
+
+/* DIAG_STAT */
+#define ADIS16400_DIAG_STAT_ZACCL_FAIL	(1<<15)
+#define ADIS16400_DIAG_STAT_YACCL_FAIL	(1<<14)
+#define ADIS16400_DIAG_STAT_XACCL_FAIL	(1<<13)
+#define ADIS16400_DIAG_STAT_XGYRO_FAIL	(1<<12)
+#define ADIS16400_DIAG_STAT_YGYRO_FAIL	(1<<11)
+#define ADIS16400_DIAG_STAT_ZGYRO_FAIL	(1<<10)
+#define ADIS16400_DIAG_STAT_ALARM2	(1<<9)
+#define ADIS16400_DIAG_STAT_ALARM1	(1<<8)
+#define ADIS16400_DIAG_STAT_FLASH_CHK	(1<<6)
+#define ADIS16400_DIAG_STAT_SELF_TEST	(1<<5)
+#define ADIS16400_DIAG_STAT_OVERFLOW	(1<<4)
+#define ADIS16400_DIAG_STAT_SPI_FAIL	(1<<3)
+#define ADIS16400_DIAG_STAT_FLASH_UPT	(1<<2)
+#define ADIS16400_DIAG_STAT_POWER_HIGH	(1<<1)
+#define ADIS16400_DIAG_STAT_POWER_LOW	(1<<0)
+
+/* GLOB_CMD */
+#define ADIS16400_GLOB_CMD_SW_RESET	(1<<7)
+#define ADIS16400_GLOB_CMD_P_AUTO_NULL	(1<<4)
+#define ADIS16400_GLOB_CMD_FLASH_UPD	(1<<3)
+#define ADIS16400_GLOB_CMD_DAC_LATCH	(1<<2)
+#define ADIS16400_GLOB_CMD_FAC_CALIB	(1<<1)
+#define ADIS16400_GLOB_CMD_AUTO_NULL	(1<<0)
+
+/* SLP_CNT */
+#define ADIS16400_SLP_CNT_POWER_OFF	(1<<8)
+
+#define ADIS16400_MAX_TX 24
+#define ADIS16400_MAX_RX 24
+
+#define ADIS16400_SPI_SLOW	(u32)(300 * 1000)
+#define ADIS16400_SPI_BURST	(u32)(1000 * 1000)
+#define ADIS16400_SPI_FAST	(u32)(2000 * 1000)
+
+/**
+ * struct adis16400_state - device instance specific data
+ * @us:			actual spi_device
+ * @work_trigger_to_ring: bh for triggered event handling
+ * @work_cont_thresh: CLEAN
+ * @inter:		used to check if new interrupt has been triggered
+ * @last_timestamp:	passing timestamp from th to bh of interrupt handler
+ * @indio_dev:		industrial I/O device structure
+ * @trig:		data ready trigger registered with iio
+ * @tx:			transmit buffer
+ * @rx:			recieve buffer
+ * @buf_lock:		mutex to protect tx and rx
+ **/
+struct adis16400_state {
+	struct spi_device		*us;
+	struct work_struct		work_trigger_to_ring;
+	struct iio_work_cont		work_cont_thresh;
+	s64				last_timestamp;
+	struct iio_dev			*indio_dev;
+	struct iio_trigger		*trig;
+	u8				*tx;
+	u8				*rx;
+	struct mutex			buf_lock;
+};
+
+int adis16400_spi_write_reg_8(struct device *dev,
+			      u8 reg_address,
+			      u8 val);
+
+int adis16400_spi_read_burst(struct device *dev, u8 *rx);
+
+int adis16400_spi_read_sequence(struct device *dev,
+				      u8 *tx, u8 *rx, int num);
+
+int adis16400_set_irq(struct device *dev, bool enable);
+
+int adis16400_reset(struct device *dev);
+
+int adis16400_stop_device(struct device *dev);
+
+int adis16400_check_status(struct device *dev);
+
+#ifdef CONFIG_IIO_RING_BUFFER
+/* At the moment triggers are only used for ring buffer
+ * filling. This may change!
+ */
+
+enum adis16400_scan {
+	ADIS16400_SCAN_SUPPLY,
+	ADIS16400_SCAN_GYRO_X,
+	ADIS16400_SCAN_GYRO_Y,
+	ADIS16400_SCAN_GYRO_Z,
+	ADIS16400_SCAN_ACC_X,
+	ADIS16400_SCAN_ACC_Y,
+	ADIS16400_SCAN_ACC_Z,
+	ADIS16400_SCAN_MAGN_X,
+	ADIS16400_SCAN_MAGN_Y,
+	ADIS16400_SCAN_MAGN_Z,
+	ADIS16400_SCAN_TEMP,
+	ADIS16400_SCAN_ADC_0
+};
+
+void adis16400_remove_trigger(struct iio_dev *indio_dev);
+int adis16400_probe_trigger(struct iio_dev *indio_dev);
+
+ssize_t adis16400_read_data_from_ring(struct device *dev,
+				      struct device_attribute *attr,
+				      char *buf);
+
+
+int adis16400_configure_ring(struct iio_dev *indio_dev);
+void adis16400_unconfigure_ring(struct iio_dev *indio_dev);
+
+int adis16400_initialize_ring(struct iio_ring_buffer *ring);
+void adis16400_uninitialize_ring(struct iio_ring_buffer *ring);
+#else /* CONFIG_IIO_RING_BUFFER */
+
+static inline void adis16400_remove_trigger(struct iio_dev *indio_dev)
+{
+}
+
+static inline int adis16400_probe_trigger(struct iio_dev *indio_dev)
+{
+	return 0;
+}
+
+static inline ssize_t
+adis16400_read_data_from_ring(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	return 0;
+}
+
+static int adis16400_configure_ring(struct iio_dev *indio_dev)
+{
+	return 0;
+}
+
+static inline void adis16400_unconfigure_ring(struct iio_dev *indio_dev)
+{
+}
+
+static inline int adis16400_initialize_ring(struct iio_ring_buffer *ring)
+{
+	return 0;
+}
+
+static inline void adis16400_uninitialize_ring(struct iio_ring_buffer *ring)
+{
+}
+
+#endif /* CONFIG_IIO_RING_BUFFER */
+#endif /* SPI_ADIS16400_H_ */
diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
new file mode 100644
index 0000000..27e4a73
--- /dev/null
+++ b/drivers/staging/iio/imu/adis16400_core.c
@@ -0,0 +1,849 @@
+/*
+ * adis16400.c	support Analog Devices ADIS16400/5
+ *		3d 2g Linear Accelerometers,
+ *		3d Gyroscopes,
+ *		3d Magnetometers via SPI
+ *
+ * Copyright (c) 2009 Manuel Stahl <manuel.stahl@iis.fraunhofer.de>
+ * Copyright (c) 2007 Jonathan Cameron <jic23@cam.ac.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+
+#include <linux/sysfs.h>
+#include <linux/list.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "../accel/accel.h"
+#include "../adc/adc.h"
+#include "../gyro/gyro.h"
+#include "../magnetometer/magnet.h"
+
+#include "adis16400.h"
+
+#define DRIVER_NAME		"adis16400"
+
+/* At the moment the spi framework doesn't allow global setting of cs_change.
+ * It's in the likely to be added comment at the top of spi.h.
+ * This means that use cannot be made of spi_write etc.
+ */
+
+/**
+ * adis16400_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
+ **/
+int adis16400_spi_write_reg_8(struct device *dev,
+		u8 reg_address,
+		u8 val)
+{
+	int ret;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct adis16400_state *st = iio_dev_get_devdata(indio_dev);
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = ADIS16400_WRITE_REG(reg_address);
+	st->tx[1] = val;
+
+	ret = spi_write(st->us, st->tx, 2);
+	mutex_unlock(&st->buf_lock);
+
+	return ret;
+}
+
+/**
+ * adis16400_spi_write_reg_16() - write 2 bytes to a pair of registers
+ * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @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 adis16400_spi_write_reg_16(struct device *dev,
+		u8 lower_reg_address,
+		u16 value)
+{
+	int ret;
+	struct spi_message msg;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct adis16400_state *st = iio_dev_get_devdata(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] = ADIS16400_WRITE_REG(lower_reg_address);
+	st->tx[1] = value & 0xFF;
+	st->tx[2] = ADIS16400_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;
+}
+
+/**
+ * adis16400_spi_read_reg_16() - read 2 bytes from a 16-bit register
+ * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @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 adis16400_spi_read_reg_16(struct device *dev,
+		u8 lower_reg_address,
+		u16 *val)
+{
+	struct spi_message msg;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct adis16400_state *st = iio_dev_get_devdata(indio_dev);
+	int ret;
+	struct spi_transfer xfers[] = {
+		{
+			.tx_buf = st->tx,
+			.bits_per_word = 8,
+			.len = 2,
+			.cs_change = 1,
+		}, {
+			.rx_buf = st->rx,
+			.bits_per_word = 8,
+			.len = 2,
+			.cs_change = 1,
+		},
+	};
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = ADIS16400_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;
+}
+
+/**
+ * adis16400_spi_read_burst() - read all data registers
+ * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @rx: somewhere to pass back the value read (min size is 24 bytes)
+ **/
+int adis16400_spi_read_burst(struct device *dev, u8 *rx)
+{
+	struct spi_message msg;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct adis16400_state *st = iio_dev_get_devdata(indio_dev);
+	u32 old_speed_hz = st->us->max_speed_hz;
+	int ret;
+
+	struct spi_transfer xfers[] = {
+		{
+			.tx_buf = st->tx,
+			.bits_per_word = 8,
+			.len = 2,
+			.cs_change = 0,
+		}, {
+			.rx_buf = rx,
+			.bits_per_word = 8,
+			.len = 24,
+			.cs_change = 1,
+		},
+	};
+
+	mutex_lock(&st->buf_lock);
+	st->tx[0] = ADIS16400_READ_REG(ADIS16400_GLOB_CMD);
+	st->tx[1] = 0;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfers[0], &msg);
+	spi_message_add_tail(&xfers[1], &msg);
+
+	st->us->max_speed_hz = min(ADIS16400_SPI_BURST, old_speed_hz);
+	spi_setup(st->us);
+
+	ret = spi_sync(st->us, &msg);
+	if (ret)
+		dev_err(&st->us->dev, "problem when burst reading");
+
+	st->us->max_speed_hz = old_speed_hz;
+	spi_setup(st->us);
+	mutex_unlock(&st->buf_lock);
+	return ret;
+}
+
+/**
+ * adis16400_spi_read_sequence() - read a sequence of 16-bit registers
+ * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @tx: register addresses in bytes 0,2,4,6... (min size is 2*num bytes)
+ * @rx: somewhere to pass back the value read (min size is 2*num bytes)
+ **/
+int adis16400_spi_read_sequence(struct device *dev,
+		u8 *tx, u8 *rx, int num)
+{
+	struct spi_message msg;
+	struct spi_transfer *xfers;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct adis16400_state *st = iio_dev_get_devdata(indio_dev);
+	int ret, i;
+
+	xfers = kzalloc(num + 1, GFP_KERNEL);
+	if (xfers == NULL) {
+		dev_err(&st->us->dev, "memory alloc failed");
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+
+	/* tx: |add1|addr2|addr3|...|addrN |zero|
+	 * rx: |zero|res1 |res2 |...|resN-1|resN| */
+	spi_message_init(&msg);
+	for (i = 0; i < num + 1; i++) {
+		if (i > 0)
+			xfers[i].rx_buf = st->rx + 2*(i - 1);
+		if (i < num)
+			xfers[i].tx_buf = st->tx + 2*i;
+		xfers[i].bits_per_word = 8;
+		xfers[i].len = 2;
+		xfers[i].cs_change = 1;
+		spi_message_add_tail(&xfers[i], &msg);
+	}
+
+	mutex_lock(&st->buf_lock);
+
+	ret = spi_sync(st->us, &msg);
+	if (ret)
+		dev_err(&st->us->dev, "problem when reading sequence");
+
+	mutex_unlock(&st->buf_lock);
+	kfree(xfers);
+
+error_ret:
+	return ret;
+}
+
+static ssize_t adis16400_spi_read_signed(struct device *dev,
+		struct device_attribute *attr,
+		char *buf,
+		unsigned bits)
+{
+	int ret;
+	s16 val = 0;
+	unsigned shift = 16 - bits;
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+
+	ret = adis16400_spi_read_reg_16(dev, this_attr->address, (u16 *)&val);
+	if (ret)
+		return ret;
+
+	if (val & ADIS16400_ERROR_ACTIVE)
+		adis16400_check_status(dev);
+	val = ((s16)(val << shift) >> shift);
+	return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t adis16400_read_12bit_unsigned(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	int ret;
+	u16 val = 0;
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+
+	ret = adis16400_spi_read_reg_16(dev, this_attr->address, &val);
+	if (ret)
+		return ret;
+
+	if (val & ADIS16400_ERROR_ACTIVE)
+		adis16400_check_status(dev);
+
+	return sprintf(buf, "%u\n", val & 0x0FFF);
+}
+
+static ssize_t adis16400_read_14bit_signed(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	ssize_t ret;
+
+	/* Take the iio_dev status lock */
+	mutex_lock(&indio_dev->mlock);
+	ret =  adis16400_spi_read_signed(dev, attr, buf, 14);
+	mutex_unlock(&indio_dev->mlock);
+
+	return ret;
+}
+
+static ssize_t adis16400_read_12bit_signed(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	ssize_t ret;
+
+	/* Take the iio_dev status lock */
+	mutex_lock(&indio_dev->mlock);
+	ret =  adis16400_spi_read_signed(dev, attr, buf, 12);
+	mutex_unlock(&indio_dev->mlock);
+
+	return ret;
+}
+
+
+static ssize_t adis16400_write_16bit(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t len)
+{
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+	int ret;
+	long val;
+
+	ret = strict_strtol(buf, 10, &val);
+	if (ret)
+		goto error_ret;
+	ret = adis16400_spi_write_reg_16(dev, this_attr->address, val);
+
+error_ret:
+	return ret ? ret : len;
+}
+
+static ssize_t adis16400_read_frequency(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	int ret, len = 0;
+	u16 t;
+	int sps;
+	ret = adis16400_spi_read_reg_16(dev,
+			ADIS16400_SMPL_PRD,
+			&t);
+	if (ret)
+		return ret;
+	sps =  (t & ADIS16400_SMPL_PRD_TIME_BASE) ? 53 : 1638;
+	sps /= (t & ADIS16400_SMPL_PRD_DIV_MASK) + 1;
+	len = sprintf(buf, "%d SPS\n", sps);
+	return len;
+}
+
+static ssize_t adis16400_write_frequency(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t len)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct adis16400_state *st = iio_dev_get_devdata(indio_dev);
+	long val;
+	int ret;
+	u8 t;
+
+	ret = strict_strtol(buf, 10, &val);
+	if (ret)
+		return ret;
+
+	mutex_lock(&indio_dev->mlock);
+
+	t = (1638 / val);
+	if (t > 0)
+		t--;
+	t &= ADIS16400_SMPL_PRD_DIV_MASK;
+	if ((t & ADIS16400_SMPL_PRD_DIV_MASK) >= 0x0A)
+		st->us->max_speed_hz = ADIS16400_SPI_SLOW;
+	else
+		st->us->max_speed_hz = ADIS16400_SPI_FAST;
+
+	ret = adis16400_spi_write_reg_8(dev,
+			ADIS16400_SMPL_PRD,
+			t);
+
+	mutex_unlock(&indio_dev->mlock);
+
+	return ret ? ret : len;
+}
+
+static ssize_t adis16400_write_reset(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t len)
+{
+	if (len < 1)
+		return -1;
+	switch (buf[0]) {
+	case '1':
+	case 'y':
+	case 'Y':
+		return adis16400_reset(dev);
+	}
+	return -1;
+}
+
+
+
+int adis16400_set_irq(struct device *dev, bool enable)
+{
+	int ret;
+	u16 msc;
+	ret = adis16400_spi_read_reg_16(dev, ADIS16400_MSC_CTRL, &msc);
+	if (ret)
+		goto error_ret;
+
+	msc |= ADIS16400_MSC_CTRL_DATA_RDY_POL_HIGH;
+	if (enable)
+		msc |= ADIS16400_MSC_CTRL_DATA_RDY_EN;
+	else
+		msc &= ~ADIS16400_MSC_CTRL_DATA_RDY_EN;
+
+	ret = adis16400_spi_write_reg_16(dev, ADIS16400_MSC_CTRL, msc);
+	if (ret)
+		goto error_ret;
+
+error_ret:
+	return ret;
+}
+
+int adis16400_reset(struct device *dev)
+{
+	int ret;
+	ret = adis16400_spi_write_reg_8(dev,
+			ADIS16400_GLOB_CMD,
+			ADIS16400_GLOB_CMD_SW_RESET);
+	if (ret)
+		dev_err(dev, "problem resetting device");
+
+	return ret;
+}
+
+/* Power down the device */
+int adis16400_stop_device(struct device *dev)
+{
+	int ret;
+	u16 val = ADIS16400_SLP_CNT_POWER_OFF;
+
+	ret = adis16400_spi_write_reg_16(dev, ADIS16400_SLP_CNT, val);
+	if (ret)
+		dev_err(dev, "problem with turning device off: SLP_CNT");
+
+	return ret;
+}
+
+int adis16400_self_test(struct device *dev)
+{
+	int ret;
+	ret = adis16400_spi_write_reg_16(dev,
+			ADIS16400_MSC_CTRL,
+			ADIS16400_MSC_CTRL_MEM_TEST);
+	if (ret) {
+		dev_err(dev, "problem starting self test");
+		goto err_ret;
+	}
+
+	adis16400_check_status(dev);
+
+err_ret:
+	return ret;
+}
+
+int adis16400_check_status(struct device *dev)
+{
+	u16 status;
+	int ret;
+
+	ret = adis16400_spi_read_reg_16(dev, ADIS16400_DIAG_STAT, &status);
+
+	if (ret < 0) {
+		dev_err(dev, "Reading status failed\n");
+		goto error_ret;
+	}
+	ret = status;
+	if (status & ADIS16400_DIAG_STAT_ZACCL_FAIL)
+		dev_err(dev, "Z-axis accelerometer self-test failure\n");
+	if (status & ADIS16400_DIAG_STAT_YACCL_FAIL)
+		dev_err(dev, "Y-axis accelerometer self-test failure\n");
+	if (status & ADIS16400_DIAG_STAT_XACCL_FAIL)
+		dev_err(dev, "X-axis accelerometer self-test failure\n");
+	if (status & ADIS16400_DIAG_STAT_XGYRO_FAIL)
+		dev_err(dev, "X-axis gyroscope self-test failure\n");
+	if (status & ADIS16400_DIAG_STAT_YGYRO_FAIL)
+		dev_err(dev, "Y-axis gyroscope self-test failure\n");
+	if (status & ADIS16400_DIAG_STAT_ZGYRO_FAIL)
+		dev_err(dev, "Z-axis gyroscope self-test failure\n");
+	if (status & ADIS16400_DIAG_STAT_ALARM2)
+		dev_err(dev, "Alarm 2 active\n");
+	if (status & ADIS16400_DIAG_STAT_ALARM1)
+		dev_err(dev, "Alarm 1 active\n");
+	if (status & ADIS16400_DIAG_STAT_FLASH_CHK)
+		dev_err(dev, "Flash checksum error\n");
+	if (status & ADIS16400_DIAG_STAT_SELF_TEST)
+		dev_err(dev, "Self test error\n");
+	if (status & ADIS16400_DIAG_STAT_OVERFLOW)
+		dev_err(dev, "Sensor overrange\n");
+	if (status & ADIS16400_DIAG_STAT_SPI_FAIL)
+		dev_err(dev, "SPI failure\n");
+	if (status & ADIS16400_DIAG_STAT_FLASH_UPT)
+		dev_err(dev, "Flash update failed\n");
+	if (status & ADIS16400_DIAG_STAT_POWER_HIGH)
+		dev_err(dev, "Power supply above 5.25V\n");
+	if (status & ADIS16400_DIAG_STAT_POWER_LOW)
+		dev_err(dev, "Power supply below 4.75V\n");
+
+error_ret:
+	return ret;
+}
+
+static int adis16400_initial_setup(struct adis16400_state *st)
+{
+	int ret;
+	u16 prod_id, smp_prd;
+	struct device *dev = &st->indio_dev->dev;
+
+	/* use low spi speed for init */
+	st->us->max_speed_hz = ADIS16400_SPI_SLOW;
+	st->us->mode = SPI_MODE_3;
+	spi_setup(st->us);
+
+	/* Disable IRQ */
+	ret = adis16400_set_irq(dev, false);
+	if (ret) {
+		dev_err(dev, "disable irq failed");
+		goto err_ret;
+	}
+
+	/* Do self test */
+
+	/* Read status register to check the result */
+	ret = adis16400_check_status(dev);
+	if (ret) {
+		adis16400_reset(dev);
+		dev_err(dev, "device not playing ball -> reset");
+		msleep(ADIS16400_STARTUP_DELAY);
+		ret = adis16400_check_status(dev);
+		if (ret) {
+			dev_err(dev, "giving up");
+			goto err_ret;
+		}
+	}
+
+	ret = adis16400_spi_read_reg_16(dev, ADIS16400_PRODUCT_ID, &prod_id);
+	if (ret)
+		goto err_ret;
+
+	if (prod_id != ADIS16400_PRODUCT_ID_DEFAULT)
+		dev_warn(dev, "unknown product id");
+
+	printk(KERN_INFO DRIVER_NAME ": prod_id 0x%04x at CS%d (irq %d)\n",
+			prod_id, st->us->chip_select, st->us->irq);
+
+	/* use high spi speed if possible */
+	ret = adis16400_spi_read_reg_16(dev, ADIS16400_SMPL_PRD, &smp_prd);
+	if (!ret && (smp_prd & ADIS16400_SMPL_PRD_DIV_MASK) < 0x0A) {
+		st->us->max_speed_hz = ADIS16400_SPI_SLOW;
+		spi_setup(st->us);
+	}
+
+
+err_ret:
+
+	return ret;
+}
+
+static IIO_DEV_ATTR_ACCEL_X_OFFSET(S_IWUSR | S_IRUGO,
+		adis16400_read_12bit_signed,
+		adis16400_write_16bit,
+		ADIS16400_XACCL_OFF);
+
+static IIO_DEV_ATTR_ACCEL_Y_OFFSET(S_IWUSR | S_IRUGO,
+		adis16400_read_12bit_signed,
+		adis16400_write_16bit,
+		ADIS16400_YACCL_OFF);
+
+static IIO_DEV_ATTR_ACCEL_Z_OFFSET(S_IWUSR | S_IRUGO,
+		adis16400_read_12bit_signed,
+		adis16400_write_16bit,
+		ADIS16400_ZACCL_OFF);
+
+static IIO_DEV_ATTR_IN_NAMED_RAW(supply, adis16400_read_14bit_signed,
+		ADIS16400_SUPPLY_OUT);
+static IIO_CONST_ATTR(in_supply_scale, "0.002418");
+
+static IIO_DEV_ATTR_GYRO_X(adis16400_read_14bit_signed,
+		ADIS16400_XGYRO_OUT);
+static IIO_DEV_ATTR_GYRO_Y(adis16400_read_14bit_signed,
+		ADIS16400_YGYRO_OUT);
+static IIO_DEV_ATTR_GYRO_Z(adis16400_read_14bit_signed,
+		ADIS16400_ZGYRO_OUT);
+static IIO_CONST_ATTR(gyro_scale, "0.05 deg/s");
+
+static IIO_DEV_ATTR_ACCEL_X(adis16400_read_14bit_signed,
+		ADIS16400_XACCL_OUT);
+static IIO_DEV_ATTR_ACCEL_Y(adis16400_read_14bit_signed,
+		ADIS16400_YACCL_OUT);
+static IIO_DEV_ATTR_ACCEL_Z(adis16400_read_14bit_signed,
+		ADIS16400_ZACCL_OUT);
+static IIO_CONST_ATTR(accel_scale, "0.00333 g");
+
+static IIO_DEV_ATTR_MAGN_X(adis16400_read_14bit_signed,
+		ADIS16400_XMAGN_OUT);
+static IIO_DEV_ATTR_MAGN_Y(adis16400_read_14bit_signed,
+		ADIS16400_YMAGN_OUT);
+static IIO_DEV_ATTR_MAGN_Z(adis16400_read_14bit_signed,
+		ADIS16400_ZMAGN_OUT);
+static IIO_CONST_ATTR(magn_scale, "0.0005 Gs");
+
+
+static IIO_DEV_ATTR_TEMP(adis16400_read_12bit_signed);
+static IIO_CONST_ATTR(temp_offset, "198.16 K");
+static IIO_CONST_ATTR(temp_scale, "0.14 K");
+
+static IIO_DEV_ATTR_IN_RAW(0, adis16400_read_12bit_unsigned,
+		ADIS16400_AUX_ADC);
+static IIO_CONST_ATTR(in0_scale, "0.000806");
+
+static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
+		adis16400_read_frequency,
+		adis16400_write_frequency);
+
+static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16400_write_reset, 0);
+
+static IIO_CONST_ATTR_AVAIL_SAMP_FREQ("409 546 819 1638");
+
+static IIO_CONST_ATTR(name, "adis16400");
+
+static struct attribute *adis16400_event_attributes[] = {
+	NULL
+};
+
+static struct attribute_group adis16400_event_attribute_group = {
+	.attrs = adis16400_event_attributes,
+};
+
+static struct attribute *adis16400_attributes[] = {
+	&iio_dev_attr_accel_x_offset.dev_attr.attr,
+	&iio_dev_attr_accel_y_offset.dev_attr.attr,
+	&iio_dev_attr_accel_z_offset.dev_attr.attr,
+	&iio_dev_attr_in_supply_raw.dev_attr.attr,
+	&iio_const_attr_in_supply_scale.dev_attr.attr,
+	&iio_dev_attr_gyro_x.dev_attr.attr,
+	&iio_dev_attr_gyro_y.dev_attr.attr,
+	&iio_dev_attr_gyro_z.dev_attr.attr,
+	&iio_const_attr_gyro_scale.dev_attr.attr,
+	&iio_dev_attr_accel_x_raw.dev_attr.attr,
+	&iio_dev_attr_accel_y_raw.dev_attr.attr,
+	&iio_dev_attr_accel_z_raw.dev_attr.attr,
+	&iio_const_attr_accel_scale.dev_attr.attr,
+	&iio_dev_attr_magn_x.dev_attr.attr,
+	&iio_dev_attr_magn_y.dev_attr.attr,
+	&iio_dev_attr_magn_z.dev_attr.attr,
+	&iio_const_attr_magn_scale.dev_attr.attr,
+	&iio_dev_attr_temp.dev_attr.attr,
+	&iio_const_attr_temp_offset.dev_attr.attr,
+	&iio_const_attr_temp_scale.dev_attr.attr,
+	&iio_dev_attr_in0_raw.dev_attr.attr,
+	&iio_const_attr_in0_scale.dev_attr.attr,
+	&iio_dev_attr_sampling_frequency.dev_attr.attr,
+	&iio_const_attr_available_sampling_frequency.dev_attr.attr,
+	&iio_dev_attr_reset.dev_attr.attr,
+	&iio_const_attr_name.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group adis16400_attribute_group = {
+	.attrs = adis16400_attributes,
+};
+
+static int __devinit adis16400_probe(struct spi_device *spi)
+{
+	int ret, regdone = 0;
+	struct adis16400_state *st = kzalloc(sizeof *st, GFP_KERNEL);
+	if (!st) {
+		ret =  -ENOMEM;
+		goto error_ret;
+	}
+	/* this is only used for removal purposes */
+	spi_set_drvdata(spi, st);
+
+	/* Allocate the comms buffers */
+	st->rx = kzalloc(sizeof(*st->rx)*ADIS16400_MAX_RX, GFP_KERNEL);
+	if (st->rx == NULL) {
+		ret = -ENOMEM;
+		goto error_free_st;
+	}
+	st->tx = kzalloc(sizeof(*st->tx)*ADIS16400_MAX_TX, GFP_KERNEL);
+	if (st->tx == NULL) {
+		ret = -ENOMEM;
+		goto error_free_rx;
+	}
+	st->us = spi;
+	mutex_init(&st->buf_lock);
+	/* setup the industrialio driver allocated elements */
+	st->indio_dev = iio_allocate_device();
+	if (st->indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_free_tx;
+	}
+
+	st->indio_dev->dev.parent = &spi->dev;
+	st->indio_dev->num_interrupt_lines = 1;
+	st->indio_dev->event_attrs = &adis16400_event_attribute_group;
+	st->indio_dev->attrs = &adis16400_attribute_group;
+	st->indio_dev->dev_data = (void *)(st);
+	st->indio_dev->driver_module = THIS_MODULE;
+	st->indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = adis16400_configure_ring(st->indio_dev);
+	if (ret)
+		goto error_free_dev;
+
+	ret = iio_device_register(st->indio_dev);
+	if (ret)
+		goto error_unreg_ring_funcs;
+	regdone = 1;
+
+	ret = adis16400_initialize_ring(st->indio_dev->ring);
+	if (ret) {
+		printk(KERN_ERR "failed to initialize the ring\n");
+		goto error_unreg_ring_funcs;
+	}
+
+	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) {
+#if 0 /* fixme: here we should support */
+		iio_init_work_cont(&st->work_cont_thresh,
+				NULL,
+				adis16400_thresh_handler_bh_no_check,
+				0,
+				0,
+				st);
+#endif
+		ret = iio_register_interrupt_line(spi->irq,
+				st->indio_dev,
+				0,
+				IRQF_TRIGGER_RISING,
+				"adis16400");
+		if (ret)
+			goto error_uninitialize_ring;
+
+		ret = adis16400_probe_trigger(st->indio_dev);
+		if (ret)
+			goto error_unregister_line;
+	}
+
+	/* Get the device into a sane initial state */
+	ret = adis16400_initial_setup(st);
+	if (ret)
+		goto error_remove_trigger;
+	return 0;
+
+error_remove_trigger:
+	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
+		adis16400_remove_trigger(st->indio_dev);
+error_unregister_line:
+	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
+		iio_unregister_interrupt_line(st->indio_dev, 0);
+error_uninitialize_ring:
+	adis16400_uninitialize_ring(st->indio_dev->ring);
+error_unreg_ring_funcs:
+	adis16400_unconfigure_ring(st->indio_dev);
+error_free_dev:
+	if (regdone)
+		iio_device_unregister(st->indio_dev);
+	else
+		iio_free_device(st->indio_dev);
+error_free_tx:
+	kfree(st->tx);
+error_free_rx:
+	kfree(st->rx);
+error_free_st:
+	kfree(st);
+error_ret:
+	return ret;
+}
+
+/* fixme, confirm ordering in this function */
+static int adis16400_remove(struct spi_device *spi)
+{
+	int ret;
+	struct adis16400_state *st = spi_get_drvdata(spi);
+	struct iio_dev *indio_dev = st->indio_dev;
+
+	ret = adis16400_stop_device(&(indio_dev->dev));
+	if (ret)
+		goto err_ret;
+
+	flush_scheduled_work();
+
+	adis16400_remove_trigger(indio_dev);
+	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
+		iio_unregister_interrupt_line(indio_dev, 0);
+
+	adis16400_uninitialize_ring(indio_dev->ring);
+	adis16400_unconfigure_ring(indio_dev);
+	iio_device_unregister(indio_dev);
+	kfree(st->tx);
+	kfree(st->rx);
+	kfree(st);
+
+	return 0;
+
+err_ret:
+	return ret;
+}
+
+static struct spi_driver adis16400_driver = {
+	.driver = {
+		.name = "adis16400",
+		.owner = THIS_MODULE,
+	},
+	.probe = adis16400_probe,
+	.remove = __devexit_p(adis16400_remove),
+};
+
+static __init int adis16400_init(void)
+{
+	return spi_register_driver(&adis16400_driver);
+}
+module_init(adis16400_init);
+
+static __exit void adis16400_exit(void)
+{
+	spi_unregister_driver(&adis16400_driver);
+}
+module_exit(adis16400_exit);
+
+MODULE_AUTHOR("Manuel Stahl <manuel.stahl@iis.fraunhofer.de>");
+MODULE_DESCRIPTION("Analog Devices ADIS16400/5 IMU SPI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c
new file mode 100644
index 0000000..5529b32
--- /dev/null
+++ b/drivers/staging/iio/imu/adis16400_ring.c
@@ -0,0 +1,245 @@
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/sysfs.h>
+#include <linux/list.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "../ring_sw.h"
+#include "../accel/accel.h"
+#include "../trigger.h"
+#include "adis16400.h"
+
+/**
+ * combine_8_to_16() utility function to munge to u8s into u16
+ **/
+static inline u16 combine_8_to_16(u8 lower, u8 upper)
+{
+	u16 _lower = lower;
+	u16 _upper = upper;
+	return _lower | (_upper << 8);
+}
+
+static IIO_SCAN_EL_C(supply, ADIS16400_SCAN_SUPPLY, IIO_SIGNED(14),
+		     ADIS16400_SUPPLY_OUT, NULL);
+
+static IIO_SCAN_EL_C(gyro_x, ADIS16400_SCAN_GYRO_X, IIO_SIGNED(14),
+		     ADIS16400_XGYRO_OUT, NULL);
+static IIO_SCAN_EL_C(gyro_y, ADIS16400_SCAN_GYRO_Y, IIO_SIGNED(14),
+		     ADIS16400_YGYRO_OUT, NULL);
+static IIO_SCAN_EL_C(gyro_z, ADIS16400_SCAN_GYRO_Z, IIO_SIGNED(14),
+		     ADIS16400_ZGYRO_OUT, NULL);
+
+static IIO_SCAN_EL_C(accel_x, ADIS16400_SCAN_ACC_X, IIO_SIGNED(14),
+		     ADIS16400_XACCL_OUT, NULL);
+static IIO_SCAN_EL_C(accel_y, ADIS16400_SCAN_ACC_Y, IIO_SIGNED(14),
+		     ADIS16400_YACCL_OUT, NULL);
+static IIO_SCAN_EL_C(accel_z, ADIS16400_SCAN_ACC_Z, IIO_SIGNED(14),
+		     ADIS16400_ZACCL_OUT, NULL);
+
+static IIO_SCAN_EL_C(magn_x, ADIS16400_SCAN_MAGN_X, IIO_SIGNED(14),
+		     ADIS16400_XMAGN_OUT, NULL);
+static IIO_SCAN_EL_C(magn_y, ADIS16400_SCAN_MAGN_Y, IIO_SIGNED(14),
+		     ADIS16400_YMAGN_OUT, NULL);
+static IIO_SCAN_EL_C(magn_z, ADIS16400_SCAN_MAGN_Z, IIO_SIGNED(14),
+		     ADIS16400_ZMAGN_OUT, NULL);
+
+static IIO_SCAN_EL_C(temp, ADIS16400_SCAN_TEMP, IIO_SIGNED(12),
+		     ADIS16400_TEMP_OUT, NULL);
+static IIO_SCAN_EL_C(adc_0, ADIS16400_SCAN_ADC_0, IIO_SIGNED(12),
+		     ADIS16400_AUX_ADC, NULL);
+
+static IIO_SCAN_EL_TIMESTAMP(12);
+
+static struct attribute *adis16400_scan_el_attrs[] = {
+	&iio_scan_el_supply.dev_attr.attr,
+	&iio_scan_el_gyro_x.dev_attr.attr,
+	&iio_scan_el_gyro_y.dev_attr.attr,
+	&iio_scan_el_gyro_z.dev_attr.attr,
+	&iio_scan_el_accel_x.dev_attr.attr,
+	&iio_scan_el_accel_y.dev_attr.attr,
+	&iio_scan_el_accel_z.dev_attr.attr,
+	&iio_scan_el_magn_x.dev_attr.attr,
+	&iio_scan_el_magn_y.dev_attr.attr,
+	&iio_scan_el_magn_z.dev_attr.attr,
+	&iio_scan_el_temp.dev_attr.attr,
+	&iio_scan_el_adc_0.dev_attr.attr,
+	&iio_scan_el_timestamp.dev_attr.attr,
+	NULL,
+};
+
+static struct attribute_group adis16400_scan_el_group = {
+	.attrs = adis16400_scan_el_attrs,
+	.name = "scan_elements",
+};
+
+/**
+ * adis16400_poll_func_th() top half interrupt handler called by trigger
+ * @private_data:	iio_dev
+ **/
+static void adis16400_poll_func_th(struct iio_dev *indio_dev)
+{
+	struct adis16400_state *st = iio_dev_get_devdata(indio_dev);
+	st->last_timestamp = indio_dev->trig->timestamp;
+	schedule_work(&st->work_trigger_to_ring);
+	/* Indicate that this interrupt is being handled */
+
+	/* Technically this is trigger related, but without this
+	 * handler running there is currently no way for the interrupt
+	 * to clear.
+	 */
+}
+
+/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
+ * specific to be rolled into the core.
+ */
+static void adis16400_trigger_bh_to_ring(struct work_struct *work_s)
+{
+	struct adis16400_state *st
+		= container_of(work_s, struct adis16400_state,
+			       work_trigger_to_ring);
+
+	int i = 0;
+	s16 *data;
+	size_t datasize = st->indio_dev
+		->ring->access.get_bpd(st->indio_dev->ring);
+
+	data = kmalloc(datasize , GFP_KERNEL);
+	if (data == NULL) {
+		dev_err(&st->us->dev, "memory alloc failed in ring bh");
+		return;
+	}
+
+	if (st->indio_dev->scan_count)
+		if (adis16400_spi_read_burst(&st->indio_dev->dev, st->rx) >= 0)
+			for (; i < st->indio_dev->scan_count; i++) {
+				data[i] = combine_8_to_16(st->rx[i*2+1],
+							  st->rx[i*2]);
+			}
+
+	/* Guaranteed to be aligned with 8 byte boundary */
+	if (st->indio_dev->scan_timestamp)
+		*((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
+
+	st->indio_dev->ring->access.store_to(st->indio_dev->ring,
+					    (u8 *)data,
+					    st->last_timestamp);
+
+	iio_trigger_notify_done(st->indio_dev->trig);
+	kfree(data);
+
+	return;
+}
+/* in these circumstances is it better to go with unaligned packing and
+ * deal with the cost?*/
+static int adis16400_data_rdy_ring_preenable(struct iio_dev *indio_dev)
+{
+	size_t size;
+	dev_dbg(&indio_dev->dev, "%s\n", __func__);
+	/* Check if there are any scan elements enabled, if not fail*/
+	if (!(indio_dev->scan_count || indio_dev->scan_timestamp))
+		return -EINVAL;
+
+	if (indio_dev->ring->access.set_bpd) {
+		if (indio_dev->scan_timestamp)
+			if (indio_dev->scan_count) /* Timestamp and data */
+				size = 6*sizeof(s64);
+			else /* Timestamp only  */
+				size = sizeof(s64);
+		else /* Data only */
+			size = indio_dev->scan_count*sizeof(s16);
+		indio_dev->ring->access.set_bpd(indio_dev->ring, size);
+	}
+
+	return 0;
+}
+
+static int adis16400_data_rdy_ring_postenable(struct iio_dev *indio_dev)
+{
+	return indio_dev->trig
+		? iio_trigger_attach_poll_func(indio_dev->trig,
+					       indio_dev->pollfunc)
+		: 0;
+}
+
+static int adis16400_data_rdy_ring_predisable(struct iio_dev *indio_dev)
+{
+	return indio_dev->trig
+		? iio_trigger_dettach_poll_func(indio_dev->trig,
+						indio_dev->pollfunc)
+		: 0;
+}
+
+void adis16400_unconfigure_ring(struct iio_dev *indio_dev)
+{
+	kfree(indio_dev->pollfunc);
+	iio_sw_rb_free(indio_dev->ring);
+}
+
+int adis16400_configure_ring(struct iio_dev *indio_dev)
+{
+	int ret = 0;
+	struct adis16400_state *st = indio_dev->dev_data;
+	struct iio_ring_buffer *ring;
+	INIT_WORK(&st->work_trigger_to_ring, adis16400_trigger_bh_to_ring);
+	/* Set default scan mode */
+
+	iio_scan_mask_set(indio_dev, iio_scan_el_supply.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_gyro_x.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_gyro_y.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_gyro_z.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_accel_x.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_accel_y.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_accel_z.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_magn_x.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_magn_y.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_magn_z.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_temp.number);
+	iio_scan_mask_set(indio_dev, iio_scan_el_adc_0.number);
+	indio_dev->scan_timestamp = true;
+
+	indio_dev->scan_el_attrs = &adis16400_scan_el_group;
+
+	ring = iio_sw_rb_allocate(indio_dev);
+	if (!ring) {
+		ret = -ENOMEM;
+		return ret;
+	}
+	indio_dev->ring = ring;
+	/* Effectively select the ring buffer implementation */
+	iio_ring_sw_register_funcs(&ring->access);
+	ring->preenable = &adis16400_data_rdy_ring_preenable;
+	ring->postenable = &adis16400_data_rdy_ring_postenable;
+	ring->predisable = &adis16400_data_rdy_ring_predisable;
+	ring->owner = THIS_MODULE;
+
+	indio_dev->pollfunc = kzalloc(sizeof(*indio_dev->pollfunc), GFP_KERNEL);
+	if (indio_dev->pollfunc == NULL) {
+		ret = -ENOMEM;
+		goto error_iio_sw_rb_free;;
+	}
+	indio_dev->pollfunc->poll_func_main = &adis16400_poll_func_th;
+	indio_dev->pollfunc->private_data = indio_dev;
+	indio_dev->modes |= INDIO_RING_TRIGGERED;
+	return 0;
+
+error_iio_sw_rb_free:
+	iio_sw_rb_free(indio_dev->ring);
+	return ret;
+}
+
+int adis16400_initialize_ring(struct iio_ring_buffer *ring)
+{
+	return iio_ring_buffer_register(ring, 0);
+}
+
+void adis16400_uninitialize_ring(struct iio_ring_buffer *ring)
+{
+	iio_ring_buffer_unregister(ring);
+}
diff --git a/drivers/staging/iio/imu/adis16400_trigger.c b/drivers/staging/iio/imu/adis16400_trigger.c
new file mode 100644
index 0000000..3b3250a
--- /dev/null
+++ b/drivers/staging/iio/imu/adis16400_trigger.c
@@ -0,0 +1,127 @@
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/sysfs.h>
+#include <linux/list.h>
+#include <linux/spi/spi.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "../trigger.h"
+#include "adis16400.h"
+
+/**
+ * adis16400_data_rdy_trig_poll() the event handler for the data rdy trig
+ **/
+static int adis16400_data_rdy_trig_poll(struct iio_dev *dev_info,
+				       int index,
+				       s64 timestamp,
+				       int no_test)
+{
+	struct adis16400_state *st = iio_dev_get_devdata(dev_info);
+	struct iio_trigger *trig = st->trig;
+
+	trig->timestamp = timestamp;
+	iio_trigger_poll(trig);
+
+	return IRQ_HANDLED;
+}
+
+IIO_EVENT_SH(data_rdy_trig, &adis16400_data_rdy_trig_poll);
+
+static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
+
+static struct attribute *adis16400_trigger_attrs[] = {
+	&dev_attr_name.attr,
+	NULL,
+};
+
+static const struct attribute_group adis16400_trigger_attr_group = {
+	.attrs = adis16400_trigger_attrs,
+};
+
+/**
+ * adis16400_data_rdy_trigger_set_state() set datardy interrupt state
+ **/
+static int adis16400_data_rdy_trigger_set_state(struct iio_trigger *trig,
+						bool state)
+{
+	struct adis16400_state *st = trig->private_data;
+	struct iio_dev *indio_dev = st->indio_dev;
+	int ret = 0;
+
+	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
+	ret = adis16400_set_irq(&st->indio_dev->dev, state);
+	if (state == false) {
+		iio_remove_event_from_list(&iio_event_data_rdy_trig,
+					   &indio_dev->interrupts[0]
+					   ->ev_list);
+		/* possible quirk with handler currently worked around
+		   by ensuring the work queue is empty */
+		flush_scheduled_work();
+	} else {
+		iio_add_event_to_list(&iio_event_data_rdy_trig,
+				      &indio_dev->interrupts[0]->ev_list);
+	}
+	return ret;
+}
+
+/**
+ * adis16400_trig_try_reen() try renabling irq for data rdy trigger
+ * @trig:	the datardy trigger
+ **/
+static int adis16400_trig_try_reen(struct iio_trigger *trig)
+{
+	struct adis16400_state *st = trig->private_data;
+	enable_irq(st->us->irq);
+	/* irq reenabled so success! */
+	return 0;
+}
+
+int adis16400_probe_trigger(struct iio_dev *indio_dev)
+{
+	int ret;
+	struct adis16400_state *st = indio_dev->dev_data;
+
+	st->trig = iio_allocate_trigger();
+	st->trig->name = kmalloc(IIO_TRIGGER_NAME_LENGTH, GFP_KERNEL);
+	if (!st->trig->name) {
+		ret = -ENOMEM;
+		goto error_free_trig;
+	}
+	snprintf((char *)st->trig->name,
+		 IIO_TRIGGER_NAME_LENGTH,
+		 "adis16400-dev%d", indio_dev->id);
+	st->trig->dev.parent = &st->us->dev;
+	st->trig->owner = THIS_MODULE;
+	st->trig->private_data = st;
+	st->trig->set_trigger_state = &adis16400_data_rdy_trigger_set_state;
+	st->trig->try_reenable = &adis16400_trig_try_reen;
+	st->trig->control_attrs = &adis16400_trigger_attr_group;
+	ret = iio_trigger_register(st->trig);
+
+	/* select default trigger */
+	indio_dev->trig = st->trig;
+	if (ret)
+		goto error_free_trig_name;
+
+	return 0;
+
+error_free_trig_name:
+	kfree(st->trig->name);
+error_free_trig:
+	iio_free_trigger(st->trig);
+
+	return ret;
+}
+
+void adis16400_remove_trigger(struct iio_dev *indio_dev)
+{
+	struct adis16400_state *state = indio_dev->dev_data;
+
+	iio_trigger_unregister(state->trig);
+	kfree(state->trig->name);
+	iio_free_trigger(state->trig);
+}
diff --git a/drivers/staging/iio/magnetometer/magnet.h b/drivers/staging/iio/magnetometer/magnet.h
new file mode 100644
index 0000000..6f6c6ed
--- /dev/null
+++ b/drivers/staging/iio/magnetometer/magnet.h
@@ -0,0 +1,31 @@
+
+#include "../sysfs.h"
+
+/* Magnetometer types of attribute */
+
+#define IIO_DEV_ATTR_MAGN_X_OFFSET(_mode, _show, _store, _addr)	\
+	IIO_DEVICE_ATTR(magn_x_offset, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_MAGN_Y_OFFSET(_mode, _show, _store, _addr)	\
+	IIO_DEVICE_ATTR(magn_y_offset, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_MAGN_Z_OFFSET(_mode, _show, _store, _addr)	\
+	IIO_DEVICE_ATTR(magn_z_offset, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_MAGN_X_GAIN(_mode, _show, _store, _addr)		\
+	IIO_DEVICE_ATTR(magn_x_gain, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_MAGN_Y_GAIN(_mode, _show, _store, _addr)		\
+	IIO_DEVICE_ATTR(magn_y_gain, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_MAGN_Z_GAIN(_mode, _show, _store, _addr)		\
+	IIO_DEVICE_ATTR(magn_z_gain, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_MAGN_X(_show, _addr)			\
+	IIO_DEVICE_ATTR(magn_x, S_IRUGO, _show, NULL, _addr)
+
+#define IIO_DEV_ATTR_MAGN_Y(_show, _addr)			\
+	IIO_DEVICE_ATTR(magn_y, S_IRUGO, _show, NULL, _addr)
+
+#define IIO_DEV_ATTR_MAGN_Z(_show, _addr)			\
+	IIO_DEVICE_ATTR(magn_z, S_IRUGO, _show, NULL, _addr)
-- 
1.6.4.4


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

* Re: [PATCH 00/20] staging:iio updates Abi changes and new drivers
  2010-05-04 13:42 [PATCH 00/20] staging:iio updates Abi changes and new drivers Jonathan Cameron
  2010-05-04 13:42 ` [PATCH 01/20] staging:iio: Add new in_raw definitions for adc channels Jonathan Cameron
@ 2010-05-04 20:48 ` Greg KH
  2010-05-04 21:36   ` Jonathan Cameron
  1 sibling, 1 reply; 23+ messages in thread
From: Greg KH @ 2010-05-04 20:48 UTC (permalink / raw)
  To: Jonathan Cameron; +Cc: gregkh, linux-iio

On Tue, May 04, 2010 at 02:42:55PM +0100, Jonathan Cameron wrote:
> Dear Greg,
> 
> The following set is based upon your staging-next tree as of Sunday.
> When the caching updates they should be available on:
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio-new-abi.git master
> 
> so if it is easier for you, pull from there.

All looks good, I've queued all of them up, thanks for the patches.

Note, some of them added some whitespace errors, that you might want to
go back and fix up now before someone else does :)

thanks,

greg k-h

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

* Re: [PATCH 00/20] staging:iio updates Abi changes and new drivers
  2010-05-04 20:48 ` [PATCH 00/20] staging:iio updates Abi changes and new drivers Greg KH
@ 2010-05-04 21:36   ` Jonathan Cameron
  0 siblings, 0 replies; 23+ messages in thread
From: Jonathan Cameron @ 2010-05-04 21:36 UTC (permalink / raw)
  To: Greg KH; +Cc: gregkh, linux-iio

On 05/04/10 21:48, Greg KH wrote:
> On Tue, May 04, 2010 at 02:42:55PM +0100, Jonathan Cameron wrote:
>> Dear Greg,
>>
>> The following set is based upon your staging-next tree as of Sunday.
>> When the caching updates they should be available on:
>>
>> git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio-new-abi.git master
>>
>> so if it is easier for you, pull from there.
> 
> All looks good, I've queued all of them up, thanks for the patches.
Thanks!
> 
> Note, some of them added some whitespace errors, that you might want to
> go back and fix up now before someone else does :)
checkpatch is giving what looks like a spurious warning on iio_bus_type export.
I'll take another look at that tomorrow.

I'm not entirely sure which patch introduced the other issues I've just sent
fixes to. (I suspect some were there all along!)  Thanks for pointing out they
were there.

Jonathan

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

end of thread, other threads:[~2010-05-04 21:33 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-05-04 13:42 [PATCH 00/20] staging:iio updates Abi changes and new drivers Jonathan Cameron
2010-05-04 13:42 ` [PATCH 01/20] staging:iio: Add new in_raw definitions for adc channels Jonathan Cameron
2010-05-04 13:42   ` [PATCH 02/20] staging:iio: Add new attrs for sampling frequency available and temp_raw Jonathan Cameron
2010-05-04 13:42     ` [PATCH 03/20] iio:staging:accelerometers move towards the new abi Jonathan Cameron
2010-05-04 13:42       ` [PATCH 04/20] staging:iio: Support functions for scan mask matching Jonathan Cameron
2010-05-04 13:43         ` [PATCH 05/20] staging: iio: Move from class to bus Jonathan Cameron
2010-05-04 13:43           ` [PATCH 06/20] staging:iio: Move event attributes into the event[n] device in sysfs Jonathan Cameron
2010-05-04 13:43             ` [PATCH 07/20] staging:iio: Clean out unused IIO_SCAN_EL and add IIO_SCAN_NAMED_EL_C Jonathan Cameron
2010-05-04 13:43               ` [PATCH 08/20] staging:iio:max1363 move to new abi Jonathan Cameron
2010-05-04 13:43                 ` [PATCH 09/20] staging:iio: Documentation, update iio_utils.h for the move to a bus Jonathan Cameron
2010-05-04 13:43                   ` [PATCH 10/20] staging:iio: ABI documentation (partial) Jonathan Cameron
2010-05-04 13:43                     ` [PATCH 11/20] staging:iio: Directory name changes to match new ABI Jonathan Cameron
2010-05-04 13:43                       ` [PATCH 12/20] staging:iio:tsl2563: change lux to illuminance0_input to match new abi Jonathan Cameron
2010-05-04 13:43                         ` [PATCH 13/20] staging:iio: Remove naming via IDR's where no longer necessary under " Jonathan Cameron
2010-05-04 13:43                           ` [PATCH 14/20] staging:iio:max1363 add support for max11606-max11617 Jonathan Cameron
2010-05-04 13:43                             ` [PATCH 15/20] staging:iio:max1363 add support for 8 bit equivalent devices, max1036-9, max11600-5 Jonathan Cameron
2010-05-04 13:43                               ` [PATCH 16/20] staging:iio:ring_sw: Fix incorrect test on successful read of last value, causes infinite loop Jonathan Cameron
2010-05-04 13:43                                 ` [PATCH 17/20] staging:iio:tsl2563 add a name attribute under the iio Jonathan Cameron
2010-05-04 13:43                                   ` [PATCH 18/20] staging:iio:Documentation: Rewrite example for new abi Jonathan Cameron
2010-05-04 13:43                                     ` [PATCH 19/20] staging:iio:imu ADIS16300 driver Jonathan Cameron
2010-05-04 13:43                                       ` [PATCH 20/20] staging:iio:imu ADIS16400 and ADIS16405 driver Jonathan Cameron
2010-05-04 20:48 ` [PATCH 00/20] staging:iio updates Abi changes and new drivers Greg KH
2010-05-04 21:36   ` 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.