aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/iio
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2011-08-29 08:47:46 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2011-08-29 08:47:46 -0700
commit6eafa4604cfa109a89524d35d93df11c37bd66b0 (patch)
treede0eddca052ed01318df559d7cd80211dd57a0fd /drivers/staging/iio
parentLinux 3.1-rc4 (diff)
parentstaging: fix rts5139 depends & build (diff)
downloadlinux-dev-6eafa4604cfa109a89524d35d93df11c37bd66b0.tar.xz
linux-dev-6eafa4604cfa109a89524d35d93df11c37bd66b0.zip
Merge 3.1-rc4 into staging-next
This resolves a conflict with: drivers/staging/brcm80211/brcmsmac/types.h Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/iio')
-rw-r--r--drivers/staging/iio/Documentation/sysfs-bus-iio23
-rw-r--r--drivers/staging/iio/Documentation/sysfs-bus-iio-adc-ad7280a21
-rw-r--r--drivers/staging/iio/Documentation/sysfs-bus-iio-impedance-analyzer-ad593330
-rw-r--r--drivers/staging/iio/Kconfig1
-rw-r--r--drivers/staging/iio/Makefile1
-rw-r--r--drivers/staging/iio/accel/accel.h87
-rw-r--r--drivers/staging/iio/accel/adis16201_core.c5
-rw-r--r--drivers/staging/iio/accel/adis16201_ring.c19
-rw-r--r--drivers/staging/iio/accel/adis16201_trigger.c13
-rw-r--r--drivers/staging/iio/accel/adis16203_core.c4
-rw-r--r--drivers/staging/iio/accel/adis16203_ring.c12
-rw-r--r--drivers/staging/iio/accel/adis16203_trigger.c14
-rw-r--r--drivers/staging/iio/accel/adis16204_core.c48
-rw-r--r--drivers/staging/iio/accel/adis16204_ring.c12
-rw-r--r--drivers/staging/iio/accel/adis16204_trigger.c14
-rw-r--r--drivers/staging/iio/accel/adis16209_core.c4
-rw-r--r--drivers/staging/iio/accel/adis16209_ring.c12
-rw-r--r--drivers/staging/iio/accel/adis16209_trigger.c14
-rw-r--r--drivers/staging/iio/accel/adis16220_core.c343
-rw-r--r--drivers/staging/iio/accel/adis16240_core.c3
-rw-r--r--drivers/staging/iio/accel/adis16240_ring.c12
-rw-r--r--drivers/staging/iio/accel/adis16240_trigger.c14
-rw-r--r--drivers/staging/iio/accel/inclinometer.h25
-rw-r--r--drivers/staging/iio/accel/kxsd9.c269
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_core.c27
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_ring.c18
-rw-r--r--drivers/staging/iio/accel/sca3000_core.c20
-rw-r--r--drivers/staging/iio/accel/sca3000_ring.c71
-rw-r--r--drivers/staging/iio/adc/Kconfig24
-rw-r--r--drivers/staging/iio/adc/Makefile2
-rw-r--r--drivers/staging/iio/adc/ad7150.c11
-rw-r--r--drivers/staging/iio/adc/ad7152.c1
-rw-r--r--drivers/staging/iio/adc/ad7192.c1184
-rw-r--r--drivers/staging/iio/adc/ad7192.h47
-rw-r--r--drivers/staging/iio/adc/ad7280a.c992
-rw-r--r--drivers/staging/iio/adc/ad7280a.h38
-rw-r--r--drivers/staging/iio/adc/ad7291.c1
-rw-r--r--drivers/staging/iio/adc/ad7298_core.c2
-rw-r--r--drivers/staging/iio/adc/ad7298_ring.c12
-rw-r--r--drivers/staging/iio/adc/ad7314.c1
-rw-r--r--drivers/staging/iio/adc/ad7476_core.c2
-rw-r--r--drivers/staging/iio/adc/ad7476_ring.c12
-rw-r--r--drivers/staging/iio/adc/ad7606_core.c2
-rw-r--r--drivers/staging/iio/adc/ad7606_ring.c12
-rw-r--r--drivers/staging/iio/adc/ad7745.c1
-rw-r--r--drivers/staging/iio/adc/ad7780.c2
-rw-r--r--drivers/staging/iio/adc/ad7793.c10
-rw-r--r--drivers/staging/iio/adc/ad7816.c3
-rw-r--r--drivers/staging/iio/adc/ad7887_core.c3
-rw-r--r--drivers/staging/iio/adc/ad7887_ring.c13
-rw-r--r--drivers/staging/iio/adc/ad799x_core.c14
-rw-r--r--drivers/staging/iio/adc/ad799x_ring.c13
-rw-r--r--drivers/staging/iio/adc/adc.h42
-rw-r--r--drivers/staging/iio/adc/adt7310.c1
-rw-r--r--drivers/staging/iio/adc/adt7410.c1
-rw-r--r--drivers/staging/iio/adc/adt75.c3
-rw-r--r--drivers/staging/iio/adc/max1363_core.c20
-rw-r--r--drivers/staging/iio/adc/max1363_ring.c13
-rw-r--r--drivers/staging/iio/addac/adt7316-i2c.c1
-rw-r--r--drivers/staging/iio/addac/adt7316.c3
-rw-r--r--drivers/staging/iio/dac/ad5446.c1
-rw-r--r--drivers/staging/iio/dac/ad5504.c5
-rw-r--r--drivers/staging/iio/dac/ad5624r_spi.c1
-rw-r--r--drivers/staging/iio/dac/ad5686.c1
-rw-r--r--drivers/staging/iio/dac/ad5791.c2
-rw-r--r--drivers/staging/iio/dds/ad5930.c1
-rw-r--r--drivers/staging/iio/dds/ad9832.c1
-rw-r--r--drivers/staging/iio/dds/ad9834.c1
-rw-r--r--drivers/staging/iio/dds/ad9850.c1
-rw-r--r--drivers/staging/iio/dds/ad9852.c2
-rw-r--r--drivers/staging/iio/dds/ad9910.c2
-rw-r--r--drivers/staging/iio/dds/ad9951.c2
-rw-r--r--drivers/staging/iio/gyro/adis16060_core.c116
-rw-r--r--drivers/staging/iio/gyro/adis16080_core.c93
-rw-r--r--drivers/staging/iio/gyro/adis16130_core.c145
-rw-r--r--drivers/staging/iio/gyro/adis16260_core.c3
-rw-r--r--drivers/staging/iio/gyro/adis16260_ring.c12
-rw-r--r--drivers/staging/iio/gyro/adis16260_trigger.c14
-rw-r--r--drivers/staging/iio/gyro/adxrs450_core.c253
-rw-r--r--drivers/staging/iio/gyro/gyro.h85
-rw-r--r--drivers/staging/iio/iio.h91
-rw-r--r--drivers/staging/iio/iio_core.h48
-rw-r--r--drivers/staging/iio/iio_core_trigger.h46
-rw-r--r--drivers/staging/iio/impedance-analyzer/Kconfig16
-rw-r--r--drivers/staging/iio/impedance-analyzer/Makefile5
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.c818
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.h28
-rw-r--r--drivers/staging/iio/imu/adis16400_core.c73
-rw-r--r--drivers/staging/iio/imu/adis16400_ring.c12
-rw-r--r--drivers/staging/iio/imu/adis16400_trigger.c14
-rw-r--r--drivers/staging/iio/industrialio-core.c211
-rw-r--r--drivers/staging/iio/industrialio-ring.c1
-rw-r--r--drivers/staging/iio/industrialio-trigger.c82
-rw-r--r--drivers/staging/iio/light/isl29018.c46
-rw-r--r--drivers/staging/iio/light/tsl2563.c4
-rw-r--r--drivers/staging/iio/light/tsl2583.c221
-rw-r--r--drivers/staging/iio/magnetometer/ak8975.c214
-rw-r--r--drivers/staging/iio/magnetometer/hmc5843.c96
-rw-r--r--drivers/staging/iio/magnetometer/magnet.h31
-rw-r--r--drivers/staging/iio/meter/ade7753.c1
-rw-r--r--drivers/staging/iio/meter/ade7754.c1
-rw-r--r--drivers/staging/iio/meter/ade7758_core.c1
-rw-r--r--drivers/staging/iio/meter/ade7758_ring.c19
-rw-r--r--drivers/staging/iio/meter/ade7758_trigger.c16
-rw-r--r--drivers/staging/iio/meter/ade7759.c1
-rw-r--r--drivers/staging/iio/meter/ade7854-i2c.c1
-rw-r--r--drivers/staging/iio/meter/ade7854-spi.c1
-rw-r--r--drivers/staging/iio/meter/ade7854.c3
-rw-r--r--drivers/staging/iio/resolver/ad2s120x.c1
-rw-r--r--drivers/staging/iio/resolver/ad2s1210.c2
-rw-r--r--drivers/staging/iio/resolver/ad2s90.c2
-rw-r--r--drivers/staging/iio/sysfs.h79
-rw-r--r--drivers/staging/iio/trigger.h116
-rw-r--r--drivers/staging/iio/trigger/iio-trig-bfin-timer.c6
-rw-r--r--drivers/staging/iio/trigger/iio-trig-gpio.c6
-rw-r--r--drivers/staging/iio/trigger/iio-trig-periodic-rtc.c7
-rw-r--r--drivers/staging/iio/trigger/iio-trig-sysfs.c13
-rw-r--r--drivers/staging/iio/trigger_consumer.h71
118 files changed, 4745 insertions, 2022 deletions
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio b/drivers/staging/iio/Documentation/sysfs-bus-iio
index 467c49a47258..c19dbf4ab249 100644
--- a/drivers/staging/iio/Documentation/sysfs-bus-iio
+++ b/drivers/staging/iio/Documentation/sysfs-bus-iio
@@ -2,7 +2,7 @@ What: /sys/bus/iio/devices/deviceX
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
- Hardware chip or device accessed by on communication port.
+ Hardware chip or device accessed by one communication port.
Corresponds to a grouping of sensor channels. X is the IIO
index of the device.
@@ -711,3 +711,24 @@ Contact: linux-iio@xxxxxxxxxxxxxxx
Description:
This attribute is used to read the amount of quadrature error
present in the device at a given time.
+
+What: /sys/.../iio:deviceX/ac_excitation_en
+KernelVersion: 3.1.0
+Contact: linux-iio@vger.kernel.org
+Description:
+ This attribute, if available, is used to enable the AC
+ excitation mode found on some converters. In ac excitation mode,
+ the polarity of the excitation voltage is reversed on
+ alternate cycles, to eliminate DC errors.
+
+What: /sys/.../iio:deviceX/bridge_switch_en
+KernelVersion: 3.1.0
+Contact: linux-iio@vger.kernel.org
+Description:
+ This attribute, if available, is used to close or open the
+ bridge power down switch found on some converters.
+ In bridge applications, such as strain gauges and load cells,
+ the bridge itself consumes the majority of the current in the
+ system. To minimize the current consumption of the system,
+ the bridge can be disconnected (when it is not being used
+ using the bridge_switch_en attribute.
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-adc-ad7280a b/drivers/staging/iio/Documentation/sysfs-bus-iio-adc-ad7280a
new file mode 100644
index 000000000000..863d3856718a
--- /dev/null
+++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-adc-ad7280a
@@ -0,0 +1,21 @@
+What: /sys/bus/iio/devices/deviceX/inY-inZ_balance_switch_en
+KernelVersion: 3.0.0
+Contact: linux-iio@vger.kernel.org
+Description:
+ Writing 1 enables the cell balance output switch corresponding
+ to input Y. Writing 0 disables it. If the inY-inZ_balance_timer
+ is set to a none zero value, the corresponding switch will
+ enable for the programmed amount of time, before it
+ automatically disables.
+
+What: /sys/bus/iio/devices/deviceX/inY-inZ_balance_timer
+KernelVersion: 3.0.0
+Contact: linux-iio@vger.kernel.org
+Description:
+ The inY-inZ_balance_timer file allows the user to program
+ individual times for each cell balance output. The AD7280A
+ allows the user to set the timer to a value from 0 minutes to
+ 36.9 minutes. The resolution of the timer is 71.5 sec.
+ The value written is the on-time in milliseconds. When the
+ timer value is set 0, the timer is disabled. The cell balance
+ outputs are controlled only by inY-inZ_balance_switch_en.
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-impedance-analyzer-ad5933 b/drivers/staging/iio/Documentation/sysfs-bus-iio-impedance-analyzer-ad5933
new file mode 100644
index 000000000000..79c7e88c64cd
--- /dev/null
+++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-impedance-analyzer-ad5933
@@ -0,0 +1,30 @@
+What: /sys/bus/iio/devices/iio:deviceX/outY_freq_start
+KernelVersion: 3.1.0
+Contact: linux-iio@vger.kernel.org
+Description:
+ Frequency sweep start frequency in Hz.
+
+What: /sys/bus/iio/devices/iio:deviceX/outY_freq_increment
+KernelVersion: 3.1.0
+Contact: linux-iio@vger.kernel.org
+Description:
+ Frequency increment in Hz (step size) between consecutive
+ frequency points along the sweep.
+
+What: /sys/bus/iio/devices/iio:deviceX/outY_freq_points
+KernelVersion: 3.1.0
+Contact: linux-iio@vger.kernel.org
+Description:
+ Number of frequency points (steps) in the frequency sweep.
+ This value, in conjunction with the outY_freq_start and the
+ outY_freq_increment, determines the frequency sweep range
+ for the sweep operation.
+
+What: /sys/bus/iio/devices/iio:deviceX/outY_settling_cycles
+KernelVersion: 3.1.0
+Contact: linux-iio@vger.kernel.org
+Description:
+ Number of output excitation cycles (settling time cycles)
+ that are allowed to pass through the unknown impedance,
+ after each frequency increment, and before the ADC is triggered
+ to perform a conversion sequence of the response signal.
diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig
index d329635fb5c4..75265678348f 100644
--- a/drivers/staging/iio/Kconfig
+++ b/drivers/staging/iio/Kconfig
@@ -62,6 +62,7 @@ source "drivers/staging/iio/addac/Kconfig"
source "drivers/staging/iio/dac/Kconfig"
source "drivers/staging/iio/dds/Kconfig"
source "drivers/staging/iio/gyro/Kconfig"
+source "drivers/staging/iio/impedance-analyzer/Kconfig"
source "drivers/staging/iio/imu/Kconfig"
source "drivers/staging/iio/light/Kconfig"
source "drivers/staging/iio/magnetometer/Kconfig"
diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile
index bb5c95c7d694..eaff649faf95 100644
--- a/drivers/staging/iio/Makefile
+++ b/drivers/staging/iio/Makefile
@@ -16,6 +16,7 @@ obj-y += addac/
obj-y += dac/
obj-y += dds/
obj-y += gyro/
+obj-y += impedance-analyzer/
obj-y += imu/
obj-y += light/
obj-y += magnetometer/
diff --git a/drivers/staging/iio/accel/accel.h b/drivers/staging/iio/accel/accel.h
deleted file mode 100644
index 50651f835cea..000000000000
--- a/drivers/staging/iio/accel/accel.h
+++ /dev/null
@@ -1,87 +0,0 @@
-
-#include "../sysfs.h"
-
-/* Accelerometer types of attribute */
-#define IIO_DEV_ATTR_ACCEL_OFFSET(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_offset, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_X_OFFSET(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_x_offset, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_Y_OFFSET(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_y_offset, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_Z_OFFSET(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_z_offset, _mode, _show, _store, _addr)
-
-#define IIO_CONST_ATTR_ACCEL_SCALE(_string) \
- IIO_CONST_ATTR(accel_scale, _string)
-
-#define IIO_DEV_ATTR_ACCEL_SCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_scale, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_X_SCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_x_scale, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_Y_SCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_y_scale, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_Z_SCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_z_scale, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_CALIBBIAS(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_calibbias, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_X_CALIBBIAS(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_x_calibbias, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_Y_CALIBBIAS(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_y_calibbias, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_Z_CALIBBIAS(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_z_calibbias, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_CALIBSCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_calibscale, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_X_CALIBSCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_x_calibscale, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_Y_CALIBSCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_y_calibscale, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_Z_CALIBSCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_z_calibscale, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_ACCEL(_show, _addr) \
- IIO_DEVICE_ATTR(accel_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_X(_show, _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_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_Z(_show, _addr) \
- IIO_DEVICE_ATTR(accel_z_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_XY(_show, _addr) \
- IIO_DEVICE_ATTR(accel_xy, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_PEAK(_show, _addr) \
- IIO_DEVICE_ATTR(accel_peak, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_XPEAK(_show, _addr) \
- IIO_DEVICE_ATTR(accel_xpeak, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_YPEAK(_show, _addr) \
- IIO_DEVICE_ATTR(accel_ypeak, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_ZPEAK(_show, _addr) \
- IIO_DEVICE_ATTR(accel_zpeak, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_XYPEAK(_show, _addr) \
- IIO_DEVICE_ATTR(accel_xypeak, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_XYZPEAK(_show, _addr) \
- IIO_DEVICE_ATTR(accel_xyzpeak, S_IRUGO, _show, NULL, _addr)
diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c
index 2fd01aecdf96..2b8c5e9c33e5 100644
--- a/drivers/staging/iio/accel/adis16201_core.c
+++ b/drivers/staging/iio/accel/adis16201_core.c
@@ -13,15 +13,12 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
#include "../ring_generic.h"
-#include "accel.h"
-#include "inclinometer.h"
-#include "../adc/adc.h"
-
#include "adis16201.h"
enum adis16201_chan {
diff --git a/drivers/staging/iio/accel/adis16201_ring.c b/drivers/staging/iio/accel/adis16201_ring.c
index 66e708ddf8b2..4b433c53e5c5 100644
--- a/drivers/staging/iio/accel/adis16201_ring.c
+++ b/drivers/staging/iio/accel/adis16201_ring.c
@@ -1,17 +1,12 @@
#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <linux/mutex.h>
-#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
-#include <linux/sysfs.h>
#include "../iio.h"
-#include "../sysfs.h"
#include "../ring_sw.h"
-#include "accel.h"
-#include "../trigger.h"
+#include "../trigger_consumer.h"
#include "adis16201.h"
@@ -38,10 +33,12 @@ static int adis16201_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
xfers[i].cs_change = 1;
xfers[i].len = 2;
xfers[i].delay_usecs = 20;
- xfers[i].tx_buf = st->tx + 2 * i;
- st->tx[2 * i] = ADIS16201_READ_REG(ADIS16201_SUPPLY_OUT +
- 2 * i);
- st->tx[2 * i + 1] = 0;
+ if (i < ADIS16201_OUTPUTS) {
+ xfers[i].tx_buf = st->tx + 2 * i;
+ st->tx[2 * i] = ADIS16201_READ_REG(ADIS16201_SUPPLY_OUT +
+ 2 * i);
+ st->tx[2 * i + 1] = 0;
+ }
if (i >= 1)
xfers[i].rx_buf = rx + 2 * (i - 1);
spi_message_add_tail(&xfers[i], &msg);
@@ -62,7 +59,7 @@ static int adis16201_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
static irqreturn_t adis16201_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
+ struct iio_dev *indio_dev = pf->indio_dev;
struct adis16201_state *st = iio_priv(indio_dev);
struct iio_ring_buffer *ring = indio_dev->ring;
diff --git a/drivers/staging/iio/accel/adis16201_trigger.c b/drivers/staging/iio/accel/adis16201_trigger.c
index 3a95c083b452..f448258884c5 100644
--- a/drivers/staging/iio/accel/adis16201_trigger.c
+++ b/drivers/staging/iio/accel/adis16201_trigger.c
@@ -1,13 +1,8 @@
#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/spi/spi.h>
#include "../iio.h"
-#include "../sysfs.h"
#include "../trigger.h"
#include "adis16201.h"
@@ -23,6 +18,11 @@ static int adis16201_data_rdy_trigger_set_state(struct iio_trigger *trig,
return adis16201_set_irq(indio_dev, state);
}
+static const struct iio_trigger_ops adis16201_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &adis16201_data_rdy_trigger_set_state,
+};
+
int adis16201_probe_trigger(struct iio_dev *indio_dev)
{
int ret;
@@ -41,9 +41,8 @@ int adis16201_probe_trigger(struct iio_dev *indio_dev)
if (ret)
goto error_free_trig;
st->trig->dev.parent = &st->us->dev;
- st->trig->owner = THIS_MODULE;
+ st->trig->ops = &adis16201_trigger_ops;
st->trig->private_data = indio_dev;
- st->trig->set_trigger_state = &adis16201_data_rdy_trigger_set_state;
ret = iio_trigger_register(st->trig);
/* select default trigger */
diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c
index cf5d15da76ad..148367627369 100644
--- a/drivers/staging/iio/accel/adis16203_core.c
+++ b/drivers/staging/iio/accel/adis16203_core.c
@@ -13,13 +13,11 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
-#include "accel.h"
-#include "inclinometer.h"
#include "../ring_generic.h"
-#include "../adc/adc.h"
#include "adis16203.h"
diff --git a/drivers/staging/iio/accel/adis16203_ring.c b/drivers/staging/iio/accel/adis16203_ring.c
index d2c07c527467..993e239f9426 100644
--- a/drivers/staging/iio/accel/adis16203_ring.c
+++ b/drivers/staging/iio/accel/adis16203_ring.c
@@ -1,20 +1,12 @@
#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/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
#include "../iio.h"
-#include "../sysfs.h"
#include "../ring_sw.h"
-#include "accel.h"
-#include "../trigger.h"
+#include "../trigger_consumer.h"
#include "adis16203.h"
/**
@@ -67,7 +59,7 @@ static int adis16203_read_ring_data(struct device *dev, u8 *rx)
static irqreturn_t adis16203_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
+ struct iio_dev *indio_dev = pf->indio_dev;
struct adis16203_state *st = iio_priv(indio_dev);
struct iio_ring_buffer *ring = indio_dev->ring;
diff --git a/drivers/staging/iio/accel/adis16203_trigger.c b/drivers/staging/iio/accel/adis16203_trigger.c
index 3caf3e8bc9d9..50165f9ddc52 100644
--- a/drivers/staging/iio/accel/adis16203_trigger.c
+++ b/drivers/staging/iio/accel/adis16203_trigger.c
@@ -1,14 +1,8 @@
#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 "adis16203.h"
@@ -24,6 +18,11 @@ static int adis16203_data_rdy_trigger_set_state(struct iio_trigger *trig,
return adis16203_set_irq(indio_dev, state);
}
+static const struct iio_trigger_ops adis16203_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &adis16203_data_rdy_trigger_set_state,
+};
+
int adis16203_probe_trigger(struct iio_dev *indio_dev)
{
int ret;
@@ -44,9 +43,8 @@ int adis16203_probe_trigger(struct iio_dev *indio_dev)
goto error_free_trig;
st->trig->dev.parent = &st->us->dev;
- st->trig->owner = THIS_MODULE;
+ st->trig->ops = &adis16203_trigger_ops;
st->trig->private_data = indio_dev;
- st->trig->set_trigger_state = &adis16203_data_rdy_trigger_set_state;
ret = iio_trigger_register(st->trig);
/* select default trigger */
diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c
index 3e2b62654b7d..445a75b1d540 100644
--- a/drivers/staging/iio/accel/adis16204_core.c
+++ b/drivers/staging/iio/accel/adis16204_core.c
@@ -17,12 +17,11 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
#include "../ring_generic.h"
-#include "accel.h"
-#include "../adc/adc.h"
#include "adis16204.h"
@@ -299,12 +298,15 @@ static int adis16204_initial_setup(struct iio_dev *indio_dev)
err_ret:
return ret;
}
+
+/* Unique to this driver currently */
+#define IIO_DEV_ATTR_ACCEL_XY(_show, _addr) \
+ IIO_DEVICE_ATTR(accel_xy, S_IRUGO, _show, NULL, _addr)
+#define IIO_DEV_ATTR_ACCEL_XYPEAK(_show, _addr) \
+ IIO_DEVICE_ATTR(accel_xypeak, S_IRUGO, _show, NULL, _addr)
+
static IIO_DEV_ATTR_ACCEL_XY(adis16204_read_14bit_signed,
ADIS16204_XY_RSS_OUT);
-static IIO_DEV_ATTR_ACCEL_XPEAK(adis16204_read_14bit_signed,
- ADIS16204_X_PEAK_OUT);
-static IIO_DEV_ATTR_ACCEL_YPEAK(adis16204_read_14bit_signed,
- ADIS16204_Y_PEAK_OUT);
static IIO_DEV_ATTR_ACCEL_XYPEAK(adis16204_read_14bit_signed,
ADIS16204_XY_PEAK_OUT);
static IIO_CONST_ATTR(accel_xy_scale, "0.017125");
@@ -319,13 +321,16 @@ enum adis16204_channel {
accel_y,
};
-static u8 adis16204_addresses[5][2] = {
+static u8 adis16204_addresses[5][3] = {
[in_supply] = { ADIS16204_SUPPLY_OUT },
[in_aux] = { ADIS16204_AUX_ADC },
[temp] = { ADIS16204_TEMP_OUT },
- [accel_x] = { ADIS16204_XACCL_OUT, ADIS16204_XACCL_NULL },
- [accel_y] = { ADIS16204_XACCL_OUT, ADIS16204_YACCL_NULL },
+ [accel_x] = { ADIS16204_XACCL_OUT, ADIS16204_XACCL_NULL,
+ ADIS16204_X_PEAK_OUT },
+ [accel_y] = { ADIS16204_XACCL_OUT, ADIS16204_YACCL_NULL,
+ ADIS16204_Y_PEAK_OUT },
};
+
static int adis16204_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2,
@@ -335,6 +340,7 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
int bits;
u8 addr;
s16 val16;
+ int addrind;
switch (mask) {
case 0:
@@ -389,15 +395,16 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
*val = 25;
return IIO_VAL_INT;
case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
- switch (chan->type) {
- case IIO_ACCEL:
+ case (1 << IIO_CHAN_INFO_PEAK_SEPARATE):
+ if (mask == (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE)) {
bits = 12;
- break;
- default:
- return -EINVAL;
- };
+ addrind = 1;
+ } else { /* PEAK_SEPARATE */
+ bits = 14;
+ addrind = 2;
+ }
mutex_lock(&indio_dev->mlock);
- addr = adis16204_addresses[chan->address][1];
+ addr = adis16204_addresses[chan->address][addrind];
ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16);
if (ret) {
mutex_unlock(&indio_dev->mlock);
@@ -453,21 +460,22 @@ static struct iio_chan_spec adis16204_channels[] = {
IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
(1 << IIO_CHAN_INFO_SCALE_SEPARATE) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_PEAK_SEPARATE),
accel_x, ADIS16204_SCAN_ACC_X,
IIO_ST('s', 14, 16, 0), 0),
IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
(1 << IIO_CHAN_INFO_SCALE_SEPARATE) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_PEAK_SEPARATE),
accel_y, ADIS16204_SCAN_ACC_Y,
IIO_ST('s', 14, 16, 0), 0),
IIO_CHAN_SOFT_TIMESTAMP(5),
};
+
static struct attribute *adis16204_attributes[] = {
&iio_dev_attr_reset.dev_attr.attr,
&iio_dev_attr_accel_xy.dev_attr.attr,
- &iio_dev_attr_accel_xpeak.dev_attr.attr,
- &iio_dev_attr_accel_ypeak.dev_attr.attr,
&iio_dev_attr_accel_xypeak.dev_attr.attr,
&iio_const_attr_accel_xy_scale.dev_attr.attr,
NULL
diff --git a/drivers/staging/iio/accel/adis16204_ring.c b/drivers/staging/iio/accel/adis16204_ring.c
index 852df06684d8..847f43858f50 100644
--- a/drivers/staging/iio/accel/adis16204_ring.c
+++ b/drivers/staging/iio/accel/adis16204_ring.c
@@ -1,20 +1,12 @@
#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/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
#include "../iio.h"
-#include "../sysfs.h"
#include "../ring_sw.h"
-#include "accel.h"
-#include "../trigger.h"
+#include "../trigger_consumer.h"
#include "adis16204.h"
/**
@@ -65,7 +57,7 @@ static int adis16204_read_ring_data(struct device *dev, u8 *rx)
static irqreturn_t adis16204_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
+ struct iio_dev *indio_dev = pf->indio_dev;
struct adis16204_state *st = iio_priv(indio_dev);
struct iio_ring_buffer *ring = indio_dev->ring;
int i = 0;
diff --git a/drivers/staging/iio/accel/adis16204_trigger.c b/drivers/staging/iio/accel/adis16204_trigger.c
index 01f73b9b8886..55b661c98d2d 100644
--- a/drivers/staging/iio/accel/adis16204_trigger.c
+++ b/drivers/staging/iio/accel/adis16204_trigger.c
@@ -1,14 +1,8 @@
#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 "adis16204.h"
@@ -24,6 +18,11 @@ static int adis16204_data_rdy_trigger_set_state(struct iio_trigger *trig,
return adis16204_set_irq(indio_dev, state);
}
+static const struct iio_trigger_ops adis16204_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &adis16204_data_rdy_trigger_set_state,
+};
+
int adis16204_probe_trigger(struct iio_dev *indio_dev)
{
int ret;
@@ -44,9 +43,8 @@ int adis16204_probe_trigger(struct iio_dev *indio_dev)
goto error_free_trig;
st->trig->dev.parent = &st->us->dev;
- st->trig->owner = THIS_MODULE;
+ st->trig->ops = &adis16204_trigger_ops;
st->trig->private_data = indio_dev;
- st->trig->set_trigger_state = &adis16204_data_rdy_trigger_set_state;
ret = iio_trigger_register(st->trig);
/* select default trigger */
diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c
index bec1fa8de9b9..ca671ddc152d 100644
--- a/drivers/staging/iio/accel/adis16209_core.c
+++ b/drivers/staging/iio/accel/adis16209_core.c
@@ -14,13 +14,11 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
#include "../ring_generic.h"
-#include "accel.h"
-#include "inclinometer.h"
-#include "../adc/adc.h"
#include "adis16209.h"
diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c
index 45017d3f02f5..f889fe72f33a 100644
--- a/drivers/staging/iio/accel/adis16209_ring.c
+++ b/drivers/staging/iio/accel/adis16209_ring.c
@@ -1,20 +1,12 @@
#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/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
#include "../iio.h"
-#include "../sysfs.h"
#include "../ring_sw.h"
-#include "accel.h"
-#include "../trigger.h"
+#include "../trigger_consumer.h"
#include "adis16209.h"
/**
@@ -65,7 +57,7 @@ static int adis16209_read_ring_data(struct device *dev, u8 *rx)
static irqreturn_t adis16209_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
+ struct iio_dev *indio_dev = pf->indio_dev;
struct adis16209_state *st = iio_priv(indio_dev);
struct iio_ring_buffer *ring = indio_dev->ring;
diff --git a/drivers/staging/iio/accel/adis16209_trigger.c b/drivers/staging/iio/accel/adis16209_trigger.c
index 6df7b47ec7b4..8df8a9791d5e 100644
--- a/drivers/staging/iio/accel/adis16209_trigger.c
+++ b/drivers/staging/iio/accel/adis16209_trigger.c
@@ -1,14 +1,8 @@
#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 "adis16209.h"
@@ -33,6 +27,11 @@ static int adis16209_data_rdy_trigger_set_state(struct iio_trigger *trig,
return adis16209_set_irq(indio_dev, state);
}
+static const struct iio_trigger_ops adis16209_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &adis16209_data_rdy_trigger_set_state,
+};
+
int adis16209_probe_trigger(struct iio_dev *indio_dev)
{
int ret;
@@ -52,9 +51,8 @@ int adis16209_probe_trigger(struct iio_dev *indio_dev)
if (ret)
goto error_free_trig;
st->trig->dev.parent = &st->us->dev;
- st->trig->owner = THIS_MODULE;
+ st->trig->ops = &adis16209_trigger_ops;
st->trig->private_data = indio_dev;
- st->trig->set_trigger_state = &adis16209_data_rdy_trigger_set_state;
ret = iio_trigger_register(st->trig);
/* select default trigger */
diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c
index bf9ba07c0383..18b0830b82f9 100644
--- a/drivers/staging/iio/accel/adis16220_core.c
+++ b/drivers/staging/iio/accel/adis16220_core.c
@@ -6,9 +6,6 @@
* 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>
@@ -16,12 +13,10 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
-#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
-#include "accel.h"
-#include "../adc/adc.h"
#include "adis16220.h"
@@ -29,16 +24,15 @@
/**
* adis16220_spi_write_reg_8() - write single byte to a register
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @indio_dev: iio device associated with child of actual device
* @reg_address: the address of the register to be written
* @val: the value to write
**/
-static int adis16220_spi_write_reg_8(struct device *dev,
+static int adis16220_spi_write_reg_8(struct iio_dev *indio_dev,
u8 reg_address,
u8 val)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16220_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
@@ -53,18 +47,17 @@ static int adis16220_spi_write_reg_8(struct device *dev,
/**
* adis16220_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)
+ * @indio_dev: iio device associated with child of actual device
* @reg_address: the address of the lower of the two registers. Second register
* is assumed to have address one greater.
* @val: value to be written
**/
-static int adis16220_spi_write_reg_16(struct device *dev,
+static int adis16220_spi_write_reg_16(struct iio_dev *indio_dev,
u8 lower_reg_address,
u16 value)
{
int ret;
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16220_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[] = {
{
@@ -77,7 +70,6 @@ static int adis16220_spi_write_reg_16(struct device *dev,
.tx_buf = st->tx + 2,
.bits_per_word = 8,
.len = 2,
- .cs_change = 1,
.delay_usecs = 35,
},
};
@@ -99,17 +91,16 @@ static int adis16220_spi_write_reg_16(struct device *dev,
/**
* adis16220_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)
+ * @indio_dev: iio device associated with child of actual device
* @reg_address: the address of the lower of the two registers. Second register
* is assumed to have address one greater.
* @val: somewhere to pass back the value read
**/
-static int adis16220_spi_read_reg_16(struct device *dev,
- u8 lower_reg_address,
- u16 *val)
+static int adis16220_spi_read_reg_16(struct iio_dev *indio_dev,
+ u8 lower_reg_address,
+ u16 *val)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16220_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
@@ -149,52 +140,23 @@ error_ret:
return ret;
}
-static ssize_t adis16220_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 = adis16220_spi_read_reg_16(dev, this_attr->address, (u16 *)&val);
- if (ret)
- return ret;
-
- val = ((s16)(val << shift) >> shift);
- return sprintf(buf, "%d\n", val);
-}
-
-static ssize_t adis16220_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 = adis16220_spi_read_reg_16(dev, this_attr->address, &val);
- if (ret)
- return ret;
-
- return sprintf(buf, "%u\n", val & 0x0FFF);
-}
-
static ssize_t adis16220_read_16bit(struct device *dev,
struct device_attribute *attr,
char *buf)
{
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct iio_dev *indio_dev = dev_get_drvdata(dev);
ssize_t ret;
+ s16 val = 0;
/* Take the iio_dev status lock */
mutex_lock(&indio_dev->mlock);
- ret = adis16220_spi_read_signed(dev, attr, buf, 16);
+ ret = adis16220_spi_read_reg_16(indio_dev, this_attr->address,
+ (u16 *)&val);
mutex_unlock(&indio_dev->mlock);
-
- return ret;
+ if (ret)
+ return ret;
+ return sprintf(buf, "%d\n", val);
}
static ssize_t adis16220_write_16bit(struct device *dev,
@@ -202,6 +164,7 @@ static ssize_t adis16220_write_16bit(struct device *dev,
const char *buf,
size_t len)
{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
long val;
@@ -209,34 +172,34 @@ static ssize_t adis16220_write_16bit(struct device *dev,
ret = strict_strtol(buf, 10, &val);
if (ret)
goto error_ret;
- ret = adis16220_spi_write_reg_16(dev, this_attr->address, val);
+ ret = adis16220_spi_write_reg_16(indio_dev, this_attr->address, val);
error_ret:
return ret ? ret : len;
}
-static int adis16220_capture(struct device *dev)
+static int adis16220_capture(struct iio_dev *indio_dev)
{
int ret;
- ret = adis16220_spi_write_reg_16(dev,
+ ret = adis16220_spi_write_reg_16(indio_dev,
ADIS16220_GLOB_CMD,
0xBF08); /* initiates a manual data capture */
if (ret)
- dev_err(dev, "problem beginning capture");
+ dev_err(&indio_dev->dev, "problem beginning capture");
msleep(10); /* delay for capture to finish */
return ret;
}
-static int adis16220_reset(struct device *dev)
+static int adis16220_reset(struct iio_dev *indio_dev)
{
int ret;
- ret = adis16220_spi_write_reg_8(dev,
+ ret = adis16220_spi_write_reg_8(indio_dev,
ADIS16220_GLOB_CMD,
ADIS16220_GLOB_CMD_SW_RESET);
if (ret)
- dev_err(dev, "problem resetting device");
+ dev_err(&indio_dev->dev, "problem resetting device");
return ret;
}
@@ -245,72 +208,84 @@ static ssize_t adis16220_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 adis16220_reset(dev) == 0 ? len : -EIO;
- }
- return -1;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ bool val;
+ int ret;
+
+ ret = strtobool(buf, &val);
+ if (ret)
+ return ret;
+ if (!val)
+ return -EINVAL;
+
+ ret = adis16220_reset(indio_dev);
+ if (ret)
+ return ret;
+ return len;
}
static ssize_t adis16220_write_capture(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 adis16220_capture(dev) == 0 ? len : -EIO;
- }
- return -1;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ bool val;
+ int ret;
+
+ ret = strtobool(buf, &val);
+ if (ret)
+ return ret;
+ if (!val)
+ return -EINVAL;
+ ret = adis16220_capture(indio_dev);
+ if (ret)
+ return ret;
+
+ return len;
}
-static int adis16220_check_status(struct device *dev)
+static int adis16220_check_status(struct iio_dev *indio_dev)
{
u16 status;
int ret;
- ret = adis16220_spi_read_reg_16(dev, ADIS16220_DIAG_STAT, &status);
+ ret = adis16220_spi_read_reg_16(indio_dev, ADIS16220_DIAG_STAT,
+ &status);
if (ret < 0) {
- dev_err(dev, "Reading status failed\n");
+ dev_err(&indio_dev->dev, "Reading status failed\n");
goto error_ret;
}
ret = status & 0x7F;
if (status & ADIS16220_DIAG_STAT_VIOLATION)
- dev_err(dev, "Capture period violation/interruption\n");
+ dev_err(&indio_dev->dev,
+ "Capture period violation/interruption\n");
if (status & ADIS16220_DIAG_STAT_SPI_FAIL)
- dev_err(dev, "SPI failure\n");
+ dev_err(&indio_dev->dev, "SPI failure\n");
if (status & ADIS16220_DIAG_STAT_FLASH_UPT)
- dev_err(dev, "Flash update failed\n");
+ dev_err(&indio_dev->dev, "Flash update failed\n");
if (status & ADIS16220_DIAG_STAT_POWER_HIGH)
- dev_err(dev, "Power supply above 3.625V\n");
+ dev_err(&indio_dev->dev, "Power supply above 3.625V\n");
if (status & ADIS16220_DIAG_STAT_POWER_LOW)
- dev_err(dev, "Power supply below 3.15V\n");
+ dev_err(&indio_dev->dev, "Power supply below 3.15V\n");
error_ret:
return ret;
}
-static int adis16220_self_test(struct device *dev)
+static int adis16220_self_test(struct iio_dev *indio_dev)
{
int ret;
- ret = adis16220_spi_write_reg_16(dev,
+ ret = adis16220_spi_write_reg_16(indio_dev,
ADIS16220_MSC_CTRL,
ADIS16220_MSC_CTRL_SELF_TEST_EN);
if (ret) {
- dev_err(dev, "problem starting self test");
+ dev_err(&indio_dev->dev, "problem starting self test");
goto err_ret;
}
- adis16220_check_status(dev);
+ adis16220_check_status(indio_dev);
err_ret:
return ret;
@@ -319,24 +294,23 @@ err_ret:
static int adis16220_initial_setup(struct iio_dev *indio_dev)
{
int ret;
- struct device *dev = &indio_dev->dev;
/* Do self test */
- ret = adis16220_self_test(dev);
+ ret = adis16220_self_test(indio_dev);
if (ret) {
- dev_err(dev, "self test failure");
+ dev_err(&indio_dev->dev, "self test failure");
goto err_ret;
}
/* Read status register to check the result */
- ret = adis16220_check_status(dev);
+ ret = adis16220_check_status(indio_dev);
if (ret) {
- adis16220_reset(dev);
- dev_err(dev, "device not playing ball -> reset");
+ adis16220_reset(indio_dev);
+ dev_err(&indio_dev->dev, "device not playing ball -> reset");
msleep(ADIS16220_STARTUP_DELAY);
- ret = adis16220_check_status(dev);
+ ret = adis16220_check_status(indio_dev);
if (ret) {
- dev_err(dev, "giving up");
+ dev_err(&indio_dev->dev, "giving up");
goto err_ret;
}
}
@@ -381,7 +355,7 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
count = ADIS16220_CAPTURE_SIZE - off;
/* write the begin position of capture buffer */
- ret = adis16220_spi_write_reg_16(&indio_dev->dev,
+ ret = adis16220_spi_write_reg_16(indio_dev,
ADIS16220_CAPT_PNTR,
off > 1);
if (ret)
@@ -480,24 +454,6 @@ static struct bin_attribute adc2_bin = {
.size = ADIS16220_CAPTURE_SIZE,
};
-static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16220_read_12bit_unsigned,
- ADIS16220_CAPT_SUPPLY);
-static IIO_CONST_ATTR_IN_NAMED_SCALE(0, supply, "0.0012207");
-static IIO_DEV_ATTR_ACCEL(adis16220_read_16bit, ADIS16220_CAPT_BUFA);
-static IIO_DEVICE_ATTR(accel_peak_raw, S_IRUGO, adis16220_read_16bit,
- NULL, ADIS16220_CAPT_PEAKA);
-static IIO_DEV_ATTR_ACCEL_OFFSET(S_IWUSR | S_IRUGO,
- adis16220_read_16bit,
- adis16220_write_16bit,
- ADIS16220_ACCL_NULL);
-static IIO_CONST_ATTR_ACCEL_SCALE("0.18704223545");
-static IIO_DEV_ATTR_TEMP_RAW(adis16220_read_12bit_unsigned);
-static IIO_CONST_ATTR_TEMP_OFFSET("25");
-static IIO_CONST_ATTR_TEMP_SCALE("-0.47");
-
-static IIO_DEV_ATTR_IN_RAW(1, adis16220_read_16bit, ADIS16220_CAPT_BUF1);
-static IIO_DEV_ATTR_IN_RAW(2, adis16220_read_16bit, ADIS16220_CAPT_BUF2);
-
static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL,
adis16220_write_reset, 0);
@@ -514,21 +470,142 @@ static IIO_DEV_ATTR_CAPTURE_COUNT(S_IWUSR | S_IRUGO,
adis16220_write_16bit,
ADIS16220_CAPT_PNTR);
-static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100200");
+enum adis16220_channel {
+ in_supply, in_1, in_2, accel, temp
+};
+
+struct adis16220_address_spec {
+ u8 addr;
+ u8 bits;
+ bool sign;
+};
+
+/* Address / bits / signed */
+static const struct adis16220_address_spec adis16220_addresses[][3] = {
+ [in_supply] = { { ADIS16220_CAPT_SUPPLY, 12, 0 }, },
+ [in_1] = { { ADIS16220_CAPT_BUF1, 16, 1 },
+ { ADIS16220_AIN1_NULL, 16, 1 },
+ { ADIS16220_CAPT_PEAK1, 16, 1 }, },
+ [in_2] = { { ADIS16220_CAPT_BUF2, 16, 1 },
+ { ADIS16220_AIN2_NULL, 16, 1 },
+ { ADIS16220_CAPT_PEAK2, 16, 1 }, },
+ [accel] = { { ADIS16220_CAPT_BUFA, 16, 1 },
+ { ADIS16220_ACCL_NULL, 16, 1 },
+ { ADIS16220_CAPT_PEAKA, 16, 1 }, },
+ [temp] = { { ADIS16220_CAPT_TEMP, 12, 0 }, }
+};
+
+static int adis16220_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2,
+ long mask)
+{
+ int ret = -EINVAL;
+ int addrind = 0;
+ u16 uval;
+ s16 sval;
+ u8 bits;
+
+ switch (mask) {
+ case 0:
+ addrind = 0;
+ break;
+ case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ if (chan->type == IIO_TEMP) {
+ *val = 25;
+ return IIO_VAL_INT;
+ }
+ addrind = 1;
+ break;
+ case (1 << IIO_CHAN_INFO_PEAK_SEPARATE):
+ addrind = 2;
+ break;
+ case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ *val = 0;
+ switch (chan->type) {
+ case IIO_TEMP:
+ *val2 = -470000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_ACCEL:
+ *val2 = 1887042;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_IN:
+ if (chan->channel == 0)
+ *val2 = 0012221;
+ else /* Should really be dependent on VDD */
+ *val2 = 305;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+ if (adis16220_addresses[chan->address][addrind].sign) {
+ ret = adis16220_spi_read_reg_16(indio_dev,
+ adis16220_addresses[chan
+ ->address]
+ [addrind].addr,
+ &sval);
+ if (ret)
+ return ret;
+ bits = adis16220_addresses[chan->address][addrind].bits;
+ sval &= (1 << bits) - 1;
+ sval = (s16)(sval << (16 - bits)) >> (16 - bits);
+ *val = sval;
+ return IIO_VAL_INT;
+ } else {
+ ret = adis16220_spi_read_reg_16(indio_dev,
+ adis16220_addresses[chan
+ ->address]
+ [addrind].addr,
+ &uval);
+ if (ret)
+ return ret;
+ bits = adis16220_addresses[chan->address][addrind].bits;
+ uval &= (1 << bits) - 1;
+ *val = uval;
+ return IIO_VAL_INT;
+ }
+}
+
+static const struct iio_chan_spec adis16220_channels[] = {
+ {
+ .type = IIO_IN,
+ .indexed = 1,
+ .channel = 0,
+ .extend_name = "supply",
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .address = in_supply,
+ }, {
+ .type = IIO_ACCEL,
+ .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE) |
+ (1 << IIO_CHAN_INFO_PEAK_SEPARATE),
+ .address = accel,
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .address = temp,
+ }, {
+ .type = IIO_IN,
+ .indexed = 1,
+ .channel = 1,
+ .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .address = in_1,
+ }, {
+ .type = IIO_IN,
+ .indexed = 1,
+ .channel = 2,
+ .address = in_2,
+ }
+};
static struct attribute *adis16220_attributes[] = {
- &iio_dev_attr_in0_supply_raw.dev_attr.attr,
- &iio_const_attr_in0_supply_scale.dev_attr.attr,
- &iio_dev_attr_accel_raw.dev_attr.attr,
- &iio_dev_attr_accel_offset.dev_attr.attr,
- &iio_dev_attr_accel_peak_raw.dev_attr.attr,
- &iio_const_attr_accel_scale.dev_attr.attr,
- &iio_dev_attr_temp_raw.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_dev_attr_in2_raw.dev_attr.attr,
- &iio_const_attr_temp_offset.dev_attr.attr,
- &iio_const_attr_temp_scale.dev_attr.attr,
- &iio_const_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_reset.dev_attr.attr,
&iio_dev_attr_capture.dev_attr.attr,
&iio_dev_attr_capture_count.dev_attr.attr,
@@ -542,7 +619,9 @@ static const struct attribute_group adis16220_attribute_group = {
static const struct iio_info adis16220_info = {
.attrs = &adis16220_attribute_group,
.driver_module = THIS_MODULE,
+ .read_raw = &adis16220_read_raw,
};
+
static int __devinit adis16220_probe(struct spi_device *spi)
{
int ret, regdone = 0;
@@ -567,6 +646,8 @@ static int __devinit adis16220_probe(struct spi_device *spi)
indio_dev->dev.parent = &spi->dev;
indio_dev->info = &adis16220_info;
indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = adis16220_channels;
+ indio_dev->num_channels = ARRAY_SIZE(adis16220_channels);
ret = iio_device_register(indio_dev);
if (ret)
diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c
index aee8b69173c4..d485f7342f8d 100644
--- a/drivers/staging/iio/accel/adis16240_core.c
+++ b/drivers/staging/iio/accel/adis16240_core.c
@@ -17,12 +17,11 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
#include "../ring_generic.h"
-#include "accel.h"
-#include "../adc/adc.h"
#include "adis16240.h"
diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c
index c812a34dacaf..051ba643d340 100644
--- a/drivers/staging/iio/accel/adis16240_ring.c
+++ b/drivers/staging/iio/accel/adis16240_ring.c
@@ -1,20 +1,12 @@
#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/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
#include "../iio.h"
-#include "../sysfs.h"
#include "../ring_sw.h"
-#include "accel.h"
-#include "../trigger.h"
+#include "../trigger_consumer.h"
#include "adis16240.h"
/**
@@ -62,7 +54,7 @@ static int adis16240_read_ring_data(struct device *dev, u8 *rx)
static irqreturn_t adis16240_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
+ struct iio_dev *indio_dev = pf->indio_dev;
struct adis16240_state *st = iio_priv(indio_dev);
struct iio_ring_buffer *ring = indio_dev->ring;
diff --git a/drivers/staging/iio/accel/adis16240_trigger.c b/drivers/staging/iio/accel/adis16240_trigger.c
index 17135fc33c99..13f1d142eea3 100644
--- a/drivers/staging/iio/accel/adis16240_trigger.c
+++ b/drivers/staging/iio/accel/adis16240_trigger.c
@@ -1,14 +1,8 @@
#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 "adis16240.h"
@@ -33,6 +27,11 @@ static int adis16240_data_rdy_trigger_set_state(struct iio_trigger *trig,
return adis16240_set_irq(indio_dev, state);
}
+static const struct iio_trigger_ops adis16240_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &adis16240_data_rdy_trigger_set_state,
+};
+
int adis16240_probe_trigger(struct iio_dev *indio_dev)
{
int ret;
@@ -53,9 +52,8 @@ int adis16240_probe_trigger(struct iio_dev *indio_dev)
goto error_free_trig;
st->trig->dev.parent = &st->us->dev;
- st->trig->owner = THIS_MODULE;
+ st->trig->ops = &adis16240_trigger_ops;
st->trig->private_data = indio_dev;
- st->trig->set_trigger_state = &adis16240_data_rdy_trigger_set_state;
ret = iio_trigger_register(st->trig);
/* select default trigger */
diff --git a/drivers/staging/iio/accel/inclinometer.h b/drivers/staging/iio/accel/inclinometer.h
deleted file mode 100644
index faf73d7892e0..000000000000
--- a/drivers/staging/iio/accel/inclinometer.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Inclinometer related attributes
- */
-#include "../sysfs.h"
-
-#define IIO_DEV_ATTR_INCLI_X(_show, _addr) \
- IIO_DEVICE_ATTR(incli_x_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_INCLI_Y(_show, _addr) \
- IIO_DEVICE_ATTR(incli_y_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_INCLI_Z(_show, _addr) \
- IIO_DEVICE_ATTR(incli_z_raw, 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_CONST_ATTR_INCLI_SCALE(_string) \
- IIO_CONST_ATTR(incli_scale, _string)
diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c
index c8a358a5df87..2a0565181d4d 100644
--- a/drivers/staging/iio/accel/kxsd9.c
+++ b/drivers/staging/iio/accel/kxsd9.c
@@ -21,11 +21,10 @@
#include <linux/spi/spi.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
-#include "../adc/adc.h"
-#include "accel.h"
#define KXSD9_REG_X 0x00
#define KXSD9_REG_Y 0x02
@@ -34,10 +33,6 @@
#define KXSD9_REG_RESET 0x0a
#define KXSD9_REG_CTRL_C 0x0c
-#define KXSD9_FS_8 0x00
-#define KXSD9_FS_6 0x01
-#define KXSD9_FS_4 0x02
-#define KXSD9_FS_2 0x03
#define KXSD9_FS_MASK 0x03
#define KXSD9_REG_CTRL_B 0x0d
@@ -46,13 +41,8 @@
#define KXSD9_READ(a) (0x80 | (a))
#define KXSD9_WRITE(a) (a)
-#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
+#define KXSD9_STATE_TX_SIZE 2
/**
* struct kxsd9_state - device related storage
* @buf_lock: protect the rx and tx buffers.
@@ -67,170 +57,70 @@ struct kxsd9_state {
u8 tx[KXSD9_STATE_TX_SIZE];
};
-/* This may want to move to mili g to allow for non integer ranges */
-static ssize_t kxsd9_read_scale(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int ret;
- ssize_t len = 0;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct kxsd9_state *st = iio_priv(indio_dev);
- struct spi_transfer xfer = {
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 1,
- .tx_buf = st->tx,
- .rx_buf = st->rx,
- };
- struct spi_message msg;
-
- mutex_lock(&st->buf_lock);
- st->tx[0] = KXSD9_READ(KXSD9_REG_CTRL_C);
- st->tx[1] = 0;
- spi_message_init(&msg);
- spi_message_add_tail(&xfer, &msg);
- ret = spi_sync(st->us, &msg);
- if (ret)
- goto error_ret;
-
- switch (st->rx[1] & KXSD9_FS_MASK) {
- case KXSD9_FS_8:
- len += sprintf(buf, "%s\n", KXSD9_SCALE_8G);
- break;
- case KXSD9_FS_6:
- len += sprintf(buf, "%s\n", KXSD9_SCALE_6G);
- break;
- case KXSD9_FS_4:
- len += sprintf(buf, "%s\n", KXSD9_SCALE_4G);
- break;
- case KXSD9_FS_2:
- len += sprintf(buf, "%s\n", KXSD9_SCALE_2G);
- break;
- }
+#define KXSD9_SCALE_2G "0.011978"
+#define KXSD9_SCALE_4G "0.023927"
+#define KXSD9_SCALE_6G "0.035934"
+#define KXSD9_SCALE_8G "0.047853"
-error_ret:
- mutex_unlock(&st->buf_lock);
+/* reverse order */
+static const int kxsd9_micro_scales[4] = { 47853, 35934, 23927, 11978 };
- return ret ? ret : len;
-}
-static ssize_t kxsd9_write_scale(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro)
{
-
- struct spi_message msg;
- int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ int ret, i;
struct kxsd9_state *st = iio_priv(indio_dev);
- u8 val;
- struct spi_transfer xfers[] = {
- {
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 1,
- .tx_buf = st->tx,
- .rx_buf = st->rx,
- }, {
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 1,
- .tx_buf = st->tx,
- },
- };
-
- if (!strncmp(buf, KXSD9_SCALE_8G,
- strlen(buf) < strlen(KXSD9_SCALE_8G)
- ? strlen(buf) : strlen(KXSD9_SCALE_8G)))
- val = KXSD9_FS_8;
- else if (!strncmp(buf, KXSD9_SCALE_6G,
- strlen(buf) < strlen(KXSD9_SCALE_6G)
- ? strlen(buf) : strlen(KXSD9_SCALE_6G)))
- val = KXSD9_FS_6;
- else if (!strncmp(buf, KXSD9_SCALE_4G,
- strlen(buf) < strlen(KXSD9_SCALE_4G)
- ? strlen(buf) : strlen(KXSD9_SCALE_4G)))
- val = KXSD9_FS_4;
- else if (!strncmp(buf, KXSD9_SCALE_2G,
- strlen(buf) < strlen(KXSD9_SCALE_2G)
- ? strlen(buf) : strlen(KXSD9_SCALE_2G)))
- val = KXSD9_FS_2;
- else
+ bool foundit = false;
+
+ for (i = 0; i < 4; i++)
+ if (micro == kxsd9_micro_scales[i]) {
+ foundit = true;
+ break;
+ }
+ if (!foundit)
return -EINVAL;
mutex_lock(&st->buf_lock);
- st->tx[0] = KXSD9_READ(KXSD9_REG_CTRL_C);
- st->tx[1] = 0;
- spi_message_init(&msg);
- spi_message_add_tail(&xfers[0], &msg);
- ret = spi_sync(st->us, &msg);
+ ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C));
if (ret)
goto error_ret;
st->tx[0] = KXSD9_WRITE(KXSD9_REG_CTRL_C);
- st->tx[1] = (st->rx[1] & ~KXSD9_FS_MASK) | val;
+ st->tx[1] = (ret & ~KXSD9_FS_MASK) | i;
- spi_message_init(&msg);
- spi_message_add_tail(&xfers[1], &msg);
- ret = spi_sync(st->us, &msg);
+ ret = spi_write(st->us, st->tx, 2);
error_ret:
mutex_unlock(&st->buf_lock);
- return ret ? ret : len;
+ return ret;
}
-static ssize_t kxsd9_read_accel(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int kxsd9_read(struct iio_dev *indio_dev, u8 address)
{
struct spi_message msg;
int ret;
- ssize_t len = 0;
- u16 val;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct kxsd9_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[] = {
{
.bits_per_word = 8,
.len = 1,
- .cs_change = 0,
.delay_usecs = 200,
.tx_buf = st->tx,
}, {
.bits_per_word = 8,
.len = 2,
- .cs_change = 1,
.rx_buf = st->rx,
},
};
mutex_lock(&st->buf_lock);
- st->tx[0] = KXSD9_READ(this_attr->address);
+ st->tx[0] = KXSD9_READ(address);
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)
- goto error_ret;
- val = (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0);
- len = sprintf(buf, "%d\n", val);
-error_ret:
- mutex_unlock(&st->buf_lock);
-
- return ret ? ret : len;
+ return ret;
+ return (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0);
}
-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_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 " "
@@ -238,48 +128,94 @@ static IIO_CONST_ATTR(accel_scale_available,
KXSD9_SCALE_8G);
static struct attribute *kxsd9_attributes[] = {
- &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,
};
+static int kxsd9_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
+{
+ int ret = -EINVAL;
+
+ if (mask == (1 << IIO_CHAN_INFO_SCALE_SHARED)) {
+ /* Check no integer component */
+ if (val)
+ return -EINVAL;
+ ret = kxsd9_write_scale(indio_dev, val2);
+ }
+
+ return ret;
+}
+
+static int kxsd9_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ int ret = -EINVAL;
+ struct kxsd9_state *st = iio_priv(indio_dev);
+
+ switch (mask) {
+ case 0:
+ ret = kxsd9_read(indio_dev, chan->address);
+ if (ret < 0)
+ goto error_ret;
+ *val = ret;
+ break;
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C));
+ if (ret)
+ goto error_ret;
+ *val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK];
+ ret = IIO_VAL_INT_PLUS_MICRO;
+ break;
+ };
+
+error_ret:
+ return ret;
+};
+#define KXSD9_ACCEL_CHAN(axis) \
+ { \
+ .type = IIO_ACCEL, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##axis, \
+ .info_mask = 1 << IIO_CHAN_INFO_SCALE_SHARED, \
+ .address = KXSD9_REG_##axis, \
+ }
+
+static struct iio_chan_spec kxsd9_channels[] = {
+ KXSD9_ACCEL_CHAN(X), KXSD9_ACCEL_CHAN(Y), KXSD9_ACCEL_CHAN(Z),
+ {
+ .type = IIO_IN,
+ .indexed = 1,
+ .address = KXSD9_REG_AUX,
+ }
+};
+
static const struct attribute_group kxsd9_attribute_group = {
.attrs = kxsd9_attributes,
};
static int __devinit kxsd9_power_up(struct kxsd9_state *st)
{
- struct spi_transfer xfers[2] = {
- {
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 1,
- .tx_buf = st->tx,
- }, {
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 1,
- .tx_buf = st->tx + 2,
- },
- };
- struct spi_message msg;
+ int ret;
+
st->tx[0] = 0x0d;
st->tx[1] = 0x40;
- st->tx[2] = 0x0c;
- st->tx[3] = 0x9b;
-
- spi_message_init(&msg);
- spi_message_add_tail(&xfers[0], &msg);
- spi_message_add_tail(&xfers[1], &msg);
+ ret = spi_write(st->us, st->tx, 2);
+ if (ret)
+ return ret;
- return spi_sync(st->us, &msg);
+ st->tx[0] = 0x0c;
+ st->tx[1] = 0x9b;
+ return spi_write(st->us, st->tx, 2);
};
static const struct iio_info kxsd9_info = {
+ .read_raw = &kxsd9_read_raw,
+ .write_raw = &kxsd9_write_raw,
.attrs = &kxsd9_attribute_group,
.driver_module = THIS_MODULE,
};
@@ -300,7 +236,9 @@ static int __devinit kxsd9_probe(struct spi_device *spi)
st->us = spi;
mutex_init(&st->buf_lock);
-
+ indio_dev->channels = kxsd9_channels;
+ indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels);
+ indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->dev.parent = &spi->dev;
indio_dev->info = &kxsd9_info;
indio_dev->modes = INDIO_DIRECT_MODE;
@@ -328,6 +266,10 @@ static int __devexit kxsd9_remove(struct spi_device *spi)
return 0;
}
+static const struct spi_device_id kxsd9_id[] = {
+ {"kxsd9", 0}
+};
+
static struct spi_driver kxsd9_driver = {
.driver = {
.name = "kxsd9",
@@ -335,6 +277,7 @@ static struct spi_driver kxsd9_driver = {
},
.probe = kxsd9_probe,
.remove = __devexit_p(kxsd9_remove),
+ .id_table = kxsd9_id,
};
static __init int kxsd9_spi_init(void)
diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c
index a29dfd27d440..33001f8992eb 100644
--- a/drivers/staging/iio/accel/lis3l02dq_core.c
+++ b/drivers/staging/iio/accel/lis3l02dq_core.c
@@ -21,13 +21,12 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
#include "../ring_generic.h"
-#include "accel.h"
-
#include "lis3l02dq.h"
/* At the moment the spi framework doesn't allow global setting of cs_change.
@@ -454,54 +453,54 @@ static irqreturn_t lis3l02dq_event_handler(int irq, void *private)
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_HIGH)
iio_push_event(indio_dev, 0,
- IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ IIO_MOD_EVENT_CODE(IIO_ACCEL,
0,
- IIO_EV_MOD_Z,
+ IIO_MOD_Z,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
timestamp);
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_LOW)
iio_push_event(indio_dev, 0,
- IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ IIO_MOD_EVENT_CODE(IIO_ACCEL,
0,
- IIO_EV_MOD_Z,
+ IIO_MOD_Z,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
timestamp);
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_HIGH)
iio_push_event(indio_dev, 0,
- IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ IIO_MOD_EVENT_CODE(IIO_ACCEL,
0,
- IIO_EV_MOD_Y,
+ IIO_MOD_Y,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
timestamp);
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_LOW)
iio_push_event(indio_dev, 0,
- IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ IIO_MOD_EVENT_CODE(IIO_ACCEL,
0,
- IIO_EV_MOD_Y,
+ IIO_MOD_Y,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
timestamp);
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_HIGH)
iio_push_event(indio_dev, 0,
- IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ IIO_MOD_EVENT_CODE(IIO_ACCEL,
0,
- IIO_EV_MOD_X,
+ IIO_MOD_X,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
timestamp);
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_LOW)
iio_push_event(indio_dev, 0,
- IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ IIO_MOD_EVENT_CODE(IIO_ACCEL,
0,
- IIO_EV_MOD_X,
+ IIO_MOD_X,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
timestamp);
diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c
index 8d5c8ac7db51..5c6fe13408b1 100644
--- a/drivers/staging/iio/accel/lis3l02dq_ring.c
+++ b/drivers/staging/iio/accel/lis3l02dq_ring.c
@@ -1,19 +1,15 @@
#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/mutex.h>
-#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
-#include <linux/sysfs.h>
#include <linux/slab.h>
#include "../iio.h"
-#include "../sysfs.h"
#include "../ring_sw.h"
#include "../kfifo_buf.h"
-#include "accel.h"
#include "../trigger.h"
+#include "../trigger_consumer.h"
#include "lis3l02dq.h"
/**
@@ -165,7 +161,7 @@ static int lis3l02dq_get_ring_element(struct iio_dev *indio_dev,
static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
+ struct iio_dev *indio_dev = pf->indio_dev;
struct iio_ring_buffer *ring = indio_dev->ring;
int len = 0;
size_t datasize = ring->access->get_bytes_per_datum(ring);
@@ -306,6 +302,12 @@ static int lis3l02dq_trig_try_reen(struct iio_trigger *trig)
return 0;
}
+static const struct iio_trigger_ops lis3l02dq_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &lis3l02dq_data_rdy_trigger_set_state,
+ .try_reenable = &lis3l02dq_trig_try_reen,
+};
+
int lis3l02dq_probe_trigger(struct iio_dev *indio_dev)
{
int ret;
@@ -318,10 +320,8 @@ int lis3l02dq_probe_trigger(struct iio_dev *indio_dev)
}
st->trig->dev.parent = &st->us->dev;
- st->trig->owner = THIS_MODULE;
+ st->trig->ops = &lis3l02dq_trigger_ops;
st->trig->private_data = indio_dev;
- st->trig->set_trigger_state = &lis3l02dq_data_rdy_trigger_set_state;
- st->trig->try_reenable = &lis3l02dq_trig_try_reen;
ret = iio_trigger_register(st->trig);
if (ret)
goto error_free_trig;
diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
index 603f5bca797c..dbf1622e19f2 100644
--- a/drivers/staging/iio/accel/sca3000_core.c
+++ b/drivers/staging/iio/accel/sca3000_core.c
@@ -18,11 +18,11 @@
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/sysfs.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
#include "../ring_generic.h"
-#include "accel.h"
#include "sca3000.h"
enum sca3000_variant {
@@ -422,7 +422,7 @@ static IIO_DEVICE_ATTR(measurement_mode, S_IRUGO | S_IWUSR,
/* More standard attributes */
-static IIO_DEV_ATTR_REV(sca3000_show_rev);
+static IIO_DEVICE_ATTR(revision, S_IRUGO, sca3000_show_rev, NULL, 0);
#define SCA3000_INFO_MASK \
(1 << IIO_CHAN_INFO_SCALE_SHARED)
@@ -816,36 +816,36 @@ static irqreturn_t sca3000_event_handler(int irq, void *private)
if (val & SCA3000_INT_STATUS_FREE_FALL)
iio_push_event(indio_dev, 0,
- IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ IIO_MOD_EVENT_CODE(IIO_ACCEL,
0,
- IIO_EV_MOD_X_AND_Y_AND_Z,
+ IIO_MOD_X_AND_Y_AND_Z,
IIO_EV_TYPE_MAG,
IIO_EV_DIR_FALLING),
last_timestamp);
if (val & SCA3000_INT_STATUS_Y_TRIGGER)
iio_push_event(indio_dev, 0,
- IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ IIO_MOD_EVENT_CODE(IIO_ACCEL,
0,
- IIO_EV_MOD_Y,
+ IIO_MOD_Y,
IIO_EV_TYPE_MAG,
IIO_EV_DIR_RISING),
last_timestamp);
if (val & SCA3000_INT_STATUS_X_TRIGGER)
iio_push_event(indio_dev, 0,
- IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ IIO_MOD_EVENT_CODE(IIO_ACCEL,
0,
- IIO_EV_MOD_X,
+ IIO_MOD_X,
IIO_EV_TYPE_MAG,
IIO_EV_DIR_RISING),
last_timestamp);
if (val & SCA3000_INT_STATUS_Z_TRIGGER)
iio_push_event(indio_dev, 0,
- IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ IIO_MOD_EVENT_CODE(IIO_ACCEL,
0,
- IIO_EV_MOD_Z,
+ IIO_MOD_Z,
IIO_EV_TYPE_MAG,
IIO_EV_DIR_RISING),
last_timestamp);
diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c
index a704c75fffc2..0b736dbe818c 100644
--- a/drivers/staging/iio/accel/sca3000_ring.c
+++ b/drivers/staging/iio/accel/sca3000_ring.c
@@ -10,9 +10,7 @@
*/
#include <linux/interrupt.h>
-#include <linux/gpio.h>
#include <linux/fs.h>
-#include <linux/device.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
@@ -24,7 +22,6 @@
#include "../sysfs.h"
#include "../ring_generic.h"
#include "../ring_hw.h"
-#include "accel.h"
#include "sca3000.h"
/* RFC / future work
@@ -226,74 +223,6 @@ static IIO_DEVICE_ATTR(75_percent, S_IRUGO | S_IWUSR,
sca3000_set_ring_int,
SCA3000_INT_MASK_RING_THREE_QUARTER);
-
-/**
- * sca3000_show_ring_bpse() -sysfs function to query bits per sample from ring
- * @dev: ring buffer device
- * @attr: this device attribute
- * @buf: buffer to write to
- **/
-static ssize_t sca3000_show_ring_bpse(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int len = 0, ret;
- struct iio_ring_buffer *ring = dev_get_drvdata(dev);
- struct iio_dev *indio_dev = ring->indio_dev;
- struct sca3000_state *st = iio_priv(indio_dev);
-
- mutex_lock(&st->lock);
- ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
- if (ret)
- goto error_ret;
- if (st->rx[0] & SCA3000_RING_BUF_8BIT)
- len = sprintf(buf, "s8/8\n");
- else
- len = sprintf(buf, "s11/16\n");
-error_ret:
- mutex_unlock(&st->lock);
-
- return ret ? ret : len;
-}
-
-/**
- * sca3000_store_ring_bpse() - bits per scan element
- * @dev: ring buffer device
- * @attr: attribute called from
- * @buf: input from userspace
- * @len: length of input
- **/
-static ssize_t sca3000_store_ring_bpse(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_ring_buffer *ring = dev_get_drvdata(dev);
- struct iio_dev *indio_dev = ring->indio_dev;
- struct sca3000_state *st = iio_priv(indio_dev);
- int ret;
-
- mutex_lock(&st->lock);
-
- ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
- if (ret)
- goto error_ret;
- if (sysfs_streq(buf, "s8/8")) {
- ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
- st->rx[0] | SCA3000_RING_BUF_8BIT);
- st->bpse = 8;
- } else if (sysfs_streq(buf, "s11/16")) {
- ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
- st->rx[0] & ~SCA3000_RING_BUF_8BIT);
- st->bpse = 11;
- } else
- ret = -EINVAL;
-error_ret:
- mutex_unlock(&st->lock);
-
- return ret ? ret : len;
-}
-
static ssize_t sca3000_show_buffer_scale(struct device *dev,
struct device_attribute *attr,
char *buf)
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index b39f2e1c1fe6..25566c624671 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -161,6 +161,20 @@ config AD7816
Say yes here to build support for Analog Devices AD7816/7/8
temperature sensors and ADC.
+config AD7192
+ tristate "Analog Devices AD7190 AD7192 AD7195 ADC driver"
+ depends on SPI
+ select IIO_RING_BUFFER
+ select IIO_SW_RING
+ select IIO_TRIGGER
+ help
+ Say yes here to build support for Analog Devices AD7190,
+ AD7192 or AD7195 SPI analog to digital convertors (ADC).
+ If unsure, say N (but it's safe to say "Y").
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad7192.
+
config ADT75
tristate "Analog Devices ADT75 temperature sensor driver"
depends on I2C
@@ -182,6 +196,16 @@ config ADT7410
Say yes here to build support for Analog Devices ADT7410
temperature sensors.
+config AD7280
+ tristate "Analog Devices AD7280A Lithium Ion Battery Monitoring System"
+ depends on SPI
+ help
+ Say yes here to build support for Analog Devices AD7280A
+ Lithium Ion Battery Monitoring System.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad7280a
+
config MAX1363
tristate "Maxim max1363 ADC driver"
depends on I2C
diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
index f02035139979..990d3fada305 100644
--- a/drivers/staging/iio/adc/Makefile
+++ b/drivers/staging/iio/adc/Makefile
@@ -37,6 +37,8 @@ obj-$(CONFIG_AD7745) += ad7745.o
obj-$(CONFIG_AD7780) += ad7780.o
obj-$(CONFIG_AD7793) += ad7793.o
obj-$(CONFIG_AD7816) += ad7816.o
+obj-$(CONFIG_AD7192) += ad7192.o
obj-$(CONFIG_ADT75) += adt75.o
obj-$(CONFIG_ADT7310) += adt7310.o
obj-$(CONFIG_ADT7410) += adt7410.o
+obj-$(CONFIG_AD7280) += ad7280a.o
diff --git a/drivers/staging/iio/adc/ad7150.c b/drivers/staging/iio/adc/ad7150.c
index 04017ef6688a..c01acbc7b34e 100644
--- a/drivers/staging/iio/adc/ad7150.c
+++ b/drivers/staging/iio/adc/ad7150.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -617,6 +618,8 @@ static IIO_DEV_ATTR_POWERDOWN_TIMER(S_IRUGO | S_IWUSR,
ad7150_store_powerdown_timer);
static struct attribute *ad7150_attributes[] = {
+ &iio_dev_attr_available_conversion_modes.dev_attr.attr,
+ &iio_dev_attr_conversion_mode.dev_attr.attr,
&iio_dev_attr_available_threshold_modes.dev_attr.attr,
&iio_dev_attr_threshold_mode.dev_attr.attr,
&iio_dev_attr_ch1_threshold.dev_attr.attr,
@@ -652,14 +655,14 @@ static irqreturn_t ad7150_event_handler(int irq, void *private)
if ((int_status & AD7150_STATUS_OUT1) && !(chip->old_state & AD7150_STATUS_OUT1))
iio_push_event(indio_dev, 0,
- IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN,
+ IIO_UNMOD_EVENT_CODE(IIO_IN,
0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
timestamp);
else if ((!(int_status & AD7150_STATUS_OUT1)) && (chip->old_state & AD7150_STATUS_OUT1))
iio_push_event(indio_dev, 0,
- IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN,
+ IIO_UNMOD_EVENT_CODE(IIO_IN,
0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
@@ -667,14 +670,14 @@ static irqreturn_t ad7150_event_handler(int irq, void *private)
if ((int_status & AD7150_STATUS_OUT2) && !(chip->old_state & AD7150_STATUS_OUT2))
iio_push_event(indio_dev, 0,
- IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN,
+ IIO_UNMOD_EVENT_CODE(IIO_IN,
1,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
timestamp);
else if ((!(int_status & AD7150_STATUS_OUT2)) && (chip->old_state & AD7150_STATUS_OUT2))
iio_push_event(indio_dev, 0,
- IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN,
+ IIO_UNMOD_EVENT_CODE(IIO_IN,
1,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
diff --git a/drivers/staging/iio/adc/ad7152.c b/drivers/staging/iio/adc/ad7152.c
index 21f5f380fb5e..fcec9b620c6e 100644
--- a/drivers/staging/iio/adc/ad7152.c
+++ b/drivers/staging/iio/adc/ad7152.c
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/i2c.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
new file mode 100644
index 000000000000..adf6d95dd34f
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7192.c
@@ -0,0 +1,1184 @@
+/*
+ * AD7190 AD7192 AD7195 SPI ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "../ring_generic.h"
+#include "../ring_sw.h"
+#include "../trigger.h"
+#include "../trigger_consumer.h"
+
+#include "ad7192.h"
+
+/* Registers */
+#define AD7192_REG_COMM 0 /* Communications Register (WO, 8-bit) */
+#define AD7192_REG_STAT 0 /* Status Register (RO, 8-bit) */
+#define AD7192_REG_MODE 1 /* Mode Register (RW, 24-bit */
+#define AD7192_REG_CONF 2 /* Configuration Register (RW, 24-bit) */
+#define AD7192_REG_DATA 3 /* Data Register (RO, 24/32-bit) */
+#define AD7192_REG_ID 4 /* ID Register (RO, 8-bit) */
+#define AD7192_REG_GPOCON 5 /* GPOCON Register (RO, 8-bit) */
+#define AD7192_REG_OFFSET 6 /* Offset Register (RW, 16-bit
+ * (AD7792)/24-bit (AD7192)) */
+#define AD7192_REG_FULLSALE 7 /* Full-Scale Register
+ * (RW, 16-bit (AD7792)/24-bit (AD7192)) */
+
+/* Communications Register Bit Designations (AD7192_REG_COMM) */
+#define AD7192_COMM_WEN (1 << 7) /* Write Enable */
+#define AD7192_COMM_WRITE (0 << 6) /* Write Operation */
+#define AD7192_COMM_READ (1 << 6) /* Read Operation */
+#define AD7192_COMM_ADDR(x) (((x) & 0x7) << 3) /* Register Address */
+#define AD7192_COMM_CREAD (1 << 2) /* Continuous Read of Data Register */
+
+/* Status Register Bit Designations (AD7192_REG_STAT) */
+#define AD7192_STAT_RDY (1 << 7) /* Ready */
+#define AD7192_STAT_ERR (1 << 6) /* Error (Overrange, Underrange) */
+#define AD7192_STAT_NOREF (1 << 5) /* Error no external reference */
+#define AD7192_STAT_PARITY (1 << 4) /* Parity */
+#define AD7192_STAT_CH3 (1 << 2) /* Channel 3 */
+#define AD7192_STAT_CH2 (1 << 1) /* Channel 2 */
+#define AD7192_STAT_CH1 (1 << 0) /* Channel 1 */
+
+/* Mode Register Bit Designations (AD7192_REG_MODE) */
+#define AD7192_MODE_SEL(x) (((x) & 0x7) << 21) /* Operation Mode Select */
+#define AD7192_MODE_DAT_STA (1 << 20) /* Status Register transmission */
+#define AD7192_MODE_CLKSRC(x) (((x) & 0x3) << 18) /* Clock Source Select */
+#define AD7192_MODE_SINC3 (1 << 15) /* SINC3 Filter Select */
+#define AD7192_MODE_ACX (1 << 14) /* AC excitation enable(AD7195 only)*/
+#define AD7192_MODE_ENPAR (1 << 13) /* Parity Enable */
+#define AD7192_MODE_CLKDIV (1 << 12) /* Clock divide by 2 (AD7190/2 only)*/
+#define AD7192_MODE_SCYCLE (1 << 11) /* Single cycle conversion */
+#define AD7192_MODE_REJ60 (1 << 10) /* 50/60Hz notch filter */
+#define AD7192_MODE_RATE(x) ((x) & 0x3FF) /* Filter Update Rate Select */
+
+/* Mode Register: AD7192_MODE_SEL options */
+#define AD7192_MODE_CONT 0 /* Continuous Conversion Mode */
+#define AD7192_MODE_SINGLE 1 /* Single Conversion Mode */
+#define AD7192_MODE_IDLE 2 /* Idle Mode */
+#define AD7192_MODE_PWRDN 3 /* Power-Down Mode */
+#define AD7192_MODE_CAL_INT_ZERO 4 /* Internal Zero-Scale Calibration */
+#define AD7192_MODE_CAL_INT_FULL 5 /* Internal Full-Scale Calibration */
+#define AD7192_MODE_CAL_SYS_ZERO 6 /* System Zero-Scale Calibration */
+#define AD7192_MODE_CAL_SYS_FULL 7 /* System Full-Scale Calibration */
+
+/* Mode Register: AD7192_MODE_CLKSRC options */
+#define AD7192_CLK_EXT_MCLK1_2 0 /* External 4.92 MHz Clock connected
+ * from MCLK1 to MCLK2 */
+#define AD7192_CLK_EXT_MCLK2 1 /* External Clock applied to MCLK2 */
+#define AD7192_CLK_INT 2 /* Internal 4.92 MHz Clock not
+ * available at the MCLK2 pin */
+#define AD7192_CLK_INT_CO 3 /* Internal 4.92 MHz Clock available
+ * at the MCLK2 pin */
+
+
+/* Configuration Register Bit Designations (AD7192_REG_CONF) */
+
+#define AD7192_CONF_CHOP (1 << 23) /* CHOP enable */
+#define AD7192_CONF_REFSEL (1 << 20) /* REFIN1/REFIN2 Reference Select */
+#define AD7192_CONF_CHAN(x) (((x) & 0xFF) << 8) /* Channel select */
+#define AD7192_CONF_BURN (1 << 7) /* Burnout current enable */
+#define AD7192_CONF_REFDET (1 << 6) /* Reference detect enable */
+#define AD7192_CONF_BUF (1 << 4) /* Buffered Mode Enable */
+#define AD7192_CONF_UNIPOLAR (1 << 3) /* Unipolar/Bipolar Enable */
+#define AD7192_CONF_GAIN(x) ((x) & 0x7) /* Gain Select */
+
+#define AD7192_CH_AIN1P_AIN2M 0 /* AIN1(+) - AIN2(-) */
+#define AD7192_CH_AIN3P_AIN4M 1 /* AIN3(+) - AIN4(-) */
+#define AD7192_CH_TEMP 2 /* Temp Sensor */
+#define AD7192_CH_AIN2P_AIN2M 3 /* AIN2(+) - AIN2(-) */
+#define AD7192_CH_AIN1 4 /* AIN1 - AINCOM */
+#define AD7192_CH_AIN2 5 /* AIN2 - AINCOM */
+#define AD7192_CH_AIN3 6 /* AIN3 - AINCOM */
+#define AD7192_CH_AIN4 7 /* AIN4 - AINCOM */
+
+/* ID Register Bit Designations (AD7192_REG_ID) */
+#define ID_AD7190 0x4
+#define ID_AD7192 0x0
+#define ID_AD7195 0x6
+#define AD7192_ID_MASK 0x0F
+
+/* GPOCON Register Bit Designations (AD7192_REG_GPOCON) */
+#define AD7192_GPOCON_BPDSW (1 << 6) /* Bridge power-down switch enable */
+#define AD7192_GPOCON_GP32EN (1 << 5) /* Digital Output P3 and P2 enable */
+#define AD7192_GPOCON_GP10EN (1 << 4) /* Digital Output P1 and P0 enable */
+#define AD7192_GPOCON_P3DAT (1 << 3) /* P3 state */
+#define AD7192_GPOCON_P2DAT (1 << 2) /* P2 state */
+#define AD7192_GPOCON_P1DAT (1 << 1) /* P1 state */
+#define AD7192_GPOCON_P0DAT (1 << 0) /* P0 state */
+
+#define AD7192_INT_FREQ_MHz 4915200
+
+/* NOTE:
+ * The AD7190/2/5 features a dual use data out ready DOUT/RDY output.
+ * In order to avoid contentions on the SPI bus, it's therefore necessary
+ * to use spi bus locking.
+ *
+ * The DOUT/RDY output must also be wired to an interrupt capable GPIO.
+ */
+
+struct ad7192_state {
+ struct spi_device *spi;
+ struct iio_trigger *trig;
+ struct regulator *reg;
+ struct ad7192_platform_data *pdata;
+ wait_queue_head_t wq_data_avail;
+ bool done;
+ bool irq_dis;
+ u16 int_vref_mv;
+ u32 mclk;
+ u32 f_order;
+ u32 mode;
+ u32 conf;
+ u32 scale_avail[8][2];
+ u32 available_scan_masks[9];
+ u8 gpocon;
+ u8 devid;
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ u8 data[4] ____cacheline_aligned;
+};
+
+static int __ad7192_write_reg(struct ad7192_state *st, bool locked,
+ bool cs_change, unsigned char reg,
+ unsigned size, unsigned val)
+{
+ u8 *data = st->data;
+ struct spi_transfer t = {
+ .tx_buf = data,
+ .len = size + 1,
+ .cs_change = cs_change,
+ };
+ struct spi_message m;
+
+ data[0] = AD7192_COMM_WRITE | AD7192_COMM_ADDR(reg);
+
+ switch (size) {
+ case 3:
+ data[1] = val >> 16;
+ data[2] = val >> 8;
+ data[3] = val;
+ break;
+ case 2:
+ data[1] = val >> 8;
+ data[2] = val;
+ break;
+ case 1:
+ data[1] = val;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ if (locked)
+ return spi_sync_locked(st->spi, &m);
+ else
+ return spi_sync(st->spi, &m);
+}
+
+static int ad7192_write_reg(struct ad7192_state *st,
+ unsigned reg, unsigned size, unsigned val)
+{
+ return __ad7192_write_reg(st, false, false, reg, size, val);
+}
+
+static int __ad7192_read_reg(struct ad7192_state *st, bool locked,
+ bool cs_change, unsigned char reg,
+ int *val, unsigned size)
+{
+ u8 *data = st->data;
+ int ret;
+ struct spi_transfer t[] = {
+ {
+ .tx_buf = data,
+ .len = 1,
+ }, {
+ .rx_buf = data,
+ .len = size,
+ .cs_change = cs_change,
+ },
+ };
+ struct spi_message m;
+
+ data[0] = AD7192_COMM_READ | AD7192_COMM_ADDR(reg);
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t[0], &m);
+ spi_message_add_tail(&t[1], &m);
+
+ if (locked)
+ ret = spi_sync_locked(st->spi, &m);
+ else
+ ret = spi_sync(st->spi, &m);
+
+ if (ret < 0)
+ return ret;
+
+ switch (size) {
+ case 3:
+ *val = data[0] << 16 | data[1] << 8 | data[2];
+ break;
+ case 2:
+ *val = data[0] << 8 | data[1];
+ break;
+ case 1:
+ *val = data[0];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ad7192_read_reg(struct ad7192_state *st,
+ unsigned reg, int *val, unsigned size)
+{
+ return __ad7192_read_reg(st, 0, 0, reg, val, size);
+}
+
+static int ad7192_read(struct ad7192_state *st, unsigned ch,
+ unsigned len, int *val)
+{
+ int ret;
+ st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) |
+ AD7192_CONF_CHAN(1 << ch);
+ st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) |
+ AD7192_MODE_SEL(AD7192_MODE_SINGLE);
+
+ ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf);
+
+ spi_bus_lock(st->spi->master);
+ st->done = false;
+
+ ret = __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, st->mode);
+ if (ret < 0)
+ goto out;
+
+ st->irq_dis = false;
+ enable_irq(st->spi->irq);
+ wait_event_interruptible(st->wq_data_avail, st->done);
+
+ ret = __ad7192_read_reg(st, 1, 0, AD7192_REG_DATA, val, len);
+out:
+ spi_bus_unlock(st->spi->master);
+
+ return ret;
+}
+
+static int ad7192_calibrate(struct ad7192_state *st, unsigned mode, unsigned ch)
+{
+ int ret;
+
+ st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) |
+ AD7192_CONF_CHAN(1 << ch);
+ st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | AD7192_MODE_SEL(mode);
+
+ ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf);
+
+ spi_bus_lock(st->spi->master);
+ st->done = false;
+
+ ret = __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3,
+ (st->devid != ID_AD7195) ?
+ st->mode | AD7192_MODE_CLKDIV :
+ st->mode);
+ if (ret < 0)
+ goto out;
+
+ st->irq_dis = false;
+ enable_irq(st->spi->irq);
+ wait_event_interruptible(st->wq_data_avail, st->done);
+
+ st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) |
+ AD7192_MODE_SEL(AD7192_MODE_IDLE);
+
+ ret = __ad7192_write_reg(st, 1, 0, AD7192_REG_MODE, 3, st->mode);
+out:
+ spi_bus_unlock(st->spi->master);
+
+ return ret;
+}
+
+static const u8 ad7192_calib_arr[8][2] = {
+ {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN1},
+ {AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN1},
+ {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN2},
+ {AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN2},
+ {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN3},
+ {AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN3},
+ {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN4},
+ {AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN4}
+};
+
+static int ad7192_calibrate_all(struct ad7192_state *st)
+{
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(ad7192_calib_arr); i++) {
+ ret = ad7192_calibrate(st, ad7192_calib_arr[i][0],
+ ad7192_calib_arr[i][1]);
+ if (ret)
+ goto out;
+ }
+
+ return 0;
+out:
+ dev_err(&st->spi->dev, "Calibration failed\n");
+ return ret;
+}
+
+static int ad7192_setup(struct ad7192_state *st)
+{
+ struct iio_dev *indio_dev = spi_get_drvdata(st->spi);
+ struct ad7192_platform_data *pdata = st->pdata;
+ unsigned long long scale_uv;
+ int i, ret, id;
+ u8 ones[6];
+
+ /* reset the serial interface */
+ memset(&ones, 0xFF, 6);
+ ret = spi_write(st->spi, &ones, 6);
+ if (ret < 0)
+ goto out;
+ msleep(1); /* Wait for at least 500us */
+
+ /* write/read test for device presence */
+ ret = ad7192_read_reg(st, AD7192_REG_ID, &id, 1);
+ if (ret)
+ goto out;
+
+ id &= AD7192_ID_MASK;
+
+ if (id != st->devid)
+ dev_warn(&st->spi->dev, "device ID query failed (0x%X)\n", id);
+
+ switch (pdata->clock_source_sel) {
+ case AD7192_CLK_EXT_MCLK1_2:
+ case AD7192_CLK_EXT_MCLK2:
+ st->mclk = AD7192_INT_FREQ_MHz;
+ break;
+ case AD7192_CLK_INT:
+ case AD7192_CLK_INT_CO:
+ if (pdata->ext_clk_Hz)
+ st->mclk = pdata->ext_clk_Hz;
+ else
+ st->mclk = AD7192_INT_FREQ_MHz;
+ break;
+ default:
+ ret = -EINVAL;
+ goto out;
+ }
+
+ st->mode = AD7192_MODE_SEL(AD7192_MODE_IDLE) |
+ AD7192_MODE_CLKSRC(pdata->clock_source_sel) |
+ AD7192_MODE_RATE(480);
+
+ st->conf = AD7192_CONF_GAIN(0);
+
+ if (pdata->rej60_en)
+ st->mode |= AD7192_MODE_REJ60;
+
+ if (pdata->sinc3_en)
+ st->mode |= AD7192_MODE_SINC3;
+
+ if (pdata->refin2_en && (st->devid != ID_AD7195))
+ st->conf |= AD7192_CONF_REFSEL;
+
+ if (pdata->chop_en) {
+ st->conf |= AD7192_CONF_CHOP;
+ if (pdata->sinc3_en)
+ st->f_order = 3; /* SINC 3rd order */
+ else
+ st->f_order = 4; /* SINC 4th order */
+ } else {
+ st->f_order = 1;
+ }
+
+ if (pdata->buf_en)
+ st->conf |= AD7192_CONF_BUF;
+
+ if (pdata->unipolar_en)
+ st->conf |= AD7192_CONF_UNIPOLAR;
+
+ if (pdata->burnout_curr_en)
+ st->conf |= AD7192_CONF_BURN;
+
+ ret = ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode);
+ if (ret)
+ goto out;
+
+ ret = ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf);
+ if (ret)
+ goto out;
+
+ ret = ad7192_calibrate_all(st);
+ if (ret)
+ goto out;
+
+ /* Populate available ADC input ranges */
+ for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) {
+ scale_uv = ((u64)st->int_vref_mv * 100000000)
+ >> (indio_dev->channels[0].scan_type.realbits -
+ ((st->conf & AD7192_CONF_UNIPOLAR) ? 0 : 1));
+ scale_uv >>= i;
+
+ st->scale_avail[i][1] = do_div(scale_uv, 100000000) * 10;
+ st->scale_avail[i][0] = scale_uv;
+ }
+
+ return 0;
+out:
+ dev_err(&st->spi->dev, "setup failed\n");
+ return ret;
+}
+
+static int ad7192_scan_from_ring(struct ad7192_state *st, unsigned ch, int *val)
+{
+ struct iio_ring_buffer *ring = iio_priv_to_dev(st)->ring;
+ int ret;
+ s64 dat64[2];
+ u32 *dat32 = (u32 *)dat64;
+
+ if (!(ring->scan_mask & (1 << ch)))
+ return -EBUSY;
+
+ ret = ring->access->read_last(ring, (u8 *) &dat64);
+ if (ret)
+ return ret;
+
+ *val = *dat32;
+
+ return 0;
+}
+
+static int ad7192_ring_preenable(struct iio_dev *indio_dev)
+{
+ struct ad7192_state *st = iio_priv(indio_dev);
+ struct iio_ring_buffer *ring = indio_dev->ring;
+ size_t d_size;
+ unsigned channel;
+
+ if (!ring->scan_count)
+ return -EINVAL;
+
+ channel = __ffs(ring->scan_mask);
+
+ d_size = ring->scan_count *
+ indio_dev->channels[0].scan_type.storagebits / 8;
+
+ if (ring->scan_timestamp) {
+ d_size += sizeof(s64);
+
+ if (d_size % sizeof(s64))
+ d_size += sizeof(s64) - (d_size % sizeof(s64));
+ }
+
+ if (indio_dev->ring->access->set_bytes_per_datum)
+ indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring,
+ d_size);
+
+ st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) |
+ AD7192_MODE_SEL(AD7192_MODE_CONT);
+ st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) |
+ AD7192_CONF_CHAN(1 << indio_dev->channels[channel].address);
+
+ ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf);
+
+ spi_bus_lock(st->spi->master);
+ __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, st->mode);
+
+ st->irq_dis = false;
+ enable_irq(st->spi->irq);
+
+ return 0;
+}
+
+static int ad7192_ring_postdisable(struct iio_dev *indio_dev)
+{
+ struct ad7192_state *st = iio_priv(indio_dev);
+
+ st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) |
+ AD7192_MODE_SEL(AD7192_MODE_IDLE);
+
+ st->done = false;
+ wait_event_interruptible(st->wq_data_avail, st->done);
+
+ if (!st->irq_dis)
+ disable_irq_nosync(st->spi->irq);
+
+ __ad7192_write_reg(st, 1, 0, AD7192_REG_MODE, 3, st->mode);
+
+ return spi_bus_unlock(st->spi->master);
+}
+
+/**
+ * ad7192_trigger_handler() bh of trigger launched polling to ring buffer
+ **/
+static irqreturn_t ad7192_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct iio_ring_buffer *ring = indio_dev->ring;
+ struct ad7192_state *st = iio_priv(indio_dev);
+ s64 dat64[2];
+ s32 *dat32 = (s32 *)dat64;
+
+ if (ring->scan_count)
+ __ad7192_read_reg(st, 1, 1, AD7192_REG_DATA,
+ dat32,
+ indio_dev->channels[0].scan_type.realbits/8);
+
+ /* Guaranteed to be aligned with 8 byte boundary */
+ if (ring->scan_timestamp)
+ dat64[1] = pf->timestamp;
+
+ ring->access->store_to(ring, (u8 *)dat64, pf->timestamp);
+
+ iio_trigger_notify_done(indio_dev->trig);
+ st->irq_dis = false;
+ enable_irq(st->spi->irq);
+
+ return IRQ_HANDLED;
+}
+
+static const struct iio_ring_setup_ops ad7192_ring_setup_ops = {
+ .preenable = &ad7192_ring_preenable,
+ .postenable = &iio_triggered_ring_postenable,
+ .predisable = &iio_triggered_ring_predisable,
+ .postdisable = &ad7192_ring_postdisable,
+};
+
+static int ad7192_register_ring_funcs_and_init(struct iio_dev *indio_dev)
+{
+ int ret;
+
+ indio_dev->ring = iio_sw_rb_allocate(indio_dev);
+ if (!indio_dev->ring) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+ /* Effectively select the ring buffer implementation */
+ indio_dev->ring->access = &ring_sw_access_funcs;
+ indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
+ &ad7192_trigger_handler,
+ IRQF_ONESHOT,
+ indio_dev,
+ "ad7192_consumer%d",
+ indio_dev->id);
+ if (indio_dev->pollfunc == NULL) {
+ ret = -ENOMEM;
+ goto error_deallocate_sw_rb;
+ }
+
+ /* Ring buffer functions - here trigger setup related */
+ indio_dev->ring->setup_ops = &ad7192_ring_setup_ops;
+
+ /* Flag that polled ring buffering is possible */
+ indio_dev->modes |= INDIO_RING_TRIGGERED;
+ return 0;
+
+error_deallocate_sw_rb:
+ iio_sw_rb_free(indio_dev->ring);
+error_ret:
+ return ret;
+}
+
+static void ad7192_ring_cleanup(struct iio_dev *indio_dev)
+{
+ iio_dealloc_pollfunc(indio_dev->pollfunc);
+ iio_sw_rb_free(indio_dev->ring);
+}
+
+/**
+ * ad7192_data_rdy_trig_poll() the event handler for the data rdy trig
+ **/
+static irqreturn_t ad7192_data_rdy_trig_poll(int irq, void *private)
+{
+ struct ad7192_state *st = iio_priv(private);
+
+ st->done = true;
+ wake_up_interruptible(&st->wq_data_avail);
+ disable_irq_nosync(irq);
+ st->irq_dis = true;
+ iio_trigger_poll(st->trig, iio_get_time_ns());
+
+ return IRQ_HANDLED;
+}
+
+static int ad7192_probe_trigger(struct iio_dev *indio_dev)
+{
+ struct ad7192_state *st = iio_priv(indio_dev);
+ int ret;
+
+ st->trig = iio_allocate_trigger("%s-dev%d",
+ spi_get_device_id(st->spi)->name,
+ indio_dev->id);
+ if (st->trig == NULL) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+
+ ret = request_irq(st->spi->irq,
+ ad7192_data_rdy_trig_poll,
+ IRQF_TRIGGER_LOW,
+ spi_get_device_id(st->spi)->name,
+ indio_dev);
+ if (ret)
+ goto error_free_trig;
+
+ disable_irq_nosync(st->spi->irq);
+ st->irq_dis = true;
+ st->trig->dev.parent = &st->spi->dev;
+ st->trig->owner = THIS_MODULE;
+ st->trig->private_data = indio_dev;
+
+ ret = iio_trigger_register(st->trig);
+
+ /* select default trigger */
+ indio_dev->trig = st->trig;
+ if (ret)
+ goto error_free_irq;
+
+ return 0;
+
+error_free_irq:
+ free_irq(st->spi->irq, indio_dev);
+error_free_trig:
+ iio_free_trigger(st->trig);
+error_ret:
+ return ret;
+}
+
+static void ad7192_remove_trigger(struct iio_dev *indio_dev)
+{
+ struct ad7192_state *st = iio_priv(indio_dev);
+
+ iio_trigger_unregister(st->trig);
+ free_irq(st->spi->irq, indio_dev);
+ iio_free_trigger(st->trig);
+}
+
+static ssize_t ad7192_read_frequency(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad7192_state *st = iio_priv(indio_dev);
+
+ return sprintf(buf, "%d\n", st->mclk /
+ (st->f_order * 1024 * AD7192_MODE_RATE(st->mode)));
+}
+
+static ssize_t ad7192_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 ad7192_state *st = iio_priv(indio_dev);
+ unsigned long lval;
+ int div, ret;
+
+ ret = strict_strtoul(buf, 10, &lval);
+ if (ret)
+ return ret;
+
+ mutex_lock(&indio_dev->mlock);
+ if (iio_ring_enabled(indio_dev)) {
+ mutex_unlock(&indio_dev->mlock);
+ return -EBUSY;
+ }
+
+ div = st->mclk / (lval * st->f_order * 1024);
+ if (div < 1 || div > 1023) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ st->mode &= ~AD7192_MODE_RATE(-1);
+ st->mode |= AD7192_MODE_RATE(div);
+ ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode);
+
+out:
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret ? ret : len;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
+ ad7192_read_frequency,
+ ad7192_write_frequency);
+
+
+static ssize_t ad7192_show_scale_available(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad7192_state *st = iio_priv(indio_dev);
+ int i, len = 0;
+
+ for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
+ len += sprintf(buf + len, "%d.%09u ", st->scale_avail[i][0],
+ st->scale_avail[i][1]);
+
+ len += sprintf(buf + len, "\n");
+
+ return len;
+}
+
+static IIO_DEVICE_ATTR_NAMED(in_m_in_scale_available, in-in_scale_available,
+ S_IRUGO, ad7192_show_scale_available, NULL, 0);
+
+static IIO_DEVICE_ATTR(in_scale_available, S_IRUGO,
+ ad7192_show_scale_available, NULL, 0);
+
+static ssize_t ad7192_show_ac_excitation(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad7192_state *st = iio_priv(indio_dev);
+
+ return sprintf(buf, "%d\n", !!(st->mode & AD7192_MODE_ACX));
+}
+
+static ssize_t ad7192_show_bridge_switch(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad7192_state *st = iio_priv(indio_dev);
+
+ return sprintf(buf, "%d\n", !!(st->gpocon & AD7192_GPOCON_BPDSW));
+}
+
+static ssize_t ad7192_set(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad7192_state *st = iio_priv(indio_dev);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ int ret;
+ bool val;
+
+ ret = strtobool(buf, &val);
+ if (ret < 0)
+ return ret;
+
+ mutex_lock(&indio_dev->mlock);
+ if (iio_ring_enabled(indio_dev)) {
+ mutex_unlock(&indio_dev->mlock);
+ return -EBUSY;
+ }
+
+ switch (this_attr->address) {
+ case AD7192_REG_GPOCON:
+ if (val)
+ st->gpocon |= AD7192_GPOCON_BPDSW;
+ else
+ st->gpocon &= ~AD7192_GPOCON_BPDSW;
+
+ ad7192_write_reg(st, AD7192_REG_GPOCON, 1, st->gpocon);
+ break;
+ case AD7192_REG_MODE:
+ if (val)
+ st->mode |= AD7192_MODE_ACX;
+ else
+ st->mode &= ~AD7192_MODE_ACX;
+
+ ad7192_write_reg(st, AD7192_REG_GPOCON, 3, st->mode);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret ? ret : len;
+}
+
+static IIO_DEVICE_ATTR(bridge_switch_en, S_IRUGO | S_IWUSR,
+ ad7192_show_bridge_switch, ad7192_set,
+ AD7192_REG_GPOCON);
+
+static IIO_DEVICE_ATTR(ac_excitation_en, S_IRUGO | S_IWUSR,
+ ad7192_show_ac_excitation, ad7192_set,
+ AD7192_REG_MODE);
+
+static struct attribute *ad7192_attributes[] = {
+ &iio_dev_attr_sampling_frequency.dev_attr.attr,
+ &iio_dev_attr_in_m_in_scale_available.dev_attr.attr,
+ &iio_dev_attr_in_scale_available.dev_attr.attr,
+ &iio_dev_attr_bridge_switch_en.dev_attr.attr,
+ &iio_dev_attr_ac_excitation_en.dev_attr.attr,
+ NULL
+};
+
+static mode_t ad7192_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr, int n)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct ad7192_state *st = iio_priv(dev_info);
+
+ mode_t mode = attr->mode;
+
+ if ((st->devid != ID_AD7195) &&
+ (attr == &iio_dev_attr_ac_excitation_en.dev_attr.attr))
+ mode = 0;
+
+ return mode;
+}
+
+static const struct attribute_group ad7192_attribute_group = {
+ .attrs = ad7192_attributes,
+ .is_visible = ad7192_attr_is_visible,
+};
+
+static int ad7192_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
+{
+ struct ad7192_state *st = iio_priv(indio_dev);
+ int ret, smpl = 0;
+ bool unipolar = !!(st->conf & AD7192_CONF_UNIPOLAR);
+
+ switch (m) {
+ case 0:
+ mutex_lock(&indio_dev->mlock);
+ if (iio_ring_enabled(indio_dev))
+ ret = ad7192_scan_from_ring(st,
+ chan->scan_index, &smpl);
+ else
+ ret = ad7192_read(st, chan->address,
+ chan->scan_type.realbits / 8, &smpl);
+ mutex_unlock(&indio_dev->mlock);
+
+ if (ret < 0)
+ return ret;
+
+ *val = (smpl >> chan->scan_type.shift) &
+ ((1 << (chan->scan_type.realbits)) - 1);
+
+ switch (chan->type) {
+ case IIO_IN:
+ case IIO_IN_DIFF:
+ if (!unipolar)
+ *val -= (1 << (chan->scan_type.realbits - 1));
+ break;
+ case IIO_TEMP:
+ *val -= 0x800000;
+ *val /= 2815; /* temp Kelvin */
+ *val -= 273; /* temp Celsius */
+ break;
+ default:
+ return -EINVAL;
+ }
+ return IIO_VAL_INT;
+
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ mutex_lock(&indio_dev->mlock);
+ *val = st->scale_avail[AD7192_CONF_GAIN(st->conf)][0];
+ *val2 = st->scale_avail[AD7192_CONF_GAIN(st->conf)][1];
+ mutex_unlock(&indio_dev->mlock);
+
+ return IIO_VAL_INT_PLUS_NANO;
+
+ case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ *val = 1000;
+
+ return IIO_VAL_INT;
+ }
+
+ return -EINVAL;
+}
+
+static int ad7192_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
+{
+ struct ad7192_state *st = iio_priv(indio_dev);
+ int ret, i;
+ unsigned int tmp;
+
+ mutex_lock(&indio_dev->mlock);
+ if (iio_ring_enabled(indio_dev)) {
+ mutex_unlock(&indio_dev->mlock);
+ return -EBUSY;
+ }
+
+ switch (mask) {
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ ret = -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
+ if (val2 == st->scale_avail[i][1]) {
+ tmp = st->conf;
+ st->conf &= ~AD7192_CONF_GAIN(-1);
+ st->conf |= AD7192_CONF_GAIN(i);
+
+ if (tmp != st->conf) {
+ ad7192_write_reg(st, AD7192_REG_CONF,
+ 3, st->conf);
+ ad7192_calibrate_all(st);
+ }
+ ret = 0;
+ }
+
+ default:
+ ret = -EINVAL;
+ }
+
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret;
+}
+
+static int ad7192_validate_trigger(struct iio_dev *indio_dev,
+ struct iio_trigger *trig)
+{
+ if (indio_dev->trig != trig)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int ad7192_write_raw_get_fmt(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ long mask)
+{
+ return IIO_VAL_INT_PLUS_NANO;
+}
+
+static const struct iio_info ad7192_info = {
+ .read_raw = &ad7192_read_raw,
+ .write_raw = &ad7192_write_raw,
+ .write_raw_get_fmt = &ad7192_write_raw_get_fmt,
+ .attrs = &ad7192_attribute_group,
+ .validate_trigger = ad7192_validate_trigger,
+ .driver_module = THIS_MODULE,
+};
+
+#define AD7192_CHAN_DIFF(_chan, _chan2, _name, _address, _si) \
+ { .type = IIO_IN_DIFF, \
+ .indexed = 1, \
+ .extend_name = _name, \
+ .channel = _chan, \
+ .channel2 = _chan2, \
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \
+ .address = _address, \
+ .scan_index = _si, \
+ .scan_type = IIO_ST('s', 24, 32, 0)}
+
+#define AD7192_CHAN(_chan, _address, _si) \
+ { .type = IIO_IN, \
+ .indexed = 1, \
+ .channel = _chan, \
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \
+ .address = _address, \
+ .scan_index = _si, \
+ .scan_type = IIO_ST('s', 24, 32, 0)}
+
+#define AD7192_CHAN_TEMP(_chan, _address, _si) \
+ { .type = IIO_TEMP, \
+ .indexed = 1, \
+ .channel = _chan, \
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \
+ .address = _address, \
+ .scan_index = _si, \
+ .scan_type = IIO_ST('s', 24, 32, 0)}
+
+static struct iio_chan_spec ad7192_channels[] = {
+ AD7192_CHAN_DIFF(1, 2, NULL, AD7192_CH_AIN1P_AIN2M, 0),
+ AD7192_CHAN_DIFF(3, 4, NULL, AD7192_CH_AIN3P_AIN4M, 1),
+ AD7192_CHAN_TEMP(0, AD7192_CH_TEMP, 2),
+ AD7192_CHAN_DIFF(2, 2, "shorted", AD7192_CH_AIN2P_AIN2M, 3),
+ AD7192_CHAN(1, AD7192_CH_AIN1, 4),
+ AD7192_CHAN(2, AD7192_CH_AIN2, 5),
+ AD7192_CHAN(3, AD7192_CH_AIN3, 6),
+ AD7192_CHAN(4, AD7192_CH_AIN4, 7),
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+};
+
+static int __devinit ad7192_probe(struct spi_device *spi)
+{
+ struct ad7192_platform_data *pdata = spi->dev.platform_data;
+ struct ad7192_state *st;
+ struct iio_dev *indio_dev;
+ int ret, i , voltage_uv = 0, regdone = 0;
+
+ if (!pdata) {
+ dev_err(&spi->dev, "no platform data?\n");
+ return -ENODEV;
+ }
+
+ if (!spi->irq) {
+ dev_err(&spi->dev, "no IRQ?\n");
+ return -ENODEV;
+ }
+
+ indio_dev = iio_allocate_device(sizeof(*st));
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+
+ st->reg = regulator_get(&spi->dev, "vcc");
+ if (!IS_ERR(st->reg)) {
+ ret = regulator_enable(st->reg);
+ if (ret)
+ goto error_put_reg;
+
+ voltage_uv = regulator_get_voltage(st->reg);
+ }
+
+ st->pdata = pdata;
+
+ if (pdata && pdata->vref_mv)
+ st->int_vref_mv = pdata->vref_mv;
+ else if (voltage_uv)
+ st->int_vref_mv = voltage_uv / 1000;
+ else
+ dev_warn(&spi->dev, "reference voltage undefined\n");
+
+ spi_set_drvdata(spi, indio_dev);
+ st->spi = spi;
+ st->devid = spi_get_device_id(spi)->driver_data;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = ad7192_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ad7192_channels);
+ indio_dev->available_scan_masks = st->available_scan_masks;
+ indio_dev->info = &ad7192_info;
+
+ for (i = 0; i < indio_dev->num_channels; i++)
+ st->available_scan_masks[i] = (1 << i) | (1 <<
+ indio_dev->channels[indio_dev->num_channels - 1].
+ scan_index);
+
+ init_waitqueue_head(&st->wq_data_avail);
+
+ ret = ad7192_register_ring_funcs_and_init(indio_dev);
+ if (ret)
+ goto error_disable_reg;
+
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto error_unreg_ring;
+ regdone = 1;
+
+ ret = ad7192_probe_trigger(indio_dev);
+ if (ret)
+ goto error_unreg_ring;
+
+ ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
+ indio_dev->channels,
+ indio_dev->num_channels);
+ if (ret)
+ goto error_remove_trigger;
+
+ ret = ad7192_setup(st);
+ if (ret)
+ goto error_uninitialize_ring;
+
+ return 0;
+
+error_uninitialize_ring:
+ iio_ring_buffer_unregister(indio_dev->ring);
+error_remove_trigger:
+ ad7192_remove_trigger(indio_dev);
+error_unreg_ring:
+ ad7192_ring_cleanup(indio_dev);
+error_disable_reg:
+ if (!IS_ERR(st->reg))
+ regulator_disable(st->reg);
+error_put_reg:
+ if (!IS_ERR(st->reg))
+ regulator_put(st->reg);
+
+ if (regdone)
+ iio_device_unregister(indio_dev);
+ else
+ iio_free_device(indio_dev);
+
+ return ret;
+}
+
+static int ad7192_remove(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct ad7192_state *st = iio_priv(indio_dev);
+
+ iio_ring_buffer_unregister(indio_dev->ring);
+ ad7192_remove_trigger(indio_dev);
+ ad7192_ring_cleanup(indio_dev);
+
+ if (!IS_ERR(st->reg)) {
+ regulator_disable(st->reg);
+ regulator_put(st->reg);
+ }
+
+ iio_device_unregister(indio_dev);
+
+ return 0;
+}
+
+static const struct spi_device_id ad7192_id[] = {
+ {"ad7190", ID_AD7190},
+ {"ad7192", ID_AD7192},
+ {"ad7195", ID_AD7195},
+ {}
+};
+
+static struct spi_driver ad7192_driver = {
+ .driver = {
+ .name = "ad7192",
+ .owner = THIS_MODULE,
+ },
+ .probe = ad7192_probe,
+ .remove = __devexit_p(ad7192_remove),
+ .id_table = ad7192_id,
+};
+
+static int __init ad7192_init(void)
+{
+ return spi_register_driver(&ad7192_driver);
+}
+module_init(ad7192_init);
+
+static void __exit ad7192_exit(void)
+{
+ spi_unregister_driver(&ad7192_driver);
+}
+module_exit(ad7192_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD7190, AD7192, AD7195 ADC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/adc/ad7192.h b/drivers/staging/iio/adc/ad7192.h
new file mode 100644
index 000000000000..a0a5b61a41f1
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7192.h
@@ -0,0 +1,47 @@
+/*
+ * AD7190 AD7192 AD7195 SPI ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+#ifndef IIO_ADC_AD7192_H_
+#define IIO_ADC_AD7192_H_
+
+/*
+ * TODO: struct ad7192_platform_data needs to go into include/linux/iio
+ */
+
+/**
+ * struct ad7192_platform_data - platform/board specific information
+ * @vref_mv: the external reference voltage in millivolt
+ * @clock_source_sel: [0..3]
+ * 0 External 4.92 MHz clock connected from MCLK1 to MCLK2
+ * 1 External Clock applied to MCLK2
+ * 2 Internal 4.92 MHz Clock not available at the MCLK2 pin
+ * 3 Internal 4.92 MHz Clock available at the MCLK2 pin
+ * @ext_clk_Hz: the external clock frequency in Hz, if not set
+ * the driver uses the internal clock (16.776 MHz)
+ * @refin2_en: REFIN1/REFIN2 Reference Select (AD7190/2 only)
+ * @rej60_en: 50/60Hz notch filter enable
+ * @sinc3_en: SINC3 filter enable (default SINC4)
+ * @chop_en: CHOP mode enable
+ * @buf_en: buffered input mode enable
+ * @unipolar_en: unipolar mode enable
+ * @burnout_curr_en: constant current generators on AIN(+|-) enable
+ */
+
+struct ad7192_platform_data {
+ u16 vref_mv;
+ u8 clock_source_sel;
+ u32 ext_clk_Hz;
+ bool refin2_en;
+ bool rej60_en;
+ bool sinc3_en;
+ bool chop_en;
+ bool buf_en;
+ bool unipolar_en;
+ bool burnout_curr_en;
+};
+
+#endif /* IIO_ADC_AD7192_H_ */
diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c
new file mode 100644
index 000000000000..ab6cf9cb5a7f
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7280a.c
@@ -0,0 +1,992 @@
+/*
+ * AD7280A Lithium Ion Battery Monitoring System
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+
+#include "ad7280a.h"
+
+/* Registers */
+#define AD7280A_CELL_VOLTAGE_1 0x0 /* D11 to D0, Read only */
+#define AD7280A_CELL_VOLTAGE_2 0x1 /* D11 to D0, Read only */
+#define AD7280A_CELL_VOLTAGE_3 0x2 /* D11 to D0, Read only */
+#define AD7280A_CELL_VOLTAGE_4 0x3 /* D11 to D0, Read only */
+#define AD7280A_CELL_VOLTAGE_5 0x4 /* D11 to D0, Read only */
+#define AD7280A_CELL_VOLTAGE_6 0x5 /* D11 to D0, Read only */
+#define AD7280A_AUX_ADC_1 0x6 /* D11 to D0, Read only */
+#define AD7280A_AUX_ADC_2 0x7 /* D11 to D0, Read only */
+#define AD7280A_AUX_ADC_3 0x8 /* D11 to D0, Read only */
+#define AD7280A_AUX_ADC_4 0x9 /* D11 to D0, Read only */
+#define AD7280A_AUX_ADC_5 0xA /* D11 to D0, Read only */
+#define AD7280A_AUX_ADC_6 0xB /* D11 to D0, Read only */
+#define AD7280A_SELF_TEST 0xC /* D11 to D0, Read only */
+#define AD7280A_CONTROL_HB 0xD /* D15 to D8, Read/write */
+#define AD7280A_CONTROL_LB 0xE /* D7 to D0, Read/write */
+#define AD7280A_CELL_OVERVOLTAGE 0xF /* D7 to D0, Read/write */
+#define AD7280A_CELL_UNDERVOLTAGE 0x10 /* D7 to D0, Read/write */
+#define AD7280A_AUX_ADC_OVERVOLTAGE 0x11 /* D7 to D0, Read/write */
+#define AD7280A_AUX_ADC_UNDERVOLTAGE 0x12 /* D7 to D0, Read/write */
+#define AD7280A_ALERT 0x13 /* D7 to D0, Read/write */
+#define AD7280A_CELL_BALANCE 0x14 /* D7 to D0, Read/write */
+#define AD7280A_CB1_TIMER 0x15 /* D7 to D0, Read/write */
+#define AD7280A_CB2_TIMER 0x16 /* D7 to D0, Read/write */
+#define AD7280A_CB3_TIMER 0x17 /* D7 to D0, Read/write */
+#define AD7280A_CB4_TIMER 0x18 /* D7 to D0, Read/write */
+#define AD7280A_CB5_TIMER 0x19 /* D7 to D0, Read/write */
+#define AD7280A_CB6_TIMER 0x1A /* D7 to D0, Read/write */
+#define AD7280A_PD_TIMER 0x1B /* D7 to D0, Read/write */
+#define AD7280A_READ 0x1C /* D7 to D0, Read/write */
+#define AD7280A_CNVST_CONTROL 0x1D /* D7 to D0, Read/write */
+
+/* Bits and Masks */
+#define AD7280A_CTRL_HB_CONV_INPUT_ALL (0 << 6)
+#define AD7280A_CTRL_HB_CONV_INPUT_6CELL_AUX1_3_4 (1 << 6)
+#define AD7280A_CTRL_HB_CONV_INPUT_6CELL (2 << 6)
+#define AD7280A_CTRL_HB_CONV_INPUT_SELF_TEST (3 << 6)
+#define AD7280A_CTRL_HB_CONV_RES_READ_ALL (0 << 4)
+#define AD7280A_CTRL_HB_CONV_RES_READ_6CELL_AUX1_3_4 (1 << 4)
+#define AD7280A_CTRL_HB_CONV_RES_READ_6CELL (2 << 4)
+#define AD7280A_CTRL_HB_CONV_RES_READ_NO (3 << 4)
+#define AD7280A_CTRL_HB_CONV_START_CNVST (0 << 3)
+#define AD7280A_CTRL_HB_CONV_START_CS (1 << 3)
+#define AD7280A_CTRL_HB_CONV_AVG_DIS (0 << 1)
+#define AD7280A_CTRL_HB_CONV_AVG_2 (1 << 1)
+#define AD7280A_CTRL_HB_CONV_AVG_4 (2 << 1)
+#define AD7280A_CTRL_HB_CONV_AVG_8 (3 << 1)
+#define AD7280A_CTRL_HB_CONV_AVG(x) ((x) << 1)
+#define AD7280A_CTRL_HB_PWRDN_SW (1 << 0)
+
+#define AD7280A_CTRL_LB_SWRST (1 << 7)
+#define AD7280A_CTRL_LB_ACQ_TIME_400ns (0 << 5)
+#define AD7280A_CTRL_LB_ACQ_TIME_800ns (1 << 5)
+#define AD7280A_CTRL_LB_ACQ_TIME_1200ns (2 << 5)
+#define AD7280A_CTRL_LB_ACQ_TIME_1600ns (3 << 5)
+#define AD7280A_CTRL_LB_ACQ_TIME(x) ((x) << 5)
+#define AD7280A_CTRL_LB_MUST_SET (1 << 4)
+#define AD7280A_CTRL_LB_THERMISTOR_EN (1 << 3)
+#define AD7280A_CTRL_LB_LOCK_DEV_ADDR (1 << 2)
+#define AD7280A_CTRL_LB_INC_DEV_ADDR (1 << 1)
+#define AD7280A_CTRL_LB_DAISY_CHAIN_RB_EN (1 << 0)
+
+#define AD7280A_ALERT_GEN_STATIC_HIGH (1 << 6)
+#define AD7280A_ALERT_RELAY_SIG_CHAIN_DOWN (3 << 6)
+
+#define AD7280A_ALL_CELLS (0xAD << 16)
+
+#define AD7280A_MAX_SPI_CLK_Hz 700000 /* < 1MHz */
+#define AD7280A_MAX_CHAIN 8
+#define AD7280A_CELLS_PER_DEV 6
+#define AD7280A_BITS 12
+#define AD7280A_NUM_CH (AD7280A_AUX_ADC_6 - \
+ AD7280A_CELL_VOLTAGE_1 + 1)
+
+#define AD7280A_DEVADDR_MASTER 0
+#define AD7280A_DEVADDR_ALL 0x1F
+/* 5-bit device address is sent LSB first */
+#define AD7280A_DEVADDR(addr) (((addr & 0x1) << 4) | ((addr & 0x2) << 3) | \
+ (addr & 0x4) | ((addr & 0x8) >> 3) | \
+ ((addr & 0x10) >> 4))
+
+/* During a read a valid write is mandatory.
+ * So writing to the highest available address (Address 0x1F)
+ * and setting the address all parts bit to 0 is recommended
+ * So the TXVAL is AD7280A_DEVADDR_ALL + CRC
+ */
+#define AD7280A_READ_TXVAL 0xF800030A
+
+/*
+ * AD7280 CRC
+ *
+ * P(x) = x^8 + x^5 + x^3 + x^2 + x^1 + x^0 = 0b100101111 => 0x2F
+ */
+#define POLYNOM 0x2F
+#define POLYNOM_ORDER 8
+#define HIGHBIT 1 << (POLYNOM_ORDER - 1);
+
+struct ad7280_state {
+ struct spi_device *spi;
+ struct iio_chan_spec *channels;
+ struct iio_dev_attr *iio_attr;
+ int slave_num;
+ int scan_cnt;
+ int readback_delay_us;
+ unsigned char crc_tab[256];
+ unsigned char ctrl_hb;
+ unsigned char ctrl_lb;
+ unsigned char cell_threshhigh;
+ unsigned char cell_threshlow;
+ unsigned char aux_threshhigh;
+ unsigned char aux_threshlow;
+ unsigned char cb_mask[AD7280A_MAX_CHAIN];
+};
+
+static void ad7280_crc8_build_table(unsigned char *crc_tab)
+{
+ unsigned char bit, crc;
+ int cnt, i;
+
+ for (cnt = 0; cnt < 256; cnt++) {
+ crc = cnt;
+ for (i = 0; i < 8; i++) {
+ bit = crc & HIGHBIT;
+ crc <<= 1;
+ if (bit)
+ crc ^= POLYNOM;
+ }
+ crc_tab[cnt] = crc;
+ }
+}
+
+static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned val)
+{
+ unsigned char crc;
+
+ crc = crc_tab[val >> 16 & 0xFF];
+ crc = crc_tab[crc ^ (val >> 8 & 0xFF)];
+
+ return crc ^ (val & 0xFF);
+}
+
+static int ad7280_check_crc(struct ad7280_state *st, unsigned val)
+{
+ unsigned char crc = ad7280_calc_crc8(st->crc_tab, val >> 10);
+
+ if (crc != ((val >> 2) & 0xFF))
+ return -EIO;
+
+ return 0;
+}
+
+/* After initiating a conversion sequence we need to wait until the
+ * conversion is done. The delay is typically in the range of 15..30 us
+ * however depending an the number of devices in the daisy chain and the
+ * number of averages taken, conversion delays and acquisition time options
+ * it may take up to 250us, in this case we better sleep instead of busy
+ * wait.
+ */
+
+static void ad7280_delay(struct ad7280_state *st)
+{
+ if (st->readback_delay_us < 50)
+ udelay(st->readback_delay_us);
+ else
+ msleep(1);
+}
+
+static int __ad7280_read32(struct spi_device *spi, unsigned *val)
+{
+ unsigned rx_buf, tx_buf = cpu_to_be32(AD7280A_READ_TXVAL);
+ int ret;
+
+ struct spi_transfer t = {
+ .tx_buf = &tx_buf,
+ .rx_buf = &rx_buf,
+ .len = 4,
+ };
+ struct spi_message m;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ ret = spi_sync(spi, &m);
+ if (ret)
+ return ret;
+
+ *val = be32_to_cpu(rx_buf);
+
+ return 0;
+}
+
+static int ad7280_write(struct ad7280_state *st, unsigned devaddr,
+ unsigned addr, bool all, unsigned val)
+{
+ unsigned reg = (devaddr << 27 | addr << 21 |
+ (val & 0xFF) << 13 | all << 12);
+
+ reg |= ad7280_calc_crc8(st->crc_tab, reg >> 11) << 3 | 0x2;
+ reg = cpu_to_be32(reg);
+
+ return spi_write(st->spi, &reg, 4);
+}
+
+static int ad7280_read(struct ad7280_state *st, unsigned devaddr,
+ unsigned addr)
+{
+ int ret;
+ unsigned tmp;
+
+ /* turns off the read operation on all parts */
+ ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1,
+ AD7280A_CTRL_HB_CONV_INPUT_ALL |
+ AD7280A_CTRL_HB_CONV_RES_READ_NO |
+ st->ctrl_hb);
+ if (ret)
+ return ret;
+
+ /* turns on the read operation on the addressed part */
+ ret = ad7280_write(st, devaddr, AD7280A_CONTROL_HB, 0,
+ AD7280A_CTRL_HB_CONV_INPUT_ALL |
+ AD7280A_CTRL_HB_CONV_RES_READ_ALL |
+ st->ctrl_hb);
+ if (ret)
+ return ret;
+
+ /* Set register address on the part to be read from */
+ ret = ad7280_write(st, devaddr, AD7280A_READ, 0, addr << 2);
+ if (ret)
+ return ret;
+
+ __ad7280_read32(st->spi, &tmp);
+
+ if (ad7280_check_crc(st, tmp))
+ return -EIO;
+
+ if (((tmp >> 27) != devaddr) || (((tmp >> 21) & 0x3F) != addr))
+ return -EFAULT;
+
+ return (tmp >> 13) & 0xFF;
+}
+
+static int ad7280_read_channel(struct ad7280_state *st, unsigned devaddr,
+ unsigned addr)
+{
+ int ret;
+ unsigned tmp;
+
+ ret = ad7280_write(st, devaddr, AD7280A_READ, 0, addr << 2);
+ if (ret)
+ return ret;
+
+ ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1,
+ AD7280A_CTRL_HB_CONV_INPUT_ALL |
+ AD7280A_CTRL_HB_CONV_RES_READ_NO |
+ st->ctrl_hb);
+ if (ret)
+ return ret;
+
+ ret = ad7280_write(st, devaddr, AD7280A_CONTROL_HB, 0,
+ AD7280A_CTRL_HB_CONV_INPUT_ALL |
+ AD7280A_CTRL_HB_CONV_RES_READ_ALL |
+ AD7280A_CTRL_HB_CONV_START_CS |
+ st->ctrl_hb);
+ if (ret)
+ return ret;
+
+ ad7280_delay(st);
+
+ __ad7280_read32(st->spi, &tmp);
+
+ if (ad7280_check_crc(st, tmp))
+ return -EIO;
+
+ if (((tmp >> 27) != devaddr) || (((tmp >> 23) & 0xF) != addr))
+ return -EFAULT;
+
+ return (tmp >> 11) & 0xFFF;
+}
+
+static int ad7280_read_all_channels(struct ad7280_state *st, unsigned cnt,
+ unsigned *array)
+{
+ int i, ret;
+ unsigned tmp, sum = 0;
+
+ ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ, 1,
+ AD7280A_CELL_VOLTAGE_1 << 2);
+ if (ret)
+ return ret;
+
+ ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1,
+ AD7280A_CTRL_HB_CONV_INPUT_ALL |
+ AD7280A_CTRL_HB_CONV_RES_READ_ALL |
+ AD7280A_CTRL_HB_CONV_START_CS |
+ st->ctrl_hb);
+ if (ret)
+ return ret;
+
+ ad7280_delay(st);
+
+ for (i = 0; i < cnt; i++) {
+ __ad7280_read32(st->spi, &tmp);
+
+ if (ad7280_check_crc(st, tmp))
+ return -EIO;
+
+ if (array)
+ array[i] = tmp;
+ /* only sum cell voltages */
+ if (((tmp >> 23) & 0xF) <= AD7280A_CELL_VOLTAGE_6)
+ sum += ((tmp >> 11) & 0xFFF);
+ }
+
+ return sum;
+}
+
+static int ad7280_chain_setup(struct ad7280_state *st)
+{
+ unsigned val, n;
+ int ret;
+
+ ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_LB, 1,
+ AD7280A_CTRL_LB_DAISY_CHAIN_RB_EN |
+ AD7280A_CTRL_LB_LOCK_DEV_ADDR |
+ AD7280A_CTRL_LB_MUST_SET |
+ AD7280A_CTRL_LB_SWRST |
+ st->ctrl_lb);
+ if (ret)
+ return ret;
+
+ ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_LB, 1,
+ AD7280A_CTRL_LB_DAISY_CHAIN_RB_EN |
+ AD7280A_CTRL_LB_LOCK_DEV_ADDR |
+ AD7280A_CTRL_LB_MUST_SET |
+ st->ctrl_lb);
+ if (ret)
+ return ret;
+
+ ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ, 1,
+ AD7280A_CONTROL_LB << 2);
+ if (ret)
+ return ret;
+
+ for (n = 0; n <= AD7280A_MAX_CHAIN; n++) {
+ __ad7280_read32(st->spi, &val);
+ if (val == 0)
+ return n - 1;
+
+ if (ad7280_check_crc(st, val))
+ return -EIO;
+
+ if (n != AD7280A_DEVADDR(val >> 27))
+ return -EIO;
+ }
+
+ return -EFAULT;
+}
+
+static ssize_t ad7280_show_balance_sw(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct ad7280_state *st = iio_priv(dev_info);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+
+ return sprintf(buf, "%d\n",
+ !!(st->cb_mask[this_attr->address >> 8] &
+ (1 << ((this_attr->address & 0xFF) + 2))));
+}
+
+static ssize_t ad7280_store_balance_sw(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct ad7280_state *st = iio_priv(dev_info);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ bool readin;
+ int ret;
+ unsigned devaddr, ch;
+
+ ret = strtobool(buf, &readin);
+ if (ret)
+ return ret;
+
+ devaddr = this_attr->address >> 8;
+ ch = this_attr->address & 0xFF;
+
+ mutex_lock(&dev_info->mlock);
+ if (readin)
+ st->cb_mask[devaddr] |= 1 << (ch + 2);
+ else
+ st->cb_mask[devaddr] &= ~(1 << (ch + 2));
+
+ ret = ad7280_write(st, devaddr, AD7280A_CELL_BALANCE,
+ 0, st->cb_mask[devaddr]);
+ mutex_unlock(&dev_info->mlock);
+
+ return ret ? ret : len;
+}
+
+static ssize_t ad7280_show_balance_timer(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct ad7280_state *st = iio_priv(dev_info);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ int ret;
+ unsigned msecs;
+
+ mutex_lock(&dev_info->mlock);
+ ret = ad7280_read(st, this_attr->address >> 8,
+ this_attr->address & 0xFF);
+ mutex_unlock(&dev_info->mlock);
+
+ if (ret < 0)
+ return ret;
+
+ msecs = (ret >> 3) * 71500;
+
+ return sprintf(buf, "%d\n", msecs);
+}
+
+static ssize_t ad7280_store_balance_timer(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct ad7280_state *st = iio_priv(dev_info);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ long val;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ val /= 71500;
+
+ if (val > 31)
+ return -EINVAL;
+
+ mutex_lock(&dev_info->mlock);
+ ret = ad7280_write(st, this_attr->address >> 8,
+ this_attr->address & 0xFF,
+ 0, (val & 0x1F) << 3);
+ mutex_unlock(&dev_info->mlock);
+
+ return ret ? ret : len;
+}
+
+static struct attribute *ad7280_attributes[AD7280A_MAX_CHAIN *
+ AD7280A_CELLS_PER_DEV * 2 + 1];
+
+static struct attribute_group ad7280_attrs_group = {
+ .attrs = ad7280_attributes,
+};
+
+static int ad7280_channel_init(struct ad7280_state *st)
+{
+ int dev, ch, cnt;
+
+ st->channels = kzalloc(sizeof(*st->channels) *
+ ((st->slave_num + 1) * 12 + 2), GFP_KERNEL);
+ if (st->channels == NULL)
+ return -ENOMEM;
+
+ for (dev = 0, cnt = 0; dev <= st->slave_num; dev++)
+ for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_AUX_ADC_6; ch++,
+ cnt++) {
+ if (ch < AD7280A_AUX_ADC_1) {
+ st->channels[cnt].type = IIO_IN_DIFF;
+ st->channels[cnt].channel = (dev * 6) + ch;
+ st->channels[cnt].channel2 =
+ st->channels[cnt].channel + 1;
+ } else {
+ st->channels[cnt].type = IIO_TEMP;
+ st->channels[cnt].channel = (dev * 6) + ch - 6;
+ }
+ st->channels[cnt].indexed = 1;
+ st->channels[cnt].info_mask =
+ (1 << IIO_CHAN_INFO_SCALE_SHARED);
+ st->channels[cnt].address =
+ AD7280A_DEVADDR(dev) << 8 | ch;
+ st->channels[cnt].scan_index = cnt;
+ st->channels[cnt].scan_type.sign = 'u';
+ st->channels[cnt].scan_type.realbits = 12;
+ st->channels[cnt].scan_type.storagebits = 32;
+ st->channels[cnt].scan_type.shift = 0;
+ }
+
+ st->channels[cnt].type = IIO_IN_DIFF;
+ st->channels[cnt].channel = 0;
+ st->channels[cnt].channel2 = dev * 6;
+ st->channels[cnt].address = AD7280A_ALL_CELLS;
+ st->channels[cnt].indexed = 1;
+ st->channels[cnt].info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED);
+ st->channels[cnt].scan_index = cnt;
+ st->channels[cnt].scan_type.sign = 'u';
+ st->channels[cnt].scan_type.realbits = 32;
+ st->channels[cnt].scan_type.storagebits = 32;
+ st->channels[cnt].scan_type.shift = 0;
+ cnt++;
+ st->channels[cnt].type = IIO_TIMESTAMP;
+ st->channels[cnt].channel = -1;
+ st->channels[cnt].scan_index = cnt;
+ st->channels[cnt].scan_type.sign = 's';
+ st->channels[cnt].scan_type.realbits = 64;
+ st->channels[cnt].scan_type.storagebits = 64;
+ st->channels[cnt].scan_type.shift = 0;
+
+ return cnt + 1;
+}
+
+static int ad7280_attr_init(struct ad7280_state *st)
+{
+ int dev, ch, cnt;
+
+ st->iio_attr = kzalloc(sizeof(*st->iio_attr) * (st->slave_num + 1) *
+ AD7280A_CELLS_PER_DEV * 2, GFP_KERNEL);
+ if (st->iio_attr == NULL)
+ return -ENOMEM;
+
+ for (dev = 0, cnt = 0; dev <= st->slave_num; dev++)
+ for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_CELL_VOLTAGE_6;
+ ch++, cnt++) {
+ st->iio_attr[cnt].address =
+ AD7280A_DEVADDR(dev) << 8 | ch;
+ st->iio_attr[cnt].dev_attr.attr.mode =
+ S_IWUSR | S_IRUGO;
+ st->iio_attr[cnt].dev_attr.show =
+ ad7280_show_balance_sw;
+ st->iio_attr[cnt].dev_attr.store =
+ ad7280_store_balance_sw;
+ st->iio_attr[cnt].dev_attr.attr.name =
+ kasprintf(GFP_KERNEL,
+ "in%d-in%d_balance_switch_en",
+ (dev * AD7280A_CELLS_PER_DEV) + ch,
+ (dev * AD7280A_CELLS_PER_DEV) + ch + 1);
+ ad7280_attributes[cnt] =
+ &st->iio_attr[cnt].dev_attr.attr;
+ cnt++;
+ st->iio_attr[cnt].address =
+ AD7280A_DEVADDR(dev) << 8 |
+ (AD7280A_CB1_TIMER + ch);
+ st->iio_attr[cnt].dev_attr.attr.mode =
+ S_IWUSR | S_IRUGO;
+ st->iio_attr[cnt].dev_attr.show =
+ ad7280_show_balance_timer;
+ st->iio_attr[cnt].dev_attr.store =
+ ad7280_store_balance_timer;
+ st->iio_attr[cnt].dev_attr.attr.name =
+ kasprintf(GFP_KERNEL, "in%d-in%d_balance_timer",
+ (dev * AD7280A_CELLS_PER_DEV) + ch,
+ (dev * AD7280A_CELLS_PER_DEV) + ch + 1);
+ ad7280_attributes[cnt] =
+ &st->iio_attr[cnt].dev_attr.attr;
+ }
+
+ ad7280_attributes[cnt] = NULL;
+
+ return 0;
+}
+
+static ssize_t ad7280_read_channel_config(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct ad7280_state *st = iio_priv(dev_info);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ unsigned val;
+
+ switch (this_attr->address) {
+ case AD7280A_CELL_OVERVOLTAGE:
+ val = 1000 + (st->cell_threshhigh * 1568) / 100;
+ break;
+ case AD7280A_CELL_UNDERVOLTAGE:
+ val = 1000 + (st->cell_threshlow * 1568) / 100;
+ break;
+ case AD7280A_AUX_ADC_OVERVOLTAGE:
+ val = (st->aux_threshhigh * 196) / 10;
+ break;
+ case AD7280A_AUX_ADC_UNDERVOLTAGE:
+ val = (st->aux_threshlow * 196) / 10;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t ad7280_write_channel_config(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct ad7280_state *st = iio_priv(dev_info);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+
+ long val;
+ int ret;
+
+ ret = strict_strtol(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ switch (this_attr->address) {
+ case AD7280A_CELL_OVERVOLTAGE:
+ case AD7280A_CELL_UNDERVOLTAGE:
+ val = ((val - 1000) * 100) / 1568; /* LSB 15.68mV */
+ break;
+ case AD7280A_AUX_ADC_OVERVOLTAGE:
+ case AD7280A_AUX_ADC_UNDERVOLTAGE:
+ val = (val * 10) / 196; /* LSB 19.6mV */
+ break;
+ default:
+ return -EFAULT;
+ }
+
+ val = clamp(val, 0L, 0xFFL);
+
+ mutex_lock(&dev_info->mlock);
+ switch (this_attr->address) {
+ case AD7280A_CELL_OVERVOLTAGE:
+ st->cell_threshhigh = val;
+ break;
+ case AD7280A_CELL_UNDERVOLTAGE:
+ st->cell_threshlow = val;
+ break;
+ case AD7280A_AUX_ADC_OVERVOLTAGE:
+ st->aux_threshhigh = val;
+ break;
+ case AD7280A_AUX_ADC_UNDERVOLTAGE:
+ st->aux_threshlow = val;
+ break;
+ }
+
+ ret = ad7280_write(st, AD7280A_DEVADDR_MASTER,
+ this_attr->address, 1, val);
+
+ mutex_unlock(&dev_info->mlock);
+
+ return ret ? ret : len;
+}
+
+static irqreturn_t ad7280_event_handler(int irq, void *private)
+{
+ struct iio_dev *dev_info = private;
+ struct ad7280_state *st = iio_priv(dev_info);
+ unsigned *channels;
+ int i, ret;
+
+ channels = kzalloc(sizeof(*channels) * st->scan_cnt, GFP_KERNEL);
+ if (channels == NULL)
+ return IRQ_HANDLED;
+
+ ret = ad7280_read_all_channels(st, st->scan_cnt, channels);
+ if (ret < 0)
+ return IRQ_HANDLED;
+
+ for (i = 0; i < st->scan_cnt; i++) {
+ if (((channels[i] >> 23) & 0xF) <= AD7280A_CELL_VOLTAGE_6) {
+ if (((channels[i] >> 11) & 0xFFF) >=
+ st->cell_threshhigh)
+ iio_push_event(dev_info, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_IN_DIFF,
+ 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ iio_get_time_ns());
+ else if (((channels[i] >> 11) & 0xFFF) <=
+ st->cell_threshlow)
+ iio_push_event(dev_info, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_IN_DIFF,
+ 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ iio_get_time_ns());
+ } else {
+ if (((channels[i] >> 11) & 0xFFF) >= st->aux_threshhigh)
+ iio_push_event(dev_info, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP,
+ 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ iio_get_time_ns());
+ else if (((channels[i] >> 11) & 0xFFF) <=
+ st->aux_threshlow)
+ iio_push_event(dev_info, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP,
+ 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ iio_get_time_ns());
+ }
+ }
+
+ kfree(channels);
+
+ return IRQ_HANDLED;
+}
+
+static IIO_DEVICE_ATTR_NAMED(in_thresh_low_value,
+ in-in_thresh_low_value,
+ S_IRUGO | S_IWUSR,
+ ad7280_read_channel_config,
+ ad7280_write_channel_config,
+ AD7280A_CELL_UNDERVOLTAGE);
+
+static IIO_DEVICE_ATTR_NAMED(in_thresh_high_value,
+ in-in_thresh_high_value,
+ S_IRUGO | S_IWUSR,
+ ad7280_read_channel_config,
+ ad7280_write_channel_config,
+ AD7280A_CELL_OVERVOLTAGE);
+
+static IIO_DEVICE_ATTR(temp_thresh_low_value,
+ S_IRUGO | S_IWUSR,
+ ad7280_read_channel_config,
+ ad7280_write_channel_config,
+ AD7280A_AUX_ADC_UNDERVOLTAGE);
+
+static IIO_DEVICE_ATTR(temp_thresh_high_value,
+ S_IRUGO | S_IWUSR,
+ ad7280_read_channel_config,
+ ad7280_write_channel_config,
+ AD7280A_AUX_ADC_OVERVOLTAGE);
+
+
+static struct attribute *ad7280_event_attributes[] = {
+ &iio_dev_attr_in_thresh_low_value.dev_attr.attr,
+ &iio_dev_attr_in_thresh_high_value.dev_attr.attr,
+ &iio_dev_attr_temp_thresh_low_value.dev_attr.attr,
+ &iio_dev_attr_temp_thresh_high_value.dev_attr.attr,
+ NULL,
+};
+
+static struct attribute_group ad7280_event_attrs_group = {
+ .attrs = ad7280_event_attributes,
+};
+
+static int ad7280_read_raw(struct iio_dev *dev_info,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
+{
+ struct ad7280_state *st = iio_priv(dev_info);
+ unsigned int scale_uv;
+ int ret;
+
+ switch (m) {
+ case 0:
+ mutex_lock(&dev_info->mlock);
+ if (chan->address == AD7280A_ALL_CELLS)
+ ret = ad7280_read_all_channels(st, st->scan_cnt, NULL);
+ else
+ ret = ad7280_read_channel(st, chan->address >> 8,
+ chan->address & 0xFF);
+ mutex_unlock(&dev_info->mlock);
+
+ if (ret < 0)
+ return ret;
+
+ *val = ret;
+
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ if ((chan->address & 0xFF) <= AD7280A_CELL_VOLTAGE_6)
+ scale_uv = (4000 * 1000) >> AD7280A_BITS;
+ else
+ scale_uv = (5000 * 1000) >> AD7280A_BITS;
+
+ *val = scale_uv / 1000;
+ *val2 = (scale_uv % 1000) * 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+ return -EINVAL;
+}
+
+static const struct iio_info ad7280_info = {
+ .read_raw = &ad7280_read_raw,
+ .num_interrupt_lines = 1,
+ .event_attrs = &ad7280_event_attrs_group,
+ .attrs = &ad7280_attrs_group,
+ .driver_module = THIS_MODULE,
+};
+
+static const struct ad7280_platform_data ad7793_default_pdata = {
+ .acquisition_time = AD7280A_ACQ_TIME_400ns,
+ .conversion_averaging = AD7280A_CONV_AVG_DIS,
+ .thermistor_term_en = true,
+};
+
+static int __devinit ad7280_probe(struct spi_device *spi)
+{
+ const struct ad7280_platform_data *pdata = spi->dev.platform_data;
+ struct ad7280_state *st;
+ int ret, regdone = 0;
+ const unsigned short tACQ_ns[4] = {465, 1010, 1460, 1890};
+ const unsigned short nAVG[4] = {1, 2, 4, 8};
+ struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
+
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+ spi_set_drvdata(spi, indio_dev);
+ st->spi = spi;
+
+ if (!pdata)
+ pdata = &ad7793_default_pdata;
+
+ ad7280_crc8_build_table(st->crc_tab);
+
+ st->spi->max_speed_hz = AD7280A_MAX_SPI_CLK_Hz;
+ st->spi->mode = SPI_MODE_1;
+ spi_setup(st->spi);
+
+ st->ctrl_lb = AD7280A_CTRL_LB_ACQ_TIME(pdata->acquisition_time & 0x3);
+ st->ctrl_hb = AD7280A_CTRL_HB_CONV_AVG(pdata->conversion_averaging
+ & 0x3) | (pdata->thermistor_term_en ?
+ AD7280A_CTRL_LB_THERMISTOR_EN : 0);
+
+ ret = ad7280_chain_setup(st);
+ if (ret < 0)
+ goto error_free_device;
+
+ st->slave_num = ret;
+ st->scan_cnt = (st->slave_num + 1) * AD7280A_NUM_CH;
+ st->cell_threshhigh = 0xFF;
+ st->aux_threshhigh = 0xFF;
+
+ /*
+ * Total Conversion Time = ((tACQ + tCONV) *
+ * (Number of Conversions per Part)) −
+ * tACQ + ((N - 1) * tDELAY)
+ *
+ * Readback Delay = Total Conversion Time + tWAIT
+ */
+
+ st->readback_delay_us =
+ ((tACQ_ns[pdata->acquisition_time & 0x3] + 695) *
+ (AD7280A_NUM_CH * nAVG[pdata->conversion_averaging & 0x3]))
+ - tACQ_ns[pdata->acquisition_time & 0x3] +
+ st->slave_num * 250;
+
+ /* Convert to usecs */
+ st->readback_delay_us = DIV_ROUND_UP(st->readback_delay_us, 1000);
+ st->readback_delay_us += 5; /* Add tWAIT */
+
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ ret = ad7280_channel_init(st);
+ if (ret < 0)
+ goto error_free_device;
+
+ indio_dev->num_channels = ret;
+ indio_dev->channels = st->channels;
+ indio_dev->info = &ad7280_info;
+
+ ret = ad7280_attr_init(st);
+ if (ret < 0)
+ goto error_free_channels;
+
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto error_free_attr;
+ regdone = 1;
+
+ if (spi->irq > 0) {
+ ret = ad7280_write(st, AD7280A_DEVADDR_MASTER,
+ AD7280A_ALERT, 1,
+ AD7280A_ALERT_RELAY_SIG_CHAIN_DOWN);
+ if (ret)
+ goto error_free_attr;
+
+ ret = ad7280_write(st, AD7280A_DEVADDR(st->slave_num),
+ AD7280A_ALERT, 0,
+ AD7280A_ALERT_GEN_STATIC_HIGH |
+ (pdata->chain_last_alert_ignore & 0xF));
+ if (ret)
+ goto error_free_attr;
+
+ ret = request_threaded_irq(spi->irq,
+ NULL,
+ ad7280_event_handler,
+ IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ indio_dev->name,
+ indio_dev);
+ if (ret)
+ goto error_free_attr;
+ }
+
+ return 0;
+
+error_free_attr:
+ kfree(st->iio_attr);
+
+error_free_channels:
+ kfree(st->channels);
+
+error_free_device:
+ if (regdone)
+ iio_device_unregister(indio_dev);
+ else
+ iio_free_device(indio_dev);
+
+ return ret;
+}
+
+static int __devexit ad7280_remove(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct ad7280_state *st = iio_priv(indio_dev);
+
+ if (spi->irq > 0)
+ free_irq(spi->irq, indio_dev);
+
+ ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1,
+ AD7280A_CTRL_HB_PWRDN_SW | st->ctrl_hb);
+
+ kfree(st->channels);
+ kfree(st->iio_attr);
+ iio_device_unregister(indio_dev);
+
+ return 0;
+}
+
+static const struct spi_device_id ad7280_id[] = {
+ {"ad7280a", 0},
+ {}
+};
+
+static struct spi_driver ad7280_driver = {
+ .driver = {
+ .name = "ad7280",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = ad7280_probe,
+ .remove = __devexit_p(ad7280_remove),
+ .id_table = ad7280_id,
+};
+
+static int __init ad7280_init(void)
+{
+ return spi_register_driver(&ad7280_driver);
+}
+module_init(ad7280_init);
+
+static void __exit ad7280_exit(void)
+{
+ spi_unregister_driver(&ad7280_driver);
+}
+module_exit(ad7280_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD7280A");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/adc/ad7280a.h b/drivers/staging/iio/adc/ad7280a.h
new file mode 100644
index 000000000000..20400b0045e5
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7280a.h
@@ -0,0 +1,38 @@
+/*
+ * AD7280A Lithium Ion Battery Monitoring System
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef IIO_ADC_AD7280_H_
+#define IIO_ADC_AD7280_H_
+
+/*
+ * TODO: struct ad7280_platform_data needs to go into include/linux/iio
+ */
+
+#define AD7280A_ACQ_TIME_400ns 0
+#define AD7280A_ACQ_TIME_800ns 1
+#define AD7280A_ACQ_TIME_1200ns 2
+#define AD7280A_ACQ_TIME_1600ns 3
+
+#define AD7280A_CONV_AVG_DIS 0
+#define AD7280A_CONV_AVG_2 1
+#define AD7280A_CONV_AVG_4 2
+#define AD7280A_CONV_AVG_8 3
+
+#define AD7280A_ALERT_REMOVE_VIN5 (1 << 2)
+#define AD7280A_ALERT_REMOVE_VIN4_VIN5 (2 << 2)
+#define AD7280A_ALERT_REMOVE_AUX5 (1 << 0)
+#define AD7280A_ALERT_REMOVE_AUX4_AUX5 (2 << 0)
+
+struct ad7280_platform_data {
+ unsigned acquisition_time;
+ unsigned conversion_averaging;
+ unsigned chain_last_alert_ignore;
+ bool thermistor_term_en;
+};
+
+#endif /* IIO_ADC_AD7280_H_ */
diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c
index 96cbb17bc2cd..e884c78d8047 100644
--- a/drivers/staging/iio/adc/ad7291.c
+++ b/drivers/staging/iio/adc/ad7291.c
@@ -14,6 +14,7 @@
#include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/i2c.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/staging/iio/adc/ad7298_core.c
index b8e4ae29b0b5..3e5bead26367 100644
--- a/drivers/staging/iio/adc/ad7298_core.c
+++ b/drivers/staging/iio/adc/ad7298_core.c
@@ -14,11 +14,11 @@
#include <linux/regulator/consumer.h>
#include <linux/err.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
#include "../ring_generic.h"
-#include "adc.h"
#include "ad7298.h"
diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c
index a04c03352624..741818c0b829 100644
--- a/drivers/staging/iio/adc/ad7298_ring.c
+++ b/drivers/staging/iio/adc/ad7298_ring.c
@@ -7,17 +7,14 @@
*/
#include <linux/interrupt.h>
-#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
-#include <linux/sysfs.h>
#include <linux/spi/spi.h>
#include "../iio.h"
#include "../ring_generic.h"
#include "../ring_sw.h"
-#include "../trigger.h"
-#include "../sysfs.h"
+#include "../trigger_consumer.h"
#include "ad7298.h"
@@ -120,7 +117,7 @@ static int ad7298_ring_preenable(struct iio_dev *indio_dev)
static irqreturn_t ad7298_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
+ struct iio_dev *indio_dev = pf->indio_dev;
struct ad7298_state *st = iio_priv(indio_dev);
struct iio_ring_buffer *ring = indio_dev->ring;
s64 time_ns;
@@ -192,11 +189,6 @@ error_ret:
void ad7298_ring_cleanup(struct iio_dev *indio_dev)
{
- if (indio_dev->trig) {
- iio_put_trigger(indio_dev->trig);
- iio_trigger_dettach_poll_func(indio_dev->trig,
- indio_dev->pollfunc);
- }
iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
diff --git a/drivers/staging/iio/adc/ad7314.c b/drivers/staging/iio/adc/ad7314.c
index 9070d9cac725..e3d38dbd846f 100644
--- a/drivers/staging/iio/adc/ad7314.c
+++ b/drivers/staging/iio/adc/ad7314.c
@@ -11,6 +11,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/spi/spi.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c
index c21089894d28..bb8be5daa6b8 100644
--- a/drivers/staging/iio/adc/ad7476_core.c
+++ b/drivers/staging/iio/adc/ad7476_core.c
@@ -13,11 +13,11 @@
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
#include "../ring_generic.h"
-#include "adc.h"
#include "ad7476.h"
diff --git a/drivers/staging/iio/adc/ad7476_ring.c b/drivers/staging/iio/adc/ad7476_ring.c
index a92fc5a1a604..b109afb89846 100644
--- a/drivers/staging/iio/adc/ad7476_ring.c
+++ b/drivers/staging/iio/adc/ad7476_ring.c
@@ -11,14 +11,12 @@
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
-#include <linux/sysfs.h>
#include <linux/spi/spi.h>
#include "../iio.h"
#include "../ring_generic.h"
#include "../ring_sw.h"
-#include "../trigger.h"
-#include "../sysfs.h"
+#include "../trigger_consumer.h"
#include "ad7476.h"
@@ -78,7 +76,7 @@ static int ad7476_ring_preenable(struct iio_dev *indio_dev)
static irqreturn_t ad7476_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
+ struct iio_dev *indio_dev = pf->indio_dev;
struct ad7476_state *st = iio_priv(indio_dev);
s64 time_ns;
__u8 *rxbuf;
@@ -154,12 +152,6 @@ error_ret:
void ad7476_ring_cleanup(struct iio_dev *indio_dev)
{
- /* ensure that the trigger has been detached */
- if (indio_dev->trig) {
- iio_put_trigger(indio_dev->trig);
- iio_trigger_dettach_poll_func(indio_dev->trig,
- indio_dev->pollfunc);
- }
iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c
index 459371ae4dcc..ef0558130ca7 100644
--- a/drivers/staging/iio/adc/ad7606_core.c
+++ b/drivers/staging/iio/adc/ad7606_core.c
@@ -16,11 +16,11 @@
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/sched.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
#include "../ring_generic.h"
-#include "adc.h"
#include "ad7606.h"
diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c
index a199bf48396c..e6424300c8e7 100644
--- a/drivers/staging/iio/adc/ad7606_ring.c
+++ b/drivers/staging/iio/adc/ad7606_ring.c
@@ -10,13 +10,11 @@
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
-#include <linux/sysfs.h>
#include "../iio.h"
#include "../ring_generic.h"
#include "../ring_sw.h"
-#include "../trigger.h"
-#include "../sysfs.h"
+#include "../trigger_consumer.h"
#include "ad7606.h"
@@ -82,8 +80,7 @@ static int ad7606_ring_preenable(struct iio_dev *indio_dev)
static irqreturn_t ad7606_trigger_handler_th_bh(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
- struct ad7606_state *st = iio_priv(indio_dev);
+ struct ad7606_state *st = iio_priv(pf->indio_dev);
gpio_set_value(st->pdata->gpio_convst, 1);
@@ -200,11 +197,6 @@ error_ret:
void ad7606_ring_cleanup(struct iio_dev *indio_dev)
{
- if (indio_dev->trig) {
- iio_put_trigger(indio_dev->trig);
- iio_trigger_dettach_poll_func(indio_dev->trig,
- indio_dev->pollfunc);
- }
iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
diff --git a/drivers/staging/iio/adc/ad7745.c b/drivers/staging/iio/adc/ad7745.c
index 4c13f26aa9ae..91d598c1a14b 100644
--- a/drivers/staging/iio/adc/ad7745.c
+++ b/drivers/staging/iio/adc/ad7745.c
@@ -14,6 +14,7 @@
#include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/i2c.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c
index e0c7b6cc05c7..46d1f8f3fe82 100644
--- a/drivers/staging/iio/adc/ad7780.c
+++ b/drivers/staging/iio/adc/ad7780.c
@@ -16,11 +16,11 @@
#include <linux/err.h>
#include <linux/sched.h>
#include <linux/gpio.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
#include "../ring_generic.h"
-#include "adc.h"
#include "ad7780.h"
diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
index 90f6c039d6c6..1bcb3ebb1bc6 100644
--- a/drivers/staging/iio/adc/ad7793.c
+++ b/drivers/staging/iio/adc/ad7793.c
@@ -22,7 +22,7 @@
#include "../ring_generic.h"
#include "../ring_sw.h"
#include "../trigger.h"
-#include "adc.h"
+#include "../trigger_consumer.h"
#include "ad7793.h"
@@ -402,7 +402,7 @@ static int ad7793_ring_postdisable(struct iio_dev *indio_dev)
static irqreturn_t ad7793_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
+ struct iio_dev *indio_dev = pf->indio_dev;
struct iio_ring_buffer *ring = indio_dev->ring;
struct ad7793_state *st = iio_priv(indio_dev);
s64 dat64[2];
@@ -470,12 +470,6 @@ error_ret:
static void ad7793_ring_cleanup(struct iio_dev *indio_dev)
{
- /* ensure that the trigger has been detached */
- if (indio_dev->trig) {
- iio_put_trigger(indio_dev->trig);
- iio_trigger_dettach_poll_func(indio_dev->trig,
- indio_dev->pollfunc);
- }
iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c
index 0c84217bde3d..f5aa57bb8f23 100644
--- a/drivers/staging/iio/adc/ad7816.c
+++ b/drivers/staging/iio/adc/ad7816.c
@@ -14,6 +14,7 @@
#include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/spi/spi.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -246,7 +247,7 @@ static const struct attribute_group ad7816_attribute_group = {
* temperature bound events
*/
-#define IIO_EVENT_CODE_AD7816_OTI IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_TEMP, \
+#define IIO_EVENT_CODE_AD7816_OTI IIO_UNMOD_EVENT_CODE(IIO_TEMP, \
0, \
IIO_EV_TYPE_THRESH, \
IIO_EV_DIR_FALLING)
diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c
index 3d9121e5c37d..74e222f92431 100644
--- a/drivers/staging/iio/adc/ad7887_core.c
+++ b/drivers/staging/iio/adc/ad7887_core.c
@@ -13,11 +13,12 @@
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
#include "../ring_generic.h"
-#include "adc.h"
+
#include "ad7887.h"
diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c
index 0ac7c0b9d71d..6b3daf41e0c6 100644
--- a/drivers/staging/iio/adc/ad7887_ring.c
+++ b/drivers/staging/iio/adc/ad7887_ring.c
@@ -8,17 +8,14 @@
*/
#include <linux/interrupt.h>
-#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
-#include <linux/sysfs.h>
#include <linux/spi/spi.h>
#include "../iio.h"
#include "../ring_generic.h"
#include "../ring_sw.h"
-#include "../trigger.h"
-#include "../sysfs.h"
+#include "../trigger_consumer.h"
#include "ad7887.h"
@@ -115,7 +112,7 @@ static int ad7887_ring_postdisable(struct iio_dev *indio_dev)
static irqreturn_t ad7887_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
+ struct iio_dev *indio_dev = pf->indio_dev;
struct ad7887_state *st = iio_priv(indio_dev);
struct iio_ring_buffer *ring = indio_dev->ring;
s64 time_ns;
@@ -191,12 +188,6 @@ error_ret:
void ad7887_ring_cleanup(struct iio_dev *indio_dev)
{
- /* ensure that the trigger has been detached */
- if (indio_dev->trig) {
- iio_put_trigger(indio_dev->trig);
- iio_trigger_dettach_poll_func(indio_dev->trig,
- indio_dev->pollfunc);
- }
iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c
index 92cfe2e3ea4a..33e4e2197143 100644
--- a/drivers/staging/iio/adc/ad799x_core.c
+++ b/drivers/staging/iio/adc/ad799x_core.c
@@ -31,12 +31,12 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/err.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
-
#include "../ring_generic.h"
-#include "adc.h"
+
#include "ad799x.h"
/*
@@ -336,8 +336,14 @@ static irqreturn_t ad799x_event_handler(int irq, void *private)
if (status & (1 << i))
iio_push_event(indio_dev, 0,
i & 0x1 ?
- IIO_EVENT_CODE_IN_HIGH_THRESH(i >> 1) :
- IIO_EVENT_CODE_IN_LOW_THRESH(i >> 1),
+ IIO_UNMOD_EVENT_CODE(IIO_IN,
+ (i >> 1),
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING) :
+ IIO_UNMOD_EVENT_CODE(IIO_IN,
+ (i >> 1),
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
iio_get_time_ns());
}
diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c
index 0376a826c26c..8f1fc52560f1 100644
--- a/drivers/staging/iio/adc/ad799x_ring.c
+++ b/drivers/staging/iio/adc/ad799x_ring.c
@@ -10,10 +10,8 @@
*/
#include <linux/interrupt.h>
-#include <linux/device.h>
#include <linux/slab.h>
#include <linux/kernel.h>
-#include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/i2c.h>
#include <linux/bitops.h>
@@ -21,8 +19,7 @@
#include "../iio.h"
#include "../ring_generic.h"
#include "../ring_sw.h"
-#include "../trigger.h"
-#include "../sysfs.h"
+#include "../trigger_consumer.h"
#include "ad799x.h"
@@ -108,7 +105,7 @@ static int ad799x_ring_preenable(struct iio_dev *indio_dev)
static irqreturn_t ad799x_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
+ struct iio_dev *indio_dev = pf->indio_dev;
struct ad799x_state *st = iio_priv(indio_dev);
struct iio_ring_buffer *ring = indio_dev->ring;
s64 time_ns;
@@ -207,12 +204,6 @@ error_ret:
void ad799x_ring_cleanup(struct iio_dev *indio_dev)
{
- /* ensure that the trigger has been detached */
- if (indio_dev->trig) {
- iio_put_trigger(indio_dev->trig);
- iio_trigger_dettach_poll_func(indio_dev->trig,
- indio_dev->pollfunc);
- }
iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
diff --git a/drivers/staging/iio/adc/adc.h b/drivers/staging/iio/adc/adc.h
deleted file mode 100644
index 40c5949880b4..000000000000
--- a/drivers/staging/iio/adc/adc.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * adc.h - sysfs attributes associated with ADCs
- *
- * 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.
- *
- * Copyright (c) 2008 Jonathan Cameron <jic23@cam.ac.uk>
- *
- */
-
-/* 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_NAMED_RAW(_num, _name, _show, _addr) \
- IIO_DEVICE_ATTR(in##_num##_##_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, \
- S_IRUGO, \
- _show, \
- NULL, \
- _addr)
-
-
-#define IIO_CONST_ATTR_IN_NAMED_OFFSET(_num, _name, _string) \
- IIO_CONST_ATTR(in##_num##_##_name##_offset, _string)
-
-#define IIO_CONST_ATTR_IN_NAMED_SCALE(_num, _name, _string) \
- IIO_CONST_ATTR(in##_num##_##_name##_scale, _string)
-
-#define IIO_EVENT_CODE_IN_HIGH_THRESH(a) \
- IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, a, IIO_EV_TYPE_THRESH, \
- IIO_EV_DIR_RISING)
-#define IIO_EVENT_CODE_IN_LOW_THRESH(a) \
- IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, a, IIO_EV_TYPE_THRESH, \
- IIO_EV_DIR_FALLING)
diff --git a/drivers/staging/iio/adc/adt7310.c b/drivers/staging/iio/adc/adt7310.c
index 1a41b8034405..697ad1b91954 100644
--- a/drivers/staging/iio/adc/adt7310.c
+++ b/drivers/staging/iio/adc/adt7310.c
@@ -13,6 +13,7 @@
#include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/spi/spi.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c
index 76aa0639a55a..b7631f18ee2d 100644
--- a/drivers/staging/iio/adc/adt7410.c
+++ b/drivers/staging/iio/adc/adt7410.c
@@ -13,6 +13,7 @@
#include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/i2c.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
diff --git a/drivers/staging/iio/adc/adt75.c b/drivers/staging/iio/adc/adt75.c
index 38f141de6a4b..dd782776ce34 100644
--- a/drivers/staging/iio/adc/adt75.c
+++ b/drivers/staging/iio/adc/adt75.c
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/i2c.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -257,7 +258,7 @@ static const struct attribute_group adt75_attribute_group = {
* temperature bound events
*/
-#define IIO_EVENT_CODE_ADT75_OTI IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_TEMP, \
+#define IIO_EVENT_CODE_ADT75_OTI IIO_UNMOD_EVENT_CODE(IIO_TEMP, \
0, \
IIO_EV_TYPE_THRESH, \
IIO_EV_DIR_FALLING)
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c
index 72b0917412ee..e10a4d828146 100644
--- a/drivers/staging/iio/adc/max1363_core.c
+++ b/drivers/staging/iio/adc/max1363_core.c
@@ -30,12 +30,12 @@
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/err.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
-
#include "../ring_generic.h"
-#include "adc.h"
+
#include "max1363.h"
#define MAX1363_MODE_SINGLE(_num, _mask) { \
@@ -255,7 +255,7 @@ static int max1363_read_raw(struct iio_dev *indio_dev,
switch (m) {
case 0:
ret = max1363_read_single_chan(indio_dev, chan, val, m);
- if (ret)
+ if (ret < 0)
return ret;
return IIO_VAL_INT;
case (1 << IIO_CHAN_INFO_SCALE_SHARED):
@@ -592,10 +592,14 @@ static int max1363_write_thresh(struct iio_dev *indio_dev,
}
static const int max1363_event_codes[] = {
- IIO_EVENT_CODE_IN_LOW_THRESH(3), IIO_EVENT_CODE_IN_HIGH_THRESH(3),
- IIO_EVENT_CODE_IN_LOW_THRESH(2), IIO_EVENT_CODE_IN_HIGH_THRESH(2),
- IIO_EVENT_CODE_IN_LOW_THRESH(1), IIO_EVENT_CODE_IN_HIGH_THRESH(1),
- IIO_EVENT_CODE_IN_LOW_THRESH(0), IIO_EVENT_CODE_IN_HIGH_THRESH(0)
+ IIO_UNMOD_EVENT_CODE(IIO_IN, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),
+ IIO_UNMOD_EVENT_CODE(IIO_IN, 1, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),
+ IIO_UNMOD_EVENT_CODE(IIO_IN, 2, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),
+ IIO_UNMOD_EVENT_CODE(IIO_IN, 3, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),
+ IIO_UNMOD_EVENT_CODE(IIO_IN, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
+ IIO_UNMOD_EVENT_CODE(IIO_IN, 1, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
+ IIO_UNMOD_EVENT_CODE(IIO_IN, 2, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
+ IIO_UNMOD_EVENT_CODE(IIO_IN, 3, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
};
static irqreturn_t max1363_event_handler(int irq, void *private)
@@ -1295,6 +1299,8 @@ static int __devinit max1363_probe(struct i2c_client *client,
indio_dev->info = st->chip_info->info;
indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = st->chip_info->channels;
+ indio_dev->num_channels = st->chip_info->num_channels;
ret = max1363_initial_setup(st);
if (ret < 0)
goto error_free_available_scan_masks;
diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c
index f43befd1f776..be601e07639d 100644
--- a/drivers/staging/iio/adc/max1363_ring.c
+++ b/drivers/staging/iio/adc/max1363_ring.c
@@ -9,19 +9,15 @@
*/
#include <linux/interrupt.h>
-#include <linux/device.h>
#include <linux/slab.h>
#include <linux/kernel.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
#include <linux/i2c.h>
#include <linux/bitops.h>
#include "../iio.h"
#include "../ring_generic.h"
#include "../ring_sw.h"
-#include "../trigger.h"
-#include "../sysfs.h"
+#include "../trigger_consumer.h"
#include "max1363.h"
@@ -108,7 +104,7 @@ static int max1363_ring_preenable(struct iio_dev *indio_dev)
static irqreturn_t max1363_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
+ struct iio_dev *indio_dev = pf->indio_dev;
struct max1363_state *st = iio_priv(indio_dev);
s64 time_ns;
__u8 *rxbuf;
@@ -199,11 +195,6 @@ error_ret:
void max1363_ring_cleanup(struct iio_dev *indio_dev)
{
/* ensure that the trigger has been detached */
- if (indio_dev->trig) {
- iio_put_trigger(indio_dev->trig);
- iio_trigger_dettach_poll_func(indio_dev->trig,
- indio_dev->pollfunc);
- }
iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c
index 52d1ea349635..69fab53dec9d 100644
--- a/drivers/staging/iio/addac/adt7316-i2c.c
+++ b/drivers/staging/iio/addac/adt7316-i2c.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include "adt7316.h"
diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c
index 637316f79f78..474d946866de 100644
--- a/drivers/staging/iio/addac/adt7316.c
+++ b/drivers/staging/iio/addac/adt7316.c
@@ -17,6 +17,7 @@
#include <linux/list.h>
#include <linux/i2c.h>
#include <linux/rtc.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -203,7 +204,7 @@ struct adt7316_chip_info {
#define ADT7316_TEMP_INT_MASK 0x1F
#define ADT7516_AIN_INT_MASK 0xE0
#define ADT7316_TEMP_AIN_INT_MASK \
- (ADT7316_TEMP_INT_MASK | ADT7316_TEMP_INT_MASK)
+ (ADT7316_TEMP_INT_MASK)
/*
* struct adt7316_chip_info - chip specifc information
diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c
index e8a9d0bf1edb..c670fb9de31f 100644
--- a/drivers/staging/iio/dac/ad5446.c
+++ b/drivers/staging/iio/dac/ad5446.c
@@ -16,6 +16,7 @@
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c
index 1915f459868b..5243ef962b5c 100644
--- a/drivers/staging/iio/dac/ad5504.c
+++ b/drivers/staging/iio/dac/ad5504.c
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/regulator/consumer.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -251,7 +252,7 @@ static struct attribute_group ad5504_ev_attribute_group = {
static irqreturn_t ad5504_event_handler(int irq, void *private)
{
iio_push_event(private, 0,
- IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_TEMP,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP,
0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
@@ -338,7 +339,7 @@ error_free_dev:
iio_free_device(indio_dev);
error_disable_reg:
if (!IS_ERR(reg))
- regulator_disable(st->reg);
+ regulator_disable(reg);
error_put_reg:
if (!IS_ERR(reg))
regulator_put(reg);
diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/staging/iio/dac/ad5624r_spi.c
index a5b3776718e9..7303bb139014 100644
--- a/drivers/staging/iio/dac/ad5624r_spi.c
+++ b/drivers/staging/iio/dac/ad5624r_spi.c
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/regulator/consumer.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
diff --git a/drivers/staging/iio/dac/ad5686.c b/drivers/staging/iio/dac/ad5686.c
index fd67cfa5edb6..ae71d3f87d64 100644
--- a/drivers/staging/iio/dac/ad5686.c
+++ b/drivers/staging/iio/dac/ad5686.c
@@ -10,6 +10,7 @@
#include <linux/gpio.h>
#include <linux/fs.h>
#include <linux/device.h>
+#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c
index 64770d2a1b4c..5c45d0fe8165 100644
--- a/drivers/staging/iio/dac/ad5791.c
+++ b/drivers/staging/iio/dac/ad5791.c
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/regulator/consumer.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -381,7 +382,6 @@ error_put_reg_pos:
if (!IS_ERR(reg_vdd))
regulator_put(reg_vdd);
-error_ret:
return ret;
}
diff --git a/drivers/staging/iio/dds/ad5930.c b/drivers/staging/iio/dds/ad5930.c
index 0b2aa4cafdd8..4847ea2941d4 100644
--- a/drivers/staging/iio/dds/ad5930.c
+++ b/drivers/staging/iio/dds/ad5930.c
@@ -14,6 +14,7 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
diff --git a/drivers/staging/iio/dds/ad9832.c b/drivers/staging/iio/dds/ad9832.c
index e3e61a469bb8..e6cfa649e8c9 100644
--- a/drivers/staging/iio/dds/ad9832.c
+++ b/drivers/staging/iio/dds/ad9832.c
@@ -13,6 +13,7 @@
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
+#include <linux/module.h>
#include <asm/div64.h>
#include "../iio.h"
diff --git a/drivers/staging/iio/dds/ad9834.c b/drivers/staging/iio/dds/ad9834.c
index e6454d58fe41..a5b5aedd7691 100644
--- a/drivers/staging/iio/dds/ad9834.c
+++ b/drivers/staging/iio/dds/ad9834.c
@@ -16,6 +16,7 @@
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
+#include <linux/module.h>
#include <asm/div64.h>
#include "../iio.h"
diff --git a/drivers/staging/iio/dds/ad9850.c b/drivers/staging/iio/dds/ad9850.c
index d7c9d05f6359..7f2dd47334f3 100644
--- a/drivers/staging/iio/dds/ad9850.c
+++ b/drivers/staging/iio/dds/ad9850.c
@@ -14,6 +14,7 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
diff --git a/drivers/staging/iio/dds/ad9852.c b/drivers/staging/iio/dds/ad9852.c
index 0184585425d8..7f65b92598d5 100644
--- a/drivers/staging/iio/dds/ad9852.c
+++ b/drivers/staging/iio/dds/ad9852.c
@@ -14,6 +14,7 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -217,7 +218,6 @@ static struct attribute *ad9852_attributes[] = {
};
static const struct attribute_group ad9852_attribute_group = {
- .name = DRV_NAME,
.attrs = ad9852_attributes,
};
diff --git a/drivers/staging/iio/dds/ad9910.c b/drivers/staging/iio/dds/ad9910.c
index 0fa217f7b901..b72df8ca7235 100644
--- a/drivers/staging/iio/dds/ad9910.c
+++ b/drivers/staging/iio/dds/ad9910.c
@@ -14,6 +14,7 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -352,7 +353,6 @@ static struct attribute *ad9910_attributes[] = {
};
static const struct attribute_group ad9910_attribute_group = {
- .name = DRV_NAME,
.attrs = ad9910_attributes,
};
diff --git a/drivers/staging/iio/dds/ad9951.c b/drivers/staging/iio/dds/ad9951.c
index d361d1f125de..3d478e7a48fc 100644
--- a/drivers/staging/iio/dds/ad9951.c
+++ b/drivers/staging/iio/dds/ad9951.c
@@ -14,6 +14,7 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -161,7 +162,6 @@ static struct attribute *ad9951_attributes[] = {
};
static const struct attribute_group ad9951_attribute_group = {
- .name = DRV_NAME,
.attrs = ad9951_attributes,
};
diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c
index afa52d1961a9..3f5087329e5b 100644
--- a/drivers/staging/iio/gyro/adis16060_core.c
+++ b/drivers/staging/iio/gyro/adis16060_core.c
@@ -13,12 +13,10 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
-
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
-#include "gyro.h"
-#include "../adc/adc.h"
#define ADIS16060_GYRO 0x20 /* Measure Angular Rate (Gyro) */
#define ADIS16060_TEMP_OUT 0x10 /* Measure Temperature */
@@ -42,11 +40,9 @@ struct adis16060_state {
static struct iio_dev *adis16060_iio_dev;
-static int adis16060_spi_write(struct device *dev,
- u8 val)
+static int adis16060_spi_write(struct iio_dev *indio_dev, u8 val)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16060_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
@@ -57,11 +53,9 @@ static int adis16060_spi_write(struct device *dev,
return ret;
}
-static int adis16060_spi_read(struct device *dev,
- u16 *val)
+static int adis16060_spi_read(struct iio_dev *indio_dev, u16 *val)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16060_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
@@ -82,60 +76,71 @@ static int adis16060_spi_read(struct device *dev,
return ret;
}
-static ssize_t adis16060_read(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int adis16060_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2,
+ long mask)
{
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- u16 val = 0;
- ssize_t ret;
-
- /* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
+ u16 tval = 0;
+ int ret;
- ret = adis16060_spi_write(dev, this_attr->address);
- if (ret < 0)
- goto error_ret;
- ret = adis16060_spi_read(dev, &val);
-error_ret:
- mutex_unlock(&indio_dev->mlock);
+ switch (mask) {
+ case 0:
+ /* Take the iio_dev status lock */
+ mutex_lock(&indio_dev->mlock);
+ ret = adis16060_spi_write(indio_dev, chan->address);
+ if (ret < 0) {
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+ }
+ ret = adis16060_spi_read(indio_dev, &tval);
+ mutex_unlock(&indio_dev->mlock);
+ *val = tval;
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ *val = -7;
+ *val2 = 461117;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ *val = 0;
+ *val2 = 34000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
- if (ret == 0)
- return sprintf(buf, "%d\n", val);
- else
- return ret;
+ return -EINVAL;
}
-static IIO_DEV_ATTR_GYRO_Z(adis16060_read, ADIS16060_GYRO);
-static IIO_DEVICE_ATTR(temp_raw, S_IRUGO, adis16060_read, NULL,
- ADIS16060_TEMP_OUT);
-static IIO_CONST_ATTR_TEMP_SCALE("34"); /* Milli degrees C */
-static IIO_CONST_ATTR_TEMP_OFFSET("-7461.117"); /* Milli degrees C */
-static IIO_DEV_ATTR_IN_RAW(0, adis16060_read, ADIS16060_AIN1);
-static IIO_DEV_ATTR_IN_RAW(1, adis16060_read, ADIS16060_AIN2);
-static IIO_CONST_ATTR(name, "adis16060");
-
-static struct attribute *adis16060_attributes[] = {
- &iio_dev_attr_gyro_z_raw.dev_attr.attr,
- &iio_dev_attr_temp_raw.dev_attr.attr,
- &iio_const_attr_temp_scale.dev_attr.attr,
- &iio_const_attr_temp_offset.dev_attr.attr,
- &iio_dev_attr_in0_raw.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_const_attr_name.dev_attr.attr,
- NULL
-};
-
-static const struct attribute_group adis16060_attribute_group = {
- .attrs = adis16060_attributes,
-};
-
static const struct iio_info adis16060_info = {
- .attrs = &adis16060_attribute_group,
+ .read_raw = &adis16060_read_raw,
.driver_module = THIS_MODULE,
};
+static const struct iio_chan_spec adis16060_channels[] = {
+ {
+ .type = IIO_GYRO,
+ .modified = 1,
+ .channel2 = IIO_MOD_Z,
+ .address = ADIS16060_GYRO,
+ }, {
+ .type = IIO_IN,
+ .indexed = 1,
+ .channel = 0,
+ .address = ADIS16060_AIN1,
+ }, {
+ .type = IIO_IN,
+ .indexed = 1,
+ .channel = 1,
+ .address = ADIS16060_AIN2,
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .address = ADIS16060_TEMP_OUT,
+ }
+};
+
static int __devinit adis16060_r_probe(struct spi_device *spi)
{
int ret, regdone = 0;
@@ -154,9 +159,12 @@ static int __devinit adis16060_r_probe(struct spi_device *spi)
st->us_r = spi;
mutex_init(&st->buf_lock);
+ indio_dev->name = spi->dev.driver->name;
indio_dev->dev.parent = &spi->dev;
indio_dev->info = &adis16060_info;
indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = adis16060_channels;
+ indio_dev->num_channels = ARRAY_SIZE(adis16060_channels);
ret = iio_device_register(indio_dev);
if (ret)
diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c
index ad2db4d723df..16ba0e11e443 100644
--- a/drivers/staging/iio/gyro/adis16080_core.c
+++ b/drivers/staging/iio/gyro/adis16080_core.c
@@ -13,11 +13,10 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
-#include "gyro.h"
-#include "../adc/adc.h"
#define ADIS16080_DIN_GYRO (0 << 10) /* Gyroscope output */
#define ADIS16080_DIN_TEMP (1 << 10) /* Temperature output */
@@ -44,11 +43,10 @@ struct adis16080_state {
u8 buf[2] ____cacheline_aligned;
};
-static int adis16080_spi_write(struct device *dev,
+static int adis16080_spi_write(struct iio_dev *indio_dev,
u16 val)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16080_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
@@ -61,11 +59,10 @@ static int adis16080_spi_write(struct device *dev,
return ret;
}
-static int adis16080_spi_read(struct device *dev,
- u16 *val)
+static int adis16080_spi_read(struct iio_dev *indio_dev,
+ u16 *val)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16080_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
@@ -79,50 +76,62 @@ static int adis16080_spi_read(struct device *dev,
return ret;
}
-static ssize_t adis16080_read(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int adis16080_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long mask)
{
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- u16 val = 0;
- ssize_t ret;
-
+ int ret = -EINVAL;
+ u16 ut;
/* Take the iio_dev status lock */
+
mutex_lock(&indio_dev->mlock);
- ret = adis16080_spi_write(dev,
- this_attr->address | ADIS16080_DIN_WRITE);
- if (ret < 0)
- goto error_ret;
- ret = adis16080_spi_read(dev, &val);
-error_ret:
+ switch (mask) {
+ case 0:
+ ret = adis16080_spi_write(indio_dev,
+ chan->address |
+ ADIS16080_DIN_WRITE);
+ if (ret < 0)
+ break;
+ ret = adis16080_spi_read(indio_dev, &ut);
+ if (ret < 0)
+ break;
+ *val = ut;
+ ret = IIO_VAL_INT;
+ break;
+ }
mutex_unlock(&indio_dev->mlock);
- if (ret == 0)
- return sprintf(buf, "%d\n", val);
- else
- return ret;
+ return ret;
}
-static IIO_DEV_ATTR_GYRO_Z(adis16080_read, ADIS16080_DIN_GYRO);
-static IIO_DEVICE_ATTR(temp_raw, S_IRUGO, adis16080_read, NULL,
- ADIS16080_DIN_TEMP);
-static IIO_DEV_ATTR_IN_RAW(0, adis16080_read, ADIS16080_DIN_AIN1);
-static IIO_DEV_ATTR_IN_RAW(1, adis16080_read, ADIS16080_DIN_AIN2);
-
-static struct attribute *adis16080_attributes[] = {
- &iio_dev_attr_gyro_z_raw.dev_attr.attr,
- &iio_dev_attr_temp_raw.dev_attr.attr,
- &iio_dev_attr_in0_raw.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- NULL
-};
-static const struct attribute_group adis16080_attribute_group = {
- .attrs = adis16080_attributes,
+static const struct iio_chan_spec adis16080_channels[] = {
+ {
+ .type = IIO_GYRO,
+ .modified = 1,
+ .channel2 = IIO_MOD_Z,
+ .address = ADIS16080_DIN_GYRO,
+ }, {
+ .type = IIO_IN,
+ .indexed = 1,
+ .channel = 0,
+ .address = ADIS16080_DIN_AIN1,
+ }, {
+ .type = IIO_IN,
+ .indexed = 1,
+ .channel = 1,
+ .address = ADIS16080_DIN_AIN2,
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 0,
+ .address = ADIS16080_DIN_TEMP,
+ }
};
static const struct iio_info adis16080_info = {
- .attrs = &adis16080_attribute_group,
+ .read_raw = &adis16080_read_raw,
.driver_module = THIS_MODULE,
};
@@ -147,6 +156,8 @@ static int __devinit adis16080_probe(struct spi_device *spi)
mutex_init(&st->buf_lock);
indio_dev->name = spi->dev.driver->name;
+ indio_dev->channels = adis16080_channels;
+ indio_dev->num_channels = ARRAY_SIZE(adis16080_channels);
indio_dev->dev.parent = &spi->dev;
indio_dev->info = &adis16080_info;
indio_dev->modes = INDIO_DIRECT_MODE;
diff --git a/drivers/staging/iio/gyro/adis16130_core.c b/drivers/staging/iio/gyro/adis16130_core.c
index c80e908d8acf..a9f270e5eb96 100644
--- a/drivers/staging/iio/gyro/adis16130_core.c
+++ b/drivers/staging/iio/gyro/adis16130_core.c
@@ -14,11 +14,10 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
-#include "gyro.h"
-#include "../adc/adc.h"
#define ADIS16130_CON 0x0
#define ADIS16130_CON_RD (1 << 6)
@@ -41,140 +40,77 @@
/**
* struct adis16130_state - device instance specific data
* @us: actual spi_device to write data
- * @mode: 24 bits (1) or 16 bits (0)
* @buf_lock: mutex to protect tx and rx
* @buf: unified tx/rx buffer
**/
struct adis16130_state {
struct spi_device *us;
- u32 mode;
struct mutex buf_lock;
u8 buf[4] ____cacheline_aligned;
};
-static int adis16130_spi_write(struct device *dev, u8 reg_addr,
- u8 val)
+static int adis16130_spi_read(struct iio_dev *indio_dev, u8 reg_addr, u32 *val)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct adis16130_state *st = iio_priv(indio_dev);
-
- mutex_lock(&st->buf_lock);
- st->buf[0] = reg_addr;
- st->buf[1] = val;
-
- ret = spi_write(st->us, st->buf, 2);
- mutex_unlock(&st->buf_lock);
-
- return ret;
-}
-
-static int adis16130_spi_read(struct device *dev, u8 reg_addr,
- u32 *val)
-{
- int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16130_state *st = iio_priv(indio_dev);
+ struct spi_message msg;
+ struct spi_transfer xfer = {
+ .tx_buf = st->buf,
+ .rx_buf = st->buf,
+ .len = 4,
+ };
mutex_lock(&st->buf_lock);
st->buf[0] = ADIS16130_CON_RD | reg_addr;
- if (st->mode)
- ret = spi_read(st->us, st->buf, 4);
- else
- ret = spi_read(st->us, st->buf, 3);
-
- if (ret == 0) {
- if (st->mode)
- *val = (st->buf[1] << 16) |
- (st->buf[2] << 8) |
- st->buf[3];
- else
- *val = (st->buf[1] << 8) | st->buf[2];
- }
+ st->buf[1] = st->buf[2] = st->buf[3] = 0;
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+ ret = spi_sync(st->us, &msg);
+ ret = spi_read(st->us, st->buf, 4);
+
+ if (ret == 0)
+ *val = (st->buf[1] << 16) | (st->buf[2] << 8) | st->buf[3];
mutex_unlock(&st->buf_lock);
return ret;
}
-static ssize_t adis16130_val_read(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int adis16130_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2,
+ long mask)
{
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- u32 val;
- ssize_t ret;
+ int ret;
+ u32 temp;
/* Take the iio_dev status lock */
mutex_lock(&indio_dev->mlock);
- ret = adis16130_spi_read(dev, this_attr->address, &val);
+ ret = adis16130_spi_read(indio_dev, chan->address, &temp);
mutex_unlock(&indio_dev->mlock);
-
- if (ret == 0)
- return sprintf(buf, "%d\n", val);
- else
+ if (ret)
return ret;
+ *val = temp;
+ return IIO_VAL_INT;
}
-static ssize_t adis16130_bitsmode_read(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct adis16130_state *st = iio_priv(indio_dev);
-
- if (st->mode == 1)
- return sprintf(buf, "s24\n");
- else
- return sprintf(buf, "s16\n");
-}
-
-static ssize_t adis16130_bitsmode_write(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- int ret;
- u8 val;
-
- if (sysfs_streq(buf, "s16"))
- val = 0;
- else if (sysfs_streq(buf, "s24"))
- val = 1;
- else
- return -EINVAL;
-
- ret = adis16130_spi_write(dev, ADIS16130_MODE, val);
-
- return ret ? ret : len;
-}
-static IIO_DEVICE_ATTR(temp_raw, S_IRUGO, adis16130_val_read, NULL,
- ADIS16130_TEMPDATA);
-
-static IIO_DEV_ATTR_GYRO_Z(adis16130_val_read, ADIS16130_RATEDATA);
-
-static IIO_DEVICE_ATTR(gyro_z_type, S_IWUSR | S_IRUGO, adis16130_bitsmode_read,
- adis16130_bitsmode_write,
- ADIS16130_MODE);
-
-static IIO_CONST_ATTR(gyro_z_type_available, "s16 s24");
-
-static struct attribute *adis16130_attributes[] = {
- &iio_dev_attr_temp_raw.dev_attr.attr,
- &iio_dev_attr_gyro_z_raw.dev_attr.attr,
- &iio_dev_attr_gyro_z_type.dev_attr.attr,
- &iio_const_attr_gyro_z_type_available.dev_attr.attr,
- NULL
-};
-
-static const struct attribute_group adis16130_attribute_group = {
- .attrs = adis16130_attributes,
+static const struct iio_chan_spec adis16130_channels[] = {
+ {
+ .type = IIO_GYRO,
+ .modified = 1,
+ .channel2 = IIO_MOD_Z,
+ .address = ADIS16130_RATEDATA,
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 0,
+ .address = ADIS16130_TEMPDATA,
+ }
};
static const struct iio_info adis16130_info = {
- .attrs = &adis16130_attribute_group,
+ .read_raw = &adis16130_read_raw,
.driver_module = THIS_MODULE,
};
@@ -196,10 +132,11 @@ static int __devinit adis16130_probe(struct spi_device *spi)
st->us = spi;
mutex_init(&st->buf_lock);
indio_dev->name = spi->dev.driver->name;
+ indio_dev->channels = adis16130_channels;
+ indio_dev->num_channels = ARRAY_SIZE(adis16130_channels);
indio_dev->dev.parent = &spi->dev;
indio_dev->info = &adis16130_info;
indio_dev->modes = INDIO_DIRECT_MODE;
- st->mode = 1;
ret = iio_device_register(indio_dev);
if (ret)
diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c
index f2d43cfcc493..fcd7819a1246 100644
--- a/drivers/staging/iio/gyro/adis16260_core.c
+++ b/drivers/staging/iio/gyro/adis16260_core.c
@@ -17,12 +17,11 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
#include "../ring_generic.h"
-#include "../adc/adc.h"
-#include "gyro.h"
#include "adis16260.h"
diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c
index a4df8b32251e..10f8a666226b 100644
--- a/drivers/staging/iio/gyro/adis16260_ring.c
+++ b/drivers/staging/iio/gyro/adis16260_ring.c
@@ -1,20 +1,12 @@
#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/slab.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 "../trigger_consumer.h"
#include "adis16260.h"
/**
@@ -68,7 +60,7 @@ static int adis16260_read_ring_data(struct device *dev, u8 *rx)
static irqreturn_t adis16260_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
+ struct iio_dev *indio_dev = pf->indio_dev;
struct adis16260_state *st = iio_priv(indio_dev);
struct iio_ring_buffer *ring = indio_dev->ring;
int i = 0;
diff --git a/drivers/staging/iio/gyro/adis16260_trigger.c b/drivers/staging/iio/gyro/adis16260_trigger.c
index 01094d0e714a..2f2b2160f44d 100644
--- a/drivers/staging/iio/gyro/adis16260_trigger.c
+++ b/drivers/staging/iio/gyro/adis16260_trigger.c
@@ -1,14 +1,8 @@
#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 "adis16260.h"
@@ -24,6 +18,11 @@ static int adis16260_data_rdy_trigger_set_state(struct iio_trigger *trig,
return adis16260_set_irq(indio_dev, state);
}
+static const struct iio_trigger_ops adis16260_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &adis16260_data_rdy_trigger_set_state,
+};
+
int adis16260_probe_trigger(struct iio_dev *indio_dev)
{
int ret;
@@ -46,9 +45,8 @@ int adis16260_probe_trigger(struct iio_dev *indio_dev)
goto error_free_trig;
st->trig->dev.parent = &st->us->dev;
- st->trig->owner = THIS_MODULE;
+ st->trig->ops = &adis16260_trigger_ops;
st->trig->private_data = indio_dev;
- st->trig->set_trigger_state = &adis16260_data_rdy_trigger_set_state;
ret = iio_trigger_register(st->trig);
/* select default trigger */
diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c
index 7502a264770b..670b615839fb 100644
--- a/drivers/staging/iio/gyro/adxrs450_core.c
+++ b/drivers/staging/iio/gyro/adxrs450_core.c
@@ -17,11 +17,10 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
-#include "gyro.h"
-#include "../adc/adc.h"
#include "adxrs450.h"
@@ -32,26 +31,12 @@
* Second register's address is reg_address + 1.
* @val: somewhere to pass back the value read
**/
-static int adxrs450_spi_read_reg_16(struct device *dev,
- u8 reg_address,
- u16 *val)
+static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev,
+ u8 reg_address,
+ u16 *val)
{
- struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adxrs450_state *st = iio_priv(indio_dev);
int ret;
- struct spi_transfer xfers[] = {
- {
- .tx_buf = st->tx,
- .bits_per_word = 8,
- .len = 4,
- .cs_change = 1,
- }, {
- .rx_buf = st->rx,
- .bits_per_word = 8,
- .len = 4,
- },
- };
mutex_lock(&st->buf_lock);
st->tx[0] = ADXRS450_READ_DATA | (reg_address >> 7);
@@ -62,10 +47,13 @@ static int adxrs450_spi_read_reg_16(struct device *dev,
if (!(hweight32(be32_to_cpu(*(u32 *)st->tx)) & 1))
st->tx[3] |= ADXRS450_P;
- spi_message_init(&msg);
- spi_message_add_tail(&xfers[0], &msg);
- spi_message_add_tail(&xfers[1], &msg);
- ret = spi_sync(st->us, &msg);
+ ret = spi_write(st->us, st->tx, 4);
+ if (ret) {
+ dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n",
+ reg_address);
+ goto error_ret;
+ }
+ ret = spi_read(st->us, st->rx, 4);
if (ret) {
dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n",
reg_address);
@@ -86,20 +74,12 @@ error_ret:
* Second register's address is reg_address + 1.
* @val: value to be written.
**/
-static int adxrs450_spi_write_reg_16(struct device *dev,
- u8 reg_address,
- u16 val)
+static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev,
+ u8 reg_address,
+ u16 val)
{
- struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adxrs450_state *st = iio_priv(indio_dev);
int ret;
- struct spi_transfer xfers = {
- .tx_buf = st->tx,
- .rx_buf = st->rx,
- .bits_per_word = 8,
- .len = 4,
- };
mutex_lock(&st->buf_lock);
st->tx[0] = ADXRS450_WRITE_DATA | reg_address >> 7;
@@ -108,14 +88,12 @@ static int adxrs450_spi_write_reg_16(struct device *dev,
st->tx[3] = val << 1;
if (!(hweight32(be32_to_cpu(*(u32 *)st->tx)) & 1))
- st->tx[3] |= ADXRS450_P;
+ st->tx[3] |= ADXRS450_P;
- spi_message_init(&msg);
- spi_message_add_tail(&xfers, &msg);
- ret = spi_sync(st->us, &msg);
+ ret = spi_write(st->us, st->tx, 4);
if (ret)
dev_err(&st->us->dev, "problem while writing 16 bit register 0x%02x\n",
- reg_address);
+ reg_address);
msleep(1); /* enforce sequential transfer delay 0.1ms */
mutex_unlock(&st->buf_lock);
return ret;
@@ -126,24 +104,10 @@ static int adxrs450_spi_write_reg_16(struct device *dev,
* @dev: device associated with child of actual iio_dev
* @val: somewhere to pass back the value read
**/
-static int adxrs450_spi_sensor_data(struct device *dev, s16 *val)
+static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val)
{
- struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adxrs450_state *st = iio_priv(indio_dev);
int ret;
- struct spi_transfer xfers[] = {
- {
- .tx_buf = st->tx,
- .bits_per_word = 8,
- .len = 4,
- .cs_change = 1,
- }, {
- .rx_buf = st->rx,
- .bits_per_word = 8,
- .len = 4,
- },
- };
mutex_lock(&st->buf_lock);
st->tx[0] = ADXRS450_SENSOR_DATA;
@@ -151,10 +115,13 @@ static int adxrs450_spi_sensor_data(struct device *dev, s16 *val)
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);
+ ret = spi_write(st->us, st->tx, 4);
+ if (ret) {
+ dev_err(&st->us->dev, "Problem while reading sensor data\n");
+ goto error_ret;
+ }
+
+ ret = spi_read(st->us, st->rx, 4);
if (ret) {
dev_err(&st->us->dev, "Problem while reading sensor data\n");
goto error_ret;
@@ -206,73 +173,12 @@ error_ret:
return ret;
}
-static ssize_t adxrs450_read_temp(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int ret;
- u16 t;
- ret = adxrs450_spi_read_reg_16(dev,
- ADXRS450_TEMP1,
- &t);
- if (ret)
- return ret;
- return sprintf(buf, "%d\n", t >> 7);
-}
-
-static ssize_t adxrs450_read_quad(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int ret;
- s16 t;
- ret = adxrs450_spi_read_reg_16(dev,
- ADXRS450_QUAD1,
- &t);
- if (ret)
- return ret;
- return sprintf(buf, "%d\n", t);
-}
-
-static ssize_t adxrs450_write_dnc(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- int ret;
- long val;
-
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- goto error_ret;
- ret = adxrs450_spi_write_reg_16(dev,
- ADXRS450_DNC1,
- val & 0x3FF);
-error_ret:
- return ret ? ret : len;
-}
-
-static ssize_t adxrs450_read_sensor_data(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int ret;
- s16 t;
-
- ret = adxrs450_spi_sensor_data(dev, &t);
- if (ret)
- return ret;
-
- return sprintf(buf, "%d\n", t);
-}
-
/* Recommended Startup Sequence by spec */
static int adxrs450_initial_setup(struct iio_dev *indio_dev)
{
u32 t;
u16 data;
int ret;
- struct device *dev = &indio_dev->dev;
struct adxrs450_state *st = iio_priv(indio_dev);
msleep(ADXRS450_STARTUP_DELAY*2);
@@ -305,23 +211,23 @@ static int adxrs450_initial_setup(struct iio_dev *indio_dev)
return -EIO;
}
- ret = adxrs450_spi_read_reg_16(dev, ADXRS450_FAULT1, &data);
+ ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_FAULT1, &data);
if (ret)
return ret;
if (data & 0x0fff) {
dev_err(&st->us->dev, "The device is not in normal status!\n");
return -EINVAL;
}
- ret = adxrs450_spi_read_reg_16(dev, ADXRS450_PID1, &data);
+ ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_PID1, &data);
if (ret)
return ret;
dev_info(&st->us->dev, "The Part ID is 0x%x\n", data);
- ret = adxrs450_spi_read_reg_16(dev, ADXRS450_SNL, &data);
+ ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_SNL, &data);
if (ret)
return ret;
t = data;
- ret = adxrs450_spi_read_reg_16(dev, ADXRS450_SNH, &data);
+ ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_SNH, &data);
if (ret)
return ret;
t |= data << 16;
@@ -330,29 +236,91 @@ static int adxrs450_initial_setup(struct iio_dev *indio_dev)
return 0;
}
-static IIO_DEV_ATTR_GYRO_Z(adxrs450_read_sensor_data, 0);
-static IIO_DEV_ATTR_TEMP_RAW(adxrs450_read_temp);
-static IIO_DEV_ATTR_GYRO_Z_QUADRATURE_CORRECTION(adxrs450_read_quad, 0);
-static IIO_DEV_ATTR_GYRO_Z_CALIBBIAS(S_IWUSR,
- NULL, adxrs450_write_dnc, 0);
-static IIO_CONST_ATTR(name, "adxrs450");
-
-static struct attribute *adxrs450_attributes[] = {
- &iio_dev_attr_gyro_z_raw.dev_attr.attr,
- &iio_dev_attr_temp_raw.dev_attr.attr,
- &iio_dev_attr_gyro_z_quadrature_correction_raw.dev_attr.attr,
- &iio_dev_attr_gyro_z_calibbias.dev_attr.attr,
- &iio_const_attr_name.dev_attr.attr,
- NULL
-};
+static int adxrs450_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
+{
+ int ret;
+ switch (mask) {
+ case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ ret = adxrs450_spi_write_reg_16(indio_dev,
+ ADXRS450_DNC1,
+ val & 0x3FF);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
-static const struct attribute_group adxrs450_attribute_group = {
- .attrs = adxrs450_attributes,
+static int adxrs450_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long mask)
+{
+ int ret;
+ s16 t;
+ u16 ut;
+ switch (mask) {
+ case 0:
+ switch (chan->type) {
+ case IIO_GYRO:
+ ret = adxrs450_spi_sensor_data(indio_dev, &t);
+ if (ret)
+ break;
+ *val = t;
+ ret = IIO_VAL_INT;
+ break;
+ case IIO_TEMP:
+ ret = adxrs450_spi_read_reg_16(indio_dev,
+ ADXRS450_TEMP1, &ut);
+ if (ret)
+ break;
+ *val = ut;
+ ret = IIO_VAL_INT;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ break;
+ case (1 << IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE):
+ ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t);
+ if (ret)
+ break;
+ *val = t;
+ ret = IIO_VAL_INT;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static const struct iio_chan_spec adxrs450_channels[] = {
+ {
+ .type = IIO_GYRO,
+ .modified = 1,
+ .channel2 = IIO_MOD_Z,
+ .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE)
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 0,
+ }
};
static const struct iio_info adxrs450_info = {
- .attrs = &adxrs450_attribute_group,
.driver_module = THIS_MODULE,
+ .read_raw = &adxrs450_read_raw,
+ .write_raw = &adxrs450_write_raw,
};
static int __devinit adxrs450_probe(struct spi_device *spi)
@@ -376,6 +344,9 @@ static int __devinit adxrs450_probe(struct spi_device *spi)
indio_dev->dev.parent = &spi->dev;
indio_dev->info = &adxrs450_info;
indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = adxrs450_channels;
+ indio_dev->num_channels = ARRAY_SIZE(adxrs450_channels);
+ indio_dev->name = spi->dev.driver->name;
ret = iio_device_register(indio_dev);
if (ret)
diff --git a/drivers/staging/iio/gyro/gyro.h b/drivers/staging/iio/gyro/gyro.h
deleted file mode 100644
index b5495613407b..000000000000
--- a/drivers/staging/iio/gyro/gyro.h
+++ /dev/null
@@ -1,85 +0,0 @@
-
-#include "../sysfs.h"
-
-/* Gyroscope types of attribute */
-
-#define IIO_CONST_ATTR_GYRO_OFFSET(_string) \
- IIO_CONST_ATTR(gyro_offset, _string)
-
-#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_CONST_ATTR_GYRO_SCALE(_string) \
- IIO_CONST_ATTR(gyro_scale, _string)
-
-#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_X_SCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(gyro_x_scale, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_GYRO_Y_SCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(gyro_y_scale, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_GYRO_Z_SCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(gyro_z_scale, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_GYRO_CALIBBIAS(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(gyro_calibbias, S_IRUGO, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_GYRO_X_CALIBBIAS(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(gyro_x_calibbias, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_GYRO_Y_CALIBBIAS(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(gyro_y_calibbias, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_GYRO_Z_CALIBBIAS(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(gyro_z_calibbias, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_GYRO_CALIBSCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(gyro_calibscale, S_IRUGO, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_GYRO_X_CALIBSCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(gyro_x_calibscale, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_GYRO_Y_CALIBSCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(gyro_y_calibscale, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_GYRO_Z_CALIBSCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(gyro_z_calibscale, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_GYRO_Z_QUADRATURE_CORRECTION(_show, _addr) \
- IIO_DEVICE_ATTR(gyro_z_quadrature_correction_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_GYRO(_show, _addr) \
- IIO_DEVICE_ATTR(gyro_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_GYRO_X(_show, _addr) \
- IIO_DEVICE_ATTR(gyro_x_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_GYRO_Y(_show, _addr) \
- IIO_DEVICE_ATTR(gyro_y_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_GYRO_Z(_show, _addr) \
- IIO_DEVICE_ATTR(gyro_z_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_ANGL(_show, _addr) \
- IIO_DEVICE_ATTR(angl_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_ANGL_X(_show, _addr) \
- IIO_DEVICE_ATTR(angl_x_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_ANGL_Y(_show, _addr) \
- IIO_DEVICE_ATTR(angl_y_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_ANGL_Z(_show, _addr) \
- IIO_DEVICE_ATTR(angl_z_raw, S_IRUGO, _show, NULL, _addr)
diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h
index 7a6ce4d0fb7b..753f769736ef 100644
--- a/drivers/staging/iio/iio.h
+++ b/drivers/staging/iio/iio.h
@@ -1,3 +1,4 @@
+
/* The industrial I/O core
*
* Copyright (c) 2008 Jonathan Cameron
@@ -22,11 +23,6 @@
* Currently assumes nano seconds.
*/
-/* Event interface flags */
-#define IIO_BUSY_BIT_POS 1
-
-/* naughty temporary hack to match these against the event version
- - need to flattern these together */
enum iio_chan_type {
/* real channel types */
IIO_IN,
@@ -75,6 +71,8 @@ enum iio_chan_info_enum {
IIO_CHAN_INFO_PEAK_SEPARATE,
IIO_CHAN_INFO_PEAK_SCALE_SHARED,
IIO_CHAN_INFO_PEAK_SCALE_SEPARATE,
+ IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED,
+ IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE,
};
/**
@@ -121,26 +119,14 @@ struct iio_chan_spec {
u8 storagebits;
u8 shift;
} scan_type;
- const long info_mask;
- const long event_mask;
- const char *extend_name;
+ long info_mask;
+ long event_mask;
+ char *extend_name;
unsigned processed_val:1;
unsigned modified:1;
unsigned indexed:1;
};
-/* Meant for internal use only */
-void __iio_device_attr_deinit(struct device_attribute *dev_attr);
-int __iio_device_attr_init(struct device_attribute *dev_attr,
- const char *postfix,
- struct iio_chan_spec const *chan,
- ssize_t (*readfunc)(struct device *dev,
- struct device_attribute *attr,
- char *buf),
- ssize_t (*writefunc)(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len),
- bool generic);
+
#define IIO_ST(si, rb, sb, sh) \
{ .sign = si, .realbits = rb, .storagebits = sb, .shift = sh }
@@ -163,20 +149,6 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
{ .type = IIO_TIMESTAMP, .channel = -1, \
.scan_index = _si, .scan_type = IIO_ST('s', 64, 64, 0) }
-int __iio_add_chan_devattr(const char *postfix,
- const char *group,
- struct iio_chan_spec const *chan,
- ssize_t (*func)(struct device *dev,
- struct device_attribute *attr,
- char *buf),
- ssize_t (*writefunc)(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len),
- int mask,
- bool generic,
- struct device *dev,
- struct list_head *attr_list);
/**
* iio_get_time_ns() - utility function to get a time stamp for events etc
**/
@@ -276,7 +248,6 @@ struct iio_info {
/**
* struct iio_dev - industrial I/O device
* @id: [INTERN] used to identify device internally
- * @dev_data: [DRIVER] device specific data
* @modes: [DRIVER] operating modes supported by device
* @currentmode: [DRIVER] current operating mode
* @dev: [DRIVER] device structure, should be assigned a parent
@@ -296,7 +267,7 @@ struct iio_info {
**/
struct iio_dev {
int id;
- void *dev_data;
+
int modes;
int currentmode;
struct device dev;
@@ -342,13 +313,6 @@ int iio_push_event(struct iio_dev *dev_info,
int ev_code,
s64 timestamp);
-/* Used to distinguish between bipolar and unipolar scan elemenents.
- * Whilst this may seem obvious, we may well want to change the representation
- * in the future!*/
-#define IIO_SIGNED(a) -(a)
-#define IIO_UNSIGNED(a) (a)
-
-extern dev_t iio_devt;
extern struct bus_type iio_bus_type;
/**
@@ -361,25 +325,6 @@ static inline void iio_put_device(struct iio_dev *dev)
put_device(&dev->dev);
};
-/**
- * to_iio_dev() - get iio_dev for which we have the struct device
- * @d: the struct device
- **/
-static inline struct iio_dev *to_iio_dev(struct device *d)
-{
- return container_of(d, struct iio_dev, dev);
-};
-
-/**
- * iio_dev_get_devdata() - helper function gets device specific data
- * @d: the iio_dev associated with the device
- **/
-static inline void *iio_dev_get_devdata(struct iio_dev *d)
-{
- return d->dev_data;
-}
-
-
/* Can we make this smaller? */
#define IIO_ALIGN L1_CACHE_BYTES
/**
@@ -406,22 +351,6 @@ static inline struct iio_dev *iio_priv_to_dev(void *priv)
void iio_free_device(struct iio_dev *dev);
/**
- * iio_put() - internal module reference count reduce
- **/
-void iio_put(void);
-
-/**
- * iio_get() - internal module reference count increase
- **/
-void iio_get(void);
-
-/**
- * iio_device_get_chrdev_minor() - get an unused minor number
- **/
-int iio_device_get_chrdev_minor(void);
-void iio_device_free_chrdev_minor(int val);
-
-/**
* iio_ring_enabled() - helper function to test if any form of ring is enabled
* @dev_info: IIO device info structure for device
**/
@@ -432,8 +361,4 @@ static inline bool iio_ring_enabled(struct iio_dev *dev_info)
| INDIO_RING_HARDWARE_BUFFER);
};
-struct ida;
-
-int iio_get_new_ida_val(struct ida *this_ida);
-void iio_free_ida_val(struct ida *this_ida, int id);
#endif /* _INDUSTRIAL_IO_H_ */
diff --git a/drivers/staging/iio/iio_core.h b/drivers/staging/iio/iio_core.h
new file mode 100644
index 000000000000..00e894d50e74
--- /dev/null
+++ b/drivers/staging/iio/iio_core.h
@@ -0,0 +1,48 @@
+/* The industrial I/O core function defs.
+ *
+ * Copyright (c) 2008 Jonathan Cameron
+ *
+ * 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.
+ *
+ * These definitions are meant for use only within the IIO core, not indvidual
+ * drivers.
+ */
+
+/**
+ * iio_device_get_chrdev_minor() - get an unused minor number
+ **/
+int iio_device_get_chrdev_minor(void);
+void iio_device_free_chrdev_minor(int val);
+
+
+/**
+ * iio_put() - internal module reference count reduce
+ **/
+void iio_put(void);
+
+/**
+ * iio_get() - internal module reference count increase
+ **/
+void iio_get(void);
+
+extern dev_t iio_devt;
+
+int __iio_add_chan_devattr(const char *postfix,
+ const char *group,
+ struct iio_chan_spec const *chan,
+ ssize_t (*func)(struct device *dev,
+ struct device_attribute *attr,
+ char *buf),
+ ssize_t (*writefunc)(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len),
+ int mask,
+ bool generic,
+ struct device *dev,
+ struct list_head *attr_list);
+
+/* Event interface flags */
+#define IIO_BUSY_BIT_POS 1
diff --git a/drivers/staging/iio/iio_core_trigger.h b/drivers/staging/iio/iio_core_trigger.h
new file mode 100644
index 000000000000..3e5195a82bca
--- /dev/null
+++ b/drivers/staging/iio/iio_core_trigger.h
@@ -0,0 +1,46 @@
+
+/* The industrial I/O core, trigger consumer handling functions
+ *
+ * Copyright (c) 2008 Jonathan Cameron
+ *
+ * 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.
+ */
+
+#ifdef CONFIG_IIO_TRIGGER
+/**
+ * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers
+ * @dev_info: iio_dev associated with the device that will consume the trigger
+ **/
+int iio_device_register_trigger_consumer(struct iio_dev *dev_info);
+
+/**
+ * iio_device_unregister_trigger_consumer() - reverse the registration process
+ * @dev_info: iio_dev associated with the device that consumed the trigger
+ **/
+void iio_device_unregister_trigger_consumer(struct iio_dev *dev_info);
+
+#else
+
+/**
+ * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers
+ * @dev_info: iio_dev associated with the device that will consume the trigger
+ **/
+static int iio_device_register_trigger_consumer(struct iio_dev *dev_info)
+{
+ return 0;
+};
+
+/**
+ * iio_device_unregister_trigger_consumer() - reverse the registration process
+ * @dev_info: iio_dev associated with the device that consumed the trigger
+ **/
+static void iio_device_unregister_trigger_consumer(struct iio_dev *dev_info)
+{
+};
+
+#endif /* CONFIG_TRIGGER_CONSUMER */
+
+
+
diff --git a/drivers/staging/iio/impedance-analyzer/Kconfig b/drivers/staging/iio/impedance-analyzer/Kconfig
new file mode 100644
index 000000000000..9e91a9bc8bfe
--- /dev/null
+++ b/drivers/staging/iio/impedance-analyzer/Kconfig
@@ -0,0 +1,16 @@
+#
+# Impedance Converter, Network Analyzer drivers
+#
+comment "Network Analyzer, Impedance Converters"
+
+config AD5933
+ tristate "Analog Devices AD5933, AD5934 driver"
+ depends on I2C
+ select IIO_RING_BUFFER
+ select IIO_SW_RING
+ help
+ Say yes here to build support for Analog Devices Impedance Converter,
+ Network Analyzer, AD5933/4, provides direct access via sysfs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5933.
diff --git a/drivers/staging/iio/impedance-analyzer/Makefile b/drivers/staging/iio/impedance-analyzer/Makefile
new file mode 100644
index 000000000000..7604d786583e
--- /dev/null
+++ b/drivers/staging/iio/impedance-analyzer/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for Impedance Converter, Network Analyzer drivers
+#
+
+obj-$(CONFIG_AD5933) += ad5933.o
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
new file mode 100644
index 000000000000..acc0e69cb588
--- /dev/null
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -0,0 +1,818 @@
+/*
+ * AD5933 AD5934 Impedance Converter, Network Analyzer
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/sysfs.h>
+#include <linux/i2c.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <asm/div64.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "../ring_generic.h"
+#include "../ring_sw.h"
+
+#include "ad5933.h"
+
+/* AD5933/AD5934 Registers */
+#define AD5933_REG_CONTROL_HB 0x80 /* R/W, 2 bytes */
+#define AD5933_REG_CONTROL_LB 0x81 /* R/W, 2 bytes */
+#define AD5933_REG_FREQ_START 0x82 /* R/W, 3 bytes */
+#define AD5933_REG_FREQ_INC 0x85 /* R/W, 3 bytes */
+#define AD5933_REG_INC_NUM 0x88 /* R/W, 2 bytes, 9 bit */
+#define AD5933_REG_SETTLING_CYCLES 0x8A /* R/W, 2 bytes */
+#define AD5933_REG_STATUS 0x8F /* R, 1 byte */
+#define AD5933_REG_TEMP_DATA 0x92 /* R, 2 bytes*/
+#define AD5933_REG_REAL_DATA 0x94 /* R, 2 bytes*/
+#define AD5933_REG_IMAG_DATA 0x96 /* R, 2 bytes*/
+
+/* AD5933_REG_CONTROL_HB Bits */
+#define AD5933_CTRL_INIT_START_FREQ (0x1 << 4)
+#define AD5933_CTRL_START_SWEEP (0x2 << 4)
+#define AD5933_CTRL_INC_FREQ (0x3 << 4)
+#define AD5933_CTRL_REPEAT_FREQ (0x4 << 4)
+#define AD5933_CTRL_MEASURE_TEMP (0x9 << 4)
+#define AD5933_CTRL_POWER_DOWN (0xA << 4)
+#define AD5933_CTRL_STANDBY (0xB << 4)
+
+#define AD5933_CTRL_RANGE_2000mVpp (0x0 << 1)
+#define AD5933_CTRL_RANGE_200mVpp (0x1 << 1)
+#define AD5933_CTRL_RANGE_400mVpp (0x2 << 1)
+#define AD5933_CTRL_RANGE_1000mVpp (0x3 << 1)
+#define AD5933_CTRL_RANGE(x) ((x) << 1)
+
+#define AD5933_CTRL_PGA_GAIN_1 (0x1 << 0)
+#define AD5933_CTRL_PGA_GAIN_5 (0x0 << 0)
+
+/* AD5933_REG_CONTROL_LB Bits */
+#define AD5933_CTRL_RESET (0x1 << 4)
+#define AD5933_CTRL_INT_SYSCLK (0x0 << 3)
+#define AD5933_CTRL_EXT_SYSCLK (0x1 << 3)
+
+/* AD5933_REG_STATUS Bits */
+#define AD5933_STAT_TEMP_VALID (0x1 << 0)
+#define AD5933_STAT_DATA_VALID (0x1 << 1)
+#define AD5933_STAT_SWEEP_DONE (0x1 << 2)
+
+/* I2C Block Commands */
+#define AD5933_I2C_BLOCK_WRITE 0xA0
+#define AD5933_I2C_BLOCK_READ 0xA1
+#define AD5933_I2C_ADDR_POINTER 0xB0
+
+/* Device Specs */
+#define AD5933_INT_OSC_FREQ_Hz 16776000
+#define AD5933_MAX_OUTPUT_FREQ_Hz 100000
+#define AD5933_MAX_RETRIES 100
+
+#define AD5933_OUT_RANGE 1
+#define AD5933_OUT_RANGE_AVAIL 2
+#define AD5933_OUT_SETTLING_CYCLES 3
+#define AD5933_IN_PGA_GAIN 4
+#define AD5933_IN_PGA_GAIN_AVAIL 5
+#define AD5933_FREQ_POINTS 6
+
+#define AD5933_POLL_TIME_ms 10
+#define AD5933_INIT_EXCITATION_TIME_ms 100
+
+struct ad5933_state {
+ struct i2c_client *client;
+ struct regulator *reg;
+ struct ad5933_platform_data *pdata;
+ struct delayed_work work;
+ unsigned long mclk_hz;
+ unsigned char ctrl_hb;
+ unsigned char ctrl_lb;
+ unsigned range_avail[4];
+ unsigned short vref_mv;
+ unsigned short settling_cycles;
+ unsigned short freq_points;
+ unsigned freq_start;
+ unsigned freq_inc;
+ unsigned state;
+ unsigned poll_time_jiffies;
+};
+
+static struct ad5933_platform_data ad5933_default_pdata = {
+ .vref_mv = 3300,
+};
+
+static struct iio_chan_spec ad5933_channels[] = {
+ IIO_CHAN(IIO_TEMP, 0, 1, 1, NULL, 0, 0, 0,
+ 0, AD5933_REG_TEMP_DATA, IIO_ST('s', 14, 16, 0), 0),
+ /* Ring Channels */
+ IIO_CHAN(IIO_IN, 0, 1, 0, "real_raw", 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ AD5933_REG_REAL_DATA, 0, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, "imag_raw", 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ AD5933_REG_IMAG_DATA, 1, IIO_ST('s', 16, 16, 0), 0),
+};
+
+static int ad5933_i2c_write(struct i2c_client *client,
+ u8 reg, u8 len, u8 *data)
+{
+ int ret;
+
+ while (len--) {
+ ret = i2c_smbus_write_byte_data(client, reg++, *data++);
+ if (ret < 0) {
+ dev_err(&client->dev, "I2C write error\n");
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static int ad5933_i2c_read(struct i2c_client *client,
+ u8 reg, u8 len, u8 *data)
+{
+ int ret;
+
+ while (len--) {
+ ret = i2c_smbus_read_byte_data(client, reg++);
+ if (ret < 0) {
+ dev_err(&client->dev, "I2C read error\n");
+ return ret;
+ }
+ *data++ = ret;
+ }
+ return 0;
+}
+
+static int ad5933_cmd(struct ad5933_state *st, unsigned char cmd)
+{
+ unsigned char dat = st->ctrl_hb | cmd;
+
+ return ad5933_i2c_write(st->client,
+ AD5933_REG_CONTROL_HB, 1, &dat);
+}
+
+static int ad5933_reset(struct ad5933_state *st)
+{
+ unsigned char dat = st->ctrl_lb | AD5933_CTRL_RESET;
+ return ad5933_i2c_write(st->client,
+ AD5933_REG_CONTROL_LB, 1, &dat);
+}
+
+static int ad5933_wait_busy(struct ad5933_state *st, unsigned char event)
+{
+ unsigned char val, timeout = AD5933_MAX_RETRIES;
+ int ret;
+
+ while (timeout--) {
+ ret = ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &val);
+ if (ret < 0)
+ return ret;
+ if (val & event)
+ return val;
+ cpu_relax();
+ mdelay(1);
+ }
+
+ return -EAGAIN;
+}
+
+static int ad5933_set_freq(struct ad5933_state *st,
+ unsigned reg, unsigned long freq)
+{
+ unsigned long long freqreg;
+ union {
+ u32 d32;
+ u8 d8[4];
+ } dat;
+
+ freqreg = (u64) freq * (u64) (1 << 27);
+ do_div(freqreg, st->mclk_hz / 4);
+
+ switch (reg) {
+ case AD5933_REG_FREQ_START:
+ st->freq_start = freq;
+ break;
+ case AD5933_REG_FREQ_INC:
+ st->freq_inc = freq;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ dat.d32 = cpu_to_be32(freqreg);
+ return ad5933_i2c_write(st->client, reg, 3, &dat.d8[1]);
+}
+
+static int ad5933_setup(struct ad5933_state *st)
+{
+ unsigned short dat;
+ int ret;
+
+ ret = ad5933_reset(st);
+ if (ret < 0)
+ return ret;
+
+ ret = ad5933_set_freq(st, AD5933_REG_FREQ_START, 10000);
+ if (ret < 0)
+ return ret;
+
+ ret = ad5933_set_freq(st, AD5933_REG_FREQ_INC, 200);
+ if (ret < 0)
+ return ret;
+
+ st->settling_cycles = 10;
+ dat = cpu_to_be16(st->settling_cycles);
+
+ ret = ad5933_i2c_write(st->client,
+ AD5933_REG_SETTLING_CYCLES, 2, (u8 *)&dat);
+ if (ret < 0)
+ return ret;
+
+ st->freq_points = 100;
+ dat = cpu_to_be16(st->freq_points);
+
+ return ad5933_i2c_write(st->client, AD5933_REG_INC_NUM, 2, (u8 *)&dat);
+}
+
+static void ad5933_calc_out_ranges(struct ad5933_state *st)
+{
+ int i;
+ unsigned normalized_3v3[4] = {1980, 198, 383, 970};
+
+ for (i = 0; i < 4; i++)
+ st->range_avail[i] = normalized_3v3[i] * st->vref_mv / 3300;
+
+}
+
+/*
+ * handles: AD5933_REG_FREQ_START and AD5933_REG_FREQ_INC
+ */
+
+static ssize_t ad5933_show_frequency(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct ad5933_state *st = iio_priv(dev_info);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ int ret;
+ unsigned long long freqreg;
+ union {
+ u32 d32;
+ u8 d8[4];
+ } dat;
+
+ mutex_lock(&dev_info->mlock);
+ ret = ad5933_i2c_read(st->client, this_attr->address, 3, &dat.d8[1]);
+ mutex_unlock(&dev_info->mlock);
+ if (ret < 0)
+ return ret;
+
+ freqreg = be32_to_cpu(dat.d32) & 0xFFFFFF;
+
+ freqreg = (u64) freqreg * (u64) (st->mclk_hz / 4);
+ do_div(freqreg, 1 << 27);
+
+ return sprintf(buf, "%d\n", (int) freqreg);
+}
+
+static ssize_t ad5933_store_frequency(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct ad5933_state *st = iio_priv(dev_info);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ long val;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ if (val > AD5933_MAX_OUTPUT_FREQ_Hz)
+ return -EINVAL;
+
+ mutex_lock(&dev_info->mlock);
+ ret = ad5933_set_freq(st, this_attr->address, val);
+ mutex_unlock(&dev_info->mlock);
+
+ return ret ? ret : len;
+}
+
+static IIO_DEVICE_ATTR(out0_freq_start, S_IRUGO | S_IWUSR,
+ ad5933_show_frequency,
+ ad5933_store_frequency,
+ AD5933_REG_FREQ_START);
+
+static IIO_DEVICE_ATTR(out0_freq_increment, S_IRUGO | S_IWUSR,
+ ad5933_show_frequency,
+ ad5933_store_frequency,
+ AD5933_REG_FREQ_INC);
+
+static ssize_t ad5933_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct ad5933_state *st = iio_priv(dev_info);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ int ret = 0, len = 0;
+
+ mutex_lock(&dev_info->mlock);
+ switch (this_attr->address) {
+ case AD5933_OUT_RANGE:
+ len = sprintf(buf, "%d\n",
+ st->range_avail[(st->ctrl_hb >> 1) & 0x3]);
+ break;
+ case AD5933_OUT_RANGE_AVAIL:
+ len = sprintf(buf, "%d %d %d %d\n", st->range_avail[0],
+ st->range_avail[3], st->range_avail[2],
+ st->range_avail[1]);
+ break;
+ case AD5933_OUT_SETTLING_CYCLES:
+ len = sprintf(buf, "%d\n", st->settling_cycles);
+ break;
+ case AD5933_IN_PGA_GAIN:
+ len = sprintf(buf, "%s\n",
+ (st->ctrl_hb & AD5933_CTRL_PGA_GAIN_1) ?
+ "1" : "0.2");
+ break;
+ case AD5933_IN_PGA_GAIN_AVAIL:
+ len = sprintf(buf, "1 0.2\n");
+ break;
+ case AD5933_FREQ_POINTS:
+ len = sprintf(buf, "%d\n", st->freq_points);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ mutex_unlock(&dev_info->mlock);
+ return ret ? ret : len;
+}
+
+static ssize_t ad5933_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct ad5933_state *st = iio_priv(dev_info);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ long val;
+ int i, ret = 0;
+ unsigned short dat;
+
+ if (this_attr->address != AD5933_IN_PGA_GAIN) {
+ ret = strict_strtol(buf, 10, &val);
+ if (ret)
+ return ret;
+ }
+
+ mutex_lock(&dev_info->mlock);
+ switch (this_attr->address) {
+ case AD5933_OUT_RANGE:
+ for (i = 0; i < 4; i++)
+ if (val == st->range_avail[i]) {
+ st->ctrl_hb &= ~AD5933_CTRL_RANGE(0x3);
+ st->ctrl_hb |= AD5933_CTRL_RANGE(i);
+ ret = ad5933_cmd(st, 0);
+ break;
+ }
+ ret = -EINVAL;
+ break;
+ case AD5933_IN_PGA_GAIN:
+ if (sysfs_streq(buf, "1")) {
+ st->ctrl_hb |= AD5933_CTRL_PGA_GAIN_1;
+ } else if (sysfs_streq(buf, "0.2")) {
+ st->ctrl_hb &= ~AD5933_CTRL_PGA_GAIN_1;
+ } else {
+ ret = -EINVAL;
+ break;
+ }
+ ret = ad5933_cmd(st, 0);
+ break;
+ case AD5933_OUT_SETTLING_CYCLES:
+ val = clamp(val, 0L, 0x7FFL);
+ st->settling_cycles = val;
+
+ /* 2x, 4x handling, see datasheet */
+ if (val > 511)
+ val = (val >> 1) | (1 << 9);
+ else if (val > 1022)
+ val = (val >> 2) | (3 << 9);
+
+ dat = cpu_to_be16(val);
+ ret = ad5933_i2c_write(st->client,
+ AD5933_REG_SETTLING_CYCLES, 2, (u8 *)&dat);
+ break;
+ case AD5933_FREQ_POINTS:
+ val = clamp(val, 0L, 511L);
+ st->freq_points = val;
+
+ dat = cpu_to_be16(val);
+ ret = ad5933_i2c_write(st->client, AD5933_REG_INC_NUM, 2,
+ (u8 *)&dat);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ mutex_unlock(&dev_info->mlock);
+ return ret ? ret : len;
+}
+
+static IIO_DEVICE_ATTR(out0_scale, S_IRUGO | S_IWUSR,
+ ad5933_show,
+ ad5933_store,
+ AD5933_OUT_RANGE);
+
+static IIO_DEVICE_ATTR(out0_scale_available, S_IRUGO,
+ ad5933_show,
+ NULL,
+ AD5933_OUT_RANGE_AVAIL);
+
+static IIO_DEVICE_ATTR(in0_scale, S_IRUGO | S_IWUSR,
+ ad5933_show,
+ ad5933_store,
+ AD5933_IN_PGA_GAIN);
+
+static IIO_DEVICE_ATTR(in0_scale_available, S_IRUGO,
+ ad5933_show,
+ NULL,
+ AD5933_IN_PGA_GAIN_AVAIL);
+
+static IIO_DEVICE_ATTR(out0_freq_points, S_IRUGO | S_IWUSR,
+ ad5933_show,
+ ad5933_store,
+ AD5933_FREQ_POINTS);
+
+static IIO_DEVICE_ATTR(out0_settling_cycles, S_IRUGO | S_IWUSR,
+ ad5933_show,
+ ad5933_store,
+ AD5933_OUT_SETTLING_CYCLES);
+
+/* note:
+ * ideally we would handle the scale attributes via the iio_info
+ * (read|write)_raw methods, however this part is a untypical since we
+ * don't create dedicated sysfs channel attributes for out0 and in0.
+ */
+static struct attribute *ad5933_attributes[] = {
+ &iio_dev_attr_out0_scale.dev_attr.attr,
+ &iio_dev_attr_out0_scale_available.dev_attr.attr,
+ &iio_dev_attr_out0_freq_start.dev_attr.attr,
+ &iio_dev_attr_out0_freq_increment.dev_attr.attr,
+ &iio_dev_attr_out0_freq_points.dev_attr.attr,
+ &iio_dev_attr_out0_settling_cycles.dev_attr.attr,
+ &iio_dev_attr_in0_scale.dev_attr.attr,
+ &iio_dev_attr_in0_scale_available.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group ad5933_attribute_group = {
+ .attrs = ad5933_attributes,
+};
+
+static int ad5933_read_raw(struct iio_dev *dev_info,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
+{
+ struct ad5933_state *st = iio_priv(dev_info);
+ unsigned short dat;
+ int ret = -EINVAL;
+
+ mutex_lock(&dev_info->mlock);
+ switch (m) {
+ case 0:
+ if (iio_ring_enabled(dev_info)) {
+ ret = -EBUSY;
+ goto out;
+ }
+ ret = ad5933_cmd(st, AD5933_CTRL_MEASURE_TEMP);
+ if (ret < 0)
+ goto out;
+ ret = ad5933_wait_busy(st, AD5933_STAT_TEMP_VALID);
+ if (ret < 0)
+ goto out;
+
+ ret = ad5933_i2c_read(st->client,
+ AD5933_REG_TEMP_DATA, 2,
+ (u8 *)&dat);
+ if (ret < 0)
+ goto out;
+ mutex_unlock(&dev_info->mlock);
+ ret = be16_to_cpu(dat);
+ /* Temp in Milli degrees Celsius */
+ if (ret < 8192)
+ *val = ret * 1000 / 32;
+ else
+ *val = (ret - 16384) * 1000 / 32;
+
+ return IIO_VAL_INT;
+ }
+
+out:
+ mutex_unlock(&dev_info->mlock);
+ return ret;
+}
+
+static const struct iio_info ad5933_info = {
+ .read_raw = &ad5933_read_raw,
+ .attrs = &ad5933_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
+static int ad5933_ring_preenable(struct iio_dev *indio_dev)
+{
+ struct ad5933_state *st = iio_priv(indio_dev);
+ struct iio_ring_buffer *ring = indio_dev->ring;
+ size_t d_size;
+ int ret;
+
+ if (!ring->scan_count)
+ return -EINVAL;
+
+ d_size = ring->scan_count *
+ ad5933_channels[1].scan_type.storagebits / 8;
+
+ if (indio_dev->ring->access->set_bytes_per_datum)
+ indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring,
+ d_size);
+
+ ret = ad5933_reset(st);
+ if (ret < 0)
+ return ret;
+
+ ret = ad5933_cmd(st, AD5933_CTRL_STANDBY);
+ if (ret < 0)
+ return ret;
+
+ ret = ad5933_cmd(st, AD5933_CTRL_INIT_START_FREQ);
+ if (ret < 0)
+ return ret;
+
+ st->state = AD5933_CTRL_INIT_START_FREQ;
+
+ return 0;
+}
+
+static int ad5933_ring_postenable(struct iio_dev *indio_dev)
+{
+ struct ad5933_state *st = iio_priv(indio_dev);
+
+ /* AD5933_CTRL_INIT_START_FREQ:
+ * High Q complex circuits require a long time to reach steady state.
+ * To facilitate the measurement of such impedances, this mode allows
+ * the user full control of the settling time requirement before
+ * entering start frequency sweep mode where the impedance measurement
+ * takes place. In this mode the impedance is excited with the
+ * programmed start frequency (ad5933_ring_preenable),
+ * but no measurement takes place.
+ */
+
+ schedule_delayed_work(&st->work,
+ msecs_to_jiffies(AD5933_INIT_EXCITATION_TIME_ms));
+ return 0;
+}
+
+static int ad5933_ring_postdisable(struct iio_dev *indio_dev)
+{
+ struct ad5933_state *st = iio_priv(indio_dev);
+
+ cancel_delayed_work_sync(&st->work);
+ return ad5933_cmd(st, AD5933_CTRL_POWER_DOWN);
+}
+
+static const struct iio_ring_setup_ops ad5933_ring_setup_ops = {
+ .preenable = &ad5933_ring_preenable,
+ .postenable = &ad5933_ring_postenable,
+ .postdisable = &ad5933_ring_postdisable,
+};
+
+static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev)
+{
+ indio_dev->ring = iio_sw_rb_allocate(indio_dev);
+ if (!indio_dev->ring)
+ return -ENOMEM;
+
+ /* Effectively select the ring buffer implementation */
+ indio_dev->ring->access = &ring_sw_access_funcs;
+
+ /* Ring buffer functions - here trigger setup related */
+ indio_dev->ring->setup_ops = &ad5933_ring_setup_ops;
+
+ indio_dev->modes |= INDIO_RING_HARDWARE_BUFFER;
+
+ return 0;
+}
+
+static void ad5933_work(struct work_struct *work)
+{
+ struct ad5933_state *st = container_of(work,
+ struct ad5933_state, work.work);
+ struct iio_dev *indio_dev = i2c_get_clientdata(st->client);
+ struct iio_ring_buffer *ring = indio_dev->ring;
+ signed short buf[2];
+ unsigned char status;
+
+ mutex_lock(&indio_dev->mlock);
+ if (st->state == AD5933_CTRL_INIT_START_FREQ) {
+ /* start sweep */
+ ad5933_cmd(st, AD5933_CTRL_START_SWEEP);
+ st->state = AD5933_CTRL_START_SWEEP;
+ schedule_delayed_work(&st->work, st->poll_time_jiffies);
+ mutex_unlock(&indio_dev->mlock);
+ return;
+ }
+
+ ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &status);
+
+ if (status & AD5933_STAT_DATA_VALID) {
+ ad5933_i2c_read(st->client,
+ (ring->scan_mask & (1 << 0)) ?
+ AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA,
+ ring->scan_count * 2, (u8 *)buf);
+
+ if (ring->scan_count == 2) {
+ buf[0] = be16_to_cpu(buf[0]);
+ buf[1] = be16_to_cpu(buf[1]);
+ } else {
+ buf[0] = be16_to_cpu(buf[0]);
+ }
+ /* save datum to the ring */
+ ring->access->store_to(ring, (u8 *)buf, iio_get_time_ns());
+ } else {
+ /* no data available - try again later */
+ schedule_delayed_work(&st->work, st->poll_time_jiffies);
+ mutex_unlock(&indio_dev->mlock);
+ return;
+ }
+
+ if (status & AD5933_STAT_SWEEP_DONE) {
+ /* last sample received - power down do nothing until
+ * the ring enable is toggled */
+ ad5933_cmd(st, AD5933_CTRL_POWER_DOWN);
+ } else {
+ /* we just received a valid datum, move on to the next */
+ ad5933_cmd(st, AD5933_CTRL_INC_FREQ);
+ schedule_delayed_work(&st->work, st->poll_time_jiffies);
+ }
+
+ mutex_unlock(&indio_dev->mlock);
+}
+
+static int __devinit ad5933_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int ret, regdone = 0, voltage_uv = 0;
+ struct ad5933_platform_data *pdata = client->dev.platform_data;
+ struct ad5933_state *st;
+ struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ st->client = client;
+
+ if (!pdata)
+ st->pdata = &ad5933_default_pdata;
+ else
+ st->pdata = pdata;
+
+ st->reg = regulator_get(&client->dev, "vcc");
+ if (!IS_ERR(st->reg)) {
+ ret = regulator_enable(st->reg);
+ if (ret)
+ goto error_put_reg;
+ voltage_uv = regulator_get_voltage(st->reg);
+ }
+
+ if (voltage_uv)
+ st->vref_mv = voltage_uv / 1000;
+ else
+ st->vref_mv = st->pdata->vref_mv;
+
+ if (st->pdata->ext_clk_Hz) {
+ st->mclk_hz = st->pdata->ext_clk_Hz;
+ st->ctrl_lb = AD5933_CTRL_EXT_SYSCLK;
+ } else {
+ st->mclk_hz = AD5933_INT_OSC_FREQ_Hz;
+ st->ctrl_lb = AD5933_CTRL_INT_SYSCLK;
+ }
+
+ ad5933_calc_out_ranges(st);
+ INIT_DELAYED_WORK(&st->work, ad5933_work);
+ st->poll_time_jiffies = msecs_to_jiffies(AD5933_POLL_TIME_ms);
+
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->info = &ad5933_info;
+ indio_dev->name = id->name;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = ad5933_channels;
+ indio_dev->num_channels = 1; /* only register temp0_input */
+
+ ret = ad5933_register_ring_funcs_and_init(indio_dev);
+ if (ret)
+ goto error_disable_reg;
+
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto error_unreg_ring;
+ regdone = 1;
+
+ /* skip temp0_input, register in0_(real|imag)_raw */
+ ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
+ &ad5933_channels[1],
+ 2);
+ if (ret)
+ goto error_unreg_ring;
+
+ /* enable both REAL and IMAG channels by default */
+ iio_scan_mask_set(indio_dev->ring, 0);
+ iio_scan_mask_set(indio_dev->ring, 1);
+
+ ret = ad5933_setup(st);
+ if (ret)
+ goto error_uninitialize_ring;
+
+ return 0;
+
+error_uninitialize_ring:
+ iio_ring_buffer_unregister(indio_dev->ring);
+error_unreg_ring:
+ iio_sw_rb_free(indio_dev->ring);
+error_disable_reg:
+ if (!IS_ERR(st->reg))
+ regulator_disable(st->reg);
+error_put_reg:
+ if (!IS_ERR(st->reg))
+ regulator_put(st->reg);
+
+ if (regdone)
+ iio_device_unregister(indio_dev);
+ else
+ iio_free_device(indio_dev);
+
+ return ret;
+}
+
+static __devexit int ad5933_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct ad5933_state *st = iio_priv(indio_dev);
+
+ iio_ring_buffer_unregister(indio_dev->ring);
+ iio_sw_rb_free(indio_dev->ring);
+ if (!IS_ERR(st->reg)) {
+ regulator_disable(st->reg);
+ regulator_put(st->reg);
+ }
+ iio_device_unregister(indio_dev);
+
+ return 0;
+}
+
+static const struct i2c_device_id ad5933_id[] = {
+ { "ad5933", 0 },
+ { "ad5934", 0 },
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, ad5933_id);
+
+static struct i2c_driver ad5933_driver = {
+ .driver = {
+ .name = "ad5933",
+ },
+ .probe = ad5933_probe,
+ .remove = __devexit_p(ad5933_remove),
+ .id_table = ad5933_id,
+};
+
+static __init int ad5933_init(void)
+{
+ return i2c_add_driver(&ad5933_driver);
+}
+module_init(ad5933_init);
+
+static __exit void ad5933_exit(void)
+{
+ i2c_del_driver(&ad5933_driver);
+}
+module_exit(ad5933_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD5933 Impedance Conv. Network Analyzer");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.h b/drivers/staging/iio/impedance-analyzer/ad5933.h
new file mode 100644
index 000000000000..b140e42d67cf
--- /dev/null
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.h
@@ -0,0 +1,28 @@
+/*
+ * AD5933 AD5934 Impedance Converter, Network Analyzer
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef IIO_ADC_AD5933_H_
+#define IIO_ADC_AD5933_H_
+
+/*
+ * TODO: struct ad5933_platform_data needs to go into include/linux/iio
+ */
+
+/**
+ * struct ad5933_platform_data - platform specific data
+ * @ext_clk_Hz: the external clock frequency in Hz, if not set
+ * the driver uses the internal clock (16.776 MHz)
+ * @vref_mv: the external reference voltage in millivolt
+ */
+
+struct ad5933_platform_data {
+ unsigned long ext_clk_Hz;
+ unsigned short vref_mv;
+};
+
+#endif /* IIO_ADC_AD5933_H_ */
diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
index a2c3b67dcbdf..58a29b1e243c 100644
--- a/drivers/staging/iio/imu/adis16400_core.c
+++ b/drivers/staging/iio/imu/adis16400_core.c
@@ -25,21 +25,18 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
#include "../ring_generic.h"
-#include "../accel/accel.h"
-#include "../adc/adc.h"
-#include "../gyro/gyro.h"
-#include "../magnetometer/magnet.h"
-
#include "adis16400.h"
#define DRIVER_NAME "adis16400"
enum adis16400_chip_variant {
ADIS16300,
+ ADIS16344,
ADIS16350,
ADIS16360,
ADIS16362,
@@ -150,8 +147,6 @@ static int adis16400_spi_read_reg_16(struct iio_dev *indio_dev,
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);
@@ -240,17 +235,18 @@ static ssize_t adis16400_write_reset(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ bool val;
+ int ret;
- if (len < 1)
- return -1;
- switch (buf[0]) {
- case '1':
- case 'y':
- case 'Y':
- return adis16400_reset(indio_dev);
- }
- return -1;
+ ret = strtobool(buf, &val);
+ if (ret < 0)
+ return ret;
+ if (val)
+ ret = adis16400_reset(dev_get_drvdata(dev));
+ if (ret < 0)
+ return ret;
+
+ return len;
}
int adis16400_set_irq(struct iio_dev *indio_dev, bool enable)
@@ -695,6 +691,38 @@ static struct iio_chan_spec adis16300_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(14)
};
+static const struct iio_chan_spec adis16344_channels[] = {
+ IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_X,
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ gyro_x, ADIS16400_SCAN_GYRO_X, IIO_ST('s', 14, 16, 0), 0),
+ IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_Y,
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ gyro_y, ADIS16400_SCAN_GYRO_Y, IIO_ST('s', 14, 16, 0), 0),
+ IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_Z,
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ gyro_z, ADIS16400_SCAN_GYRO_Z, IIO_ST('s', 14, 16, 0), 0),
+ IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ accel_x, ADIS16400_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0),
+ IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ accel_y, ADIS16400_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0),
+ IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z,
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ accel_z, ADIS16400_SCAN_ACC_Z, IIO_ST('s', 14, 16, 0), 0),
+ IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ temp0, ADIS16350_SCAN_TEMP_X, IIO_ST('s', 12, 16, 0), 0),
+ IIO_CHAN_SOFT_TIMESTAMP(12)
+};
+
static struct attribute *adis16400_attributes[] = {
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
@@ -719,6 +747,16 @@ static struct adis16400_chip_info adis16400_chips[] = {
(1 << ADIS16300_SCAN_INCLI_X) | (1 << ADIS16300_SCAN_INCLI_Y) |
(1 << 14),
},
+ [ADIS16344] = {
+ .channels = adis16344_channels,
+ .num_channels = ARRAY_SIZE(adis16344_channels),
+ .gyro_scale_micro = 873,
+ .accel_scale_micro = 981,
+ .default_scan_mask = (1 << ADIS16400_SCAN_GYRO_X) |
+ (1 << ADIS16400_SCAN_GYRO_Y) | (1 << ADIS16400_SCAN_GYRO_Z) |
+ (1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) |
+ (1 << ADIS16400_SCAN_ACC_Z),
+ },
[ADIS16350] = {
.channels = adis16350_channels,
.num_channels = ARRAY_SIZE(adis16350_channels),
@@ -874,6 +912,7 @@ err_ret:
static const struct spi_device_id adis16400_id[] = {
{"adis16300", ADIS16300},
+ {"adis16344", ADIS16344},
{"adis16350", ADIS16350},
{"adis16354", ADIS16350},
{"adis16355", ADIS16350},
diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c
index 3612373ddede..3fc24037db29 100644
--- a/drivers/staging/iio/imu/adis16400_ring.c
+++ b/drivers/staging/iio/imu/adis16400_ring.c
@@ -1,21 +1,13 @@
#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/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
#include <linux/bitops.h>
#include "../iio.h"
-#include "../sysfs.h"
#include "../ring_sw.h"
-#include "../accel/accel.h"
-#include "../trigger.h"
+#include "../trigger_consumer.h"
#include "adis16400.h"
/**
@@ -119,7 +111,7 @@ static int adis16350_spi_read_all(struct device *dev, u8 *rx)
static irqreturn_t adis16400_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
+ struct iio_dev *indio_dev = pf->indio_dev;
struct adis16400_state *st = iio_priv(indio_dev);
struct iio_ring_buffer *ring = indio_dev->ring;
int i = 0, j, ret = 0;
diff --git a/drivers/staging/iio/imu/adis16400_trigger.c b/drivers/staging/iio/imu/adis16400_trigger.c
index c6ec41a02a69..3860d92f1ae7 100644
--- a/drivers/staging/iio/imu/adis16400_trigger.c
+++ b/drivers/staging/iio/imu/adis16400_trigger.c
@@ -1,14 +1,8 @@
#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"
@@ -24,6 +18,11 @@ static int adis16400_data_rdy_trigger_set_state(struct iio_trigger *trig,
return adis16400_set_irq(indio_dev, state);
}
+static const struct iio_trigger_ops adis16400_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &adis16400_data_rdy_trigger_set_state,
+};
+
int adis16400_probe_trigger(struct iio_dev *indio_dev)
{
int ret;
@@ -45,9 +44,8 @@ int adis16400_probe_trigger(struct iio_dev *indio_dev)
if (ret)
goto error_free_trig;
st->trig->dev.parent = &st->us->dev;
- st->trig->owner = THIS_MODULE;
st->trig->private_data = indio_dev;
- st->trig->set_trigger_state = &adis16400_data_rdy_trigger_set_state;
+ st->trig->ops = &adis16400_trigger_ops;
ret = iio_trigger_register(st->trig);
/* select default trigger */
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index 19819e7578c6..ed8a6df5bf42 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -22,7 +22,8 @@
#include <linux/cdev.h>
#include <linux/slab.h>
#include "iio.h"
-#include "trigger_consumer.h"
+#include "iio_core.h"
+#include "iio_core_trigger.h"
#define IIO_ID_PREFIX "device"
#define IIO_ID_FORMAT IIO_ID_PREFIX "%d"
@@ -35,7 +36,6 @@ static DEFINE_IDA(iio_chrdev_ida);
static DEFINE_SPINLOCK(iio_ida_lock);
dev_t iio_devt;
-EXPORT_SYMBOL(iio_devt);
#define IIO_DEV_MAX 256
struct bus_type iio_bus_type = {
@@ -85,8 +85,38 @@ static const char * const iio_chan_info_postfix[] = {
[IIO_CHAN_INFO_CALIBBIAS_SHARED/2] = "calibbias",
[IIO_CHAN_INFO_PEAK_SHARED/2] = "peak_raw",
[IIO_CHAN_INFO_PEAK_SCALE_SHARED/2] = "peak_scale",
+ [IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED/2]
+ = "quadrature_correction_raw",
};
+/* Return a negative errno on failure */
+static int iio_get_new_ida_val(struct ida *this_ida)
+{
+ int ret;
+ int val;
+
+ida_again:
+ if (unlikely(ida_pre_get(this_ida, GFP_KERNEL) == 0))
+ return -ENOMEM;
+
+ spin_lock(&iio_ida_lock);
+ ret = ida_get_new(this_ida, &val);
+ spin_unlock(&iio_ida_lock);
+ if (unlikely(ret == -EAGAIN))
+ goto ida_again;
+ else if (unlikely(ret))
+ return ret;
+
+ return val;
+}
+
+static void iio_free_ida_val(struct ida *this_ida, int id)
+{
+ spin_lock(&iio_ida_lock);
+ ida_remove(this_ida, id);
+ spin_unlock(&iio_ida_lock);
+}
+
int iio_push_event(struct iio_dev *dev_info,
int ev_line,
int ev_code,
@@ -246,28 +276,18 @@ static struct device_type iio_event_type = {
int iio_device_get_chrdev_minor(void)
{
- int ret, val;
+ int ret;
-ida_again:
- if (unlikely(ida_pre_get(&iio_chrdev_ida, GFP_KERNEL) == 0))
- return -ENOMEM;
- spin_lock(&iio_ida_lock);
- ret = ida_get_new(&iio_chrdev_ida, &val);
- spin_unlock(&iio_ida_lock);
- if (unlikely(ret == -EAGAIN))
- goto ida_again;
- else if (unlikely(ret))
+ ret = iio_get_new_ida_val(&iio_chrdev_ida);
+ if (ret < IIO_DEV_MAX) /* both errors and valid */
return ret;
- if (val > IIO_DEV_MAX)
+ else
return -ENOMEM;
- return val;
}
void iio_device_free_chrdev_minor(int val)
{
- spin_lock(&iio_ida_lock);
- ida_remove(&iio_chrdev_ida, val);
- spin_unlock(&iio_ida_lock);
+ iio_free_ida_val(&iio_chrdev_ida, val);
}
static int iio_setup_ev_int(struct iio_event_interface *ev_int,
@@ -329,24 +349,6 @@ static void iio_free_ev_int(struct iio_event_interface *ev_int)
put_device(&ev_int->dev);
}
-static int __init iio_dev_init(void)
-{
- int err;
-
- err = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio");
- if (err < 0)
- printk(KERN_ERR "%s: failed to allocate char dev region\n",
- __FILE__);
-
- return err;
-}
-
-static void __exit iio_dev_exit(void)
-{
- if (iio_devt)
- unregister_chrdev_region(iio_devt, IIO_DEV_MAX);
-}
-
static int __init iio_init(void)
{
int ret;
@@ -360,9 +362,12 @@ static int __init iio_init(void)
goto error_nothing;
}
- ret = iio_dev_init();
- if (ret < 0)
+ ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio");
+ if (ret < 0) {
+ printk(KERN_ERR "%s: failed to allocate char dev region\n",
+ __FILE__);
goto error_unregister_bus_type;
+ }
return 0;
@@ -374,7 +379,8 @@ error_nothing:
static void __exit iio_exit(void)
{
- iio_dev_exit();
+ if (iio_devt)
+ unregister_chrdev_region(iio_devt, IIO_DEV_MAX);
bus_unregister(&iio_bus_type);
}
@@ -524,6 +530,7 @@ static int __iio_build_postfix(struct iio_chan_spec const *chan,
return 0;
}
+static
int __iio_device_attr_init(struct device_attribute *dev_attr,
const char *postfix,
struct iio_chan_spec const *chan,
@@ -596,7 +603,7 @@ error_ret:
return ret;
}
-void __iio_device_attr_deinit(struct device_attribute *dev_attr)
+static void __iio_device_attr_deinit(struct device_attribute *dev_attr)
{
kfree(dev_attr->attr.name);
}
@@ -725,19 +732,29 @@ static ssize_t iio_show_dev_name(struct device *dev,
static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
+static struct attribute *iio_base_dummy_attrs[] = {
+ NULL
+};
+static struct attribute_group iio_base_dummy_group = {
+ .attrs = iio_base_dummy_attrs,
+};
+
static int iio_device_register_sysfs(struct iio_dev *dev_info)
{
int i, ret = 0;
struct iio_dev_attr *p, *n;
- if (dev_info->info->attrs) {
+ if (dev_info->info->attrs)
ret = sysfs_create_group(&dev_info->dev.kobj,
dev_info->info->attrs);
- if (ret) {
- dev_err(dev_info->dev.parent,
- "Failed to register sysfs hooks\n");
- goto error_ret;
- }
+ else
+ ret = sysfs_create_group(&dev_info->dev.kobj,
+ &iio_base_dummy_group);
+
+ if (ret) {
+ dev_err(dev_info->dev.parent,
+ "Failed to register sysfs hooks\n");
+ goto error_ret;
}
/*
@@ -753,7 +770,7 @@ static int iio_device_register_sysfs(struct iio_dev *dev_info)
if (ret < 0)
goto error_clear_attrs;
}
- if (dev_info->name) {
+ if (dev_info->name) {
ret = sysfs_add_file_to_group(&dev_info->dev.kobj,
&dev_attr_name.attr,
NULL);
@@ -770,6 +787,8 @@ error_clear_attrs:
}
if (dev_info->info->attrs)
sysfs_remove_group(&dev_info->dev.kobj, dev_info->info->attrs);
+ else
+ sysfs_remove_group(&dev_info->dev.kobj, &iio_base_dummy_group);
error_ret:
return ret;
@@ -790,38 +809,10 @@ static void iio_device_unregister_sysfs(struct iio_dev *dev_info)
if (dev_info->info->attrs)
sysfs_remove_group(&dev_info->dev.kobj, dev_info->info->attrs);
+ else
+ sysfs_remove_group(&dev_info->dev.kobj, &iio_base_dummy_group);
}
-/* Return a negative errno on failure */
-int iio_get_new_ida_val(struct ida *this_ida)
-{
- int ret;
- int val;
-
-ida_again:
- if (unlikely(ida_pre_get(this_ida, GFP_KERNEL) == 0))
- return -ENOMEM;
-
- spin_lock(&iio_ida_lock);
- ret = ida_get_new(this_ida, &val);
- spin_unlock(&iio_ida_lock);
- if (unlikely(ret == -EAGAIN))
- goto ida_again;
- else if (unlikely(ret))
- return ret;
-
- return val;
-}
-EXPORT_SYMBOL(iio_get_new_ida_val);
-
-void iio_free_ida_val(struct ida *this_ida, int id)
-{
- spin_lock(&iio_ida_lock);
- ida_remove(this_ida, id);
- spin_unlock(&iio_ida_lock);
-}
-EXPORT_SYMBOL(iio_free_ida_val);
-
static const char * const iio_ev_type_text[] = {
[IIO_EV_TYPE_THRESH] = "thresh",
[IIO_EV_TYPE_MAG] = "mag",
@@ -911,7 +902,7 @@ static int iio_device_add_event_sysfs(struct iio_dev *dev_info,
struct iio_chan_spec const *chan)
{
- int ret = 0, i, mask;
+ int ret = 0, i, mask = 0;
char *postfix;
if (!chan->event_mask)
return 0;
@@ -944,6 +935,7 @@ static int iio_device_add_event_sysfs(struct iio_dev *dev_info,
break;
default:
printk(KERN_INFO "currently unhandled type of event\n");
+ continue;
}
ret = __iio_add_chan_devattr(postfix,
NULL,
@@ -989,18 +981,17 @@ error_ret:
return ret;
}
-static inline void __iio_remove_all_event_sysfs(struct iio_dev *dev_info,
- const char *groupname,
- int num)
+static inline void __iio_remove_event_config_attrs(struct iio_dev *dev_info,
+ int i)
{
struct iio_dev_attr *p, *n;
list_for_each_entry_safe(p, n,
- &dev_info->event_interfaces[num].
+ &dev_info->event_interfaces[i].
dev_attr_list, l) {
sysfs_remove_file_from_group(&dev_info
- ->event_interfaces[num].dev.kobj,
+ ->event_interfaces[i].dev.kobj,
&p->dev_attr.attr,
- groupname);
+ NULL);
kfree(p->dev_attr.attr.name);
kfree(p);
}
@@ -1010,7 +1001,7 @@ static inline int __iio_add_event_config_attrs(struct iio_dev *dev_info, int i)
{
int j;
int ret;
- INIT_LIST_HEAD(&dev_info->event_interfaces[0].dev_attr_list);
+ INIT_LIST_HEAD(&dev_info->event_interfaces[i].dev_attr_list);
/* Dynically created from the channels array */
if (dev_info->channels) {
for (j = 0; j < dev_info->num_channels; j++) {
@@ -1024,18 +1015,11 @@ static inline int __iio_add_event_config_attrs(struct iio_dev *dev_info, int i)
return 0;
error_clear_attrs:
- __iio_remove_all_event_sysfs(dev_info, NULL, i);
+ __iio_remove_event_config_attrs(dev_info, i);
return ret;
}
-static inline int __iio_remove_event_config_attrs(struct iio_dev *dev_info,
- int i)
-{
- __iio_remove_all_event_sysfs(dev_info, NULL, i);
- return 0;
-}
-
static int iio_device_register_eventset(struct iio_dev *dev_info)
{
int ret = 0, i, j;
@@ -1061,7 +1045,7 @@ static int iio_device_register_eventset(struct iio_dev *dev_info)
if (ret) {
dev_err(&dev_info->dev,
"Could not get chrdev interface\n");
- goto error_free_setup_ev_ints;
+ goto error_free_setup_event_lines;
}
dev_set_drvdata(&dev_info->event_interfaces[i].dev,
@@ -1077,31 +1061,33 @@ static int iio_device_register_eventset(struct iio_dev *dev_info)
if (ret) {
dev_err(&dev_info->dev,
"Failed to register sysfs for event attrs");
- goto error_remove_sysfs_interfaces;
+ iio_free_ev_int(&dev_info->event_interfaces[i]);
+ goto error_free_setup_event_lines;
}
- }
-
- for (i = 0; i < dev_info->info->num_interrupt_lines; i++) {
ret = __iio_add_event_config_attrs(dev_info, i);
- if (ret)
- goto error_unregister_config_attrs;
+ if (ret) {
+ if (dev_info->info->event_attrs != NULL)
+ sysfs_remove_group(&dev_info
+ ->event_interfaces[i]
+ .dev.kobj,
+ &dev_info->info
+ ->event_attrs[i]);
+ iio_free_ev_int(&dev_info->event_interfaces[i]);
+ goto error_free_setup_event_lines;
+ }
}
return 0;
-error_unregister_config_attrs:
- for (j = 0; j < i; j++)
- __iio_remove_event_config_attrs(dev_info, i);
- i = dev_info->info->num_interrupt_lines - 1;
-error_remove_sysfs_interfaces:
- for (j = 0; j < i; j++)
+error_free_setup_event_lines:
+ for (j = 0; j < i; j++) {
+ __iio_remove_event_config_attrs(dev_info, j);
if (dev_info->info->event_attrs != NULL)
sysfs_remove_group(&dev_info
- ->event_interfaces[j].dev.kobj,
- &dev_info->info->event_attrs[j]);
-error_free_setup_ev_ints:
- for (j = 0; j < i; j++)
+ ->event_interfaces[j].dev.kobj,
+ &dev_info->info->event_attrs[j]);
iio_free_ev_int(&dev_info->event_interfaces[j]);
+ }
kfree(dev_info->event_interfaces);
error_ret:
@@ -1120,17 +1106,16 @@ static void iio_device_unregister_eventset(struct iio_dev *dev_info)
sysfs_remove_group(&dev_info
->event_interfaces[i].dev.kobj,
&dev_info->info->event_attrs[i]);
- }
-
- for (i = 0; i < dev_info->info->num_interrupt_lines; i++)
iio_free_ev_int(&dev_info->event_interfaces[i]);
+ }
kfree(dev_info->event_interfaces);
}
static void iio_dev_release(struct device *device)
{
+ struct iio_dev *dev_info = container_of(device, struct iio_dev, dev);
iio_put();
- kfree(to_iio_dev(device));
+ kfree(dev_info);
}
static struct device_type iio_dev_type = {
diff --git a/drivers/staging/iio/industrialio-ring.c b/drivers/staging/iio/industrialio-ring.c
index 843eb82a69ba..dce50b1a4ee9 100644
--- a/drivers/staging/iio/industrialio-ring.c
+++ b/drivers/staging/iio/industrialio-ring.c
@@ -21,6 +21,7 @@
#include <linux/poll.h>
#include "iio.h"
+#include "iio_core.h"
#include "ring_generic.h"
/**
diff --git a/drivers/staging/iio/industrialio-trigger.c b/drivers/staging/iio/industrialio-trigger.c
index 90ca2df23eab..f1ece8619e8d 100644
--- a/drivers/staging/iio/industrialio-trigger.c
+++ b/drivers/staging/iio/industrialio-trigger.c
@@ -8,7 +8,6 @@
*/
#include <linux/kernel.h>
-#include <linux/module.h>
#include <linux/idr.h>
#include <linux/err.h>
#include <linux/device.h>
@@ -18,6 +17,8 @@
#include "iio.h"
#include "trigger.h"
+#include "iio_core.h"
+#include "iio_core_trigger.h"
#include "trigger_consumer.h"
/* RFC - Question of approach
@@ -173,13 +174,12 @@ static struct iio_trigger *iio_trigger_find_by_name(const char *name,
void iio_trigger_poll(struct iio_trigger *trig, s64 time)
{
int i;
- if (!trig->use_count) {
+ if (!trig->use_count)
for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++)
if (trig->subirqs[i].enabled) {
trig->use_count++;
generic_handle_irq(trig->subirq_base + i);
}
- }
}
EXPORT_SYMBOL(iio_trigger_poll);
@@ -206,8 +206,8 @@ EXPORT_SYMBOL(iio_trigger_poll_chained);
void iio_trigger_notify_done(struct iio_trigger *trig)
{
trig->use_count--;
- if (trig->use_count == 0 && trig->try_reenable)
- if (trig->try_reenable(trig)) {
+ if (trig->use_count == 0 && trig->ops && trig->ops->try_reenable)
+ if (trig->ops->try_reenable(trig)) {
/* Missed and interrupt so launch new poll now */
iio_trigger_poll(trig, 0);
}
@@ -215,6 +215,26 @@ void iio_trigger_notify_done(struct iio_trigger *trig)
EXPORT_SYMBOL(iio_trigger_notify_done);
/* Trigger Consumer related functions */
+static int iio_trigger_get_irq(struct iio_trigger *trig)
+{
+ int ret;
+ mutex_lock(&trig->pool_lock);
+ ret = bitmap_find_free_region(trig->pool,
+ CONFIG_IIO_CONSUMERS_PER_TRIGGER,
+ ilog2(1));
+ mutex_unlock(&trig->pool_lock);
+ if (ret >= 0)
+ ret += trig->subirq_base;
+
+ return ret;
+}
+
+static void iio_trigger_put_irq(struct iio_trigger *trig, int irq)
+{
+ mutex_lock(&trig->pool_lock);
+ clear_bit(irq - trig->subirq_base, trig->pool);
+ mutex_unlock(&trig->pool_lock);
+}
/* Complexity in here. With certain triggers (datardy) an acknowledgement
* may be needed if the pollfuncs do not include the data read for the
@@ -223,44 +243,45 @@ EXPORT_SYMBOL(iio_trigger_notify_done);
* the relevant function is in there may be the best option.
*/
/* Worth protecting against double additions?*/
-int iio_trigger_attach_poll_func(struct iio_trigger *trig,
- struct iio_poll_func *pf)
+static int iio_trigger_attach_poll_func(struct iio_trigger *trig,
+ struct iio_poll_func *pf)
{
int ret = 0;
bool notinuse
= bitmap_empty(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER);
+ /* Prevent the module being removed whilst attached to a trigger */
+ __module_get(pf->indio_dev->info->driver_module);
pf->irq = iio_trigger_get_irq(trig);
ret = request_threaded_irq(pf->irq, pf->h, pf->thread,
pf->type, pf->name,
pf);
- if (trig->set_trigger_state && notinuse)
- ret = trig->set_trigger_state(trig, true);
+ if (trig->ops && trig->ops->set_trigger_state && notinuse)
+ ret = trig->ops->set_trigger_state(trig, true);
return ret;
}
-EXPORT_SYMBOL(iio_trigger_attach_poll_func);
-int iio_trigger_dettach_poll_func(struct iio_trigger *trig,
- struct iio_poll_func *pf)
+static int iio_trigger_dettach_poll_func(struct iio_trigger *trig,
+ struct iio_poll_func *pf)
{
int ret = 0;
bool no_other_users
= (bitmap_weight(trig->pool,
CONFIG_IIO_CONSUMERS_PER_TRIGGER)
== 1);
- if (trig->set_trigger_state && no_other_users) {
- ret = trig->set_trigger_state(trig, false);
+ if (trig->ops && trig->ops->set_trigger_state && no_other_users) {
+ ret = trig->ops->set_trigger_state(trig, false);
if (ret)
goto error_ret;
}
iio_trigger_put_irq(trig, pf->irq);
free_irq(pf->irq, pf);
+ module_put(pf->indio_dev->info->driver_module);
error_ret:
return ret;
}
-EXPORT_SYMBOL(iio_trigger_dettach_poll_func);
irqreturn_t iio_pollfunc_store_time(int irq, void *p)
{
@@ -274,7 +295,7 @@ struct iio_poll_func
*iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p),
irqreturn_t (*thread)(int irq, void *p),
int type,
- void *private,
+ struct iio_dev *indio_dev,
const char *fmt,
...)
{
@@ -294,7 +315,7 @@ struct iio_poll_func
pf->h = h;
pf->thread = thread;
pf->type = type;
- pf->private_data = private;
+ pf->indio_dev = indio_dev;
return pf;
}
@@ -318,12 +339,10 @@ static ssize_t iio_trigger_read_current(struct device *dev,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
- int len = 0;
+
if (dev_info->trig)
- len = sprintf(buf,
- "%s\n",
- dev_info->trig->name);
- return len;
+ return sprintf(buf, "%s\n", dev_info->trig->name);
+ return 0;
}
/**
@@ -358,8 +377,8 @@ static ssize_t iio_trigger_write_current(struct device *dev,
return ret;
}
- if (trig && trig->validate_device) {
- ret = trig->validate_device(trig, dev_info);
+ if (trig && trig->ops && trig->ops->validate_device) {
+ ret = trig->ops->validate_device(trig, dev_info);
if (ret)
return ret;
}
@@ -477,6 +496,7 @@ struct iio_trigger *iio_allocate_trigger(const char *fmt, ...)
IRQ_NOPROBE);
}
iio_get();
+ get_device(&trig->dev);
}
return trig;
}
@@ -491,20 +511,18 @@ EXPORT_SYMBOL(iio_free_trigger);
int iio_device_register_trigger_consumer(struct iio_dev *dev_info)
{
- int ret;
- ret = sysfs_create_group(&dev_info->dev.kobj,
- &iio_trigger_consumer_attr_group);
- return ret;
+ return sysfs_create_group(&dev_info->dev.kobj,
+ &iio_trigger_consumer_attr_group);
}
-EXPORT_SYMBOL(iio_device_register_trigger_consumer);
-int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info)
+void iio_device_unregister_trigger_consumer(struct iio_dev *dev_info)
{
+ /* Clean up and associated but not attached triggers references */
+ if (dev_info->trig)
+ iio_put_trigger(dev_info->trig);
sysfs_remove_group(&dev_info->dev.kobj,
&iio_trigger_consumer_attr_group);
- return 0;
}
-EXPORT_SYMBOL(iio_device_unregister_trigger_consumer);
int iio_triggered_ring_postenable(struct iio_dev *indio_dev)
{
diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
index 426b6af70807..da5bb33a66c1 100644
--- a/drivers/staging/iio/light/isl29018.c
+++ b/drivers/staging/iio/light/isl29018.c
@@ -53,6 +53,10 @@
#define ISL29018_REG_ADD_DATA_MSB 0x03
#define ISL29018_MAX_REGS ISL29018_REG_ADD_DATA_MSB
+#define ISL29018_REG_TEST 0x08
+#define ISL29018_TEST_SHIFT 0
+#define ISL29018_TEST_MASK (0xFF << ISL29018_TEST_SHIFT)
+
struct isl29018_chip {
struct i2c_client *client;
struct mutex lock;
@@ -457,6 +461,48 @@ static int isl29018_chip_init(struct i2c_client *client)
memset(chip->reg_cache, 0, sizeof(chip->reg_cache));
+ /* Code added per Intersil Application Note 1534:
+ * When VDD sinks to approximately 1.8V or below, some of
+ * the part's registers may change their state. When VDD
+ * recovers to 2.25V (or greater), the part may thus be in an
+ * unknown mode of operation. The user can return the part to
+ * a known mode of operation either by (a) setting VDD = 0V for
+ * 1 second or more and then powering back up with a slew rate
+ * of 0.5V/ms or greater, or (b) via I2C disable all ALS/PROX
+ * conversions, clear the test registers, and then rewrite all
+ * registers to the desired values.
+ * ...
+ * FOR ISL29011, ISL29018, ISL29021, ISL29023
+ * 1. Write 0x00 to register 0x08 (TEST)
+ * 2. Write 0x00 to register 0x00 (CMD1)
+ * 3. Rewrite all registers to the desired values
+ *
+ * ISL29018 Data Sheet (FN6619.1, Feb 11, 2010) essentially says
+ * the same thing EXCEPT the data sheet asks for a 1ms delay after
+ * writing the CMD1 register.
+ */
+ status = isl29018_write_data(client, ISL29018_REG_TEST, 0,
+ ISL29018_TEST_MASK, ISL29018_TEST_SHIFT);
+ if (status < 0) {
+ dev_err(&client->dev, "Failed to clear isl29018 TEST reg."
+ "(%d)\n", status);
+ return status;
+ }
+
+ /* See Intersil AN1534 comments above.
+ * "Operating Mode" (COMMAND1) register is reprogrammed when
+ * data is read from the device.
+ */
+ status = isl29018_write_data(client, ISL29018_REG_ADD_COMMAND1, 0,
+ 0xff, 0);
+ if (status < 0) {
+ dev_err(&client->dev, "Failed to clear isl29018 CMD1 reg."
+ "(%d)\n", status);
+ return status;
+ }
+
+ msleep(1); /* per data sheet, page 10 */
+
/* set defaults */
status = isl29018_set_range(client, chip->range, &new_range);
if (status < 0) {
diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c
index f25243b08472..665a7441b2ee 100644
--- a/drivers/staging/iio/light/tsl2563.c
+++ b/drivers/staging/iio/light/tsl2563.c
@@ -596,7 +596,7 @@ static irqreturn_t tsl2563_event_handler(int irq, void *private)
struct tsl2563_chip *chip = iio_priv(dev_info);
iio_push_event(dev_info, 0,
- IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_LIGHT,
+ IIO_UNMOD_EVENT_CODE(IIO_LIGHT,
0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_EITHER),
@@ -697,7 +697,7 @@ static int __devinit tsl2563_probe(struct i2c_client *client,
struct tsl2563_platform_data *pdata = client->dev.platform_data;
int err = 0;
int ret;
- u8 id;
+ u8 id = 0;
indio_dev = iio_allocate_device(sizeof(*chip));
if (!indio_dev)
diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c
index 5694610da1ca..c7daa2fcecf3 100644
--- a/drivers/staging/iio/light/tsl2583.c
+++ b/drivers/staging/iio/light/tsl2583.c
@@ -27,6 +27,7 @@
#include <linux/mutex.h>
#include <linux/unistd.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include "../iio.h"
#define TSL258X_MAX_DEVICE_REGS 32
@@ -68,7 +69,7 @@ enum {
TSL258X_CHIP_UNKNOWN = 0,
TSL258X_CHIP_WORKING = 1,
TSL258X_CHIP_SUSPENDED = 2
-} TSL258X_CHIP_WORKING_STATUS;
+};
/* Per-device data */
struct taos_als_info {
@@ -87,7 +88,6 @@ struct taos_settings {
struct tsl2583_chip {
struct mutex als_mutex;
struct i2c_client *client;
- struct iio_dev *iio_dev;
struct taos_als_info als_cur_info;
struct taos_settings taos_settings;
int als_time_scale;
@@ -114,7 +114,7 @@ struct taos_lux {
/* This structure is intentionally large to accommodate updates via sysfs. */
/* Sized to 11 = max 10 segments + 1 termination segment */
/* Assumption is is one and only one type of glass used */
-struct taos_lux taos_device_lux[11] = {
+static struct taos_lux taos_device_lux[11] = {
{ 9830, 8520, 15729 },
{ 12452, 10807, 23344 },
{ 14746, 6383, 11705 },
@@ -159,8 +159,7 @@ static void taos_defaults(struct tsl2583_chip *chip)
static int
taos_i2c_read(struct i2c_client *client, u8 reg, u8 *val, unsigned int len)
{
- int ret;
- int i;
+ int i, ret;
for (i = 0; i < len; i++) {
/* select register to write */
@@ -191,47 +190,47 @@ taos_i2c_read(struct i2c_client *client, u8 reg, u8 *val, unsigned int len)
* the array are then used along with the time scale factor array values, to
* calculate the lux.
*/
-static int taos_get_lux(struct i2c_client *client)
+static int taos_get_lux(struct iio_dev *indio_dev)
{
u16 ch0, ch1; /* separated ch0/ch1 data from device */
u32 lux; /* raw lux calculated from device data */
u32 ratio;
u8 buf[5];
struct taos_lux *p;
- struct tsl2583_chip *chip = i2c_get_clientdata(client);
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
int i, ret;
u32 ch0lux = 0;
u32 ch1lux = 0;
if (mutex_trylock(&chip->als_mutex) == 0) {
- dev_info(&client->dev, "taos_get_lux device is busy\n");
+ dev_info(&chip->client->dev, "taos_get_lux device is busy\n");
return chip->als_cur_info.lux; /* busy, so return LAST VALUE */
}
if (chip->taos_chip_status != TSL258X_CHIP_WORKING) {
/* device is not enabled */
- dev_err(&client->dev, "taos_get_lux device is not enabled\n");
+ dev_err(&chip->client->dev, "taos_get_lux device is not enabled\n");
ret = -EBUSY ;
goto out_unlock;
}
- ret = taos_i2c_read(client, (TSL258X_CMD_REG), &buf[0], 1);
+ ret = taos_i2c_read(chip->client, (TSL258X_CMD_REG), &buf[0], 1);
if (ret < 0) {
- dev_err(&client->dev, "taos_get_lux failed to read CMD_REG\n");
+ dev_err(&chip->client->dev, "taos_get_lux failed to read CMD_REG\n");
goto out_unlock;
}
/* is data new & valid */
if (!(buf[0] & TSL258X_STA_ADC_INTR)) {
- dev_err(&client->dev, "taos_get_lux data not valid\n");
+ dev_err(&chip->client->dev, "taos_get_lux data not valid\n");
ret = chip->als_cur_info.lux; /* return LAST VALUE */
goto out_unlock;
}
for (i = 0; i < 4; i++) {
int reg = TSL258X_CMD_REG | (TSL258X_ALS_CHAN0LO + i);
- ret = taos_i2c_read(client, reg, &buf[i], 1);
+ ret = taos_i2c_read(chip->client, reg, &buf[i], 1);
if (ret < 0) {
- dev_err(&client->dev, "taos_get_lux failed to read"
+ dev_err(&chip->client->dev, "taos_get_lux failed to read"
" register %x\n", reg);
goto out_unlock;
}
@@ -239,11 +238,12 @@ static int taos_get_lux(struct i2c_client *client)
/* clear status, really interrupt status (interrupts are off), but
* we use the bit anyway - don't forget 0x80 - this is a command*/
- ret = i2c_smbus_write_byte(client,
- (TSL258X_CMD_REG | TSL258X_CMD_SPL_FN | TSL258X_CMD_ALS_INT_CLR));
+ ret = i2c_smbus_write_byte(chip->client,
+ (TSL258X_CMD_REG | TSL258X_CMD_SPL_FN |
+ TSL258X_CMD_ALS_INT_CLR));
if (ret < 0) {
- dev_err(&client->dev,
+ dev_err(&chip->client->dev,
"taos_i2c_write_command failed in taos_get_lux, err = %d\n",
ret);
goto out_unlock; /* have no data, so return failure */
@@ -285,7 +285,7 @@ static int taos_get_lux(struct i2c_client *client)
/* note: lux is 31 bit max at this point */
if (ch1lux > ch0lux) {
- dev_dbg(&client->dev, "No Data - Return last value\n");
+ dev_dbg(&chip->client->dev, "No Data - Return last value\n");
ret = chip->als_cur_info.lux = 0;
goto out_unlock;
}
@@ -319,54 +319,56 @@ out_unlock:
* to derive actual lux).
* Return updated gain_trim value.
*/
-int taos_als_calibrate(struct i2c_client *client)
+static int taos_als_calibrate(struct iio_dev *indio_dev)
{
- struct tsl2583_chip *chip = i2c_get_clientdata(client);
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
u8 reg_val;
unsigned int gain_trim_val;
int ret;
int lux_val;
- ret = i2c_smbus_write_byte(client, (TSL258X_CMD_REG | TSL258X_CNTRL));
+ ret = i2c_smbus_write_byte(chip->client,
+ (TSL258X_CMD_REG | TSL258X_CNTRL));
if (ret < 0) {
- dev_err(&client->dev,
+ dev_err(&chip->client->dev,
"taos_als_calibrate failed to reach the CNTRL register, ret=%d\n",
ret);
return ret;
}
- reg_val = i2c_smbus_read_byte(client);
+ reg_val = i2c_smbus_read_byte(chip->client);
if ((reg_val & (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON))
!= (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) {
- dev_err(&client->dev,
+ dev_err(&chip->client->dev,
"taos_als_calibrate failed: device not powered on with ADC enabled\n");
return -1;
}
- ret = i2c_smbus_write_byte(client, (TSL258X_CMD_REG | TSL258X_CNTRL));
+ ret = i2c_smbus_write_byte(chip->client,
+ (TSL258X_CMD_REG | TSL258X_CNTRL));
if (ret < 0) {
- dev_err(&client->dev,
+ dev_err(&chip->client->dev,
"taos_als_calibrate failed to reach the STATUS register, ret=%d\n",
ret);
return ret;
}
- reg_val = i2c_smbus_read_byte(client);
+ reg_val = i2c_smbus_read_byte(chip->client);
if ((reg_val & TSL258X_STA_ADC_VALID) != TSL258X_STA_ADC_VALID) {
- dev_err(&client->dev,
+ dev_err(&chip->client->dev,
"taos_als_calibrate failed: STATUS - ADC not valid.\n");
return -ENODATA;
}
- lux_val = taos_get_lux(client);
+ lux_val = taos_get_lux(indio_dev);
if (lux_val < 0) {
- dev_err(&client->dev, "taos_als_calibrate failed to get lux\n");
+ dev_err(&chip->client->dev, "taos_als_calibrate failed to get lux\n");
return lux_val;
}
gain_trim_val = (unsigned int) (((chip->taos_settings.als_cal_target)
* chip->taos_settings.als_gain_trim) / lux_val);
if ((gain_trim_val < 250) || (gain_trim_val > 4000)) {
- dev_err(&client->dev,
+ dev_err(&chip->client->dev,
"taos_als_calibrate failed: trim_val of %d is out of range\n",
gain_trim_val);
return -ENODATA;
@@ -380,21 +382,21 @@ int taos_als_calibrate(struct i2c_client *client)
* Turn the device on.
* Configuration must be set before calling this function.
*/
-static int taos_chip_on(struct i2c_client *client)
+static int taos_chip_on(struct iio_dev *indio_dev)
{
int i;
- int ret = 0;
+ int ret;
u8 *uP;
u8 utmp;
int als_count;
int als_time;
- struct tsl2583_chip *chip = i2c_get_clientdata(client);
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
/* and make sure we're not already on */
if (chip->taos_chip_status == TSL258X_CHIP_WORKING) {
/* if forcing a register update - turn off, then on */
- dev_info(&client->dev, "device is already enabled\n");
- return -EINVAL;
+ dev_info(&chip->client->dev, "device is already enabled\n");
+ return -EINVAL;
}
/* determine als integration regster */
@@ -416,20 +418,21 @@ static int taos_chip_on(struct i2c_client *client)
/* TSL258x Specific power-on / adc enable sequence
* Power on the device 1st. */
utmp = TSL258X_CNTL_PWR_ON;
- ret = i2c_smbus_write_byte_data(client,
- TSL258X_CMD_REG | TSL258X_CNTRL, utmp);
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL258X_CMD_REG | TSL258X_CNTRL, utmp);
if (ret < 0) {
- dev_err(&client->dev, "taos_chip_on failed on CNTRL reg.\n");
+ dev_err(&chip->client->dev, "taos_chip_on failed on CNTRL reg.\n");
return -1;
}
/* Use the following shadow copy for our delay before enabling ADC.
* Write all the registers. */
for (i = 0, uP = chip->taos_config; i < TSL258X_REG_MAX; i++) {
- ret = i2c_smbus_write_byte_data(client, TSL258X_CMD_REG + i,
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL258X_CMD_REG + i,
*uP++);
if (ret < 0) {
- dev_err(&client->dev,
+ dev_err(&chip->client->dev,
"taos_chip_on failed on reg %d.\n", i);
return -1;
}
@@ -439,10 +442,11 @@ static int taos_chip_on(struct i2c_client *client)
/* NOW enable the ADC
* initialize the desired mode of operation */
utmp = TSL258X_CNTL_PWR_ON | TSL258X_CNTL_ADC_ENBL;
- ret = i2c_smbus_write_byte_data(client, TSL258X_CMD_REG | TSL258X_CNTRL,
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL258X_CMD_REG | TSL258X_CNTRL,
utmp);
if (ret < 0) {
- dev_err(&client->dev, "taos_chip_on failed on 2nd CTRL reg.\n");
+ dev_err(&chip->client->dev, "taos_chip_on failed on 2nd CTRL reg.\n");
return -1;
}
chip->taos_chip_status = TSL258X_CHIP_WORKING;
@@ -450,33 +454,26 @@ static int taos_chip_on(struct i2c_client *client)
return ret;
}
-static int taos_chip_off(struct i2c_client *client)
+static int taos_chip_off(struct iio_dev *indio_dev)
{
- struct tsl2583_chip *chip = i2c_get_clientdata(client);
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
int ret;
/* turn device off */
chip->taos_chip_status = TSL258X_CHIP_SUSPENDED;
- ret = i2c_smbus_write_byte_data(client, TSL258X_CMD_REG | TSL258X_CNTRL,
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL258X_CMD_REG | TSL258X_CNTRL,
0x00);
return ret;
}
/* Sysfs Interface Functions */
-static ssize_t taos_device_id(struct device *dev,
-struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
-
- return sprintf(buf, "%s\n", chip->client->name);
-}
static ssize_t taos_power_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
return sprintf(buf, "%d\n", chip->taos_chip_status);
}
@@ -485,16 +482,15 @@ static ssize_t taos_power_state_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
unsigned long value;
if (strict_strtoul(buf, 0, &value))
return -EINVAL;
if (value == 0)
- taos_chip_off(chip->client);
+ taos_chip_off(indio_dev);
else
- taos_chip_on(chip->client);
+ taos_chip_on(indio_dev);
return len;
}
@@ -503,7 +499,7 @@ static ssize_t taos_gain_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
char gain[4] = {0};
switch (chip->taos_settings.als_gain) {
@@ -528,7 +524,7 @@ static ssize_t taos_gain_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
unsigned long value;
if (strict_strtoul(buf, 0, &value))
@@ -565,7 +561,7 @@ static ssize_t taos_als_time_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
return sprintf(buf, "%d\n", chip->taos_settings.als_time);
}
@@ -574,7 +570,7 @@ static ssize_t taos_als_time_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
unsigned long value;
if (strict_strtoul(buf, 0, &value))
@@ -586,7 +582,7 @@ static ssize_t taos_als_time_store(struct device *dev,
if (value % 50)
return -EINVAL;
- chip->taos_settings.als_time = value;
+ chip->taos_settings.als_time = value;
return len;
}
@@ -602,7 +598,7 @@ static ssize_t taos_als_trim_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
return sprintf(buf, "%d\n", chip->taos_settings.als_gain_trim);
}
@@ -611,7 +607,7 @@ static ssize_t taos_als_trim_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
unsigned long value;
if (strict_strtoul(buf, 0, &value))
@@ -627,7 +623,7 @@ static ssize_t taos_als_cal_target_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
return sprintf(buf, "%d\n", chip->taos_settings.als_cal_target);
}
@@ -636,7 +632,7 @@ static ssize_t taos_als_cal_target_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
unsigned long value;
if (strict_strtoul(buf, 0, &value))
@@ -651,27 +647,26 @@ static ssize_t taos_als_cal_target_store(struct device *dev,
static ssize_t taos_lux_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
- int lux;
+ int ret;
- lux = taos_get_lux(chip->client);
+ ret = taos_get_lux(dev_get_drvdata(dev));
+ if (ret < 0)
+ return ret;
- return sprintf(buf, "%d\n", lux);
+ return sprintf(buf, "%d\n", ret);
}
static ssize_t taos_do_calibrate(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
unsigned long value;
if (strict_strtoul(buf, 0, &value))
return -EINVAL;
if (value == 1)
- taos_als_calibrate(chip->client);
+ taos_als_calibrate(indio_dev);
return len;
}
@@ -703,8 +698,8 @@ static ssize_t taos_luxtable_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2583_chip *chip = indio_dev->dev_data;
- int value[ARRAY_SIZE(taos_device_lux)];
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
+ int value[ARRAY_SIZE(taos_device_lux)*3 + 1];
int n;
get_options(buf, ARRAY_SIZE(value), value);
@@ -725,18 +720,17 @@ static ssize_t taos_luxtable_store(struct device *dev,
}
if (chip->taos_chip_status == TSL258X_CHIP_WORKING)
- taos_chip_off(chip->client);
+ taos_chip_off(indio_dev);
/* Zero out the table */
memset(taos_device_lux, 0, sizeof(taos_device_lux));
memcpy(taos_device_lux, &value[1], (value[0] * 4));
- taos_chip_on(chip->client);
+ taos_chip_on(indio_dev);
return len;
}
-static DEVICE_ATTR(name, S_IRUGO, taos_device_id, NULL);
static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
taos_power_state_show, taos_power_state_store);
@@ -762,7 +756,6 @@ static DEVICE_ATTR(illuminance0_lux_table, S_IRUGO | S_IWUSR,
taos_luxtable_show, taos_luxtable_store);
static struct attribute *sysfs_attrs_ctrl[] = {
- &dev_attr_name.attr,
&dev_attr_power_state.attr,
&dev_attr_illuminance0_calibscale.attr, /* Gain */
&dev_attr_illuminance0_calibscale_available.attr,
@@ -798,9 +791,10 @@ static const struct iio_info tsl2583_info = {
static int __devinit taos_probe(struct i2c_client *clientp,
const struct i2c_device_id *idp)
{
- int i, ret = 0;
+ int i, ret;
unsigned char buf[TSL258X_MAX_DEVICE_REGS];
- static struct tsl2583_chip *chip;
+ struct tsl2583_chip *chip;
+ struct iio_dev *indio_dev;
if (!i2c_check_functionality(clientp->adapter,
I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -810,12 +804,15 @@ static int __devinit taos_probe(struct i2c_client *clientp,
return -EOPNOTSUPP;
}
- chip = kzalloc(sizeof(struct tsl2583_chip), GFP_KERNEL);
- if (!chip)
- return -ENOMEM;
-
+ indio_dev = iio_allocate_device(sizeof(*chip));
+ if (indio_dev == NULL) {
+ ret = -ENOMEM;
+ dev_err(&clientp->dev, "iio allocation failed\n");
+ goto fail1;
+ }
+ chip = iio_priv(indio_dev);
chip->client = clientp;
- i2c_set_clientdata(clientp, chip);
+ i2c_set_clientdata(clientp, indio_dev);
mutex_init(&chip->als_mutex);
chip->taos_chip_status = TSL258X_CHIP_UNKNOWN;
@@ -827,14 +824,14 @@ static int __devinit taos_probe(struct i2c_client *clientp,
if (ret < 0) {
dev_err(&clientp->dev, "i2c_smbus_write_bytes() to cmd "
"reg failed in taos_probe(), err = %d\n", ret);
- goto fail1;
+ goto fail2;
}
ret = i2c_smbus_read_byte(clientp);
if (ret < 0) {
dev_err(&clientp->dev, "i2c_smbus_read_byte from "
"reg failed in taos_probe(), err = %d\n", ret);
- goto fail1;
+ goto fail2;
}
buf[i] = ret;
}
@@ -842,58 +839,50 @@ static int __devinit taos_probe(struct i2c_client *clientp,
if (!taos_tsl258x_device(buf)) {
dev_info(&clientp->dev, "i2c device found but does not match "
"expected id in taos_probe()\n");
- goto fail1;
+ goto fail2;
}
ret = i2c_smbus_write_byte(clientp, (TSL258X_CMD_REG | TSL258X_CNTRL));
if (ret < 0) {
dev_err(&clientp->dev, "i2c_smbus_write_byte() to cmd reg "
"failed in taos_probe(), err = %d\n", ret);
- goto fail1;
- }
-
- chip->iio_dev = iio_allocate_device(0);
- if (!chip->iio_dev) {
- ret = -ENOMEM;
- dev_err(&clientp->dev, "iio allocation failed\n");
- goto fail1;
+ goto fail2;
}
- chip->iio_dev->info = &tsl2583_info;
- chip->iio_dev->dev.parent = &clientp->dev;
- chip->iio_dev->dev_data = (void *)(chip);
- chip->iio_dev->modes = INDIO_DIRECT_MODE;
- ret = iio_device_register(chip->iio_dev);
+ indio_dev->info = &tsl2583_info;
+ indio_dev->dev.parent = &clientp->dev;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->name = chip->client->name;
+ ret = iio_device_register(indio_dev);
if (ret) {
dev_err(&clientp->dev, "iio registration failed\n");
- goto fail1;
+ goto fail2;
}
/* Load up the V2 defaults (these are hard coded defaults for now) */
taos_defaults(chip);
/* Make sure the chip is on */
- taos_chip_on(clientp);
+ taos_chip_on(indio_dev);
dev_info(&clientp->dev, "Light sensor found.\n");
-
return 0;
-
fail1:
- kfree(chip);
-
+ iio_free_device(indio_dev);
+fail2:
return ret;
}
static int taos_suspend(struct i2c_client *client, pm_message_t state)
{
- struct tsl2583_chip *chip = i2c_get_clientdata(client);
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
int ret = 0;
mutex_lock(&chip->als_mutex);
if (chip->taos_chip_status == TSL258X_CHIP_WORKING) {
- ret = taos_chip_off(client);
+ ret = taos_chip_off(indio_dev);
chip->taos_chip_status = TSL258X_CHIP_SUSPENDED;
}
@@ -903,13 +892,14 @@ static int taos_suspend(struct i2c_client *client, pm_message_t state)
static int taos_resume(struct i2c_client *client)
{
- struct tsl2583_chip *chip = i2c_get_clientdata(client);
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
int ret = 0;
mutex_lock(&chip->als_mutex);
if (chip->taos_chip_status == TSL258X_CHIP_SUSPENDED)
- ret = taos_chip_on(client);
+ ret = taos_chip_on(indio_dev);
mutex_unlock(&chip->als_mutex);
return ret;
@@ -918,11 +908,8 @@ static int taos_resume(struct i2c_client *client)
static int __devexit taos_remove(struct i2c_client *client)
{
- struct tsl2583_chip *chip = i2c_get_clientdata(client);
-
- iio_device_unregister(chip->iio_dev);
+ iio_device_unregister(i2c_get_clientdata(client));
- kfree(chip);
return 0;
}
diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c
index 33919e87e7ce..a17fa9f6a30e 100644
--- a/drivers/staging/iio/magnetometer/ak8975.c
+++ b/drivers/staging/iio/magnetometer/ak8975.c
@@ -31,7 +31,6 @@
#include <linux/gpio.h>
#include "../iio.h"
-#include "magnet.h"
/*
* Register definitions, as well as various shifts and masks to get at the
@@ -93,38 +92,28 @@ struct ak8975_data {
struct mutex lock;
u8 asa[3];
long raw_to_gauss[3];
- unsigned long mode;
+ bool mode;
u8 reg_cache[AK8975_MAX_REGS];
int eoc_gpio;
int eoc_irq;
};
+static const int ak8975_index_to_reg[] = {
+ AK8975_REG_HXL, AK8975_REG_HYL, AK8975_REG_HZL,
+};
+
/*
* Helper function to write to the I2C device's registers.
*/
static int ak8975_write_data(struct i2c_client *client,
u8 reg, u8 val, u8 mask, u8 shift)
{
- u8 regval;
- struct i2c_msg msg;
- u8 w_data[2];
- int ret = 0;
-
struct ak8975_data *data = i2c_get_clientdata(client);
+ u8 regval;
+ int ret;
- regval = data->reg_cache[reg];
- regval &= ~mask;
- regval |= val << shift;
-
- w_data[0] = reg;
- w_data[1] = regval;
-
- msg.addr = client->addr;
- msg.flags = 0;
- msg.len = 2;
- msg.buf = w_data;
-
- ret = i2c_transfer(client->adapter, &msg, 1);
+ regval = (data->reg_cache[reg] & ~mask) | (val << shift);
+ ret = i2c_smbus_write_byte_data(client, reg, regval);
if (ret < 0) {
dev_err(&client->dev, "Write to device fails status %x\n", ret);
return ret;
@@ -140,21 +129,20 @@ static int ak8975_write_data(struct i2c_client *client,
static int ak8975_read_data(struct i2c_client *client,
u8 reg, u8 length, u8 *buffer)
{
- struct i2c_msg msg[2];
- u8 w_data[2];
int ret;
-
- w_data[0] = reg;
-
- msg[0].addr = client->addr;
- msg[0].flags = I2C_M_NOSTART; /* set repeated start and write */
- msg[0].len = 1;
- msg[0].buf = w_data;
-
- msg[1].addr = client->addr;
- msg[1].flags = I2C_M_RD;
- msg[1].len = length;
- msg[1].buf = buffer;
+ struct i2c_msg msg[2] = {
+ {
+ .addr = client->addr,
+ .flags = I2C_M_NOSTART,
+ .len = 1,
+ .buf = &reg,
+ }, {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = length,
+ .buf = buffer,
+ }
+ };
ret = i2c_transfer(client->adapter, msg, 2);
if (ret < 0) {
@@ -204,8 +192,41 @@ static int ak8975_setup(struct i2c_client *client)
return ret;
}
- /* Precalculate scale factor for each axis and
- store in the device data. */
+/*
+ * Precalculate scale factor (in Gauss units) for each axis and
+ * store in the device data.
+ *
+ * This scale factor is axis-dependent, and is derived from 3 calibration
+ * factors ASA(x), ASA(y), and ASA(z).
+ *
+ * These ASA values are read from the sensor device at start of day, and
+ * cached in the device context struct.
+ *
+ * Adjusting the flux value with the sensitivity adjustment value should be
+ * done via the following formula:
+ *
+ * Hadj = H * ( ( ( (ASA-128)*0.5 ) / 128 ) + 1 )
+ *
+ * where H is the raw value, ASA is the sensitivity adjustment, and Hadj
+ * is the resultant adjusted value.
+ *
+ * We reduce the formula to:
+ *
+ * Hadj = H * (ASA + 128) / 256
+ *
+ * H is in the range of -4096 to 4095. The magnetometer has a range of
+ * +-1229uT. To go from the raw value to uT is:
+ *
+ * HuT = H * 1229/4096, or roughly, 3/10.
+ *
+ * Since 1uT = 100 gauss, our final scale factor becomes:
+ *
+ * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100
+ * Hadj = H * ((ASA + 128) * 30 / 256
+ *
+ * Since ASA doesn't change, we cache the resultant scale factor into the
+ * device context in ak8975_setup().
+ */
data->raw_to_gauss[0] = ((data->asa[0] + 128) * 30) >> 8;
data->raw_to_gauss[1] = ((data->asa[1] + 128) * 30) >> 8;
data->raw_to_gauss[2] = ((data->asa[2] + 128) * 30) >> 8;
@@ -222,7 +243,7 @@ static ssize_t show_mode(struct device *dev, struct device_attribute *devattr,
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ak8975_data *data = iio_priv(indio_dev);
- return sprintf(buf, "%lu\n", data->mode);
+ return sprintf(buf, "%u\n", data->mode);
}
/*
@@ -235,26 +256,22 @@ static ssize_t store_mode(struct device *dev, struct device_attribute *devattr,
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ak8975_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
- unsigned long oval;
+ bool value;
int ret;
/* Convert mode string and do some basic sanity checking on it.
only 0 or 1 are valid. */
- if (strict_strtoul(buf, 10, &oval))
- return -EINVAL;
-
- if (oval > 1) {
- dev_err(dev, "mode value is not supported\n");
- return -EINVAL;
- }
+ ret = strtobool(buf, &value);
+ if (ret < 0)
+ return ret;
mutex_lock(&data->lock);
/* Write the mode to the device. */
- if (data->mode != oval) {
+ if (data->mode != value) {
ret = ak8975_write_data(client,
AK8975_REG_CNTL,
- (u8)oval,
+ (u8)value,
AK8975_REG_CNTL_MODE_MASK,
AK8975_REG_CNTL_MODE_SHIFT);
@@ -263,7 +280,7 @@ static ssize_t store_mode(struct device *dev, struct device_attribute *devattr,
mutex_unlock(&data->lock);
return ret;
}
- data->mode = oval;
+ data->mode = value;
}
mutex_unlock(&data->lock);
@@ -271,50 +288,6 @@ static ssize_t store_mode(struct device *dev, struct device_attribute *devattr,
return count;
}
-/*
- * Emits the scale factor to bring the raw value into Gauss units.
- *
- * This scale factor is axis-dependent, and is derived from 3 calibration
- * factors ASA(x), ASA(y), and ASA(z).
- *
- * These ASA values are read from the sensor device at start of day, and
- * cached in the device context struct.
- *
- * Adjusting the flux value with the sensitivity adjustment value should be
- * done via the following formula:
- *
- * Hadj = H * ( ( ( (ASA-128)*0.5 ) / 128 ) + 1 )
- *
- * where H is the raw value, ASA is the sensitivity adjustment, and Hadj
- * is the resultant adjusted value.
- *
- * We reduce the formula to:
- *
- * Hadj = H * (ASA + 128) / 256
- *
- * H is in the range of -4096 to 4095. The magnetometer has a range of
- * +-1229uT. To go from the raw value to uT is:
- *
- * HuT = H * 1229/4096, or roughly, 3/10.
- *
- * Since 1uT = 100 gauss, our final scale factor becomes:
- *
- * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100
- * Hadj = H * ((ASA + 128) * 30 / 256
- *
- * Since ASA doesn't change, we cache the resultant scale factor into the
- * device context in ak8975_setup().
- */
-static ssize_t show_scale(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ak8975_data *data = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(devattr);
-
- return sprintf(buf, "%ld\n", data->raw_to_gauss[this_attr->address]);
-}
-
static int wait_conversion_complete_gpio(struct ak8975_data *data)
{
struct i2c_client *client = data->client;
@@ -371,13 +344,10 @@ static int wait_conversion_complete_polled(struct ak8975_data *data)
/*
* Emits the raw flux value for the x, y, or z axis.
*/
-static ssize_t show_raw(struct device *dev, struct device_attribute *devattr,
- char *buf)
+static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ak8975_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(devattr);
u16 meas_reg;
s16 raw;
u8 read_status;
@@ -429,7 +399,8 @@ static ssize_t show_raw(struct device *dev, struct device_attribute *devattr,
/* Read the flux value from the appropriate register
(the register is specified in the iio device attributes). */
- ret = ak8975_read_data(client, this_attr->address, 2, (u8 *)&meas_reg);
+ ret = ak8975_read_data(client, ak8975_index_to_reg[index],
+ 2, (u8 *)&meas_reg);
if (ret < 0) {
dev_err(&client->dev, "Read axis data fails\n");
goto exit;
@@ -442,30 +413,48 @@ static ssize_t show_raw(struct device *dev, struct device_attribute *devattr,
/* Clamp to valid range. */
raw = clamp_t(s16, raw, -4096, 4095);
-
- return sprintf(buf, "%d\n", raw);
+ *val = raw;
+ return IIO_VAL_INT;
exit:
mutex_unlock(&data->lock);
return ret;
}
+static int ak8975_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2,
+ long mask)
+{
+ struct ak8975_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case 0:
+ return ak8975_read_axis(indio_dev, chan->address, val);
+ case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ *val = data->raw_to_gauss[chan->address];
+ return IIO_VAL_INT;
+ }
+ return -EINVAL;
+}
+
+#define AK8975_CHANNEL(axis, index) \
+ { \
+ .type = IIO_MAGN, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##axis, \
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \
+ .address = index, \
+ }
+
+static const struct iio_chan_spec ak8975_channels[] = {
+ AK8975_CHANNEL(X, 0), AK8975_CHANNEL(Y, 1), AK8975_CHANNEL(Z, 2),
+};
+
static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, show_mode, store_mode, 0);
-static IIO_DEV_ATTR_MAGN_X_SCALE(S_IRUGO, show_scale, NULL, 0);
-static IIO_DEV_ATTR_MAGN_Y_SCALE(S_IRUGO, show_scale, NULL, 1);
-static IIO_DEV_ATTR_MAGN_Z_SCALE(S_IRUGO, show_scale, NULL, 2);
-static IIO_DEV_ATTR_MAGN_X(show_raw, AK8975_REG_HXL);
-static IIO_DEV_ATTR_MAGN_Y(show_raw, AK8975_REG_HYL);
-static IIO_DEV_ATTR_MAGN_Z(show_raw, AK8975_REG_HZL);
static struct attribute *ak8975_attr[] = {
&iio_dev_attr_mode.dev_attr.attr,
- &iio_dev_attr_magn_x_scale.dev_attr.attr,
- &iio_dev_attr_magn_y_scale.dev_attr.attr,
- &iio_dev_attr_magn_z_scale.dev_attr.attr,
- &iio_dev_attr_magn_x_raw.dev_attr.attr,
- &iio_dev_attr_magn_y_raw.dev_attr.attr,
- &iio_dev_attr_magn_z_raw.dev_attr.attr,
NULL
};
@@ -475,6 +464,7 @@ static struct attribute_group ak8975_attr_group = {
static const struct iio_info ak8975_info = {
.attrs = &ak8975_attr_group,
+ .read_raw = &ak8975_read_raw,
.driver_module = THIS_MODULE,
};
@@ -530,6 +520,8 @@ static int ak8975_probe(struct i2c_client *client,
data->eoc_irq = client->irq;
data->eoc_gpio = eoc_gpio;
indio_dev->dev.parent = &client->dev;
+ indio_dev->channels = ak8975_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ak8975_channels);
indio_dev->info = &ak8975_info;
indio_dev->modes = INDIO_DIRECT_MODE;
diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
index b44c273a91a8..1bb71864d586 100644
--- a/drivers/staging/iio/magnetometer/hmc5843.c
+++ b/drivers/staging/iio/magnetometer/hmc5843.c
@@ -24,7 +24,6 @@
#include <linux/types.h>
#include "../iio.h"
#include "../sysfs.h"
-#include "magnet.h"
#define HMC5843_I2C_ADDRESS 0x1E
@@ -62,9 +61,9 @@
/*
* Device status
*/
-#define DATA_READY 0x01
-#define DATA_OUTPUT_LOCK 0x02
-#define VOLTAGE_REGULATOR_ENABLED 0x04
+#define DATA_READY 0x01
+#define DATA_OUTPUT_LOCK 0x02
+#define VOLTAGE_REGULATOR_ENABLED 0x04
/*
* Mode register configuration
@@ -89,22 +88,16 @@
/*
* Device Configutration
*/
-#define CONF_NORMAL 0x00
+#define CONF_NORMAL 0x00
#define CONF_POSITIVE_BIAS 0x01
#define CONF_NEGATIVE_BIAS 0x02
#define CONF_NOT_USED 0x03
#define MEAS_CONF_MASK 0x03
-static const char *regval_to_scale[] = {
- "0.0000006173",
- "0.0000007692",
- "0.0000010309",
- "0.0000012821",
- "0.0000018868",
- "0.0000021739",
- "0.0000025641",
- "0.0000035714",
+static int hmc5843_regval_to_nanoscale[] = {
+ 6173, 7692, 10309, 12821, 18868, 21739, 25641, 35714
};
+
static const int regval_to_input_field_mg[] = {
700,
1000,
@@ -115,7 +108,7 @@ static const int regval_to_input_field_mg[] = {
4500,
6500
};
-static const char *regval_to_samp_freq[] = {
+static const char * const regval_to_samp_freq[] = {
"0.5",
"1",
"2",
@@ -150,37 +143,28 @@ static s32 hmc5843_configure(struct i2c_client *client,
}
/* Return the measurement value from the specified channel */
-static ssize_t hmc5843_read_measurement(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int hmc5843_read_measurement(struct iio_dev *indio_dev,
+ int address,
+ int *val)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
- s16 coordinate_val;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct hmc5843_data *data = iio_priv(indio_dev);
s32 result;
mutex_lock(&data->lock);
-
result = i2c_smbus_read_byte_data(client, HMC5843_STATUS_REG);
while (!(result & DATA_READY))
result = i2c_smbus_read_byte_data(client, HMC5843_STATUS_REG);
- result = i2c_smbus_read_word_data(client, this_attr->address);
+ result = i2c_smbus_read_word_data(client, address);
mutex_unlock(&data->lock);
if (result < 0)
return -EINVAL;
- coordinate_val = (s16)swab16((u16)result);
- return sprintf(buf, "%d\n", coordinate_val);
+ *val = (s16)swab16((u16)result);
+ return IIO_VAL_INT;
}
-static IIO_DEV_ATTR_MAGN_X(hmc5843_read_measurement,
- HMC5843_DATA_OUT_X_MSB_REG);
-static IIO_DEV_ATTR_MAGN_Y(hmc5843_read_measurement,
- HMC5843_DATA_OUT_Y_MSB_REG);
-static IIO_DEV_ATTR_MAGN_Z(hmc5843_read_measurement,
- HMC5843_DATA_OUT_Z_MSB_REG);
+
/*
* From the datasheet
@@ -336,7 +320,7 @@ static s32 hmc5843_set_rate(struct i2c_client *client,
reg_val = (data->meas_conf) | (rate << RATE_OFFSET);
if (rate >= RATE_NOT_USED) {
dev_err(&client->dev,
- "This data output rate is not supported \n");
+ "This data output rate is not supported\n");
return -EINVAL;
}
return i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_A, reg_val);
@@ -467,28 +451,46 @@ static IIO_DEVICE_ATTR(magn_range,
set_range,
HMC5843_CONFIG_REG_B);
-static ssize_t show_scale(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int hmc5843_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2,
+ long mask)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct hmc5843_data *data = iio_priv(indio_dev);
- return strlen(strcpy(buf, regval_to_scale[data->range]));
+
+ switch (mask) {
+ case 0:
+ return hmc5843_read_measurement(indio_dev,
+ chan->address,
+ val);
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ *val = 0;
+ *val2 = hmc5843_regval_to_nanoscale[data->range];
+ return IIO_VAL_INT_PLUS_NANO;
+ };
+ return -EINVAL;
}
-static IIO_DEVICE_ATTR(magn_scale,
- S_IRUGO,
- show_scale,
- NULL , 0);
+
+#define HMC5843_CHANNEL(axis, add) \
+ { \
+ .type = IIO_MAGN, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##axis, \
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \
+ .address = add \
+ }
+
+static const struct iio_chan_spec hmc5843_channels[] = {
+ HMC5843_CHANNEL(X, HMC5843_DATA_OUT_X_MSB_REG),
+ HMC5843_CHANNEL(Y, HMC5843_DATA_OUT_Y_MSB_REG),
+ HMC5843_CHANNEL(Z, HMC5843_DATA_OUT_Z_MSB_REG),
+};
static struct attribute *hmc5843_attributes[] = {
&iio_dev_attr_meas_conf.dev_attr.attr,
&iio_dev_attr_operating_mode.dev_attr.attr,
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_dev_attr_magn_range.dev_attr.attr,
- &iio_dev_attr_magn_scale.dev_attr.attr,
- &iio_dev_attr_magn_x_raw.dev_attr.attr,
- &iio_dev_attr_magn_y_raw.dev_attr.attr,
- &iio_dev_attr_magn_z_raw.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
NULL
};
@@ -530,6 +532,7 @@ static void hmc5843_init_client(struct i2c_client *client)
static const struct iio_info hmc5843_info = {
.attrs = &hmc5843_group,
+ .read_raw = &hmc5843_read_raw,
.driver_module = THIS_MODULE,
};
@@ -558,6 +561,9 @@ static int hmc5843_probe(struct i2c_client *client,
hmc5843_init_client(client);
indio_dev->info = &hmc5843_info;
+ indio_dev->name = id->name;
+ indio_dev->channels = hmc5843_channels;
+ indio_dev->num_channels = ARRAY_SIZE(hmc5843_channels);
indio_dev->dev.parent = &client->dev;
indio_dev->modes = INDIO_DIRECT_MODE;
err = iio_device_register(indio_dev);
diff --git a/drivers/staging/iio/magnetometer/magnet.h b/drivers/staging/iio/magnetometer/magnet.h
deleted file mode 100644
index 1260eb7bd41e..000000000000
--- a/drivers/staging/iio/magnetometer/magnet.h
+++ /dev/null
@@ -1,31 +0,0 @@
-
-#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_SCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(magn_x_scale, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_MAGN_Y_SCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(magn_y_scale, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_MAGN_Z_SCALE(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(magn_z_scale, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_MAGN_X(_show, _addr) \
- IIO_DEVICE_ATTR(magn_x_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_MAGN_Y(_show, _addr) \
- IIO_DEVICE_ATTR(magn_y_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_MAGN_Z(_show, _addr) \
- IIO_DEVICE_ATTR(magn_z_raw, S_IRUGO, _show, NULL, _addr)
diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
index 4d1bd42ff9e0..bccc5798fa5c 100644
--- a/drivers/staging/iio/meter/ade7753.c
+++ b/drivers/staging/iio/meter/ade7753.c
@@ -17,6 +17,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c
index f4f85fd5619b..6f0f464aba38 100644
--- a/drivers/staging/iio/meter/ade7754.c
+++ b/drivers/staging/iio/meter/ade7754.c
@@ -17,6 +17,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c
index 299b95434e20..ac0e092e49d3 100644
--- a/drivers/staging/iio/meter/ade7758_core.c
+++ b/drivers/staging/iio/meter/ade7758_core.c
@@ -17,6 +17,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c
index b89b7f882e84..1e2a09643a35 100644
--- a/drivers/staging/iio/meter/ade7758_ring.c
+++ b/drivers/staging/iio/meter/ade7758_ring.c
@@ -6,23 +6,14 @@
* Licensed under the GPL-2.
*/
#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/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
#include <asm/unaligned.h>
#include "../iio.h"
-#include "../sysfs.h"
#include "../ring_sw.h"
-#include "../accel/accel.h"
-#include "../trigger.h"
+#include "../trigger_consumer.h"
#include "ade7758.h"
/**
@@ -69,7 +60,7 @@ out:
static irqreturn_t ade7758_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->private_data;
+ struct iio_dev *indio_dev = pf->indio_dev;
struct iio_ring_buffer *ring = indio_dev->ring;
struct ade7758_state *st = iio_priv(indio_dev);
s64 dat64[2];
@@ -136,12 +127,6 @@ static const struct iio_ring_setup_ops ade7758_ring_setup_ops = {
void ade7758_unconfigure_ring(struct iio_dev *indio_dev)
{
- /* ensure that the trigger has been detached */
- if (indio_dev->trig) {
- iio_put_trigger(indio_dev->trig);
- iio_trigger_dettach_poll_func(indio_dev->trig,
- indio_dev->pollfunc);
- }
iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
diff --git a/drivers/staging/iio/meter/ade7758_trigger.c b/drivers/staging/iio/meter/ade7758_trigger.c
index a5c3248151ed..392dfe302443 100644
--- a/drivers/staging/iio/meter/ade7758_trigger.c
+++ b/drivers/staging/iio/meter/ade7758_trigger.c
@@ -7,16 +7,10 @@
*/
#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 "ade7758.h"
@@ -57,6 +51,12 @@ static int ade7758_trig_try_reen(struct iio_trigger *trig)
return 0;
}
+static const struct iio_trigger_ops ade7758_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &ade7758_data_rdy_trigger_set_state,
+ .try_reenable = &ade7758_trig_try_reen,
+};
+
int ade7758_probe_trigger(struct iio_dev *indio_dev)
{
struct ade7758_state *st = iio_priv(indio_dev);
@@ -79,10 +79,8 @@ int ade7758_probe_trigger(struct iio_dev *indio_dev)
goto error_free_trig;
st->trig->dev.parent = &st->us->dev;
- st->trig->owner = THIS_MODULE;
+ st->trig->ops = &ade7758_trigger_ops;
st->trig->private_data = indio_dev;
- st->trig->set_trigger_state = &ade7758_data_rdy_trigger_set_state;
- st->trig->try_reenable = &ade7758_trig_try_reen;
ret = iio_trigger_register(st->trig);
/* select default trigger */
diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c
index a51a64cad034..31723e8e64fa 100644
--- a/drivers/staging/iio/meter/ade7759.c
+++ b/drivers/staging/iio/meter/ade7759.c
@@ -17,6 +17,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
diff --git a/drivers/staging/iio/meter/ade7854-i2c.c b/drivers/staging/iio/meter/ade7854-i2c.c
index dd7234353405..cbca3fd8fcd6 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include "../iio.h"
#include "ade7854.h"
diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c
index e0d10865590a..cfa23ba30efe 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include "../iio.h"
#include "ade7854.h"
diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c
index b82659f43bc6..bc1f83eea7c6 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -582,7 +583,7 @@ error_unreg_dev:
iio_device_unregister(indio_dev);
error_free_dev:
iio_free_device(indio_dev);
-error_ret:
+
return ret;
}
EXPORT_SYMBOL(ade7854_probe);
diff --git a/drivers/staging/iio/resolver/ad2s120x.c b/drivers/staging/iio/resolver/ad2s120x.c
index bed4c725f2df..fdaf0a8fcf90 100644
--- a/drivers/staging/iio/resolver/ad2s120x.c
+++ b/drivers/staging/iio/resolver/ad2s120x.c
@@ -16,6 +16,7 @@
#include <linux/sysfs.h>
#include <linux/delay.h>
#include <linux/gpio.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c
index ecaf7bb790fe..f8459e8e8552 100644
--- a/drivers/staging/iio/resolver/ad2s1210.c
+++ b/drivers/staging/iio/resolver/ad2s1210.c
@@ -16,6 +16,7 @@
#include <linux/sysfs.h>
#include <linux/delay.h>
#include <linux/gpio.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -639,7 +640,6 @@ static struct attribute *ad2s1210_attributes[] = {
};
static const struct attribute_group ad2s1210_attribute_group = {
- .name = DRV_NAME,
.attrs = ad2s1210_attributes,
};
diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c
index 166e2414ac85..3739bd24951c 100644
--- a/drivers/staging/iio/resolver/ad2s90.c
+++ b/drivers/staging/iio/resolver/ad2s90.c
@@ -14,6 +14,7 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -58,7 +59,6 @@ static struct attribute *ad2s90_attributes[] = {
};
static const struct attribute_group ad2s90_attribute_group = {
- .name = DRV_NAME,
.attrs = ad2s90_attributes,
};
diff --git a/drivers/staging/iio/sysfs.h b/drivers/staging/iio/sysfs.h
index dd79b5844212..0b75823fbe1b 100644
--- a/drivers/staging/iio/sysfs.h
+++ b/drivers/staging/iio/sysfs.h
@@ -12,19 +12,17 @@
#ifndef _INDUSTRIAL_IO_SYSFS_H_
#define _INDUSTRIAL_IO_SYSFS_H_
-#include "iio.h"
+struct iio_chan_spec;
/**
* struct iio_dev_attr - iio specific device attribute
* @dev_attr: underlying device attribute
* @address: associated register address
- * @val2: secondary attribute value
* @l: list head for maintaining list of dynamically created attrs.
*/
struct iio_dev_attr {
struct device_attribute dev_attr;
int address;
- int val2;
struct list_head l;
struct iio_chan_spec const *c;
};
@@ -64,10 +62,6 @@ struct iio_const_attr {
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 \
- = IIO_ATTR_2(_name, _mode, _show, _store, _addr, _val2)
-
#define IIO_CONST_ATTR(_name, _string) \
struct iio_const_attr iio_const_attr_##_name \
= { .string = _string, \
@@ -77,17 +71,8 @@ struct iio_const_attr {
struct iio_const_attr iio_const_attr_##_vname \
= { .string = _string, \
.dev_attr = __ATTR(_name, S_IRUGO, iio_read_const_attr, NULL)}
-/* Generic attributes of onetype or another */
-
-/**
- * IIO_DEV_ATTR_REV - revision number for the device
- * @_show: output method for the attribute
- *
- * Very much device dependent.
- **/
-#define IIO_DEV_ATTR_REV(_show) \
- IIO_DEVICE_ATTR(revision, S_IRUGO, _show, NULL, 0)
+/* Generic attributes of onetype or another */
/**
* IIO_DEV_ATTR_RESET: resets the device
**/
@@ -95,13 +80,6 @@ struct iio_const_attr {
IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, _store, 0)
/**
- * IIO_CONST_ATTR_NAME - constant identifier
- * @_string: the name
- **/
-#define IIO_CONST_ATTR_NAME(_string) \
- IIO_CONST_ATTR(name, _string)
-
-/**
* IIO_DEV_ATTR_SAMP_FREQ - sets any internal clock frequency
* @_mode: sysfs file mode/permissions
* @_show: output method for the attribute
@@ -111,15 +89,11 @@ struct iio_const_attr {
IIO_DEVICE_ATTR(sampling_frequency, _mode, _show, _store, 0)
/**
- * IIO_DEV_ATTR_AVAIL_SAMP_FREQ - list available sampling frequencies
+ * IIO_DEV_ATTR_SAMP_FREQ_AVAIL - list available sampling frequencies
* @_show: output method for the attribute
*
* 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)
/**
@@ -131,27 +105,6 @@ struct iio_const_attr {
#define IIO_CONST_ATTR_SAMP_FREQ_AVAIL(_string) \
IIO_CONST_ATTR(sampling_frequency_available, _string)
-/**
- * IIO_DEV_ATTR_SW_RING_ENABLE - enable software ring buffer
- * @_show: output method for the attribute
- * @_store: input method for the attribute
- *
- * Success may be dependent on attachment of trigger previously.
- **/
-#define IIO_DEV_ATTR_SW_RING_ENABLE(_show, _store) \
- IIO_DEVICE_ATTR(sw_ring_enable, S_IRUGO | S_IWUSR, _show, _store, 0)
-
-/**
- * IIO_DEV_ATTR_HW_RING_ENABLE - enable hardware ring buffer
- * @_show: output method for the attribute
- * @_store: input method for the attribute
- *
- * This is a different attribute from the software one as one can envision
- * schemes where a combination of the two may be used.
- **/
-#define IIO_DEV_ATTR_HW_RING_ENABLE(_show, _store) \
- IIO_DEVICE_ATTR(hw_ring_enable, S_IRUGO | S_IWUSR, _show, _store, 0)
-
#define IIO_DEV_ATTR_TEMP_RAW(_show) \
IIO_DEVICE_ATTR(temp_raw, S_IRUGO, _show, NULL, 0)
@@ -161,28 +114,6 @@ struct iio_const_attr {
#define IIO_CONST_ATTR_TEMP_SCALE(_string) \
IIO_CONST_ATTR(temp_scale, _string)
-/* must match our channel defs */
-#define IIO_EV_CLASS_IN IIO_IN
-#define IIO_EV_CLASS_IN_DIFF IIO_IN_DIFF
-#define IIO_EV_CLASS_ACCEL IIO_ACCEL
-#define IIO_EV_CLASS_GYRO IIO_GYRO
-#define IIO_EV_CLASS_MAGN IIO_MAGN
-#define IIO_EV_CLASS_LIGHT IIO_LIGHT
-#define IIO_EV_CLASS_PROXIMITY IIO_PROXIMITY
-#define IIO_EV_CLASS_TEMP IIO_TEMP
-
-#define IIO_EV_MOD_X IIO_MOD_X
-#define IIO_EV_MOD_Y IIO_MOD_Y
-#define IIO_EV_MOD_Z IIO_MOD_Z
-#define IIO_EV_MOD_X_AND_Y IIO_MOD_X_AND_Y
-#define IIO_EV_MOD_X_ANX_Z IIO_MOD_X_AND_Z
-#define IIO_EV_MOD_Y_AND_Z IIO_MOD_Y_AND_Z
-#define IIO_EV_MOD_X_AND_Y_AND_Z IIO_MOD_X_AND_Y_AND_Z
-#define IIO_EV_MOD_X_OR_Y IIO_MOD_X_OR_Y
-#define IIO_EV_MOD_X_OR_Z IIO_MOD_X_OR_Z
-#define IIO_EV_MOD_Y_OR_Z IIO_MOD_Y_OR_Z
-#define IIO_EV_MOD_X_OR_Y_OR_Z IIO_MOD_X_OR_Y_OR_Z
-
#define IIO_EV_TYPE_THRESH 0
#define IIO_EV_TYPE_MAG 1
#define IIO_EV_TYPE_ROC 2
@@ -207,10 +138,6 @@ struct iio_const_attr {
#define IIO_UNMOD_EVENT_CODE(channelclass, number, type, direction) \
IIO_EVENT_CODE(channelclass, 0, number, 0, type, direction)
-
-#define IIO_BUFFER_EVENT_CODE(code) \
- (IIO_EV_CLASS_BUFFER | (code << 8))
-
#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 24) & 0xf)
/* Event code number extraction depends on which type of event we have.
diff --git a/drivers/staging/iio/trigger.h b/drivers/staging/iio/trigger.h
index e0b58ed749b8..598fcb3599f9 100644
--- a/drivers/staging/iio/trigger.h
+++ b/drivers/staging/iio/trigger.h
@@ -7,6 +7,7 @@
* the Free Software Foundation.
*/
#include <linux/irq.h>
+#include <linux/module.h>
#ifndef _IIO_TRIGGER_H_
#define _IIO_TRIGGER_H_
@@ -16,6 +17,27 @@ struct iio_subirq {
};
/**
+ * struct iio_trigger_ops - operations structure for an iio_trigger.
+ * @owner: used to monitor usage count of the trigger.
+ * @set_trigger_state: switch on/off the trigger on demand
+ * @try_reenable: function to reenable the trigger when the
+ * use count is zero (may be NULL)
+ * @validate_device: function to validate the device when the
+ * current trigger gets changed.
+ *
+ * This is typically static const within a driver and shared by
+ * instances of a given device.
+ **/
+struct iio_trigger_ops {
+ struct module *owner;
+ int (*set_trigger_state)(struct iio_trigger *trig, bool state);
+ int (*try_reenable)(struct iio_trigger *trig);
+ int (*validate_device)(struct iio_trigger *trig,
+ struct iio_dev *indio_dev);
+};
+
+
+/**
* struct iio_trigger - industrial I/O trigger device
*
* @id: [INTERN] unique id number
@@ -26,11 +48,6 @@ struct iio_subirq {
* @alloc_list: [DRIVER] used for driver specific trigger list
* @owner: [DRIVER] used to monitor usage count of the trigger.
* @use_count: use count for the trigger
- * @set_trigger_state: [DRIVER] switch on/off the trigger on demand
- * @try_reenable: function to reenable the trigger when the
- * use count is zero (may be NULL)
- * @validate_device: function to validate the device when the
- * current trigger gets changed.
* @subirq_chip: [INTERN] associate 'virtual' irq chip.
* @subirq_base: [INTERN] base number for irqs provided by trigger.
* @subirqs: [INTERN] information about the 'child' irqs.
@@ -38,6 +55,7 @@ struct iio_subirq {
* @pool_lock: [INTERN] protection of the irq pool.
**/
struct iio_trigger {
+ const struct iio_trigger_ops *ops;
int id;
const char *name;
struct device dev;
@@ -48,11 +66,6 @@ struct iio_trigger {
struct module *owner;
int use_count;
- int (*set_trigger_state)(struct iio_trigger *trig, bool state);
- int (*try_reenable)(struct iio_trigger *trig);
- int (*validate_device)(struct iio_trigger *trig,
- struct iio_dev *indio_dev);
-
struct irq_chip subirq_chip;
int subirq_base;
@@ -61,29 +74,6 @@ struct iio_trigger {
struct mutex pool_lock;
};
-/**
- * struct iio_poll_func - poll function pair
- *
- * @private_data: data specific to device (passed into poll func)
- * @h: the function that is actually run on trigger
- * @thread: threaded interrupt part
- * @type: the type of interrupt (basically if oneshot)
- * @name: name used to identify the trigger consumer.
- * @irq: the corresponding irq as allocated from the
- * trigger pool
- * @timestamp: some devices need a timestamp grabbed as soon
- * as possible after the trigger - hence handler
- * passes it via here.
- **/
-struct iio_poll_func {
- void *private_data;
- irqreturn_t (*h)(int irq, void *p);
- irqreturn_t (*thread)(int irq, void *p);
- int type;
- char *name;
- int irq;
- s64 timestamp;
-};
static inline struct iio_trigger *to_iio_trigger(struct device *d)
{
@@ -92,14 +82,14 @@ static inline struct iio_trigger *to_iio_trigger(struct device *d)
static inline void iio_put_trigger(struct iio_trigger *trig)
{
+ module_put(trig->ops->owner);
put_device(&trig->dev);
- module_put(trig->owner);
};
static inline void iio_get_trigger(struct iio_trigger *trig)
{
- __module_get(trig->owner);
get_device(&trig->dev);
+ __module_get(trig->ops->owner);
};
/**
@@ -115,23 +105,6 @@ int iio_trigger_register(struct iio_trigger *trig_info);
void iio_trigger_unregister(struct iio_trigger *trig_info);
/**
- * iio_trigger_attach_poll_func() - add a function pair to be run on trigger
- * @trig: trigger to which the function pair are being added
- * @pf: poll function pair
- **/
-int iio_trigger_attach_poll_func(struct iio_trigger *trig,
- struct iio_poll_func *pf);
-
-/**
- * iio_trigger_dettach_poll_func() - remove function pair from those to be
- * run on trigger
- * @trig: trigger from which the function is being removed
- * @pf: poll function pair
- **/
-int iio_trigger_dettach_poll_func(struct iio_trigger *trig,
- struct iio_poll_func *pf);
-
-/**
* iio_trigger_poll() - called on a trigger occurring
* @trig: trigger which occurred
*
@@ -139,48 +112,9 @@ int iio_trigger_dettach_poll_func(struct iio_trigger *trig,
**/
void iio_trigger_poll(struct iio_trigger *trig, s64 time);
void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time);
-void iio_trigger_notify_done(struct iio_trigger *trig);
irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private);
-static inline int iio_trigger_get_irq(struct iio_trigger *trig)
-{
- int ret;
- mutex_lock(&trig->pool_lock);
- ret = bitmap_find_free_region(trig->pool,
- CONFIG_IIO_CONSUMERS_PER_TRIGGER,
- ilog2(1));
- mutex_unlock(&trig->pool_lock);
- if (ret >= 0)
- ret += trig->subirq_base;
-
- return ret;
-};
-
-static inline void iio_trigger_put_irq(struct iio_trigger *trig, int irq)
-{
- mutex_lock(&trig->pool_lock);
- clear_bit(irq - trig->subirq_base, trig->pool);
- mutex_unlock(&trig->pool_lock);
-};
-
-struct iio_poll_func
-*iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p),
- irqreturn_t (*thread)(int irq, void *p),
- int type,
- void *private,
- const char *fmt,
- ...);
-void iio_dealloc_pollfunc(struct iio_poll_func *pf);
-irqreturn_t iio_pollfunc_store_time(int irq, void *p);
-
-/*
- * Two functions for common case where all that happens is a pollfunc
- * is attached and detached from a trigger
- */
-int iio_triggered_ring_postenable(struct iio_dev *indio_dev);
-int iio_triggered_ring_predisable(struct iio_dev *indio_dev);
-
struct iio_trigger *iio_allocate_trigger(const char *fmt, ...)
__attribute__((format(printf, 1, 2)));
void iio_free_trigger(struct iio_trigger *trig);
diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
index 4f1729565582..243f38f80de1 100644
--- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
+++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
@@ -143,6 +143,10 @@ static int iio_bfin_tmr_get_number(int irq)
return -ENODEV;
}
+static const struct iio_trigger_ops iio_bfin_tmr_trigger_ops = {
+ owner = THIS_MODULE,
+};
+
static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
{
struct bfin_tmr_state *st;
@@ -175,7 +179,7 @@ static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
}
st->trig->private_data = st;
- st->trig->owner = THIS_MODULE;
+ st->trig->ops = &iio_bfin_tmr_trigger_ops;
st->trig->dev.groups = iio_bfin_tmr_trigger_attr_groups;
ret = iio_trigger_register(st->trig);
if (ret)
diff --git a/drivers/staging/iio/trigger/iio-trig-gpio.c b/drivers/staging/iio/trigger/iio-trig-gpio.c
index f1fb795e6410..f2a655981622 100644
--- a/drivers/staging/iio/trigger/iio-trig-gpio.c
+++ b/drivers/staging/iio/trigger/iio-trig-gpio.c
@@ -47,6 +47,10 @@ static irqreturn_t iio_gpio_trigger_poll(int irq, void *private)
return IRQ_HANDLED;
}
+static const struct iio_trigger_ops iio_gpio_trigger_ops = {
+ .owner = THIS_MODULE,
+};
+
static int iio_gpio_trigger_probe(struct platform_device *pdev)
{
struct iio_gpio_trigger_info *trig_info;
@@ -81,7 +85,7 @@ static int iio_gpio_trigger_probe(struct platform_device *pdev)
}
trig->private_data = trig_info;
trig_info->irq = irq;
- trig->owner = THIS_MODULE;
+ trig->ops = &iio_gpio_trigger_ops;
ret = request_irq(irq, iio_gpio_trigger_poll,
irqflags, trig->name, trig);
if (ret) {
diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
index 01cf7e20b515..d35d085da949 100644
--- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
@@ -96,6 +96,11 @@ static void iio_prtc_trigger_poll(void *private_data)
iio_trigger_poll(private_data, 0);
}
+static const struct iio_trigger_ops iio_prtc_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &iio_trig_periodic_rtc_set_state,
+};
+
static int iio_trig_periodic_rtc_probe(struct platform_device *dev)
{
char **pdata = dev->dev.platform_data;
@@ -121,7 +126,7 @@ static int iio_trig_periodic_rtc_probe(struct platform_device *dev)
}
trig->private_data = trig_info;
trig->owner = THIS_MODULE;
- trig->set_trigger_state = &iio_trig_periodic_rtc_set_state;
+ trig->ops = &iio_prtc_trigger_ops;
/* RTC access */
trig_info->rtc
= rtc_class_open(pdata[i]);
diff --git a/drivers/staging/iio/trigger/iio-trig-sysfs.c b/drivers/staging/iio/trigger/iio-trig-sysfs.c
index 47248cd1fa0d..174dc65709d5 100644
--- a/drivers/staging/iio/trigger/iio-trig-sysfs.c
+++ b/drivers/staging/iio/trigger/iio-trig-sysfs.c
@@ -77,9 +77,16 @@ static const struct attribute_group *iio_sysfs_trig_groups[] = {
NULL
};
+
+/* Nothing to actually do upon release */
+static void iio_trigger_sysfs_release(struct device *dev)
+{
+}
+
static struct device iio_sysfs_trig_dev = {
.bus = &iio_bus_type,
.groups = iio_sysfs_trig_groups,
+ .release = &iio_trigger_sysfs_release,
};
static ssize_t iio_sysfs_trigger_poll(struct device *dev,
@@ -107,6 +114,10 @@ static const struct attribute_group *iio_sysfs_trigger_attr_groups[] = {
NULL
};
+static const struct iio_trigger_ops iio_sysfs_trigger_ops = {
+ .owner = THIS_MODULE,
+};
+
static int iio_sysfs_trigger_probe(int id)
{
struct iio_sysfs_trig *t;
@@ -135,7 +146,7 @@ static int iio_sysfs_trigger_probe(int id)
}
t->trig->dev.groups = iio_sysfs_trigger_attr_groups;
- t->trig->owner = THIS_MODULE;
+ t->trig->ops = &iio_sysfs_trigger_ops;
t->trig->dev.parent = &iio_sysfs_trig_dev;
ret = iio_trigger_register(t->trig);
diff --git a/drivers/staging/iio/trigger_consumer.h b/drivers/staging/iio/trigger_consumer.h
index 9d52d9637777..418e0bd5f4ce 100644
--- a/drivers/staging/iio/trigger_consumer.h
+++ b/drivers/staging/iio/trigger_consumer.h
@@ -1,47 +1,52 @@
-
-/* The industrial I/O core, trigger consumer handling functions
+/* The industrial I/O core, trigger consumer functions
*
- * Copyright (c) 2008 Jonathan Cameron
+ * Copyright (c) 2008-2011 Jonathan Cameron
*
* 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.
*/
-#ifdef CONFIG_IIO_TRIGGER
-/**
- * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers
- * @dev_info: iio_dev associated with the device that will consume the trigger
- **/
-int iio_device_register_trigger_consumer(struct iio_dev *dev_info);
-
-/**
- * iio_device_unregister_trigger_consumer() - reverse the registration process
- * @dev_info: iio_dev associated with the device that consumed the trigger
- **/
-int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info);
-
-#else
-
/**
- * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers
- * @dev_info: iio_dev associated with the device that will consume the trigger
- **/
-static int iio_device_register_trigger_consumer(struct iio_dev *dev_info)
-{
- return 0;
-};
-
-/**
- * iio_device_unregister_trigger_consumer() - reverse the registration process
- * @dev_info: iio_dev associated with the device that consumed the trigger
+ * struct iio_poll_func - poll function pair
+ *
+ * @indio_dev: data specific to device (passed into poll func)
+ * @h: the function that is actually run on trigger
+ * @thread: threaded interrupt part
+ * @type: the type of interrupt (basically if oneshot)
+ * @name: name used to identify the trigger consumer.
+ * @irq: the corresponding irq as allocated from the
+ * trigger pool
+ * @timestamp: some devices need a timestamp grabbed as soon
+ * as possible after the trigger - hence handler
+ * passes it via here.
**/
-static int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info)
-{
- return 0;
+struct iio_poll_func {
+ struct iio_dev *indio_dev;
+ irqreturn_t (*h)(int irq, void *p);
+ irqreturn_t (*thread)(int irq, void *p);
+ int type;
+ char *name;
+ int irq;
+ s64 timestamp;
};
-#endif /* CONFIG_TRIGGER_CONSUMER */
+struct iio_poll_func
+*iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p),
+ irqreturn_t (*thread)(int irq, void *p),
+ int type,
+ struct iio_dev *indio_dev,
+ const char *fmt,
+ ...);
+void iio_dealloc_pollfunc(struct iio_poll_func *pf);
+irqreturn_t iio_pollfunc_store_time(int irq, void *p);
+void iio_trigger_notify_done(struct iio_trigger *trig);
+/*
+ * Two functions for common case where all that happens is a pollfunc
+ * is attached and detached from a trigger
+ */
+int iio_triggered_ring_postenable(struct iio_dev *indio_dev);
+int iio_triggered_ring_predisable(struct iio_dev *indio_dev);