aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/iio
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2011-06-23 20:20:51 +0000
committerNicholas Bellinger <nab@linux-iscsi.org>2011-06-23 20:20:51 +0000
commit74d83b7eedab14e4b963a2220ff76f98fa6d4cb8 (patch)
treeff4b10ebd9cf1a057c4b1a703732858a539faff7 /drivers/staging/iio
parent[SCSI] target: Convert TASK_ATTR to scsi_tcq.h definitions (diff)
parentLinux 3.0-rc4 (diff)
downloadlinux-dev-74d83b7eedab14e4b963a2220ff76f98fa6d4cb8.tar.xz
linux-dev-74d83b7eedab14e4b963a2220ff76f98fa6d4cb8.zip
Merge tag 'v3.0-rc4' of /pub/scm/linux/kernel/git/torvalds/linux-2.6 into for-linus
Diffstat (limited to 'drivers/staging/iio')
-rw-r--r--drivers/staging/iio/Documentation/device.txt78
-rw-r--r--drivers/staging/iio/Documentation/generic_buffer.c95
-rw-r--r--drivers/staging/iio/Documentation/iio_utils.h20
-rw-r--r--drivers/staging/iio/Documentation/overview.txt19
-rw-r--r--drivers/staging/iio/Documentation/ring.txt44
-rw-r--r--drivers/staging/iio/Documentation/sysfs-bus-iio13
-rw-r--r--drivers/staging/iio/Documentation/sysfs-bus-iio-light13
-rw-r--r--drivers/staging/iio/Documentation/sysfs-bus-iio-light-tsl258320
-rw-r--r--drivers/staging/iio/Documentation/trigger.txt16
-rw-r--r--drivers/staging/iio/Documentation/userspace.txt12
-rw-r--r--drivers/staging/iio/Kconfig15
-rw-r--r--drivers/staging/iio/accel/adis16201.h11
-rw-r--r--drivers/staging/iio/accel/adis16201_core.c489
-rw-r--r--drivers/staging/iio/accel/adis16201_ring.c146
-rw-r--r--drivers/staging/iio/accel/adis16201_trigger.c82
-rw-r--r--drivers/staging/iio/accel/adis16203.h20
-rw-r--r--drivers/staging/iio/accel/adis16203_core.c411
-rw-r--r--drivers/staging/iio/accel/adis16203_ring.c123
-rw-r--r--drivers/staging/iio/accel/adis16203_trigger.c83
-rw-r--r--drivers/staging/iio/accel/adis16204.h18
-rw-r--r--drivers/staging/iio/accel/adis16204_core.c434
-rw-r--r--drivers/staging/iio/accel/adis16204_ring.c126
-rw-r--r--drivers/staging/iio/accel/adis16204_trigger.c83
-rw-r--r--drivers/staging/iio/accel/adis16209.h6
-rw-r--r--drivers/staging/iio/accel/adis16209_core.c468
-rw-r--r--drivers/staging/iio/accel/adis16209_ring.c143
-rw-r--r--drivers/staging/iio/accel/adis16209_trigger.c77
-rw-r--r--drivers/staging/iio/accel/adis16220_core.c13
-rw-r--r--drivers/staging/iio/accel/adis16240.h7
-rw-r--r--drivers/staging/iio/accel/adis16240_core.c390
-rw-r--r--drivers/staging/iio/accel/adis16240_ring.c131
-rw-r--r--drivers/staging/iio/accel/adis16240_trigger.c78
-rw-r--r--drivers/staging/iio/accel/kxsd9.c14
-rw-r--r--drivers/staging/iio/accel/lis3l02dq.h46
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_core.c844
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_ring.c504
-rw-r--r--drivers/staging/iio/accel/sca3000.h76
-rw-r--r--drivers/staging/iio/accel/sca3000_core.c955
-rw-r--r--drivers/staging/iio/accel/sca3000_ring.c269
-rw-r--r--drivers/staging/iio/adc/Kconfig60
-rw-r--r--drivers/staging/iio/adc/Makefile1
-rw-r--r--drivers/staging/iio/adc/ad7150.c178
-rw-r--r--drivers/staging/iio/adc/ad7152.c33
-rw-r--r--drivers/staging/iio/adc/ad7291.c502
-rw-r--r--drivers/staging/iio/adc/ad7298.h12
-rw-r--r--drivers/staging/iio/adc/ad7298_core.c242
-rw-r--r--drivers/staging/iio/adc/ad7298_ring.c134
-rw-r--r--drivers/staging/iio/adc/ad7314.c35
-rw-r--r--drivers/staging/iio/adc/ad7476.h7
-rw-r--r--drivers/staging/iio/adc/ad7476_core.c173
-rw-r--r--drivers/staging/iio/adc/ad7476_ring.c127
-rw-r--r--drivers/staging/iio/adc/ad7606.h20
-rw-r--r--drivers/staging/iio/adc/ad7606_core.c300
-rw-r--r--drivers/staging/iio/adc/ad7606_par.c30
-rw-r--r--drivers/staging/iio/adc/ad7606_ring.c152
-rw-r--r--drivers/staging/iio/adc/ad7606_spi.c24
-rw-r--r--drivers/staging/iio/adc/ad7745.c121
-rw-r--r--drivers/staging/iio/adc/ad7780.c301
-rw-r--r--drivers/staging/iio/adc/ad7780.h30
-rw-r--r--drivers/staging/iio/adc/ad7816.c111
-rw-r--r--drivers/staging/iio/adc/ad7887.h17
-rw-r--r--drivers/staging/iio/adc/ad7887_core.c200
-rw-r--r--drivers/staging/iio/adc/ad7887_ring.c156
-rw-r--r--drivers/staging/iio/adc/ad799x.h33
-rw-r--r--drivers/staging/iio/adc/ad799x_core.c859
-rw-r--r--drivers/staging/iio/adc/ad799x_ring.c93
-rw-r--r--drivers/staging/iio/adc/adt7310.c206
-rw-r--r--drivers/staging/iio/adc/adt7410.c201
-rw-r--r--drivers/staging/iio/adc/adt75.c180
-rw-r--r--drivers/staging/iio/adc/max1363.h93
-rw-r--r--drivers/staging/iio/adc/max1363_core.c1945
-rw-r--r--drivers/staging/iio/adc/max1363_ring.c109
-rw-r--r--drivers/staging/iio/addac/adt7316.c502
-rw-r--r--drivers/staging/iio/chrdev.h44
-rw-r--r--drivers/staging/iio/dac/Kconfig21
-rw-r--r--drivers/staging/iio/dac/Makefile2
-rw-r--r--drivers/staging/iio/dac/ad5446.c30
-rw-r--r--drivers/staging/iio/dac/ad5446.h1
-rw-r--r--drivers/staging/iio/dac/ad5504.c404
-rw-r--r--drivers/staging/iio/dac/ad5504.h70
-rw-r--r--drivers/staging/iio/dac/ad5624r_spi.c23
-rw-r--r--drivers/staging/iio/dac/ad5791.c444
-rw-r--r--drivers/staging/iio/dac/ad5791.h116
-rw-r--r--drivers/staging/iio/dac/max517.c17
-rw-r--r--drivers/staging/iio/dds/Kconfig4
-rw-r--r--drivers/staging/iio/dds/ad5930.c14
-rw-r--r--drivers/staging/iio/dds/ad9832.c23
-rw-r--r--drivers/staging/iio/dds/ad9834.c54
-rw-r--r--drivers/staging/iio/dds/ad9834.h8
-rw-r--r--drivers/staging/iio/dds/ad9850.c12
-rw-r--r--drivers/staging/iio/dds/ad9852.c12
-rw-r--r--drivers/staging/iio/dds/ad9910.c12
-rw-r--r--drivers/staging/iio/dds/ad9951.c12
-rw-r--r--drivers/staging/iio/gyro/Kconfig10
-rw-r--r--drivers/staging/iio/gyro/Makefile3
-rw-r--r--drivers/staging/iio/gyro/adis16060_core.c10
-rw-r--r--drivers/staging/iio/gyro/adis16080_core.c13
-rw-r--r--drivers/staging/iio/gyro/adis16130_core.c14
-rw-r--r--drivers/staging/iio/gyro/adis16260.h7
-rw-r--r--drivers/staging/iio/gyro/adis16260_core.c477
-rw-r--r--drivers/staging/iio/gyro/adis16260_ring.c124
-rw-r--r--drivers/staging/iio/gyro/adis16260_trigger.c85
-rw-r--r--drivers/staging/iio/gyro/adxrs450.h58
-rw-r--r--drivers/staging/iio/gyro/adxrs450_core.c455
-rw-r--r--drivers/staging/iio/gyro/gyro.h3
-rw-r--r--drivers/staging/iio/iio.h356
-rw-r--r--drivers/staging/iio/imu/Kconfig26
-rw-r--r--drivers/staging/iio/imu/Makefile8
-rw-r--r--drivers/staging/iio/imu/adis16300.h184
-rw-r--r--drivers/staging/iio/imu/adis16300_core.c756
-rw-r--r--drivers/staging/iio/imu/adis16300_ring.c238
-rw-r--r--drivers/staging/iio/imu/adis16300_trigger.c125
-rw-r--r--drivers/staging/iio/imu/adis16350.h177
-rw-r--r--drivers/staging/iio/imu/adis16350_core.c757
-rw-r--r--drivers/staging/iio/imu/adis16350_ring.c236
-rw-r--r--drivers/staging/iio/imu/adis16350_trigger.c125
-rw-r--r--drivers/staging/iio/imu/adis16400.h38
-rw-r--r--drivers/staging/iio/imu/adis16400_core.c731
-rw-r--r--drivers/staging/iio/imu/adis16400_ring.c237
-rw-r--r--drivers/staging/iio/imu/adis16400_trigger.c100
-rw-r--r--drivers/staging/iio/industrialio-core.c943
-rw-r--r--drivers/staging/iio/industrialio-ring.c587
-rw-r--r--drivers/staging/iio/industrialio-trigger.c300
-rw-r--r--drivers/staging/iio/kfifo_buf.c63
-rw-r--r--drivers/staging/iio/kfifo_buf.h40
-rw-r--r--drivers/staging/iio/light/Kconfig28
-rw-r--r--drivers/staging/iio/light/Makefile1
-rw-r--r--drivers/staging/iio/light/isl29018.c23
-rw-r--r--drivers/staging/iio/light/tsl2563.c427
-rw-r--r--drivers/staging/iio/light/tsl2583.c964
-rw-r--r--drivers/staging/iio/magnetometer/ak8975.c130
-rw-r--r--drivers/staging/iio/magnetometer/hmc5843.c10
-rw-r--r--drivers/staging/iio/meter/ade7753.c14
-rw-r--r--drivers/staging/iio/meter/ade7754.c14
-rw-r--r--drivers/staging/iio/meter/ade7758.h71
-rw-r--r--drivers/staging/iio/meter/ade7758_core.c366
-rw-r--r--drivers/staging/iio/meter/ade7758_ring.c281
-rw-r--r--drivers/staging/iio/meter/ade7758_trigger.c95
-rw-r--r--drivers/staging/iio/meter/ade7759.c15
-rw-r--r--drivers/staging/iio/meter/ade7854.c10
-rw-r--r--drivers/staging/iio/resolver/ad2s120x.c13
-rw-r--r--drivers/staging/iio/resolver/ad2s1210.c12
-rw-r--r--drivers/staging/iio/resolver/ad2s90.c12
-rw-r--r--drivers/staging/iio/ring_generic.h293
-rw-r--r--drivers/staging/iio/ring_sw.c205
-rw-r--r--drivers/staging/iio/ring_sw.h196
-rw-r--r--drivers/staging/iio/sysfs.h184
-rw-r--r--drivers/staging/iio/trigger.h116
-rw-r--r--drivers/staging/iio/trigger/Kconfig1
-rw-r--r--drivers/staging/iio/trigger/iio-trig-bfin-timer.c22
-rw-r--r--drivers/staging/iio/trigger/iio-trig-gpio.c25
-rw-r--r--drivers/staging/iio/trigger/iio-trig-periodic-rtc.c24
-rw-r--r--drivers/staging/iio/trigger/iio-trig-sysfs.c169
153 files changed, 11865 insertions, 14044 deletions
diff --git a/drivers/staging/iio/Documentation/device.txt b/drivers/staging/iio/Documentation/device.txt
index 69d9570f29fc..1abb80cb884e 100644
--- a/drivers/staging/iio/Documentation/device.txt
+++ b/drivers/staging/iio/Documentation/device.txt
@@ -8,34 +8,66 @@ The crucial structure for device drivers in iio is iio_dev.
First allocate one using:
-struct iio_dev *indio_dev = iio_allocate_device();
+struct iio_dev *indio_dev = iio_allocate_device(sizeof(struct chip_state));
+where chip_state is a structure of local state data for this instance of
+the chip.
-Then fill in the following:
-
-indio_dev->dev.parent
- the struct device associated with the underlying hardware.
-
-indio_dev->num_interrupt_lines
- number of event triggering hardware lines the device has.
+That data can be accessed using iio_priv(struct iio_dev *)
-indio_dev->event_attrs
- attributes used to enable / disable hardware events - note the
- attributes are embedded in iio_event_attr structures with an
- associated iio_event_handler which may or may note be shared.
- If num_interrupt_lines = 0, then no need to fill this in.
-
-indio_dev->attrs
- general attributes such as polled access to device channels.
+Then fill in the following:
-indio_dev->dev_data
- private device specific data.
+- indio_dev->dev.parent
+ Struct device associated with the underlying hardware.
+- indio_dev->name
+ Name of the device being driven - made available as the name
+ attribute in sysfs.
-indio_dev->driver_module
- typically set to THIS_MODULE. Used to specify ownership of some
- iio created resources.
+- indio_dev->info
+ pointer to a structure with elements that tend to be fixed for
+ large sets of different parts supported by a given driver.
+ This contains:
+ * info->driver_module:
+ Set to THIS_MODULE. Used to ensure correct ownership
+ of various resources allocate by the core.
+ * info->num_interrupt_lines:
+ Number of event triggering hardware lines the device has.
+ * info->event_attrs:
+ Attributes used to enable / disable hardware events.
+ * info->attrs:
+ General device attributes. Typically used for the weird
+ and the wonderful bits not covered by the channel specification.
+ * info->read_raw:
+ Raw data reading function. Used for both raw channel access
+ and for associate parameters such as offsets and scales.
+ * info->write_raw:
+ Raw value writing function. Used for writable device values such
+ as DAC values and caliboffset.
+ * info->read_event_config:
+ Typically only set if there are some interrupt lines. This
+ is used to read if an on sensor event detector is enabled.
+ * info->write_event_config:
+ Enable / disable an on sensor event detector.
+ * info->read_event_value:
+ Read value associated with on sensor event detectors. Note that
+ the meaning of the returned value is dependent on the event
+ type.
+ * info->write_event_value:
+ Write the value associated with on sensor event detectors. E.g.
+ a threshold above which an interrupt occurs. Note that the
+ meaning of the value to be set is event type dependant.
-indio_dev->modes
- whether direct access and / or ring buffer access is supported.
+- indio_dev->modes:
+ Specify whether direct access and / or ring buffer access is supported.
+- indio_dev->ring:
+ An optional associated buffer.
+- indio_dev->pollfunc:
+ Poll function related elements. This controls what occurs when a trigger
+ to which this device is attached sends and event.
+- indio_dev->channels:
+ Specification of device channels. Most attributes etc are built
+ form this spec.
+- indio_dev->num_channels:
+ How many channels are there?
Once these are set up, a call to iio_device_register(indio_dev),
will register the device with the iio core.
diff --git a/drivers/staging/iio/Documentation/generic_buffer.c b/drivers/staging/iio/Documentation/generic_buffer.c
index 3cc18ab4ebfd..f82894f42d27 100644
--- a/drivers/staging/iio/Documentation/generic_buffer.c
+++ b/drivers/staging/iio/Documentation/generic_buffer.c
@@ -27,6 +27,7 @@
#include <sys/dir.h>
#include <linux/types.h>
#include <string.h>
+#include <poll.h>
#include "iio_utils.h"
/**
@@ -53,6 +54,24 @@ int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
return bytes;
}
+void print2byte(int input, struct iio_channel_info *info)
+{
+ /* shift before conversion to avoid sign extension
+ of left aligned data */
+ input = input >> info->shift;
+ if (info->is_signed) {
+ int16_t val = input;
+ val &= (1 << info->bits_used) - 1;
+ val = (int16_t)(val << (16 - info->bits_used)) >>
+ (16 - info->bits_used);
+ printf("%05f ", val,
+ (float)(val + info->offset)*info->scale);
+ } else {
+ uint16_t val = input;
+ val &= (1 << info->bits_used) - 1;
+ printf("%05f ", ((float)val + info->offset)*info->scale);
+ }
+}
/**
* process_scan() - print out the values in SI units
* @data: pointer to the start of the scan
@@ -70,25 +89,8 @@ void process_scan(char *data,
switch (infoarray[k].bytes) {
/* only a few cases implemented so far */
case 2:
- if (infoarray[k].is_signed) {
- int16_t val = *(int16_t *)
- (data
- + infoarray[k].location);
- if ((val >> infoarray[k].bits_used) & 1)
- val = (val & infoarray[k].mask) |
- ~infoarray[k].mask;
- printf("%05f ", ((float)val +
- infoarray[k].offset)*
- infoarray[k].scale);
- } else {
- uint16_t val = *(uint16_t *)
- (data +
- infoarray[k].location);
- val = (val & infoarray[k].mask);
- printf("%05f ", ((float)val +
- infoarray[k].offset)*
- infoarray[k].scale);
- }
+ print2byte(*(uint16_t *)(data + infoarray[k].location),
+ &infoarray[k]);
break;
case 8:
if (infoarray[k].is_signed) {
@@ -132,10 +134,9 @@ int main(int argc, char **argv)
int datardytrigger = 1;
char *data;
- size_t read_size;
- struct iio_event_data dat;
+ ssize_t read_size;
int dev_num, trig_num;
- char *buffer_access, *buffer_event;
+ char *buffer_access;
int scan_size;
int noevents = 0;
char *dummy;
@@ -210,7 +211,7 @@ int main(int argc, char **argv)
*/
ret = build_channel_array(dev_dir_name, &infoarray, &num_channels);
if (ret) {
- printf("Problem reading scan element information \n");
+ printf("Problem reading scan element information\n");
goto error_free_triggername;
}
@@ -251,54 +252,32 @@ int main(int argc, char **argv)
}
ret = asprintf(&buffer_access,
- "/dev/device%d:buffer0:access0",
+ "/dev/device%d:buffer0",
dev_num);
if (ret < 0) {
ret = -ENOMEM;
goto error_free_data;
}
- ret = asprintf(&buffer_event, "/dev/device%d:buffer0:event0", dev_num);
- if (ret < 0) {
- ret = -ENOMEM;
- goto error_free_buffer_access;
- }
/* Attempt to open non blocking the access dev */
fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
if (fp == -1) { /*If it isn't there make the node */
printf("Failed to open %s\n", buffer_access);
ret = -errno;
- goto error_free_buffer_event;
- }
- /* Attempt to open the event access dev (blocking this time) */
- fp_ev = fopen(buffer_event, "rb");
- if (fp_ev == NULL) {
- printf("Failed to open %s\n", buffer_event);
- ret = -errno;
- goto error_close_buffer_access;
+ goto error_free_buffer_access;
}
/* Wait for events 10 times */
for (j = 0; j < num_loops; j++) {
if (!noevents) {
- read_size = fread(&dat,
- 1,
- sizeof(struct iio_event_data),
- fp_ev);
- switch (dat.id) {
- case IIO_EVENT_CODE_RING_100_FULL:
- toread = buf_len;
- break;
- case IIO_EVENT_CODE_RING_75_FULL:
- toread = buf_len*3/4;
- break;
- case IIO_EVENT_CODE_RING_50_FULL:
- toread = buf_len/2;
- break;
- default:
- printf("Unexpecteded event code\n");
- continue;
- }
+ struct pollfd pfd = {
+ .fd = fp,
+ .events = POLLIN,
+ };
+
+ poll(&pfd, 1, -1);
+ toread = buf_len;
+
} else {
usleep(timedelay);
toread = 64;
@@ -320,22 +299,18 @@ int main(int argc, char **argv)
/* Stop the ring buffer */
ret = write_sysfs_int("enable", buf_dir_name, 0);
if (ret < 0)
- goto error_close_buffer_event;
+ goto error_close_buffer_access;
/* Disconnect from the trigger - just write a dummy name.*/
write_sysfs_string("trigger/current_trigger",
dev_dir_name, "NULL");
-error_close_buffer_event:
- fclose(fp_ev);
error_close_buffer_access:
close(fp);
error_free_data:
free(data);
error_free_buffer_access:
free(buffer_access);
-error_free_buffer_event:
- free(buffer_event);
error_free_buf_dir_name:
free(buf_dir_name);
error_free_triggername:
diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h
index fd78e4ff99ae..150f44073631 100644
--- a/drivers/staging/iio/Documentation/iio_utils.h
+++ b/drivers/staging/iio/Documentation/iio_utils.h
@@ -16,25 +16,11 @@
#define IIO_MAX_NAME_LENGTH 30
-#define IIO_EV_CLASS_BUFFER 0
-#define IIO_BUFFER_EVENT_CODE(code) \
- (IIO_EV_CLASS_BUFFER | (code << 8))
-
-#define IIO_EVENT_CODE_RING_50_FULL IIO_BUFFER_EVENT_CODE(0)
-#define IIO_EVENT_CODE_RING_75_FULL IIO_BUFFER_EVENT_CODE(1)
-#define IIO_EVENT_CODE_RING_100_FULL IIO_BUFFER_EVENT_CODE(2)
-
-
#define FORMAT_SCAN_ELEMENTS_DIR "%s:buffer0/scan_elements"
#define FORMAT_TYPE_FILE "%s_type"
const char *iio_dir = "/sys/bus/iio/devices/";
-struct iio_event_data {
- int id;
- __s64 timestamp;
-};
-
/**
* iioutils_break_up_name() - extract generic name from full channel name
* @full_name: the full channel name
@@ -85,6 +71,7 @@ struct iio_channel_info {
unsigned index;
unsigned bytes;
unsigned bits_used;
+ unsigned shift;
uint64_t mask;
unsigned is_signed;
unsigned enabled;
@@ -103,6 +90,7 @@ struct iio_channel_info {
inline int iioutils_get_type(unsigned *is_signed,
unsigned *bytes,
unsigned *bits_used,
+ unsigned *shift,
uint64_t *mask,
const char *device_dir,
const char *name,
@@ -157,7 +145,8 @@ inline int iioutils_get_type(unsigned *is_signed,
goto error_free_filename;
}
fscanf(sysfsfp,
- "%c%u/%u", &signchar, bits_used, &padint);
+ "%c%u/%u>>%u", &signchar, bits_used,
+ &padint, shift);
*bytes = padint / 8;
if (*bits_used == 64)
*mask = ~0;
@@ -395,6 +384,7 @@ inline int build_channel_array(const char *device_dir,
ret = iioutils_get_type(&current->is_signed,
&current->bytes,
&current->bits_used,
+ &current->shift,
&current->mask,
device_dir,
current->name,
diff --git a/drivers/staging/iio/Documentation/overview.txt b/drivers/staging/iio/Documentation/overview.txt
index d97106cb2b96..afc39ecde9ca 100644
--- a/drivers/staging/iio/Documentation/overview.txt
+++ b/drivers/staging/iio/Documentation/overview.txt
@@ -3,8 +3,7 @@ Overview of IIO
The Industrial I/O subsystem is intended to provide support for devices
that in some sense are analog to digital converters (ADCs). As many
actual devices combine some ADCs with digital to analog converters
-(DACs) the intention is to add that functionality at a future date
-(hence the name).
+(DACs) that functionality is also supported.
The aim is to fill the gap between the somewhat similar hwmon and
input subsystems. Hwmon is very much directed at low sample rate
@@ -31,32 +30,28 @@ event must be accessed via polling.
Note: A given device may have one or more event channel. These events are
turned on or off (if possible) via sysfs interfaces.
-* Hardware ring buffer support. Some recent sensors have included
+* Hardware buffer support. Some recent sensors have included
fifo / ring buffers on the sensor chip. These greatly reduce the load
on the host CPU by buffering relatively large numbers of data samples
based on an internal sampling clock. Examples include VTI SCA3000
-series and Analog Device ADXL345 accelerometers. Each ring buffer
-typically has an event chrdev (similar to the more general ones above)
-to pass on events such as buffer 50% full and an access chrdev via
-which the raw data it self may be read back.
+series and Analog Device ADXL345 accelerometers. Each buffer supports
+polling to establish when data is available.
-* Trigger and software ring buffer support. In many data analysis
+* Trigger and software buffer support. In many data analysis
applications it it useful to be able to capture data based on some
external signal (trigger). These triggers might be a data ready
signal, a gpio line connected to some external system or an on
processor periodic interrupt. A single trigger may initialize data
capture or reading from a number of sensors. These triggers are
-used in IIO to fill software ring buffers acting in a very similar
+used in IIO to fill software buffers acting in a very similar
fashion to the hardware buffers described above.
Other documentation:
-userspace.txt - overview of ring buffer reading from userspace.
-
device.txt - elements of a typical device driver.
trigger.txt - elements of a typical trigger driver.
-ring.txt - additional elements required for ring buffer support.
+ring.txt - additional elements required for buffer support.
sysfs-bus-iio - abi documentation file.
diff --git a/drivers/staging/iio/Documentation/ring.txt b/drivers/staging/iio/Documentation/ring.txt
index 3696c364e644..7e99ef2b7bc0 100644
--- a/drivers/staging/iio/Documentation/ring.txt
+++ b/drivers/staging/iio/Documentation/ring.txt
@@ -1,57 +1,55 @@
-Ring buffer support within IIO
+Buffer support within IIO
This document is intended as a general overview of the functionality
-a ring buffer may supply and how it is specified within IIO. For more
-specific information on a given ring buffer implementation, see the
-comments in the source code. Note that the intention is to allow
-some drivers to specify ring buffers choice at probe or runtime, but
-for now the selection is hard coded within a given driver.
+a buffer may supply and how it is specified within IIO. For more
+specific information on a given buffer implementation, see the
+comments in the source code. Note that some drivers allow buffer
+implementation to be selected at compile time via Kconfig options.
-A given ring buffer implementation typically embedded a struct
+A given buffer implementation typically embeds a struct
iio_ring_buffer and it is a pointer to this that is provided to the
IIO core. Access to the embedding structure is typically done via
container_of functions.
-struct iio_ring_buffer contains 4 function pointers
-(preenable, postenable, predisable, postdisable).
-These are used to perform implementation specific steps on either side
-of the core changing it's current mode to indicate that the ring buffer
+struct iio_ring_buffer contains a struct iio_ring_setup_ops *setup_ops
+which in turn contains the 4 function pointers
+(preenable, postenable, predisable and postdisable).
+These are used to perform device specific steps on either side
+of the core changing it's current mode to indicate that the buffer
is enabled or disabled (along with enabling triggering etc as appropriate).
Also in struct iio_ring_buffer is a struct iio_ring_access_funcs.
The function pointers within here are used to allow the core to handle
-as much ring buffer functionality as possible. Note almost all of these
+as much buffer functionality as possible. Note almost all of these
are optional.
mark_in_use, unmark_in_use
- Basically indicate that not changes should be made to the ring
- buffer state that will effect the form of the data being captures
- (e.g. scan elements or length)
+ Basically indicate that not changes should be made to the buffer state that
+ will effect the form of the data being captures (e.g. scan elements or length)
store_to
- If possible, push data to ring buffer.
+ If possible, push data to the buffer.
read_last
- If possible get the most recent entry from the buffer (without removal).
+ If possible, get the most recent scan from the buffer (without removal).
This provides polling like functionality whilst the ring buffering is in
use without a separate read from the device.
-rip_lots
- The primary ring buffer reading function. Note that it may well not return
- as much data as requested. The deadoffset is used to indicate that some
- initial data in the data array is not guaranteed to be valid.
+rip_first_n
+ The primary buffer reading function. Note that it may well not return
+ as much data as requested.
mark_param_changed
Used to indicate that something has changed. Used in conjunction with
request_update
If parameters have changed that require reinitialization or configuration of
- the ring buffer this will trigger it.
+ the buffer this will trigger it.
get_bytes_per_datum, set_bytes_per_datum
Get/set the number of bytes for a complete scan. (All samples + timestamp)
get_length / set_length
- Get/set the number of sample sets that may be held by the buffer.
+ Get/set the number of complete scans that may be held by the buffer.
is_enabled
Query if ring buffer is in use
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio b/drivers/staging/iio/Documentation/sysfs-bus-iio
index 4915aee14d88..467c49a47258 100644
--- a/drivers/staging/iio/Documentation/sysfs-bus-iio
+++ b/drivers/staging/iio/Documentation/sysfs-bus-iio
@@ -6,6 +6,12 @@ Description:
Corresponds to a grouping of sensor channels. X is the IIO
index of the device.
+What: /sys/bus/iio/devices/device[n]/power_state
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ This property gets/sets the device power state.
+
What: /sys/bus/iio/devices/triggerX
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
@@ -698,3 +704,10 @@ Description:
with all _en attributes to establish which channels are present,
and the relevant _type attributes to establish the data storage
format.
+
+What: /sys/bus/iio/devices/deviceX/gyro_z_quadrature_correction_raw
+KernelVersion: 2.6.38
+Contact: linux-iio@xxxxxxxxxxxxxxx
+Description:
+ This attribute is used to read the amount of quadrature error
+ present in the device at a given time.
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-light b/drivers/staging/iio/Documentation/sysfs-bus-iio-light
index 5d84856dc14a..21d277405816 100644
--- a/drivers/staging/iio/Documentation/sysfs-bus-iio-light
+++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-light
@@ -62,3 +62,16 @@ Description:
sensing mode. This value should be the output from a reading
and if expressed in SI units, should include _input. If this
value is not in SI units, then it should include _raw.
+
+What: /sys/bus/iio/devices/device[n]/illuminance0_target
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ This property gets/sets the last known external
+ lux measurement used in/for calibration.
+
+What: /sys/bus/iio/devices/device[n]/illuminance0_integration_time
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ This property gets/sets the sensors ADC analog integration time.
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-light-tsl2583 b/drivers/staging/iio/Documentation/sysfs-bus-iio-light-tsl2583
new file mode 100644
index 000000000000..660781df409f
--- /dev/null
+++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-light-tsl2583
@@ -0,0 +1,20 @@
+What: /sys/bus/iio/devices/device[n]/lux_table
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ This property gets/sets the table of coefficients
+ used in calculating illuminance in lux.
+
+What: /sys/bus/iio/devices/device[n]/illuminance0_calibrate
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ This property causes an internal calibration of the als gain trim
+ value which is later used in calculating illuminance in lux.
+
+What: /sys/bus/iio/devices/device[n]/illuminance0_input_target
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ This property is the known externally illuminance (in lux).
+ It is used in the process of calibrating the device accuracy.
diff --git a/drivers/staging/iio/Documentation/trigger.txt b/drivers/staging/iio/Documentation/trigger.txt
index 650157f5c9de..fc2012ebc100 100644
--- a/drivers/staging/iio/Documentation/trigger.txt
+++ b/drivers/staging/iio/Documentation/trigger.txt
@@ -5,14 +5,11 @@ an IIO device. Whilst this can create device specific complexities
such triggers are registered with the core in the same way as
stand-alone triggers.
-struct iio_trig *trig = iio_allocate_trigger();
+struct iio_trig *trig = iio_allocate_trigger("<trigger format string>", ...);
allocates a trigger structure. The key elements to then fill in within
a driver are:
-trig->control_attrs
- Any sysfs attributes needed to control parameters of the trigger
-
trig->private_data
Device specific private data.
@@ -20,8 +17,12 @@ trig->owner
Typically set to THIS_MODULE. Used to ensure correct
ownership of core allocated resources.
-trig->name
- A unique name for the trigger.
+trig->set_trigger_state:
+ Function that enables / disables the underlying source of the trigger.
+
+There is also a
+trig->alloc_list which is useful for drivers that allocate multiple
+triggers to keep track of what they have created.
When these have been set call:
@@ -30,9 +31,8 @@ iio_trigger_register(trig);
to register the trigger with the core, making it available to trigger
consumers.
-
Trigger Consumers
-Currently triggers are only used for the filling of software ring
+Currently triggers are only used for the filling of software
buffers and as such any device supporting INDIO_RING_TRIGGERED has the
consumer interface automatically created.
diff --git a/drivers/staging/iio/Documentation/userspace.txt b/drivers/staging/iio/Documentation/userspace.txt
deleted file mode 100644
index ff06e5dc7188..000000000000
--- a/drivers/staging/iio/Documentation/userspace.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-Userspace access to IIO
-
-The sysfs attributes are documented in sysfs-bus-iio.
-
-Udev will create the following entries under /dev by default:
-
-device0:buffer0:access0 - ring access chrdev
-device0:buffer0:event0 - ring event chrdev
-device0:event0 - general event chrdev.
-
-The files, lis3l02dqbuffersimple.c and iio_utils.h in this directory provide an example
-of how to use the ring buffer and event interfaces.
diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig
index 6775bf90e2f1..f96d5b5d5141 100644
--- a/drivers/staging/iio/Kconfig
+++ b/drivers/staging/iio/Kconfig
@@ -5,17 +5,17 @@
menuconfig IIO
tristate "Industrial I/O support"
depends on !S390
- ---help---
+ help
The industrial I/O subsystem provides a unified framework for
drivers for many different types of embedded sensors using a
number of different physical interfaces (i2c, spi, etc). See
- Documentation/industrialio for more information.
+ drivers/staging/iio/Documentation for more information.
if IIO
config IIO_RING_BUFFER
- bool "Enable ring buffer support within IIO"
+ bool "Enable buffer support within IIO"
help
- Provide core support for various ring buffer based data
+ Provide core support for various buffer based data
acquisition methods.
if IIO_RING_BUFFER
@@ -48,6 +48,13 @@ config IIO_TRIGGER
ring buffers. The triggers are effectively a 'capture
data now' interrupt.
+config IIO_CONSUMERS_PER_TRIGGER
+ int "Maximum number of consumers per trigger"
+ depends on IIO_TRIGGER
+ default "2"
+ help
+ This value controls the maximum number of consumers that a
+ given trigger may handle. Default is 2.
source "drivers/staging/iio/accel/Kconfig"
source "drivers/staging/iio/adc/Kconfig"
diff --git a/drivers/staging/iio/accel/adis16201.h b/drivers/staging/iio/accel/adis16201.h
index 23fe54d09d12..4cc1a5bfab40 100644
--- a/drivers/staging/iio/accel/adis16201.h
+++ b/drivers/staging/iio/accel/adis16201.h
@@ -64,9 +64,6 @@
/**
* struct adis16201_state - device instance specific data
* @us: actual spi_device
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter: used to check if new interrupt has been triggered
- * @last_timestamp: passing timestamp from th to bh of interrupt handler
* @indio_dev: industrial I/O device structure
* @trig: data ready trigger registered with iio
* @tx: transmit buffer
@@ -75,8 +72,6 @@
**/
struct adis16201_state {
struct spi_device *us;
- struct work_struct work_trigger_to_ring;
- s64 last_timestamp;
struct iio_dev *indio_dev;
struct iio_trigger *trig;
u8 *tx;
@@ -84,9 +79,8 @@ struct adis16201_state {
struct mutex buf_lock;
};
-int adis16201_set_irq(struct device *dev, bool enable);
+int adis16201_set_irq(struct iio_dev *indio_dev, bool enable);
-#ifdef CONFIG_IIO_RING_BUFFER
enum adis16201_scan {
ADIS16201_SCAN_SUPPLY,
ADIS16201_SCAN_ACC_X,
@@ -97,6 +91,7 @@ enum adis16201_scan {
ADIS16201_SCAN_INCLI_Y,
};
+#ifdef CONFIG_IIO_RING_BUFFER
void adis16201_remove_trigger(struct iio_dev *indio_dev);
int adis16201_probe_trigger(struct iio_dev *indio_dev);
@@ -107,8 +102,6 @@ ssize_t adis16201_read_data_from_ring(struct device *dev,
int adis16201_configure_ring(struct iio_dev *indio_dev);
void adis16201_unconfigure_ring(struct iio_dev *indio_dev);
-int adis16201_initialize_ring(struct iio_ring_buffer *ring);
-void adis16201_uninitialize_ring(struct iio_ring_buffer *ring);
#else /* CONFIG_IIO_RING_BUFFER */
static inline void adis16201_remove_trigger(struct iio_dev *indio_dev)
diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c
index 79b785a0013a..e4c49f00d132 100644
--- a/drivers/staging/iio/accel/adis16201_core.c
+++ b/drivers/staging/iio/accel/adis16201_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,20 +13,28 @@
#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_generic.h"
+
#include "accel.h"
#include "inclinometer.h"
-#include "../gyro/gyro.h"
#include "../adc/adc.h"
#include "adis16201.h"
#define DRIVER_NAME "adis16201"
-static int adis16201_check_status(struct device *dev);
+enum adis16201_chan {
+ in_supply,
+ temp,
+ accel_x,
+ accel_y,
+ incli_x,
+ incli_y,
+ in_aux,
+};
/**
* adis16201_spi_write_reg_8() - write single byte to a register
@@ -57,18 +62,17 @@ static int adis16201_spi_write_reg_8(struct device *dev,
/**
* adis16201_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 adis16201_spi_write_reg_16(struct device *dev,
- u8 lower_reg_address,
- u16 value)
+static int adis16201_spi_write_reg_16(struct iio_dev *indio_dev,
+ u8 lower_reg_address,
+ u16 value)
{
int ret;
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16201_state *st = iio_dev_get_devdata(indio_dev);
struct spi_transfer xfers[] = {
{
@@ -80,7 +84,6 @@ static int adis16201_spi_write_reg_16(struct device *dev,
.tx_buf = st->tx + 2,
.bits_per_word = 8,
.len = 2,
- .cs_change = 1,
},
};
@@ -101,17 +104,16 @@ static int adis16201_spi_write_reg_16(struct device *dev,
/**
* adis16201_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 adis16201_spi_read_reg_16(struct device *dev,
+static int adis16201_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 adis16201_state *st = iio_dev_get_devdata(indio_dev);
int ret;
struct spi_transfer xfers[] = {
@@ -125,7 +127,6 @@ static int adis16201_spi_read_reg_16(struct device *dev,
.rx_buf = st->rx,
.bits_per_word = 8,
.len = 2,
- .cs_change = 1,
.delay_usecs = 20,
},
};
@@ -150,160 +151,6 @@ error_ret:
return ret;
}
-static ssize_t adis16201_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 = adis16201_spi_read_reg_16(dev, this_attr->address, &val);
- if (ret)
- return ret;
-
- if (val & ADIS16201_ERROR_ACTIVE) {
- ret = adis16201_check_status(dev);
- if (ret)
- return ret;
- }
-
- return sprintf(buf, "%u\n", val & 0x0FFF);
-}
-
-static ssize_t adis16201_read_temp(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ssize_t ret;
- u16 val;
-
- /* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
-
- ret = adis16201_spi_read_reg_16(dev, ADIS16201_TEMP_OUT, (u16 *)&val);
- if (ret)
- goto error_ret;
-
- if (val & ADIS16201_ERROR_ACTIVE) {
- ret = adis16201_check_status(dev);
- if (ret)
- goto error_ret;
- }
-
- val &= 0xFFF;
- ret = sprintf(buf, "%d\n", val);
-
-error_ret:
- mutex_unlock(&indio_dev->mlock);
- return ret;
-}
-
-static ssize_t adis16201_read_9bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- s16 val = 0;
- ssize_t ret;
-
- mutex_lock(&indio_dev->mlock);
-
- ret = adis16201_spi_read_reg_16(dev, this_attr->address, (u16 *)&val);
- if (!ret) {
- if (val & ADIS16201_ERROR_ACTIVE) {
- ret = adis16201_check_status(dev);
- if (ret)
- goto error_ret;
- }
- val = ((s16)(val << 7) >> 7);
- ret = sprintf(buf, "%d\n", val);
- }
-
-error_ret:
- mutex_unlock(&indio_dev->mlock);
-
- return ret;
-}
-
-static ssize_t adis16201_read_12bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- s16 val = 0;
- ssize_t ret;
-
- mutex_lock(&indio_dev->mlock);
-
- ret = adis16201_spi_read_reg_16(dev, this_attr->address, (u16 *)&val);
- if (!ret) {
- if (val & ADIS16201_ERROR_ACTIVE) {
- ret = adis16201_check_status(dev);
- if (ret)
- goto error_ret;
- }
-
- val = ((s16)(val << 4) >> 4);
- ret = sprintf(buf, "%d\n", val);
- }
-
-error_ret:
- mutex_unlock(&indio_dev->mlock);
-
- return ret;
-}
-
-static ssize_t adis16201_read_14bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- s16 val = 0;
- ssize_t ret;
-
- mutex_lock(&indio_dev->mlock);
-
- ret = adis16201_spi_read_reg_16(dev, this_attr->address, (u16 *)&val);
- if (!ret) {
- if (val & ADIS16201_ERROR_ACTIVE) {
- ret = adis16201_check_status(dev);
- if (ret)
- goto error_ret;
- }
-
- val = ((s16)(val << 2) >> 2);
- ret = sprintf(buf, "%d\n", val);
- }
-
-error_ret:
- mutex_unlock(&indio_dev->mlock);
-
- return ret;
-}
-
-static ssize_t adis16201_write_16bit(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int ret;
- long val;
-
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- goto error_ret;
- ret = adis16201_spi_write_reg_16(dev, this_attr->address, val);
-
-error_ret:
- return ret ? ret : len;
-}
-
static int adis16201_reset(struct device *dev)
{
int ret;
@@ -331,12 +178,12 @@ static ssize_t adis16201_write_reset(struct device *dev,
return -EINVAL;
}
-int adis16201_set_irq(struct device *dev, bool enable)
+int adis16201_set_irq(struct iio_dev *indio_dev, bool enable)
{
int ret = 0;
u16 msc;
- ret = adis16201_spi_read_reg_16(dev, ADIS16201_MSC_CTRL, &msc);
+ ret = adis16201_spi_read_reg_16(indio_dev, ADIS16201_MSC_CTRL, &msc);
if (ret)
goto error_ret;
@@ -347,20 +194,21 @@ int adis16201_set_irq(struct device *dev, bool enable)
else
msc &= ~ADIS16201_MSC_CTRL_DATA_RDY_EN;
- ret = adis16201_spi_write_reg_16(dev, ADIS16201_MSC_CTRL, msc);
+ ret = adis16201_spi_write_reg_16(indio_dev, ADIS16201_MSC_CTRL, msc);
error_ret:
return ret;
}
-static int adis16201_check_status(struct device *dev)
+static int adis16201_check_status(struct iio_dev *indio_dev)
{
u16 status;
int ret;
- ret = adis16201_spi_read_reg_16(dev, ADIS16201_DIAG_STAT, &status);
+ ret = adis16201_spi_read_reg_16(indio_dev,
+ ADIS16201_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 & 0xF;
@@ -368,30 +216,30 @@ static int adis16201_check_status(struct device *dev)
ret = -EFAULT;
if (status & ADIS16201_DIAG_STAT_SPI_FAIL)
- dev_err(dev, "SPI failure\n");
+ dev_err(&indio_dev->dev, "SPI failure\n");
if (status & ADIS16201_DIAG_STAT_FLASH_UPT)
- dev_err(dev, "Flash update failed\n");
+ dev_err(&indio_dev->dev, "Flash update failed\n");
if (status & ADIS16201_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 & ADIS16201_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 adis16201_self_test(struct device *dev)
+static int adis16201_self_test(struct iio_dev *indio_dev)
{
int ret;
- ret = adis16201_spi_write_reg_16(dev,
+ ret = adis16201_spi_write_reg_16(indio_dev,
ADIS16201_MSC_CTRL,
ADIS16201_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;
}
- ret = adis16201_check_status(dev);
+ ret = adis16201_check_status(indio_dev);
err_ret:
return ret;
@@ -403,26 +251,26 @@ static int adis16201_initial_setup(struct adis16201_state *st)
struct device *dev = &st->indio_dev->dev;
/* Disable IRQ */
- ret = adis16201_set_irq(dev, false);
+ ret = adis16201_set_irq(st->indio_dev, false);
if (ret) {
dev_err(dev, "disable irq failed");
goto err_ret;
}
/* Do self test */
- ret = adis16201_self_test(dev);
+ ret = adis16201_self_test(st->indio_dev);
if (ret) {
dev_err(dev, "self test failure");
goto err_ret;
}
/* Read status register to check the result */
- ret = adis16201_check_status(dev);
+ ret = adis16201_check_status(st->indio_dev);
if (ret) {
adis16201_reset(dev);
dev_err(dev, "device not playing ball -> reset");
msleep(ADIS16201_STARTUP_DELAY);
- ret = adis16201_check_status(dev);
+ ret = adis16201_check_status(st->indio_dev);
if (ret) {
dev_err(dev, "giving up");
goto err_ret;
@@ -436,77 +284,172 @@ err_ret:
return ret;
}
-static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16201_read_12bit_unsigned,
- ADIS16201_SUPPLY_OUT);
-static IIO_CONST_ATTR(in0_supply_scale, "0.00122");
-static IIO_DEV_ATTR_IN_RAW(1, adis16201_read_12bit_unsigned,
- ADIS16201_AUX_ADC);
-static IIO_CONST_ATTR(in1_scale, "0.00061");
-
-static IIO_DEV_ATTR_ACCEL_X(adis16201_read_14bit_signed,
- ADIS16201_XACCL_OUT);
-static IIO_DEV_ATTR_ACCEL_Y(adis16201_read_14bit_signed,
- ADIS16201_YACCL_OUT);
-static IIO_DEV_ATTR_ACCEL_X_OFFSET(S_IWUSR | S_IRUGO,
- adis16201_read_12bit_signed,
- adis16201_write_16bit,
- ADIS16201_XACCL_OFFS);
-static IIO_DEV_ATTR_ACCEL_Y_OFFSET(S_IWUSR | S_IRUGO,
- adis16201_read_12bit_signed,
- adis16201_write_16bit,
- ADIS16201_YACCL_OFFS);
-static IIO_CONST_ATTR(accel_scale, "0.4625");
-
-static IIO_DEV_ATTR_INCLI_X(adis16201_read_14bit_signed,
- ADIS16201_XINCL_OUT);
-static IIO_DEV_ATTR_INCLI_Y(adis16201_read_14bit_signed,
- ADIS16201_YINCL_OUT);
-static IIO_DEV_ATTR_INCLI_X_OFFSET(S_IWUSR | S_IRUGO,
- adis16201_read_9bit_signed,
- adis16201_write_16bit,
- ADIS16201_XACCL_OFFS);
-static IIO_DEV_ATTR_INCLI_Y_OFFSET(S_IWUSR | S_IRUGO,
- adis16201_read_9bit_signed,
- adis16201_write_16bit,
- ADIS16201_YACCL_OFFS);
-static IIO_CONST_ATTR(incli_scale, "0.1");
-
-static IIO_DEV_ATTR_TEMP_RAW(adis16201_read_temp);
-static IIO_CONST_ATTR(temp_offset, "25");
-static IIO_CONST_ATTR(temp_scale, "-0.47");
+static u8 adis16201_addresses[7][2] = {
+ [in_supply] = { ADIS16201_SUPPLY_OUT, },
+ [temp] = { ADIS16201_TEMP_OUT },
+ [accel_x] = { ADIS16201_XACCL_OUT, ADIS16201_XACCL_OFFS },
+ [accel_y] = { ADIS16201_YACCL_OUT, ADIS16201_YACCL_OFFS },
+ [in_aux] = { ADIS16201_AUX_ADC },
+ [incli_x] = { ADIS16201_XINCL_OUT },
+ [incli_y] = { ADIS16201_YINCL_OUT },
+};
-static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16201_write_reset, 0);
+static int adis16201_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2,
+ long mask)
+{
+ int ret;
+ int bits;
+ u8 addr;
+ s16 val16;
+
+ switch (mask) {
+ case 0:
+ mutex_lock(&indio_dev->mlock);
+ addr = adis16201_addresses[chan->address][0];
+ ret = adis16201_spi_read_reg_16(indio_dev, addr, &val16);
+ if (ret)
+ return ret;
-static IIO_CONST_ATTR(name, "adis16201");
+ if (val16 & ADIS16201_ERROR_ACTIVE) {
+ ret = adis16201_check_status(indio_dev);
+ if (ret)
+ return ret;
+ }
+ val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
+ if (chan->scan_type.sign == 's')
+ val16 = (s16)(val16 <<
+ (16 - chan->scan_type.realbits)) >>
+ (16 - chan->scan_type.realbits);
+ *val = val16;
+ mutex_unlock(&indio_dev->mlock);
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ switch (chan->type) {
+ case IIO_IN:
+ *val = 0;
+ if (chan->channel == 0)
+ *val2 = 1220;
+ else
+ *val2 = 610;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_TEMP:
+ *val = 0;
+ *val2 = -470000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_ACCEL:
+ *val = 0;
+ *val2 = 462500;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_INCLI:
+ *val = 0;
+ *val2 = 100000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ *val = 25;
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ switch (chan->type) {
+ case IIO_ACCEL:
+ bits = 12;
+ break;
+ case IIO_INCLI:
+ bits = 9;
+ break;
+ default:
+ return -EINVAL;
+ };
+ mutex_lock(&indio_dev->mlock);
+ addr = adis16201_addresses[chan->address][1];
+ ret = adis16201_spi_read_reg_16(indio_dev, addr, &val16);
+ if (ret) {
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+ }
+ val16 &= (1 << bits) - 1;
+ val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
+ *val = val16;
+ mutex_unlock(&indio_dev->mlock);
+ return IIO_VAL_INT;
+ }
+ return -EINVAL;
+}
-static struct attribute *adis16201_event_attributes[] = {
- NULL
-};
+static int adis16201_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
+{
+ int bits;
+ s16 val16;
+ u8 addr;
+ switch (mask) {
+ case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ switch (chan->type) {
+ case IIO_ACCEL:
+ bits = 12;
+ break;
+ case IIO_INCLI:
+ bits = 9;
+ break;
+ default:
+ return -EINVAL;
+ };
+ val16 = val & ((1 << bits) - 1);
+ addr = adis16201_addresses[chan->address][1];
+ return adis16201_spi_write_reg_16(indio_dev, addr, val16);
+ }
+ return -EINVAL;
+}
-static struct attribute_group adis16201_event_attribute_group = {
- .attrs = adis16201_event_attributes,
+static struct iio_chan_spec adis16201_channels[] = {
+ IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ in_supply, ADIS16201_SCAN_SUPPLY,
+ IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE) |
+ (1 << IIO_CHAN_INFO_OFFSET_SEPARATE),
+ temp, ADIS16201_SCAN_TEMP,
+ IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED) |
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ accel_x, ADIS16201_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_SHARED) |
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ accel_y, ADIS16201_SCAN_ACC_Y,
+ IIO_ST('s', 14, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ in_aux, ADIS16201_SCAN_AUX_ADC,
+ IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED) |
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ incli_x, ADIS16201_SCAN_INCLI_X,
+ IIO_ST('s', 14, 16, 0), 0),
+ IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED) |
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ incli_y, ADIS16201_SCAN_INCLI_Y,
+ IIO_ST('s', 14, 16, 0), 0),
+ IIO_CHAN_SOFT_TIMESTAMP(7)
};
+static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16201_write_reset, 0);
+
static struct attribute *adis16201_attributes[] = {
- &iio_dev_attr_in0_supply_raw.dev_attr.attr,
- &iio_const_attr_in0_supply_scale.dev_attr.attr,
- &iio_dev_attr_temp_raw.dev_attr.attr,
- &iio_const_attr_temp_offset.dev_attr.attr,
- &iio_const_attr_temp_scale.dev_attr.attr,
&iio_dev_attr_reset.dev_attr.attr,
- &iio_const_attr_name.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_const_attr_in1_scale.dev_attr.attr,
- &iio_dev_attr_accel_x_raw.dev_attr.attr,
- &iio_dev_attr_accel_y_raw.dev_attr.attr,
- &iio_dev_attr_accel_x_offset.dev_attr.attr,
- &iio_dev_attr_accel_y_offset.dev_attr.attr,
- &iio_const_attr_accel_scale.dev_attr.attr,
- &iio_dev_attr_incli_x_raw.dev_attr.attr,
- &iio_dev_attr_incli_y_raw.dev_attr.attr,
- &iio_dev_attr_incli_x_offset.dev_attr.attr,
- &iio_dev_attr_incli_y_offset.dev_attr.attr,
- &iio_const_attr_incli_scale.dev_attr.attr,
NULL
};
@@ -514,6 +457,13 @@ static const struct attribute_group adis16201_attribute_group = {
.attrs = adis16201_attributes,
};
+static const struct iio_info adis16201_info = {
+ .attrs = &adis16201_attribute_group,
+ .read_raw = &adis16201_read_raw,
+ .write_raw = &adis16201_write_raw,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit adis16201_probe(struct spi_device *spi)
{
int ret, regdone = 0;
@@ -539,18 +489,19 @@ static int __devinit adis16201_probe(struct spi_device *spi)
st->us = spi;
mutex_init(&st->buf_lock);
/* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_tx;
}
+ st->indio_dev->name = spi->dev.driver->name;
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->num_interrupt_lines = 1;
- st->indio_dev->event_attrs = &adis16201_event_attribute_group;
- st->indio_dev->attrs = &adis16201_attribute_group;
+ st->indio_dev->info = &adis16201_info;
+
+ st->indio_dev->channels = adis16201_channels;
+ st->indio_dev->num_channels = ARRAY_SIZE(adis16201_channels);
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
ret = adis16201_configure_ring(st->indio_dev);
@@ -562,24 +513,18 @@ static int __devinit adis16201_probe(struct spi_device *spi)
goto error_unreg_ring_funcs;
regdone = 1;
- ret = adis16201_initialize_ring(st->indio_dev->ring);
+ ret = iio_ring_buffer_register_ex(st->indio_dev->ring, 0,
+ adis16201_channels,
+ ARRAY_SIZE(adis16201_channels));
if (ret) {
printk(KERN_ERR "failed to initialize the ring\n");
goto error_unreg_ring_funcs;
}
if (spi->irq) {
- ret = iio_register_interrupt_line(spi->irq,
- st->indio_dev,
- 0,
- IRQF_TRIGGER_RISING,
- "adis16201");
- if (ret)
- goto error_uninitialize_ring;
-
ret = adis16201_probe_trigger(st->indio_dev);
if (ret)
- goto error_unregister_line;
+ goto error_uninitialize_ring;
}
/* Get the device into a sane initial state */
@@ -590,11 +535,8 @@ static int __devinit adis16201_probe(struct spi_device *spi)
error_remove_trigger:
adis16201_remove_trigger(st->indio_dev);
-error_unregister_line:
- if (spi->irq)
- iio_unregister_interrupt_line(st->indio_dev, 0);
error_uninitialize_ring:
- adis16201_uninitialize_ring(st->indio_dev->ring);
+ iio_ring_buffer_unregister(st->indio_dev->ring);
error_unreg_ring_funcs:
adis16201_unconfigure_ring(st->indio_dev);
error_free_dev:
@@ -617,13 +559,8 @@ static int adis16201_remove(struct spi_device *spi)
struct adis16201_state *st = spi_get_drvdata(spi);
struct iio_dev *indio_dev = st->indio_dev;
- flush_scheduled_work();
-
adis16201_remove_trigger(indio_dev);
- if (spi->irq)
- iio_unregister_interrupt_line(indio_dev, 0);
-
- adis16201_uninitialize_ring(indio_dev->ring);
+ iio_ring_buffer_unregister(indio_dev->ring);
iio_device_unregister(indio_dev);
adis16201_unconfigure_ring(indio_dev);
kfree(st->tx);
diff --git a/drivers/staging/iio/accel/adis16201_ring.c b/drivers/staging/iio/accel/adis16201_ring.c
index e6870a2721f1..c61f981255ca 100644
--- a/drivers/staging/iio/accel/adis16201_ring.c
+++ b/drivers/staging/iio/accel/adis16201_ring.c
@@ -1,14 +1,11 @@
#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"
@@ -17,74 +14,15 @@
#include "../trigger.h"
#include "adis16201.h"
-static IIO_SCAN_EL_C(in_supply, ADIS16201_SCAN_SUPPLY, ADIS16201_SUPPLY_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in_supply, u, 12, 16);
-static IIO_SCAN_EL_C(accel_x, ADIS16201_SCAN_ACC_X, ADIS16201_XACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_y, ADIS16201_SCAN_ACC_Y, ADIS16201_YACCL_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(accel, s, 14, 16);
-static IIO_SCAN_EL_C(in0, ADIS16201_SCAN_AUX_ADC, ADIS16201_AUX_ADC, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in0, u, 12, 16);
-static IIO_SCAN_EL_C(temp, ADIS16201_SCAN_TEMP, ADIS16201_TEMP_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(temp, u, 12, 16);
-static IIO_SCAN_EL_C(incli_x, ADIS16201_SCAN_INCLI_X,
- ADIS16201_XINCL_OUT, NULL);
-static IIO_SCAN_EL_C(incli_y, ADIS16201_SCAN_INCLI_Y,
- ADIS16201_YINCL_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(incli, s, 14, 16);
-static IIO_SCAN_EL_TIMESTAMP(7);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
-
-static struct attribute *adis16201_scan_el_attrs[] = {
- &iio_scan_el_in_supply.dev_attr.attr,
- &iio_const_attr_in_supply_index.dev_attr.attr,
- &iio_const_attr_in_supply_type.dev_attr.attr,
- &iio_scan_el_accel_x.dev_attr.attr,
- &iio_const_attr_accel_x_index.dev_attr.attr,
- &iio_scan_el_accel_y.dev_attr.attr,
- &iio_const_attr_accel_y_index.dev_attr.attr,
- &iio_const_attr_accel_type.dev_attr.attr,
- &iio_scan_el_in0.dev_attr.attr,
- &iio_const_attr_in0_index.dev_attr.attr,
- &iio_const_attr_in0_type.dev_attr.attr,
- &iio_scan_el_temp.dev_attr.attr,
- &iio_const_attr_temp_index.dev_attr.attr,
- &iio_const_attr_temp_type.dev_attr.attr,
- &iio_scan_el_incli_x.dev_attr.attr,
- &iio_const_attr_incli_x_index.dev_attr.attr,
- &iio_scan_el_incli_y.dev_attr.attr,
- &iio_const_attr_incli_y_index.dev_attr.attr,
- &iio_const_attr_incli_type.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group adis16201_scan_el_group = {
- .attrs = adis16201_scan_el_attrs,
- .name = "scan_elements",
-};
-
-/**
- * adis16201_poll_func_th() top half interrupt handler called by trigger
- * @private_data: iio_dev
- **/
-static void adis16201_poll_func_th(struct iio_dev *indio_dev, s64 time)
-{
- struct adis16201_state *st = iio_dev_get_devdata(indio_dev);
- st->last_timestamp = time;
- schedule_work(&st->work_trigger_to_ring);
-}
/**
* adis16201_read_ring_data() read data registers which will be placed into ring
* @dev: device associated with child of actual device (iio_dev or iio_trig)
* @rx: somewhere to pass back the value read
**/
-static int adis16201_read_ring_data(struct device *dev, u8 *rx)
+static int adis16201_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16201_state *st = iio_dev_get_devdata(indio_dev);
struct spi_transfer xfers[ADIS16201_OUTPUTS + 1];
int ret;
@@ -101,7 +39,8 @@ static int adis16201_read_ring_data(struct device *dev, u8 *rx)
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] = 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);
@@ -120,55 +59,57 @@ static int adis16201_read_ring_data(struct device *dev, u8 *rx)
/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
* specific to be rolled into the core.
*/
-static void adis16201_trigger_bh_to_ring(struct work_struct *work_s)
+static irqreturn_t adis16201_trigger_handler(int irq, void *p)
{
- struct adis16201_state *st
- = container_of(work_s, struct adis16201_state,
- work_trigger_to_ring);
- struct iio_ring_buffer *ring = st->indio_dev->ring;
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->private_data;
+ struct adis16201_state *st = iio_dev_get_devdata(indio_dev);
+ struct iio_ring_buffer *ring = indio_dev->ring;
int i = 0;
s16 *data;
- size_t datasize = ring->access.get_bytes_per_datum(ring);
+ size_t datasize = ring->access->get_bytes_per_datum(ring);
data = kmalloc(datasize, GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
- return;
+ return -ENOMEM;
}
if (ring->scan_count)
- if (adis16201_read_ring_data(&st->indio_dev->dev, st->rx) >= 0)
+ if (adis16201_read_ring_data(st->indio_dev, st->rx) >= 0)
for (; i < ring->scan_count; i++)
data[i] = be16_to_cpup(
(__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
if (ring->scan_timestamp)
- *((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
+ *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
- ring->access.store_to(ring,
- (u8 *)data,
- st->last_timestamp);
+ ring->access->store_to(ring, (u8 *)data, pf->timestamp);
iio_trigger_notify_done(st->indio_dev->trig);
kfree(data);
- return;
+ return IRQ_HANDLED;
}
void adis16201_unconfigure_ring(struct iio_dev *indio_dev)
{
- kfree(indio_dev->pollfunc);
+ iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
+static const struct iio_ring_setup_ops adis16201_ring_setup_ops = {
+ .preenable = &iio_sw_ring_preenable,
+ .postenable = &iio_triggered_ring_postenable,
+ .predisable = &iio_triggered_ring_predisable,
+};
+
int adis16201_configure_ring(struct iio_dev *indio_dev)
{
int ret = 0;
- struct adis16201_state *st = indio_dev->dev_data;
struct iio_ring_buffer *ring;
- INIT_WORK(&st->work_trigger_to_ring, adis16201_trigger_bh_to_ring);
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
@@ -177,42 +118,35 @@ int adis16201_configure_ring(struct iio_dev *indio_dev)
}
indio_dev->ring = ring;
/* Effectively select the ring buffer implementation */
- iio_ring_sw_register_funcs(&ring->access);
ring->bpe = 2;
- ring->scan_el_attrs = &adis16201_scan_el_group;
ring->scan_timestamp = true;
- ring->preenable = &iio_sw_ring_preenable;
- ring->postenable = &iio_triggered_ring_postenable;
- ring->predisable = &iio_triggered_ring_predisable;
+ ring->access = &ring_sw_access_funcs;
+ ring->setup_ops = &adis16201_ring_setup_ops;
ring->owner = THIS_MODULE;
/* Set default scan mode */
- iio_scan_mask_set(ring, iio_scan_el_in_supply.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_x.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_y.number);
- iio_scan_mask_set(ring, iio_scan_el_temp.number);
- iio_scan_mask_set(ring, iio_scan_el_in0.number);
- iio_scan_mask_set(ring, iio_scan_el_incli_x.number);
- iio_scan_mask_set(ring, iio_scan_el_incli_y.number);
-
- ret = iio_alloc_pollfunc(indio_dev, NULL, &adis16201_poll_func_th);
- if (ret)
+ iio_scan_mask_set(ring, ADIS16201_SCAN_SUPPLY);
+ iio_scan_mask_set(ring, ADIS16201_SCAN_ACC_X);
+ iio_scan_mask_set(ring, ADIS16201_SCAN_ACC_Y);
+ iio_scan_mask_set(ring, ADIS16201_SCAN_AUX_ADC);
+ iio_scan_mask_set(ring, ADIS16201_SCAN_TEMP);
+ iio_scan_mask_set(ring, ADIS16201_SCAN_INCLI_X);
+ iio_scan_mask_set(ring, ADIS16201_SCAN_INCLI_Y);
+
+ indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
+ &adis16201_trigger_handler,
+ IRQF_ONESHOT,
+ indio_dev,
+ "adis16201_consumer%d",
+ indio_dev->id);
+ if (indio_dev->pollfunc == NULL) {
+ ret = -ENOMEM;
goto error_iio_sw_rb_free;
+ }
indio_dev->modes |= INDIO_RING_TRIGGERED;
return 0;
-
error_iio_sw_rb_free:
iio_sw_rb_free(indio_dev->ring);
return ret;
}
-
-int adis16201_initialize_ring(struct iio_ring_buffer *ring)
-{
- return iio_ring_buffer_register(ring, 0);
-}
-
-void adis16201_uninitialize_ring(struct iio_ring_buffer *ring)
-{
- iio_ring_buffer_unregister(ring);
-}
diff --git a/drivers/staging/iio/accel/adis16201_trigger.c b/drivers/staging/iio/accel/adis16201_trigger.c
index 8a9cea1986e7..bea917e03b42 100644
--- a/drivers/staging/iio/accel/adis16201_trigger.c
+++ b/drivers/staging/iio/accel/adis16201_trigger.c
@@ -4,7 +4,6 @@
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/sysfs.h>
-#include <linux/list.h>
#include <linux/spi/spi.h>
#include "../iio.h"
@@ -13,35 +12,6 @@
#include "adis16201.h"
/**
- * adis16201_data_rdy_trig_poll() the event handler for the data rdy trig
- **/
-static int adis16201_data_rdy_trig_poll(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct adis16201_state *st = iio_dev_get_devdata(dev_info);
- struct iio_trigger *trig = st->trig;
-
- iio_trigger_poll(trig, timestamp);
-
- return IRQ_HANDLED;
-}
-
-IIO_EVENT_SH(data_rdy_trig, &adis16201_data_rdy_trig_poll);
-
-static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
-
-static struct attribute *adis16201_trigger_attrs[] = {
- &dev_attr_name.attr,
- NULL,
-};
-
-static const struct attribute_group adis16201_trigger_attr_group = {
- .attrs = adis16201_trigger_attrs,
-};
-
-/**
* adis16201_data_rdy_trigger_set_state() set datardy interrupt state
**/
static int adis16201_data_rdy_trigger_set_state(struct iio_trigger *trig,
@@ -49,31 +19,9 @@ static int adis16201_data_rdy_trigger_set_state(struct iio_trigger *trig,
{
struct adis16201_state *st = trig->private_data;
struct iio_dev *indio_dev = st->indio_dev;
- int ret = 0;
dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
- ret = adis16201_set_irq(&st->indio_dev->dev, state);
- if (state == false) {
- iio_remove_event_from_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]
- ->ev_list);
- flush_scheduled_work();
- } else {
- iio_add_event_to_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]->ev_list);
- }
- return ret;
-}
-
-/**
- * adis16201_trig_try_reen() try renabling irq for data rdy trigger
- * @trig: the datardy trigger
- **/
-static int adis16201_trig_try_reen(struct iio_trigger *trig)
-{
- struct adis16201_state *st = trig->private_data;
- enable_irq(st->us->irq);
- return 0;
+ return adis16201_set_irq(st->indio_dev, state);
}
int adis16201_probe_trigger(struct iio_dev *indio_dev)
@@ -81,34 +29,36 @@ int adis16201_probe_trigger(struct iio_dev *indio_dev)
int ret;
struct adis16201_state *st = indio_dev->dev_data;
- st->trig = iio_allocate_trigger();
- st->trig->name = kasprintf(GFP_KERNEL,
- "adis16201-dev%d",
- indio_dev->id);
- if (!st->trig->name) {
+ st->trig = iio_allocate_trigger("adis16201-dev%d", indio_dev->id);
+ if (st->trig == NULL) {
ret = -ENOMEM;
- goto error_free_trig;
+ goto error_ret;
}
+ ret = request_irq(st->us->irq,
+ &iio_trigger_generic_data_rdy_poll,
+ IRQF_TRIGGER_RISING,
+ "adis16201",
+ st->trig);
+ if (ret)
+ goto error_free_trig;
st->trig->dev.parent = &st->us->dev;
st->trig->owner = THIS_MODULE;
st->trig->private_data = st;
st->trig->set_trigger_state = &adis16201_data_rdy_trigger_set_state;
- st->trig->try_reenable = &adis16201_trig_try_reen;
- st->trig->control_attrs = &adis16201_trigger_attr_group;
ret = iio_trigger_register(st->trig);
/* select default trigger */
indio_dev->trig = st->trig;
if (ret)
- goto error_free_trig_name;
+ goto error_free_irq;
return 0;
-error_free_trig_name:
- kfree(st->trig->name);
+error_free_irq:
+ free_irq(st->us->irq, st->trig);
error_free_trig:
iio_free_trigger(st->trig);
-
+error_ret:
return ret;
}
@@ -117,6 +67,6 @@ void adis16201_remove_trigger(struct iio_dev *indio_dev)
struct adis16201_state *state = indio_dev->dev_data;
iio_trigger_unregister(state->trig);
- kfree(state->trig->name);
+ free_irq(state->us->irq, state->trig);
iio_free_trigger(state->trig);
}
diff --git a/drivers/staging/iio/accel/adis16203.h b/drivers/staging/iio/accel/adis16203.h
index b88688128d61..175e21bb9b40 100644
--- a/drivers/staging/iio/accel/adis16203.h
+++ b/drivers/staging/iio/accel/adis16203.h
@@ -59,9 +59,6 @@
/**
* struct adis16203_state - device instance specific data
* @us: actual spi_device
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter: used to check if new interrupt has been triggered
- * @last_timestamp: passing timestamp from th to bh of interrupt handler
* @indio_dev: industrial I/O device structure
* @trig: data ready trigger registered with iio
* @tx: transmit buffer
@@ -70,8 +67,6 @@
**/
struct adis16203_state {
struct spi_device *us;
- struct work_struct work_trigger_to_ring;
- s64 last_timestamp;
struct iio_dev *indio_dev;
struct iio_trigger *trig;
u8 *tx;
@@ -79,9 +74,8 @@ struct adis16203_state {
struct mutex buf_lock;
};
-int adis16203_set_irq(struct device *dev, bool enable);
+int adis16203_set_irq(struct iio_dev *indio_dev, bool enable);
-#ifdef CONFIG_IIO_RING_BUFFER
enum adis16203_scan {
ADIS16203_SCAN_SUPPLY,
ADIS16203_SCAN_AUX_ADC,
@@ -90,6 +84,7 @@ enum adis16203_scan {
ADIS16203_SCAN_INCLI_Y,
};
+#ifdef CONFIG_IIO_RING_BUFFER
void adis16203_remove_trigger(struct iio_dev *indio_dev);
int adis16203_probe_trigger(struct iio_dev *indio_dev);
@@ -100,8 +95,6 @@ ssize_t adis16203_read_data_from_ring(struct device *dev,
int adis16203_configure_ring(struct iio_dev *indio_dev);
void adis16203_unconfigure_ring(struct iio_dev *indio_dev);
-int adis16203_initialize_ring(struct iio_ring_buffer *ring);
-void adis16203_uninitialize_ring(struct iio_ring_buffer *ring);
#else /* CONFIG_IIO_RING_BUFFER */
static inline void adis16203_remove_trigger(struct iio_dev *indio_dev)
@@ -130,14 +123,5 @@ static inline void adis16203_unconfigure_ring(struct iio_dev *indio_dev)
{
}
-static inline int adis16203_initialize_ring(struct iio_ring_buffer *ring)
-{
- return 0;
-}
-
-static inline void adis16203_uninitialize_ring(struct iio_ring_buffer *ring)
-{
-}
-
#endif /* CONFIG_IIO_RING_BUFFER */
#endif /* SPI_ADIS16203_H_ */
diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c
index b57f19087a93..36be4d5dc614 100644
--- a/drivers/staging/iio/accel/adis16203_core.c
+++ b/drivers/staging/iio/accel/adis16203_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,33 +13,29 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
-#include <linux/list.h>
#include "../iio.h"
#include "../sysfs.h"
#include "accel.h"
#include "inclinometer.h"
-#include "../gyro/gyro.h"
+#include "../ring_generic.h"
#include "../adc/adc.h"
#include "adis16203.h"
#define DRIVER_NAME "adis16203"
-static int adis16203_check_status(struct device *dev);
-
/**
* adis16203_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 adis16203_spi_write_reg_8(struct device *dev,
- u8 reg_address,
- u8 val)
+static int adis16203_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 adis16203_state *st = iio_dev_get_devdata(indio_dev);
mutex_lock(&st->buf_lock);
@@ -57,18 +50,17 @@ static int adis16203_spi_write_reg_8(struct device *dev,
/**
* adis16203_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 adis16203_spi_write_reg_16(struct device *dev,
- u8 lower_reg_address,
- u16 value)
+static int adis16203_spi_write_reg_16(struct iio_dev *indio_dev,
+ u8 lower_reg_address,
+ u16 value)
{
int ret;
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16203_state *st = iio_dev_get_devdata(indio_dev);
struct spi_transfer xfers[] = {
{
@@ -80,7 +72,6 @@ static int adis16203_spi_write_reg_16(struct device *dev,
.tx_buf = st->tx + 2,
.bits_per_word = 8,
.len = 2,
- .cs_change = 1,
},
};
@@ -101,17 +92,16 @@ static int adis16203_spi_write_reg_16(struct device *dev,
/**
* adis16203_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 adis16203_spi_read_reg_16(struct device *dev,
+static int adis16203_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 adis16203_state *st = iio_dev_get_devdata(indio_dev);
int ret;
struct spi_transfer xfers[] = {
@@ -125,7 +115,6 @@ static int adis16203_spi_read_reg_16(struct device *dev,
.rx_buf = st->rx,
.bits_per_word = 8,
.len = 2,
- .cs_change = 1,
.delay_usecs = 20,
},
};
@@ -150,101 +139,43 @@ error_ret:
return ret;
}
-static ssize_t adis16203_read_12bit_unsigned(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int adis16203_check_status(struct iio_dev *indio_dev)
{
+ u16 status;
int ret;
- u16 val = 0;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
- ret = adis16203_spi_read_reg_16(dev, this_attr->address, &val);
- if (ret)
- return ret;
-
- if (val & ADIS16203_ERROR_ACTIVE)
- adis16203_check_status(dev);
-
- return sprintf(buf, "%u\n", val & 0x0FFF);
-}
-static ssize_t adis16203_read_temp(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ssize_t ret;
- u16 val;
-
- /* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
-
- ret = adis16203_spi_read_reg_16(dev, ADIS16203_TEMP_OUT, (u16 *)&val);
- if (ret)
+ ret = adis16203_spi_read_reg_16(indio_dev,
+ ADIS16203_DIAG_STAT,
+ &status);
+ if (ret < 0) {
+ dev_err(&indio_dev->dev, "Reading status failed\n");
goto error_ret;
-
- if (val & ADIS16203_ERROR_ACTIVE)
- adis16203_check_status(dev);
-
- val &= 0xFFF;
- ret = sprintf(buf, "%d\n", val);
-
-error_ret:
- mutex_unlock(&indio_dev->mlock);
- return ret;
-}
-
-static ssize_t adis16203_read_14bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- s16 val = 0;
- ssize_t ret;
-
- mutex_lock(&indio_dev->mlock);
-
- ret = adis16203_spi_read_reg_16(dev, this_attr->address, (u16 *)&val);
- if (!ret) {
- if (val & ADIS16203_ERROR_ACTIVE)
- adis16203_check_status(dev);
-
- val = ((s16)(val << 2) >> 2);
- ret = sprintf(buf, "%d\n", val);
}
+ ret = status & 0x1F;
- mutex_unlock(&indio_dev->mlock);
-
- return ret;
-}
-
-static ssize_t adis16203_write_16bit(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int ret;
- long val;
-
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- goto error_ret;
- ret = adis16203_spi_write_reg_16(dev, this_attr->address, val);
+ if (status & ADIS16203_DIAG_STAT_SELFTEST_FAIL)
+ dev_err(&indio_dev->dev, "Self test failure\n");
+ if (status & ADIS16203_DIAG_STAT_SPI_FAIL)
+ dev_err(&indio_dev->dev, "SPI failure\n");
+ if (status & ADIS16203_DIAG_STAT_FLASH_UPT)
+ dev_err(&indio_dev->dev, "Flash update failed\n");
+ if (status & ADIS16203_DIAG_STAT_POWER_HIGH)
+ dev_err(&indio_dev->dev, "Power supply above 3.625V\n");
+ if (status & ADIS16203_DIAG_STAT_POWER_LOW)
+ dev_err(&indio_dev->dev, "Power supply below 3.15V\n");
error_ret:
- return ret ? ret : len;
+ return ret;
}
-static int adis16203_reset(struct device *dev)
+static int adis16203_reset(struct iio_dev *indio_dev)
{
int ret;
- ret = adis16203_spi_write_reg_8(dev,
+ ret = adis16203_spi_write_reg_8(indio_dev,
ADIS16203_GLOB_CMD,
ADIS16203_GLOB_CMD_SW_RESET);
if (ret)
- dev_err(dev, "problem resetting device");
+ dev_err(&indio_dev->dev, "problem resetting device");
return ret;
}
@@ -253,23 +184,24 @@ static ssize_t adis16203_write_reset(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
if (len < 1)
return -EINVAL;
switch (buf[0]) {
case '1':
case 'y':
case 'Y':
- return adis16203_reset(dev);
+ return adis16203_reset(indio_dev);
}
return -EINVAL;
}
-int adis16203_set_irq(struct device *dev, bool enable)
+int adis16203_set_irq(struct iio_dev *indio_dev, bool enable)
{
int ret = 0;
u16 msc;
- ret = adis16203_spi_read_reg_16(dev, ADIS16203_MSC_CTRL, &msc);
+ ret = adis16203_spi_read_reg_16(indio_dev, ADIS16203_MSC_CTRL, &msc);
if (ret)
goto error_ret;
@@ -280,142 +212,195 @@ int adis16203_set_irq(struct device *dev, bool enable)
else
msc &= ~ADIS16203_MSC_CTRL_DATA_RDY_EN;
- ret = adis16203_spi_write_reg_16(dev, ADIS16203_MSC_CTRL, msc);
+ ret = adis16203_spi_write_reg_16(indio_dev, ADIS16203_MSC_CTRL, msc);
error_ret:
return ret;
}
-static int adis16203_check_status(struct device *dev)
+static int adis16203_self_test(struct iio_dev *indio_dev)
{
- u16 status;
int ret;
-
- ret = adis16203_spi_read_reg_16(dev, ADIS16203_DIAG_STAT, &status);
- if (ret < 0) {
- dev_err(dev, "Reading status failed\n");
- goto error_ret;
- }
- ret = status & 0x1F;
-
- if (status & ADIS16203_DIAG_STAT_SELFTEST_FAIL)
- dev_err(dev, "Self test failure\n");
- if (status & ADIS16203_DIAG_STAT_SPI_FAIL)
- dev_err(dev, "SPI failure\n");
- if (status & ADIS16203_DIAG_STAT_FLASH_UPT)
- dev_err(dev, "Flash update failed\n");
- if (status & ADIS16203_DIAG_STAT_POWER_HIGH)
- dev_err(dev, "Power supply above 3.625V\n");
- if (status & ADIS16203_DIAG_STAT_POWER_LOW)
- dev_err(dev, "Power supply below 3.15V\n");
-
-error_ret:
- return ret;
-}
-
-static int adis16203_self_test(struct device *dev)
-{
- int ret;
- ret = adis16203_spi_write_reg_16(dev,
+ ret = adis16203_spi_write_reg_16(indio_dev,
ADIS16203_MSC_CTRL,
ADIS16203_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;
}
- adis16203_check_status(dev);
+ adis16203_check_status(indio_dev);
err_ret:
return ret;
}
-static int adis16203_initial_setup(struct adis16203_state *st)
+static int adis16203_initial_setup(struct iio_dev *indio_dev)
{
int ret;
- struct device *dev = &st->indio_dev->dev;
/* Disable IRQ */
- ret = adis16203_set_irq(dev, false);
+ ret = adis16203_set_irq(indio_dev, false);
if (ret) {
- dev_err(dev, "disable irq failed");
+ dev_err(&indio_dev->dev, "disable irq failed");
goto err_ret;
}
/* Do self test */
- ret = adis16203_self_test(dev);
+ ret = adis16203_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 = adis16203_check_status(dev);
+ ret = adis16203_check_status(indio_dev);
if (ret) {
- adis16203_reset(dev);
- dev_err(dev, "device not playing ball -> reset");
+ adis16203_reset(indio_dev);
+ dev_err(&indio_dev->dev, "device not playing ball -> reset");
msleep(ADIS16203_STARTUP_DELAY);
- ret = adis16203_check_status(dev);
+ ret = adis16203_check_status(indio_dev);
if (ret) {
- dev_err(dev, "giving up");
+ dev_err(&indio_dev->dev, "giving up");
goto err_ret;
}
}
- printk(KERN_INFO DRIVER_NAME ": at CS%d (irq %d)\n",
- st->us->chip_select, st->us->irq);
-
err_ret:
return ret;
}
-static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16203_read_12bit_unsigned,
- ADIS16203_SUPPLY_OUT);
-static IIO_CONST_ATTR(in0_supply_scale, "0.00122");
-static IIO_DEV_ATTR_IN_RAW(1, adis16203_read_12bit_unsigned,
- ADIS16203_AUX_ADC);
-static IIO_CONST_ATTR(in1_scale, "0.00061");
-
-static IIO_DEV_ATTR_INCLI_X(adis16203_read_14bit_signed,
- ADIS16203_XINCL_OUT);
-static IIO_DEV_ATTR_INCLI_Y(adis16203_read_14bit_signed,
- ADIS16203_YINCL_OUT);
-static IIO_DEV_ATTR_INCLI_X_OFFSET(S_IWUSR | S_IRUGO,
- adis16203_read_14bit_signed,
- adis16203_write_16bit,
- ADIS16203_INCL_NULL);
-static IIO_CONST_ATTR(incli_scale, "0.025");
-
-static IIO_DEV_ATTR_TEMP_RAW(adis16203_read_temp);
-static IIO_CONST_ATTR(temp_offset, "25");
-static IIO_CONST_ATTR(temp_scale, "-0.47");
+enum adis16203_chan {
+ in_supply,
+ in_aux,
+ incli_x,
+ incli_y,
+ temp,
+};
+
+static u8 adis16203_addresses[5][2] = {
+ [in_supply] = { ADIS16203_SUPPLY_OUT },
+ [in_aux] = { ADIS16203_AUX_ADC },
+ [incli_x] = { ADIS16203_XINCL_OUT, ADIS16203_INCL_NULL},
+ [incli_y] = { ADIS16203_YINCL_OUT },
+ [temp] = { ADIS16203_TEMP_OUT }
+};
-static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16203_write_reset, 0);
+static int adis16203_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
+{
+ /* currently only one writable parameter which keeps this simple */
+ u8 addr = adis16203_addresses[chan->address][1];
+ return adis16203_spi_write_reg_16(indio_dev, addr, val & 0x3FFF);
+}
-static IIO_CONST_ATTR(name, "adis16203");
+static int adis16203_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2,
+ long mask)
+{
+ int ret;
+ int bits;
+ u8 addr;
+ s16 val16;
+ switch (mask) {
+ case 0:
+ mutex_lock(&indio_dev->mlock);
+ addr = adis16203_addresses[chan->address][0];
+ ret = adis16203_spi_read_reg_16(indio_dev, addr, &val16);
+ if (ret)
+ return ret;
-static struct attribute *adis16203_event_attributes[] = {
- NULL
-};
+ if (val16 & ADIS16203_ERROR_ACTIVE) {
+ ret = adis16203_check_status(indio_dev);
+ if (ret)
+ return ret;
+ }
+ val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
+ if (chan->scan_type.sign == 's')
+ val16 = (s16)(val16 <<
+ (16 - chan->scan_type.realbits)) >>
+ (16 - chan->scan_type.realbits);
+ *val = val16;
+ mutex_unlock(&indio_dev->mlock);
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ switch (chan->type) {
+ case IIO_IN:
+ *val = 0;
+ if (chan->channel == 0)
+ *val2 = 1220;
+ else
+ *val2 = 610;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_TEMP:
+ *val = 0;
+ *val2 = -470000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_INCLI:
+ *val = 0;
+ *val2 = 25000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+ case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ *val = 25;
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ bits = 14;
+ mutex_lock(&indio_dev->mlock);
+ addr = adis16203_addresses[chan->address][1];
+ ret = adis16203_spi_read_reg_16(indio_dev, addr, &val16);
+ if (ret) {
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+ }
+ val16 &= (1 << bits) - 1;
+ val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
+ *val = val16;
+ mutex_unlock(&indio_dev->mlock);
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
-static struct attribute_group adis16203_event_attribute_group = {
- .attrs = adis16203_event_attributes,
+static struct iio_chan_spec adis16203_channels[] = {
+ IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ in_supply, ADIS16203_SCAN_SUPPLY,
+ IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ in_aux, ADIS16203_SCAN_AUX_ADC,
+ IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED) |
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ incli_x, ADIS16203_SCAN_INCLI_X,
+ IIO_ST('s', 14, 16, 0), 0),
+ /* Fixme: Not what it appears to be - see data sheet */
+ IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ incli_y, ADIS16203_SCAN_INCLI_Y,
+ IIO_ST('s', 14, 16, 0), 0),
+ IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE) |
+ (1 << IIO_CHAN_INFO_OFFSET_SEPARATE),
+ temp, ADIS16203_SCAN_TEMP,
+ IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN_SOFT_TIMESTAMP(5),
};
+static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16203_write_reset, 0);
+
static struct attribute *adis16203_attributes[] = {
- &iio_dev_attr_in0_supply_raw.dev_attr.attr,
- &iio_const_attr_in0_supply_scale.dev_attr.attr,
- &iio_dev_attr_temp_raw.dev_attr.attr,
- &iio_const_attr_temp_offset.dev_attr.attr,
- &iio_const_attr_temp_scale.dev_attr.attr,
&iio_dev_attr_reset.dev_attr.attr,
- &iio_const_attr_name.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_const_attr_in1_scale.dev_attr.attr,
- &iio_dev_attr_incli_x_raw.dev_attr.attr,
- &iio_dev_attr_incli_y_raw.dev_attr.attr,
- &iio_dev_attr_incli_x_offset.dev_attr.attr,
- &iio_const_attr_incli_scale.dev_attr.attr,
NULL
};
@@ -423,6 +408,13 @@ static const struct attribute_group adis16203_attribute_group = {
.attrs = adis16203_attributes,
};
+static const struct iio_info adis16203_info = {
+ .attrs = &adis16203_attribute_group,
+ .read_raw = &adis16203_read_raw,
+ .write_raw = &adis16203_write_raw,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit adis16203_probe(struct spi_device *spi)
{
int ret, regdone = 0;
@@ -448,18 +440,17 @@ static int __devinit adis16203_probe(struct spi_device *spi)
st->us = spi;
mutex_init(&st->buf_lock);
/* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_tx;
}
-
+ st->indio_dev->name = spi->dev.driver->name;
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->num_interrupt_lines = 1;
- st->indio_dev->event_attrs = &adis16203_event_attribute_group;
- st->indio_dev->attrs = &adis16203_attribute_group;
+ st->indio_dev->channels = adis16203_channels;
+ st->indio_dev->num_channels = ARRAY_SIZE(adis16203_channels);
+ st->indio_dev->info = &adis16203_info;
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
ret = adis16203_configure_ring(st->indio_dev);
@@ -471,39 +462,30 @@ static int __devinit adis16203_probe(struct spi_device *spi)
goto error_unreg_ring_funcs;
regdone = 1;
- ret = adis16203_initialize_ring(st->indio_dev->ring);
+ ret = iio_ring_buffer_register_ex(st->indio_dev->ring, 0,
+ adis16203_channels,
+ ARRAY_SIZE(adis16203_channels));
if (ret) {
printk(KERN_ERR "failed to initialize the ring\n");
goto error_unreg_ring_funcs;
}
if (spi->irq) {
- ret = iio_register_interrupt_line(spi->irq,
- st->indio_dev,
- 0,
- IRQF_TRIGGER_RISING,
- "adis16203");
- if (ret)
- goto error_uninitialize_ring;
-
ret = adis16203_probe_trigger(st->indio_dev);
if (ret)
- goto error_unregister_line;
+ goto error_uninitialize_ring;
}
/* Get the device into a sane initial state */
- ret = adis16203_initial_setup(st);
+ ret = adis16203_initial_setup(st->indio_dev);
if (ret)
goto error_remove_trigger;
return 0;
error_remove_trigger:
adis16203_remove_trigger(st->indio_dev);
-error_unregister_line:
- if (spi->irq)
- iio_unregister_interrupt_line(st->indio_dev, 0);
error_uninitialize_ring:
- adis16203_uninitialize_ring(st->indio_dev->ring);
+ iio_ring_buffer_unregister(st->indio_dev->ring);
error_unreg_ring_funcs:
adis16203_unconfigure_ring(st->indio_dev);
error_free_dev:
@@ -526,13 +508,8 @@ static int adis16203_remove(struct spi_device *spi)
struct adis16203_state *st = spi_get_drvdata(spi);
struct iio_dev *indio_dev = st->indio_dev;
- flush_scheduled_work();
-
adis16203_remove_trigger(indio_dev);
- if (spi->irq)
- iio_unregister_interrupt_line(indio_dev, 0);
-
- adis16203_uninitialize_ring(indio_dev->ring);
+ iio_ring_buffer_unregister(indio_dev->ring);
iio_device_unregister(indio_dev);
adis16203_unconfigure_ring(indio_dev);
kfree(st->tx);
diff --git a/drivers/staging/iio/accel/adis16203_ring.c b/drivers/staging/iio/accel/adis16203_ring.c
index 3d774f7efa25..a9a789d79c09 100644
--- a/drivers/staging/iio/accel/adis16203_ring.c
+++ b/drivers/staging/iio/accel/adis16203_ring.c
@@ -17,57 +17,6 @@
#include "../trigger.h"
#include "adis16203.h"
-static IIO_SCAN_EL_C(in_supply, ADIS16203_SCAN_SUPPLY, ADIS16203_SUPPLY_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in_supply, u, 12, 16);
-static IIO_SCAN_EL_C(in0, ADIS16203_SCAN_AUX_ADC, ADIS16203_AUX_ADC, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in0, u, 12, 16);
-static IIO_SCAN_EL_C(temp, ADIS16203_SCAN_TEMP, ADIS16203_TEMP_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(temp, u, 12, 16);
-static IIO_SCAN_EL_C(incli_x, ADIS16203_SCAN_INCLI_X,
- ADIS16203_XINCL_OUT, NULL);
-static IIO_SCAN_EL_C(incli_y, ADIS16203_SCAN_INCLI_Y,
- ADIS16203_YINCL_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(incli, s, 14, 16);
-static IIO_SCAN_EL_TIMESTAMP(5);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
-
-static struct attribute *adis16203_scan_el_attrs[] = {
- &iio_scan_el_in_supply.dev_attr.attr,
- &iio_const_attr_in_supply_index.dev_attr.attr,
- &iio_const_attr_in_supply_type.dev_attr.attr,
- &iio_scan_el_in0.dev_attr.attr,
- &iio_const_attr_in0_index.dev_attr.attr,
- &iio_const_attr_in0_type.dev_attr.attr,
- &iio_scan_el_temp.dev_attr.attr,
- &iio_const_attr_temp_index.dev_attr.attr,
- &iio_const_attr_temp_type.dev_attr.attr,
- &iio_scan_el_incli_x.dev_attr.attr,
- &iio_const_attr_incli_x_index.dev_attr.attr,
- &iio_scan_el_incli_y.dev_attr.attr,
- &iio_const_attr_incli_y_index.dev_attr.attr,
- &iio_const_attr_incli_type.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group adis16203_scan_el_group = {
- .attrs = adis16203_scan_el_attrs,
- .name = "scan_elements",
-};
-
-/**
- * adis16203_poll_func_th() top half interrupt handler called by trigger
- * @private_data: iio_dev
- **/
-static void adis16203_poll_func_th(struct iio_dev *indio_dev, s64 timestamp)
-{
- struct adis16203_state *st = iio_dev_get_devdata(indio_dev);
- st->last_timestamp = timestamp;
- schedule_work(&st->work_trigger_to_ring);
-}
-
/**
* adis16203_read_ring_data() read data registers which will be placed into ring
* @dev: device associated with child of actual device (iio_dev or iio_trig)
@@ -115,21 +64,21 @@ static int adis16203_read_ring_data(struct device *dev, u8 *rx)
/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
* specific to be rolled into the core.
*/
-static void adis16203_trigger_bh_to_ring(struct work_struct *work_s)
+static irqreturn_t adis16203_trigger_handler(int irq, void *p)
{
- struct adis16203_state *st
- = container_of(work_s, struct adis16203_state,
- work_trigger_to_ring);
- struct iio_ring_buffer *ring = st->indio_dev->ring;
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->private_data;
+ struct adis16203_state *st = iio_dev_get_devdata(indio_dev);
+ struct iio_ring_buffer *ring = indio_dev->ring;
int i = 0;
s16 *data;
- size_t datasize = ring->access.get_bytes_per_datum(ring);
+ size_t datasize = ring->access->get_bytes_per_datum(ring);
data = kmalloc(datasize, GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
- return;
+ return -ENOMEM;
}
if (ring->scan_count)
@@ -140,30 +89,34 @@ static void adis16203_trigger_bh_to_ring(struct work_struct *work_s)
/* Guaranteed to be aligned with 8 byte boundary */
if (ring->scan_timestamp)
- *((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
+ *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
- ring->access.store_to(ring,
+ ring->access->store_to(ring,
(u8 *)data,
- st->last_timestamp);
+ pf->timestamp);
iio_trigger_notify_done(st->indio_dev->trig);
kfree(data);
- return;
+ return IRQ_HANDLED;
}
void adis16203_unconfigure_ring(struct iio_dev *indio_dev)
{
- kfree(indio_dev->pollfunc);
+ iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
+static const struct iio_ring_setup_ops adis16203_ring_setup_ops = {
+ .preenable = &iio_sw_ring_preenable,
+ .postenable = &iio_triggered_ring_postenable,
+ .predisable = &iio_triggered_ring_predisable,
+};
+
int adis16203_configure_ring(struct iio_dev *indio_dev)
{
int ret = 0;
- struct adis16203_state *st = indio_dev->dev_data;
struct iio_ring_buffer *ring;
- INIT_WORK(&st->work_trigger_to_ring, adis16203_trigger_bh_to_ring);
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
@@ -172,25 +125,29 @@ int adis16203_configure_ring(struct iio_dev *indio_dev)
}
indio_dev->ring = ring;
/* Effectively select the ring buffer implementation */
- iio_ring_sw_register_funcs(&ring->access);
ring->bpe = 2;
- ring->scan_el_attrs = &adis16203_scan_el_group;
ring->scan_timestamp = true;
- ring->preenable = &iio_sw_ring_preenable;
- ring->postenable = &iio_triggered_ring_postenable;
- ring->predisable = &iio_triggered_ring_predisable;
+ ring->access = &ring_sw_access_funcs;
+ ring->setup_ops = &adis16203_ring_setup_ops;
ring->owner = THIS_MODULE;
/* Set default scan mode */
- iio_scan_mask_set(ring, iio_scan_el_in_supply.number);
- iio_scan_mask_set(ring, iio_scan_el_temp.number);
- iio_scan_mask_set(ring, iio_scan_el_in0.number);
- iio_scan_mask_set(ring, iio_scan_el_incli_x.number);
- iio_scan_mask_set(ring, iio_scan_el_incli_y.number);
-
- ret = iio_alloc_pollfunc(indio_dev, NULL, &adis16203_poll_func_th);
- if (ret)
+ iio_scan_mask_set(ring, ADIS16203_SCAN_SUPPLY);
+ iio_scan_mask_set(ring, ADIS16203_SCAN_TEMP);
+ iio_scan_mask_set(ring, ADIS16203_SCAN_AUX_ADC);
+ iio_scan_mask_set(ring, ADIS16203_SCAN_INCLI_X);
+ iio_scan_mask_set(ring, ADIS16203_SCAN_INCLI_Y);
+
+ indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
+ &adis16203_trigger_handler,
+ IRQF_ONESHOT,
+ indio_dev,
+ "adis16203_consumer%d",
+ indio_dev->id);
+ if (indio_dev->pollfunc == NULL) {
+ ret = -ENOMEM;
goto error_iio_sw_rb_free;
+ }
indio_dev->modes |= INDIO_RING_TRIGGERED;
return 0;
@@ -199,13 +156,3 @@ error_iio_sw_rb_free:
iio_sw_rb_free(indio_dev->ring);
return ret;
}
-
-int adis16203_initialize_ring(struct iio_ring_buffer *ring)
-{
- return iio_ring_buffer_register(ring, 0);
-}
-
-void adis16203_uninitialize_ring(struct iio_ring_buffer *ring)
-{
- iio_ring_buffer_unregister(ring);
-}
diff --git a/drivers/staging/iio/accel/adis16203_trigger.c b/drivers/staging/iio/accel/adis16203_trigger.c
index 50be51c25dc2..ca5db1731988 100644
--- a/drivers/staging/iio/accel/adis16203_trigger.c
+++ b/drivers/staging/iio/accel/adis16203_trigger.c
@@ -13,35 +13,6 @@
#include "adis16203.h"
/**
- * adis16203_data_rdy_trig_poll() the event handler for the data rdy trig
- **/
-static int adis16203_data_rdy_trig_poll(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct adis16203_state *st = iio_dev_get_devdata(dev_info);
- struct iio_trigger *trig = st->trig;
-
- iio_trigger_poll(trig, timestamp);
-
- return IRQ_HANDLED;
-}
-
-IIO_EVENT_SH(data_rdy_trig, &adis16203_data_rdy_trig_poll);
-
-static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
-
-static struct attribute *adis16203_trigger_attrs[] = {
- &dev_attr_name.attr,
- NULL,
-};
-
-static const struct attribute_group adis16203_trigger_attr_group = {
- .attrs = adis16203_trigger_attrs,
-};
-
-/**
* adis16203_data_rdy_trigger_set_state() set datardy interrupt state
**/
static int adis16203_data_rdy_trigger_set_state(struct iio_trigger *trig,
@@ -49,31 +20,9 @@ static int adis16203_data_rdy_trigger_set_state(struct iio_trigger *trig,
{
struct adis16203_state *st = trig->private_data;
struct iio_dev *indio_dev = st->indio_dev;
- int ret = 0;
dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
- ret = adis16203_set_irq(&st->indio_dev->dev, state);
- if (state == false) {
- iio_remove_event_from_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]
- ->ev_list);
- flush_scheduled_work();
- } else {
- iio_add_event_to_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]->ev_list);
- }
- return ret;
-}
-
-/**
- * adis16203_trig_try_reen() try renabling irq for data rdy trigger
- * @trig: the datardy trigger
- **/
-static int adis16203_trig_try_reen(struct iio_trigger *trig)
-{
- struct adis16203_state *st = trig->private_data;
- enable_irq(st->us->irq);
- return 0;
+ return adis16203_set_irq(st->indio_dev, state);
}
int adis16203_probe_trigger(struct iio_dev *indio_dev)
@@ -81,34 +30,38 @@ int adis16203_probe_trigger(struct iio_dev *indio_dev)
int ret;
struct adis16203_state *st = indio_dev->dev_data;
- st->trig = iio_allocate_trigger();
- st->trig->name = kasprintf(GFP_KERNEL,
- "adis16203-dev%d",
- indio_dev->id);
- if (!st->trig->name) {
+ st->trig = iio_allocate_trigger("adis16203-dev%d", indio_dev->id);
+ if (st->trig == NULL) {
ret = -ENOMEM;
- goto error_free_trig;
+ goto error_ret;
}
+
+ ret = request_irq(st->us->irq,
+ &iio_trigger_generic_data_rdy_poll,
+ IRQF_TRIGGER_RISING,
+ "adis16203",
+ st->trig);
+ if (ret)
+ goto error_free_trig;
+
st->trig->dev.parent = &st->us->dev;
st->trig->owner = THIS_MODULE;
st->trig->private_data = st;
st->trig->set_trigger_state = &adis16203_data_rdy_trigger_set_state;
- st->trig->try_reenable = &adis16203_trig_try_reen;
- st->trig->control_attrs = &adis16203_trigger_attr_group;
ret = iio_trigger_register(st->trig);
/* select default trigger */
indio_dev->trig = st->trig;
if (ret)
- goto error_free_trig_name;
+ goto error_free_irq;
return 0;
-error_free_trig_name:
- kfree(st->trig->name);
+error_free_irq:
+ free_irq(st->us->irq, st->trig);
error_free_trig:
iio_free_trigger(st->trig);
-
+error_ret:
return ret;
}
@@ -117,6 +70,6 @@ void adis16203_remove_trigger(struct iio_dev *indio_dev)
struct adis16203_state *state = indio_dev->dev_data;
iio_trigger_unregister(state->trig);
- kfree(state->trig->name);
+ free_irq(state->us->irq, state->trig);
iio_free_trigger(state->trig);
}
diff --git a/drivers/staging/iio/accel/adis16204.h b/drivers/staging/iio/accel/adis16204.h
index e61844684f99..5310a4297688 100644
--- a/drivers/staging/iio/accel/adis16204.h
+++ b/drivers/staging/iio/accel/adis16204.h
@@ -67,9 +67,6 @@
/**
* struct adis16204_state - device instance specific data
* @us: actual spi_device
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter: used to check if new interrupt has been triggered
- * @last_timestamp: passing timestamp from th to bh of interrupt handler
* @indio_dev: industrial I/O device structure
* @trig: data ready trigger registered with iio
* @tx: transmit buffer
@@ -78,8 +75,6 @@
**/
struct adis16204_state {
struct spi_device *us;
- struct work_struct work_trigger_to_ring;
- s64 last_timestamp;
struct iio_dev *indio_dev;
struct iio_trigger *trig;
u8 *tx;
@@ -87,7 +82,7 @@ struct adis16204_state {
struct mutex buf_lock;
};
-int adis16204_set_irq(struct device *dev, bool enable);
+int adis16204_set_irq(struct iio_dev *indio_dev, bool enable);
#ifdef CONFIG_IIO_RING_BUFFER
enum adis16204_scan {
@@ -108,8 +103,6 @@ ssize_t adis16204_read_data_from_ring(struct device *dev,
int adis16204_configure_ring(struct iio_dev *indio_dev);
void adis16204_unconfigure_ring(struct iio_dev *indio_dev);
-int adis16204_initialize_ring(struct iio_ring_buffer *ring);
-void adis16204_uninitialize_ring(struct iio_ring_buffer *ring);
#else /* CONFIG_IIO_RING_BUFFER */
static inline void adis16204_remove_trigger(struct iio_dev *indio_dev)
@@ -138,14 +131,5 @@ static inline void adis16204_unconfigure_ring(struct iio_dev *indio_dev)
{
}
-static inline int adis16204_initialize_ring(struct iio_ring_buffer *ring)
-{
- return 0;
-}
-
-static inline void adis16204_uninitialize_ring(struct iio_ring_buffer *ring)
-{
-}
-
#endif /* CONFIG_IIO_RING_BUFFER */
#endif /* SPI_ADIS16204_H_ */
diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c
index cc15e40726fc..16806704bf48 100644
--- a/drivers/staging/iio/accel/adis16204_core.c
+++ b/drivers/staging/iio/accel/adis16204_core.c
@@ -20,28 +20,25 @@
#include "../iio.h"
#include "../sysfs.h"
+#include "../ring_generic.h"
#include "accel.h"
-#include "../gyro/gyro.h"
#include "../adc/adc.h"
#include "adis16204.h"
#define DRIVER_NAME "adis16204"
-static int adis16204_check_status(struct device *dev);
-
/**
* adis16204_spi_write_reg_8() - write single byte to a register
* @dev: device associated with child of actual device (iio_dev or iio_trig)
* @reg_address: the address of the register to be written
* @val: the value to write
**/
-static int adis16204_spi_write_reg_8(struct device *dev,
+static int adis16204_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 adis16204_state *st = iio_dev_get_devdata(indio_dev);
mutex_lock(&st->buf_lock);
@@ -56,18 +53,17 @@ static int adis16204_spi_write_reg_8(struct device *dev,
/**
* adis16204_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 adis16204_spi_write_reg_16(struct device *dev,
+static int adis16204_spi_write_reg_16(struct iio_dev *indio_dev,
u8 lower_reg_address,
u16 value)
{
int ret;
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16204_state *st = iio_dev_get_devdata(indio_dev);
struct spi_transfer xfers[] = {
{
@@ -100,17 +96,16 @@ static int adis16204_spi_write_reg_16(struct device *dev,
/**
* adis16204_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 adis16204_spi_read_reg_16(struct device *dev,
- u8 lower_reg_address,
- u16 *val)
+static int adis16204_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 adis16204_state *st = iio_dev_get_devdata(indio_dev);
int ret;
struct spi_transfer xfers[] = {
@@ -124,7 +119,6 @@ static int adis16204_spi_read_reg_16(struct device *dev,
.rx_buf = st->rx,
.bits_per_word = 8,
.len = 2,
- .cs_change = 1,
.delay_usecs = 20,
},
};
@@ -149,72 +143,31 @@ error_ret:
return ret;
}
-static ssize_t adis16204_read_12bit_unsigned(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int adis16204_check_status(struct iio_dev *indio_dev)
{
+ u16 status;
int ret;
- u16 val = 0;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
- ret = adis16204_spi_read_reg_16(dev, this_attr->address, &val);
- if (ret)
- return ret;
-
- if (val & ADIS16204_ERROR_ACTIVE)
- adis16204_check_status(dev);
- return sprintf(buf, "%u\n", val & 0x0FFF);
-}
-
-static ssize_t adis16204_read_temp(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ssize_t ret;
- u16 val;
-
- /* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
-
- ret = adis16204_spi_read_reg_16(dev, ADIS16204_TEMP_OUT, (u16 *)&val);
- if (ret)
+ ret = adis16204_spi_read_reg_16(indio_dev,
+ ADIS16204_DIAG_STAT, &status);
+ if (ret < 0) {
+ dev_err(&indio_dev->dev, "Reading status failed\n");
goto error_ret;
-
- if (val & ADIS16204_ERROR_ACTIVE)
- adis16204_check_status(dev);
-
- val &= 0xFFF;
- ret = sprintf(buf, "%d\n", val);
-
-error_ret:
- mutex_unlock(&indio_dev->mlock);
- return ret;
-}
-
-static ssize_t adis16204_read_12bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- s16 val = 0;
- ssize_t ret;
-
- mutex_lock(&indio_dev->mlock);
-
- ret = adis16204_spi_read_reg_16(dev, this_attr->address, (u16 *)&val);
- if (!ret) {
- if (val & ADIS16204_ERROR_ACTIVE)
- adis16204_check_status(dev);
-
- val = ((s16)(val << 4) >> 4);
- ret = sprintf(buf, "%d\n", val);
}
+ ret = status & 0x1F;
- mutex_unlock(&indio_dev->mlock);
+ if (status & ADIS16204_DIAG_STAT_SELFTEST_FAIL)
+ dev_err(&indio_dev->dev, "Self test failure\n");
+ if (status & ADIS16204_DIAG_STAT_SPI_FAIL)
+ dev_err(&indio_dev->dev, "SPI failure\n");
+ if (status & ADIS16204_DIAG_STAT_FLASH_UPT)
+ dev_err(&indio_dev->dev, "Flash update failed\n");
+ if (status & ADIS16204_DIAG_STAT_POWER_HIGH)
+ dev_err(&indio_dev->dev, "Power supply above 3.625V\n");
+ if (status & ADIS16204_DIAG_STAT_POWER_LOW)
+ dev_err(&indio_dev->dev, "Power supply below 2.975V\n");
+error_ret:
return ret;
}
@@ -229,10 +182,11 @@ static ssize_t adis16204_read_14bit_signed(struct device *dev,
mutex_lock(&indio_dev->mlock);
- ret = adis16204_spi_read_reg_16(dev, this_attr->address, (u16 *)&val);
+ ret = adis16204_spi_read_reg_16(indio_dev,
+ this_attr->address, (u16 *)&val);
if (!ret) {
if (val & ADIS16204_ERROR_ACTIVE)
- adis16204_check_status(dev);
+ adis16204_check_status(indio_dev);
val = ((s16)(val << 2) >> 2);
ret = sprintf(buf, "%d\n", val);
@@ -243,32 +197,14 @@ static ssize_t adis16204_read_14bit_signed(struct device *dev,
return ret;
}
-static ssize_t adis16204_write_16bit(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+static int adis16204_reset(struct iio_dev *indio_dev)
{
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
- long val;
-
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- goto error_ret;
- ret = adis16204_spi_write_reg_16(dev, this_attr->address, val);
-
-error_ret:
- return ret ? ret : len;
-}
-
-static int adis16204_reset(struct device *dev)
-{
- int ret;
- ret = adis16204_spi_write_reg_8(dev,
+ ret = adis16204_spi_write_reg_8(indio_dev,
ADIS16204_GLOB_CMD,
ADIS16204_GLOB_CMD_SW_RESET);
if (ret)
- dev_err(dev, "problem resetting device");
+ dev_err(&indio_dev->dev, "problem resetting device");
return ret;
}
@@ -277,23 +213,25 @@ static ssize_t adis16204_write_reset(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+
if (len < 1)
return -EINVAL;
switch (buf[0]) {
case '1':
case 'y':
case 'Y':
- return adis16204_reset(dev);
+ return adis16204_reset(indio_dev);
}
return -EINVAL;
}
-int adis16204_set_irq(struct device *dev, bool enable)
+int adis16204_set_irq(struct iio_dev *indio_dev, bool enable)
{
int ret = 0;
u16 msc;
- ret = adis16204_spi_read_reg_16(dev, ADIS16204_MSC_CTRL, &msc);
+ ret = adis16204_spi_read_reg_16(indio_dev, ADIS16204_MSC_CTRL, &msc);
if (ret)
goto error_ret;
@@ -304,106 +242,63 @@ int adis16204_set_irq(struct device *dev, bool enable)
else
msc &= ~ADIS16204_MSC_CTRL_DATA_RDY_EN;
- ret = adis16204_spi_write_reg_16(dev, ADIS16204_MSC_CTRL, msc);
-
-error_ret:
- return ret;
-}
-
-static int adis16204_check_status(struct device *dev)
-{
- u16 status;
- int ret;
-
- ret = adis16204_spi_read_reg_16(dev, ADIS16204_DIAG_STAT, &status);
- if (ret < 0) {
- dev_err(dev, "Reading status failed\n");
- goto error_ret;
- }
- ret = status & 0x1F;
-
- if (status & ADIS16204_DIAG_STAT_SELFTEST_FAIL)
- dev_err(dev, "Self test failure\n");
- if (status & ADIS16204_DIAG_STAT_SPI_FAIL)
- dev_err(dev, "SPI failure\n");
- if (status & ADIS16204_DIAG_STAT_FLASH_UPT)
- dev_err(dev, "Flash update failed\n");
- if (status & ADIS16204_DIAG_STAT_POWER_HIGH)
- dev_err(dev, "Power supply above 3.625V\n");
- if (status & ADIS16204_DIAG_STAT_POWER_LOW)
- dev_err(dev, "Power supply below 2.975V\n");
+ ret = adis16204_spi_write_reg_16(indio_dev, ADIS16204_MSC_CTRL, msc);
error_ret:
return ret;
}
-static int adis16204_self_test(struct device *dev)
+static int adis16204_self_test(struct iio_dev *indio_dev)
{
int ret;
- ret = adis16204_spi_write_reg_16(dev,
+ ret = adis16204_spi_write_reg_16(indio_dev,
ADIS16204_MSC_CTRL,
ADIS16204_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;
}
- adis16204_check_status(dev);
+ adis16204_check_status(indio_dev);
err_ret:
return ret;
}
-static int adis16204_initial_setup(struct adis16204_state *st)
+static int adis16204_initial_setup(struct iio_dev *indio_dev)
{
int ret;
- struct device *dev = &st->indio_dev->dev;
/* Disable IRQ */
- ret = adis16204_set_irq(dev, false);
+ ret = adis16204_set_irq(indio_dev, false);
if (ret) {
- dev_err(dev, "disable irq failed");
+ dev_err(&indio_dev->dev, "disable irq failed");
goto err_ret;
}
/* Do self test */
- ret = adis16204_self_test(dev);
+ ret = adis16204_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 = adis16204_check_status(dev);
+ ret = adis16204_check_status(indio_dev);
if (ret) {
- adis16204_reset(dev);
- dev_err(dev, "device not playing ball -> reset");
+ adis16204_reset(indio_dev);
+ dev_err(&indio_dev->dev, "device not playing ball -> reset");
msleep(ADIS16204_STARTUP_DELAY);
- ret = adis16204_check_status(dev);
+ ret = adis16204_check_status(indio_dev);
if (ret) {
- dev_err(dev, "giving up");
+ dev_err(&indio_dev->dev, "giving up");
goto err_ret;
}
}
- printk(KERN_INFO DRIVER_NAME ": at CS%d (irq %d)\n",
- st->us->chip_select, st->us->irq);
-
err_ret:
return ret;
}
-
-static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16204_read_12bit_unsigned,
- ADIS16204_SUPPLY_OUT);
-static IIO_CONST_ATTR(in0_supply_scale, "0.00122");
-static IIO_DEV_ATTR_IN_RAW(1, adis16204_read_12bit_unsigned,
- ADIS16204_AUX_ADC);
-static IIO_CONST_ATTR(in1_scale, "0.00061");
-
-static IIO_DEV_ATTR_ACCEL_X(adis16204_read_14bit_signed,
- ADIS16204_XACCL_OUT);
-static IIO_DEV_ATTR_ACCEL_Y(adis16204_read_14bit_signed,
- ADIS16204_YACCL_OUT);
static IIO_DEV_ATTR_ACCEL_XY(adis16204_read_14bit_signed,
ADIS16204_XY_RSS_OUT);
static IIO_DEV_ATTR_ACCEL_XPEAK(adis16204_read_14bit_signed,
@@ -412,54 +307,164 @@ 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_DEV_ATTR_ACCEL_X_OFFSET(S_IWUSR | S_IRUGO,
- adis16204_read_12bit_signed,
- adis16204_write_16bit,
- ADIS16204_XACCL_NULL);
-static IIO_DEV_ATTR_ACCEL_Y_OFFSET(S_IWUSR | S_IRUGO,
- adis16204_read_12bit_signed,
- adis16204_write_16bit,
- ADIS16204_YACCL_NULL);
-static IIO_CONST_ATTR(accel_x_scale, "0.017125");
-static IIO_CONST_ATTR(accel_y_scale, "0.008407");
static IIO_CONST_ATTR(accel_xy_scale, "0.017125");
-static IIO_DEV_ATTR_TEMP_RAW(adis16204_read_temp);
-static IIO_CONST_ATTR(temp_offset, "25");
-static IIO_CONST_ATTR(temp_scale, "-0.47");
-
static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16204_write_reset, 0);
-static IIO_CONST_ATTR(name, "adis16204");
-
-static struct attribute *adis16204_event_attributes[] = {
- NULL
+enum adis16204_channel {
+ in_supply,
+ in_aux,
+ temp,
+ accel_x,
+ accel_y,
};
-static struct attribute_group adis16204_event_attribute_group = {
- .attrs = adis16204_event_attributes,
+static u8 adis16204_addresses[5][2] = {
+ [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 },
};
+static int adis16204_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2,
+ long mask)
+{
+ int ret;
+ int bits;
+ u8 addr;
+ s16 val16;
+
+ switch (mask) {
+ case 0:
+ mutex_lock(&indio_dev->mlock);
+ addr = adis16204_addresses[chan->address][0];
+ ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16);
+ if (ret)
+ return ret;
+
+ if (val16 & ADIS16204_ERROR_ACTIVE) {
+ ret = adis16204_check_status(indio_dev);
+ if (ret)
+ return ret;
+ }
+ val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
+ if (chan->scan_type.sign == 's')
+ val16 = (s16)(val16 <<
+ (16 - chan->scan_type.realbits)) >>
+ (16 - chan->scan_type.realbits);
+ *val = val16;
+ mutex_unlock(&indio_dev->mlock);
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ switch (chan->type) {
+ case IIO_IN:
+ *val = 0;
+ if (chan->channel == 0)
+ *val2 = 1220;
+ else
+ *val2 = 610;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_TEMP:
+ *val = 0;
+ *val2 = -470000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_ACCEL:
+ *val = 0;
+ if (chan->channel == 'x')
+ *val2 = 17125;
+ else
+ *val2 = 8407;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ *val = 25;
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ switch (chan->type) {
+ case IIO_ACCEL:
+ bits = 12;
+ break;
+ default:
+ return -EINVAL;
+ };
+ mutex_lock(&indio_dev->mlock);
+ addr = adis16204_addresses[chan->address][1];
+ ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16);
+ if (ret) {
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+ }
+ val16 &= (1 << bits) - 1;
+ val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
+ *val = val16;
+ mutex_unlock(&indio_dev->mlock);
+ return IIO_VAL_INT;
+ }
+ return -EINVAL;
+}
+static int adis16204_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
+{
+ int bits;
+ s16 val16;
+ u8 addr;
+ switch (mask) {
+ case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ switch (chan->type) {
+ case IIO_ACCEL:
+ bits = 12;
+ break;
+ default:
+ return -EINVAL;
+ };
+ val16 = val & ((1 << bits) - 1);
+ addr = adis16204_addresses[chan->address][1];
+ return adis16204_spi_write_reg_16(indio_dev, addr, val16);
+ }
+ return -EINVAL;
+}
+
+static struct iio_chan_spec adis16204_channels[] = {
+ IIO_CHAN(IIO_IN, 0, 0, 0, "supply", 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ in_supply, ADIS16204_SCAN_SUPPLY,
+ IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ in_aux, ADIS16204_SCAN_AUX_ADC,
+ IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE) |
+ (1 << IIO_CHAN_INFO_OFFSET_SEPARATE),
+ temp, ADIS16204_SCAN_TEMP,
+ 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),
+ 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),
+ 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_in0_supply_raw.dev_attr.attr,
- &iio_const_attr_in0_supply_scale.dev_attr.attr,
- &iio_dev_attr_temp_raw.dev_attr.attr,
- &iio_const_attr_temp_offset.dev_attr.attr,
- &iio_const_attr_temp_scale.dev_attr.attr,
&iio_dev_attr_reset.dev_attr.attr,
- &iio_const_attr_name.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_const_attr_in1_scale.dev_attr.attr,
- &iio_dev_attr_accel_x_raw.dev_attr.attr,
- &iio_dev_attr_accel_y_raw.dev_attr.attr,
&iio_dev_attr_accel_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_dev_attr_accel_x_offset.dev_attr.attr,
- &iio_dev_attr_accel_y_offset.dev_attr.attr,
- &iio_const_attr_accel_x_scale.dev_attr.attr,
- &iio_const_attr_accel_y_scale.dev_attr.attr,
&iio_const_attr_accel_xy_scale.dev_attr.attr,
NULL
};
@@ -468,6 +473,13 @@ static const struct attribute_group adis16204_attribute_group = {
.attrs = adis16204_attributes,
};
+static const struct iio_info adis16204_info = {
+ .attrs = &adis16204_attribute_group,
+ .read_raw = &adis16204_read_raw,
+ .write_raw = &adis16204_write_raw,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit adis16204_probe(struct spi_device *spi)
{
int ret, regdone = 0;
@@ -493,18 +505,18 @@ static int __devinit adis16204_probe(struct spi_device *spi)
st->us = spi;
mutex_init(&st->buf_lock);
/* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_tx;
}
+ st->indio_dev->name = spi->dev.driver->name;
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->num_interrupt_lines = 1;
- st->indio_dev->event_attrs = &adis16204_event_attribute_group;
- st->indio_dev->attrs = &adis16204_attribute_group;
+ st->indio_dev->info = &adis16204_info;
+ st->indio_dev->channels = adis16204_channels;
+ st->indio_dev->num_channels = ARRAY_SIZE(adis16204_channels);
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
ret = adis16204_configure_ring(st->indio_dev);
@@ -516,39 +528,30 @@ static int __devinit adis16204_probe(struct spi_device *spi)
goto error_unreg_ring_funcs;
regdone = 1;
- ret = adis16204_initialize_ring(st->indio_dev->ring);
+ ret = iio_ring_buffer_register_ex(st->indio_dev->ring, 0,
+ adis16204_channels,
+ ARRAY_SIZE(adis16204_channels));
if (ret) {
printk(KERN_ERR "failed to initialize the ring\n");
goto error_unreg_ring_funcs;
}
if (spi->irq) {
- ret = iio_register_interrupt_line(spi->irq,
- st->indio_dev,
- 0,
- IRQF_TRIGGER_RISING,
- "adis16204");
- if (ret)
- goto error_uninitialize_ring;
-
ret = adis16204_probe_trigger(st->indio_dev);
if (ret)
- goto error_unregister_line;
+ goto error_uninitialize_ring;
}
/* Get the device into a sane initial state */
- ret = adis16204_initial_setup(st);
+ ret = adis16204_initial_setup(st->indio_dev);
if (ret)
goto error_remove_trigger;
return 0;
error_remove_trigger:
adis16204_remove_trigger(st->indio_dev);
-error_unregister_line:
- if (spi->irq)
- iio_unregister_interrupt_line(st->indio_dev, 0);
error_uninitialize_ring:
- adis16204_uninitialize_ring(st->indio_dev->ring);
+ iio_ring_buffer_unregister(st->indio_dev->ring);
error_unreg_ring_funcs:
adis16204_unconfigure_ring(st->indio_dev);
error_free_dev:
@@ -571,13 +574,8 @@ static int adis16204_remove(struct spi_device *spi)
struct adis16204_state *st = spi_get_drvdata(spi);
struct iio_dev *indio_dev = st->indio_dev;
- flush_scheduled_work();
-
adis16204_remove_trigger(indio_dev);
- if (spi->irq)
- iio_unregister_interrupt_line(indio_dev, 0);
-
- adis16204_uninitialize_ring(indio_dev->ring);
+ iio_ring_buffer_unregister(st->indio_dev->ring);
iio_device_unregister(indio_dev);
adis16204_unconfigure_ring(indio_dev);
kfree(st->tx);
@@ -609,5 +607,5 @@ static __exit void adis16204_exit(void)
module_exit(adis16204_exit);
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
-MODULE_DESCRIPTION("Analog Devices ADIS16204 Programmable High-g Digital Impact Sensor and Recorder");
+MODULE_DESCRIPTION("ADIS16204 High-g Digital Impact Sensor and Recorder");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/accel/adis16204_ring.c b/drivers/staging/iio/accel/adis16204_ring.c
index 420b160fe3ab..a2d36fb822e5 100644
--- a/drivers/staging/iio/accel/adis16204_ring.c
+++ b/drivers/staging/iio/accel/adis16204_ring.c
@@ -17,55 +17,6 @@
#include "../trigger.h"
#include "adis16204.h"
-static IIO_SCAN_EL_C(in_supply, ADIS16204_SCAN_SUPPLY, ADIS16204_SUPPLY_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in_supply, u, 12, 16);
-static IIO_SCAN_EL_C(accel_x, ADIS16204_SCAN_ACC_X, ADIS16204_XACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_y, ADIS16204_SCAN_ACC_Y, ADIS16204_YACCL_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(accel, s, 14, 16);
-static IIO_SCAN_EL_C(in0, ADIS16204_SCAN_AUX_ADC, ADIS16204_AUX_ADC, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in0, u, 12, 16);
-static IIO_SCAN_EL_C(temp, ADIS16204_SCAN_TEMP, ADIS16204_TEMP_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(temp, u, 12, 16);
-static IIO_SCAN_EL_TIMESTAMP(5);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
-
-static struct attribute *adis16204_scan_el_attrs[] = {
- &iio_scan_el_in_supply.dev_attr.attr,
- &iio_const_attr_in_supply_index.dev_attr.attr,
- &iio_const_attr_in_supply_type.dev_attr.attr,
- &iio_scan_el_accel_x.dev_attr.attr,
- &iio_const_attr_accel_x_index.dev_attr.attr,
- &iio_scan_el_accel_y.dev_attr.attr,
- &iio_const_attr_accel_y_index.dev_attr.attr,
- &iio_const_attr_accel_type.dev_attr.attr,
- &iio_scan_el_in0.dev_attr.attr,
- &iio_const_attr_in0_index.dev_attr.attr,
- &iio_const_attr_in0_type.dev_attr.attr,
- &iio_scan_el_temp.dev_attr.attr,
- &iio_const_attr_temp_index.dev_attr.attr,
- &iio_const_attr_temp_type.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group adis16204_scan_el_group = {
- .attrs = adis16204_scan_el_attrs,
- .name = "scan_elements",
-};
-
-/**
- * adis16204_poll_func_th() top half interrupt handler called by trigger
- * @private_data: iio_dev
- **/
-static void adis16204_poll_func_th(struct iio_dev *indio_dev, s64 timestamp)
-{
- struct adis16204_state *st = iio_dev_get_devdata(indio_dev);
- st->last_timestamp = timestamp;
- schedule_work(&st->work_trigger_to_ring);
-}
-
/**
* adis16204_read_ring_data() read data registers which will be placed into ring
* @dev: device associated with child of actual device (iio_dev or iio_trig)
@@ -91,7 +42,8 @@ static int adis16204_read_ring_data(struct device *dev, u8 *rx)
xfers[i].len = 2;
xfers[i].delay_usecs = 20;
xfers[i].tx_buf = st->tx + 2 * i;
- st->tx[2 * i] = ADIS16204_READ_REG(ADIS16204_SUPPLY_OUT + 2 * i);
+ st->tx[2 * i]
+ = ADIS16204_READ_REG(ADIS16204_SUPPLY_OUT + 2 * i);
st->tx[2 * i + 1] = 0;
if (i >= 1)
xfers[i].rx_buf = rx + 2 * (i - 1);
@@ -110,21 +62,20 @@ static int adis16204_read_ring_data(struct device *dev, u8 *rx)
/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
* specific to be rolled into the core.
*/
-static void adis16204_trigger_bh_to_ring(struct work_struct *work_s)
+static irqreturn_t adis16204_trigger_handler(int irq, void *p)
{
- struct adis16204_state *st
- = container_of(work_s, struct adis16204_state,
- work_trigger_to_ring);
- struct iio_ring_buffer *ring = st->indio_dev->ring;
-
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->private_data;
+ struct adis16204_state *st = iio_dev_get_devdata(indio_dev);
+ struct iio_ring_buffer *ring = indio_dev->ring;
int i = 0;
s16 *data;
- size_t datasize = ring->access.get_bytes_per_datum(ring);
+ size_t datasize = ring->access->get_bytes_per_datum(ring);
data = kmalloc(datasize, GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
- return;
+ return -ENOMEM;
}
if (ring->scan_count)
@@ -135,30 +86,32 @@ static void adis16204_trigger_bh_to_ring(struct work_struct *work_s)
/* Guaranteed to be aligned with 8 byte boundary */
if (ring->scan_timestamp)
- *((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
+ *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
- ring->access.store_to(ring,
- (u8 *)data,
- st->last_timestamp);
+ ring->access->store_to(ring, (u8 *)data, pf->timestamp);
iio_trigger_notify_done(st->indio_dev->trig);
kfree(data);
- return;
+ return IRQ_HANDLED;
}
void adis16204_unconfigure_ring(struct iio_dev *indio_dev)
{
- kfree(indio_dev->pollfunc);
+ iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
+static const struct iio_ring_setup_ops adis16204_ring_setup_ops = {
+ .preenable = &iio_sw_ring_preenable,
+ .postenable = &iio_triggered_ring_postenable,
+ .predisable = &iio_triggered_ring_predisable,
+};
+
int adis16204_configure_ring(struct iio_dev *indio_dev)
{
int ret = 0;
- struct adis16204_state *st = indio_dev->dev_data;
struct iio_ring_buffer *ring;
- INIT_WORK(&st->work_trigger_to_ring, adis16204_trigger_bh_to_ring);
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
@@ -167,25 +120,30 @@ int adis16204_configure_ring(struct iio_dev *indio_dev)
}
indio_dev->ring = ring;
/* Effectively select the ring buffer implementation */
- iio_ring_sw_register_funcs(&ring->access);
+ ring->access = &ring_sw_access_funcs;
ring->bpe = 2;
- ring->scan_el_attrs = &adis16204_scan_el_group;
ring->scan_timestamp = true;
- ring->preenable = &iio_sw_ring_preenable;
- ring->postenable = &iio_triggered_ring_postenable;
- ring->predisable = &iio_triggered_ring_predisable;
+ ring->setup_ops = &adis16204_ring_setup_ops;
ring->owner = THIS_MODULE;
/* Set default scan mode */
- iio_scan_mask_set(ring, iio_scan_el_in_supply.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_x.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_y.number);
- iio_scan_mask_set(ring, iio_scan_el_temp.number);
- iio_scan_mask_set(ring, iio_scan_el_in0.number);
-
- ret = iio_alloc_pollfunc(indio_dev, NULL, &adis16204_poll_func_th);
- if (ret)
+ iio_scan_mask_set(ring, ADIS16204_SCAN_SUPPLY);
+ iio_scan_mask_set(ring, ADIS16204_SCAN_ACC_X);
+ iio_scan_mask_set(ring, ADIS16204_SCAN_ACC_Y);
+ iio_scan_mask_set(ring, ADIS16204_SCAN_AUX_ADC);
+ iio_scan_mask_set(ring, ADIS16204_SCAN_TEMP);
+
+ indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
+ &adis16204_trigger_handler,
+ IRQF_ONESHOT,
+ indio_dev,
+ "%s_consumer%d",
+ indio_dev->name,
+ indio_dev->id);
+ if (indio_dev->pollfunc == NULL) {
+ ret = -ENOMEM;
goto error_iio_sw_rb_free;
+ }
indio_dev->modes |= INDIO_RING_TRIGGERED;
return 0;
@@ -194,13 +152,3 @@ error_iio_sw_rb_free:
iio_sw_rb_free(indio_dev->ring);
return ret;
}
-
-int adis16204_initialize_ring(struct iio_ring_buffer *ring)
-{
- return iio_ring_buffer_register(ring, 0);
-}
-
-void adis16204_uninitialize_ring(struct iio_ring_buffer *ring)
-{
- iio_ring_buffer_unregister(ring);
-}
diff --git a/drivers/staging/iio/accel/adis16204_trigger.c b/drivers/staging/iio/accel/adis16204_trigger.c
index 8e9db90e51eb..5e1f9ae9d5c1 100644
--- a/drivers/staging/iio/accel/adis16204_trigger.c
+++ b/drivers/staging/iio/accel/adis16204_trigger.c
@@ -13,35 +13,6 @@
#include "adis16204.h"
/**
- * adis16204_data_rdy_trig_poll() the event handler for the data rdy trig
- **/
-static int adis16204_data_rdy_trig_poll(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct adis16204_state *st = iio_dev_get_devdata(dev_info);
- struct iio_trigger *trig = st->trig;
-
- iio_trigger_poll(trig, timestamp);
-
- return IRQ_HANDLED;
-}
-
-IIO_EVENT_SH(data_rdy_trig, &adis16204_data_rdy_trig_poll);
-
-static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
-
-static struct attribute *adis16204_trigger_attrs[] = {
- &dev_attr_name.attr,
- NULL,
-};
-
-static const struct attribute_group adis16204_trigger_attr_group = {
- .attrs = adis16204_trigger_attrs,
-};
-
-/**
* adis16204_data_rdy_trigger_set_state() set datardy interrupt state
**/
static int adis16204_data_rdy_trigger_set_state(struct iio_trigger *trig,
@@ -49,31 +20,9 @@ static int adis16204_data_rdy_trigger_set_state(struct iio_trigger *trig,
{
struct adis16204_state *st = trig->private_data;
struct iio_dev *indio_dev = st->indio_dev;
- int ret = 0;
dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
- ret = adis16204_set_irq(&st->indio_dev->dev, state);
- if (state == false) {
- iio_remove_event_from_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]
- ->ev_list);
- flush_scheduled_work();
- } else {
- iio_add_event_to_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]->ev_list);
- }
- return ret;
-}
-
-/**
- * adis16204_trig_try_reen() try renabling irq for data rdy trigger
- * @trig: the datardy trigger
- **/
-static int adis16204_trig_try_reen(struct iio_trigger *trig)
-{
- struct adis16204_state *st = trig->private_data;
- enable_irq(st->us->irq);
- return 0;
+ return adis16204_set_irq(st->indio_dev, state);
}
int adis16204_probe_trigger(struct iio_dev *indio_dev)
@@ -81,34 +30,38 @@ int adis16204_probe_trigger(struct iio_dev *indio_dev)
int ret;
struct adis16204_state *st = indio_dev->dev_data;
- st->trig = iio_allocate_trigger();
- st->trig->name = kasprintf(GFP_KERNEL,
- "adis16204-dev%d",
- indio_dev->id);
- if (!st->trig->name) {
+ st->trig = iio_allocate_trigger("adis16204-dev%d", indio_dev->id);
+ if (st->trig == NULL) {
ret = -ENOMEM;
- goto error_free_trig;
+ goto error_ret;
}
+
+ ret = request_irq(st->us->irq,
+ &iio_trigger_generic_data_rdy_poll,
+ IRQF_TRIGGER_RISING,
+ "adis16204",
+ st->trig);
+ if (ret)
+ goto error_free_trig;
+
st->trig->dev.parent = &st->us->dev;
st->trig->owner = THIS_MODULE;
st->trig->private_data = st;
st->trig->set_trigger_state = &adis16204_data_rdy_trigger_set_state;
- st->trig->try_reenable = &adis16204_trig_try_reen;
- st->trig->control_attrs = &adis16204_trigger_attr_group;
ret = iio_trigger_register(st->trig);
/* select default trigger */
indio_dev->trig = st->trig;
if (ret)
- goto error_free_trig_name;
+ goto error_free_irq;
return 0;
-error_free_trig_name:
- kfree(st->trig->name);
+error_free_irq:
+ free_irq(st->us->irq, st->trig);
error_free_trig:
iio_free_trigger(st->trig);
-
+error_ret:
return ret;
}
@@ -117,6 +70,6 @@ void adis16204_remove_trigger(struct iio_dev *indio_dev)
struct adis16204_state *state = indio_dev->dev_data;
iio_trigger_unregister(state->trig);
- kfree(state->trig->name);
+ free_irq(state->us->irq, state->trig);
iio_free_trigger(state->trig);
}
diff --git a/drivers/staging/iio/accel/adis16209.h b/drivers/staging/iio/accel/adis16209.h
index 8b0da1349555..58d08db6f9b5 100644
--- a/drivers/staging/iio/accel/adis16209.h
+++ b/drivers/staging/iio/accel/adis16209.h
@@ -104,8 +104,6 @@
/**
* struct adis16209_state - device instance specific data
* @us: actual spi_device
- * @work_trigger_to_ring: bh for triggered event handling
- * @last_timestamp: passing timestamp from th to bh of interrupt handler
* @indio_dev: industrial I/O device structure
* @trig: data ready trigger registered with iio
* @tx: transmit buffer
@@ -114,8 +112,6 @@
**/
struct adis16209_state {
struct spi_device *us;
- struct work_struct work_trigger_to_ring;
- s64 last_timestamp;
struct iio_dev *indio_dev;
struct iio_trigger *trig;
u8 *tx;
@@ -123,7 +119,7 @@ struct adis16209_state {
struct mutex buf_lock;
};
-int adis16209_set_irq(struct device *dev, bool enable);
+int adis16209_set_irq(struct iio_dev *indio_dev, bool enable);
#ifdef CONFIG_IIO_RING_BUFFER
diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c
index e4ac956208a6..c423cc960254 100644
--- a/drivers/staging/iio/accel/adis16209_core.c
+++ b/drivers/staging/iio/accel/adis16209_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>
@@ -23,27 +20,23 @@
#include "../ring_generic.h"
#include "accel.h"
#include "inclinometer.h"
-#include "../gyro/gyro.h"
#include "../adc/adc.h"
#include "adis16209.h"
#define DRIVER_NAME "adis16209"
-static int adis16209_check_status(struct device *dev);
-
/**
* adis16209_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 actual device
* @reg_address: the address of the register to be written
* @val: the value to write
**/
-static int adis16209_spi_write_reg_8(struct device *dev,
- u8 reg_address,
- u8 val)
+static int adis16209_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 adis16209_state *st = iio_dev_get_devdata(indio_dev);
mutex_lock(&st->buf_lock);
@@ -58,18 +51,17 @@ static int adis16209_spi_write_reg_8(struct device *dev,
/**
* adis16209_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 actual device
* @reg_address: the address of the lower of the two registers. Second register
* is assumed to have address one greater.
* @val: value to be written
**/
-static int adis16209_spi_write_reg_16(struct device *dev,
- u8 lower_reg_address,
- u16 value)
+static int adis16209_spi_write_reg_16(struct iio_dev *indio_dev,
+ u8 lower_reg_address,
+ u16 value)
{
int ret;
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16209_state *st = iio_dev_get_devdata(indio_dev);
struct spi_transfer xfers[] = {
{
@@ -82,7 +74,6 @@ static int adis16209_spi_write_reg_16(struct device *dev,
.tx_buf = st->tx + 2,
.bits_per_word = 8,
.len = 2,
- .cs_change = 1,
.delay_usecs = 30,
},
};
@@ -104,17 +95,16 @@ static int adis16209_spi_write_reg_16(struct device *dev,
/**
* adis16209_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 device
* @reg_address: the address of the lower of the two registers. Second register
* is assumed to have address one greater.
* @val: somewhere to pass back the value read
**/
-static int adis16209_spi_read_reg_16(struct device *dev,
- u8 lower_reg_address,
- u16 *val)
+static int adis16209_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 adis16209_state *st = iio_dev_get_devdata(indio_dev);
int ret;
struct spi_transfer xfers[] = {
@@ -128,7 +118,6 @@ static int adis16209_spi_read_reg_16(struct device *dev,
.rx_buf = st->rx,
.bits_per_word = 8,
.len = 2,
- .cs_change = 1,
.delay_usecs = 30,
},
};
@@ -154,119 +143,14 @@ error_ret:
return ret;
}
-static ssize_t adis16209_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 = adis16209_spi_read_reg_16(dev, this_attr->address, &val);
- if (ret)
- return ret;
-
- if (val & ADIS16209_ERROR_ACTIVE)
- adis16209_check_status(dev);
-
- return sprintf(buf, "%u\n", val & 0x0FFF);
-}
-
-static ssize_t adis16209_read_14bit_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 = adis16209_spi_read_reg_16(dev, this_attr->address, &val);
- if (ret)
- return ret;
-
- if (val & ADIS16209_ERROR_ACTIVE)
- adis16209_check_status(dev);
-
- return sprintf(buf, "%u\n", val & 0x3FFF);
-}
-
-static ssize_t adis16209_read_temp(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ssize_t ret;
- u16 val;
-
- /* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
-
- ret = adis16209_spi_read_reg_16(dev, ADIS16209_TEMP_OUT, (u16 *)&val);
- if (ret)
- goto error_ret;
-
- if (val & ADIS16209_ERROR_ACTIVE)
- adis16209_check_status(dev);
-
- val &= 0xFFF;
- ret = sprintf(buf, "%d\n", val);
-
-error_ret:
- mutex_unlock(&indio_dev->mlock);
- return ret;
-}
-
-static ssize_t adis16209_read_14bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- s16 val = 0;
- ssize_t ret;
-
- mutex_lock(&indio_dev->mlock);
-
- ret = adis16209_spi_read_reg_16(dev, this_attr->address, (u16 *)&val);
- if (!ret) {
- if (val & ADIS16209_ERROR_ACTIVE)
- adis16209_check_status(dev);
-
- val = ((s16)(val << 2) >> 2);
- ret = sprintf(buf, "%d\n", val);
- }
-
- mutex_unlock(&indio_dev->mlock);
-
- return ret;
-}
-
-static ssize_t adis16209_write_16bit(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+static int adis16209_reset(struct iio_dev *indio_dev)
{
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
- long val;
-
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- goto error_ret;
- ret = adis16209_spi_write_reg_16(dev, this_attr->address, val);
-
-error_ret:
- return ret ? ret : len;
-}
-
-static int adis16209_reset(struct device *dev)
-{
- int ret;
- ret = adis16209_spi_write_reg_8(dev,
+ ret = adis16209_spi_write_reg_8(indio_dev,
ADIS16209_GLOB_CMD,
ADIS16209_GLOB_CMD_SW_RESET);
if (ret)
- dev_err(dev, "problem resetting device");
+ dev_err(&indio_dev->dev, "problem resetting device");
return ret;
}
@@ -275,23 +159,25 @@ static ssize_t adis16209_write_reset(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+
if (len < 1)
return -EINVAL;
switch (buf[0]) {
case '1':
case 'y':
case 'Y':
- return adis16209_reset(dev);
+ return adis16209_reset(indio_dev);
}
return -EINVAL;
}
-int adis16209_set_irq(struct device *dev, bool enable)
+int adis16209_set_irq(struct iio_dev *indio_dev, bool enable)
{
int ret = 0;
u16 msc;
- ret = adis16209_spi_read_reg_16(dev, ADIS16209_MSC_CTRL, &msc);
+ ret = adis16209_spi_read_reg_16(indio_dev, ADIS16209_MSC_CTRL, &msc);
if (ret)
goto error_ret;
@@ -302,160 +188,267 @@ int adis16209_set_irq(struct device *dev, bool enable)
else
msc &= ~ADIS16209_MSC_CTRL_DATA_RDY_EN;
- ret = adis16209_spi_write_reg_16(dev, ADIS16209_MSC_CTRL, msc);
+ ret = adis16209_spi_write_reg_16(indio_dev, ADIS16209_MSC_CTRL, msc);
error_ret:
return ret;
}
-static int adis16209_check_status(struct device *dev)
+static int adis16209_check_status(struct iio_dev *indio_dev)
{
u16 status;
int ret;
- ret = adis16209_spi_read_reg_16(dev, ADIS16209_DIAG_STAT, &status);
+ ret = adis16209_spi_read_reg_16(indio_dev,
+ ADIS16209_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 & 0x1F;
if (status & ADIS16209_DIAG_STAT_SELFTEST_FAIL)
- dev_err(dev, "Self test failure\n");
+ dev_err(&indio_dev->dev, "Self test failure\n");
if (status & ADIS16209_DIAG_STAT_SPI_FAIL)
- dev_err(dev, "SPI failure\n");
+ dev_err(&indio_dev->dev, "SPI failure\n");
if (status & ADIS16209_DIAG_STAT_FLASH_UPT)
- dev_err(dev, "Flash update failed\n");
+ dev_err(&indio_dev->dev, "Flash update failed\n");
if (status & ADIS16209_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 & ADIS16209_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 adis16209_self_test(struct device *dev)
+static int adis16209_self_test(struct iio_dev *indio_dev)
{
int ret;
- ret = adis16209_spi_write_reg_16(dev,
+ ret = adis16209_spi_write_reg_16(indio_dev,
ADIS16209_MSC_CTRL,
ADIS16209_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;
}
- adis16209_check_status(dev);
+ adis16209_check_status(indio_dev);
err_ret:
return ret;
}
-static int adis16209_initial_setup(struct adis16209_state *st)
+static int adis16209_initial_setup(struct iio_dev *indio_dev)
{
int ret;
- struct device *dev = &st->indio_dev->dev;
/* Disable IRQ */
- ret = adis16209_set_irq(dev, false);
+ ret = adis16209_set_irq(indio_dev, false);
if (ret) {
- dev_err(dev, "disable irq failed");
+ dev_err(&indio_dev->dev, "disable irq failed");
goto err_ret;
}
/* Do self test */
- ret = adis16209_self_test(dev);
+ ret = adis16209_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 = adis16209_check_status(dev);
+ ret = adis16209_check_status(indio_dev);
if (ret) {
- adis16209_reset(dev);
- dev_err(dev, "device not playing ball -> reset");
+ adis16209_reset(indio_dev);
+ dev_err(&indio_dev->dev, "device not playing ball -> reset");
msleep(ADIS16209_STARTUP_DELAY);
- ret = adis16209_check_status(dev);
+ ret = adis16209_check_status(indio_dev);
if (ret) {
- dev_err(dev, "giving up");
+ dev_err(&indio_dev->dev, "giving up");
goto err_ret;
}
}
- printk(KERN_INFO DRIVER_NAME ": at CS%d (irq %d)\n",
- st->us->chip_select, st->us->irq);
-
err_ret:
return ret;
}
-static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16209_read_14bit_unsigned,
- ADIS16209_SUPPLY_OUT);
-static IIO_CONST_ATTR_IN_NAMED_SCALE(0, supply, "0.30518");
-static IIO_DEV_ATTR_IN_RAW(1, adis16209_read_12bit_unsigned,
- ADIS16209_AUX_ADC);
-static IIO_CONST_ATTR(in1_scale, "0.6105");
-
-static IIO_DEV_ATTR_ACCEL_X(adis16209_read_14bit_signed,
- ADIS16209_XACCL_OUT);
-static IIO_DEV_ATTR_ACCEL_Y(adis16209_read_14bit_signed,
- ADIS16209_YACCL_OUT);
-static IIO_DEV_ATTR_ACCEL_X_CALIBBIAS(S_IWUSR | S_IRUGO,
- adis16209_read_14bit_signed,
- adis16209_write_16bit,
- ADIS16209_XACCL_NULL);
-static IIO_DEV_ATTR_ACCEL_Y_CALIBBIAS(S_IWUSR | S_IRUGO,
- adis16209_read_14bit_signed,
- adis16209_write_16bit,
- ADIS16209_YACCL_NULL);
-static IIO_CONST_ATTR_ACCEL_SCALE("0.002394195531");
-
-static IIO_DEV_ATTR_INCLI_X(adis16209_read_14bit_signed,
- ADIS16209_XINCL_OUT);
-static IIO_DEV_ATTR_INCLI_Y(adis16209_read_14bit_signed,
- ADIS16209_YINCL_OUT);
-static IIO_CONST_ATTR(incli_scale, "0.00043633231");
-
-static IIO_DEVICE_ATTR(rot_raw, S_IRUGO, adis16209_read_14bit_signed,
- NULL, ADIS16209_ROT_OUT);
-
-static IIO_DEV_ATTR_TEMP_RAW(adis16209_read_temp);
-static IIO_CONST_ATTR_TEMP_OFFSET("25");
-static IIO_CONST_ATTR_TEMP_SCALE("-0.47");
+enum adis16209_chan {
+ in_supply,
+ temp,
+ accel_x,
+ accel_y,
+ incli_x,
+ incli_y,
+ in_aux,
+ rot,
+};
-static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16209_write_reset, 0);
+static const u8 adis16209_addresses[8][2] = {
+ [in_supply] = { ADIS16209_SUPPLY_OUT },
+ [in_aux] = { ADIS16209_AUX_ADC },
+ [accel_x] = { ADIS16209_XACCL_OUT, ADIS16209_XACCL_NULL },
+ [accel_y] = { ADIS16209_YACCL_OUT, ADIS16209_YACCL_NULL },
+ [incli_x] = { ADIS16209_XINCL_OUT, ADIS16209_XINCL_NULL },
+ [incli_y] = { ADIS16209_YINCL_OUT, ADIS16209_YINCL_NULL },
+ [rot] = { ADIS16209_ROT_OUT },
+ [temp] = { ADIS16209_TEMP_OUT },
+};
+
+static int adis16209_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
+{
+ int bits;
+ s16 val16;
+ u8 addr;
+ switch (mask) {
+ case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ switch (chan->type) {
+ case IIO_ACCEL:
+ case IIO_INCLI:
+ bits = 14;
+ break;
+ default:
+ return -EINVAL;
+ };
+ val16 = val & ((1 << bits) - 1);
+ addr = adis16209_addresses[chan->address][1];
+ return adis16209_spi_write_reg_16(indio_dev, addr, val16);
+ }
+ return -EINVAL;
+}
-static IIO_CONST_ATTR_NAME("adis16209");
+static int adis16209_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2,
+ long mask)
+{
+ int ret;
+ int bits;
+ u8 addr;
+ s16 val16;
+
+ switch (mask) {
+ case 0:
+ mutex_lock(&indio_dev->mlock);
+ addr = adis16209_addresses[chan->address][0];
+ ret = adis16209_spi_read_reg_16(indio_dev, addr, &val16);
+ if (ret)
+ return ret;
-static struct attribute *adis16209_event_attributes[] = {
- NULL
-};
+ if (val16 & ADIS16209_ERROR_ACTIVE) {
+ ret = adis16209_check_status(indio_dev);
+ if (ret)
+ return ret;
+ }
+ val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
+ if (chan->scan_type.sign == 's')
+ val16 = (s16)(val16 <<
+ (16 - chan->scan_type.realbits)) >>
+ (16 - chan->scan_type.realbits);
+ *val = val16;
+ mutex_unlock(&indio_dev->mlock);
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ switch (chan->type) {
+ case IIO_IN:
+ *val = 0;
+ if (chan->channel == 0)
+ *val2 = 305180;
+ else
+ *val2 = 610500;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_TEMP:
+ *val = 0;
+ *val2 = -470000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_ACCEL:
+ *val = 0;
+ *val2 = 2394;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_INCLI:
+ *val = 0;
+ *val2 = 436;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ *val = 25;
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ switch (chan->type) {
+ case IIO_ACCEL:
+ bits = 14;
+ break;
+ default:
+ return -EINVAL;
+ };
+ mutex_lock(&indio_dev->mlock);
+ addr = adis16209_addresses[chan->address][1];
+ ret = adis16209_spi_read_reg_16(indio_dev, addr, &val16);
+ if (ret) {
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+ }
+ val16 &= (1 << bits) - 1;
+ val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
+ *val = val16;
+ mutex_unlock(&indio_dev->mlock);
+ return IIO_VAL_INT;
+ }
+ return -EINVAL;
+}
-static struct attribute_group adis16209_event_attribute_group = {
- .attrs = adis16209_event_attributes,
+static struct iio_chan_spec adis16209_channels[] = {
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ in_supply, ADIS16209_SCAN_SUPPLY,
+ IIO_ST('u', 14, 16, 0), 0),
+ IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE) |
+ (1 << IIO_CHAN_INFO_OFFSET_SEPARATE),
+ temp, ADIS16209_SCAN_TEMP,
+ IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED) |
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ accel_x, ADIS16209_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_SHARED) |
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ accel_y, ADIS16209_SCAN_ACC_Y,
+ IIO_ST('s', 14, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ in_aux, ADIS16209_SCAN_AUX_ADC,
+ IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_INCLI, 0, 1, 0, NULL, 0, IIO_MOD_X,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ incli_x, ADIS16209_SCAN_INCLI_X,
+ IIO_ST('s', 14, 16, 0), 0),
+ IIO_CHAN(IIO_INCLI, 0, 1, 0, NULL, 0, IIO_MOD_Y,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ incli_y, ADIS16209_SCAN_INCLI_Y,
+ IIO_ST('s', 14, 16, 0), 0),
+ IIO_CHAN(IIO_ROT, 0, 1, 0, NULL, 0, IIO_MOD_X,
+ 0,
+ rot, ADIS16209_SCAN_ROT,
+ IIO_ST('s', 14, 16, 0), 0),
+ IIO_CHAN_SOFT_TIMESTAMP(8)
};
+static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16209_write_reset, 0);
+
static struct attribute *adis16209_attributes[] = {
- &iio_dev_attr_in0_supply_raw.dev_attr.attr,
- &iio_const_attr_in0_supply_scale.dev_attr.attr,
- &iio_dev_attr_temp_raw.dev_attr.attr,
- &iio_const_attr_temp_offset.dev_attr.attr,
- &iio_const_attr_temp_scale.dev_attr.attr,
&iio_dev_attr_reset.dev_attr.attr,
- &iio_const_attr_name.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_const_attr_in1_scale.dev_attr.attr,
- &iio_dev_attr_accel_x_raw.dev_attr.attr,
- &iio_dev_attr_accel_y_raw.dev_attr.attr,
- &iio_dev_attr_accel_x_calibbias.dev_attr.attr,
- &iio_dev_attr_accel_y_calibbias.dev_attr.attr,
- &iio_const_attr_accel_scale.dev_attr.attr,
- &iio_dev_attr_incli_x_raw.dev_attr.attr,
- &iio_dev_attr_incli_y_raw.dev_attr.attr,
- &iio_const_attr_incli_scale.dev_attr.attr,
- &iio_dev_attr_rot_raw.dev_attr.attr,
NULL
};
@@ -463,6 +456,13 @@ static const struct attribute_group adis16209_attribute_group = {
.attrs = adis16209_attributes,
};
+static const struct iio_info adis16209_info = {
+ .attrs = &adis16209_attribute_group,
+ .read_raw = &adis16209_read_raw,
+ .write_raw = &adis16209_write_raw,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit adis16209_probe(struct spi_device *spi)
{
int ret, regdone = 0;
@@ -488,18 +488,18 @@ static int __devinit adis16209_probe(struct spi_device *spi)
st->us = spi;
mutex_init(&st->buf_lock);
/* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_tx;
}
+ st->indio_dev->name = spi->dev.driver->name;
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->num_interrupt_lines = 1;
- st->indio_dev->event_attrs = &adis16209_event_attribute_group;
- st->indio_dev->attrs = &adis16209_attribute_group;
+ st->indio_dev->info = &adis16209_info;
+ st->indio_dev->channels = adis16209_channels;
+ st->indio_dev->num_channels = ARRAY_SIZE(adis16209_channels);
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
ret = adis16209_configure_ring(st->indio_dev);
@@ -511,37 +511,28 @@ static int __devinit adis16209_probe(struct spi_device *spi)
goto error_unreg_ring_funcs;
regdone = 1;
- ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
+ ret = iio_ring_buffer_register_ex(st->indio_dev->ring, 0,
+ adis16209_channels,
+ ARRAY_SIZE(adis16209_channels));
if (ret) {
printk(KERN_ERR "failed to initialize the ring\n");
goto error_unreg_ring_funcs;
}
if (spi->irq) {
- ret = iio_register_interrupt_line(spi->irq,
- st->indio_dev,
- 0,
- IRQF_TRIGGER_RISING,
- "adis16209");
- if (ret)
- goto error_uninitialize_ring;
-
ret = adis16209_probe_trigger(st->indio_dev);
if (ret)
- goto error_unregister_line;
+ goto error_uninitialize_ring;
}
/* Get the device into a sane initial state */
- ret = adis16209_initial_setup(st);
+ ret = adis16209_initial_setup(st->indio_dev);
if (ret)
goto error_remove_trigger;
return 0;
error_remove_trigger:
adis16209_remove_trigger(st->indio_dev);
-error_unregister_line:
- if (spi->irq)
- iio_unregister_interrupt_line(st->indio_dev, 0);
error_uninitialize_ring:
iio_ring_buffer_unregister(st->indio_dev->ring);
error_unreg_ring_funcs:
@@ -569,9 +560,6 @@ static int adis16209_remove(struct spi_device *spi)
flush_scheduled_work();
adis16209_remove_trigger(indio_dev);
- if (spi->irq)
- iio_unregister_interrupt_line(indio_dev, 0);
-
iio_ring_buffer_unregister(indio_dev->ring);
iio_device_unregister(indio_dev);
adis16209_unconfigure_ring(indio_dev);
diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c
index 8eba0af98ed5..390908b3f02f 100644
--- a/drivers/staging/iio/accel/adis16209_ring.c
+++ b/drivers/staging/iio/accel/adis16209_ring.c
@@ -17,71 +17,6 @@
#include "../trigger.h"
#include "adis16209.h"
-static IIO_SCAN_EL_C(in_supply, ADIS16209_SCAN_SUPPLY,
- ADIS16209_SUPPLY_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in_supply, u, 14, 16)
-static IIO_SCAN_EL_C(accel_x, ADIS16209_SCAN_ACC_X, ADIS16209_XACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_y, ADIS16209_SCAN_ACC_Y, ADIS16209_YACCL_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(accel, s, 14, 16);
-static IIO_SCAN_EL_C(in0, ADIS16209_SCAN_AUX_ADC, ADIS16209_AUX_ADC, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in0, u, 12, 16);
-static IIO_SCAN_EL_C(temp, ADIS16209_SCAN_TEMP, ADIS16209_TEMP_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(temp, u, 12, 16);
-static IIO_SCAN_EL_C(incli_x, ADIS16209_SCAN_INCLI_X,
- ADIS16209_XINCL_OUT, NULL);
-static IIO_SCAN_EL_C(incli_y, ADIS16209_SCAN_INCLI_Y,
- ADIS16209_YINCL_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(incli, s, 14, 16);
-static IIO_SCAN_EL_C(rot, ADIS16209_SCAN_ROT, ADIS16209_ROT_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(rot, s, 14, 16);
-static IIO_SCAN_EL_TIMESTAMP(8);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
-
-static struct attribute *adis16209_scan_el_attrs[] = {
- &iio_scan_el_in_supply.dev_attr.attr,
- &iio_const_attr_in_supply_index.dev_attr.attr,
- &iio_const_attr_in_supply_type.dev_attr.attr,
- &iio_scan_el_accel_x.dev_attr.attr,
- &iio_const_attr_accel_x_index.dev_attr.attr,
- &iio_scan_el_accel_y.dev_attr.attr,
- &iio_const_attr_accel_y_index.dev_attr.attr,
- &iio_const_attr_accel_type.dev_attr.attr,
- &iio_scan_el_in0.dev_attr.attr,
- &iio_const_attr_in0_index.dev_attr.attr,
- &iio_const_attr_in0_type.dev_attr.attr,
- &iio_scan_el_temp.dev_attr.attr,
- &iio_const_attr_temp_index.dev_attr.attr,
- &iio_const_attr_temp_type.dev_attr.attr,
- &iio_scan_el_incli_x.dev_attr.attr,
- &iio_const_attr_incli_x_index.dev_attr.attr,
- &iio_scan_el_incli_y.dev_attr.attr,
- &iio_const_attr_incli_y_index.dev_attr.attr,
- &iio_const_attr_incli_type.dev_attr.attr,
- &iio_scan_el_rot.dev_attr.attr,
- &iio_const_attr_rot_index.dev_attr.attr,
- &iio_const_attr_rot_type.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group adis16209_scan_el_group = {
- .attrs = adis16209_scan_el_attrs,
- .name = "scan_elements",
-};
-
-/**
- * adis16209_poll_func_th() top half interrupt handler called by trigger
- * @private_data: iio_dev
- **/
-static void adis16209_poll_func_th(struct iio_dev *indio_dev, s64 time)
-{
- struct adis16209_state *st = iio_dev_get_devdata(indio_dev);
- st->last_timestamp = time;
- schedule_work(&st->work_trigger_to_ring);
-}
-
/**
* adis16209_read_ring_data() read data registers which will be placed into ring
* @dev: device associated with child of actual device (iio_dev or iio_trig)
@@ -127,55 +62,56 @@ static int adis16209_read_ring_data(struct device *dev, u8 *rx)
/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
* specific to be rolled into the core.
*/
-static void adis16209_trigger_bh_to_ring(struct work_struct *work_s)
+static irqreturn_t adis16209_trigger_handler(int irq, void *p)
{
- struct adis16209_state *st
- = container_of(work_s, struct adis16209_state,
- work_trigger_to_ring);
- struct iio_ring_buffer *ring = st->indio_dev->ring;
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->private_data;
+ struct adis16209_state *st = iio_dev_get_devdata(indio_dev);
+ struct iio_ring_buffer *ring = indio_dev->ring;
int i = 0;
s16 *data;
- size_t datasize = ring->access.get_bytes_per_datum(ring);
+ size_t datasize = ring->access->get_bytes_per_datum(ring);
data = kmalloc(datasize , GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
- return;
+ return -ENOMEM;
}
- if (ring->scan_count)
- if (adis16209_read_ring_data(&st->indio_dev->dev, st->rx) >= 0)
- for (; i < ring->scan_count; i++)
- data[i] = be16_to_cpup(
- (__be16 *)&(st->rx[i*2]));
+ if (ring->scan_count &&
+ adis16209_read_ring_data(&st->indio_dev->dev, st->rx) >= 0)
+ for (; i < ring->scan_count; i++)
+ data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
if (ring->scan_timestamp)
- *((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
+ *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
- ring->access.store_to(ring,
- (u8 *)data,
- st->last_timestamp);
+ ring->access->store_to(ring, (u8 *)data, pf->timestamp);
iio_trigger_notify_done(st->indio_dev->trig);
kfree(data);
- return;
+ return IRQ_HANDLED;
}
void adis16209_unconfigure_ring(struct iio_dev *indio_dev)
{
- kfree(indio_dev->pollfunc);
+ iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
+static const struct iio_ring_setup_ops adis16209_ring_setup_ops = {
+ .preenable = &iio_sw_ring_preenable,
+ .postenable = &iio_triggered_ring_postenable,
+ .predisable = &iio_triggered_ring_predisable,
+};
+
int adis16209_configure_ring(struct iio_dev *indio_dev)
{
int ret = 0;
- struct adis16209_state *st = indio_dev->dev_data;
struct iio_ring_buffer *ring;
- INIT_WORK(&st->work_trigger_to_ring, adis16209_trigger_bh_to_ring);
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
@@ -184,28 +120,33 @@ int adis16209_configure_ring(struct iio_dev *indio_dev)
}
indio_dev->ring = ring;
/* Effectively select the ring buffer implementation */
- iio_ring_sw_register_funcs(&ring->access);
+ ring->access = &ring_sw_access_funcs;
ring->bpe = 2;
- ring->scan_el_attrs = &adis16209_scan_el_group;
ring->scan_timestamp = true;
- ring->preenable = &iio_sw_ring_preenable;
- ring->postenable = &iio_triggered_ring_postenable;
- ring->predisable = &iio_triggered_ring_predisable;
+ ring->setup_ops = &adis16209_ring_setup_ops;
ring->owner = THIS_MODULE;
/* Set default scan mode */
- iio_scan_mask_set(ring, iio_scan_el_in_supply.number);
- iio_scan_mask_set(ring, iio_scan_el_rot.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_x.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_y.number);
- iio_scan_mask_set(ring, iio_scan_el_temp.number);
- iio_scan_mask_set(ring, iio_scan_el_in0.number);
- iio_scan_mask_set(ring, iio_scan_el_incli_x.number);
- iio_scan_mask_set(ring, iio_scan_el_incli_y.number);
-
- ret = iio_alloc_pollfunc(indio_dev, NULL, &adis16209_poll_func_th);
- if (ret)
+ iio_scan_mask_set(ring, ADIS16209_SCAN_SUPPLY);
+ iio_scan_mask_set(ring, ADIS16209_SCAN_ACC_X);
+ iio_scan_mask_set(ring, ADIS16209_SCAN_ACC_Y);
+ iio_scan_mask_set(ring, ADIS16209_SCAN_AUX_ADC);
+ iio_scan_mask_set(ring, ADIS16209_SCAN_TEMP);
+ iio_scan_mask_set(ring, ADIS16209_SCAN_INCLI_X);
+ iio_scan_mask_set(ring, ADIS16209_SCAN_INCLI_Y);
+ iio_scan_mask_set(ring, ADIS16209_SCAN_ROT);
+
+ indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
+ &adis16209_trigger_handler,
+ IRQF_ONESHOT,
+ indio_dev,
+ "%s_consumer%d",
+ indio_dev->name,
+ indio_dev->id);
+ if (indio_dev->pollfunc == NULL) {
+ ret = -ENOMEM;
goto error_iio_sw_rb_free;
+ }
indio_dev->modes |= INDIO_RING_TRIGGERED;
return 0;
diff --git a/drivers/staging/iio/accel/adis16209_trigger.c b/drivers/staging/iio/accel/adis16209_trigger.c
index d2980dc74440..211ee7045697 100644
--- a/drivers/staging/iio/accel/adis16209_trigger.c
+++ b/drivers/staging/iio/accel/adis16209_trigger.c
@@ -15,32 +15,12 @@
/**
* adis16209_data_rdy_trig_poll() the event handler for the data rdy trig
**/
-static int adis16209_data_rdy_trig_poll(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
+static irqreturn_t adis16209_data_rdy_trig_poll(int irq, void *trig)
{
- struct adis16209_state *st = iio_dev_get_devdata(dev_info);
- struct iio_trigger *trig = st->trig;
-
- iio_trigger_poll(trig, timestamp);
-
+ iio_trigger_poll(trig, iio_get_time_ns());
return IRQ_HANDLED;
}
-IIO_EVENT_SH(data_rdy_trig, &adis16209_data_rdy_trig_poll);
-
-static IIO_TRIGGER_NAME_ATTR;
-
-static struct attribute *adis16209_trigger_attrs[] = {
- &dev_attr_name.attr,
- NULL,
-};
-
-static const struct attribute_group adis16209_trigger_attr_group = {
- .attrs = adis16209_trigger_attrs,
-};
-
/**
* adis16209_data_rdy_trigger_set_state() set datardy interrupt state
**/
@@ -49,31 +29,9 @@ static int adis16209_data_rdy_trigger_set_state(struct iio_trigger *trig,
{
struct adis16209_state *st = trig->private_data;
struct iio_dev *indio_dev = st->indio_dev;
- int ret = 0;
dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
- ret = adis16209_set_irq(&st->indio_dev->dev, state);
- if (state == false) {
- iio_remove_event_from_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]
- ->ev_list);
- flush_scheduled_work();
- } else {
- iio_add_event_to_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]->ev_list);
- }
- return ret;
-}
-
-/**
- * adis16209_trig_try_reen() try renabling irq for data rdy trigger
- * @trig: the datardy trigger
- **/
-static int adis16209_trig_try_reen(struct iio_trigger *trig)
-{
- struct adis16209_state *st = trig->private_data;
- enable_irq(st->us->irq);
- return 0;
+ return adis16209_set_irq(st->indio_dev, state);
}
int adis16209_probe_trigger(struct iio_dev *indio_dev)
@@ -81,34 +39,37 @@ int adis16209_probe_trigger(struct iio_dev *indio_dev)
int ret;
struct adis16209_state *st = indio_dev->dev_data;
- st->trig = iio_allocate_trigger();
- st->trig->name = kasprintf(GFP_KERNEL,
- "adis16209-dev%d",
- indio_dev->id);
- if (!st->trig->name) {
+ st->trig = iio_allocate_trigger("adis16209-dev%d", indio_dev->id);
+ if (st->trig == NULL) {
ret = -ENOMEM;
- goto error_free_trig;
+ goto error_ret;
}
+
+ ret = request_irq(st->us->irq,
+ adis16209_data_rdy_trig_poll,
+ IRQF_TRIGGER_RISING,
+ "adis16209",
+ st->trig);
+ if (ret)
+ goto error_free_trig;
st->trig->dev.parent = &st->us->dev;
st->trig->owner = THIS_MODULE;
st->trig->private_data = st;
st->trig->set_trigger_state = &adis16209_data_rdy_trigger_set_state;
- st->trig->try_reenable = &adis16209_trig_try_reen;
- st->trig->control_attrs = &adis16209_trigger_attr_group;
ret = iio_trigger_register(st->trig);
/* select default trigger */
indio_dev->trig = st->trig;
if (ret)
- goto error_free_trig_name;
+ goto error_free_irq;
return 0;
-error_free_trig_name:
- kfree(st->trig->name);
+error_free_irq:
+ free_irq(st->us->irq, st->trig);
error_free_trig:
iio_free_trigger(st->trig);
-
+error_ret:
return ret;
}
@@ -117,6 +78,6 @@ void adis16209_remove_trigger(struct iio_dev *indio_dev)
struct adis16209_state *state = indio_dev->dev_data;
iio_trigger_unregister(state->trig);
- kfree(state->trig->name);
+ free_irq(state->us->irq, state->trig);
iio_free_trigger(state->trig);
}
diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c
index 1c1e98aee2d9..605a75ea3996 100644
--- a/drivers/staging/iio/accel/adis16220_core.c
+++ b/drivers/staging/iio/accel/adis16220_core.c
@@ -521,8 +521,6 @@ static IIO_DEV_ATTR_CAPTURE_COUNT(S_IWUSR | S_IRUGO,
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100200");
-static IIO_CONST_ATTR_NAME("adis16220");
-
static struct attribute *adis16220_attributes[] = {
&iio_dev_attr_in0_supply_raw.dev_attr.attr,
&iio_const_attr_in0_supply_scale.dev_attr.attr,
@@ -539,7 +537,6 @@ static struct attribute *adis16220_attributes[] = {
&iio_dev_attr_reset.dev_attr.attr,
&iio_dev_attr_capture.dev_attr.attr,
&iio_dev_attr_capture_count.dev_attr.attr,
- &iio_const_attr_name.dev_attr.attr,
NULL
};
@@ -547,6 +544,10 @@ static const struct attribute_group adis16220_attribute_group = {
.attrs = adis16220_attributes,
};
+static const struct iio_info adis16220_info = {
+ .attrs = &adis16220_attribute_group,
+ .driver_module = THIS_MODULE,
+};
static int __devinit adis16220_probe(struct spi_device *spi)
{
int ret, regdone = 0;
@@ -572,16 +573,16 @@ static int __devinit adis16220_probe(struct spi_device *spi)
st->us = spi;
mutex_init(&st->buf_lock);
/* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_tx;
}
+ st->indio_dev->name = spi->dev.driver->name;
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->attrs = &adis16220_attribute_group;
+ st->indio_dev->info = &adis16220_info;
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(st->indio_dev);
diff --git a/drivers/staging/iio/accel/adis16240.h b/drivers/staging/iio/accel/adis16240.h
index 76a45797b9dd..162b1f468a1a 100644
--- a/drivers/staging/iio/accel/adis16240.h
+++ b/drivers/staging/iio/accel/adis16240.h
@@ -126,9 +126,6 @@
/**
* struct adis16240_state - device instance specific data
* @us: actual spi_device
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter: used to check if new interrupt has been triggered
- * @last_timestamp: passing timestamp from th to bh of interrupt handler
* @indio_dev: industrial I/O device structure
* @trig: data ready trigger registered with iio
* @tx: transmit buffer
@@ -137,8 +134,6 @@
**/
struct adis16240_state {
struct spi_device *us;
- struct work_struct work_trigger_to_ring;
- s64 last_timestamp;
struct iio_dev *indio_dev;
struct iio_trigger *trig;
u8 *tx;
@@ -146,7 +141,7 @@ struct adis16240_state {
struct mutex buf_lock;
};
-int adis16240_set_irq(struct device *dev, bool enable);
+int adis16240_set_irq(struct iio_dev *indio_dev, bool enable);
#ifdef CONFIG_IIO_RING_BUFFER
/* At the moment triggers are only used for ring buffer
diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c
index d11d164207ee..ac6038557b0d 100644
--- a/drivers/staging/iio/accel/adis16240_core.c
+++ b/drivers/staging/iio/accel/adis16240_core.c
@@ -28,20 +28,19 @@
#define DRIVER_NAME "adis16240"
-static int adis16240_check_status(struct device *dev);
+static int adis16240_check_status(struct iio_dev *indio_dev);
/**
* adis16240_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_dev associated with device
* @reg_address: the address of the register to be written
* @val: the value to write
**/
-static int adis16240_spi_write_reg_8(struct device *dev,
- u8 reg_address,
- u8 val)
+static int adis16240_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 adis16240_state *st = iio_dev_get_devdata(indio_dev);
mutex_lock(&st->buf_lock);
@@ -56,18 +55,17 @@ static int adis16240_spi_write_reg_8(struct device *dev,
/**
* adis16240_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_dev for this device
* @reg_address: the address of the lower of the two registers. Second register
* is assumed to have address one greater.
* @val: value to be written
**/
-static int adis16240_spi_write_reg_16(struct device *dev,
- u8 lower_reg_address,
- u16 value)
+static int adis16240_spi_write_reg_16(struct iio_dev *indio_dev,
+ u8 lower_reg_address,
+ u16 value)
{
int ret;
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16240_state *st = iio_dev_get_devdata(indio_dev);
struct spi_transfer xfers[] = {
{
@@ -80,7 +78,6 @@ static int adis16240_spi_write_reg_16(struct device *dev,
.tx_buf = st->tx + 2,
.bits_per_word = 8,
.len = 2,
- .cs_change = 1,
.delay_usecs = 35,
},
};
@@ -102,17 +99,16 @@ static int adis16240_spi_write_reg_16(struct device *dev,
/**
* adis16240_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_dev for this device
* @reg_address: the address of the lower of the two registers. Second register
* is assumed to have address one greater.
* @val: somewhere to pass back the value read
**/
-static int adis16240_spi_read_reg_16(struct device *dev,
+static int adis16240_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 adis16240_state *st = iio_dev_get_devdata(indio_dev);
int ret;
struct spi_transfer xfers[] = {
@@ -159,61 +155,30 @@ static ssize_t adis16240_spi_read_signed(struct device *dev,
char *buf,
unsigned bits)
{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
int ret;
s16 val = 0;
unsigned shift = 16 - bits;
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- ret = adis16240_spi_read_reg_16(dev, this_attr->address, (u16 *)&val);
+ ret = adis16240_spi_read_reg_16(indio_dev,
+ this_attr->address, (u16 *)&val);
if (ret)
return ret;
if (val & ADIS16240_ERROR_ACTIVE)
- adis16240_check_status(dev);
+ adis16240_check_status(indio_dev);
val = ((s16)(val << shift) >> shift);
return sprintf(buf, "%d\n", val);
}
-static ssize_t adis16240_read_10bit_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 = adis16240_spi_read_reg_16(dev, this_attr->address, &val);
- if (ret)
- return ret;
-
- if (val & ADIS16240_ERROR_ACTIVE)
- adis16240_check_status(dev);
-
- return sprintf(buf, "%u\n", val & 0x03FF);
-}
-
-static ssize_t adis16240_read_10bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ssize_t ret;
-
- /* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
- ret = adis16240_spi_read_signed(dev, attr, buf, 10);
- mutex_unlock(&indio_dev->mlock);
-
- return ret;
-}
-
static ssize_t adis16240_read_12bit_signed(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
ssize_t ret;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
/* Take the iio_dev status lock */
mutex_lock(&indio_dev->mlock);
@@ -223,32 +188,14 @@ static ssize_t adis16240_read_12bit_signed(struct device *dev,
return ret;
}
-static ssize_t adis16240_write_16bit(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+static int adis16240_reset(struct iio_dev *indio_dev)
{
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
- long val;
-
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- goto error_ret;
- ret = adis16240_spi_write_reg_16(dev, this_attr->address, val);
-
-error_ret:
- return ret ? ret : len;
-}
-
-static int adis16240_reset(struct device *dev)
-{
- int ret;
- ret = adis16240_spi_write_reg_8(dev,
+ ret = adis16240_spi_write_reg_8(indio_dev,
ADIS16240_GLOB_CMD,
ADIS16240_GLOB_CMD_SW_RESET);
if (ret)
- dev_err(dev, "problem resetting device");
+ dev_err(&indio_dev->dev, "problem resetting device");
return ret;
}
@@ -257,23 +204,26 @@ static ssize_t adis16240_write_reset(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+
if (len < 1)
return -EINVAL;
switch (buf[0]) {
case '1':
case 'y':
case 'Y':
- return adis16240_reset(dev);
+ return adis16240_reset(indio_dev);
}
return -EINVAL;
}
-int adis16240_set_irq(struct device *dev, bool enable)
+int adis16240_set_irq(struct iio_dev *indio_dev, bool enable)
{
int ret = 0;
u16 msc;
- ret = adis16240_spi_read_reg_16(dev, ADIS16240_MSC_CTRL, &msc);
+ ret = adis16240_spi_read_reg_16(indio_dev,
+ ADIS16240_MSC_CTRL, &msc);
if (ret)
goto error_ret;
@@ -284,37 +234,40 @@ int adis16240_set_irq(struct device *dev, bool enable)
else
msc &= ~ADIS16240_MSC_CTRL_DATA_RDY_EN;
- ret = adis16240_spi_write_reg_16(dev, ADIS16240_MSC_CTRL, msc);
+ ret = adis16240_spi_write_reg_16(indio_dev,
+ ADIS16240_MSC_CTRL, msc);
error_ret:
return ret;
}
-static int adis16240_self_test(struct device *dev)
+static int adis16240_self_test(struct iio_dev *indio_dev)
{
int ret;
- ret = adis16240_spi_write_reg_16(dev,
+ ret = adis16240_spi_write_reg_16(indio_dev,
ADIS16240_MSC_CTRL,
ADIS16240_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;
}
msleep(ADIS16240_STARTUP_DELAY);
- adis16240_check_status(dev);
+ adis16240_check_status(indio_dev);
err_ret:
return ret;
}
-static int adis16240_check_status(struct device *dev)
+static int adis16240_check_status(struct iio_dev *indio_dev)
{
u16 status;
int ret;
+ struct device *dev = &indio_dev->dev;
- ret = adis16240_spi_read_reg_16(dev, ADIS16240_DIAG_STAT, &status);
+ ret = adis16240_spi_read_reg_16(indio_dev,
+ ADIS16240_DIAG_STAT, &status);
if (ret < 0) {
dev_err(dev, "Reading status failed\n");
@@ -337,122 +290,216 @@ error_ret:
return ret;
}
-static int adis16240_initial_setup(struct adis16240_state *st)
+static int adis16240_initial_setup(struct iio_dev *indio_dev)
{
int ret;
- struct device *dev = &st->indio_dev->dev;
+ struct device *dev = &indio_dev->dev;
/* Disable IRQ */
- ret = adis16240_set_irq(dev, false);
+ ret = adis16240_set_irq(indio_dev, false);
if (ret) {
dev_err(dev, "disable irq failed");
goto err_ret;
}
/* Do self test */
- ret = adis16240_self_test(dev);
+ ret = adis16240_self_test(indio_dev);
if (ret) {
dev_err(dev, "self test failure");
goto err_ret;
}
/* Read status register to check the result */
- ret = adis16240_check_status(dev);
+ ret = adis16240_check_status(indio_dev);
if (ret) {
- adis16240_reset(dev);
+ adis16240_reset(indio_dev);
dev_err(dev, "device not playing ball -> reset");
msleep(ADIS16240_STARTUP_DELAY);
- ret = adis16240_check_status(dev);
+ ret = adis16240_check_status(indio_dev);
if (ret) {
dev_err(dev, "giving up");
goto err_ret;
}
}
- printk(KERN_INFO DRIVER_NAME ": at CS%d (irq %d)\n",
- st->us->chip_select, st->us->irq);
-
err_ret:
return ret;
}
-static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16240_read_10bit_unsigned,
- ADIS16240_SUPPLY_OUT);
-static IIO_DEV_ATTR_IN_RAW(1, adis16240_read_10bit_signed,
- ADIS16240_AUX_ADC);
-static IIO_CONST_ATTR_IN_NAMED_SCALE(0, supply, "0.00488");
-
-static IIO_CONST_ATTR_ACCEL_SCALE("0.50406181");
-static IIO_CONST_ATTR(accel_peak_scale, "6.6292954");
-static IIO_DEV_ATTR_ACCEL_X(adis16240_read_10bit_signed,
- ADIS16240_XACCL_OUT);
-static IIO_DEVICE_ATTR(accel_x_peak_raw, S_IRUGO,
- adis16240_read_10bit_signed, NULL,
- ADIS16240_XPEAK_OUT);
-static IIO_DEV_ATTR_ACCEL_Y(adis16240_read_10bit_signed,
- ADIS16240_YACCL_OUT);
-static IIO_DEVICE_ATTR(accel_y_peak_raw, S_IRUGO,
- adis16240_read_10bit_signed, NULL,
- ADIS16240_YPEAK_OUT);
-static IIO_DEV_ATTR_ACCEL_Z(adis16240_read_10bit_signed,
- ADIS16240_ZACCL_OUT);
-static IIO_DEVICE_ATTR(accel_z_peak_raw, S_IRUGO,
- adis16240_read_10bit_signed, NULL,
- ADIS16240_ZPEAK_OUT);
-
static IIO_DEVICE_ATTR(accel_xyz_squared_peak_raw, S_IRUGO,
adis16240_read_12bit_signed, NULL,
ADIS16240_XYZPEAK_OUT);
-static IIO_DEV_ATTR_ACCEL_X_CALIBBIAS(S_IWUSR | S_IRUGO,
- adis16240_read_10bit_signed,
- adis16240_write_16bit,
- ADIS16240_XACCL_OFF);
-static IIO_DEV_ATTR_ACCEL_Y_CALIBBIAS(S_IWUSR | S_IRUGO,
- adis16240_read_10bit_signed,
- adis16240_write_16bit,
- ADIS16240_YACCL_OFF);
-static IIO_DEV_ATTR_ACCEL_Z_CALIBBIAS(S_IWUSR | S_IRUGO,
- adis16240_read_10bit_signed,
- adis16240_write_16bit,
- ADIS16240_ZACCL_OFF);
-static IIO_DEV_ATTR_TEMP_RAW(adis16240_read_10bit_unsigned);
-static IIO_CONST_ATTR_TEMP_SCALE("0.244");
static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16240_write_reset, 0);
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("4096");
-static IIO_CONST_ATTR_NAME("adis16240");
+enum adis16240_chan {
+ in_supply,
+ in_aux,
+ accel_x,
+ accel_y,
+ accel_z,
+ temp,
+};
-static struct attribute *adis16240_event_attributes[] = {
- NULL
+static const u8 adis16240_addresses[6][3] = {
+ [in_supply] = { ADIS16240_SUPPLY_OUT },
+ [in_aux] = { ADIS16240_AUX_ADC },
+ [accel_x] = { ADIS16240_XACCL_OUT, ADIS16240_XACCL_OFF,
+ ADIS16240_XPEAK_OUT },
+ [accel_y] = { ADIS16240_YACCL_OUT, ADIS16240_YACCL_OFF,
+ ADIS16240_YPEAK_OUT },
+ [accel_z] = { ADIS16240_ZACCL_OUT, ADIS16240_ZACCL_OFF,
+ ADIS16240_ZPEAK_OUT },
+ [temp] = { ADIS16240_TEMP_OUT },
};
-static struct attribute_group adis16240_event_attribute_group = {
- .attrs = adis16240_event_attributes,
+static int adis16240_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2,
+ long mask)
+{
+ int ret;
+ int bits;
+ u8 addr;
+ s16 val16;
+
+ switch (mask) {
+ case 0:
+ mutex_lock(&indio_dev->mlock);
+ addr = adis16240_addresses[chan->address][0];
+ ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16);
+ if (ret)
+ return ret;
+
+ if (val16 & ADIS16240_ERROR_ACTIVE) {
+ ret = adis16240_check_status(indio_dev);
+ if (ret)
+ return ret;
+ }
+ val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
+ if (chan->scan_type.sign == 's')
+ val16 = (s16)(val16 <<
+ (16 - chan->scan_type.realbits)) >>
+ (16 - chan->scan_type.realbits);
+ *val = val16;
+ mutex_unlock(&indio_dev->mlock);
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ switch (chan->type) {
+ case IIO_IN:
+ *val = 0;
+ if (chan->channel == 0)
+ *val2 = 4880;
+ else
+ return -EINVAL;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_TEMP:
+ *val = 0;
+ *val2 = 244000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_ACCEL:
+ *val = 0;
+ *val2 = 504062;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case (1 << IIO_CHAN_INFO_PEAK_SCALE_SHARED):
+ *val = 6;
+ *val2 = 629295;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ *val = 25;
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ bits = 10;
+ mutex_lock(&indio_dev->mlock);
+ addr = adis16240_addresses[chan->address][1];
+ ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16);
+ if (ret) {
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+ }
+ val16 &= (1 << bits) - 1;
+ val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
+ *val = val16;
+ mutex_unlock(&indio_dev->mlock);
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_PEAK_SEPARATE):
+ bits = 10;
+ mutex_lock(&indio_dev->mlock);
+ addr = adis16240_addresses[chan->address][2];
+ ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16);
+ if (ret) {
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+ }
+ val16 &= (1 << bits) - 1;
+ val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
+ *val = val16;
+ mutex_unlock(&indio_dev->mlock);
+ return IIO_VAL_INT;
+ }
+ return -EINVAL;
+}
+
+static int adis16240_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
+{
+ int bits = 10;
+ s16 val16;
+ u8 addr;
+ switch (mask) {
+ case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ val16 = val & ((1 << bits) - 1);
+ addr = adis16240_addresses[chan->address][1];
+ return adis16240_spi_write_reg_16(indio_dev, addr, val16);
+ }
+ return -EINVAL;
+}
+
+static struct iio_chan_spec adis16240_channels[] = {
+ IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ in_supply, ADIS16240_SCAN_SUPPLY,
+ IIO_ST('u', 10, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ 0,
+ in_aux, ADIS16240_SCAN_AUX_ADC,
+ IIO_ST('u', 10, 16, 0), 0),
+ IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED) |
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ accel_x, ADIS16240_SCAN_ACC_X,
+ IIO_ST('s', 10, 16, 0), 0),
+ IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED) |
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ accel_y, ADIS16240_SCAN_ACC_Y,
+ IIO_ST('s', 10, 16, 0), 0),
+ IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED) |
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ accel_z, ADIS16240_SCAN_ACC_Z,
+ IIO_ST('s', 10, 16, 0), 0),
+ IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ temp, ADIS16240_SCAN_TEMP,
+ IIO_ST('u', 10, 16, 0), 0),
+ IIO_CHAN_SOFT_TIMESTAMP(6)
};
static struct attribute *adis16240_attributes[] = {
- &iio_dev_attr_in0_supply_raw.dev_attr.attr,
- &iio_const_attr_in0_supply_scale.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_const_attr_accel_scale.dev_attr.attr,
- &iio_const_attr_accel_peak_scale.dev_attr.attr,
- &iio_dev_attr_accel_x_raw.dev_attr.attr,
- &iio_dev_attr_accel_x_calibbias.dev_attr.attr,
- &iio_dev_attr_accel_x_peak_raw.dev_attr.attr,
- &iio_dev_attr_accel_y_raw.dev_attr.attr,
- &iio_dev_attr_accel_y_calibbias.dev_attr.attr,
- &iio_dev_attr_accel_y_peak_raw.dev_attr.attr,
- &iio_dev_attr_accel_z_raw.dev_attr.attr,
- &iio_dev_attr_accel_z_calibbias.dev_attr.attr,
- &iio_dev_attr_accel_z_peak_raw.dev_attr.attr,
&iio_dev_attr_accel_xyz_squared_peak_raw.dev_attr.attr,
- &iio_dev_attr_temp_raw.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_const_attr_name.dev_attr.attr,
NULL
};
@@ -460,6 +507,13 @@ static const struct attribute_group adis16240_attribute_group = {
.attrs = adis16240_attributes,
};
+static const struct iio_info adis16240_info = {
+ .attrs = &adis16240_attribute_group,
+ .read_raw = &adis16240_read_raw,
+ .write_raw = &adis16240_write_raw,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit adis16240_probe(struct spi_device *spi)
{
int ret, regdone = 0;
@@ -485,18 +539,18 @@ static int __devinit adis16240_probe(struct spi_device *spi)
st->us = spi;
mutex_init(&st->buf_lock);
/* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_tx;
}
+ st->indio_dev->name = spi->dev.driver->name;
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->num_interrupt_lines = 1;
- st->indio_dev->event_attrs = &adis16240_event_attribute_group;
- st->indio_dev->attrs = &adis16240_attribute_group;
+ st->indio_dev->info = &adis16240_info;
+ st->indio_dev->channels = adis16240_channels;
+ st->indio_dev->num_channels = ARRAY_SIZE(adis16240_channels);
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
ret = adis16240_configure_ring(st->indio_dev);
@@ -508,37 +562,28 @@ static int __devinit adis16240_probe(struct spi_device *spi)
goto error_unreg_ring_funcs;
regdone = 1;
- ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
+ ret = iio_ring_buffer_register_ex(st->indio_dev->ring, 0,
+ adis16240_channels,
+ ARRAY_SIZE(adis16240_channels));
if (ret) {
printk(KERN_ERR "failed to initialize the ring\n");
goto error_unreg_ring_funcs;
}
if (spi->irq) {
- ret = iio_register_interrupt_line(spi->irq,
- st->indio_dev,
- 0,
- IRQF_TRIGGER_RISING,
- "adis16240");
- if (ret)
- goto error_uninitialize_ring;
-
ret = adis16240_probe_trigger(st->indio_dev);
if (ret)
- goto error_unregister_line;
+ goto error_uninitialize_ring;
}
/* Get the device into a sane initial state */
- ret = adis16240_initial_setup(st);
+ ret = adis16240_initial_setup(st->indio_dev);
if (ret)
goto error_remove_trigger;
return 0;
error_remove_trigger:
adis16240_remove_trigger(st->indio_dev);
-error_unregister_line:
- if (spi->irq)
- iio_unregister_interrupt_line(st->indio_dev, 0);
error_uninitialize_ring:
iio_ring_buffer_unregister(st->indio_dev->ring);
error_unreg_ring_funcs:
@@ -566,9 +611,6 @@ static int adis16240_remove(struct spi_device *spi)
flush_scheduled_work();
adis16240_remove_trigger(indio_dev);
- if (spi->irq)
- iio_unregister_interrupt_line(indio_dev, 0);
-
iio_ring_buffer_unregister(indio_dev->ring);
iio_device_unregister(indio_dev);
adis16240_unconfigure_ring(indio_dev);
diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c
index f882e9c150e2..0c6d781d94c6 100644
--- a/drivers/staging/iio/accel/adis16240_ring.c
+++ b/drivers/staging/iio/accel/adis16240_ring.c
@@ -17,59 +17,6 @@
#include "../trigger.h"
#include "adis16240.h"
-static IIO_SCAN_EL_C(in_supply, ADIS16240_SCAN_SUPPLY,
- ADIS16240_SUPPLY_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in_supply, u, 10, 16);
-static IIO_SCAN_EL_C(accel_x, ADIS16240_SCAN_ACC_X, ADIS16240_XACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_y, ADIS16240_SCAN_ACC_Y, ADIS16240_YACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_z, ADIS16240_SCAN_ACC_Z, ADIS16240_ZACCL_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(accel, s, 10, 16);
-static IIO_SCAN_EL_C(in0, ADIS16240_SCAN_AUX_ADC, ADIS16240_AUX_ADC, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in0, u, 10, 16);
-static IIO_SCAN_EL_C(temp, ADIS16240_SCAN_TEMP, ADIS16240_TEMP_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(temp, u, 10, 16);
-static IIO_SCAN_EL_TIMESTAMP(6);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
-
-static struct attribute *adis16240_scan_el_attrs[] = {
- &iio_scan_el_in_supply.dev_attr.attr,
- &iio_const_attr_in_supply_index.dev_attr.attr,
- &iio_const_attr_in_supply_type.dev_attr.attr,
- &iio_scan_el_accel_x.dev_attr.attr,
- &iio_const_attr_accel_x_index.dev_attr.attr,
- &iio_scan_el_accel_y.dev_attr.attr,
- &iio_const_attr_accel_y_index.dev_attr.attr,
- &iio_scan_el_accel_z.dev_attr.attr,
- &iio_const_attr_accel_z_index.dev_attr.attr,
- &iio_const_attr_accel_type.dev_attr.attr,
- &iio_scan_el_in0.dev_attr.attr,
- &iio_const_attr_in0_index.dev_attr.attr,
- &iio_const_attr_in0_type.dev_attr.attr,
- &iio_scan_el_temp.dev_attr.attr,
- &iio_const_attr_temp_index.dev_attr.attr,
- &iio_const_attr_temp_type.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group adis16240_scan_el_group = {
- .attrs = adis16240_scan_el_attrs,
- .name = "scan_elements",
-};
-
-/**
- * adis16240_poll_func_th() top half interrupt handler called by trigger
- * @private_data: iio_dev
- **/
-static void adis16240_poll_func_th(struct iio_dev *indio_dev, s64 time)
-{
- struct adis16240_state *st = iio_dev_get_devdata(indio_dev);
- st->last_timestamp = time;
- schedule_work(&st->work_trigger_to_ring);
-}
-
/**
* adis16240_read_ring_data() read data registers which will be placed into ring
* @dev: device associated with child of actual device (iio_dev or iio_trig)
@@ -112,56 +59,56 @@ static int adis16240_read_ring_data(struct device *dev, u8 *rx)
return ret;
}
-
-static void adis16240_trigger_bh_to_ring(struct work_struct *work_s)
+static irqreturn_t adis16240_trigger_handler(int irq, void *p)
{
- struct adis16240_state *st
- = container_of(work_s, struct adis16240_state,
- work_trigger_to_ring);
- struct iio_ring_buffer *ring = st->indio_dev->ring;
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->private_data;
+ struct adis16240_state *st = iio_dev_get_devdata(indio_dev);
+ struct iio_ring_buffer *ring = indio_dev->ring;
int i = 0;
s16 *data;
- size_t datasize = ring->access.get_bytes_per_datum(ring);
+ size_t datasize = ring->access->get_bytes_per_datum(ring);
- data = kmalloc(datasize , GFP_KERNEL);
+ data = kmalloc(datasize, GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
- return;
+ return -ENOMEM;
}
- if (ring->scan_count)
- if (adis16240_read_ring_data(&st->indio_dev->dev, st->rx) >= 0)
- for (; i < ring->scan_count; i++)
- data[i] = be16_to_cpup(
- (__be16 *)&(st->rx[i*2]));
+ if (ring->scan_count &&
+ adis16240_read_ring_data(&st->indio_dev->dev, st->rx) >= 0)
+ for (; i < ring->scan_count; i++)
+ data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
if (ring->scan_timestamp)
- *((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
+ *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
- ring->access.store_to(ring,
- (u8 *)data,
- st->last_timestamp);
+ ring->access->store_to(ring, (u8 *)data, pf->timestamp);
iio_trigger_notify_done(st->indio_dev->trig);
kfree(data);
- return;
+ return IRQ_HANDLED;
}
void adis16240_unconfigure_ring(struct iio_dev *indio_dev)
{
- kfree(indio_dev->pollfunc);
+ iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
+static const struct iio_ring_setup_ops adis16240_ring_setup_ops = {
+ .preenable = &iio_sw_ring_preenable,
+ .postenable = &iio_triggered_ring_postenable,
+ .predisable = &iio_triggered_ring_predisable,
+};
+
int adis16240_configure_ring(struct iio_dev *indio_dev)
{
int ret = 0;
- struct adis16240_state *st = indio_dev->dev_data;
struct iio_ring_buffer *ring;
- INIT_WORK(&st->work_trigger_to_ring, adis16240_trigger_bh_to_ring);
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
@@ -170,26 +117,31 @@ int adis16240_configure_ring(struct iio_dev *indio_dev)
}
indio_dev->ring = ring;
/* Effectively select the ring buffer implementation */
- iio_ring_sw_register_funcs(&ring->access);
+ ring->access = &ring_sw_access_funcs;
ring->bpe = 2;
- ring->scan_el_attrs = &adis16240_scan_el_group;
ring->scan_timestamp = true;
- ring->preenable = &iio_sw_ring_preenable;
- ring->postenable = &iio_triggered_ring_postenable;
- ring->predisable = &iio_triggered_ring_predisable;
+ ring->setup_ops = &adis16240_ring_setup_ops;
ring->owner = THIS_MODULE;
/* Set default scan mode */
- iio_scan_mask_set(ring, iio_scan_el_in_supply.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_x.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_y.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_z.number);
- iio_scan_mask_set(ring, iio_scan_el_temp.number);
- iio_scan_mask_set(ring, iio_scan_el_in0.number);
-
- ret = iio_alloc_pollfunc(indio_dev, NULL, &adis16240_poll_func_th);
- if (ret)
+ iio_scan_mask_set(ring, ADIS16240_SCAN_SUPPLY);
+ iio_scan_mask_set(ring, ADIS16240_SCAN_ACC_X);
+ iio_scan_mask_set(ring, ADIS16240_SCAN_ACC_Y);
+ iio_scan_mask_set(ring, ADIS16240_SCAN_ACC_Z);
+ iio_scan_mask_set(ring, ADIS16240_SCAN_AUX_ADC);
+ iio_scan_mask_set(ring, ADIS16240_SCAN_TEMP);
+
+ indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
+ &adis16240_trigger_handler,
+ IRQF_ONESHOT,
+ indio_dev,
+ "%s_consumer%d",
+ indio_dev->name,
+ indio_dev->id);
+ if (indio_dev->pollfunc == NULL) {
+ ret = -ENOMEM;
goto error_iio_sw_rb_free;
+ }
indio_dev->modes |= INDIO_RING_TRIGGERED;
return 0;
@@ -198,4 +150,3 @@ error_iio_sw_rb_free:
iio_sw_rb_free(indio_dev->ring);
return ret;
}
-
diff --git a/drivers/staging/iio/accel/adis16240_trigger.c b/drivers/staging/iio/accel/adis16240_trigger.c
index 6cb8681f2853..ece3ca8fb7eb 100644
--- a/drivers/staging/iio/accel/adis16240_trigger.c
+++ b/drivers/staging/iio/accel/adis16240_trigger.c
@@ -15,32 +15,12 @@
/**
* adis16240_data_rdy_trig_poll() the event handler for the data rdy trig
**/
-static int adis16240_data_rdy_trig_poll(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
+static irqreturn_t adis16240_data_rdy_trig_poll(int irq, void *trig)
{
- struct adis16240_state *st = iio_dev_get_devdata(dev_info);
- struct iio_trigger *trig = st->trig;
-
- iio_trigger_poll(trig, timestamp);
-
+ iio_trigger_poll(trig, iio_get_time_ns());
return IRQ_HANDLED;
}
-IIO_EVENT_SH(data_rdy_trig, &adis16240_data_rdy_trig_poll);
-
-static IIO_TRIGGER_NAME_ATTR;
-
-static struct attribute *adis16240_trigger_attrs[] = {
- &dev_attr_name.attr,
- NULL,
-};
-
-static const struct attribute_group adis16240_trigger_attr_group = {
- .attrs = adis16240_trigger_attrs,
-};
-
/**
* adis16240_data_rdy_trigger_set_state() set datardy interrupt state
**/
@@ -49,31 +29,9 @@ static int adis16240_data_rdy_trigger_set_state(struct iio_trigger *trig,
{
struct adis16240_state *st = trig->private_data;
struct iio_dev *indio_dev = st->indio_dev;
- int ret = 0;
dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
- ret = adis16240_set_irq(&st->indio_dev->dev, state);
- if (state == false) {
- iio_remove_event_from_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]
- ->ev_list);
- flush_scheduled_work();
- } else {
- iio_add_event_to_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]->ev_list);
- }
- return ret;
-}
-
-/**
- * adis16240_trig_try_reen() try renabling irq for data rdy trigger
- * @trig: the datardy trigger
- **/
-static int adis16240_trig_try_reen(struct iio_trigger *trig)
-{
- struct adis16240_state *st = trig->private_data;
- enable_irq(st->us->irq);
- return 0;
+ return adis16240_set_irq(st->indio_dev, state);
}
int adis16240_probe_trigger(struct iio_dev *indio_dev)
@@ -81,34 +39,38 @@ int adis16240_probe_trigger(struct iio_dev *indio_dev)
int ret;
struct adis16240_state *st = indio_dev->dev_data;
- st->trig = iio_allocate_trigger();
- st->trig->name = kasprintf(GFP_KERNEL,
- "adis16240-dev%d",
- indio_dev->id);
- if (!st->trig->name) {
+ st->trig = iio_allocate_trigger("adis16240-dev%d", indio_dev->id);
+ if (st->trig == NULL) {
ret = -ENOMEM;
- goto error_free_trig;
+ goto error_ret;
}
+
+ ret = request_irq(st->us->irq,
+ adis16240_data_rdy_trig_poll,
+ IRQF_TRIGGER_RISING,
+ "adis16240",
+ st->trig);
+ if (ret)
+ goto error_free_trig;
+
st->trig->dev.parent = &st->us->dev;
st->trig->owner = THIS_MODULE;
st->trig->private_data = st;
st->trig->set_trigger_state = &adis16240_data_rdy_trigger_set_state;
- st->trig->try_reenable = &adis16240_trig_try_reen;
- st->trig->control_attrs = &adis16240_trigger_attr_group;
ret = iio_trigger_register(st->trig);
/* select default trigger */
indio_dev->trig = st->trig;
if (ret)
- goto error_free_trig_name;
+ goto error_free_irq;
return 0;
-error_free_trig_name:
- kfree(st->trig->name);
+error_free_irq:
+ free_irq(st->us->irq, st->trig);
error_free_trig:
iio_free_trigger(st->trig);
-
+error_ret:
return ret;
}
@@ -117,6 +79,6 @@ void adis16240_remove_trigger(struct iio_dev *indio_dev)
struct adis16240_state *state = indio_dev->dev_data;
iio_trigger_unregister(state->trig);
- kfree(state->trig->name);
+ free_irq(state->us->irq, state->trig);
iio_free_trigger(state->trig);
}
diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c
index 79f57950ebeb..973156e75773 100644
--- a/drivers/staging/iio/accel/kxsd9.c
+++ b/drivers/staging/iio/accel/kxsd9.c
@@ -301,6 +301,11 @@ error_ret:
};
+static const struct iio_info kxsd9_info = {
+ .attrs = &kxsd9_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit kxsd9_probe(struct spi_device *spi)
{
@@ -329,19 +334,14 @@ static int __devinit kxsd9_probe(struct spi_device *spi)
st->us = spi;
mutex_init(&st->buf_lock);
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_tx;
}
st->indio_dev->dev.parent = &spi->dev;
- /* for now */
- st->indio_dev->num_interrupt_lines = 0;
- st->indio_dev->event_attrs = NULL;
-
- st->indio_dev->attrs = &kxsd9_attribute_group;
+ st->indio_dev->info = &kxsd9_info;
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(st->indio_dev);
diff --git a/drivers/staging/iio/accel/lis3l02dq.h b/drivers/staging/iio/accel/lis3l02dq.h
index 11402187f9ae..18b23acfb6f4 100644
--- a/drivers/staging/iio/accel/lis3l02dq.h
+++ b/drivers/staging/iio/accel/lis3l02dq.h
@@ -148,38 +148,31 @@ Form of high byte dependent on justification set in ctrl reg */
#define LIS3L02DQ_MAX_RX 12
/**
* struct lis3l02dq_state - device instance specific data
- * @helper: data and func pointer allowing generic functions
* @us: actual spi_device
- * @work_thresh: bh for threshold events
- * @thresh_timestamp: timestamp for threshold interrupts.
- * @inter: used to check if new interrupt has been triggered
* @trig: data ready trigger registered with iio
* @tx: transmit buffer
* @rx: receive buffer
* @buf_lock: mutex to protect tx and rx
**/
struct lis3l02dq_state {
- struct iio_sw_ring_helper_state help;
struct spi_device *us;
- struct work_struct work_thresh;
- s64 thresh_timestamp;
- bool inter;
struct iio_trigger *trig;
- u8 *tx;
- u8 *rx;
struct mutex buf_lock;
-};
+ bool trigger_on;
-#define lis3l02dq_h_to_s(_h) \
- container_of(_h, struct lis3l02dq_state, help)
+ u8 tx[LIS3L02DQ_MAX_RX] ____cacheline_aligned;
+ u8 rx[LIS3L02DQ_MAX_RX] ____cacheline_aligned;
+};
-int lis3l02dq_spi_read_reg_8(struct device *dev,
+int lis3l02dq_spi_read_reg_8(struct iio_dev *indio_dev,
u8 reg_address,
u8 *val);
-int lis3l02dq_spi_write_reg_8(struct device *dev,
+int lis3l02dq_spi_write_reg_8(struct iio_dev *indio_dev,
u8 reg_address,
- u8 *val);
+ u8 val);
+
+int lis3l02dq_disable_all_events(struct iio_dev *indio_dev);
#ifdef CONFIG_IIO_RING_BUFFER
/* At the moment triggers are only used for ring buffer
@@ -188,9 +181,9 @@ int lis3l02dq_spi_write_reg_8(struct device *dev,
void lis3l02dq_remove_trigger(struct iio_dev *indio_dev);
int lis3l02dq_probe_trigger(struct iio_dev *indio_dev);
-ssize_t lis3l02dq_read_accel_from_ring(struct device *dev,
- struct device_attribute *attr,
- char *buf);
+ssize_t lis3l02dq_read_accel_from_ring(struct iio_ring_buffer *ring,
+ int index,
+ int *val);
int lis3l02dq_configure_ring(struct iio_dev *indio_dev);
@@ -199,14 +192,18 @@ void lis3l02dq_unconfigure_ring(struct iio_dev *indio_dev);
#ifdef CONFIG_LIS3L02DQ_BUF_RING_SW
#define lis3l02dq_free_buf iio_sw_rb_free
#define lis3l02dq_alloc_buf iio_sw_rb_allocate
-#define lis3l02dq_register_buf_funcs iio_ring_sw_register_funcs
+#define lis3l02dq_access_funcs ring_sw_access_funcs
#endif
#ifdef CONFIG_LIS3L02DQ_BUF_KFIFO
#define lis3l02dq_free_buf iio_kfifo_free
#define lis3l02dq_alloc_buf iio_kfifo_allocate
-#define lis3l02dq_register_buf_funcs iio_kfifo_register_funcs
+#define lis3l02dq_access_funcs kfifo_access_funcs
#endif
+irqreturn_t lis3l02dq_data_rdy_trig_poll(int irq, void *private);
+#define lis3l02dq_th lis3l02dq_data_rdy_trig_poll
+
#else /* CONFIG_IIO_RING_BUFFER */
+#define lis3l02dq_th lis3l02dq_noring
static inline void lis3l02dq_remove_trigger(struct iio_dev *indio_dev)
{
@@ -215,11 +212,10 @@ static inline int lis3l02dq_probe_trigger(struct iio_dev *indio_dev)
{
return 0;
}
-
static inline ssize_t
-lis3l02dq_read_accel_from_ring(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+lis3l02dq_read_accel_from_ring(struct iio_ring_buffer *ring,
+ int index,
+ int *val)
{
return 0;
}
diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c
index 3067f9662d20..ba5bc679204f 100644
--- a/drivers/staging/iio/accel/lis3l02dq_core.c
+++ b/drivers/staging/iio/accel/lis3l02dq_core.c
@@ -15,20 +15,16 @@
#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_generic.h"
-#include "../ring_sw.h"
#include "accel.h"
@@ -38,27 +34,31 @@
* It's in the likely to be added comment at the top of spi.h.
* This means that use cannot be made of spi_write etc.
*/
+/* direct copy of the irq_default_primary_handler */
+#ifndef CONFIG_IIO_RING_BUFFER
+static irqreturn_t lis3l02dq_noring(int irq, void *private)
+{
+ return IRQ_WAKE_THREAD;
+}
+#endif
/**
* lis3l02dq_spi_read_reg_8() - read single byte from a single register
- * @dev: device asosciated with child of actual device (iio_dev or iio_trig)
+ * @indio_dev: iio_dev for this actual device
* @reg_address: the address of the register to be read
* @val: pass back the resulting value
**/
-int lis3l02dq_spi_read_reg_8(struct device *dev, u8 reg_address, u8 *val)
+int lis3l02dq_spi_read_reg_8(struct iio_dev *indio_dev,
+ u8 reg_address, u8 *val)
{
- int ret;
+ struct lis3l02dq_state *st = iio_priv(indio_dev);
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct iio_sw_ring_helper_state *h = iio_dev_get_devdata(indio_dev);
- struct lis3l02dq_state *st = lis3l02dq_h_to_s(h);
-
+ int ret;
struct spi_transfer xfer = {
.tx_buf = st->tx,
.rx_buf = st->rx,
.bits_per_word = 8,
.len = 2,
- .cs_change = 1,
};
mutex_lock(&st->buf_lock);
@@ -76,34 +76,21 @@ int lis3l02dq_spi_read_reg_8(struct device *dev, u8 reg_address, u8 *val)
/**
* lis3l02dq_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_dev for this device
* @reg_address: the address of the register to be written
* @val: the value to write
**/
-int lis3l02dq_spi_write_reg_8(struct device *dev,
+int lis3l02dq_spi_write_reg_8(struct iio_dev *indio_dev,
u8 reg_address,
- u8 *val)
+ u8 val)
{
int ret;
- struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct iio_sw_ring_helper_state *h
- = iio_dev_get_devdata(indio_dev);
- struct lis3l02dq_state *st = lis3l02dq_h_to_s(h);
- struct spi_transfer xfer = {
- .tx_buf = st->tx,
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 1,
- };
+ struct lis3l02dq_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
st->tx[0] = LIS3L02DQ_WRITE_REG(reg_address);
- st->tx[1] = *val;
-
- spi_message_init(&msg);
- spi_message_add_tail(&xfer, &msg);
- ret = spi_sync(st->us, &msg);
+ st->tx[1] = val;
+ ret = spi_write(st->us, st->tx, 2);
mutex_unlock(&st->buf_lock);
return ret;
@@ -111,21 +98,18 @@ int lis3l02dq_spi_write_reg_8(struct device *dev,
/**
* lisl302dq_spi_write_reg_s16() - write 2 bytes to a pair of registers
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @reg_address: the address of the lower of the two registers. Second register
- * is assumed to have address one greater.
- * @val: value to be written
+ * @indio_dev: iio_dev for this device
+ * @lower_reg_address: the address of the lower of the two registers.
+ * Second register is assumed to have address one greater.
+ * @value: value to be written
**/
-static int lis3l02dq_spi_write_reg_s16(struct device *dev,
+static int lis3l02dq_spi_write_reg_s16(struct iio_dev *indio_dev,
u8 lower_reg_address,
s16 value)
{
int ret;
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct iio_sw_ring_helper_state *h
- = iio_dev_get_devdata(indio_dev);
- struct lis3l02dq_state *st = lis3l02dq_h_to_s(h);
+ struct lis3l02dq_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[] = { {
.tx_buf = st->tx,
.bits_per_word = 8,
@@ -135,7 +119,6 @@ static int lis3l02dq_spi_write_reg_s16(struct device *dev,
.tx_buf = st->tx + 2,
.bits_per_word = 8,
.len = 2,
- .cs_change = 1,
},
};
@@ -154,23 +137,15 @@ static int lis3l02dq_spi_write_reg_s16(struct device *dev,
return ret;
}
-/**
- * lisl302dq_spi_read_reg_s16() - write 2 bytes to a pair of registers
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @reg_address: the address of the lower of the two registers. Second register
- * is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int lis3l02dq_spi_read_reg_s16(struct device *dev,
- u8 lower_reg_address,
- s16 *val)
+static int lis3l02dq_read_reg_s16(struct iio_dev *indio_dev,
+ u8 lower_reg_address,
+ int *val)
{
+ struct lis3l02dq_state *st = iio_priv(indio_dev);
+
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct iio_sw_ring_helper_state *h
- = iio_dev_get_devdata(indio_dev);
- struct lis3l02dq_state *st = lis3l02dq_h_to_s(h);
int ret;
+ s16 tempval;
struct spi_transfer xfers[] = { {
.tx_buf = st->tx,
.rx_buf = st->rx,
@@ -182,15 +157,13 @@ static int lis3l02dq_spi_read_reg_s16(struct device *dev,
.rx_buf = st->rx + 2,
.bits_per_word = 8,
.len = 2,
- .cs_change = 1,
-
},
};
mutex_lock(&st->buf_lock);
st->tx[0] = LIS3L02DQ_READ_REG(lower_reg_address);
st->tx[1] = 0;
- st->tx[2] = LIS3L02DQ_READ_REG(lower_reg_address+1);
+ st->tx[2] = LIS3L02DQ_READ_REG(lower_reg_address + 1);
st->tx[3] = 0;
spi_message_init(&msg);
@@ -201,144 +174,135 @@ static int lis3l02dq_spi_read_reg_s16(struct device *dev,
dev_err(&st->us->dev, "problem when reading 16 bit register");
goto error_ret;
}
- *val = (s16)(st->rx[1]) | ((s16)(st->rx[3]) << 8);
+ tempval = (s16)(st->rx[1]) | ((s16)(st->rx[3]) << 8);
+ *val = tempval;
error_ret:
mutex_unlock(&st->buf_lock);
return ret;
}
-/**
- * lis3l02dq_read_signed() - attribute function used for 8 bit signed values
- * @dev: the child device associated with the iio_dev or iio_trigger
- * @attr: the attribute being processed
- * @buf: buffer into which put the output string
- **/
-static ssize_t lis3l02dq_read_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int ret;
- s8 val;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
- ret = lis3l02dq_spi_read_reg_8(dev, this_attr->address, (u8 *)&val);
-
- return ret ? ret : sprintf(buf, "%d\n", val);
-}
-
-static ssize_t lis3l02dq_read_unsigned(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int ret;
- u8 val;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
- ret = lis3l02dq_spi_read_reg_8(dev, this_attr->address, &val);
-
- return ret ? ret : sprintf(buf, "%d\n", val);
-}
-
-static ssize_t lis3l02dq_write_signed(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- long valin;
- s8 val;
- int ret;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
- ret = strict_strtol(buf, 10, &valin);
- if (ret)
- goto error_ret;
- val = valin;
- ret = lis3l02dq_spi_write_reg_8(dev, this_attr->address, (u8 *)&val);
+enum lis3l02dq_rm_ind {
+ LIS3L02DQ_ACCEL,
+ LIS3L02DQ_GAIN,
+ LIS3L02DQ_BIAS,
+};
-error_ret:
- return ret ? ret : len;
-}
+static u8 lis3l02dq_axis_map[3][3] = {
+ [LIS3L02DQ_ACCEL] = { LIS3L02DQ_REG_OUT_X_L_ADDR,
+ LIS3L02DQ_REG_OUT_Y_L_ADDR,
+ LIS3L02DQ_REG_OUT_Z_L_ADDR },
+ [LIS3L02DQ_GAIN] = { LIS3L02DQ_REG_GAIN_X_ADDR,
+ LIS3L02DQ_REG_GAIN_Y_ADDR,
+ LIS3L02DQ_REG_GAIN_Z_ADDR },
+ [LIS3L02DQ_BIAS] = { LIS3L02DQ_REG_OFFSET_X_ADDR,
+ LIS3L02DQ_REG_OFFSET_Y_ADDR,
+ LIS3L02DQ_REG_OFFSET_Z_ADDR }
+};
-static ssize_t lis3l02dq_write_unsigned(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+static int lis3l02dq_read_thresh(struct iio_dev *indio_dev,
+ int e,
+ int *val)
{
- int ret;
- ulong valin;
- u8 val;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
- ret = strict_strtoul(buf, 10, &valin);
- if (ret)
- goto err_ret;
- val = valin;
- ret = lis3l02dq_spi_write_reg_8(dev, this_attr->address, &val);
-
-err_ret:
- return ret ? ret : len;
+ return lis3l02dq_read_reg_s16(indio_dev, LIS3L02DQ_REG_THS_L_ADDR, val);
}
-static ssize_t lis3l02dq_read_16bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int lis3l02dq_write_thresh(struct iio_dev *indio_dev,
+ int event_code,
+ int val)
{
- int ret;
- s16 val = 0;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
- ret = lis3l02dq_spi_read_reg_s16(dev, this_attr->address, &val);
-
- if (ret)
- return ret;
-
- return sprintf(buf, "%d\n", val);
+ u16 value = val;
+ return lis3l02dq_spi_write_reg_s16(indio_dev,
+ LIS3L02DQ_REG_THS_L_ADDR,
+ value);
}
-static ssize_t lis3l02dq_read_accel(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int lis3l02dq_write_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);
- ssize_t ret;
-
- /* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
- if (indio_dev->currentmode == INDIO_RING_TRIGGERED)
- ret = lis3l02dq_read_accel_from_ring(dev, attr, buf);
- else
- ret = lis3l02dq_read_16bit_signed(dev, attr, buf);
- mutex_unlock(&indio_dev->mlock);
-
+ int ret = -EINVAL, reg;
+ u8 uval;
+ s8 sval;
+ switch (mask) {
+ case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ if (val > 255 || val < -256)
+ return -EINVAL;
+ sval = val;
+ reg = lis3l02dq_axis_map[LIS3L02DQ_BIAS][chan->address];
+ ret = lis3l02dq_spi_write_reg_8(indio_dev, reg, sval);
+ break;
+ case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ if (val & ~0xFF)
+ return -EINVAL;
+ uval = val;
+ reg = lis3l02dq_axis_map[LIS3L02DQ_GAIN][chan->address];
+ ret = lis3l02dq_spi_write_reg_8(indio_dev, reg, uval);
+ break;
+ }
return ret;
}
-static ssize_t lis3l02dq_write_16bit_signed(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+static int lis3l02dq_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);
- int ret;
- long val;
-
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- goto error_ret;
- ret = lis3l02dq_spi_write_reg_s16(dev, this_attr->address, val);
-
+ u8 utemp;
+ s8 stemp;
+ ssize_t ret = 0;
+ u8 reg;
+
+ switch (mask) {
+ case 0:
+ /* Take the iio_dev status lock */
+ mutex_lock(&indio_dev->mlock);
+ if (indio_dev->currentmode == INDIO_RING_TRIGGERED)
+ ret = lis3l02dq_read_accel_from_ring(indio_dev->ring,
+ chan->scan_index,
+ val);
+ else {
+ reg = lis3l02dq_axis_map
+ [LIS3L02DQ_ACCEL][chan->address];
+ ret = lis3l02dq_read_reg_s16(indio_dev, reg, val);
+ }
+ mutex_unlock(&indio_dev->mlock);
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ *val = 0;
+ *val2 = 9580;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ reg = lis3l02dq_axis_map[LIS3L02DQ_GAIN][chan->address];
+ ret = lis3l02dq_spi_read_reg_8(indio_dev, reg, &utemp);
+ if (ret)
+ goto error_ret;
+ /* to match with what previous code does */
+ *val = utemp;
+ return IIO_VAL_INT;
+
+ case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ reg = lis3l02dq_axis_map[LIS3L02DQ_BIAS][chan->address];
+ ret = lis3l02dq_spi_read_reg_8(indio_dev, reg, (u8 *)&stemp);
+ /* to match with what previous code does */
+ *val = stemp;
+ return IIO_VAL_INT;
+ }
error_ret:
- return ret ? ret : len;
+ return ret;
}
static ssize_t lis3l02dq_read_frequency(struct device *dev,
struct device_attribute *attr,
char *buf)
{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
int ret, len = 0;
s8 t;
- ret = lis3l02dq_spi_read_reg_8(dev,
+ ret = lis3l02dq_spi_read_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_1_ADDR,
(u8 *)&t);
if (ret)
@@ -376,7 +340,7 @@ static ssize_t lis3l02dq_write_frequency(struct device *dev,
return ret;
mutex_lock(&indio_dev->mlock);
- ret = lis3l02dq_spi_read_reg_8(dev,
+ ret = lis3l02dq_spi_read_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_1_ADDR,
&t);
if (ret)
@@ -399,11 +363,11 @@ static ssize_t lis3l02dq_write_frequency(struct device *dev,
default:
ret = -EINVAL;
goto error_ret_mutex;
- };
+ }
- ret = lis3l02dq_spi_write_reg_8(dev,
+ ret = lis3l02dq_spi_write_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_1_ADDR,
- &t);
+ t);
error_ret_mutex:
mutex_unlock(&indio_dev->mlock);
@@ -411,8 +375,9 @@ error_ret_mutex:
return ret ? ret : len;
}
-static int lis3l02dq_initial_setup(struct lis3l02dq_state *st)
+static int lis3l02dq_initial_setup(struct iio_dev *indio_dev)
{
+ struct lis3l02dq_state *st = iio_priv(indio_dev);
int ret;
u8 val, valtest;
@@ -422,17 +387,17 @@ static int lis3l02dq_initial_setup(struct lis3l02dq_state *st)
val = LIS3L02DQ_DEFAULT_CTRL1;
/* Write suitable defaults to ctrl1 */
- ret = lis3l02dq_spi_write_reg_8(&st->help.indio_dev->dev,
+ ret = lis3l02dq_spi_write_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_1_ADDR,
- &val);
+ val);
if (ret) {
dev_err(&st->us->dev, "problem with setup control register 1");
goto err_ret;
}
/* Repeat as sometimes doesn't work first time?*/
- ret = lis3l02dq_spi_write_reg_8(&st->help.indio_dev->dev,
+ ret = lis3l02dq_spi_write_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_1_ADDR,
- &val);
+ val);
if (ret) {
dev_err(&st->us->dev, "problem with setup control register 1");
goto err_ret;
@@ -440,28 +405,29 @@ static int lis3l02dq_initial_setup(struct lis3l02dq_state *st)
/* Read back to check this has worked acts as loose test of correct
* chip */
- ret = lis3l02dq_spi_read_reg_8(&st->help.indio_dev->dev,
+ ret = lis3l02dq_spi_read_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_1_ADDR,
&valtest);
if (ret || (valtest != val)) {
- dev_err(&st->help.indio_dev->dev, "device not playing ball");
+ dev_err(&indio_dev->dev,
+ "device not playing ball %d %d\n", valtest, val);
ret = -EINVAL;
goto err_ret;
}
val = LIS3L02DQ_DEFAULT_CTRL2;
- ret = lis3l02dq_spi_write_reg_8(&st->help.indio_dev->dev,
+ ret = lis3l02dq_spi_write_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_2_ADDR,
- &val);
+ val);
if (ret) {
dev_err(&st->us->dev, "problem with setup control register 2");
goto err_ret;
}
val = LIS3L02DQ_REG_WAKE_UP_CFG_LATCH_SRC;
- ret = lis3l02dq_spi_write_reg_8(&st->help.indio_dev->dev,
+ ret = lis3l02dq_spi_write_reg_8(indio_dev,
LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
- &val);
+ val);
if (ret)
dev_err(&st->us->dev, "problem with interrupt cfg register");
err_ret:
@@ -469,309 +435,215 @@ err_ret:
return ret;
}
-#define LIS3L02DQ_SIGNED_ATTR(name, reg) \
- IIO_DEVICE_ATTR(name, \
- S_IWUSR | S_IRUGO, \
- lis3l02dq_read_signed, \
- lis3l02dq_write_signed, \
- reg);
-
-#define LIS3L02DQ_UNSIGNED_ATTR(name, reg) \
- IIO_DEVICE_ATTR(name, \
- S_IWUSR | S_IRUGO, \
- lis3l02dq_read_unsigned, \
- lis3l02dq_write_unsigned, \
- reg);
-
-static LIS3L02DQ_SIGNED_ATTR(accel_x_calibbias,
- LIS3L02DQ_REG_OFFSET_X_ADDR);
-static LIS3L02DQ_SIGNED_ATTR(accel_y_calibbias,
- LIS3L02DQ_REG_OFFSET_Y_ADDR);
-static LIS3L02DQ_SIGNED_ATTR(accel_z_calibbias,
- LIS3L02DQ_REG_OFFSET_Z_ADDR);
-
-static LIS3L02DQ_UNSIGNED_ATTR(accel_x_calibscale,
- LIS3L02DQ_REG_GAIN_X_ADDR);
-static LIS3L02DQ_UNSIGNED_ATTR(accel_y_calibscale,
- LIS3L02DQ_REG_GAIN_Y_ADDR);
-static LIS3L02DQ_UNSIGNED_ATTR(accel_z_calibscale,
- LIS3L02DQ_REG_GAIN_Z_ADDR);
-
-static IIO_DEVICE_ATTR(accel_raw_mag_value,
- S_IWUSR | S_IRUGO,
- lis3l02dq_read_16bit_signed,
- lis3l02dq_write_16bit_signed,
- LIS3L02DQ_REG_THS_L_ADDR);
-/* RFC The reading method for these will change depending on whether
- * ring buffer capture is in use. Is it worth making these take two
- * functions and let the core handle which to call, or leave as in this
- * driver where it is the drivers problem to manage this?
- */
-
-static IIO_DEV_ATTR_ACCEL_X(lis3l02dq_read_accel,
- LIS3L02DQ_REG_OUT_X_L_ADDR);
-
-static IIO_DEV_ATTR_ACCEL_Y(lis3l02dq_read_accel,
- LIS3L02DQ_REG_OUT_Y_L_ADDR);
-
-static IIO_DEV_ATTR_ACCEL_Z(lis3l02dq_read_accel,
- LIS3L02DQ_REG_OUT_Z_L_ADDR);
-
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
lis3l02dq_read_frequency,
lis3l02dq_write_frequency);
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("280 560 1120 4480");
-static ssize_t lis3l02dq_read_interrupt_config(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int ret;
- s8 val;
- struct iio_event_attr *this_attr = to_iio_event_attr(attr);
-
- ret = lis3l02dq_spi_read_reg_8(dev->parent,
- LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
- (u8 *)&val);
-
- return ret ? ret : sprintf(buf, "%d\n", !!(val & this_attr->mask));
-}
-
-static ssize_t lis3l02dq_write_interrupt_config(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_event_attr *this_attr = to_iio_event_attr(attr);
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- int ret, currentlyset, changed = 0;
- u8 valold, controlold;
- bool val;
-
- val = !(buf[0] == '0');
-
- mutex_lock(&indio_dev->mlock);
- /* read current value */
- ret = lis3l02dq_spi_read_reg_8(dev->parent,
- LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
- &valold);
- if (ret)
- goto error_mutex_unlock;
-
- /* read current control */
- ret = lis3l02dq_spi_read_reg_8(dev,
- LIS3L02DQ_REG_CTRL_2_ADDR,
- &controlold);
- if (ret)
- goto error_mutex_unlock;
- currentlyset = !!(valold & this_attr->mask);
- if (val == false && currentlyset) {
- valold &= ~this_attr->mask;
- changed = 1;
- iio_remove_event_from_list(this_attr->listel,
- &indio_dev->interrupts[0]
- ->ev_list);
- } else if (val == true && !currentlyset) {
- changed = 1;
- valold |= this_attr->mask;
- iio_add_event_to_list(this_attr->listel,
- &indio_dev->interrupts[0]->ev_list);
- }
-
- if (changed) {
- ret = lis3l02dq_spi_write_reg_8(dev,
- LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
- &valold);
- if (ret)
- goto error_mutex_unlock;
- /* This always enables the interrupt, even if we've remove the
- * last thing using it. For this device we can use the reference
- * count on the handler to tell us if anyone wants the interrupt
- */
- controlold = this_attr->listel->refcount ?
- (controlold | LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT) :
- (controlold & ~LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT);
- ret = lis3l02dq_spi_write_reg_8(dev,
- LIS3L02DQ_REG_CTRL_2_ADDR,
- &controlold);
- if (ret)
- goto error_mutex_unlock;
- }
-error_mutex_unlock:
- mutex_unlock(&indio_dev->mlock);
-
- return ret ? ret : len;
-}
-
-
-static int lis3l02dq_thresh_handler_th(struct iio_dev *indio_dev,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct iio_sw_ring_helper_state *h
- = iio_dev_get_devdata(indio_dev);
- struct lis3l02dq_state *st = lis3l02dq_h_to_s(h);
-
- /* Stash the timestamp somewhere convenient for the bh */
- st->thresh_timestamp = timestamp;
- schedule_work(&st->work_thresh);
-
- return 0;
-}
-
-
-/* Unforunately it appears the interrupt won't clear unless you read from the
- * src register.
- */
-static void lis3l02dq_thresh_handler_bh_no_check(struct work_struct *work_s)
+static irqreturn_t lis3l02dq_event_handler(int irq, void *private)
{
- struct lis3l02dq_state *st
- = container_of(work_s,
- struct lis3l02dq_state, work_thresh);
-
+ struct iio_dev *indio_dev = private;
u8 t;
- lis3l02dq_spi_read_reg_8(&st->help.indio_dev->dev,
+ s64 timestamp = iio_get_time_ns();
+
+ lis3l02dq_spi_read_reg_8(indio_dev,
LIS3L02DQ_REG_WAKE_UP_SRC_ADDR,
&t);
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_HIGH)
- iio_push_event(st->help.indio_dev, 0,
+ iio_push_event(indio_dev, 0,
IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
0,
IIO_EV_MOD_Z,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
- st->thresh_timestamp);
+ timestamp);
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_LOW)
- iio_push_event(st->help.indio_dev, 0,
+ iio_push_event(indio_dev, 0,
IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
0,
IIO_EV_MOD_Z,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
- st->thresh_timestamp);
+ timestamp);
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_HIGH)
- iio_push_event(st->help.indio_dev, 0,
+ iio_push_event(indio_dev, 0,
IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
0,
IIO_EV_MOD_Y,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
- st->thresh_timestamp);
+ timestamp);
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_LOW)
- iio_push_event(st->help.indio_dev, 0,
+ iio_push_event(indio_dev, 0,
IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
0,
IIO_EV_MOD_Y,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
- st->thresh_timestamp);
+ timestamp);
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_HIGH)
- iio_push_event(st->help.indio_dev, 0,
+ iio_push_event(indio_dev, 0,
IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
0,
IIO_EV_MOD_X,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
- st->thresh_timestamp);
+ timestamp);
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_LOW)
- iio_push_event(st->help.indio_dev, 0,
+ iio_push_event(indio_dev, 0,
IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
0,
IIO_EV_MOD_X,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
- st->thresh_timestamp);
- /* reenable the irq */
- enable_irq(st->us->irq);
+ timestamp);
+
/* Ack and allow for new interrupts */
- lis3l02dq_spi_read_reg_8(&st->help.indio_dev->dev,
+ lis3l02dq_spi_read_reg_8(indio_dev,
LIS3L02DQ_REG_WAKE_UP_ACK_ADDR,
&t);
- return;
+ return IRQ_HANDLED;
}
-/* A shared handler for a number of threshold types */
-IIO_EVENT_SH(threshold, &lis3l02dq_thresh_handler_th);
-
-IIO_EVENT_ATTR_SH(accel_x_thresh_rising_en,
- iio_event_threshold,
- lis3l02dq_read_interrupt_config,
- lis3l02dq_write_interrupt_config,
- LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_X_HIGH);
-
-IIO_EVENT_ATTR_SH(accel_y_thresh_rising_en,
- iio_event_threshold,
- lis3l02dq_read_interrupt_config,
- lis3l02dq_write_interrupt_config,
- LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Y_HIGH);
-
-IIO_EVENT_ATTR_SH(accel_z_thresh_rising_en,
- iio_event_threshold,
- lis3l02dq_read_interrupt_config,
- lis3l02dq_write_interrupt_config,
- LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_HIGH);
-
-IIO_EVENT_ATTR_SH(accel_x_thresh_falling_en,
- iio_event_threshold,
- lis3l02dq_read_interrupt_config,
- lis3l02dq_write_interrupt_config,
- LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_X_LOW);
-
-IIO_EVENT_ATTR_SH(accel_y_thresh_falling_en,
- iio_event_threshold,
- lis3l02dq_read_interrupt_config,
- lis3l02dq_write_interrupt_config,
- LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Y_LOW);
-
-IIO_EVENT_ATTR_SH(accel_z_thresh_falling_en,
- iio_event_threshold,
- lis3l02dq_read_interrupt_config,
- lis3l02dq_write_interrupt_config,
- LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_LOW);
-
-
-static struct attribute *lis3l02dq_event_attributes[] = {
- &iio_event_attr_accel_x_thresh_rising_en.dev_attr.attr,
- &iio_event_attr_accel_y_thresh_rising_en.dev_attr.attr,
- &iio_event_attr_accel_z_thresh_rising_en.dev_attr.attr,
- &iio_event_attr_accel_x_thresh_falling_en.dev_attr.attr,
- &iio_event_attr_accel_y_thresh_falling_en.dev_attr.attr,
- &iio_event_attr_accel_z_thresh_falling_en.dev_attr.attr,
- &iio_dev_attr_accel_raw_mag_value.dev_attr.attr,
- NULL
+#define LIS3L02DQ_INFO_MASK \
+ ((1 << IIO_CHAN_INFO_SCALE_SHARED) | \
+ (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | \
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE))
+
+#define LIS3L02DQ_EVENT_MASK \
+ (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | \
+ IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING))
+
+static struct iio_chan_spec lis3l02dq_channels[] = {
+ IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, LIS3L02DQ_INFO_MASK,
+ 0, 0, IIO_ST('s', 12, 16, 0), LIS3L02DQ_EVENT_MASK),
+ IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, LIS3L02DQ_INFO_MASK,
+ 1, 1, IIO_ST('s', 12, 16, 0), LIS3L02DQ_EVENT_MASK),
+ IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z, LIS3L02DQ_INFO_MASK,
+ 2, 2, IIO_ST('s', 12, 16, 0), LIS3L02DQ_EVENT_MASK),
+ IIO_CHAN_SOFT_TIMESTAMP(3)
};
-static struct attribute_group lis3l02dq_event_attribute_group = {
- .attrs = lis3l02dq_event_attributes,
-};
-static IIO_CONST_ATTR_NAME("lis3l02dq");
-static IIO_CONST_ATTR(accel_scale, "0.00958");
+static ssize_t lis3l02dq_read_event_config(struct iio_dev *indio_dev,
+ int event_code)
+{
+
+ u8 val;
+ int ret;
+ u8 mask = (1 << (IIO_EVENT_CODE_EXTRACT_MODIFIER(event_code)*2 +
+ (IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
+ IIO_EV_DIR_RISING)));
+ ret = lis3l02dq_spi_read_reg_8(indio_dev,
+ LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
+ &val);
+ if (ret < 0)
+ return ret;
+
+ return !!(val & mask);
+}
+
+int lis3l02dq_disable_all_events(struct iio_dev *indio_dev)
+{
+ int ret;
+ u8 control, val;
+
+ ret = lis3l02dq_spi_read_reg_8(indio_dev,
+ LIS3L02DQ_REG_CTRL_2_ADDR,
+ &control);
+
+ control &= ~LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT;
+ ret = lis3l02dq_spi_write_reg_8(indio_dev,
+ LIS3L02DQ_REG_CTRL_2_ADDR,
+ control);
+ if (ret)
+ goto error_ret;
+ /* Also for consistency clear the mask */
+ ret = lis3l02dq_spi_read_reg_8(indio_dev,
+ LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
+ &val);
+ if (ret)
+ goto error_ret;
+ val &= ~0x3f;
+
+ ret = lis3l02dq_spi_write_reg_8(indio_dev,
+ LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
+ val);
+ if (ret)
+ goto error_ret;
+
+ ret = control;
+error_ret:
+ return ret;
+}
+
+static int lis3l02dq_write_event_config(struct iio_dev *indio_dev,
+ int event_code,
+ int state)
+{
+ int ret = 0;
+ u8 val, control;
+ u8 currentlyset;
+ bool changed = false;
+ u8 mask = (1 << (IIO_EVENT_CODE_EXTRACT_MODIFIER(event_code)*2 +
+ (IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
+ IIO_EV_DIR_RISING)));
+
+ mutex_lock(&indio_dev->mlock);
+ /* read current control */
+ ret = lis3l02dq_spi_read_reg_8(indio_dev,
+ LIS3L02DQ_REG_CTRL_2_ADDR,
+ &control);
+ if (ret)
+ goto error_ret;
+ ret = lis3l02dq_spi_read_reg_8(indio_dev,
+ LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
+ &val);
+ if (ret < 0)
+ goto error_ret;
+ currentlyset = val & mask;
+
+ if (!currentlyset && state) {
+ changed = true;
+ val |= mask;
+ } else if (currentlyset && !state) {
+ changed = true;
+ val &= ~mask;
+ }
+
+ if (changed) {
+ ret = lis3l02dq_spi_write_reg_8(indio_dev,
+ LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
+ val);
+ if (ret)
+ goto error_ret;
+ control = val & 0x3f ?
+ (control | LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT) :
+ (control & ~LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT);
+ ret = lis3l02dq_spi_write_reg_8(indio_dev,
+ LIS3L02DQ_REG_CTRL_2_ADDR,
+ control);
+ if (ret)
+ goto error_ret;
+ }
+
+error_ret:
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+}
static struct attribute *lis3l02dq_attributes[] = {
- &iio_dev_attr_accel_x_calibbias.dev_attr.attr,
- &iio_dev_attr_accel_y_calibbias.dev_attr.attr,
- &iio_dev_attr_accel_z_calibbias.dev_attr.attr,
- &iio_dev_attr_accel_x_calibscale.dev_attr.attr,
- &iio_dev_attr_accel_y_calibscale.dev_attr.attr,
- &iio_dev_attr_accel_z_calibscale.dev_attr.attr,
- &iio_const_attr_accel_scale.dev_attr.attr,
- &iio_dev_attr_accel_x_raw.dev_attr.attr,
- &iio_dev_attr_accel_y_raw.dev_attr.attr,
- &iio_dev_attr_accel_z_raw.dev_attr.attr,
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
- &iio_const_attr_name.dev_attr.attr,
NULL
};
@@ -779,103 +651,96 @@ static const struct attribute_group lis3l02dq_attribute_group = {
.attrs = lis3l02dq_attributes,
};
+static const struct iio_info lis3l02dq_info = {
+ .num_interrupt_lines = 1,
+ .read_raw = &lis3l02dq_read_raw,
+ .write_raw = &lis3l02dq_write_raw,
+ .read_event_value = &lis3l02dq_read_thresh,
+ .write_event_value = &lis3l02dq_write_thresh,
+ .write_event_config = &lis3l02dq_write_event_config,
+ .read_event_config = &lis3l02dq_read_event_config,
+ .driver_module = THIS_MODULE,
+ .attrs = &lis3l02dq_attribute_group,
+};
+
static int __devinit lis3l02dq_probe(struct spi_device *spi)
{
int ret, regdone = 0;
- struct lis3l02dq_state *st = kzalloc(sizeof *st, GFP_KERNEL);
- if (!st) {
- ret = -ENOMEM;
+ struct lis3l02dq_state *st;
+ struct iio_dev *indio_dev;
+
+ indio_dev = iio_allocate_device(sizeof *st);
+ if (indio_dev == NULL) {
+ ret = -ENOMEM;
goto error_ret;
}
- INIT_WORK(&st->work_thresh, lis3l02dq_thresh_handler_bh_no_check);
+ st = iio_priv(indio_dev);
/* this is only used tor removal purposes */
spi_set_drvdata(spi, st);
- /* Allocate the comms buffers */
- st->rx = kzalloc(sizeof(*st->rx)*LIS3L02DQ_MAX_RX, GFP_KERNEL);
- if (st->rx == NULL) {
- ret = -ENOMEM;
- goto error_free_st;
- }
- st->tx = kzalloc(sizeof(*st->tx)*LIS3L02DQ_MAX_TX, GFP_KERNEL);
- if (st->tx == NULL) {
- ret = -ENOMEM;
- goto error_free_rx;
- }
st->us = spi;
mutex_init(&st->buf_lock);
- /* setup the industrialio driver allocated elements */
- st->help.indio_dev = iio_allocate_device();
- if (st->help.indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_free_tx;
- }
+ indio_dev->name = spi->dev.driver->name;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->info = &lis3l02dq_info;
+ indio_dev->channels = lis3l02dq_channels;
+ indio_dev->num_channels = ARRAY_SIZE(lis3l02dq_channels);
- st->help.indio_dev->dev.parent = &spi->dev;
- st->help.indio_dev->num_interrupt_lines = 1;
- st->help.indio_dev->event_attrs = &lis3l02dq_event_attribute_group;
- st->help.indio_dev->attrs = &lis3l02dq_attribute_group;
- st->help.indio_dev->dev_data = (void *)(&st->help);
- st->help.indio_dev->driver_module = THIS_MODULE;
- st->help.indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->modes = INDIO_DIRECT_MODE;
- ret = lis3l02dq_configure_ring(st->help.indio_dev);
+ ret = lis3l02dq_configure_ring(indio_dev);
if (ret)
goto error_free_dev;
- ret = iio_device_register(st->help.indio_dev);
+ ret = iio_device_register(indio_dev);
if (ret)
goto error_unreg_ring_funcs;
regdone = 1;
- ret = iio_ring_buffer_register(st->help.indio_dev->ring, 0);
+ ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
+ lis3l02dq_channels,
+ ARRAY_SIZE(lis3l02dq_channels));
if (ret) {
printk(KERN_ERR "failed to initialize the ring\n");
goto error_unreg_ring_funcs;
}
if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) {
- st->inter = 0;
- ret = iio_register_interrupt_line(spi->irq,
- st->help.indio_dev,
- 0,
- IRQF_TRIGGER_RISING,
- "lis3l02dq");
+ ret = request_threaded_irq(st->us->irq,
+ &lis3l02dq_th,
+ &lis3l02dq_event_handler,
+ IRQF_TRIGGER_RISING,
+ "lis3l02dq",
+ indio_dev);
if (ret)
goto error_uninitialize_ring;
- ret = lis3l02dq_probe_trigger(st->help.indio_dev);
+ ret = lis3l02dq_probe_trigger(indio_dev);
if (ret)
- goto error_unregister_line;
+ goto error_free_interrupt;
}
/* Get the device into a sane initial state */
- ret = lis3l02dq_initial_setup(st);
+ ret = lis3l02dq_initial_setup(indio_dev);
if (ret)
goto error_remove_trigger;
return 0;
error_remove_trigger:
- if (st->help.indio_dev->modes & INDIO_RING_TRIGGERED)
- lis3l02dq_remove_trigger(st->help.indio_dev);
-error_unregister_line:
- if (st->help.indio_dev->modes & INDIO_RING_TRIGGERED)
- iio_unregister_interrupt_line(st->help.indio_dev, 0);
+ if (indio_dev->modes & INDIO_RING_TRIGGERED)
+ lis3l02dq_remove_trigger(indio_dev);
+error_free_interrupt:
+ if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
+ free_irq(st->us->irq, indio_dev);
error_uninitialize_ring:
- iio_ring_buffer_unregister(st->help.indio_dev->ring);
+ iio_ring_buffer_unregister(indio_dev->ring);
error_unreg_ring_funcs:
- lis3l02dq_unconfigure_ring(st->help.indio_dev);
+ lis3l02dq_unconfigure_ring(indio_dev);
error_free_dev:
if (regdone)
- iio_device_unregister(st->help.indio_dev);
+ iio_device_unregister(indio_dev);
else
- iio_free_device(st->help.indio_dev);
-error_free_tx:
- kfree(st->tx);
-error_free_rx:
- kfree(st->rx);
-error_free_st:
- kfree(st);
+ iio_free_device(indio_dev);
error_ret:
return ret;
}
@@ -884,23 +749,21 @@ error_ret:
static int lis3l02dq_stop_device(struct iio_dev *indio_dev)
{
int ret;
- struct iio_sw_ring_helper_state *h
- = iio_dev_get_devdata(indio_dev);
- struct lis3l02dq_state *st = lis3l02dq_h_to_s(h);
+ struct lis3l02dq_state *st = iio_priv(indio_dev);
u8 val = 0;
mutex_lock(&indio_dev->mlock);
- ret = lis3l02dq_spi_write_reg_8(&indio_dev->dev,
+ ret = lis3l02dq_spi_write_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_1_ADDR,
- &val);
+ val);
if (ret) {
dev_err(&st->us->dev, "problem with turning device off: ctrl1");
goto err_ret;
}
- ret = lis3l02dq_spi_write_reg_8(&indio_dev->dev,
+ ret = lis3l02dq_spi_write_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_2_ADDR,
- &val);
+ val);
if (ret)
dev_err(&st->us->dev, "problem with turning device off: ctrl2");
err_ret:
@@ -912,25 +775,24 @@ err_ret:
static int lis3l02dq_remove(struct spi_device *spi)
{
int ret;
- struct lis3l02dq_state *st = spi_get_drvdata(spi);
- struct iio_dev *indio_dev = st->help.indio_dev;
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct lis3l02dq_state *st = iio_priv(indio_dev);
- ret = lis3l02dq_stop_device(indio_dev);
+ ret = lis3l02dq_disable_all_events(indio_dev);
if (ret)
goto err_ret;
- flush_scheduled_work();
+ ret = lis3l02dq_stop_device(indio_dev);
+ if (ret)
+ goto err_ret;
- lis3l02dq_remove_trigger(indio_dev);
if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
- iio_unregister_interrupt_line(indio_dev, 0);
+ free_irq(st->us->irq, indio_dev);
+ lis3l02dq_remove_trigger(indio_dev);
iio_ring_buffer_unregister(indio_dev->ring);
lis3l02dq_unconfigure_ring(indio_dev);
iio_device_unregister(indio_dev);
- kfree(st->tx);
- kfree(st->rx);
- kfree(st);
return 0;
diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c
index 529a3cc6d0c7..8d5c8ac7db51 100644
--- a/drivers/staging/iio/accel/lis3l02dq_ring.c
+++ b/drivers/staging/iio/accel/lis3l02dq_ring.c
@@ -1,13 +1,11 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
-#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/sysfs.h>
-#include <linux/list.h>
#include <linux/slab.h>
#include "../iio.h"
@@ -29,180 +27,49 @@ static inline u16 combine_8_to_16(u8 lower, u8 upper)
}
/**
- * lis3l02dq_scan_el_set_state() set whether a scan contains a given channel
- * @scan_el: associtate iio scan element attribute
- * @indio_dev: the device structure
- * @bool: desired state
- *
- * mlock already held when this is called.
- **/
-static int lis3l02dq_scan_el_set_state(struct iio_scan_el *scan_el,
- struct iio_dev *indio_dev,
- bool state)
-{
- u8 t, mask;
- int ret;
-
- ret = lis3l02dq_spi_read_reg_8(&indio_dev->dev,
- LIS3L02DQ_REG_CTRL_1_ADDR,
- &t);
- if (ret)
- goto error_ret;
- switch (scan_el->label) {
- case LIS3L02DQ_REG_OUT_X_L_ADDR:
- mask = LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE;
- break;
- case LIS3L02DQ_REG_OUT_Y_L_ADDR:
- mask = LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE;
- break;
- case LIS3L02DQ_REG_OUT_Z_L_ADDR:
- mask = LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE;
- break;
- default:
- ret = -EINVAL;
- goto error_ret;
- }
-
- if (!(mask & t) == state) {
- if (state)
- t |= mask;
- else
- t &= ~mask;
- ret = lis3l02dq_spi_write_reg_8(&indio_dev->dev,
- LIS3L02DQ_REG_CTRL_1_ADDR,
- &t);
- }
-error_ret:
- return ret;
-
-}
-static IIO_SCAN_EL_C(accel_x, 0,
- LIS3L02DQ_REG_OUT_X_L_ADDR,
- &lis3l02dq_scan_el_set_state);
-static IIO_SCAN_EL_C(accel_y, 1,
- LIS3L02DQ_REG_OUT_Y_L_ADDR,
- &lis3l02dq_scan_el_set_state);
-static IIO_SCAN_EL_C(accel_z, 2,
- LIS3L02DQ_REG_OUT_Z_L_ADDR,
- &lis3l02dq_scan_el_set_state);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(accel, s, 12, 16);
-static IIO_SCAN_EL_TIMESTAMP(3);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
-
-static struct attribute *lis3l02dq_scan_el_attrs[] = {
- &iio_scan_el_accel_x.dev_attr.attr,
- &iio_const_attr_accel_x_index.dev_attr.attr,
- &iio_scan_el_accel_y.dev_attr.attr,
- &iio_const_attr_accel_y_index.dev_attr.attr,
- &iio_scan_el_accel_z.dev_attr.attr,
- &iio_const_attr_accel_z_index.dev_attr.attr,
- &iio_const_attr_accel_type.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group lis3l02dq_scan_el_group = {
- .attrs = lis3l02dq_scan_el_attrs,
- .name = "scan_elements",
-};
-
-/**
- * lis3l02dq_poll_func_th() top half interrupt handler called by trigger
- * @private_data: iio_dev
+ * lis3l02dq_data_rdy_trig_poll() the event handler for the data rdy trig
**/
-static void lis3l02dq_poll_func_th(struct iio_dev *indio_dev, s64 time)
+irqreturn_t lis3l02dq_data_rdy_trig_poll(int irq, void *private)
{
- struct iio_sw_ring_helper_state *h
- = iio_dev_get_devdata(indio_dev);
- struct lis3l02dq_state *st = lis3l02dq_h_to_s(h);
- /* in this case we need to slightly extend the helper function */
- iio_sw_poll_func_th(indio_dev, time);
-
- /* Indicate that this interrupt is being handled */
- /* Technically this is trigger related, but without this
- * handler running there is currently now way for the interrupt
- * to clear.
- */
- st->inter = 1;
+ struct iio_dev *indio_dev = private;
+ struct lis3l02dq_state *st = iio_priv(indio_dev);
+
+ if (st->trigger_on) {
+ iio_trigger_poll(st->trig, iio_get_time_ns());
+ return IRQ_HANDLED;
+ } else
+ return IRQ_WAKE_THREAD;
}
/**
- * lis3l02dq_data_rdy_trig_poll() the event handler for the data rdy trig
+ * lis3l02dq_read_accel_from_ring() individual acceleration read from ring
**/
-static int lis3l02dq_data_rdy_trig_poll(struct iio_dev *indio_dev,
+ssize_t lis3l02dq_read_accel_from_ring(struct iio_ring_buffer *ring,
int index,
- s64 timestamp,
- int no_test)
+ int *val)
{
- struct iio_sw_ring_helper_state *h
- = iio_dev_get_devdata(indio_dev);
- struct lis3l02dq_state *st = lis3l02dq_h_to_s(h);
-
- iio_trigger_poll(st->trig, timestamp);
+ int ret;
+ s16 *data;
- return IRQ_HANDLED;
-}
+ if (!iio_scan_mask_query(ring, index))
+ return -EINVAL;
-/* This is an event as it is a response to a physical interrupt */
-IIO_EVENT_SH(data_rdy_trig, &lis3l02dq_data_rdy_trig_poll);
+ if (!ring->access->read_last)
+ return -EBUSY;
-/**
- * lis3l02dq_read_accel_from_ring() individual acceleration read from ring
- **/
-ssize_t lis3l02dq_read_accel_from_ring(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_scan_el *el = NULL;
- int ret, len = 0, i = 0;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct iio_ring_buffer *ring = dev_info->ring;
- struct attribute_group *scan_el_attrs = ring->scan_el_attrs;
- s16 *data;
+ data = kmalloc(ring->access->get_bytes_per_datum(ring),
+ GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
- while (scan_el_attrs->attrs[i]) {
- el = to_iio_scan_el((struct device_attribute *)
- (scan_el_attrs->attrs[i]));
- /* label is in fact the address */
- if (el->label == this_attr->address)
- break;
- i++;
- }
- if (!scan_el_attrs->attrs[i]) {
- ret = -EINVAL;
- goto error_ret;
- }
- /* If this element is in the scan mask */
- ret = iio_scan_mask_query(ring, el->number);
- if (ret < 0)
- goto error_ret;
- if (ret) {
- data = kmalloc(ring->access.get_bytes_per_datum(ring),
- GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
- ret = ring->access.read_last(ring,
- (u8 *)data);
- if (ret)
- goto error_free_data;
- } else {
- ret = -EINVAL;
- goto error_ret;
- }
- len = iio_scan_mask_count_to_right(ring, el->number);
- if (len < 0) {
- ret = len;
+ ret = ring->access->read_last(ring, (u8 *)data);
+ if (ret)
goto error_free_data;
- }
- len = sprintf(buf, "ring %d\n", data[len]);
+ *val = data[bitmap_weight(&ring->scan_mask, index)];
error_free_data:
kfree(data);
-error_ret:
- return ret ? ret : len;
+ return ret;
}
static const u8 read_all_tx_array[] = {
@@ -220,9 +87,10 @@ static const u8 read_all_tx_array[] = {
* @rx_array: (dma capable) receive array, must be at least
* 4*number of channels
**/
-static int lis3l02dq_read_all(struct lis3l02dq_state *st, u8 *rx_array)
+static int lis3l02dq_read_all(struct iio_dev *indio_dev, u8 *rx_array)
{
- struct iio_ring_buffer *ring = st->help.indio_dev->ring;
+ struct iio_ring_buffer *ring = indio_dev->ring;
+ struct lis3l02dq_state *st = iio_priv(indio_dev);
struct spi_transfer *xfers;
struct spi_message msg;
int ret, i, j = 0;
@@ -234,7 +102,7 @@ static int lis3l02dq_read_all(struct lis3l02dq_state *st, u8 *rx_array)
mutex_lock(&st->buf_lock);
- for (i = 0; i < ARRAY_SIZE(read_all_tx_array)/4; i++) {
+ for (i = 0; i < ARRAY_SIZE(read_all_tx_array)/4; i++)
if (ring->scan_mask & (1 << i)) {
/* lower byte */
xfers[j].tx_buf = st->tx + 2*j;
@@ -258,7 +126,7 @@ static int lis3l02dq_read_all(struct lis3l02dq_state *st, u8 *rx_array)
xfers[j].cs_change = 1;
j++;
}
- }
+
/* After these are transmitted, the rx_buff should have
* values in alternate bytes
*/
@@ -273,31 +141,20 @@ static int lis3l02dq_read_all(struct lis3l02dq_state *st, u8 *rx_array)
return ret;
}
-static void lis3l02dq_trigger_bh_to_ring(struct work_struct *work_s)
-{
- struct iio_sw_ring_helper_state *h
- = container_of(work_s, struct iio_sw_ring_helper_state,
- work_trigger_to_ring);
- struct lis3l02dq_state *st = lis3l02dq_h_to_s(h);
-
- st->inter = 0;
- iio_sw_trigger_bh_to_ring(work_s);
-}
-
-static int lis3l02dq_get_ring_element(struct iio_sw_ring_helper_state *h,
+static int lis3l02dq_get_ring_element(struct iio_dev *indio_dev,
u8 *buf)
{
int ret, i;
u8 *rx_array ;
s16 *data = (s16 *)buf;
- rx_array = kzalloc(4 * (h->indio_dev->ring->scan_count), GFP_KERNEL);
+ rx_array = kzalloc(4 * (indio_dev->ring->scan_count), GFP_KERNEL);
if (rx_array == NULL)
return -ENOMEM;
- ret = lis3l02dq_read_all(lis3l02dq_h_to_s(h), rx_array);
+ ret = lis3l02dq_read_all(indio_dev, rx_array);
if (ret < 0)
return ret;
- for (i = 0; i < h->indio_dev->ring->scan_count; i++)
+ for (i = 0; i < indio_dev->ring->scan_count; i++)
data[i] = combine_8_to_16(rx_array[i*4+1],
rx_array[i*4+3]);
kfree(rx_array);
@@ -305,19 +162,48 @@ static int lis3l02dq_get_ring_element(struct iio_sw_ring_helper_state *h,
return i*sizeof(data[0]);
}
+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_ring_buffer *ring = indio_dev->ring;
+ int len = 0;
+ size_t datasize = ring->access->get_bytes_per_datum(ring);
+ char *data = kmalloc(datasize, GFP_KERNEL);
+
+ if (data == NULL) {
+ dev_err(indio_dev->dev.parent,
+ "memory alloc failed in ring bh");
+ return -ENOMEM;
+ }
+
+ if (ring->scan_count)
+ len = lis3l02dq_get_ring_element(indio_dev, data);
+
+ /* Guaranteed to be aligned with 8 byte boundary */
+ if (ring->scan_timestamp)
+ *(s64 *)(((phys_addr_t)data + len
+ + sizeof(s64) - 1) & ~(sizeof(s64) - 1))
+ = pf->timestamp;
+ ring->access->store_to(ring, (u8 *)data, pf->timestamp);
+
+ iio_trigger_notify_done(indio_dev->trig);
+ kfree(data);
+ return IRQ_HANDLED;
+}
+
/* Caller responsible for locking as necessary. */
static int
-__lis3l02dq_write_data_ready_config(struct device *dev,
- struct iio_event_handler_list *list,
- bool state)
+__lis3l02dq_write_data_ready_config(struct device *dev, bool state)
{
int ret;
u8 valold;
bool currentlyset;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct lis3l02dq_state *st = iio_priv(indio_dev);
/* Get the current event mask register */
- ret = lis3l02dq_spi_read_reg_8(dev,
+ ret = lis3l02dq_spi_read_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_2_ADDR,
&valold);
if (ret)
@@ -328,32 +214,36 @@ __lis3l02dq_write_data_ready_config(struct device *dev,
/* Disable requested */
if (!state && currentlyset) {
-
+ /* disable the data ready signal */
valold &= ~LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION;
+
/* The double write is to overcome a hardware bug?*/
- ret = lis3l02dq_spi_write_reg_8(dev,
+ ret = lis3l02dq_spi_write_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_2_ADDR,
- &valold);
+ valold);
if (ret)
goto error_ret;
- ret = lis3l02dq_spi_write_reg_8(dev,
+ ret = lis3l02dq_spi_write_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_2_ADDR,
- &valold);
+ valold);
if (ret)
goto error_ret;
-
- iio_remove_event_from_list(list,
- &indio_dev->interrupts[0]
- ->ev_list);
-
+ st->trigger_on = false;
/* Enable requested */
} else if (state && !currentlyset) {
/* if not set, enable requested */
- valold |= LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION;
- iio_add_event_to_list(list, &indio_dev->interrupts[0]->ev_list);
- ret = lis3l02dq_spi_write_reg_8(dev,
+ /* first disable all events */
+ ret = lis3l02dq_disable_all_events(indio_dev);
+ if (ret < 0)
+ goto error_ret;
+
+ valold = ret |
+ LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION;
+
+ st->trigger_on = true;
+ ret = lis3l02dq_spi_write_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_2_ADDR,
- &valold);
+ valold);
if (ret)
goto error_ret;
}
@@ -373,65 +263,45 @@ error_ret:
static int lis3l02dq_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
- struct lis3l02dq_state *st = trig->private_data;
+ struct iio_dev *indio_dev = trig->private_data;
int ret = 0;
u8 t;
- __lis3l02dq_write_data_ready_config(&st->help.indio_dev->dev,
- &iio_event_data_rdy_trig,
- state);
+
+ __lis3l02dq_write_data_ready_config(&indio_dev->dev, state);
if (state == false) {
- /* possible quirk with handler currently worked around
- by ensuring the work queue is empty */
- flush_scheduled_work();
- /* Clear any outstanding ready events */
- ret = lis3l02dq_read_all(st, NULL);
+ /*
+ * A possible quirk with teh handler is currently worked around
+ * by ensuring outstanding read events are cleared.
+ */
+ ret = lis3l02dq_read_all(indio_dev, NULL);
}
- lis3l02dq_spi_read_reg_8(&st->help.indio_dev->dev,
+ lis3l02dq_spi_read_reg_8(indio_dev,
LIS3L02DQ_REG_WAKE_UP_SRC_ADDR,
&t);
return ret;
}
-static IIO_TRIGGER_NAME_ATTR;
-
-static struct attribute *lis3l02dq_trigger_attrs[] = {
- &dev_attr_name.attr,
- NULL,
-};
-
-static const struct attribute_group lis3l02dq_trigger_attr_group = {
- .attrs = lis3l02dq_trigger_attrs,
-};
-
/**
* lis3l02dq_trig_try_reen() try renabling irq for data rdy trigger
* @trig: the datardy trigger
- *
- * As the trigger may occur on any data element being updated it is
- * really rather likely to occur during the read from the previous
- * trigger event. The only way to discover if this has occurred on
- * boards not supporting level interrupts is to take a look at the line.
- * If it is indicating another interrupt and we don't seem to have a
- * handler looking at it, then we need to notify the core that we need
- * to tell the triggering core to try reading all these again.
- **/
+ */
static int lis3l02dq_trig_try_reen(struct iio_trigger *trig)
{
- struct lis3l02dq_state *st = trig->private_data;
- enable_irq(st->us->irq);
+ struct iio_dev *indio_dev = trig->private_data;
+ struct lis3l02dq_state *st = iio_priv(indio_dev);
+ int i;
+
/* If gpio still high (or high again) */
- if (gpio_get_value(irq_to_gpio(st->us->irq)))
- if (st->inter == 0) {
- /* already interrupt handler dealing with it */
- disable_irq_nosync(st->us->irq);
- if (st->inter == 1) {
- /* interrupt handler snuck in between test
- * and disable */
- enable_irq(st->us->irq);
- return 0;
- }
- return -EAGAIN;
- }
+ /* In theory possible we will need to do this several times */
+ for (i = 0; i < 5; i++)
+ if (gpio_get_value(irq_to_gpio(st->us->irq)))
+ lis3l02dq_read_all(indio_dev, NULL);
+ else
+ break;
+ if (i == 5)
+ printk(KERN_INFO
+ "Failed to clear the interrupt for lis3l02dq\n");
+
/* irq reenabled so success! */
return 0;
}
@@ -439,62 +309,124 @@ static int lis3l02dq_trig_try_reen(struct iio_trigger *trig)
int lis3l02dq_probe_trigger(struct iio_dev *indio_dev)
{
int ret;
- struct lis3l02dq_state *state = indio_dev->dev_data;
+ struct lis3l02dq_state *st = iio_priv(indio_dev);
- state->trig = iio_allocate_trigger();
- if (!state->trig)
- return -ENOMEM;
-
- state->trig->name = kasprintf(GFP_KERNEL,
- "lis3l02dq-dev%d",
- indio_dev->id);
- if (!state->trig->name) {
+ st->trig = iio_allocate_trigger("lis3l02dq-dev%d", indio_dev->id);
+ if (!st->trig) {
ret = -ENOMEM;
- goto error_free_trig;
+ goto error_ret;
}
- state->trig->dev.parent = &state->us->dev;
- state->trig->owner = THIS_MODULE;
- state->trig->private_data = state;
- state->trig->set_trigger_state = &lis3l02dq_data_rdy_trigger_set_state;
- state->trig->try_reenable = &lis3l02dq_trig_try_reen;
- state->trig->control_attrs = &lis3l02dq_trigger_attr_group;
- ret = iio_trigger_register(state->trig);
+ st->trig->dev.parent = &st->us->dev;
+ st->trig->owner = THIS_MODULE;
+ 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_name;
+ goto error_free_trig;
return 0;
-error_free_trig_name:
- kfree(state->trig->name);
error_free_trig:
- iio_free_trigger(state->trig);
-
+ iio_free_trigger(st->trig);
+error_ret:
return ret;
}
void lis3l02dq_remove_trigger(struct iio_dev *indio_dev)
{
- struct lis3l02dq_state *state = indio_dev->dev_data;
+ struct lis3l02dq_state *st = iio_priv(indio_dev);
- iio_trigger_unregister(state->trig);
- kfree(state->trig->name);
- iio_free_trigger(state->trig);
+ iio_trigger_unregister(st->trig);
+ iio_free_trigger(st->trig);
}
void lis3l02dq_unconfigure_ring(struct iio_dev *indio_dev)
{
- kfree(indio_dev->pollfunc);
+ iio_dealloc_pollfunc(indio_dev->pollfunc);
lis3l02dq_free_buf(indio_dev->ring);
}
+static int lis3l02dq_ring_postenable(struct iio_dev *indio_dev)
+{
+ /* Disable unwanted channels otherwise the interrupt will not clear */
+ u8 t;
+ int ret;
+ bool oneenabled = false;
+
+ ret = lis3l02dq_spi_read_reg_8(indio_dev,
+ LIS3L02DQ_REG_CTRL_1_ADDR,
+ &t);
+ if (ret)
+ goto error_ret;
+
+ if (iio_scan_mask_query(indio_dev->ring, 0)) {
+ t |= LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE;
+ oneenabled = true;
+ } else
+ t &= ~LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE;
+ if (iio_scan_mask_query(indio_dev->ring, 1)) {
+ t |= LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE;
+ oneenabled = true;
+ } else
+ t &= ~LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE;
+ if (iio_scan_mask_query(indio_dev->ring, 2)) {
+ t |= LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE;
+ oneenabled = true;
+ } else
+ t &= ~LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE;
+
+ if (!oneenabled) /* what happens in this case is unknown */
+ return -EINVAL;
+ ret = lis3l02dq_spi_write_reg_8(indio_dev,
+ LIS3L02DQ_REG_CTRL_1_ADDR,
+ t);
+ if (ret)
+ goto error_ret;
+
+ return iio_triggered_ring_postenable(indio_dev);
+error_ret:
+ return ret;
+}
+
+/* Turn all channels on again */
+static int lis3l02dq_ring_predisable(struct iio_dev *indio_dev)
+{
+ u8 t;
+ int ret;
+
+ ret = iio_triggered_ring_predisable(indio_dev);
+ if (ret)
+ goto error_ret;
+
+ ret = lis3l02dq_spi_read_reg_8(indio_dev,
+ LIS3L02DQ_REG_CTRL_1_ADDR,
+ &t);
+ if (ret)
+ goto error_ret;
+ t |= LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE |
+ LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE |
+ LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE;
+
+ ret = lis3l02dq_spi_write_reg_8(indio_dev,
+ LIS3L02DQ_REG_CTRL_1_ADDR,
+ t);
+
+error_ret:
+ return ret;
+}
+
+static const struct iio_ring_setup_ops lis3l02dq_ring_setup_ops = {
+ .preenable = &iio_sw_ring_preenable,
+ .postenable = &lis3l02dq_ring_postenable,
+ .predisable = &lis3l02dq_ring_predisable,
+};
+
int lis3l02dq_configure_ring(struct iio_dev *indio_dev)
{
int ret;
- struct iio_sw_ring_helper_state *h = iio_dev_get_devdata(indio_dev);
struct iio_ring_buffer *ring;
- INIT_WORK(&h->work_trigger_to_ring, lis3l02dq_trigger_bh_to_ring);
- h->get_ring_element = &lis3l02dq_get_ring_element;
ring = lis3l02dq_alloc_buf(indio_dev);
if (!ring)
@@ -502,23 +434,31 @@ int lis3l02dq_configure_ring(struct iio_dev *indio_dev)
indio_dev->ring = ring;
/* Effectively select the ring buffer implementation */
- lis3l02dq_register_buf_funcs(&ring->access);
+ indio_dev->ring->access = &lis3l02dq_access_funcs;
ring->bpe = 2;
- ring->scan_el_attrs = &lis3l02dq_scan_el_group;
+
ring->scan_timestamp = true;
- ring->preenable = &iio_sw_ring_preenable;
- ring->postenable = &iio_triggered_ring_postenable;
- ring->predisable = &iio_triggered_ring_predisable;
+ ring->setup_ops = &lis3l02dq_ring_setup_ops;
ring->owner = THIS_MODULE;
/* Set default scan mode */
- iio_scan_mask_set(ring, iio_scan_el_accel_x.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_y.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_z.number);
-
- ret = iio_alloc_pollfunc(indio_dev, NULL, &lis3l02dq_poll_func_th);
- if (ret)
+ iio_scan_mask_set(ring, 0);
+ iio_scan_mask_set(ring, 1);
+ iio_scan_mask_set(ring, 2);
+
+ /* Functions are NULL as we set handler below */
+ indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
+ &lis3l02dq_trigger_handler,
+ 0,
+ indio_dev,
+ "lis3l02dq_consumer%d",
+ indio_dev->id);
+
+ if (indio_dev->pollfunc == NULL) {
+ ret = -ENOMEM;
goto error_iio_sw_rb_free;
+ }
+
indio_dev->modes |= INDIO_RING_TRIGGERED;
return 0;
diff --git a/drivers/staging/iio/accel/sca3000.h b/drivers/staging/iio/accel/sca3000.h
index db710334b99b..cf0751d917a9 100644
--- a/drivers/staging/iio/accel/sca3000.h
+++ b/drivers/staging/iio/accel/sca3000.h
@@ -158,17 +158,17 @@
/**
* struct sca3000_state - device instance state information
- * @us: the associated spi device
- * @info: chip variant information
- * @indio_dev: device information used by the IIO core
- * @interrupt_handler_ws: event interrupt handler for all events
- * @last_timestamp: the timestamp of the last event
- * @mo_det_use_count: reference counter for the motion detection unit
- * @lock: lock used to protect elements of sca3000_state
- * and the underlying device state.
- * @bpse: number of bits per scan element
- * @tx: dma-able transmit buffer
- * @rx: dma-able receive buffer
+ * @us: the associated spi device
+ * @info: chip variant information
+ * @indio_dev: device information used by the IIO core
+ * @interrupt_handler_ws: event interrupt handler for all events
+ * @last_timestamp: the timestamp of the last event
+ * @mo_det_use_count: reference counter for the motion detection unit
+ * @lock: lock used to protect elements of sca3000_state
+ * and the underlying device state.
+ * @bpse: number of bits per scan element
+ * @tx: dma-able transmit buffer
+ * @rx: dma-able receive buffer
**/
struct sca3000_state {
struct spi_device *us;
@@ -179,15 +179,14 @@ struct sca3000_state {
int mo_det_use_count;
struct mutex lock;
int bpse;
- u8 *tx;
- /* not used during a ring buffer read */
- u8 *rx;
+ /* Can these share a cacheline ? */
+ u8 rx[2] ____cacheline_aligned;
+ u8 tx[6] ____cacheline_aligned;
};
/**
* struct sca3000_chip_info - model dependent parameters
- * @name: model identification
- * @scale: string containing floating point scale factor
+ * @scale: scale * 10^-6
* @temp_output: some devices have temperature sensors.
* @measurement_mode_freq: normal mode sampling frequency
* @option_mode_1: first optional mode. Not all models have one
@@ -199,30 +198,20 @@ struct sca3000_state {
* sca3000 variant.
**/
struct sca3000_chip_info {
- const char *name;
- const char *scale;
+ unsigned int scale;
bool temp_output;
int measurement_mode_freq;
int option_mode_1;
int option_mode_1_freq;
int option_mode_2;
int option_mode_2_freq;
+ int mot_det_mult_xz[6];
+ int mot_det_mult_y[7];
};
-/**
- * sca3000_read_data() read a series of values from the device
- * @dev: device
- * @reg_address_high: start address (decremented read)
- * @rx: pointer where received data is placed. Callee
- * responsible for freeing this.
- * @len: number of bytes to read
- *
- * The main lock must be held.
- **/
-int sca3000_read_data(struct sca3000_state *st,
- u8 reg_address_high,
- u8 **rx_p,
- int len);
+int sca3000_read_data_short(struct sca3000_state *st,
+ u8 reg_address_high,
+ int len);
/**
* sca3000_write_reg() write a single register
@@ -233,29 +222,6 @@ int sca3000_read_data(struct sca3000_state *st,
**/
int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val);
-/* Conversion function for use with the ring buffer when in 11bit mode */
-static inline int sca3000_11bit_convert(uint8_t msb, uint8_t lsb)
-{
- int16_t val;
-
- val = ((lsb >> 3) & 0x1C) | (msb << 5);
- val |= (val & (1 << 12)) ? 0xE000 : 0;
-
- return val;
-}
-
-static inline int sca3000_13bit_convert(uint8_t msb, uint8_t lsb)
-{
- s16 val;
-
- val = ((lsb >> 3) & 0x1F) | (msb << 5);
- /* sign fill */
- val |= (val & (1 << 12)) ? 0xE000 : 0;
-
- return val;
-}
-
-
#ifdef CONFIG_IIO_RING_BUFFER
/**
* sca3000_register_ring_funcs() setup the ring state change functions
diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
index 5b06dea6af25..f213b8698eb2 100644
--- a/drivers/staging/iio/accel/sca3000_core.c
+++ b/drivers/staging/iio/accel/sca3000_core.c
@@ -40,95 +40,74 @@ enum sca3000_variant {
* do not actually appear to be available.
*/
static const struct sca3000_chip_info sca3000_spi_chip_info_tbl[] = {
- {
- .name = "sca3000-d01",
- .scale = " 0.0073575",
+ [d01] = {
+ .scale = 7357,
.temp_output = true,
.measurement_mode_freq = 250,
.option_mode_1 = SCA3000_OP_MODE_BYPASS,
.option_mode_1_freq = 250,
- }, {
- .name = "sca3000-e02",
- .scale = "0.00981",
+ .mot_det_mult_xz = {50, 100, 200, 350, 650, 1300},
+ .mot_det_mult_y = {50, 100, 150, 250, 450, 850, 1750},
+ },
+ [e02] = {
+ .scale = 9810,
.measurement_mode_freq = 125,
.option_mode_1 = SCA3000_OP_MODE_NARROW,
.option_mode_1_freq = 63,
- }, {
- .name = "sca3000-e04",
- .scale = "0.01962",
+ .mot_det_mult_xz = {100, 150, 300, 550, 1050, 2050},
+ .mot_det_mult_y = {50, 100, 200, 350, 700, 1350, 2700},
+ },
+ [e04] = {
+ .scale = 19620,
.measurement_mode_freq = 100,
.option_mode_1 = SCA3000_OP_MODE_NARROW,
.option_mode_1_freq = 50,
.option_mode_2 = SCA3000_OP_MODE_WIDE,
.option_mode_2_freq = 400,
- }, {
- .name = "sca3000-e05",
- .scale = "0.0613125",
+ .mot_det_mult_xz = {200, 300, 600, 1100, 2100, 4100},
+ .mot_det_mult_y = {100, 200, 400, 7000, 1400, 2700, 54000},
+ },
+ [e05] = {
+ .scale = 61313,
.measurement_mode_freq = 200,
.option_mode_1 = SCA3000_OP_MODE_NARROW,
.option_mode_1_freq = 50,
.option_mode_2 = SCA3000_OP_MODE_WIDE,
.option_mode_2_freq = 400,
+ .mot_det_mult_xz = {600, 900, 1700, 3200, 6100, 11900},
+ .mot_det_mult_y = {300, 600, 1200, 2000, 4100, 7800, 15600},
},
};
-
int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val)
{
- struct spi_transfer xfer = {
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 1,
- .tx_buf = st->tx,
- };
- struct spi_message msg;
-
st->tx[0] = SCA3000_WRITE_REG(address);
st->tx[1] = val;
- spi_message_init(&msg);
- spi_message_add_tail(&xfer, &msg);
-
- return spi_sync(st->us, &msg);
+ return spi_write(st->us, st->tx, 2);
}
-int sca3000_read_data(struct sca3000_state *st,
- uint8_t reg_address_high,
- u8 **rx_p,
- int len)
+int sca3000_read_data_short(struct sca3000_state *st,
+ uint8_t reg_address_high,
+ int len)
{
- int ret;
struct spi_message msg;
- struct spi_transfer xfer = {
- .bits_per_word = 8,
- .len = len + 1,
- .cs_change = 1,
- .tx_buf = st->tx,
+ struct spi_transfer xfer[2] = {
+ {
+ .len = 1,
+ .tx_buf = st->tx,
+ }, {
+ .len = len,
+ .rx_buf = st->rx,
+ }
};
-
- *rx_p = kmalloc(len + 1, GFP_KERNEL);
- if (*rx_p == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
- xfer.rx_buf = *rx_p;
st->tx[0] = SCA3000_READ_REG(reg_address_high);
spi_message_init(&msg);
- spi_message_add_tail(&xfer, &msg);
-
- ret = spi_sync(st->us, &msg);
-
- if (ret) {
- dev_err(get_device(&st->us->dev), "problem reading register");
- goto error_free_rx;
- }
-
- return 0;
-error_free_rx:
- kfree(*rx_p);
-error_ret:
- return ret;
+ spi_message_add_tail(&xfer[0], &msg);
+ spi_message_add_tail(&xfer[1], &msg);
+ return spi_sync(st->us, &msg);
}
+
/**
* sca3000_reg_lock_on() test if the ctrl register lock is on
*
@@ -136,17 +115,13 @@ error_ret:
**/
static int sca3000_reg_lock_on(struct sca3000_state *st)
{
- u8 *rx;
int ret;
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_STATUS, &rx, 1);
-
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_STATUS, 1);
if (ret < 0)
return ret;
- ret = !(rx[1] & SCA3000_LOCKED);
- kfree(rx);
- return ret;
+ return !(st->rx[0] & SCA3000_LOCKED);
}
/**
@@ -161,19 +136,15 @@ static int __sca3000_unlock_reg_lock(struct sca3000_state *st)
struct spi_message msg;
struct spi_transfer xfer[3] = {
{
- .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,
}, {
- .bits_per_word = 8,
.len = 2,
- .cs_change = 1,
.tx_buf = st->tx + 4,
},
};
@@ -236,8 +207,7 @@ error_ret:
* Lock must be held.
**/
static int sca3000_read_ctrl_reg(struct sca3000_state *st,
- u8 ctrl_reg,
- u8 **rx_p)
+ u8 ctrl_reg)
{
int ret;
@@ -253,8 +223,11 @@ static int sca3000_read_ctrl_reg(struct sca3000_state *st,
ret = sca3000_write_reg(st, SCA3000_REG_ADDR_CTRL_SEL, ctrl_reg);
if (ret)
goto error_ret;
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_CTRL_DATA, rx_p, 1);
-
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_CTRL_DATA, 1);
+ if (ret)
+ goto error_ret;
+ else
+ return st->rx[0];
error_ret:
return ret;
}
@@ -267,20 +240,18 @@ error_ret:
**/
static int sca3000_check_status(struct device *dev)
{
- u8 *rx;
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct sca3000_state *st = indio_dev->dev_data;
mutex_lock(&st->lock);
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_STATUS, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_STATUS, 1);
if (ret < 0)
goto error_ret;
- if (rx[1] & SCA3000_EEPROM_CS_ERROR)
+ if (st->rx[0] & SCA3000_EEPROM_CS_ERROR)
dev_err(dev, "eeprom error\n");
- if (rx[1] & SCA3000_SPI_FRAME_ERROR)
+ if (st->rx[0] & SCA3000_SPI_FRAME_ERROR)
dev_err(dev, "Previous SPI Frame was corrupt\n");
- kfree(rx);
error_ret:
mutex_unlock(&st->lock);
@@ -288,53 +259,7 @@ error_ret:
}
#endif /* SCA3000_DEBUG */
-/**
- * sca3000_read_13bit_signed() sysfs interface to read 13 bit signed registers
- *
- * These are described as signed 12 bit on the data sheet, which appears
- * to be a conventional 2's complement 13 bit.
- **/
-static ssize_t sca3000_read_13bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int len = 0, ret;
- int val;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- u8 *rx;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct sca3000_state *st = indio_dev->dev_data;
-
- mutex_lock(&st->lock);
- ret = sca3000_read_data(st, this_attr->address, &rx, 2);
- if (ret < 0)
- goto error_ret;
- val = sca3000_13bit_convert(rx[1], rx[2]);
- len += sprintf(buf + len, "%d\n", val);
- kfree(rx);
-error_ret:
- mutex_unlock(&st->lock);
-
- return ret ? ret : len;
-}
-static ssize_t sca3000_show_scale(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct sca3000_state *st = dev_info->dev_data;
- return sprintf(buf, "%s\n", st->info->scale);
-}
-
-static ssize_t sca3000_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct sca3000_state *st = dev_info->dev_data;
- return sprintf(buf, "%s\n", st->info->name);
-}
/**
* sca3000_show_reg() - sysfs interface to read the chip revision number
**/
@@ -346,18 +271,14 @@ static ssize_t sca3000_show_rev(struct device *dev,
struct iio_dev *dev_info = dev_get_drvdata(dev);
struct sca3000_state *st = dev_info->dev_data;
- u8 *rx;
-
mutex_lock(&st->lock);
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_REVID, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_REVID, 1);
if (ret < 0)
goto error_ret;
len += sprintf(buf + len,
"major=%d, minor=%d\n",
- rx[1] & SCA3000_REVID_MAJOR_MASK,
- rx[1] & SCA3000_REVID_MINOR_MASK);
- kfree(rx);
-
+ st->rx[0] & SCA3000_REVID_MAJOR_MASK,
+ st->rx[0] & SCA3000_REVID_MINOR_MASK);
error_ret:
mutex_unlock(&st->lock);
@@ -410,15 +331,14 @@ sca3000_show_measurement_mode(struct device *dev,
struct iio_dev *dev_info = dev_get_drvdata(dev);
struct sca3000_state *st = dev_info->dev_data;
int len = 0, ret;
- u8 *rx;
mutex_lock(&st->lock);
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_MODE, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
if (ret)
goto error_ret;
/* mask bottom 2 bits - only ones that are relevant */
- rx[1] &= 0x03;
- switch (rx[1]) {
+ st->rx[0] &= 0x03;
+ switch (st->rx[0]) {
case SCA3000_MEAS_MODE_NORMAL:
len += sprintf(buf + len, "0 - normal mode\n");
break;
@@ -462,7 +382,6 @@ sca3000_store_measurement_mode(struct device *dev,
struct iio_dev *dev_info = dev_get_drvdata(dev);
struct sca3000_state *st = dev_info->dev_data;
int ret;
- u8 *rx;
int mask = 0x03;
long val;
@@ -470,20 +389,18 @@ sca3000_store_measurement_mode(struct device *dev,
ret = strict_strtol(buf, 10, &val);
if (ret)
goto error_ret;
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_MODE, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
if (ret)
goto error_ret;
- rx[1] &= ~mask;
- rx[1] |= (val & mask);
- ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, rx[1]);
+ st->rx[0] &= ~mask;
+ st->rx[0] |= (val & mask);
+ ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, st->rx[0]);
if (ret)
- goto error_free_rx;
+ goto error_ret;
mutex_unlock(&st->lock);
return len;
-error_free_rx:
- kfree(rx);
error_ret:
mutex_unlock(&st->lock);
@@ -505,18 +422,70 @@ static IIO_DEVICE_ATTR(measurement_mode, S_IRUGO | S_IWUSR,
/* More standard attributes */
-static IIO_DEV_ATTR_NAME(sca3000_show_name);
static IIO_DEV_ATTR_REV(sca3000_show_rev);
-static IIO_DEVICE_ATTR(accel_scale, S_IRUGO, sca3000_show_scale,
- NULL, 0);
-static IIO_DEV_ATTR_ACCEL_X(sca3000_read_13bit_signed,
- SCA3000_REG_ADDR_X_MSB);
-static IIO_DEV_ATTR_ACCEL_Y(sca3000_read_13bit_signed,
- SCA3000_REG_ADDR_Y_MSB);
-static IIO_DEV_ATTR_ACCEL_Z(sca3000_read_13bit_signed,
- SCA3000_REG_ADDR_Z_MSB);
+#define SCA3000_INFO_MASK \
+ (1 << IIO_CHAN_INFO_SCALE_SHARED)
+#define SCA3000_EVENT_MASK \
+ (IIO_EV_BIT(IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING))
+
+static struct iio_chan_spec sca3000_channels[] = {
+ IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, SCA3000_INFO_MASK,
+ 0, 0, IIO_ST('s', 11, 16, 5), SCA3000_EVENT_MASK),
+ IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, SCA3000_INFO_MASK,
+ 1, 1, IIO_ST('s', 11, 16, 5), SCA3000_EVENT_MASK),
+ IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z, SCA3000_INFO_MASK,
+ 2, 2, IIO_ST('s', 11, 16, 5), SCA3000_EVENT_MASK),
+};
+
+static u8 sca3000_addresses[3][3] = {
+ [0] = {SCA3000_REG_ADDR_X_MSB, SCA3000_REG_CTRL_SEL_MD_X_TH,
+ SCA3000_MD_CTRL_OR_X},
+ [1] = {SCA3000_REG_ADDR_Y_MSB, SCA3000_REG_CTRL_SEL_MD_Y_TH,
+ SCA3000_MD_CTRL_OR_Y},
+ [2] = {SCA3000_REG_ADDR_Z_MSB, SCA3000_REG_CTRL_SEL_MD_Z_TH,
+ SCA3000_MD_CTRL_OR_Z},
+};
+static int sca3000_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long mask)
+{
+ struct sca3000_state *st = indio_dev->dev_data;
+ int ret;
+ u8 address;
+
+ switch (mask) {
+ case 0:
+ mutex_lock(&st->lock);
+ if (st->mo_det_use_count) {
+ mutex_unlock(&st->lock);
+ return -EBUSY;
+ }
+ address = sca3000_addresses[chan->address][0];
+ ret = sca3000_read_data_short(st, address, 2);
+ if (ret < 0) {
+ mutex_unlock(&st->lock);
+ return ret;
+ }
+ *val = (be16_to_cpup((__be16 *)st->rx) >> 3) & 0x1FFF;
+ *val = ((*val) << (sizeof(*val)*8 - 13)) >>
+ (sizeof(*val)*8 - 13);
+ mutex_unlock(&st->lock);
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ *val = 0;
+ if (chan->type == IIO_ACCEL)
+ *val2 = st->info->scale;
+ else /* temperature */
+ *val2 = 555556;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
/**
* sca3000_read_av_freq() sysfs function to get available frequencies
@@ -532,15 +501,16 @@ static ssize_t sca3000_read_av_freq(struct device *dev,
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct sca3000_state *st = indio_dev->dev_data;
- int len = 0, ret;
- u8 *rx;
+ int len = 0, ret, val;
+
mutex_lock(&st->lock);
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_MODE, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
+ val = st->rx[0];
mutex_unlock(&st->lock);
if (ret)
goto error_ret;
- rx[1] &= 0x03;
- switch (rx[1]) {
+
+ switch (val & 0x03) {
case SCA3000_MEAS_MODE_NORMAL:
len += sprintf(buf + len, "%d %d %d\n",
st->info->measurement_mode_freq,
@@ -560,7 +530,6 @@ static ssize_t sca3000_read_av_freq(struct device *dev,
st->info->option_mode_2_freq/4);
break;
}
- kfree(rx);
return len;
error_ret:
return ret;
@@ -575,12 +544,11 @@ static inline int __sca3000_get_base_freq(struct sca3000_state *st,
int *base_freq)
{
int ret;
- u8 *rx;
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_MODE, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
if (ret)
goto error_ret;
- switch (0x03 & rx[1]) {
+ switch (0x03 & st->rx[0]) {
case SCA3000_MEAS_MODE_NORMAL:
*base_freq = info->measurement_mode_freq;
break;
@@ -591,7 +559,6 @@ static inline int __sca3000_get_base_freq(struct sca3000_state *st,
*base_freq = info->option_mode_2_freq;
break;
}
- kfree(rx);
error_ret:
return ret;
}
@@ -605,18 +572,19 @@ static ssize_t sca3000_read_frequency(struct device *dev,
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct sca3000_state *st = indio_dev->dev_data;
- int ret, len = 0, base_freq = 0;
- u8 *rx;
+ int ret, len = 0, base_freq = 0, val;
+
mutex_lock(&st->lock);
ret = __sca3000_get_base_freq(st, st->info, &base_freq);
if (ret)
goto error_ret_mut;
- ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, &rx);
+ ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL);
mutex_unlock(&st->lock);
if (ret)
goto error_ret;
+ val = ret;
if (base_freq > 0)
- switch (rx[1]&0x03) {
+ switch (val & 0x03) {
case 0x00:
case 0x03:
len = sprintf(buf, "%d\n", base_freq);
@@ -628,7 +596,7 @@ static ssize_t sca3000_read_frequency(struct device *dev,
len = sprintf(buf, "%d\n", base_freq/4);
break;
}
- kfree(rx);
+
return len;
error_ret_mut:
mutex_unlock(&st->lock);
@@ -647,7 +615,7 @@ static ssize_t sca3000_set_frequency(struct device *dev,
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct sca3000_state *st = indio_dev->dev_data;
int ret, base_freq = 0;
- u8 *rx;
+ int ctrlval;
long val;
ret = strict_strtol(buf, 10, &val);
@@ -660,21 +628,23 @@ static ssize_t sca3000_set_frequency(struct device *dev,
if (ret)
goto error_free_lock;
- ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, &rx);
- if (ret)
+ ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL);
+ if (ret < 0)
goto error_free_lock;
+ ctrlval = ret;
/* clear the bits */
- rx[1] &= ~0x03;
+ ctrlval &= ~0x03;
if (val == base_freq/2) {
- rx[1] |= SCA3000_OUT_CTRL_BUF_DIV_2;
+ ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_2;
} else if (val == base_freq/4) {
- rx[1] |= SCA3000_OUT_CTRL_BUF_DIV_4;
+ ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_4;
} else if (val != base_freq) {
ret = -EINVAL;
goto error_free_lock;
}
- ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, rx[1]);
+ ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL,
+ ctrlval);
error_free_lock:
mutex_unlock(&st->lock);
@@ -704,17 +674,14 @@ static ssize_t sca3000_read_temp(struct device *dev,
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct sca3000_state *st = indio_dev->dev_data;
- int len = 0, ret;
+ int ret;
int val;
- u8 *rx;
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_TEMP_MSB, &rx, 2);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_TEMP_MSB, 2);
if (ret < 0)
goto error_ret;
- val = ((rx[1]&0x3F) << 3) | ((rx[2] & 0xE0) >> 5);
- len += sprintf(buf + len, "%d\n", val);
- kfree(rx);
+ val = ((st->rx[0] & 0x3F) << 3) | ((st->rx[1] & 0xE0) >> 5);
- return len;
+ return sprintf(buf, "%d\n", val);
error_ret:
return ret;
@@ -725,80 +692,71 @@ static IIO_CONST_ATTR_TEMP_SCALE("0.555556");
static IIO_CONST_ATTR_TEMP_OFFSET("-214.6");
/**
- * sca3000_show_thresh() sysfs query of a threshold
+ * sca3000_read_thresh() - query of a threshold
**/
-static ssize_t sca3000_show_thresh(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int sca3000_read_thresh(struct iio_dev *indio_dev,
+ int e,
+ int *val)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ int ret, i;
struct sca3000_state *st = indio_dev->dev_data;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int len = 0, ret;
- u8 *rx;
-
+ int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e);
mutex_lock(&st->lock);
- ret = sca3000_read_ctrl_reg(st,
- this_attr->address,
- &rx);
+ ret = sca3000_read_ctrl_reg(st, sca3000_addresses[num][1]);
mutex_unlock(&st->lock);
- if (ret)
+ if (ret < 0)
return ret;
- len += sprintf(buf + len, "%d\n", rx[1]);
- kfree(rx);
+ *val = 0;
+ if (num == 1)
+ for_each_set_bit(i, (unsigned long *)&ret,
+ ARRAY_SIZE(st->info->mot_det_mult_y))
+ *val += st->info->mot_det_mult_y[i];
+ else
+ for_each_set_bit(i, (unsigned long *)&ret,
+ ARRAY_SIZE(st->info->mot_det_mult_xz))
+ *val += st->info->mot_det_mult_xz[i];
- return len;
+ return 0;
}
/**
- * sca3000_write_thresh() sysfs control of threshold
+ * sca3000_write_thresh() control of threshold
**/
-static ssize_t sca3000_write_thresh(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+static int sca3000_write_thresh(struct iio_dev *indio_dev,
+ int e,
+ int val)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct sca3000_state *st = indio_dev->dev_data;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e);
int ret;
- long val;
+ int i;
+ u8 nonlinear = 0;
+
+ if (num == 1) {
+ i = ARRAY_SIZE(st->info->mot_det_mult_y);
+ while (i > 0)
+ if (val >= st->info->mot_det_mult_y[--i]) {
+ nonlinear |= (1 << i);
+ val -= st->info->mot_det_mult_y[i];
+ }
+ } else {
+ i = ARRAY_SIZE(st->info->mot_det_mult_xz);
+ while (i > 0)
+ if (val >= st->info->mot_det_mult_xz[--i]) {
+ nonlinear |= (1 << i);
+ val -= st->info->mot_det_mult_xz[i];
+ }
+ }
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- return ret;
mutex_lock(&st->lock);
- ret = sca3000_write_ctrl_reg(st, this_attr->address, val);
+ ret = sca3000_write_ctrl_reg(st, sca3000_addresses[num][1], nonlinear);
mutex_unlock(&st->lock);
- return ret ? ret : len;
+ return ret;
}
-static IIO_DEVICE_ATTR(accel_x_raw_mag_rising_value,
- S_IRUGO | S_IWUSR,
- sca3000_show_thresh,
- sca3000_write_thresh,
- SCA3000_REG_CTRL_SEL_MD_X_TH);
-
-static IIO_DEVICE_ATTR(accel_y_raw_mag_rising_value,
- S_IRUGO | S_IWUSR,
- sca3000_show_thresh,
- sca3000_write_thresh,
- SCA3000_REG_CTRL_SEL_MD_Y_TH);
-
-static IIO_DEVICE_ATTR(accel_z_raw_mag_rising_value,
- S_IRUGO | S_IWUSR,
- sca3000_show_thresh,
- sca3000_write_thresh,
- SCA3000_REG_CTRL_SEL_MD_Z_TH);
-
static struct attribute *sca3000_attributes[] = {
- &iio_dev_attr_name.dev_attr.attr,
&iio_dev_attr_revision.dev_attr.attr,
- &iio_dev_attr_accel_scale.dev_attr.attr,
- &iio_dev_attr_accel_x_raw.dev_attr.attr,
- &iio_dev_attr_accel_y_raw.dev_attr.attr,
- &iio_dev_attr_accel_z_raw.dev_attr.attr,
&iio_dev_attr_measurement_mode_available.dev_attr.attr,
&iio_dev_attr_measurement_mode.dev_attr.attr,
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
@@ -807,12 +765,7 @@ static struct attribute *sca3000_attributes[] = {
};
static struct attribute *sca3000_attributes_with_temp[] = {
- &iio_dev_attr_name.dev_attr.attr,
&iio_dev_attr_revision.dev_attr.attr,
- &iio_dev_attr_accel_scale.dev_attr.attr,
- &iio_dev_attr_accel_x_raw.dev_attr.attr,
- &iio_dev_attr_accel_y_raw.dev_attr.attr,
- &iio_dev_attr_accel_z_raw.dev_attr.attr,
&iio_dev_attr_measurement_mode_available.dev_attr.attr,
&iio_dev_attr_measurement_mode.dev_attr.attr,
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
@@ -836,134 +789,102 @@ static const struct attribute_group sca3000_attribute_group_with_temp = {
/* depending on event, push to the ring buffer event chrdev or the event one */
/**
- * sca3000_interrupt_handler_bh() - handling ring and non ring events
+ * sca3000_event_handler() - handling ring and non ring events
*
* This function is complicated by the fact that the devices can signify ring
* and non ring events via the same interrupt line and they can only
* be distinguished via a read of the relevant status register.
**/
-static void sca3000_interrupt_handler_bh(struct work_struct *work_s)
+static irqreturn_t sca3000_event_handler(int irq, void *private)
{
- struct sca3000_state *st
- = container_of(work_s, struct sca3000_state,
- interrupt_handler_ws);
- u8 *rx;
- int ret;
+ struct iio_dev *indio_dev = private;
+ struct sca3000_state *st;
+ int ret, val;
+ s64 last_timestamp = iio_get_time_ns();
+ st = indio_dev->dev_data;
/* Could lead if badly timed to an extra read of status reg,
* but ensures no interrupt is missed.
*/
- enable_irq(st->us->irq);
mutex_lock(&st->lock);
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_INT_STATUS,
- &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_STATUS, 1);
+ val = st->rx[0];
mutex_unlock(&st->lock);
if (ret)
goto done;
- sca3000_ring_int_process(rx[1], st->indio_dev->ring);
+ sca3000_ring_int_process(val, st->indio_dev->ring);
- if (rx[1] & SCA3000_INT_STATUS_FREE_FALL)
+ if (val & SCA3000_INT_STATUS_FREE_FALL)
iio_push_event(st->indio_dev, 0,
IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
0,
IIO_EV_MOD_X_AND_Y_AND_Z,
IIO_EV_TYPE_MAG,
IIO_EV_DIR_FALLING),
- st->last_timestamp);
+ last_timestamp);
- if (rx[1] & SCA3000_INT_STATUS_Y_TRIGGER)
+ if (val & SCA3000_INT_STATUS_Y_TRIGGER)
iio_push_event(st->indio_dev, 0,
IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
0,
IIO_EV_MOD_Y,
IIO_EV_TYPE_MAG,
IIO_EV_DIR_RISING),
- st->last_timestamp);
+ last_timestamp);
- if (rx[1] & SCA3000_INT_STATUS_X_TRIGGER)
+ if (val & SCA3000_INT_STATUS_X_TRIGGER)
iio_push_event(st->indio_dev, 0,
IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
0,
IIO_EV_MOD_X,
IIO_EV_TYPE_MAG,
IIO_EV_DIR_RISING),
- st->last_timestamp);
+ last_timestamp);
- if (rx[1] & SCA3000_INT_STATUS_Z_TRIGGER)
+ if (val & SCA3000_INT_STATUS_Z_TRIGGER)
iio_push_event(st->indio_dev, 0,
IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
0,
IIO_EV_MOD_Z,
IIO_EV_TYPE_MAG,
IIO_EV_DIR_RISING),
- st->last_timestamp);
+ last_timestamp);
done:
- kfree(rx);
- return;
+ return IRQ_HANDLED;
}
/**
- * sca3000_handler_th() handles all interrupt events from device
- *
- * These devices deploy unified interrupt status registers meaning
- * all interrupts must be handled together
- **/
-static int sca3000_handler_th(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct sca3000_state *st = dev_info->dev_data;
-
- st->last_timestamp = timestamp;
- schedule_work(&st->interrupt_handler_ws);
-
- return 0;
-}
-
-/**
- * sca3000_query_mo_det() is motion detection enabled for this axis
- *
- * First queries if motion detection is enabled and then if this axis is
- * on.
+ * sca3000_read_event_config() what events are enabled
**/
-static ssize_t sca3000_query_mo_det(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int sca3000_read_event_config(struct iio_dev *indio_dev,
+ int e)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev->parent);
struct sca3000_state *st = indio_dev->dev_data;
- struct iio_event_attr *this_attr = to_iio_event_attr(attr);
- int ret, len = 0;
- u8 *rx;
+ int ret;
u8 protect_mask = 0x03;
+ int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e);
/* read current value of mode register */
mutex_lock(&st->lock);
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_MODE, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
if (ret)
goto error_ret;
- if ((rx[1]&protect_mask) != SCA3000_MEAS_MODE_MOT_DET)
- len += sprintf(buf + len, "0\n");
+ if ((st->rx[0] & protect_mask) != SCA3000_MEAS_MODE_MOT_DET)
+ ret = 0;
else {
- kfree(rx);
- ret = sca3000_read_ctrl_reg(st,
- SCA3000_REG_CTRL_SEL_MD_CTRL,
- &rx);
- if (ret)
+ ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL);
+ if (ret < 0)
goto error_ret;
/* only supporting logical or's for now */
- len += sprintf(buf + len, "%d\n",
- (rx[1] & this_attr->mask) ? 1 : 0);
+ ret = !!(ret & sca3000_addresses[num][2]);
}
- kfree(rx);
error_ret:
mutex_unlock(&st->lock);
- return ret ? ret : len;
+ return ret;
}
/**
* sca3000_query_free_fall_mode() is free fall mode enabled
@@ -973,80 +894,20 @@ static ssize_t sca3000_query_free_fall_mode(struct device *dev,
char *buf)
{
int ret, len;
- u8 *rx;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct sca3000_state *st = indio_dev->dev_data;
+ int val;
mutex_lock(&st->lock);
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_MODE, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
+ val = st->rx[0];
mutex_unlock(&st->lock);
- if (ret)
+ if (ret < 0)
return ret;
len = sprintf(buf, "%d\n",
- !!(rx[1] & SCA3000_FREE_FALL_DETECT));
- kfree(rx);
-
- return len;
-}
-/**
- * sca3000_query_ring_int() is the hardware ring status interrupt enabled
- **/
-static ssize_t sca3000_query_ring_int(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_event_attr *this_attr = to_iio_event_attr(attr);
- int ret, len;
- u8 *rx;
- struct iio_dev *indio_dev = dev_get_drvdata(dev->parent);
- struct sca3000_state *st = indio_dev->dev_data;
- mutex_lock(&st->lock);
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_INT_MASK, &rx, 1);
- mutex_unlock(&st->lock);
- if (ret)
- return ret;
- len = sprintf(buf, "%d\n", (rx[1] & this_attr->mask) ? 1 : 0);
- kfree(rx);
-
+ !!(val & SCA3000_FREE_FALL_DETECT));
return len;
}
-/**
- * sca3000_set_ring_int() set state of ring status interrupt
- **/
-static ssize_t sca3000_set_ring_int(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev->parent);
- struct sca3000_state *st = indio_dev->dev_data;
- struct iio_event_attr *this_attr = to_iio_event_attr(attr);
-
- long val;
- int ret;
- u8 *rx;
-
- mutex_lock(&st->lock);
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- goto error_ret;
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_INT_MASK, &rx, 1);
- if (ret)
- goto error_ret;
- if (val)
- ret = sca3000_write_reg(st,
- SCA3000_REG_ADDR_INT_MASK,
- rx[1] | this_attr->mask);
- else
- ret = sca3000_write_reg(st,
- SCA3000_REG_ADDR_INT_MASK,
- rx[1] & ~this_attr->mask);
- kfree(rx);
-error_ret:
- mutex_unlock(&st->lock);
-
- return ret ? ret : len;
-}
/**
* sca3000_set_free_fall_mode() simple on off control for free fall int
@@ -1065,7 +926,6 @@ static ssize_t sca3000_set_free_fall_mode(struct device *dev,
struct sca3000_state *st = indio_dev->dev_data;
long val;
int ret;
- u8 *rx;
u8 protect_mask = SCA3000_FREE_FALL_DETECT;
mutex_lock(&st->lock);
@@ -1074,20 +934,18 @@ static ssize_t sca3000_set_free_fall_mode(struct device *dev,
goto error_ret;
/* read current value of mode register */
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_MODE, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
if (ret)
goto error_ret;
/*if off and should be on*/
- if (val && !(rx[1] & protect_mask))
+ if (val && !(st->rx[0] & protect_mask))
ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
- (rx[1] | SCA3000_FREE_FALL_DETECT));
+ (st->rx[0] | SCA3000_FREE_FALL_DETECT));
/* if on and should be off */
- else if (!val && (rx[1]&protect_mask))
+ else if (!val && (st->rx[0] & protect_mask))
ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
- (rx[1] & ~protect_mask));
-
- kfree(rx);
+ (st->rx[0] & ~protect_mask));
error_ret:
mutex_unlock(&st->lock);
@@ -1103,127 +961,77 @@ error_ret:
* There is a complexity in knowing which mode to return to when
* this mode is disabled. Currently normal mode is assumed.
**/
-static ssize_t sca3000_set_mo_det(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+static int sca3000_write_event_config(struct iio_dev *indio_dev,
+ int e,
+ int state)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev->parent);
struct sca3000_state *st = indio_dev->dev_data;
- struct iio_event_attr *this_attr = to_iio_event_attr(attr);
- long val;
- int ret;
- u8 *rx;
+ int ret, ctrlval;
u8 protect_mask = 0x03;
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- return ret;
+ int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e);
mutex_lock(&st->lock);
/* First read the motion detector config to find out if
* this axis is on*/
- ret = sca3000_read_ctrl_reg(st,
- SCA3000_REG_CTRL_SEL_MD_CTRL,
- &rx);
- if (ret)
+ ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL);
+ if (ret < 0)
goto exit_point;
+ ctrlval = ret;
/* Off and should be on */
- if (val && !(rx[1] & this_attr->mask)) {
+ if (state && !(ctrlval & sca3000_addresses[num][2])) {
ret = sca3000_write_ctrl_reg(st,
SCA3000_REG_CTRL_SEL_MD_CTRL,
- rx[1] | this_attr->mask);
+ ctrlval |
+ sca3000_addresses[num][2]);
if (ret)
- goto exit_point_free_rx;
+ goto exit_point;
st->mo_det_use_count++;
- } else if (!val && (rx[1]&this_attr->mask)) {
+ } else if (!state && (ctrlval & sca3000_addresses[num][2])) {
ret = sca3000_write_ctrl_reg(st,
SCA3000_REG_CTRL_SEL_MD_CTRL,
- rx[1] & ~(this_attr->mask));
+ ctrlval &
+ ~(sca3000_addresses[num][2]));
if (ret)
- goto exit_point_free_rx;
+ goto exit_point;
st->mo_det_use_count--;
- } else /* relies on clean state for device on boot */
- goto exit_point_free_rx;
- kfree(rx);
+ }
+
/* read current value of mode register */
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_MODE, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
if (ret)
goto exit_point;
/*if off and should be on*/
if ((st->mo_det_use_count)
- && ((rx[1]&protect_mask) != SCA3000_MEAS_MODE_MOT_DET))
+ && ((st->rx[0] & protect_mask) != SCA3000_MEAS_MODE_MOT_DET))
ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
- (rx[1] & ~protect_mask)
+ (st->rx[0] & ~protect_mask)
| SCA3000_MEAS_MODE_MOT_DET);
/* if on and should be off */
else if (!(st->mo_det_use_count)
- && ((rx[1]&protect_mask) == SCA3000_MEAS_MODE_MOT_DET))
+ && ((st->rx[0] & protect_mask) == SCA3000_MEAS_MODE_MOT_DET))
ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
- (rx[1] & ~protect_mask));
-exit_point_free_rx:
- kfree(rx);
+ (st->rx[0] & ~protect_mask));
exit_point:
mutex_unlock(&st->lock);
- return ret ? ret : len;
+ return ret;
}
-/* Shared event handler for all events as single event status register */
-IIO_EVENT_SH(all, &sca3000_handler_th);
-
/* Free fall detector related event attribute */
-IIO_EVENT_ATTR_NAMED_SH(accel_xayaz_mag_falling_en,
- accel_x&y&z_mag_falling_en,
- iio_event_all,
- sca3000_query_free_fall_mode,
- sca3000_set_free_fall_mode,
- 0);
-
-IIO_CONST_ATTR_NAMED(accel_xayaz_mag_falling_period,
- accel_x&y&z_mag_falling_period,
- "0.226");
-
-/* Motion detector related event attributes */
-IIO_EVENT_ATTR_SH(accel_x_mag_rising_en,
- iio_event_all,
- sca3000_query_mo_det,
- sca3000_set_mo_det,
- SCA3000_MD_CTRL_OR_X);
-
-IIO_EVENT_ATTR_SH(accel_y_mag_rising_en,
- iio_event_all,
- sca3000_query_mo_det,
- sca3000_set_mo_det,
- SCA3000_MD_CTRL_OR_Y);
-
-IIO_EVENT_ATTR_SH(accel_z_mag_rising_en,
- iio_event_all,
- sca3000_query_mo_det,
- sca3000_set_mo_det,
- SCA3000_MD_CTRL_OR_Z);
-
-/* Hardware ring buffer related event attributes */
-IIO_EVENT_ATTR_RING_50_FULL_SH(iio_event_all,
- sca3000_query_ring_int,
- sca3000_set_ring_int,
- SCA3000_INT_MASK_RING_HALF);
-
-IIO_EVENT_ATTR_RING_75_FULL_SH(iio_event_all,
- sca3000_query_ring_int,
- sca3000_set_ring_int,
- SCA3000_INT_MASK_RING_THREE_QUARTER);
+static IIO_DEVICE_ATTR_NAMED(accel_xayaz_mag_falling_en,
+ accel_x&y&z_mag_falling_en,
+ S_IRUGO | S_IWUSR,
+ sca3000_query_free_fall_mode,
+ sca3000_set_free_fall_mode,
+ 0);
+
+static IIO_CONST_ATTR_NAMED(accel_xayaz_mag_falling_period,
+ accel_x&y&z_mag_falling_period,
+ "0.226");
static struct attribute *sca3000_event_attributes[] = {
- &iio_event_attr_accel_xayaz_mag_falling_en.dev_attr.attr,
+ &iio_dev_attr_accel_xayaz_mag_falling_en.dev_attr.attr,
&iio_const_attr_accel_xayaz_mag_falling_period.dev_attr.attr,
- &iio_event_attr_accel_x_mag_rising_en.dev_attr.attr,
- &iio_dev_attr_accel_x_raw_mag_rising_value.dev_attr.attr,
- &iio_event_attr_accel_y_mag_rising_en.dev_attr.attr,
- &iio_dev_attr_accel_y_raw_mag_rising_value.dev_attr.attr,
- &iio_event_attr_accel_z_mag_rising_en.dev_attr.attr,
- &iio_dev_attr_accel_z_raw_mag_rising_value.dev_attr.attr,
- &iio_event_attr_ring_50_full.dev_attr.attr,
- &iio_event_attr_ring_75_full.dev_attr.attr,
NULL,
};
@@ -1241,70 +1049,50 @@ static struct attribute_group sca3000_event_attribute_group = {
static int sca3000_clean_setup(struct sca3000_state *st)
{
int ret;
- u8 *rx;
mutex_lock(&st->lock);
/* Ensure all interrupts have been acknowledged */
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_INT_STATUS, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_STATUS, 1);
if (ret)
goto error_ret;
- kfree(rx);
/* Turn off all motion detection channels */
- ret = sca3000_read_ctrl_reg(st,
- SCA3000_REG_CTRL_SEL_MD_CTRL,
- &rx);
- if (ret)
+ ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL);
+ if (ret < 0)
goto error_ret;
- ret = sca3000_write_ctrl_reg(st,
- SCA3000_REG_CTRL_SEL_MD_CTRL,
- rx[1] & SCA3000_MD_CTRL_PROT_MASK);
- kfree(rx);
+ ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL,
+ ret & SCA3000_MD_CTRL_PROT_MASK);
if (ret)
goto error_ret;
/* Disable ring buffer */
- sca3000_read_ctrl_reg(st,
- SCA3000_REG_CTRL_SEL_OUT_CTRL,
- &rx);
- /* Frequency of ring buffer sampling deliberately restricted to make
- * debugging easier - add control of this later */
- ret = sca3000_write_ctrl_reg(st,
- SCA3000_REG_CTRL_SEL_OUT_CTRL,
- (rx[1] & SCA3000_OUT_CTRL_PROT_MASK)
+ ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL);
+ ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL,
+ (ret & SCA3000_OUT_CTRL_PROT_MASK)
| SCA3000_OUT_CTRL_BUF_X_EN
| SCA3000_OUT_CTRL_BUF_Y_EN
| SCA3000_OUT_CTRL_BUF_Z_EN
| SCA3000_OUT_CTRL_BUF_DIV_4);
- kfree(rx);
-
if (ret)
goto error_ret;
/* Enable interrupts, relevant to mode and set up as active low */
- ret = sca3000_read_data(st,
- SCA3000_REG_ADDR_INT_MASK,
- &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1);
if (ret)
goto error_ret;
ret = sca3000_write_reg(st,
SCA3000_REG_ADDR_INT_MASK,
- (rx[1] & SCA3000_INT_MASK_PROT_MASK)
+ (ret & SCA3000_INT_MASK_PROT_MASK)
| SCA3000_INT_MASK_ACTIVE_LOW);
- kfree(rx);
if (ret)
goto error_ret;
/* Select normal measurement mode, free fall off, ring off */
/* Ring in 12 bit mode - it is fine to overwrite reserved bits 3,5
* as that occurs in one of the example on the datasheet */
- ret = sca3000_read_data(st,
- SCA3000_REG_ADDR_MODE,
- &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
if (ret)
goto error_ret;
- ret = sca3000_write_reg(st,
- SCA3000_REG_ADDR_MODE,
- (rx[1] & SCA3000_MODE_PROT_MASK));
- kfree(rx);
+ ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
+ (st->rx[0] & SCA3000_MODE_PROT_MASK));
st->bpse = 11;
error_ret:
@@ -1312,8 +1100,29 @@ error_ret:
return ret;
}
-static int __devinit __sca3000_probe(struct spi_device *spi,
- enum sca3000_variant variant)
+static const struct iio_info sca3000_info = {
+ .attrs = &sca3000_attribute_group,
+ .read_raw = &sca3000_read_raw,
+ .num_interrupt_lines = 1,
+ .event_attrs = &sca3000_event_attribute_group,
+ .read_event_value = &sca3000_read_thresh,
+ .write_event_value = &sca3000_write_thresh,
+ .read_event_config = &sca3000_read_event_config,
+ .write_event_config = &sca3000_write_event_config,
+ .driver_module = THIS_MODULE,
+};
+
+static const struct iio_info sca3000_info_with_temp = {
+ .attrs = &sca3000_attribute_group_with_temp,
+ .read_raw = &sca3000_read_raw,
+ .read_event_value = &sca3000_read_thresh,
+ .write_event_value = &sca3000_write_thresh,
+ .read_event_config = &sca3000_read_event_config,
+ .write_event_config = &sca3000_write_event_config,
+ .driver_module = THIS_MODULE,
+};
+
+static int __devinit sca3000_probe(struct spi_device *spi)
{
int ret, regdone = 0;
struct sca3000_state *st;
@@ -1325,75 +1134,57 @@ static int __devinit __sca3000_probe(struct spi_device *spi,
}
spi_set_drvdata(spi, st);
- st->tx = kmalloc(sizeof(*st->tx)*6, GFP_KERNEL);
- if (st->tx == NULL) {
- ret = -ENOMEM;
- goto error_clear_st;
- }
- st->rx = kmalloc(sizeof(*st->rx)*3, GFP_KERNEL);
- if (st->rx == NULL) {
- ret = -ENOMEM;
- goto error_free_tx;
- }
st->us = spi;
mutex_init(&st->lock);
- st->info = &sca3000_spi_chip_info_tbl[variant];
+ st->info = &sca3000_spi_chip_info_tbl[spi_get_device_id(spi)
+ ->driver_data];
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
- goto error_free_rx;
+ goto error_clear_st;
}
-
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->num_interrupt_lines = 1;
- st->indio_dev->event_attrs = &sca3000_event_attribute_group;
+ st->indio_dev->name = spi_get_device_id(spi)->name;
if (st->info->temp_output)
- st->indio_dev->attrs = &sca3000_attribute_group_with_temp;
- else
- st->indio_dev->attrs = &sca3000_attribute_group;
+ st->indio_dev->info = &sca3000_info_with_temp;
+ else {
+ st->indio_dev->info = &sca3000_info;
+ st->indio_dev->channels = sca3000_channels;
+ st->indio_dev->num_channels = ARRAY_SIZE(sca3000_channels);
+ }
st->indio_dev->dev_data = (void *)(st);
st->indio_dev->modes = INDIO_DIRECT_MODE;
sca3000_configure_ring(st->indio_dev);
-
ret = iio_device_register(st->indio_dev);
if (ret < 0)
goto error_free_dev;
regdone = 1;
- ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
+ ret = iio_ring_buffer_register_ex(st->indio_dev->ring, 0,
+ sca3000_channels,
+ ARRAY_SIZE(sca3000_channels));
if (ret < 0)
goto error_unregister_dev;
if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) {
- INIT_WORK(&st->interrupt_handler_ws,
- sca3000_interrupt_handler_bh);
- ret = iio_register_interrupt_line(spi->irq,
- st->indio_dev,
- 0,
- IRQF_TRIGGER_FALLING,
- "sca3000");
+ ret = request_threaded_irq(spi->irq,
+ NULL,
+ &sca3000_event_handler,
+ IRQF_TRIGGER_FALLING,
+ "sca3000",
+ st->indio_dev);
if (ret)
goto error_unregister_ring;
- /* RFC
- * Probably a common situation. All interrupts need an ack
- * and there is only one handler so the complicated list system
- * is overkill. At very least a simpler registration method
- * might be worthwhile.
- */
- iio_add_event_to_list(
- iio_event_attr_accel_z_mag_rising_en.listel,
- &st->indio_dev
- ->interrupts[0]->ev_list);
}
sca3000_register_ring_funcs(st->indio_dev);
ret = sca3000_clean_setup(st);
if (ret)
- goto error_unregister_interrupt_line;
+ goto error_free_irq;
return 0;
-error_unregister_interrupt_line:
+error_free_irq:
if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
- iio_unregister_interrupt_line(st->indio_dev, 0);
+ free_irq(spi->irq, st->indio_dev);
error_unregister_ring:
iio_ring_buffer_unregister(st->indio_dev->ring);
error_unregister_dev:
@@ -1402,10 +1193,6 @@ error_free_dev:
iio_device_unregister(st->indio_dev);
else
iio_free_device(st->indio_dev);
-error_free_rx:
- kfree(st->rx);
-error_free_tx:
- kfree(st->tx);
error_clear_st:
kfree(st);
error_ret:
@@ -1415,20 +1202,19 @@ error_ret:
static int sca3000_stop_all_interrupts(struct sca3000_state *st)
{
int ret;
- u8 *rx;
mutex_lock(&st->lock);
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_INT_MASK, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1);
if (ret)
goto error_ret;
ret = sca3000_write_reg(st, SCA3000_REG_ADDR_INT_MASK,
- (rx[1] & ~(SCA3000_INT_MASK_RING_THREE_QUARTER
- | SCA3000_INT_MASK_RING_HALF
- | SCA3000_INT_MASK_ALL_INTS)));
+ (st->rx[0] &
+ ~(SCA3000_INT_MASK_RING_THREE_QUARTER |
+ SCA3000_INT_MASK_RING_HALF |
+ SCA3000_INT_MASK_ALL_INTS)));
error_ret:
- kfree(rx);
+ mutex_unlock(&st->lock);
return ret;
-
}
static int sca3000_remove(struct spi_device *spi)
@@ -1441,87 +1227,44 @@ static int sca3000_remove(struct spi_device *spi)
if (ret)
return ret;
if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
- iio_unregister_interrupt_line(indio_dev, 0);
+ free_irq(spi->irq, indio_dev);
iio_ring_buffer_unregister(indio_dev->ring);
sca3000_unconfigure_ring(indio_dev);
iio_device_unregister(indio_dev);
- kfree(st->tx);
- kfree(st->rx);
kfree(st);
return 0;
}
-/* These macros save on an awful lot of repeated code */
-#define SCA3000_VARIANT_PROBE(_name) \
- static int __devinit \
- sca3000_##_name##_probe(struct spi_device *spi) \
- { \
- return __sca3000_probe(spi, _name); \
- }
-
-#define SCA3000_VARIANT_SPI_DRIVER(_name) \
- struct spi_driver sca3000_##_name##_driver = { \
- .driver = { \
- .name = "sca3000_" #_name, \
- .owner = THIS_MODULE, \
- }, \
- .probe = sca3000_##_name##_probe, \
- .remove = __devexit_p(sca3000_remove), \
- }
-
-SCA3000_VARIANT_PROBE(d01);
-static SCA3000_VARIANT_SPI_DRIVER(d01);
-
-SCA3000_VARIANT_PROBE(e02);
-static SCA3000_VARIANT_SPI_DRIVER(e02);
-
-SCA3000_VARIANT_PROBE(e04);
-static SCA3000_VARIANT_SPI_DRIVER(e04);
+static const struct spi_device_id sca3000_id[] = {
+ {"sca3000_d01", d01},
+ {"sca3000_e02", e02},
+ {"sca3000_e04", e04},
+ {"sca3000_e05", e05},
+ {}
+};
-SCA3000_VARIANT_PROBE(e05);
-static SCA3000_VARIANT_SPI_DRIVER(e05);
+static struct spi_driver sca3000_driver = {
+ .driver = {
+ .name = "sca3000",
+ .owner = THIS_MODULE,
+ },
+ .probe = sca3000_probe,
+ .remove = __devexit_p(sca3000_remove),
+ .id_table = sca3000_id,
+};
static __init int sca3000_init(void)
{
- int ret;
-
- ret = spi_register_driver(&sca3000_d01_driver);
- if (ret)
- goto error_ret;
- ret = spi_register_driver(&sca3000_e02_driver);
- if (ret)
- goto error_unreg_d01;
- ret = spi_register_driver(&sca3000_e04_driver);
- if (ret)
- goto error_unreg_e02;
- ret = spi_register_driver(&sca3000_e05_driver);
- if (ret)
- goto error_unreg_e04;
-
- return 0;
-
-error_unreg_e04:
- spi_unregister_driver(&sca3000_e04_driver);
-error_unreg_e02:
- spi_unregister_driver(&sca3000_e02_driver);
-error_unreg_d01:
- spi_unregister_driver(&sca3000_d01_driver);
-error_ret:
-
- return ret;
+ return spi_register_driver(&sca3000_driver);
}
+module_init(sca3000_init);
static __exit void sca3000_exit(void)
{
- spi_unregister_driver(&sca3000_e05_driver);
- spi_unregister_driver(&sca3000_e04_driver);
- spi_unregister_driver(&sca3000_e02_driver);
- spi_unregister_driver(&sca3000_d01_driver);
+ spi_unregister_driver(&sca3000_driver);
}
-
-module_init(sca3000_init);
module_exit(sca3000_exit);
MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c
index a730a7638de1..7c4ff0b1df04 100644
--- a/drivers/staging/iio/accel/sca3000_ring.c
+++ b/drivers/staging/iio/accel/sca3000_ring.c
@@ -17,6 +17,8 @@
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/sysfs.h>
+#include <linux/sched.h>
+#include <linux/poll.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -34,26 +36,61 @@
* Currently scan elements aren't configured so it doesn't matter.
*/
+static int sca3000_read_data(struct sca3000_state *st,
+ uint8_t reg_address_high,
+ u8 **rx_p,
+ int len)
+{
+ int ret;
+ struct spi_message msg;
+ struct spi_transfer xfer[2] = {
+ {
+ .len = 1,
+ .tx_buf = st->tx,
+ }, {
+ .len = len,
+ }
+ };
+ *rx_p = kmalloc(len, GFP_KERNEL);
+ if (*rx_p == NULL) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+ xfer[1].rx_buf = *rx_p;
+ st->tx[0] = SCA3000_READ_REG(reg_address_high);
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer[0], &msg);
+ spi_message_add_tail(&xfer[1], &msg);
+ ret = spi_sync(st->us, &msg);
+ if (ret) {
+ dev_err(get_device(&st->us->dev), "problem reading register");
+ goto error_free_rx;
+ }
+
+ return 0;
+error_free_rx:
+ kfree(*rx_p);
+error_ret:
+ return ret;
+}
+
/**
- * sca3000_rip_hw_rb() - main ring access function, pulls data from ring
+ * sca3000_read_first_n_hw_rb() - main ring access, pulls data from ring
* @r: the ring
* @count: number of samples to try and pull
* @data: output the actual samples pulled from the hw ring
- * @dead_offset: cheating a bit here: Set to 1 so as to allow for the
- * leading byte used in bus comms.
*
* Currently does not provide timestamps. As the hardware doesn't add them they
* can only be inferred approximately from ring buffer events such as 50% full
* and knowledge of when buffer was last emptied. This is left to userspace.
**/
-static int sca3000_rip_hw_rb(struct iio_ring_buffer *r,
- size_t count, u8 **data, int *dead_offset)
+static int sca3000_read_first_n_hw_rb(struct iio_ring_buffer *r,
+ size_t count, char __user *buf)
{
struct iio_hw_ring_buffer *hw_ring = iio_to_hw_ring_buf(r);
struct iio_dev *indio_dev = hw_ring->private;
struct sca3000_state *st = indio_dev->dev_data;
u8 *rx;
- s16 *samples;
int ret, i, num_available, num_read = 0;
int bytes_per_sample = 1;
@@ -61,44 +98,38 @@ static int sca3000_rip_hw_rb(struct iio_ring_buffer *r,
bytes_per_sample = 2;
mutex_lock(&st->lock);
- /* Check how much data is available:
- * RFC: Implement an ioctl to not bother checking whether there
- * is enough data in the ring? Afterall, if we are responding
- * to an interrupt we have a minimum content guaranteed so it
- * seems slight silly to waste time checking it is there.
- */
- ret = sca3000_read_data(st,
- SCA3000_REG_ADDR_BUF_COUNT,
- &rx, 1);
+ if (count % bytes_per_sample) {
+ ret = -EINVAL;
+ goto error_ret;
+ }
+
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_BUF_COUNT, 1);
if (ret)
goto error_ret;
else
- num_available = rx[1];
- /* num_available is the total number of samples available
+ num_available = st->rx[0];
+ /*
+ * num_available is the total number of samples available
* i.e. number of time points * number of channels.
*/
- kfree(rx);
if (count > num_available * bytes_per_sample)
num_read = num_available*bytes_per_sample;
else
- num_read = count - (count % (bytes_per_sample));
+ num_read = count;
- /* Avoid the read request byte */
- *dead_offset = 1;
ret = sca3000_read_data(st,
SCA3000_REG_ADDR_RING_OUT,
- data, num_read);
-
- /* Convert byte order and shift to default resolution */
- if (st->bpse == 11) {
- samples = (s16*)(*data+1);
- for (i = 0; i < (num_read/2); i++) {
- samples[i] = be16_to_cpup(
- (__be16 *)&(samples[i]));
- samples[i] >>= 3;
- }
- }
+ &rx, num_read);
+ if (ret)
+ goto error_ret;
+ for (i = 0; i < num_read; i++)
+ *(((u16 *)rx) + i) = be16_to_cpup((u16 *)rx + i);
+
+ if (copy_to_user(buf, rx, num_read))
+ ret = -EFAULT;
+ kfree(rx);
+ r->stufftoread = 0;
error_ret:
mutex_unlock(&st->lock);
@@ -127,6 +158,76 @@ static IIO_RING_BYTES_PER_DATUM_ATTR;
static IIO_RING_LENGTH_ATTR;
/**
+ * sca3000_query_ring_int() is the hardware ring status interrupt enabled
+ **/
+static ssize_t sca3000_query_ring_int(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ int ret, val;
+ struct iio_ring_buffer *ring = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = ring->indio_dev;
+ struct sca3000_state *st = indio_dev->dev_data;
+
+ mutex_lock(&st->lock);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1);
+ val = st->rx[0];
+ mutex_unlock(&st->lock);
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "%d\n", !!(val & this_attr->address));
+}
+
+/**
+ * sca3000_set_ring_int() set state of ring status interrupt
+ **/
+static ssize_t sca3000_set_ring_int(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 = indio_dev->dev_data;
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ long val;
+ int ret;
+
+ mutex_lock(&st->lock);
+ ret = strict_strtol(buf, 10, &val);
+ if (ret)
+ goto error_ret;
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1);
+ if (ret)
+ goto error_ret;
+ if (val)
+ ret = sca3000_write_reg(st,
+ SCA3000_REG_ADDR_INT_MASK,
+ st->rx[0] | this_attr->address);
+ else
+ ret = sca3000_write_reg(st,
+ SCA3000_REG_ADDR_INT_MASK,
+ st->rx[0] & ~this_attr->address);
+error_ret:
+ mutex_unlock(&st->lock);
+
+ return ret ? ret : len;
+}
+
+static IIO_DEVICE_ATTR(50_percent, S_IRUGO | S_IWUSR,
+ sca3000_query_ring_int,
+ sca3000_set_ring_int,
+ SCA3000_INT_MASK_RING_HALF);
+
+static IIO_DEVICE_ATTR(75_percent, S_IRUGO | S_IWUSR,
+ sca3000_query_ring_int,
+ 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
@@ -137,20 +238,18 @@ static ssize_t sca3000_show_ring_bpse(struct device *dev,
char *buf)
{
int len = 0, ret;
- u8 *rx;
struct iio_ring_buffer *ring = dev_get_drvdata(dev);
struct iio_dev *indio_dev = ring->indio_dev;
struct sca3000_state *st = indio_dev->dev_data;
mutex_lock(&st->lock);
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_MODE, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
if (ret)
goto error_ret;
- if (rx[1] & SCA3000_RING_BUF_8BIT)
+ if (st->rx[0] & SCA3000_RING_BUF_8BIT)
len = sprintf(buf, "s8/8\n");
else
len = sprintf(buf, "s11/16\n");
- kfree(rx);
error_ret:
mutex_unlock(&st->lock);
@@ -173,20 +272,19 @@ static ssize_t sca3000_store_ring_bpse(struct device *dev,
struct iio_dev *indio_dev = ring->indio_dev;
struct sca3000_state *st = indio_dev->dev_data;
int ret;
- u8 *rx;
mutex_lock(&st->lock);
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_MODE, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
if (ret)
goto error_ret;
- if (strncmp(buf, "s8/8", 4) == 0) {
+ if (sysfs_streq(buf, "s8/8")) {
ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
- rx[1] | SCA3000_RING_BUF_8BIT);
+ st->rx[0] | SCA3000_RING_BUF_8BIT);
st->bpse = 8;
- } else if (strncmp(buf, "s11/16", 5) == 0) {
+ } else if (sysfs_streq(buf, "s11/16")) {
ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
- rx[1] & ~SCA3000_RING_BUF_8BIT);
+ st->rx[0] & ~SCA3000_RING_BUF_8BIT);
st->bpse = 11;
} else
ret = -EINVAL;
@@ -196,32 +294,22 @@ error_ret:
return ret ? ret : len;
}
-static IIO_SCAN_EL_C(accel_x, 0, 0, NULL);
-static IIO_SCAN_EL_C(accel_y, 1, 0, NULL);
-static IIO_SCAN_EL_C(accel_z, 2, 0, NULL);
-static IIO_CONST_ATTR(accel_type_available, "s8/8 s11/16");
-static IIO_DEVICE_ATTR(accel_type,
- S_IRUGO | S_IWUSR,
- sca3000_show_ring_bpse,
- sca3000_store_ring_bpse,
- 0);
+static ssize_t sca3000_show_buffer_scale(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_ring_buffer *ring = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = ring->indio_dev;
+ struct sca3000_state *st = indio_dev->dev_data;
-static struct attribute *sca3000_scan_el_attrs[] = {
- &iio_scan_el_accel_x.dev_attr.attr,
- &iio_const_attr_accel_x_index.dev_attr.attr,
- &iio_scan_el_accel_y.dev_attr.attr,
- &iio_const_attr_accel_y_index.dev_attr.attr,
- &iio_scan_el_accel_z.dev_attr.attr,
- &iio_const_attr_accel_z_index.dev_attr.attr,
- &iio_const_attr_accel_type_available.dev_attr.attr,
- &iio_dev_attr_accel_type.dev_attr.attr,
- NULL
-};
+ return sprintf(buf, "0.%06d\n", 4*st->info->scale);
+}
-static struct attribute_group sca3000_scan_el_group = {
- .attrs = sca3000_scan_el_attrs,
- .name = "scan_elements",
-};
+static IIO_DEVICE_ATTR(accel_scale,
+ S_IRUGO,
+ sca3000_show_buffer_scale,
+ NULL,
+ 0);
/*
* Ring buffer attributes
@@ -233,6 +321,9 @@ static struct attribute *sca3000_ring_attributes[] = {
&dev_attr_length.attr,
&dev_attr_bytes_per_datum.attr,
&dev_attr_enable.attr,
+ &iio_dev_attr_50_percent.dev_attr.attr,
+ &iio_dev_attr_75_percent.dev_attr.attr,
+ &iio_dev_attr_accel_scale.dev_attr.attr,
NULL,
};
@@ -258,11 +349,12 @@ static struct iio_ring_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev)
ring = kzalloc(sizeof *ring, GFP_KERNEL);
if (!ring)
return NULL;
+
ring->private = indio_dev;
buf = &ring->buf;
+ buf->stufftoread = 0;
iio_ring_buffer_init(buf, indio_dev);
buf->dev.type = &sca3000_ring_type;
- device_initialize(&buf->dev);
buf->dev.parent = &indio_dev->dev;
dev_set_drvdata(&buf->dev, (void *)buf);
@@ -275,6 +367,12 @@ static inline void sca3000_rb_free(struct iio_ring_buffer *r)
iio_put_ring_buffer(r);
}
+static const struct iio_ring_access_funcs sca3000_ring_access_funcs = {
+ .read_first_n = &sca3000_read_first_n_hw_rb,
+ .get_length = &sca3000_ring_get_length,
+ .get_bytes_per_datum = &sca3000_ring_get_bytes_per_datum,
+};
+
int sca3000_configure_ring(struct iio_dev *indio_dev)
{
indio_dev->ring = sca3000_rb_allocate(indio_dev);
@@ -282,10 +380,11 @@ int sca3000_configure_ring(struct iio_dev *indio_dev)
return -ENOMEM;
indio_dev->modes |= INDIO_RING_HARDWARE_BUFFER;
- indio_dev->ring->scan_el_attrs = &sca3000_scan_el_group;
- indio_dev->ring->access.rip_lots = &sca3000_rip_hw_rb;
- indio_dev->ring->access.get_length = &sca3000_ring_get_length;
- indio_dev->ring->access.get_bytes_per_datum = &sca3000_ring_get_bytes_per_datum;
+ indio_dev->ring->access = &sca3000_ring_access_funcs;
+
+ iio_scan_mask_set(indio_dev->ring, 0);
+ iio_scan_mask_set(indio_dev->ring, 1);
+ iio_scan_mask_set(indio_dev->ring, 2);
return 0;
}
@@ -300,22 +399,20 @@ int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state)
{
struct sca3000_state *st = indio_dev->dev_data;
int ret;
- u8 *rx;
mutex_lock(&st->lock);
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_MODE, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
if (ret)
goto error_ret;
if (state) {
printk(KERN_INFO "supposedly enabling ring buffer\n");
ret = sca3000_write_reg(st,
SCA3000_REG_ADDR_MODE,
- (rx[1] | SCA3000_RING_BUF_ENABLE));
+ (st->rx[0] | SCA3000_RING_BUF_ENABLE));
} else
ret = sca3000_write_reg(st,
SCA3000_REG_ADDR_MODE,
- (rx[1] & ~SCA3000_RING_BUF_ENABLE));
- kfree(rx);
+ (st->rx[0] & ~SCA3000_RING_BUF_ENABLE));
error_ret:
mutex_unlock(&st->lock);
@@ -338,10 +435,14 @@ static int sca3000_hw_ring_postdisable(struct iio_dev *indio_dev)
return __sca3000_hw_ring_state_set(indio_dev, 0);
}
+static const struct iio_ring_setup_ops sca3000_ring_setup_ops = {
+ .preenable = &sca3000_hw_ring_preenable,
+ .postdisable = &sca3000_hw_ring_postdisable,
+};
+
void sca3000_register_ring_funcs(struct iio_dev *indio_dev)
{
- indio_dev->ring->preenable = &sca3000_hw_ring_preenable;
- indio_dev->ring->postdisable = &sca3000_hw_ring_postdisable;
+ indio_dev->ring->setup_ops = &sca3000_ring_setup_ops;
}
/**
@@ -352,11 +453,9 @@ void sca3000_register_ring_funcs(struct iio_dev *indio_dev)
**/
void sca3000_ring_int_process(u8 val, struct iio_ring_buffer *ring)
{
- if (val & SCA3000_INT_STATUS_THREE_QUARTERS)
- iio_push_or_escallate_ring_event(ring,
- IIO_EVENT_CODE_RING_75_FULL,
- 0);
- else if (val & SCA3000_INT_STATUS_HALF)
- iio_push_ring_event(ring,
- IIO_EVENT_CODE_RING_50_FULL, 0);
+ if (val & (SCA3000_INT_STATUS_THREE_QUARTERS |
+ SCA3000_INT_STATUS_HALF)) {
+ ring->stufftoread = true;
+ wake_up_interruptible(&ring->pollq);
+ }
}
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index 6692a3d87f23..8c751c46ddd7 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -3,30 +3,6 @@
#
comment "Analog to digital convertors"
-config MAX1363
- tristate "MAXIM max1363 ADC driver"
- depends on I2C
- select IIO_TRIGGER if IIO_RING_BUFFER
- select MAX1363_RING_BUFFER
- help
- Say yes here to build support for many MAXIM i2c analog to digital
- convertors (ADC). (max1361, max1362, max1363, max1364, max1036,
- max1037, max1038, max1039, max1136, max1136, max1137, max1138,
- max1139, max1236, max1237, max11238, max1239, max11600, max11601,
- max11602, max11603, max11604, max11605, max11606, max11607,
- max11608, max11609, max11610, max11611, max11612, max11613,
- max11614, max11615, max11616, max11617) Provides direct access
- via sysfs.
-
-config MAX1363_RING_BUFFER
- bool "MAXIM max1363: use ring buffer"
- depends on MAX1363
- select IIO_RING_BUFFER
- select IIO_SW_RING
- help
- Say yes here to include ring buffer support in the MAX1363
- ADC driver.
-
config AD7150
tristate "Analog Devices ad7150/1/6 capacitive sensor driver"
depends on I2C
@@ -142,6 +118,18 @@ config AD7887
To compile this driver as a module, choose M here: the
module will be called ad7887.
+config AD7780
+ tristate "Analog Devices AD7780 AD7781 ADC driver"
+ depends on SPI
+ depends on GPIOLIB
+ help
+ Say yes here to build support for Analog Devices
+ AD7780 and AD7781 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 ad7780.
+
config AD7745
tristate "Analog Devices AD7745, AD7746 AD7747 capacitive sensor driver"
depends on I2C
@@ -179,3 +167,27 @@ config ADT7410
help
Say yes here to build support for Analog Devices ADT7410
temperature sensors.
+
+config MAX1363
+ tristate "Maxim max1363 ADC driver"
+ depends on I2C
+ select IIO_TRIGGER if IIO_RING_BUFFER
+ select MAX1363_RING_BUFFER
+ help
+ Say yes here to build support for many Maxim i2c analog to digital
+ convertors (ADC). (max1361, max1362, max1363, max1364, max1036,
+ max1037, max1038, max1039, max1136, max1136, max1137, max1138,
+ max1139, max1236, max1237, max11238, max1239, max11600, max11601,
+ max11602, max11603, max11604, max11605, max11606, max11607,
+ max11608, max11609, max11610, max11611, max11612, max11613,
+ max11614, max11615, max11616, max11617, max11644, max11645,
+ max11646, max11647) Provides direct access via sysfs.
+
+config MAX1363_RING_BUFFER
+ bool "Maxim max1363: use ring buffer"
+ depends on MAX1363
+ select IIO_RING_BUFFER
+ select IIO_SW_RING
+ help
+ Say yes here to include ring buffer support in the MAX1363
+ ADC driver.
diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
index 31067defd79b..1d9b3f582eab 100644
--- a/drivers/staging/iio/adc/Makefile
+++ b/drivers/staging/iio/adc/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_AD7152) += ad7152.o
obj-$(CONFIG_AD7291) += ad7291.o
obj-$(CONFIG_AD7314) += ad7314.o
obj-$(CONFIG_AD7745) += ad7745.o
+obj-$(CONFIG_AD7780) += ad7780.o
obj-$(CONFIG_AD7816) += ad7816.o
obj-$(CONFIG_ADT75) += adt75.o
obj-$(CONFIG_ADT7310) += adt7310.o
diff --git a/drivers/staging/iio/adc/ad7150.c b/drivers/staging/iio/adc/ad7150.c
index 8555766109d8..ca32b6778a9e 100644
--- a/drivers/staging/iio/adc/ad7150.c
+++ b/drivers/staging/iio/adc/ad7150.c
@@ -7,15 +7,10 @@
*/
#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
#include <linux/i2c.h>
-#include <linux/rtc.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -63,12 +58,9 @@
*/
struct ad7150_chip_info {
- const char *name;
struct i2c_client *client;
struct iio_dev *indio_dev;
- struct work_struct thresh_work;
bool inter;
- s64 last_timestamp;
u16 ch1_threshold; /* Ch1 Threshold (in fixed threshold mode) */
u8 ch1_sensitivity; /* Ch1 Sensitivity (in adaptive threshold mode) */
u8 ch1_timeout; /* Ch1 Timeout (in adaptive threshold mode) */
@@ -88,7 +80,8 @@ struct ad7150_conversion_mode {
u8 reg_cfg;
};
-struct ad7150_conversion_mode ad7150_conv_mode_table[AD7150_MAX_CONV_MODE] = {
+static struct ad7150_conversion_mode
+ad7150_conv_mode_table[AD7150_MAX_CONV_MODE] = {
{ "idle", 0 },
{ "continuous-conversion", 1 },
{ "single-conversion", 2 },
@@ -590,17 +583,6 @@ static IIO_DEV_ATTR_CH2_SETUP(S_IRUGO | S_IWUSR,
ad7150_show_ch2_setup,
ad7150_store_ch2_setup);
-static ssize_t ad7150_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7150_chip_info *chip = dev_info->dev_data;
- return sprintf(buf, "%s\n", chip->name);
-}
-
-static IIO_DEVICE_ATTR(name, S_IRUGO, ad7150_show_name, NULL, 0);
-
static ssize_t ad7150_show_powerdown_timer(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -649,7 +631,6 @@ static struct attribute *ad7150_attributes[] = {
&iio_dev_attr_powerdown_timer.dev_attr.attr,
&iio_dev_attr_ch1_value.dev_attr.attr,
&iio_dev_attr_ch2_value.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
NULL,
};
@@ -661,96 +642,57 @@ static const struct attribute_group ad7150_attribute_group = {
* threshold events
*/
-#define IIO_EVENT_CODE_CH1_HIGH IIO_BUFFER_EVENT_CODE(0)
-#define IIO_EVENT_CODE_CH1_LOW IIO_BUFFER_EVENT_CODE(1)
-#define IIO_EVENT_CODE_CH2_HIGH IIO_BUFFER_EVENT_CODE(2)
-#define IIO_EVENT_CODE_CH2_LOW IIO_BUFFER_EVENT_CODE(3)
-
-#define IIO_EVENT_ATTR_CH1_HIGH_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(ch1_high, _evlist, _show, _store, _mask)
-
-#define IIO_EVENT_ATTR_CH2_HIGH_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(ch2_high, _evlist, _show, _store, _mask)
-
-#define IIO_EVENT_ATTR_CH1_LOW_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(ch1_low, _evlist, _show, _store, _mask)
-
-#define IIO_EVENT_ATTR_CH2_LOW_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(ch2_low, _evlist, _show, _store, _mask)
-
-static void ad7150_interrupt_handler_bh(struct work_struct *work_s)
+static irqreturn_t ad7150_event_handler(int irq, void *private)
{
- struct ad7150_chip_info *chip =
- container_of(work_s, struct ad7150_chip_info, thresh_work);
+ struct iio_dev *indio_dev = private;
+ struct ad7150_chip_info *chip = iio_dev_get_devdata(indio_dev);
u8 int_status;
-
- enable_irq(chip->client->irq);
+ s64 timestamp = iio_get_time_ns();
ad7150_i2c_read(chip, AD7150_STATUS, &int_status, 1);
if ((int_status & AD7150_STATUS_OUT1) && !(chip->old_state & AD7150_STATUS_OUT1))
- iio_push_event(chip->indio_dev, 0,
- IIO_EVENT_CODE_CH1_HIGH,
- chip->last_timestamp);
+ iio_push_event(indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_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(chip->indio_dev, 0,
- IIO_EVENT_CODE_CH1_LOW,
- chip->last_timestamp);
+ iio_push_event(indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN,
+ 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ timestamp);
if ((int_status & AD7150_STATUS_OUT2) && !(chip->old_state & AD7150_STATUS_OUT2))
- iio_push_event(chip->indio_dev, 0,
- IIO_EVENT_CODE_CH2_HIGH,
- chip->last_timestamp);
+ iio_push_event(indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_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(chip->indio_dev, 0,
- IIO_EVENT_CODE_CH2_LOW,
- chip->last_timestamp);
+ iio_push_event(indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN,
+ 1,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ timestamp);
+ return IRQ_HANDLED;
}
-static int ad7150_interrupt_handler_th(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct ad7150_chip_info *chip = dev_info->dev_data;
-
- chip->last_timestamp = timestamp;
- schedule_work(&chip->thresh_work);
-
- return 0;
-}
-
-IIO_EVENT_SH(threshold, &ad7150_interrupt_handler_th);
-
-static ssize_t ad7150_query_out_mode(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- /*
- * AD7150 provides two logic output channels, which can be used as interrupt
- * but the pins are not configurable
- */
- return sprintf(buf, "1\n");
-}
-
-static ssize_t ad7150_set_out_mode(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return len;
-}
-
-IIO_EVENT_ATTR_CH1_HIGH_SH(iio_event_threshold, ad7150_query_out_mode, ad7150_set_out_mode, 0);
-IIO_EVENT_ATTR_CH2_HIGH_SH(iio_event_threshold, ad7150_query_out_mode, ad7150_set_out_mode, 0);
-IIO_EVENT_ATTR_CH1_LOW_SH(iio_event_threshold, ad7150_query_out_mode, ad7150_set_out_mode, 0);
-IIO_EVENT_ATTR_CH2_LOW_SH(iio_event_threshold, ad7150_query_out_mode, ad7150_set_out_mode, 0);
+static IIO_CONST_ATTR(ch1_high_en, "1");
+static IIO_CONST_ATTR(ch2_high_en, "1");
+static IIO_CONST_ATTR(ch1_low_en, "1");
+static IIO_CONST_ATTR(ch2_low_en, "1");
static struct attribute *ad7150_event_attributes[] = {
- &iio_event_attr_ch1_high.dev_attr.attr,
- &iio_event_attr_ch2_high.dev_attr.attr,
- &iio_event_attr_ch1_low.dev_attr.attr,
- &iio_event_attr_ch2_low.dev_attr.attr,
+ &iio_const_attr_ch1_high_en.dev_attr.attr,
+ &iio_const_attr_ch2_high_en.dev_attr.attr,
+ &iio_const_attr_ch1_low_en.dev_attr.attr,
+ &iio_const_attr_ch2_low_en.dev_attr.attr,
NULL,
};
@@ -758,6 +700,12 @@ static struct attribute_group ad7150_event_attribute_group = {
.attrs = ad7150_event_attributes,
};
+static const struct iio_info ad7150_info = {
+ .attrs = &ad7150_attribute_group,
+ .num_interrupt_lines = 1,
+ .event_attrs = &ad7150_event_attribute_group,
+ .driver_module = THIS_MODULE,
+};
/*
* device probe and remove
*/
@@ -776,21 +724,20 @@ static int __devinit ad7150_probe(struct i2c_client *client,
i2c_set_clientdata(client, chip);
chip->client = client;
- chip->name = id->name;
- chip->indio_dev = iio_allocate_device();
+ chip->indio_dev = iio_allocate_device(0);
if (chip->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_chip;
}
- /* Echipabilish that the iio_dev is a child of the i2c device */
+ /* Establish that the iio_dev is a child of the i2c device */
+ chip->indio_dev->name = id->name;
chip->indio_dev->dev.parent = &client->dev;
- chip->indio_dev->attrs = &ad7150_attribute_group;
- chip->indio_dev->event_attrs = &ad7150_event_attribute_group;
+
+ chip->indio_dev->info = &ad7150_info;
chip->indio_dev->dev_data = (void *)(chip);
- chip->indio_dev->driver_module = THIS_MODULE;
- chip->indio_dev->num_interrupt_lines = 1;
+
chip->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(chip->indio_dev);
@@ -798,19 +745,16 @@ static int __devinit ad7150_probe(struct i2c_client *client,
goto error_free_dev;
regdone = 1;
- if (client->irq && gpio_is_valid(irq_to_gpio(client->irq)) > 0) {
- ret = iio_register_interrupt_line(client->irq,
- chip->indio_dev,
- 0,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- "ad7150");
+ if (client->irq) {
+ ret = request_threaded_irq(client->irq,
+ NULL,
+ &ad7150_event_handler,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING,
+ "ad7150",
+ chip->indio_dev);
if (ret)
goto error_free_dev;
-
- iio_add_event_to_list(iio_event_attr_ch2_low.listel,
- &chip->indio_dev->interrupts[0]->ev_list);
-
- INIT_WORK(&chip->thresh_work, ad7150_interrupt_handler_bh);
}
dev_err(&client->dev, "%s capacitive sensor registered, irq: %d\n", id->name, client->irq);
@@ -833,8 +777,8 @@ static int __devexit ad7150_remove(struct i2c_client *client)
struct ad7150_chip_info *chip = i2c_get_clientdata(client);
struct iio_dev *indio_dev = chip->indio_dev;
- if (client->irq && gpio_is_valid(irq_to_gpio(client->irq)) > 0)
- iio_unregister_interrupt_line(indio_dev, 0);
+ if (client->irq)
+ free_irq(client->irq, indio_dev);
iio_device_unregister(indio_dev);
kfree(chip);
diff --git a/drivers/staging/iio/adc/ad7152.c b/drivers/staging/iio/adc/ad7152.c
index fa7f84062307..7a38bcbbe1af 100644
--- a/drivers/staging/iio/adc/ad7152.c
+++ b/drivers/staging/iio/adc/ad7152.c
@@ -7,15 +7,11 @@
*/
#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
-#include <linux/list.h>
#include <linux/i2c.h>
-#include <linux/rtc.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -54,7 +50,6 @@
*/
struct ad7152_chip_info {
- const char *name;
struct i2c_client *client;
struct iio_dev *indio_dev;
u16 ch1_offset; /* Channel 1 offset calibration coefficient */
@@ -72,7 +67,8 @@ struct ad7152_conversion_mode {
u8 reg_cfg;
};
-struct ad7152_conversion_mode ad7152_conv_mode_table[AD7152_MAX_CONV_MODE] = {
+static struct ad7152_conversion_mode
+ad7152_conv_mode_table[AD7152_MAX_CONV_MODE] = {
{ "idle", 0 },
{ "continuous-conversion", 1 },
{ "single-conversion", 2 },
@@ -482,17 +478,6 @@ static IIO_DEV_ATTR_FILTER_RATE_SETUP(S_IRUGO | S_IWUSR,
ad7152_show_filter_rate_setup,
ad7152_store_filter_rate_setup);
-static ssize_t ad7152_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7152_chip_info *chip = dev_info->dev_data;
- return sprintf(buf, "%s\n", chip->name);
-}
-
-static IIO_DEVICE_ATTR(name, S_IRUGO, ad7152_show_name, NULL, 0);
-
static struct attribute *ad7152_attributes[] = {
&iio_dev_attr_available_conversion_modes.dev_attr.attr,
&iio_dev_attr_conversion_mode.dev_attr.attr,
@@ -505,7 +490,6 @@ static struct attribute *ad7152_attributes[] = {
&iio_dev_attr_ch1_setup.dev_attr.attr,
&iio_dev_attr_ch2_setup.dev_attr.attr,
&iio_dev_attr_filter_rate_setup.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
NULL,
};
@@ -513,6 +497,10 @@ static const struct attribute_group ad7152_attribute_group = {
.attrs = ad7152_attributes,
};
+static const struct iio_info ad7152_info = {
+ .attrs = &ad7152_attribute_group,
+ .driver_module = THIS_MODULE,
+};
/*
* device probe and remove
*/
@@ -531,19 +519,18 @@ static int __devinit ad7152_probe(struct i2c_client *client,
i2c_set_clientdata(client, chip);
chip->client = client;
- chip->name = id->name;
- chip->indio_dev = iio_allocate_device();
+ chip->indio_dev = iio_allocate_device(0);
if (chip->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_chip;
}
/* Echipabilish that the iio_dev is a child of the i2c device */
+ chip->indio_dev->name = id->name;
chip->indio_dev->dev.parent = &client->dev;
- chip->indio_dev->attrs = &ad7152_attribute_group;
+ chip->indio_dev->info = &ad7152_info;
chip->indio_dev->dev_data = (void *)(chip);
- chip->indio_dev->driver_module = THIS_MODULE;
chip->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(chip->indio_dev);
@@ -567,8 +554,6 @@ static int __devexit ad7152_remove(struct i2c_client *client)
struct ad7152_chip_info *chip = i2c_get_clientdata(client);
struct iio_dev *indio_dev = chip->indio_dev;
- if (client->irq && gpio_is_valid(irq_to_gpio(client->irq)) > 0)
- iio_unregister_interrupt_line(indio_dev, 0);
iio_device_unregister(indio_dev);
kfree(chip);
diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c
index 34041a72aa52..1be3453479b7 100644
--- a/drivers/staging/iio/adc/ad7291.c
+++ b/drivers/staging/iio/adc/ad7291.c
@@ -8,14 +8,12 @@
#include <linux/interrupt.h>
#include <linux/gpio.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/i2c.h>
-#include <linux/rtc.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -62,11 +60,8 @@
*/
struct ad7291_chip_info {
- const char *name;
struct i2c_client *client;
struct iio_dev *indio_dev;
- struct work_struct thresh_work;
- s64 last_timestamp;
u16 command;
u8 channels; /* Active voltage channels */
};
@@ -438,17 +433,6 @@ static IIO_DEVICE_ATTR(channel_mask, S_IRUGO | S_IWUSR,
ad7291_store_channel_mask,
0);
-static ssize_t ad7291_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7291_chip_info *chip = dev_info->dev_data;
- return sprintf(buf, "%s\n", chip->name);
-}
-
-static IIO_DEVICE_ATTR(name, S_IRUGO, ad7291_show_name, NULL, 0);
-
static struct attribute *ad7291_attributes[] = {
&iio_dev_attr_available_modes.dev_attr.attr,
&iio_dev_attr_mode.dev_attr.attr,
@@ -459,7 +443,6 @@ static struct attribute *ad7291_attributes[] = {
&iio_dev_attr_t_average.dev_attr.attr,
&iio_dev_attr_voltage.dev_attr.attr,
&iio_dev_attr_channel_mask.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
NULL,
};
@@ -471,28 +454,23 @@ static const struct attribute_group ad7291_attribute_group = {
* temperature bound events
*/
-#define IIO_EVENT_CODE_AD7291_T_SENSE_HIGH IIO_BUFFER_EVENT_CODE(0)
-#define IIO_EVENT_CODE_AD7291_T_SENSE_LOW IIO_BUFFER_EVENT_CODE(1)
-#define IIO_EVENT_CODE_AD7291_T_AVG_HIGH IIO_BUFFER_EVENT_CODE(2)
-#define IIO_EVENT_CODE_AD7291_T_AVG_LOW IIO_BUFFER_EVENT_CODE(3)
-#define IIO_EVENT_CODE_AD7291_VOLTAGE_BASE IIO_BUFFER_EVENT_CODE(4)
-
-static void ad7291_interrupt_bh(struct work_struct *work_s)
+static irqreturn_t ad7291_event_handler(int irq, void *private)
{
- struct ad7291_chip_info *chip =
- container_of(work_s, struct ad7291_chip_info, thresh_work);
+ struct iio_dev *indio_dev = private;
+ struct ad7291_chip_info *chip = iio_dev_get_devdata(private);
u16 t_status, v_status;
u16 command;
int i;
+ s64 timestamp = iio_get_time_ns();
if (ad7291_i2c_read(chip, AD7291_T_ALERT_STATUS, &t_status))
- return;
+ return IRQ_HANDLED;
if (ad7291_i2c_read(chip, AD7291_VOLTAGE_ALERT_STATUS, &v_status))
- return;
+ return IRQ_HANDLED;
if (!(t_status || v_status))
- return;
+ return IRQ_HANDLED;
command = chip->command | AD7291_ALART_CLEAR;
ad7291_i2c_write(chip, AD7291_COMMAND, command);
@@ -500,50 +478,67 @@ static void ad7291_interrupt_bh(struct work_struct *work_s)
command = chip->command & ~AD7291_ALART_CLEAR;
ad7291_i2c_write(chip, AD7291_COMMAND, command);
- enable_irq(chip->client->irq);
-
- for (i = 0; i < 4; i++) {
- if (t_status & (1 << i))
- iio_push_event(chip->indio_dev, 0,
- IIO_EVENT_CODE_AD7291_T_SENSE_HIGH + i,
- chip->last_timestamp);
- }
-
- for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT*2; i++) {
+ if (t_status & (1 << 0))
+ iio_push_event(indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP,
+ 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ timestamp);
+ if (t_status & (1 << 1))
+ iio_push_event(indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP,
+ 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ timestamp);
+ if (t_status & (1 << 2))
+ iio_push_event(indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP,
+ 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ timestamp);
+ if (t_status & (1 << 3))
+ iio_push_event(indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP,
+ 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ timestamp);
+
+ for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT*2; i += 2) {
if (v_status & (1 << i))
- iio_push_event(chip->indio_dev, 0,
- IIO_EVENT_CODE_AD7291_VOLTAGE_BASE + i,
- chip->last_timestamp);
+ iio_push_event(indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_IN,
+ i/2,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ timestamp);
+ if (v_status & (1 << (i + 1)))
+ iio_push_event(indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_IN,
+ i/2,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ timestamp);
}
-}
-
-static int ad7291_interrupt(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct ad7291_chip_info *chip = dev_info->dev_data;
-
- chip->last_timestamp = timestamp;
- schedule_work(&chip->thresh_work);
- return 0;
+ return IRQ_HANDLED;
}
-IIO_EVENT_SH(ad7291, &ad7291_interrupt);
-
static inline ssize_t ad7291_show_t_bound(struct device *dev,
struct device_attribute *attr,
- u8 bound_reg,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
struct ad7291_chip_info *chip = dev_info->dev_data;
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
u16 data;
char sign = ' ';
int ret;
- ret = ad7291_i2c_read(chip, bound_reg, &data);
+ ret = ad7291_i2c_read(chip, this_attr->address, &data);
if (ret)
return -EIO;
@@ -561,12 +556,12 @@ static inline ssize_t ad7291_show_t_bound(struct device *dev,
static inline ssize_t ad7291_set_t_bound(struct device *dev,
struct device_attribute *attr,
- u8 bound_reg,
const char *buf,
size_t len)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
struct ad7291_chip_info *chip = dev_info->dev_data;
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
long tmp1, tmp2;
u16 data;
char *pos;
@@ -600,64 +595,13 @@ static inline ssize_t ad7291_set_t_bound(struct device *dev,
/* convert positive value to supplyment */
data = (AD7291_T_VALUE_SIGN << 1) - data;
- ret = ad7291_i2c_write(chip, bound_reg, data);
+ ret = ad7291_i2c_write(chip, this_attr->address, data);
if (ret)
return -EIO;
return ret;
}
-static ssize_t ad7291_show_t_sense_high(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return ad7291_show_t_bound(dev, attr,
- AD7291_T_SENSE_HIGH, buf);
-}
-
-static inline ssize_t ad7291_set_t_sense_high(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return ad7291_set_t_bound(dev, attr,
- AD7291_T_SENSE_HIGH, buf, len);
-}
-
-static ssize_t ad7291_show_t_sense_low(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return ad7291_show_t_bound(dev, attr,
- AD7291_T_SENSE_LOW, buf);
-}
-
-static inline ssize_t ad7291_set_t_sense_low(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return ad7291_set_t_bound(dev, attr,
- AD7291_T_SENSE_LOW, buf, len);
-}
-
-static ssize_t ad7291_show_t_sense_hyst(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return ad7291_show_t_bound(dev, attr,
- AD7291_T_SENSE_HYST, buf);
-}
-
-static inline ssize_t ad7291_set_t_sense_hyst(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return ad7291_set_t_bound(dev, attr,
- AD7291_T_SENSE_HYST, buf, len);
-}
-
static inline ssize_t ad7291_show_v_bound(struct device *dev,
struct device_attribute *attr,
u8 bound_reg,
@@ -712,191 +656,121 @@ static inline ssize_t ad7291_set_v_bound(struct device *dev,
return ret;
}
-static int ad7291_get_voltage_limit_regs(const char *channel)
-{
- int index;
-
- if (strlen(channel) < 3 && channel[0] != 'v')
- return -EINVAL;
-
- index = channel[1] - '0';
- if (index >= AD7291_VOLTAGE_LIMIT_COUNT)
- return -EINVAL;
-
- return index;
-}
-
-static ssize_t ad7291_show_voltage_high(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int regs;
-
- regs = ad7291_get_voltage_limit_regs(attr->attr.name);
-
- if (regs < 0)
- return regs;
-
- return ad7291_show_t_bound(dev, attr, regs, buf);
-}
-
-static inline ssize_t ad7291_set_voltage_high(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- int regs;
-
- regs = ad7291_get_voltage_limit_regs(attr->attr.name);
-
- if (regs < 0)
- return regs;
-
- return ad7291_set_t_bound(dev, attr, regs, buf, len);
-}
-
-static ssize_t ad7291_show_voltage_low(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int regs;
-
- regs = ad7291_get_voltage_limit_regs(attr->attr.name);
-
- if (regs < 0)
- return regs;
-
- return ad7291_show_t_bound(dev, attr, regs+1, buf);
-}
-
-static inline ssize_t ad7291_set_voltage_low(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- int regs;
-
- regs = ad7291_get_voltage_limit_regs(attr->attr.name);
-
- if (regs < 0)
- return regs;
-
- return ad7291_set_t_bound(dev, attr, regs+1, buf, len);
-}
-
-static ssize_t ad7291_show_voltage_hyst(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int regs;
-
- regs = ad7291_get_voltage_limit_regs(attr->attr.name);
-
- if (regs < 0)
- return regs;
-
- return ad7291_show_t_bound(dev, attr, regs+2, buf);
-}
-
-static inline ssize_t ad7291_set_voltage_hyst(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- int regs;
-
- regs = ad7291_get_voltage_limit_regs(attr->attr.name);
-
- if (regs < 0)
- return regs;
-
- return ad7291_set_t_bound(dev, attr, regs+2, buf, len);
-}
-
-IIO_EVENT_ATTR_SH(t_sense_high, iio_event_ad7291,
- ad7291_show_t_sense_high, ad7291_set_t_sense_high, 0);
-IIO_EVENT_ATTR_SH(t_sense_low, iio_event_ad7291,
- ad7291_show_t_sense_low, ad7291_set_t_sense_low, 0);
-IIO_EVENT_ATTR_SH(t_sense_hyst, iio_event_ad7291,
- ad7291_show_t_sense_hyst, ad7291_set_t_sense_hyst, 0);
-
-IIO_EVENT_ATTR_SH(v0_high, iio_event_ad7291,
- ad7291_show_voltage_high, ad7291_set_voltage_high, 0);
-IIO_EVENT_ATTR_SH(v0_low, iio_event_ad7291,
- ad7291_show_voltage_low, ad7291_set_voltage_low, 0);
-IIO_EVENT_ATTR_SH(v0_hyst, iio_event_ad7291,
- ad7291_show_voltage_hyst, ad7291_set_voltage_hyst, 0);
-IIO_EVENT_ATTR_SH(v1_high, iio_event_ad7291,
- ad7291_show_voltage_high, ad7291_set_voltage_high, 0);
-IIO_EVENT_ATTR_SH(v1_low, iio_event_ad7291,
- ad7291_show_voltage_low, ad7291_set_voltage_low, 0);
-IIO_EVENT_ATTR_SH(v1_hyst, iio_event_ad7291,
- ad7291_show_voltage_hyst, ad7291_set_voltage_hyst, 0);
-IIO_EVENT_ATTR_SH(v2_high, iio_event_ad7291,
- ad7291_show_voltage_high, ad7291_set_voltage_high, 0);
-IIO_EVENT_ATTR_SH(v2_low, iio_event_ad7291,
- ad7291_show_voltage_low, ad7291_set_voltage_low, 0);
-IIO_EVENT_ATTR_SH(v2_hyst, iio_event_ad7291,
- ad7291_show_voltage_hyst, ad7291_set_voltage_hyst, 0);
-IIO_EVENT_ATTR_SH(v3_high, iio_event_ad7291,
- ad7291_show_voltage_high, ad7291_set_voltage_high, 0);
-IIO_EVENT_ATTR_SH(v3_low, iio_event_ad7291,
- ad7291_show_voltage_low, ad7291_set_voltage_low, 0);
-IIO_EVENT_ATTR_SH(v3_hyst, iio_event_ad7291,
- ad7291_show_voltage_hyst, ad7291_set_voltage_hyst, 0);
-IIO_EVENT_ATTR_SH(v4_high, iio_event_ad7291,
- ad7291_show_voltage_high, ad7291_set_voltage_high, 0);
-IIO_EVENT_ATTR_SH(v4_low, iio_event_ad7291,
- ad7291_show_voltage_low, ad7291_set_voltage_low, 0);
-IIO_EVENT_ATTR_SH(v4_hyst, iio_event_ad7291,
- ad7291_show_voltage_hyst, ad7291_set_voltage_hyst, 0);
-IIO_EVENT_ATTR_SH(v5_high, iio_event_ad7291,
- ad7291_show_voltage_high, ad7291_set_voltage_high, 0);
-IIO_EVENT_ATTR_SH(v5_low, iio_event_ad7291,
- ad7291_show_voltage_low, ad7291_set_voltage_low, 0);
-IIO_EVENT_ATTR_SH(v5_hyst, iio_event_ad7291,
- ad7291_show_voltage_hyst, ad7291_set_voltage_hyst, 0);
-IIO_EVENT_ATTR_SH(v6_high, iio_event_ad7291,
- ad7291_show_voltage_high, ad7291_set_voltage_high, 0);
-IIO_EVENT_ATTR_SH(v6_low, iio_event_ad7291,
- ad7291_show_voltage_low, ad7291_set_voltage_low, 0);
-IIO_EVENT_ATTR_SH(v6_hyst, iio_event_ad7291,
- ad7291_show_voltage_hyst, ad7291_set_voltage_hyst, 0);
-IIO_EVENT_ATTR_SH(v7_high, iio_event_ad7291,
- ad7291_show_voltage_high, ad7291_set_voltage_high, 0);
-IIO_EVENT_ATTR_SH(v7_low, iio_event_ad7291,
- ad7291_show_voltage_low, ad7291_set_voltage_low, 0);
-IIO_EVENT_ATTR_SH(v7_hyst, iio_event_ad7291,
- ad7291_show_voltage_hyst, ad7291_set_voltage_hyst, 0);
+static IIO_DEVICE_ATTR(t_sense_high_value,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound,
+ AD7291_T_SENSE_HIGH);
+static IIO_DEVICE_ATTR(t_sense_low_value,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound,
+ AD7291_T_SENSE_LOW);
+static IIO_DEVICE_ATTR(t_sense_hyst_value,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound,
+ AD7291_T_SENSE_HYST);
+static IIO_DEVICE_ATTR(v0_high,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x04);
+static IIO_DEVICE_ATTR(v0_low,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x05);
+static IIO_DEVICE_ATTR(v0_hyst,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x06);
+static IIO_DEVICE_ATTR(v1_high,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x07);
+static IIO_DEVICE_ATTR(v1_low,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x08);
+static IIO_DEVICE_ATTR(v1_hyst,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x09);
+static IIO_DEVICE_ATTR(v2_high,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x0A);
+static IIO_DEVICE_ATTR(v2_low,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x0B);
+static IIO_DEVICE_ATTR(v2_hyst,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x0C);
+static IIO_DEVICE_ATTR(v3_high,
+ S_IRUGO | S_IWUSR,
+ /* Datasheet suggests this one and this one only
+ has the registers in different order */
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x0E);
+static IIO_DEVICE_ATTR(v3_low,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x0D);
+static IIO_DEVICE_ATTR(v3_hyst,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x0F);
+static IIO_DEVICE_ATTR(v4_high,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x10);
+static IIO_DEVICE_ATTR(v4_low,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x11);
+static IIO_DEVICE_ATTR(v4_hyst,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x12);
+static IIO_DEVICE_ATTR(v5_high,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x13);
+static IIO_DEVICE_ATTR(v5_low,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x14);
+static IIO_DEVICE_ATTR(v5_hyst,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x15);
+static IIO_DEVICE_ATTR(v6_high,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x16);
+static IIO_DEVICE_ATTR(v6_low,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x17);
+static IIO_DEVICE_ATTR(v6_hyst,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x18);
+static IIO_DEVICE_ATTR(v7_high,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x19);
+static IIO_DEVICE_ATTR(v7_low,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x1A);
+static IIO_DEVICE_ATTR(v7_hyst,
+ S_IRUGO | S_IWUSR,
+ ad7291_show_t_bound, ad7291_set_t_bound, 0x1B);
static struct attribute *ad7291_event_attributes[] = {
- &iio_event_attr_t_sense_high.dev_attr.attr,
- &iio_event_attr_t_sense_low.dev_attr.attr,
- &iio_event_attr_t_sense_hyst.dev_attr.attr,
- &iio_event_attr_v0_high.dev_attr.attr,
- &iio_event_attr_v0_low.dev_attr.attr,
- &iio_event_attr_v0_hyst.dev_attr.attr,
- &iio_event_attr_v1_high.dev_attr.attr,
- &iio_event_attr_v1_low.dev_attr.attr,
- &iio_event_attr_v1_hyst.dev_attr.attr,
- &iio_event_attr_v2_high.dev_attr.attr,
- &iio_event_attr_v2_low.dev_attr.attr,
- &iio_event_attr_v2_hyst.dev_attr.attr,
- &iio_event_attr_v3_high.dev_attr.attr,
- &iio_event_attr_v3_low.dev_attr.attr,
- &iio_event_attr_v3_hyst.dev_attr.attr,
- &iio_event_attr_v4_high.dev_attr.attr,
- &iio_event_attr_v4_low.dev_attr.attr,
- &iio_event_attr_v4_hyst.dev_attr.attr,
- &iio_event_attr_v5_high.dev_attr.attr,
- &iio_event_attr_v5_low.dev_attr.attr,
- &iio_event_attr_v5_hyst.dev_attr.attr,
- &iio_event_attr_v6_high.dev_attr.attr,
- &iio_event_attr_v6_low.dev_attr.attr,
- &iio_event_attr_v6_hyst.dev_attr.attr,
- &iio_event_attr_v7_high.dev_attr.attr,
- &iio_event_attr_v7_low.dev_attr.attr,
- &iio_event_attr_v7_hyst.dev_attr.attr,
+ &iio_dev_attr_t_sense_high_value.dev_attr.attr,
+ &iio_dev_attr_t_sense_low_value.dev_attr.attr,
+ &iio_dev_attr_t_sense_hyst_value.dev_attr.attr,
+ &iio_dev_attr_v0_high.dev_attr.attr,
+ &iio_dev_attr_v0_low.dev_attr.attr,
+ &iio_dev_attr_v0_hyst.dev_attr.attr,
+ &iio_dev_attr_v1_high.dev_attr.attr,
+ &iio_dev_attr_v1_low.dev_attr.attr,
+ &iio_dev_attr_v1_hyst.dev_attr.attr,
+ &iio_dev_attr_v2_high.dev_attr.attr,
+ &iio_dev_attr_v2_low.dev_attr.attr,
+ &iio_dev_attr_v2_hyst.dev_attr.attr,
+ &iio_dev_attr_v3_high.dev_attr.attr,
+ &iio_dev_attr_v3_low.dev_attr.attr,
+ &iio_dev_attr_v3_hyst.dev_attr.attr,
+ &iio_dev_attr_v4_high.dev_attr.attr,
+ &iio_dev_attr_v4_low.dev_attr.attr,
+ &iio_dev_attr_v4_hyst.dev_attr.attr,
+ &iio_dev_attr_v5_high.dev_attr.attr,
+ &iio_dev_attr_v5_low.dev_attr.attr,
+ &iio_dev_attr_v5_hyst.dev_attr.attr,
+ &iio_dev_attr_v6_high.dev_attr.attr,
+ &iio_dev_attr_v6_low.dev_attr.attr,
+ &iio_dev_attr_v6_hyst.dev_attr.attr,
+ &iio_dev_attr_v7_high.dev_attr.attr,
+ &iio_dev_attr_v7_low.dev_attr.attr,
+ &iio_dev_attr_v7_hyst.dev_attr.attr,
NULL,
};
@@ -904,6 +778,12 @@ static struct attribute_group ad7291_event_attribute_group = {
.attrs = ad7291_event_attributes,
};
+static const struct iio_info ad7291_info = {
+ .attrs = &ad7291_attribute_group,
+ .num_interrupt_lines = 1,
+ .event_attrs = &ad7291_event_attribute_group,
+};
+
/*
* device probe and remove
*/
@@ -923,21 +803,18 @@ static int __devinit ad7291_probe(struct i2c_client *client,
i2c_set_clientdata(client, chip);
chip->client = client;
- chip->name = id->name;
chip->command = AD7291_NOISE_DELAY | AD7291_T_SENSE_MASK;
- chip->indio_dev = iio_allocate_device();
+ chip->indio_dev = iio_allocate_device(0);
if (chip->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_chip;
}
+ chip->indio_dev->name = id->name;
chip->indio_dev->dev.parent = &client->dev;
- chip->indio_dev->attrs = &ad7291_attribute_group;
- chip->indio_dev->event_attrs = &ad7291_event_attribute_group;
+ chip->indio_dev->info = &ad7291_info;
chip->indio_dev->dev_data = (void *)chip;
- chip->indio_dev->driver_module = THIS_MODULE;
- chip->indio_dev->num_interrupt_lines = 1;
chip->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(chip->indio_dev);
@@ -945,24 +822,15 @@ static int __devinit ad7291_probe(struct i2c_client *client,
goto error_free_dev;
if (client->irq > 0) {
- ret = iio_register_interrupt_line(client->irq,
- chip->indio_dev,
- 0,
- IRQF_TRIGGER_LOW,
- chip->name);
+ ret = request_threaded_irq(client->irq,
+ NULL,
+ &ad7291_event_handler,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ id->name,
+ chip->indio_dev);
if (ret)
goto error_unreg_dev;
- /*
- * The event handler list element refer to iio_event_ad7291.
- * All event attributes bind to the same event handler.
- * So, only register event handler once.
- */
- iio_add_event_to_list(&iio_event_ad7291,
- &chip->indio_dev->interrupts[0]->ev_list);
-
- INIT_WORK(&chip->thresh_work, ad7291_interrupt_bh);
-
/* set irq polarity low level */
chip->command |= AD7291_ALART_POLARITY;
}
@@ -979,7 +847,7 @@ static int __devinit ad7291_probe(struct i2c_client *client,
return 0;
error_unreg_irq:
- iio_unregister_interrupt_line(chip->indio_dev, 0);
+ free_irq(client->irq, chip->indio_dev);
error_unreg_dev:
iio_device_unregister(chip->indio_dev);
error_free_dev:
@@ -996,7 +864,7 @@ static int __devexit ad7291_remove(struct i2c_client *client)
struct iio_dev *indio_dev = chip->indio_dev;
if (client->irq)
- iio_unregister_interrupt_line(indio_dev, 0);
+ free_irq(client->irq, chip->indio_dev);
iio_device_unregister(indio_dev);
iio_free_device(chip->indio_dev);
kfree(chip);
diff --git a/drivers/staging/iio/adc/ad7298.h b/drivers/staging/iio/adc/ad7298.h
index fe7ed77d638f..628f5adcf0c9 100644
--- a/drivers/staging/iio/adc/ad7298.h
+++ b/drivers/staging/iio/adc/ad7298.h
@@ -17,14 +17,13 @@
#define AD7298_TAVG (1 << 1) /* temperature sensor averaging enable */
#define AD7298_PDD (1 << 0) /* partial power down enable */
-#define AD7298_CH_MASK (AD7298_CH0 | AD7298_CH1 | AD7298_CH2 | AD7298_CH3 | \
- AD7298_CH4 | AD7298_CH5 | AD7298_CH6 | AD7298_CH7)
-
#define AD7298_MAX_CHAN 8
#define AD7298_BITS 12
#define AD7298_STORAGE_BITS 16
#define AD7298_INTREF_mV 2500
+#define AD7298_CH_TEMP 9
+
#define RES_MASK(bits) ((1 << (bits)) - 1)
/*
@@ -37,11 +36,8 @@ struct ad7298_platform_data {
};
struct ad7298_state {
- struct iio_dev *indio_dev;
struct spi_device *spi;
struct regulator *reg;
- struct work_struct poll_work;
- atomic_t protect_ring;
size_t d_size;
u16 int_vref_mv;
unsigned ext_ref;
@@ -58,11 +54,11 @@ struct ad7298_state {
};
#ifdef CONFIG_IIO_RING_BUFFER
-int ad7298_scan_from_ring(struct ad7298_state *st, long ch);
+int ad7298_scan_from_ring(struct iio_dev *indio_dev, long ch);
int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev);
void ad7298_ring_cleanup(struct iio_dev *indio_dev);
#else /* CONFIG_IIO_RING_BUFFER */
-static inline int ad7298_scan_from_ring(struct ad7298_state *st, long ch)
+static inline int ad7298_scan_from_ring(struct iio_dev *indio_dev, long ch)
{
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/staging/iio/adc/ad7298_core.c
index 2e9154e7d887..b8e4ae29b0b5 100644
--- a/drivers/staging/iio/adc/ad7298_core.c
+++ b/drivers/staging/iio/adc/ad7298_core.c
@@ -6,7 +6,6 @@
* Licensed under the GPL-2.
*/
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -23,6 +22,37 @@
#include "ad7298.h"
+static struct iio_chan_spec ad7298_channels[] = {
+ IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ 9, AD7298_CH_TEMP, IIO_ST('s', 32, 32, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 1, 1, IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 2, 2, IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 3, 3, IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 4, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 4, 4, IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 5, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 5, 5, IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 6, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 6, 6, IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 7, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 7, 7, IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+};
+
static int ad7298_scan_direct(struct ad7298_state *st, unsigned ch)
{
int ret;
@@ -36,55 +66,28 @@ static int ad7298_scan_direct(struct ad7298_state *st, unsigned ch)
return be16_to_cpu(st->rx_buf[0]);
}
-static ssize_t ad7298_scan(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int ad7298_scan_temp(struct ad7298_state *st, int *val)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7298_state *st = dev_info->dev_data;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int ret;
+ int tmp, ret;
- mutex_lock(&dev_info->mlock);
- if (iio_ring_enabled(dev_info))
- ret = ad7298_scan_from_ring(st, this_attr->address);
- else
- ret = ad7298_scan_direct(st, this_attr->address);
- mutex_unlock(&dev_info->mlock);
+ tmp = cpu_to_be16(AD7298_WRITE | AD7298_TSENSE |
+ AD7298_TAVG | st->ext_ref);
- if (ret < 0)
+ ret = spi_write(st->spi, (u8 *)&tmp, 2);
+ if (ret)
return ret;
- return sprintf(buf, "%d\n", ret & RES_MASK(AD7298_BITS));
-}
-
-static IIO_DEV_ATTR_IN_RAW(0, ad7298_scan, 0);
-static IIO_DEV_ATTR_IN_RAW(1, ad7298_scan, 1);
-static IIO_DEV_ATTR_IN_RAW(2, ad7298_scan, 2);
-static IIO_DEV_ATTR_IN_RAW(3, ad7298_scan, 3);
-static IIO_DEV_ATTR_IN_RAW(4, ad7298_scan, 4);
-static IIO_DEV_ATTR_IN_RAW(5, ad7298_scan, 5);
-static IIO_DEV_ATTR_IN_RAW(6, ad7298_scan, 6);
-static IIO_DEV_ATTR_IN_RAW(7, ad7298_scan, 7);
-
-static ssize_t ad7298_show_temp(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7298_state *st = iio_dev_get_devdata(dev_info);
- int tmp;
+ tmp = 0;
- tmp = cpu_to_be16(AD7298_WRITE | AD7298_TSENSE |
- AD7298_TAVG | st->ext_ref);
+ ret = spi_write(st->spi, (u8 *)&tmp, 2);
+ if (ret)
+ return ret;
- mutex_lock(&dev_info->mlock);
- spi_write(st->spi, (u8 *)&tmp, 2);
- tmp = 0;
- spi_write(st->spi, (u8 *)&tmp, 2);
usleep_range(101, 1000); /* sleep > 100us */
- spi_read(st->spi, (u8 *)&tmp, 2);
- mutex_unlock(&dev_info->mlock);
+
+ ret = spi_read(st->spi, (u8 *)&tmp, 2);
+ if (ret)
+ return ret;
tmp = be16_to_cpu(tmp) & RES_MASK(AD7298_BITS);
@@ -101,65 +104,74 @@ static ssize_t ad7298_show_temp(struct device *dev,
tmp *= 250; /* temperature in milli degrees Celsius */
}
- return sprintf(buf, "%d\n", tmp);
-}
+ *val = tmp;
-static IIO_DEVICE_ATTR(temp0_input, S_IRUGO, ad7298_show_temp, NULL, 0);
-
-static ssize_t ad7298_show_scale(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7298_state *st = iio_dev_get_devdata(dev_info);
- /* Corresponds to Vref / 2^(bits) */
- unsigned int scale_uv = (st->int_vref_mv * 1000) >> AD7298_BITS;
-
- return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
+ return 0;
}
-static IIO_DEVICE_ATTR(in_scale, S_IRUGO, ad7298_show_scale, NULL, 0);
-static ssize_t ad7298_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int ad7298_read_raw(struct iio_dev *dev_info,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7298_state *st = iio_dev_get_devdata(dev_info);
-
- return sprintf(buf, "%s\n", spi_get_device_id(st->spi)->name);
+ int ret;
+ struct ad7298_state *st = iio_priv(dev_info);
+ unsigned int scale_uv;
+
+ switch (m) {
+ case 0:
+ mutex_lock(&dev_info->mlock);
+ if (iio_ring_enabled(dev_info)) {
+ if (chan->address == AD7298_CH_TEMP)
+ ret = -ENODEV;
+ else
+ ret = ad7298_scan_from_ring(dev_info,
+ chan->address);
+ } else {
+ if (chan->address == AD7298_CH_TEMP)
+ ret = ad7298_scan_temp(st, val);
+ else
+ ret = ad7298_scan_direct(st, chan->address);
+ }
+ mutex_unlock(&dev_info->mlock);
+
+ if (ret < 0)
+ return ret;
+
+ if (chan->address != AD7298_CH_TEMP)
+ *val = ret & RES_MASK(AD7298_BITS);
+
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ scale_uv = (st->int_vref_mv * 1000) >> AD7298_BITS;
+ *val = scale_uv / 1000;
+ *val2 = (scale_uv % 1000) * 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ *val = 1;
+ *val2 = 0;
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+ return -EINVAL;
}
-static IIO_DEVICE_ATTR(name, S_IRUGO, ad7298_show_name, NULL, 0);
-
-static struct attribute *ad7298_attributes[] = {
- &iio_dev_attr_in0_raw.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_dev_attr_in2_raw.dev_attr.attr,
- &iio_dev_attr_in3_raw.dev_attr.attr,
- &iio_dev_attr_in4_raw.dev_attr.attr,
- &iio_dev_attr_in5_raw.dev_attr.attr,
- &iio_dev_attr_in6_raw.dev_attr.attr,
- &iio_dev_attr_in7_raw.dev_attr.attr,
- &iio_dev_attr_in_scale.dev_attr.attr,
- &iio_dev_attr_temp0_input.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
- NULL,
-};
-static const struct attribute_group ad7298_attribute_group = {
- .attrs = ad7298_attributes,
+static const struct iio_info ad7298_info = {
+ .read_raw = &ad7298_read_raw,
+ .driver_module = THIS_MODULE,
};
static int __devinit ad7298_probe(struct spi_device *spi)
{
struct ad7298_platform_data *pdata = spi->dev.platform_data;
struct ad7298_state *st;
- int ret;
+ int ret, regdone = 0;
+ struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
- st = kzalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
st->reg = regulator_get(&spi->dev, "vcc");
if (!IS_ERR(st->reg)) {
@@ -168,22 +180,16 @@ static int __devinit ad7298_probe(struct spi_device *spi)
goto error_put_reg;
}
- spi_set_drvdata(spi, st);
+ spi_set_drvdata(spi, indio_dev);
- atomic_set(&st->protect_ring, 0);
st->spi = spi;
- st->indio_dev = iio_allocate_device();
- if (st->indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_disable_reg;
- }
-
- st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->attrs = &ad7298_attribute_group;
- st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
- st->indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = ad7298_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ad7298_channels);
+ indio_dev->info = &ad7298_info;
/* Setup default message */
@@ -208,39 +214,44 @@ static int __devinit ad7298_probe(struct spi_device *spi)
st->int_vref_mv = AD7298_INTREF_mV;
}
- ret = ad7298_register_ring_funcs_and_init(st->indio_dev);
+ ret = ad7298_register_ring_funcs_and_init(indio_dev);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
- ret = iio_device_register(st->indio_dev);
+ ret = iio_device_register(indio_dev);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
+ regdone = 1;
- ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
+ ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
+ &ad7298_channels[1], /* skip temp0 */
+ ARRAY_SIZE(ad7298_channels) - 1);
if (ret)
goto error_cleanup_ring;
+
return 0;
error_cleanup_ring:
- ad7298_ring_cleanup(st->indio_dev);
- iio_device_unregister(st->indio_dev);
-error_free_device:
- iio_free_device(st->indio_dev);
+ ad7298_ring_cleanup(indio_dev);
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
error_put_reg:
if (!IS_ERR(st->reg))
regulator_put(st->reg);
- kfree(st);
-error_ret:
+
+ if (regdone)
+ iio_device_unregister(indio_dev);
+ else
+ iio_free_device(indio_dev);
+
return ret;
}
static int __devexit ad7298_remove(struct spi_device *spi)
{
- struct ad7298_state *st = spi_get_drvdata(spi);
- struct iio_dev *indio_dev = st->indio_dev;
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct ad7298_state *st = iio_priv(indio_dev);
iio_ring_buffer_unregister(indio_dev->ring);
ad7298_ring_cleanup(indio_dev);
@@ -249,7 +260,8 @@ static int __devexit ad7298_remove(struct spi_device *spi)
regulator_disable(st->reg);
regulator_put(st->reg);
}
- kfree(st);
+ iio_device_unregister(indio_dev);
+
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c
index 9068d7f54d15..a04c03352624 100644
--- a/drivers/staging/iio/adc/ad7298_ring.c
+++ b/drivers/staging/iio/adc/ad7298_ring.c
@@ -7,7 +7,6 @@
*/
#include <linux/interrupt.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -22,52 +21,9 @@
#include "ad7298.h"
-static IIO_SCAN_EL_C(in0, 0, 0, NULL);
-static IIO_SCAN_EL_C(in1, 1, 0, NULL);
-static IIO_SCAN_EL_C(in2, 2, 0, NULL);
-static IIO_SCAN_EL_C(in3, 3, 0, NULL);
-static IIO_SCAN_EL_C(in4, 4, 0, NULL);
-static IIO_SCAN_EL_C(in5, 5, 0, NULL);
-static IIO_SCAN_EL_C(in6, 6, 0, NULL);
-static IIO_SCAN_EL_C(in7, 7, 0, NULL);
-
-static IIO_SCAN_EL_TIMESTAMP(8);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
-
-static IIO_CONST_ATTR(in_type, "u12/16") ;
-
-static struct attribute *ad7298_scan_el_attrs[] = {
- &iio_scan_el_in0.dev_attr.attr,
- &iio_const_attr_in0_index.dev_attr.attr,
- &iio_scan_el_in1.dev_attr.attr,
- &iio_const_attr_in1_index.dev_attr.attr,
- &iio_scan_el_in2.dev_attr.attr,
- &iio_const_attr_in2_index.dev_attr.attr,
- &iio_scan_el_in3.dev_attr.attr,
- &iio_const_attr_in3_index.dev_attr.attr,
- &iio_scan_el_in4.dev_attr.attr,
- &iio_const_attr_in4_index.dev_attr.attr,
- &iio_scan_el_in5.dev_attr.attr,
- &iio_const_attr_in5_index.dev_attr.attr,
- &iio_scan_el_in6.dev_attr.attr,
- &iio_const_attr_in6_index.dev_attr.attr,
- &iio_scan_el_in7.dev_attr.attr,
- &iio_const_attr_in7_index.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- &iio_const_attr_in_type.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group ad7298_scan_el_group = {
- .name = "scan_elements",
- .attrs = ad7298_scan_el_attrs,
-};
-
-int ad7298_scan_from_ring(struct ad7298_state *st, long ch)
+int ad7298_scan_from_ring(struct iio_dev *dev_info, long ch)
{
- struct iio_ring_buffer *ring = st->indio_dev->ring;
+ struct iio_ring_buffer *ring = dev_info->ring;
int ret;
u16 *ring_data;
@@ -76,12 +32,13 @@ int ad7298_scan_from_ring(struct ad7298_state *st, long ch)
goto error_ret;
}
- ring_data = kmalloc(ring->access.get_bytes_per_datum(ring), GFP_KERNEL);
+ ring_data = kmalloc(ring->access->get_bytes_per_datum(ring),
+ GFP_KERNEL);
if (ring_data == NULL) {
ret = -ENOMEM;
goto error_ret;
}
- ret = ring->access.read_last(ring, (u8 *) ring_data);
+ ret = ring->access->read_last(ring, (u8 *) ring_data);
if (ret)
goto error_free_ring_data;
@@ -102,7 +59,7 @@ error_ret:
**/
static int ad7298_ring_preenable(struct iio_dev *indio_dev)
{
- struct ad7298_state *st = indio_dev->dev_data;
+ struct ad7298_state *st = iio_priv(indio_dev);
struct iio_ring_buffer *ring = indio_dev->ring;
size_t d_size;
int i, m;
@@ -117,8 +74,8 @@ static int ad7298_ring_preenable(struct iio_dev *indio_dev)
d_size += sizeof(s64) - (d_size % sizeof(s64));
}
- if (ring->access.set_bytes_per_datum)
- ring->access.set_bytes_per_datum(ring, d_size);
+ if (ring->access->set_bytes_per_datum)
+ ring->access->set_bytes_per_datum(ring, d_size);
st->d_size = d_size;
@@ -155,47 +112,24 @@ static int ad7298_ring_preenable(struct iio_dev *indio_dev)
}
/**
- * ad7298_poll_func_th() th of trigger launched polling to ring buffer
- *
- * As sampling only occurs on spi comms occurring, leave timestamping until
- * then. Some triggers will generate their own time stamp. Currently
- * there is no way of notifying them when no one cares.
- **/
-static void ad7298_poll_func_th(struct iio_dev *indio_dev, s64 time)
-{
- struct ad7298_state *st = indio_dev->dev_data;
-
- schedule_work(&st->poll_work);
- return;
-}
-
-/**
- * ad7298_poll_bh_to_ring() bh of trigger launched polling to ring buffer
- * @work_s: the work struct through which this was scheduled
+ * ad7298_trigger_handler() bh of trigger launched polling to ring buffer
*
* Currently there is no option in this driver to disable the saving of
* timestamps within the ring.
- * I think the one copy of this at a time was to avoid problems if the
- * trigger was set far too high and the reads then locked up the computer.
**/
-static void ad7298_poll_bh_to_ring(struct work_struct *work_s)
+static irqreturn_t ad7298_trigger_handler(int irq, void *p)
{
- struct ad7298_state *st = container_of(work_s, struct ad7298_state,
- poll_work);
- struct iio_dev *indio_dev = st->indio_dev;
- struct iio_sw_ring_buffer *sw_ring = iio_to_sw_ring(indio_dev->ring);
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->private_data;
+ struct ad7298_state *st = iio_priv(indio_dev);
struct iio_ring_buffer *ring = indio_dev->ring;
s64 time_ns;
__u16 buf[16];
int b_sent, i;
- /* Ensure only one copy of this function running at a time */
- if (atomic_inc_return(&st->protect_ring) > 1)
- return;
-
b_sent = spi_sync(st->spi, &st->ring_msg);
if (b_sent)
- goto done;
+ return b_sent;
if (ring->scan_timestamp) {
time_ns = iio_get_time_ns();
@@ -206,14 +140,20 @@ static void ad7298_poll_bh_to_ring(struct work_struct *work_s)
for (i = 0; i < ring->scan_count; i++)
buf[i] = be16_to_cpu(st->rx_buf[i]);
- indio_dev->ring->access.store_to(&sw_ring->buf, (u8 *)buf, time_ns);
-done:
- atomic_dec(&st->protect_ring);
+ indio_dev->ring->access->store_to(ring, (u8 *)buf, time_ns);
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
}
+static const struct iio_ring_setup_ops ad7298_ring_setup_ops = {
+ .preenable = &ad7298_ring_preenable,
+ .postenable = &iio_triggered_ring_postenable,
+ .predisable = &iio_triggered_ring_predisable,
+};
+
int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev)
{
- struct ad7298_state *st = indio_dev->dev_data;
int ret;
indio_dev->ring = iio_sw_rb_allocate(indio_dev);
@@ -222,24 +162,28 @@ int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev)
goto error_ret;
}
/* Effectively select the ring buffer implementation */
- iio_ring_sw_register_funcs(&indio_dev->ring->access);
- ret = iio_alloc_pollfunc(indio_dev, NULL, &ad7298_poll_func_th);
- if (ret)
+ indio_dev->ring->access = &ring_sw_access_funcs;
+
+ indio_dev->pollfunc = iio_alloc_pollfunc(NULL,
+ &ad7298_trigger_handler,
+ IRQF_ONESHOT,
+ indio_dev,
+ "ad7298_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->preenable = &ad7298_ring_preenable;
- indio_dev->ring->postenable = &iio_triggered_ring_postenable;
- indio_dev->ring->predisable = &iio_triggered_ring_predisable;
- indio_dev->ring->scan_el_attrs = &ad7298_scan_el_group;
+ indio_dev->ring->setup_ops = &ad7298_ring_setup_ops;
indio_dev->ring->scan_timestamp = true;
- INIT_WORK(&st->poll_work, &ad7298_poll_bh_to_ring);
-
/* 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:
@@ -253,6 +197,6 @@ void ad7298_ring_cleanup(struct iio_dev *indio_dev)
iio_trigger_dettach_poll_func(indio_dev->trig,
indio_dev->pollfunc);
}
- kfree(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 8c17b1fe9026..98bb16fcff26 100644
--- a/drivers/staging/iio/adc/ad7314.c
+++ b/drivers/staging/iio/adc/ad7314.c
@@ -6,16 +6,11 @@
* Licensed under the GPL-2 or later.
*/
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
-#include <linux/list.h>
#include <linux/spi/spi.h>
-#include <linux/rtc.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -47,7 +42,6 @@
*/
struct ad7314_chip_info {
- const char *name;
struct spi_device *spi_dev;
struct iio_dev *indio_dev;
s64 last_timestamp;
@@ -160,7 +154,7 @@ static ssize_t ad7314_show_temperature(struct device *dev,
if (chip->mode)
ad7314_spi_write(chip, chip->mode);
- if (strcmp(chip->name, "ad7314")) {
+ if (strcmp(dev_info->name, "ad7314")) {
data = (data & AD7314_TEMP_MASK) >>
AD7314_TEMP_OFFSET;
if (data & AD7314_TEMP_SIGN) {
@@ -186,22 +180,10 @@ static ssize_t ad7314_show_temperature(struct device *dev,
static IIO_DEVICE_ATTR(temperature, S_IRUGO, ad7314_show_temperature, NULL, 0);
-static ssize_t ad7314_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7314_chip_info *chip = dev_info->dev_data;
- return sprintf(buf, "%s\n", chip->name);
-}
-
-static IIO_DEVICE_ATTR(name, S_IRUGO, ad7314_show_name, NULL, 0);
-
static struct attribute *ad7314_attributes[] = {
&iio_dev_attr_available_modes.dev_attr.attr,
&iio_dev_attr_mode.dev_attr.attr,
&iio_dev_attr_temperature.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
NULL,
};
@@ -209,6 +191,10 @@ static const struct attribute_group ad7314_attribute_group = {
.attrs = ad7314_attributes,
};
+static const struct iio_info ad7314_info = {
+ .attrs = &ad7314_attribute_group,
+ .driver_module = THIS_MODULE,
+};
/*
* device probe and remove
*/
@@ -227,25 +213,24 @@ static int __devinit ad7314_probe(struct spi_device *spi_dev)
dev_set_drvdata(&spi_dev->dev, chip);
chip->spi_dev = spi_dev;
- chip->name = spi_dev->modalias;
- chip->indio_dev = iio_allocate_device();
+ chip->indio_dev = iio_allocate_device(0);
if (chip->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_chip;
}
+ chip->indio_dev->name = spi_get_device_id(spi_dev)->name;
chip->indio_dev->dev.parent = &spi_dev->dev;
- chip->indio_dev->attrs = &ad7314_attribute_group;
+ chip->indio_dev->info = &ad7314_info;
chip->indio_dev->dev_data = (void *)chip;
- chip->indio_dev->driver_module = THIS_MODULE;
ret = iio_device_register(chip->indio_dev);
if (ret)
goto error_free_dev;
dev_info(&spi_dev->dev, "%s temperature sensor registered.\n",
- chip->name);
+ chip->indio_dev->name);
return 0;
error_free_dev:
@@ -262,8 +247,6 @@ static int __devexit ad7314_remove(struct spi_device *spi_dev)
struct iio_dev *indio_dev = chip->indio_dev;
dev_set_drvdata(&spi_dev->dev, NULL);
- if (spi_dev->irq)
- iio_unregister_interrupt_line(indio_dev, 0);
iio_device_unregister(indio_dev);
iio_free_device(chip->indio_dev);
kfree(chip);
diff --git a/drivers/staging/iio/adc/ad7476.h b/drivers/staging/iio/adc/ad7476.h
index f917e9c3d54f..01a70211f4ff 100644
--- a/drivers/staging/iio/adc/ad7476.h
+++ b/drivers/staging/iio/adc/ad7476.h
@@ -19,11 +19,8 @@ struct ad7476_platform_data {
};
struct ad7476_chip_info {
- u8 bits;
- u8 storagebits;
- u8 res_shift;
- char sign;
u16 int_vref_mv;
+ struct iio_chan_spec channel[2];
};
struct ad7476_state {
@@ -31,8 +28,6 @@ struct ad7476_state {
struct spi_device *spi;
const struct ad7476_chip_info *chip_info;
struct regulator *reg;
- struct work_struct poll_work;
- atomic_t protect_ring;
size_t d_size;
u16 int_vref_mv;
struct spi_transfer xfer;
diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c
index d263904b3d1d..50cedb422839 100644
--- a/drivers/staging/iio/adc/ad7476_core.c
+++ b/drivers/staging/iio/adc/ad7476_core.c
@@ -6,13 +6,10 @@
* Licensed under the GPL-2 or later.
*/
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
-#include <linux/list.h>
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
@@ -35,117 +32,97 @@ static int ad7476_scan_direct(struct ad7476_state *st)
return (st->data[0] << 8) | st->data[1];
}
-static ssize_t ad7476_scan(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int ad7476_read_raw(struct iio_dev *dev_info,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7476_state *st = dev_info->dev_data;
int ret;
-
- mutex_lock(&dev_info->mlock);
- if (iio_ring_enabled(dev_info))
- ret = ad7476_scan_from_ring(st);
- else
- ret = ad7476_scan_direct(st);
- mutex_unlock(&dev_info->mlock);
-
- if (ret < 0)
- return ret;
-
- return sprintf(buf, "%d\n", (ret >> st->chip_info->res_shift) &
- RES_MASK(st->chip_info->bits));
-}
-static IIO_DEV_ATTR_IN_RAW(0, ad7476_scan, 0);
-
-static ssize_t ad7476_show_scale(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- /* Driver currently only support internal vref */
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7476_state *st = iio_dev_get_devdata(dev_info);
- /* Corresponds to Vref / 2^(bits) */
- unsigned int scale_uv = (st->int_vref_mv * 1000) >> st->chip_info->bits;
-
- return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
-}
-static IIO_DEVICE_ATTR(in_scale, S_IRUGO, ad7476_show_scale, NULL, 0);
-
-static ssize_t ad7476_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7476_state *st = iio_dev_get_devdata(dev_info);
-
- return sprintf(buf, "%s\n", spi_get_device_id(st->spi)->name);
+ struct ad7476_state *st = dev_info->dev_data;
+ unsigned int scale_uv;
+
+ switch (m) {
+ case 0:
+ mutex_lock(&dev_info->mlock);
+ if (iio_ring_enabled(dev_info))
+ ret = ad7476_scan_from_ring(st);
+ else
+ ret = ad7476_scan_direct(st);
+ mutex_unlock(&dev_info->mlock);
+
+ if (ret < 0)
+ return ret;
+ *val = (ret >> st->chip_info->channel[0].scan_type.shift) &
+ RES_MASK(st->chip_info->channel[0].scan_type.realbits);
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ scale_uv = (st->int_vref_mv * 1000)
+ >> st->chip_info->channel[0].scan_type.realbits;
+ *val = scale_uv/1000;
+ *val2 = (scale_uv%1000)*1000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+ return -EINVAL;
}
-static IIO_DEVICE_ATTR(name, S_IRUGO, ad7476_show_name, NULL, 0);
-
-static struct attribute *ad7476_attributes[] = {
- &iio_dev_attr_in0_raw.dev_attr.attr,
- &iio_dev_attr_in_scale.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
- NULL,
-};
-
-static const struct attribute_group ad7476_attribute_group = {
- .attrs = ad7476_attributes,
-};
static const struct ad7476_chip_info ad7476_chip_info_tbl[] = {
[ID_AD7466] = {
- .bits = 12,
- .storagebits = 16,
- .res_shift = 0,
- .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 12, 16, 0), 0),
+ .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7467] = {
- .bits = 10,
- .storagebits = 16,
- .res_shift = 2,
- .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 10, 16, 2), 0),
+ .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7468] = {
- .bits = 8,
- .storagebits = 16,
- .res_shift = 4,
- .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .channel[0] = IIO_CHAN(IIO_IN, 0, 1 , 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 8, 16, 4), 0),
+ .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7475] = {
- .bits = 12,
- .storagebits = 16,
- .res_shift = 0,
- .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 12, 16, 0), 0),
+ .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7476] = {
- .bits = 12,
- .storagebits = 16,
- .res_shift = 0,
- .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 12, 16, 0), 0),
+ .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7477] = {
- .bits = 10,
- .storagebits = 16,
- .res_shift = 2,
- .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 10, 16, 2), 0),
+ .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7478] = {
- .bits = 8,
- .storagebits = 16,
- .res_shift = 4,
- .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 8, 16, 4), 0),
+ .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7495] = {
- .bits = 12,
- .storagebits = 16,
- .res_shift = 0,
+ .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 12, 16, 0), 0),
+ .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
.int_vref_mv = 2500,
- .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
},
};
+static const struct iio_info ad7476_info = {
+ .driver_module = THIS_MODULE,
+ .read_raw = &ad7476_read_raw,
+};
+
static int __devinit ad7476_probe(struct spi_device *spi)
{
struct ad7476_platform_data *pdata = spi->dev.platform_data;
@@ -181,10 +158,9 @@ static int __devinit ad7476_probe(struct spi_device *spi)
spi_set_drvdata(spi, st);
- atomic_set(&st->protect_ring, 0);
st->spi = spi;
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_disable_reg;
@@ -192,15 +168,16 @@ static int __devinit ad7476_probe(struct spi_device *spi)
/* Establish that the iio_dev is a child of the spi device */
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->attrs = &ad7476_attribute_group;
+ st->indio_dev->name = spi_get_device_id(spi)->name;
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
-
+ st->indio_dev->channels = st->chip_info->channel;
+ st->indio_dev->num_channels = 2;
+ st->indio_dev->info = &ad7476_info;
/* Setup default message */
st->xfer.rx_buf = &st->data;
- st->xfer.len = st->chip_info->storagebits / 8;
+ st->xfer.len = st->chip_info->channel[0].scan_type.storagebits / 8;
spi_message_init(&st->msg);
spi_message_add_tail(&st->xfer, &st->msg);
@@ -213,7 +190,9 @@ static int __devinit ad7476_probe(struct spi_device *spi)
if (ret)
goto error_free_device;
- ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
+ ret = iio_ring_buffer_register_ex(st->indio_dev->ring, 0,
+ st->chip_info->channel,
+ ARRAY_SIZE(st->chip_info->channel));
if (ret)
goto error_cleanup_ring;
return 0;
diff --git a/drivers/staging/iio/adc/ad7476_ring.c b/drivers/staging/iio/adc/ad7476_ring.c
index 92d93787d5b8..b1b2ee2c56b0 100644
--- a/drivers/staging/iio/adc/ad7476_ring.c
+++ b/drivers/staging/iio/adc/ad7476_ring.c
@@ -8,13 +8,10 @@
*/
#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
-#include <linux/list.h>
#include <linux/spi/spi.h>
#include "../iio.h"
@@ -25,51 +22,19 @@
#include "ad7476.h"
-static IIO_SCAN_EL_C(in0, 0, 0, NULL);
-static IIO_SCAN_EL_TIMESTAMP(1);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
-
-static ssize_t ad7476_show_type(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_ring_buffer *ring = dev_get_drvdata(dev);
- struct iio_dev *indio_dev = ring->indio_dev;
- struct ad7476_state *st = indio_dev->dev_data;
-
- return sprintf(buf, "%c%d/%d>>%d\n", st->chip_info->sign,
- st->chip_info->bits, st->chip_info->storagebits,
- st->chip_info->res_shift);
-}
-static IIO_DEVICE_ATTR(in_type, S_IRUGO, ad7476_show_type, NULL, 0);
-
-static struct attribute *ad7476_scan_el_attrs[] = {
- &iio_scan_el_in0.dev_attr.attr,
- &iio_const_attr_in0_index.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- &iio_dev_attr_in_type.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group ad7476_scan_el_group = {
- .name = "scan_elements",
- .attrs = ad7476_scan_el_attrs,
-};
-
int ad7476_scan_from_ring(struct ad7476_state *st)
{
struct iio_ring_buffer *ring = st->indio_dev->ring;
int ret;
u8 *ring_data;
- ring_data = kmalloc(ring->access.get_bytes_per_datum(ring), GFP_KERNEL);
+ ring_data = kmalloc(ring->access->get_bytes_per_datum(ring),
+ GFP_KERNEL);
if (ring_data == NULL) {
ret = -ENOMEM;
goto error_ret;
}
- ret = ring->access.read_last(ring, ring_data);
+ ret = ring->access->read_last(ring, ring_data);
if (ret)
goto error_free_ring_data;
@@ -93,7 +58,8 @@ static int ad7476_ring_preenable(struct iio_dev *indio_dev)
struct ad7476_state *st = indio_dev->dev_data;
struct iio_ring_buffer *ring = indio_dev->ring;
- st->d_size = ring->scan_count * st->chip_info->storagebits / 8;
+ st->d_size = ring->scan_count *
+ st->chip_info->channel[0].scan_type.storagebits / 8;
if (ring->scan_timestamp) {
st->d_size += sizeof(s64);
@@ -102,55 +68,28 @@ static int ad7476_ring_preenable(struct iio_dev *indio_dev)
st->d_size += sizeof(s64) - (st->d_size % sizeof(s64));
}
- if (indio_dev->ring->access.set_bytes_per_datum)
- indio_dev->ring->access.set_bytes_per_datum(indio_dev->ring,
+ if (indio_dev->ring->access->set_bytes_per_datum)
+ indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring,
st->d_size);
return 0;
}
-/**
- * ad7476_poll_func_th() th of trigger launched polling to ring buffer
- *
- * As sampling only occurs on i2c comms occurring, leave timestamping until
- * then. Some triggers will generate their own time stamp. Currently
- * there is no way of notifying them when no one cares.
- **/
-static void ad7476_poll_func_th(struct iio_dev *indio_dev, s64 time)
+static irqreturn_t ad7476_trigger_handler(int irq, void *p)
{
- struct ad7476_state *st = indio_dev->dev_data;
-
- schedule_work(&st->poll_work);
- return;
-}
-/**
- * ad7476_poll_bh_to_ring() bh of trigger launched polling to ring buffer
- * @work_s: the work struct through which this was scheduled
- *
- * Currently there is no option in this driver to disable the saving of
- * timestamps within the ring.
- * I think the one copy of this at a time was to avoid problems if the
- * trigger was set far too high and the reads then locked up the computer.
- **/
-static void ad7476_poll_bh_to_ring(struct work_struct *work_s)
-{
- struct ad7476_state *st = container_of(work_s, struct ad7476_state,
- poll_work);
- struct iio_dev *indio_dev = st->indio_dev;
- struct iio_sw_ring_buffer *sw_ring = iio_to_sw_ring(indio_dev->ring);
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->private_data;
+ struct ad7476_state *st = iio_dev_get_devdata(indio_dev);
s64 time_ns;
__u8 *rxbuf;
int b_sent;
- /* Ensure only one copy of this function running at a time */
- if (atomic_inc_return(&st->protect_ring) > 1)
- return;
-
rxbuf = kzalloc(st->d_size, GFP_KERNEL);
if (rxbuf == NULL)
- return;
+ return -ENOMEM;
- b_sent = spi_read(st->spi, rxbuf, st->chip_info->storagebits / 8);
+ b_sent = spi_read(st->spi, rxbuf,
+ st->chip_info->channel[0].scan_type.storagebits / 8);
if (b_sent < 0)
goto done;
@@ -160,12 +99,20 @@ static void ad7476_poll_bh_to_ring(struct work_struct *work_s)
memcpy(rxbuf + st->d_size - sizeof(s64),
&time_ns, sizeof(time_ns));
- indio_dev->ring->access.store_to(&sw_ring->buf, rxbuf, time_ns);
+ indio_dev->ring->access->store_to(indio_dev->ring, rxbuf, time_ns);
done:
+ iio_trigger_notify_done(indio_dev->trig);
kfree(rxbuf);
- atomic_dec(&st->protect_ring);
+
+ return IRQ_HANDLED;
}
+static const struct iio_ring_setup_ops ad7476_ring_setup_ops = {
+ .preenable = &ad7476_ring_preenable,
+ .postenable = &iio_triggered_ring_postenable,
+ .predisable = &iio_triggered_ring_predisable,
+};
+
int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev)
{
struct ad7476_state *st = indio_dev->dev_data;
@@ -177,24 +124,28 @@ int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev)
goto error_ret;
}
/* Effectively select the ring buffer implementation */
- iio_ring_sw_register_funcs(&indio_dev->ring->access);
- ret = iio_alloc_pollfunc(indio_dev, NULL, &ad7476_poll_func_th);
- if (ret)
+ indio_dev->ring->access = &ring_sw_access_funcs;
+ indio_dev->pollfunc
+ = iio_alloc_pollfunc(NULL,
+ &ad7476_trigger_handler,
+ IRQF_ONESHOT,
+ indio_dev,
+ "%s_consumer%d",
+ spi_get_device_id(st->spi)->name,
+ 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->preenable = &ad7476_ring_preenable;
- indio_dev->ring->postenable = &iio_triggered_ring_postenable;
- indio_dev->ring->predisable = &iio_triggered_ring_predisable;
- indio_dev->ring->scan_el_attrs = &ad7476_scan_el_group;
+ indio_dev->ring->setup_ops = &ad7476_ring_setup_ops;
indio_dev->ring->scan_timestamp = true;
- INIT_WORK(&st->poll_work, &ad7476_poll_bh_to_ring);
-
/* 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:
@@ -209,6 +160,6 @@ void ad7476_ring_cleanup(struct iio_dev *indio_dev)
iio_trigger_dettach_poll_func(indio_dev->trig,
indio_dev->pollfunc);
}
- kfree(indio_dev->pollfunc);
+ iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h
index 338bade801a7..b8b3d8ef1ff2 100644
--- a/drivers/staging/iio/adc/ad7606.h
+++ b/drivers/staging/iio/adc/ad7606.h
@@ -43,17 +43,17 @@ struct ad7606_platform_data {
/**
* struct ad7606_chip_info - chip specifc information
* @name: indentification string for chip
- * @bits: accuracy of the adc in bits
- * @bits: output coding [s]igned or [u]nsigned
* @int_vref_mv: the internal reference voltage
- * @num_channels: number of physical inputs on chip
+ * @channels: channel specification
+ * @num_channels: number of channels
*/
struct ad7606_chip_info {
- char name[10];
+ const char *name;
u8 bits;
char sign;
u16 int_vref_mv;
+ struct iio_chan_spec *channels;
unsigned num_channels;
};
@@ -62,14 +62,12 @@ struct ad7606_chip_info {
*/
struct ad7606_state {
- struct iio_dev *indio_dev;
struct device *dev;
const struct ad7606_chip_info *chip_info;
struct ad7606_platform_data *pdata;
struct regulator *reg;
struct work_struct poll_work;
wait_queue_head_t wq_data_avail;
- atomic_t protect_ring;
size_t d_size;
const struct ad7606_bus_ops *bops;
int irq;
@@ -97,12 +95,12 @@ struct ad7606_bus_ops {
int (*read_block)(struct device *, int, void *);
};
-void ad7606_suspend(struct ad7606_state *st);
-void ad7606_resume(struct ad7606_state *st);
-struct ad7606_state *ad7606_probe(struct device *dev, int irq,
+void ad7606_suspend(struct iio_dev *indio_dev);
+void ad7606_resume(struct iio_dev *indio_dev);
+struct iio_dev *ad7606_probe(struct device *dev, int irq,
void __iomem *base_address, unsigned id,
const struct ad7606_bus_ops *bops);
-int ad7606_remove(struct ad7606_state *st);
+int ad7606_remove(struct iio_dev *indio_dev);
int ad7606_reset(struct ad7606_state *st);
enum ad7606_supported_device_ids {
@@ -111,7 +109,7 @@ enum ad7606_supported_device_ids {
ID_AD7606_4
};
-int ad7606_scan_from_ring(struct ad7606_state *st, unsigned ch);
+int ad7606_scan_from_ring(struct iio_dev *indio_dev, unsigned ch);
int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev);
void ad7606_ring_cleanup(struct iio_dev *indio_dev);
#endif /* IIO_ADC_AD7606_H_ */
diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c
index 4c700f07fb83..459371ae4dcc 100644
--- a/drivers/staging/iio/adc/ad7606_core.c
+++ b/drivers/staging/iio/adc/ad7606_core.c
@@ -7,12 +7,10 @@
*/
#include <linux/interrupt.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
-#include <linux/list.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
#include <linux/gpio.h>
@@ -38,8 +36,9 @@ int ad7606_reset(struct ad7606_state *st)
return -ENODEV;
}
-static int ad7606_scan_direct(struct ad7606_state *st, unsigned ch)
+static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned ch)
{
+ struct ad7606_state *st = iio_priv(indio_dev);
int ret;
st->done = false;
@@ -78,67 +77,44 @@ error_ret:
return ret;
}
-static ssize_t ad7606_scan(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int ad7606_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7606_state *st = dev_info->dev_data;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
-
- mutex_lock(&dev_info->mlock);
- if (iio_ring_enabled(dev_info))
- ret = ad7606_scan_from_ring(st, this_attr->address);
- else
- ret = ad7606_scan_direct(st, this_attr->address);
- mutex_unlock(&dev_info->mlock);
-
- if (ret < 0)
- return ret;
-
- return sprintf(buf, "%d\n", (short) ret);
-}
-
-static IIO_DEV_ATTR_IN_RAW(0, ad7606_scan, 0);
-static IIO_DEV_ATTR_IN_RAW(1, ad7606_scan, 1);
-static IIO_DEV_ATTR_IN_RAW(2, ad7606_scan, 2);
-static IIO_DEV_ATTR_IN_RAW(3, ad7606_scan, 3);
-static IIO_DEV_ATTR_IN_RAW(4, ad7606_scan, 4);
-static IIO_DEV_ATTR_IN_RAW(5, ad7606_scan, 5);
-static IIO_DEV_ATTR_IN_RAW(6, ad7606_scan, 6);
-static IIO_DEV_ATTR_IN_RAW(7, ad7606_scan, 7);
-
-static ssize_t ad7606_show_scale(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- /* Driver currently only support internal vref */
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7606_state *st = iio_dev_get_devdata(dev_info);
- unsigned int scale_uv = (st->range * 1000 * 2) >> st->chip_info->bits;
-
- return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
-}
-static IIO_DEVICE_ATTR(in_scale, S_IRUGO, ad7606_show_scale, NULL, 0);
-
-static ssize_t ad7606_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7606_state *st = iio_dev_get_devdata(dev_info);
-
- return sprintf(buf, "%s\n", st->chip_info->name);
+ struct ad7606_state *st = iio_priv(indio_dev);
+ unsigned int scale_uv;
+
+ switch (m) {
+ case 0:
+ mutex_lock(&indio_dev->mlock);
+ if (iio_ring_enabled(indio_dev))
+ ret = ad7606_scan_from_ring(indio_dev, chan->address);
+ else
+ ret = ad7606_scan_direct(indio_dev, chan->address);
+ mutex_unlock(&indio_dev->mlock);
+
+ if (ret < 0)
+ return ret;
+ *val = (short) ret;
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ scale_uv = (st->range * 1000 * 2)
+ >> st->chip_info->channels[0].scan_type.realbits;
+ *val = scale_uv / 1000;
+ *val2 = (scale_uv % 1000) * 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+ return -EINVAL;
}
-static IIO_DEVICE_ATTR(name, S_IRUGO, ad7606_show_name, NULL, 0);
-
static ssize_t ad7606_show_range(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7606_state *st = iio_dev_get_devdata(dev_info);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad7606_state *st = iio_priv(indio_dev);
return sprintf(buf, "%u\n", st->range);
}
@@ -146,8 +122,8 @@ static ssize_t ad7606_show_range(struct device *dev,
static ssize_t ad7606_store_range(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7606_state *st = iio_dev_get_devdata(dev_info);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad7606_state *st = iio_priv(indio_dev);
unsigned long lval;
if (strict_strtoul(buf, 10, &lval))
@@ -156,10 +132,10 @@ static ssize_t ad7606_store_range(struct device *dev,
dev_err(dev, "range is not supported\n");
return -EINVAL;
}
- mutex_lock(&dev_info->mlock);
+ mutex_lock(&indio_dev->mlock);
gpio_set_value(st->pdata->gpio_range, lval == 10000);
st->range = lval;
- mutex_unlock(&dev_info->mlock);
+ mutex_unlock(&indio_dev->mlock);
return count;
}
@@ -171,8 +147,8 @@ static IIO_CONST_ATTR(range_available, "5000 10000");
static ssize_t ad7606_show_oversampling_ratio(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7606_state *st = iio_dev_get_devdata(dev_info);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad7606_state *st = iio_priv(indio_dev);
return sprintf(buf, "%u\n", st->oversampling);
}
@@ -192,8 +168,8 @@ static int ad7606_oversampling_get_index(unsigned val)
static ssize_t ad7606_store_oversampling_ratio(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7606_state *st = iio_dev_get_devdata(dev_info);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad7606_state *st = iio_priv(indio_dev);
unsigned long lval;
int ret;
@@ -206,12 +182,12 @@ static ssize_t ad7606_store_oversampling_ratio(struct device *dev,
return ret;
}
- mutex_lock(&dev_info->mlock);
+ mutex_lock(&indio_dev->mlock);
gpio_set_value(st->pdata->gpio_os0, (ret >> 0) & 1);
gpio_set_value(st->pdata->gpio_os1, (ret >> 1) & 1);
gpio_set_value(st->pdata->gpio_os1, (ret >> 2) & 1);
st->oversampling = lval;
- mutex_unlock(&dev_info->mlock);
+ mutex_unlock(&indio_dev->mlock);
return count;
}
@@ -222,16 +198,6 @@ static IIO_DEVICE_ATTR(oversampling_ratio, S_IRUGO | S_IWUSR,
static IIO_CONST_ATTR(oversampling_ratio_available, "0 2 4 8 16 32 64");
static struct attribute *ad7606_attributes[] = {
- &iio_dev_attr_in0_raw.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_dev_attr_in2_raw.dev_attr.attr,
- &iio_dev_attr_in3_raw.dev_attr.attr,
- &iio_dev_attr_in4_raw.dev_attr.attr,
- &iio_dev_attr_in5_raw.dev_attr.attr,
- &iio_dev_attr_in6_raw.dev_attr.attr,
- &iio_dev_attr_in7_raw.dev_attr.attr,
- &iio_dev_attr_in_scale.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
&iio_dev_attr_range.dev_attr.attr,
&iio_const_attr_range_available.dev_attr.attr,
&iio_dev_attr_oversampling_ratio.dev_attr.attr,
@@ -243,20 +209,12 @@ static mode_t ad7606_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 ad7606_state *st = iio_dev_get_devdata(dev_info);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad7606_state *st = iio_priv(indio_dev);
mode_t mode = attr->mode;
- if (st->chip_info->num_channels <= 6 &&
- (attr == &iio_dev_attr_in7_raw.dev_attr.attr ||
- attr == &iio_dev_attr_in6_raw.dev_attr.attr))
- mode = 0;
- else if (st->chip_info->num_channels <= 4 &&
- (attr == &iio_dev_attr_in5_raw.dev_attr.attr ||
- attr == &iio_dev_attr_in4_raw.dev_attr.attr))
- mode = 0;
- else if (!st->have_os &&
+ if (!st->have_os &&
(attr == &iio_dev_attr_oversampling_ratio.dev_attr.attr ||
attr ==
&iio_const_attr_oversampling_ratio_available.dev_attr.attr))
@@ -274,29 +232,92 @@ static const struct attribute_group ad7606_attribute_group = {
.is_visible = ad7606_attr_is_visible,
};
+static struct iio_chan_spec ad7606_8_channels[] = {
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 1, 1, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 2, 2, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 3, 3, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 4, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 4, 4, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 5, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 5, 5, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 6, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 6, 6, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 7, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 7, 7, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+};
+
+static struct iio_chan_spec ad7606_6_channels[] = {
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 1, 1, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 2, 2, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 3, 3, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 4, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 4, 4, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 5, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 5, 5, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN_SOFT_TIMESTAMP(6),
+};
+
+static struct iio_chan_spec ad7606_4_channels[] = {
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 1, 1, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 2, 2, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 3, 3, IIO_ST('s', 16, 16, 0), 0),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
static const struct ad7606_chip_info ad7606_chip_info_tbl[] = {
/*
* More devices added in future
*/
[ID_AD7606_8] = {
.name = "ad7606",
- .bits = 16,
- .sign = IIO_SCAN_EL_TYPE_SIGNED,
.int_vref_mv = 2500,
+ .channels = ad7606_8_channels,
.num_channels = 8,
},
[ID_AD7606_6] = {
.name = "ad7606-6",
- .bits = 16,
- .sign = IIO_SCAN_EL_TYPE_SIGNED,
.int_vref_mv = 2500,
+ .channels = ad7606_6_channels,
.num_channels = 6,
},
[ID_AD7606_4] = {
.name = "ad7606-4",
- .bits = 16,
- .sign = IIO_SCAN_EL_TYPE_SIGNED,
.int_vref_mv = 2500,
+ .channels = ad7606_4_channels,
.num_channels = 4,
},
};
@@ -343,8 +364,8 @@ static int ad7606_request_gpios(struct ad7606_state *st)
st->have_reset = true;
ret = gpio_request_one(st->pdata->gpio_range, GPIOF_DIR_OUT |
- ((st->range == 10000) ? GPIOF_INIT_HIGH :
- GPIOF_INIT_LOW), "AD7606_RANGE");
+ ((st->range == 10000) ? GPIOF_INIT_HIGH :
+ GPIOF_INIT_LOW), "AD7606_RANGE");
if (!ret)
st->have_range = true;
@@ -391,9 +412,10 @@ static void ad7606_free_gpios(struct ad7606_state *st)
*/
static irqreturn_t ad7606_interrupt(int irq, void *dev_id)
{
- struct ad7606_state *st = dev_id;
+ struct iio_dev *indio_dev = dev_id;
+ struct ad7606_state *st = iio_priv(indio_dev);
- if (iio_ring_enabled(st->indio_dev)) {
+ if (iio_ring_enabled(indio_dev)) {
if (!work_pending(&st->poll_work))
schedule_work(&st->poll_work);
} else {
@@ -404,21 +426,29 @@ static irqreturn_t ad7606_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
};
-struct ad7606_state *ad7606_probe(struct device *dev, int irq,
+static const struct iio_info ad7606_info = {
+ .driver_module = THIS_MODULE,
+ .read_raw = &ad7606_read_raw,
+ .attrs = &ad7606_attribute_group,
+};
+
+struct iio_dev *ad7606_probe(struct device *dev, int irq,
void __iomem *base_address,
unsigned id,
const struct ad7606_bus_ops *bops)
{
struct ad7606_platform_data *pdata = dev->platform_data;
struct ad7606_state *st;
- int ret;
+ int ret, regdone = 0;
+ struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
- st = kzalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL) {
+ if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
}
+ st = iio_priv(indio_dev);
+
st->dev = dev;
st->id = id;
st->irq = irq;
@@ -445,93 +475,91 @@ struct ad7606_state *ad7606_probe(struct device *dev, int irq,
st->pdata = pdata;
st->chip_info = &ad7606_chip_info_tbl[id];
- atomic_set(&st->protect_ring, 0);
-
- st->indio_dev = iio_allocate_device();
- if (st->indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_disable_reg;
- }
-
- st->indio_dev->dev.parent = dev;
- st->indio_dev->attrs = &ad7606_attribute_group;
- st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
- st->indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->dev.parent = dev;
+ indio_dev->info = &ad7606_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->name = st->chip_info->name;
+ indio_dev->channels = st->chip_info->channels;
+ indio_dev->num_channels = st->chip_info->num_channels;
init_waitqueue_head(&st->wq_data_avail);
ret = ad7606_request_gpios(st);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
ret = ad7606_reset(st);
if (ret)
dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n");
ret = request_irq(st->irq, ad7606_interrupt,
- IRQF_TRIGGER_FALLING, st->chip_info->name, st);
+ IRQF_TRIGGER_FALLING, st->chip_info->name, indio_dev);
if (ret)
goto error_free_gpios;
- ret = ad7606_register_ring_funcs_and_init(st->indio_dev);
+ ret = ad7606_register_ring_funcs_and_init(indio_dev);
if (ret)
goto error_free_irq;
- ret = iio_device_register(st->indio_dev);
+ ret = iio_device_register(indio_dev);
if (ret)
goto error_free_irq;
+ regdone = 1;
- ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
+ ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
+ indio_dev->channels,
+ indio_dev->num_channels);
if (ret)
goto error_cleanup_ring;
- return st;
+ return indio_dev;
error_cleanup_ring:
- ad7606_ring_cleanup(st->indio_dev);
- iio_device_unregister(st->indio_dev);
+ ad7606_ring_cleanup(indio_dev);
error_free_irq:
- free_irq(st->irq, st);
+ free_irq(st->irq, indio_dev);
error_free_gpios:
ad7606_free_gpios(st);
-error_free_device:
- iio_free_device(st->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);
- kfree(st);
+ if (regdone)
+ iio_device_unregister(indio_dev);
+ else
+ iio_free_device(indio_dev);
error_ret:
return ERR_PTR(ret);
}
-int ad7606_remove(struct ad7606_state *st)
+int ad7606_remove(struct iio_dev *indio_dev)
{
- struct iio_dev *indio_dev = st->indio_dev;
+ struct ad7606_state *st = iio_priv(indio_dev);
+
iio_ring_buffer_unregister(indio_dev->ring);
ad7606_ring_cleanup(indio_dev);
- iio_device_unregister(indio_dev);
- free_irq(st->irq, st);
+
+ free_irq(st->irq, indio_dev);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);
regulator_put(st->reg);
}
ad7606_free_gpios(st);
+ iio_device_unregister(indio_dev);
- kfree(st);
return 0;
}
-void ad7606_suspend(struct ad7606_state *st)
+void ad7606_suspend(struct iio_dev *indio_dev)
{
+ struct ad7606_state *st = iio_priv(indio_dev);
+
if (st->have_stby) {
if (st->have_range)
gpio_set_value(st->pdata->gpio_range, 1);
@@ -539,8 +567,10 @@ void ad7606_suspend(struct ad7606_state *st)
}
}
-void ad7606_resume(struct ad7606_state *st)
+void ad7606_resume(struct iio_dev *indio_dev)
{
+ struct ad7606_state *st = iio_priv(indio_dev);
+
if (st->have_stby) {
if (st->have_range)
gpio_set_value(st->pdata->gpio_range,
diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c
index 43a554ce753d..d21218da923f 100644
--- a/drivers/staging/iio/adc/ad7606_par.c
+++ b/drivers/staging/iio/adc/ad7606_par.c
@@ -12,13 +12,15 @@
#include <linux/err.h>
#include <linux/io.h>
+#include "../iio.h"
#include "ad7606.h"
static int ad7606_par16_read_block(struct device *dev,
int count, void *buf)
{
struct platform_device *pdev = to_platform_device(dev);
- struct ad7606_state *st = platform_get_drvdata(pdev);
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+ struct ad7606_state *st = iio_priv(indio_dev);
insw((unsigned long) st->base_address, buf, count);
@@ -33,7 +35,8 @@ static int ad7606_par8_read_block(struct device *dev,
int count, void *buf)
{
struct platform_device *pdev = to_platform_device(dev);
- struct ad7606_state *st = platform_get_drvdata(pdev);
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+ struct ad7606_state *st = iio_priv(indio_dev);
insb((unsigned long) st->base_address, buf, count * 2);
@@ -47,7 +50,7 @@ static const struct ad7606_bus_ops ad7606_par8_bops = {
static int __devinit ad7606_par_probe(struct platform_device *pdev)
{
struct resource *res;
- struct ad7606_state *st;
+ struct iio_dev *indio_dev;
void __iomem *addr;
resource_size_t remap_size;
int ret, irq;
@@ -75,17 +78,17 @@ static int __devinit ad7606_par_probe(struct platform_device *pdev)
goto out1;
}
- st = ad7606_probe(&pdev->dev, irq, addr,
+ indio_dev = ad7606_probe(&pdev->dev, irq, addr,
platform_get_device_id(pdev)->driver_data,
remap_size > 1 ? &ad7606_par16_bops :
&ad7606_par8_bops);
- if (IS_ERR(st)) {
- ret = PTR_ERR(st);
+ if (IS_ERR(indio_dev)) {
+ ret = PTR_ERR(indio_dev);
goto out2;
}
- platform_set_drvdata(pdev, st);
+ platform_set_drvdata(pdev, indio_dev);
return 0;
@@ -99,10 +102,11 @@ out1:
static int __devexit ad7606_par_remove(struct platform_device *pdev)
{
- struct ad7606_state *st = platform_get_drvdata(pdev);
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct resource *res;
+ struct ad7606_state *st = iio_priv(indio_dev);
- ad7606_remove(st);
+ ad7606_remove(indio_dev);
iounmap(st->base_address);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -116,18 +120,18 @@ static int __devexit ad7606_par_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int ad7606_par_suspend(struct device *dev)
{
- struct ad7606_state *st = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ad7606_suspend(st);
+ ad7606_suspend(indio_dev);
return 0;
}
static int ad7606_par_resume(struct device *dev)
{
- struct ad7606_state *st = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ad7606_resume(st);
+ ad7606_resume(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c
index b32cb0dea6d8..a199bf48396c 100644
--- a/drivers/staging/iio/adc/ad7606_ring.c
+++ b/drivers/staging/iio/adc/ad7606_ring.c
@@ -7,7 +7,6 @@
#include <linux/interrupt.h>
#include <linux/gpio.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -21,99 +20,19 @@
#include "ad7606.h"
-static IIO_SCAN_EL_C(in0, 0, 0, NULL);
-static IIO_SCAN_EL_C(in1, 1, 0, NULL);
-static IIO_SCAN_EL_C(in2, 2, 0, NULL);
-static IIO_SCAN_EL_C(in3, 3, 0, NULL);
-static IIO_SCAN_EL_C(in4, 4, 0, NULL);
-static IIO_SCAN_EL_C(in5, 5, 0, NULL);
-static IIO_SCAN_EL_C(in6, 6, 0, NULL);
-static IIO_SCAN_EL_C(in7, 7, 0, NULL);
-
-static IIO_SCAN_EL_TIMESTAMP(8);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
-
-static ssize_t ad7606_show_type(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+int ad7606_scan_from_ring(struct iio_dev *indio_dev, unsigned ch)
{
- struct iio_ring_buffer *ring = dev_get_drvdata(dev);
- struct iio_dev *indio_dev = ring->indio_dev;
- struct ad7606_state *st = indio_dev->dev_data;
-
- return sprintf(buf, "%c%d/%d\n", st->chip_info->sign,
- st->chip_info->bits, st->chip_info->bits);
-}
-static IIO_DEVICE_ATTR(in_type, S_IRUGO, ad7606_show_type, NULL, 0);
-
-static struct attribute *ad7606_scan_el_attrs[] = {
- &iio_scan_el_in0.dev_attr.attr,
- &iio_const_attr_in0_index.dev_attr.attr,
- &iio_scan_el_in1.dev_attr.attr,
- &iio_const_attr_in1_index.dev_attr.attr,
- &iio_scan_el_in2.dev_attr.attr,
- &iio_const_attr_in2_index.dev_attr.attr,
- &iio_scan_el_in3.dev_attr.attr,
- &iio_const_attr_in3_index.dev_attr.attr,
- &iio_scan_el_in4.dev_attr.attr,
- &iio_const_attr_in4_index.dev_attr.attr,
- &iio_scan_el_in5.dev_attr.attr,
- &iio_const_attr_in5_index.dev_attr.attr,
- &iio_scan_el_in6.dev_attr.attr,
- &iio_const_attr_in6_index.dev_attr.attr,
- &iio_scan_el_in7.dev_attr.attr,
- &iio_const_attr_in7_index.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- &iio_dev_attr_in_type.dev_attr.attr,
- NULL,
-};
-
-static mode_t ad7606_scan_el_attr_is_visible(struct kobject *kobj,
- struct attribute *attr, int n)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct iio_ring_buffer *ring = dev_get_drvdata(dev);
- struct iio_dev *indio_dev = ring->indio_dev;
- struct ad7606_state *st = indio_dev->dev_data;
-
- mode_t mode = attr->mode;
-
- if (st->chip_info->num_channels <= 6 &&
- (attr == &iio_scan_el_in7.dev_attr.attr ||
- attr == &iio_const_attr_in7_index.dev_attr.attr ||
- attr == &iio_scan_el_in6.dev_attr.attr ||
- attr == &iio_const_attr_in6_index.dev_attr.attr))
- mode = 0;
- else if (st->chip_info->num_channels <= 4 &&
- (attr == &iio_scan_el_in5.dev_attr.attr ||
- attr == &iio_const_attr_in5_index.dev_attr.attr ||
- attr == &iio_scan_el_in4.dev_attr.attr ||
- attr == &iio_const_attr_in4_index.dev_attr.attr))
- mode = 0;
-
- return mode;
-}
-
-static struct attribute_group ad7606_scan_el_group = {
- .name = "scan_elements",
- .attrs = ad7606_scan_el_attrs,
- .is_visible = ad7606_scan_el_attr_is_visible,
-};
-
-int ad7606_scan_from_ring(struct ad7606_state *st, unsigned ch)
-{
- struct iio_ring_buffer *ring = st->indio_dev->ring;
+ struct iio_ring_buffer *ring = indio_dev->ring;
int ret;
u16 *ring_data;
- ring_data = kmalloc(ring->access.get_bytes_per_datum(ring), GFP_KERNEL);
+ ring_data = kmalloc(ring->access->get_bytes_per_datum(ring),
+ GFP_KERNEL);
if (ring_data == NULL) {
ret = -ENOMEM;
goto error_ret;
}
- ret = ring->access.read_last(ring, (u8 *) ring_data);
+ ret = ring->access->read_last(ring, (u8 *) ring_data);
if (ret)
goto error_free_ring_data;
@@ -134,12 +53,12 @@ error_ret:
**/
static int ad7606_ring_preenable(struct iio_dev *indio_dev)
{
- struct ad7606_state *st = indio_dev->dev_data;
+ struct ad7606_state *st = iio_priv(indio_dev);
struct iio_ring_buffer *ring = indio_dev->ring;
size_t d_size;
d_size = st->chip_info->num_channels *
- st->chip_info->bits / 8;
+ st->chip_info->channels[0].scan_type.storagebits / 8;
if (ring->scan_timestamp) {
d_size += sizeof(s64);
@@ -148,8 +67,8 @@ static int ad7606_ring_preenable(struct iio_dev *indio_dev)
d_size += sizeof(s64) - (d_size % sizeof(s64));
}
- if (ring->access.set_bytes_per_datum)
- ring->access.set_bytes_per_datum(ring, d_size);
+ if (ring->access->set_bytes_per_datum)
+ ring->access->set_bytes_per_datum(ring, d_size);
st->d_size = d_size;
@@ -157,16 +76,20 @@ static int ad7606_ring_preenable(struct iio_dev *indio_dev)
}
/**
- * ad7606_poll_func_th() th of trigger launched polling to ring buffer
+ * ad7606_trigger_handler_th() th/bh of trigger launched polling to ring buffer
*
**/
-static void ad7606_poll_func_th(struct iio_dev *indio_dev, s64 time)
+static irqreturn_t ad7606_trigger_handler_th_bh(int irq, void *p)
{
- struct ad7606_state *st = indio_dev->dev_data;
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->private_data;
+ struct ad7606_state *st = iio_priv(indio_dev);
+
gpio_set_value(st->pdata->gpio_convst, 1);
- return;
+ return IRQ_HANDLED;
}
+
/**
* ad7606_poll_bh_to_ring() bh of trigger launched polling to ring buffer
* @work_s: the work struct through which this was scheduled
@@ -180,17 +103,12 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s)
{
struct ad7606_state *st = container_of(work_s, struct ad7606_state,
poll_work);
- struct iio_dev *indio_dev = st->indio_dev;
- struct iio_sw_ring_buffer *sw_ring = iio_to_sw_ring(indio_dev->ring);
+ struct iio_dev *indio_dev = iio_priv_to_dev(st);
struct iio_ring_buffer *ring = indio_dev->ring;
s64 time_ns;
__u8 *buf;
int ret;
- /* Ensure only one copy of this function running at a time */
- if (atomic_inc_return(&st->protect_ring) > 1)
- return;
-
buf = kzalloc(st->d_size, GFP_KERNEL);
if (buf == NULL)
return;
@@ -225,16 +143,22 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s)
memcpy(buf + st->d_size - sizeof(s64),
&time_ns, sizeof(time_ns));
- ring->access.store_to(&sw_ring->buf, buf, time_ns);
+ ring->access->store_to(indio_dev->ring, buf, time_ns);
done:
gpio_set_value(st->pdata->gpio_convst, 0);
+ iio_trigger_notify_done(indio_dev->trig);
kfree(buf);
- atomic_dec(&st->protect_ring);
}
+static const struct iio_ring_setup_ops ad7606_ring_setup_ops = {
+ .preenable = &ad7606_ring_preenable,
+ .postenable = &iio_triggered_ring_postenable,
+ .predisable = &iio_triggered_ring_predisable,
+};
+
int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev)
{
- struct ad7606_state *st = indio_dev->dev_data;
+ struct ad7606_state *st = iio_priv(indio_dev);
int ret;
indio_dev->ring = iio_sw_rb_allocate(indio_dev);
@@ -244,17 +168,22 @@ int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev)
}
/* Effectively select the ring buffer implementation */
- iio_ring_sw_register_funcs(&indio_dev->ring->access);
- ret = iio_alloc_pollfunc(indio_dev, NULL, &ad7606_poll_func_th);
- if (ret)
+ indio_dev->ring->access = &ring_sw_access_funcs;
+ indio_dev->pollfunc = iio_alloc_pollfunc(&ad7606_trigger_handler_th_bh,
+ &ad7606_trigger_handler_th_bh,
+ 0,
+ indio_dev,
+ "%s_consumer%d",
+ indio_dev->name,
+ 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->preenable = &ad7606_ring_preenable;
- indio_dev->ring->postenable = &iio_triggered_ring_postenable;
- indio_dev->ring->predisable = &iio_triggered_ring_predisable;
- indio_dev->ring->scan_el_attrs = &ad7606_scan_el_group;
+ indio_dev->ring->setup_ops = &ad7606_ring_setup_ops;
indio_dev->ring->scan_timestamp = true ;
INIT_WORK(&st->poll_work, &ad7606_poll_bh_to_ring);
@@ -262,6 +191,7 @@ int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev)
/* 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:
@@ -275,6 +205,6 @@ void ad7606_ring_cleanup(struct iio_dev *indio_dev)
iio_trigger_dettach_poll_func(indio_dev->trig,
indio_dev->pollfunc);
}
- kfree(indio_dev->pollfunc);
+ iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c
index d738491222f2..0769c807d95f 100644
--- a/drivers/staging/iio/adc/ad7606_spi.c
+++ b/drivers/staging/iio/adc/ad7606_spi.c
@@ -10,6 +10,8 @@
#include <linux/spi/spi.h>
#include <linux/types.h>
#include <linux/err.h>
+
+#include "../iio.h"
#include "ad7606.h"
#define MAX_SPI_FREQ_HZ 23500000 /* VDRIVE above 4.75 V */
@@ -39,42 +41,42 @@ static const struct ad7606_bus_ops ad7606_spi_bops = {
static int __devinit ad7606_spi_probe(struct spi_device *spi)
{
- struct ad7606_state *st;
+ struct iio_dev *indio_dev;
- st = ad7606_probe(&spi->dev, spi->irq, NULL,
+ indio_dev = ad7606_probe(&spi->dev, spi->irq, NULL,
spi_get_device_id(spi)->driver_data,
&ad7606_spi_bops);
- if (IS_ERR(st))
- return PTR_ERR(st);
+ if (IS_ERR(indio_dev))
+ return PTR_ERR(indio_dev);
- spi_set_drvdata(spi, st);
+ spi_set_drvdata(spi, indio_dev);
return 0;
}
static int __devexit ad7606_spi_remove(struct spi_device *spi)
{
- struct ad7606_state *st = dev_get_drvdata(&spi->dev);
+ struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev);
- return ad7606_remove(st);
+ return ad7606_remove(indio_dev);
}
#ifdef CONFIG_PM
static int ad7606_spi_suspend(struct device *dev)
{
- struct ad7606_state *st = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ad7606_suspend(st);
+ ad7606_suspend(indio_dev);
return 0;
}
static int ad7606_spi_resume(struct device *dev)
{
- struct ad7606_state *st = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ad7606_resume(st);
+ ad7606_resume(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7745.c b/drivers/staging/iio/adc/ad7745.c
index ab7ef8450ae2..1944223ef163 100644
--- a/drivers/staging/iio/adc/ad7745.c
+++ b/drivers/staging/iio/adc/ad7745.c
@@ -8,14 +8,12 @@
#include <linux/interrupt.h>
#include <linux/gpio.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/i2c.h>
-#include <linux/rtc.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -55,12 +53,9 @@
*/
struct ad774x_chip_info {
- const char *name;
struct i2c_client *client;
struct iio_dev *indio_dev;
- struct work_struct thresh_work;
bool inter;
- s64 last_timestamp;
u16 cap_offs; /* Capacitive offset */
u16 cap_gain; /* Capacitive gain calibration */
u16 volt_gain; /* Voltage gain calibration */
@@ -76,7 +71,8 @@ struct ad774x_conversion_mode {
u8 reg_cfg;
};
-struct ad774x_conversion_mode ad774x_conv_mode_table[AD774X_MAX_CONV_MODE] = {
+static struct ad774x_conversion_mode
+ad774x_conv_mode_table[AD774X_MAX_CONV_MODE] = {
{ "idle", 0 },
{ "continuous-conversion", 1 },
{ "single-conversion", 2 },
@@ -502,17 +498,6 @@ static IIO_DEV_ATTR_CAP_GAIN(S_IRUGO | S_IWUSR,
ad774x_show_cap_gain,
ad774x_store_cap_gain);
-static ssize_t ad774x_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad774x_chip_info *chip = dev_info->dev_data;
- return sprintf(buf, "%s\n", chip->name);
-}
-
-static IIO_DEVICE_ATTR(name, S_IRUGO, ad774x_show_name, NULL, 0);
-
static struct attribute *ad774x_attributes[] = {
&iio_dev_attr_available_conversion_modes.dev_attr.attr,
&iio_dev_attr_conversion_mode.dev_attr.attr,
@@ -526,7 +511,6 @@ static struct attribute *ad774x_attributes[] = {
&iio_dev_attr_cap0_raw.dev_attr.attr,
&iio_dev_attr_capdac0_raw.dev_attr.attr,
&iio_dev_attr_capdac1_raw.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
NULL,
};
@@ -538,8 +522,8 @@ static const struct attribute_group ad774x_attribute_group = {
* data ready events
*/
-#define IIO_EVENT_CODE_CAP_RDY IIO_BUFFER_EVENT_CODE(0)
-#define IIO_EVENT_CODE_VT_RDY IIO_BUFFER_EVENT_CODE(1)
+#define IIO_EVENT_CODE_CAP_RDY 0
+#define IIO_EVENT_CODE_VT_RDY 1
#define IIO_EVENT_ATTR_CAP_RDY_SH(_evlist, _show, _store, _mask) \
IIO_EVENT_ATTR_SH(cap_rdy, _evlist, _show, _store, _mask)
@@ -547,67 +531,33 @@ static const struct attribute_group ad774x_attribute_group = {
#define IIO_EVENT_ATTR_VT_RDY_SH(_evlist, _show, _store, _mask) \
IIO_EVENT_ATTR_SH(vt_rdy, _evlist, _show, _store, _mask)
-static void ad774x_interrupt_handler_bh(struct work_struct *work_s)
+static irqreturn_t ad774x_event_handler(int irq, void *private)
{
- struct ad774x_chip_info *chip =
- container_of(work_s, struct ad774x_chip_info, thresh_work);
+ struct iio_dev *indio_dev = private;
+ struct ad774x_chip_info *chip = iio_dev_get_devdata(indio_dev);
u8 int_status;
- enable_irq(chip->client->irq);
-
ad774x_i2c_read(chip, AD774X_STATUS, &int_status, 1);
if (int_status & AD774X_STATUS_RDYCAP)
- iio_push_event(chip->indio_dev, 0,
- IIO_EVENT_CODE_CAP_RDY,
- chip->last_timestamp);
+ iio_push_event(indio_dev, 0,
+ IIO_EVENT_CODE_CAP_RDY,
+ iio_get_time_ns());
if (int_status & AD774X_STATUS_RDYVT)
- iio_push_event(chip->indio_dev, 0,
- IIO_EVENT_CODE_VT_RDY,
- chip->last_timestamp);
-}
-
-static int ad774x_interrupt_handler_th(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct ad774x_chip_info *chip = dev_info->dev_data;
-
- chip->last_timestamp = timestamp;
- schedule_work(&chip->thresh_work);
+ iio_push_event(indio_dev, 0,
+ IIO_EVENT_CODE_VT_RDY,
+ iio_get_time_ns());
- return 0;
+ return IRQ_HANDLED;
}
-IIO_EVENT_SH(data_rdy, &ad774x_interrupt_handler_th);
-
-static ssize_t ad774x_query_out_mode(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- /*
- * AD774X provides one /RDY pin, which can be used as interrupt
- * but the pin is not configurable
- */
- return sprintf(buf, "1\n");
-}
-
-static ssize_t ad774x_set_out_mode(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return len;
-}
-
-IIO_EVENT_ATTR_CAP_RDY_SH(iio_event_data_rdy, ad774x_query_out_mode, ad774x_set_out_mode, 0);
-IIO_EVENT_ATTR_VT_RDY_SH(iio_event_data_rdy, ad774x_query_out_mode, ad774x_set_out_mode, 0);
+static IIO_CONST_ATTR(cap_rdy_en, "1");
+static IIO_CONST_ATTR(vt_rdy_en, "1");
static struct attribute *ad774x_event_attributes[] = {
- &iio_event_attr_cap_rdy.dev_attr.attr,
- &iio_event_attr_vt_rdy.dev_attr.attr,
+ &iio_const_attr_cap_rdy_en.dev_attr.attr,
+ &iio_const_attr_vt_rdy_en.dev_attr.attr,
NULL,
};
@@ -615,6 +565,12 @@ static struct attribute_group ad774x_event_attribute_group = {
.attrs = ad774x_event_attributes,
};
+static const struct iio_info ad774x_info = {
+ .attrs = &ad774x_event_attribute_group,
+ .event_attrs = &ad774x_event_attribute_group,
+ .num_interrupt_lines = 1,
+ .driver_module = THIS_MODULE,
+};
/*
* device probe and remove
*/
@@ -633,21 +589,18 @@ static int __devinit ad774x_probe(struct i2c_client *client,
i2c_set_clientdata(client, chip);
chip->client = client;
- chip->name = id->name;
- chip->indio_dev = iio_allocate_device();
+ chip->indio_dev = iio_allocate_device(0);
if (chip->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_chip;
}
/* Establish that the iio_dev is a child of the i2c device */
+ chip->indio_dev->name = id->name;
chip->indio_dev->dev.parent = &client->dev;
- chip->indio_dev->attrs = &ad774x_attribute_group;
- chip->indio_dev->event_attrs = &ad774x_event_attribute_group;
+ chip->indio_dev->info = &ad774x_info;
chip->indio_dev->dev_data = (void *)(chip);
- chip->indio_dev->driver_module = THIS_MODULE;
- chip->indio_dev->num_interrupt_lines = 1;
chip->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(chip->indio_dev);
@@ -656,18 +609,14 @@ static int __devinit ad774x_probe(struct i2c_client *client,
regdone = 1;
if (client->irq) {
- ret = iio_register_interrupt_line(client->irq,
- chip->indio_dev,
- 0,
- IRQF_TRIGGER_FALLING,
- "ad774x");
+ ret = request_threaded_irq(client->irq,
+ NULL,
+ &ad774x_event_handler,
+ IRQF_TRIGGER_FALLING,
+ "ad774x",
+ chip->indio_dev);
if (ret)
goto error_free_dev;
-
- iio_add_event_to_list(iio_event_attr_cap_rdy.listel,
- &chip->indio_dev->interrupts[0]->ev_list);
-
- INIT_WORK(&chip->thresh_work, ad774x_interrupt_handler_bh);
}
dev_err(&client->dev, "%s capacitive sensor registered, irq: %d\n", id->name, client->irq);
@@ -676,7 +625,7 @@ static int __devinit ad774x_probe(struct i2c_client *client,
error_free_dev:
if (regdone)
- iio_device_unregister(chip->indio_dev);
+ free_irq(client->irq, chip->indio_dev);
else
iio_free_device(chip->indio_dev);
error_free_chip:
@@ -691,7 +640,7 @@ static int __devexit ad774x_remove(struct i2c_client *client)
struct iio_dev *indio_dev = chip->indio_dev;
if (client->irq)
- iio_unregister_interrupt_line(indio_dev, 0);
+ free_irq(client->irq, indio_dev);
iio_device_unregister(indio_dev);
kfree(chip);
diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c
new file mode 100644
index 000000000000..e0c7b6cc05c7
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7780.c
@@ -0,0 +1,301 @@
+/*
+ * AD7780/AD7781 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/gpio.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "../ring_generic.h"
+#include "adc.h"
+
+#include "ad7780.h"
+
+#define AD7780_RDY (1 << 7)
+#define AD7780_FILTER (1 << 6)
+#define AD7780_ERR (1 << 5)
+#define AD7780_ID1 (1 << 4)
+#define AD7780_ID0 (1 << 3)
+#define AD7780_GAIN (1 << 2)
+#define AD7780_PAT1 (1 << 1)
+#define AD7780_PAT0 (1 << 0)
+
+struct ad7780_chip_info {
+ struct iio_chan_spec channel;
+};
+
+struct ad7780_state {
+ struct spi_device *spi;
+ const struct ad7780_chip_info *chip_info;
+ struct regulator *reg;
+ struct ad7780_platform_data *pdata;
+ wait_queue_head_t wq_data_avail;
+ bool done;
+ u16 int_vref_mv;
+ struct spi_transfer xfer;
+ struct spi_message msg;
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ unsigned int data ____cacheline_aligned;
+};
+
+enum ad7780_supported_device_ids {
+ ID_AD7780,
+ ID_AD7781,
+};
+
+static int ad7780_read(struct ad7780_state *st, int *val)
+{
+ int ret;
+
+ spi_bus_lock(st->spi->master);
+
+ enable_irq(st->spi->irq);
+ st->done = false;
+ gpio_set_value(st->pdata->gpio_pdrst, 1);
+
+ ret = wait_event_interruptible(st->wq_data_avail, st->done);
+ disable_irq_nosync(st->spi->irq);
+ if (ret)
+ goto out;
+
+ ret = spi_sync_locked(st->spi, &st->msg);
+ *val = be32_to_cpu(st->data);
+out:
+ gpio_set_value(st->pdata->gpio_pdrst, 0);
+ spi_bus_unlock(st->spi->master);
+
+ return ret;
+}
+
+static int ad7780_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
+{
+ struct ad7780_state *st = iio_priv(indio_dev);
+ struct iio_chan_spec channel = st->chip_info->channel;
+ int ret, smpl = 0;
+ unsigned long scale_uv;
+
+ switch (m) {
+ case 0:
+ mutex_lock(&indio_dev->mlock);
+ ret = ad7780_read(st, &smpl);
+ mutex_unlock(&indio_dev->mlock);
+
+ if (ret < 0)
+ return ret;
+
+ if ((smpl & AD7780_ERR) ||
+ !((smpl & AD7780_PAT0) && !(smpl & AD7780_PAT1)))
+ return -EIO;
+
+ *val = (smpl >> channel.scan_type.shift) &
+ ((1 << (channel.scan_type.realbits)) - 1);
+ *val -= (1 << (channel.scan_type.realbits - 1));
+
+ if (!(smpl & AD7780_GAIN))
+ *val *= 128;
+
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ scale_uv = (st->int_vref_mv * 100000)
+ >> (channel.scan_type.realbits - 1);
+ *val = scale_uv / 100000;
+ *val2 = (scale_uv % 100000) * 10;
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+ return -EINVAL;
+}
+
+static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
+ [ID_AD7780] = {
+ .channel = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('s', 24, 32, 8), 0),
+ },
+ [ID_AD7781] = {
+ .channel = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('s', 20, 32, 12), 0),
+ },
+};
+
+/**
+ * Interrupt handler
+ */
+static irqreturn_t ad7780_interrupt(int irq, void *dev_id)
+{
+ struct ad7780_state *st = dev_id;
+
+ st->done = true;
+ wake_up_interruptible(&st->wq_data_avail);
+
+ return IRQ_HANDLED;
+};
+
+static const struct iio_info ad7780_info = {
+ .read_raw = &ad7780_read_raw,
+ .driver_module = THIS_MODULE,
+};
+
+static int __devinit ad7780_probe(struct spi_device *spi)
+{
+ struct ad7780_platform_data *pdata = spi->dev.platform_data;
+ struct ad7780_state *st;
+ struct iio_dev *indio_dev;
+ int ret, voltage_uv = 0;
+
+ if (!pdata) {
+ dev_dbg(&spi->dev, "no platform data?\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->chip_info =
+ &ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data];
+
+ 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 unspecified\n");
+
+ spi_set_drvdata(spi, indio_dev);
+ st->spi = spi;
+
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = &st->chip_info->channel;
+ indio_dev->num_channels = 1;
+ indio_dev->info = &ad7780_info;
+
+ init_waitqueue_head(&st->wq_data_avail);
+
+ /* Setup default message */
+
+ st->xfer.rx_buf = &st->data;
+ st->xfer.len = st->chip_info->channel.scan_type.storagebits / 8;
+
+ spi_message_init(&st->msg);
+ spi_message_add_tail(&st->xfer, &st->msg);
+
+ ret = gpio_request_one(st->pdata->gpio_pdrst, GPIOF_OUT_INIT_LOW,
+ "AD7780 /PDRST");
+ if (ret) {
+ dev_err(&spi->dev, "failed to request GPIO PDRST\n");
+ goto error_disable_reg;
+ }
+
+ ret = request_irq(spi->irq, ad7780_interrupt,
+ IRQF_TRIGGER_FALLING, spi_get_device_id(spi)->name, st);
+ if (ret)
+ goto error_free_gpio;
+
+ disable_irq(spi->irq);
+
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto error_free_irq;
+
+ return 0;
+
+error_free_irq:
+ free_irq(spi->irq, st);
+error_free_gpio:
+ gpio_free(st->pdata->gpio_pdrst);
+error_disable_reg:
+ if (!IS_ERR(st->reg))
+ regulator_disable(st->reg);
+error_put_reg:
+ if (!IS_ERR(st->reg))
+ regulator_put(st->reg);
+
+ iio_free_device(indio_dev);
+
+ return ret;
+}
+
+static int ad7780_remove(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct ad7780_state *st = iio_priv(indio_dev);
+
+ free_irq(spi->irq, st);
+ gpio_free(st->pdata->gpio_pdrst);
+ 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 ad7780_id[] = {
+ {"ad7780", ID_AD7780},
+ {"ad7781", ID_AD7781},
+ {}
+};
+
+static struct spi_driver ad7780_driver = {
+ .driver = {
+ .name = "ad7780",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = ad7780_probe,
+ .remove = __devexit_p(ad7780_remove),
+ .id_table = ad7780_id,
+};
+
+static int __init ad7780_init(void)
+{
+ return spi_register_driver(&ad7780_driver);
+}
+module_init(ad7780_init);
+
+static void __exit ad7780_exit(void)
+{
+ spi_unregister_driver(&ad7780_driver);
+}
+module_exit(ad7780_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD7780/1 ADC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/adc/ad7780.h b/drivers/staging/iio/adc/ad7780.h
new file mode 100644
index 000000000000..67e511c3d6f0
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7780.h
@@ -0,0 +1,30 @@
+/*
+ * AD7780/AD7781 SPI ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+#ifndef IIO_ADC_AD7780_H_
+#define IIO_ADC_AD7780_H_
+
+/*
+ * TODO: struct ad7780_platform_data needs to go into include/linux/iio
+ */
+
+/* NOTE:
+ * The AD7780 doesn't feature a dedicated SPI chip select, in addition it
+ * 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 combined with a dedicated GPIO to control the
+ * power down reset signal of the AD7780.
+ *
+ * The DOUT/RDY output must also be wired to an interrupt capable GPIO.
+ */
+
+struct ad7780_platform_data {
+ u16 vref_mv;
+ int gpio_pdrst;
+};
+
+#endif /* IIO_ADC_AD7780_H_ */
diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c
index ad7415a6b8d9..11379e469b07 100644
--- a/drivers/staging/iio/adc/ad7816.c
+++ b/drivers/staging/iio/adc/ad7816.c
@@ -8,14 +8,12 @@
#include <linux/interrupt.h>
#include <linux/gpio.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/spi/spi.h>
-#include <linux/rtc.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -44,11 +42,8 @@
*/
struct ad7816_chip_info {
- const char *name;
struct spi_device *spi_dev;
struct iio_dev *indio_dev;
- struct work_struct thresh_work;
- s64 last_timestamp;
u16 rdwr_pin;
u16 convert_pin;
u16 busy_pin;
@@ -185,13 +180,13 @@ static ssize_t ad7816_store_channel(struct device *dev,
if (data > AD7816_CS_MAX && data != AD7816_CS_MASK) {
dev_err(&chip->spi_dev->dev, "Invalid channel id %lu for %s.\n",
- data, chip->name);
+ data, dev_info->name);
return -EINVAL;
- } else if (strcmp(chip->name, "ad7818") == 0 && data > 1) {
+ } else if (strcmp(dev_info->name, "ad7818") == 0 && data > 1) {
dev_err(&chip->spi_dev->dev,
"Invalid channel id %lu for ad7818.\n", data);
return -EINVAL;
- } else if (strcmp(chip->name, "ad7816") == 0 && data > 0) {
+ } else if (strcmp(dev_info->name, "ad7816") == 0 && data > 0) {
dev_err(&chip->spi_dev->dev,
"Invalid channel id %lu for ad7816.\n", data);
return -EINVAL;
@@ -236,23 +231,11 @@ static ssize_t ad7816_show_value(struct device *dev,
static IIO_DEVICE_ATTR(value, S_IRUGO, ad7816_show_value, NULL, 0);
-static ssize_t ad7816_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7816_chip_info *chip = dev_info->dev_data;
- return sprintf(buf, "%s\n", chip->name);
-}
-
-static IIO_DEVICE_ATTR(name, S_IRUGO, ad7816_show_name, NULL, 0);
-
static struct attribute *ad7816_attributes[] = {
&iio_dev_attr_available_modes.dev_attr.attr,
&iio_dev_attr_mode.dev_attr.attr,
&iio_dev_attr_channel.dev_attr.attr,
&iio_dev_attr_value.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
NULL,
};
@@ -264,35 +247,19 @@ static const struct attribute_group ad7816_attribute_group = {
* temperature bound events
*/
-#define IIO_EVENT_CODE_AD7816_OTI IIO_BUFFER_EVENT_CODE(0)
+#define IIO_EVENT_CODE_AD7816_OTI IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_TEMP, \
+ 0, \
+ IIO_EV_TYPE_THRESH, \
+ IIO_EV_DIR_FALLING)
-static void ad7816_interrupt_bh(struct work_struct *work_s)
+static irqreturn_t ad7816_event_handler(int irq, void *private)
{
- struct ad7816_chip_info *chip =
- container_of(work_s, struct ad7816_chip_info, thresh_work);
-
- enable_irq(chip->spi_dev->irq);
-
- iio_push_event(chip->indio_dev, 0,
- IIO_EVENT_CODE_AD7816_OTI,
- chip->last_timestamp);
+ iio_push_event(private, 0,
+ IIO_EVENT_CODE_AD7816_OTI,
+ iio_get_time_ns());
+ return IRQ_HANDLED;
}
-static int ad7816_interrupt(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct ad7816_chip_info *chip = dev_info->dev_data;
-
- chip->last_timestamp = timestamp;
- schedule_work(&chip->thresh_work);
-
- return 0;
-}
-
-IIO_EVENT_SH(ad7816, &ad7816_interrupt);
-
static ssize_t ad7816_show_oti(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -352,11 +319,11 @@ static inline ssize_t ad7816_set_oti(struct device *dev,
return len;
}
-IIO_EVENT_ATTR_SH(oti, iio_event_ad7816,
- ad7816_show_oti, ad7816_set_oti, 0);
+static IIO_DEVICE_ATTR(oti, S_IRUGO | S_IWUSR,
+ ad7816_show_oti, ad7816_set_oti, 0);
static struct attribute *ad7816_event_attributes[] = {
- &iio_event_attr_oti.dev_attr.attr,
+ &iio_dev_attr_oti.dev_attr.attr,
NULL,
};
@@ -364,6 +331,13 @@ static struct attribute_group ad7816_event_attribute_group = {
.attrs = ad7816_event_attributes,
};
+static const struct iio_info ad7816_info = {
+ .attrs = &ad7816_attribute_group,
+ .num_interrupt_lines = 1,
+ .event_attrs = &ad7816_event_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
/*
* device probe and remove
*/
@@ -389,28 +363,27 @@ static int __devinit ad7816_probe(struct spi_device *spi_dev)
dev_set_drvdata(&spi_dev->dev, chip);
chip->spi_dev = spi_dev;
- chip->name = spi_dev->modalias;
for (i = 0; i <= AD7816_CS_MAX; i++)
chip->oti_data[i] = 203;
chip->rdwr_pin = pins[0];
chip->convert_pin = pins[1];
chip->busy_pin = pins[2];
- ret = gpio_request(chip->rdwr_pin, chip->name);
+ ret = gpio_request(chip->rdwr_pin, spi_get_device_id(spi_dev)->name);
if (ret) {
dev_err(&spi_dev->dev, "Fail to request rdwr gpio PIN %d.\n",
chip->rdwr_pin);
goto error_free_chip;
}
gpio_direction_input(chip->rdwr_pin);
- ret = gpio_request(chip->convert_pin, chip->name);
+ ret = gpio_request(chip->convert_pin, spi_get_device_id(spi_dev)->name);
if (ret) {
dev_err(&spi_dev->dev, "Fail to request convert gpio PIN %d.\n",
chip->convert_pin);
goto error_free_gpio_rdwr;
}
gpio_direction_input(chip->convert_pin);
- ret = gpio_request(chip->busy_pin, chip->name);
+ ret = gpio_request(chip->busy_pin, spi_get_device_id(spi_dev)->name);
if (ret) {
dev_err(&spi_dev->dev, "Fail to request busy gpio PIN %d.\n",
chip->busy_pin);
@@ -418,18 +391,15 @@ static int __devinit ad7816_probe(struct spi_device *spi_dev)
}
gpio_direction_input(chip->busy_pin);
- chip->indio_dev = iio_allocate_device();
+ chip->indio_dev = iio_allocate_device(0);
if (chip->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_gpio;
}
-
+ chip->indio_dev->name = spi_get_device_id(spi_dev)->name;
chip->indio_dev->dev.parent = &spi_dev->dev;
- chip->indio_dev->attrs = &ad7816_attribute_group;
- chip->indio_dev->event_attrs = &ad7816_event_attribute_group;
+ chip->indio_dev->info = &ad7816_info;
chip->indio_dev->dev_data = (void *)chip;
- chip->indio_dev->driver_module = THIS_MODULE;
- chip->indio_dev->num_interrupt_lines = 1;
chip->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(chip->indio_dev);
@@ -438,27 +408,18 @@ static int __devinit ad7816_probe(struct spi_device *spi_dev)
if (spi_dev->irq) {
/* Only low trigger is supported in ad7816/7/8 */
- ret = iio_register_interrupt_line(spi_dev->irq,
- chip->indio_dev,
- 0,
- IRQF_TRIGGER_LOW,
- chip->name);
+ ret = request_threaded_irq(spi_dev->irq,
+ NULL,
+ &ad7816_event_handler,
+ IRQF_TRIGGER_LOW,
+ chip->indio_dev->name,
+ chip->indio_dev);
if (ret)
goto error_unreg_dev;
-
- /*
- * The event handler list element refer to iio_event_ad7816.
- * All event attributes bind to the same event handler.
- * So, only register event handler once.
- */
- iio_add_event_to_list(&iio_event_ad7816,
- &chip->indio_dev->interrupts[0]->ev_list);
-
- INIT_WORK(&chip->thresh_work, ad7816_interrupt_bh);
}
dev_info(&spi_dev->dev, "%s temperature sensor and ADC registered.\n",
- chip->name);
+ chip->indio_dev->name);
return 0;
@@ -485,7 +446,7 @@ static int __devexit ad7816_remove(struct spi_device *spi_dev)
dev_set_drvdata(&spi_dev->dev, NULL);
if (spi_dev->irq)
- iio_unregister_interrupt_line(indio_dev, 0);
+ free_irq(spi_dev->irq, indio_dev);
iio_device_unregister(indio_dev);
iio_free_device(chip->indio_dev);
gpio_free(chip->busy_pin);
diff --git a/drivers/staging/iio/adc/ad7887.h b/drivers/staging/iio/adc/ad7887.h
index 439c802b38f2..837046c7b894 100644
--- a/drivers/staging/iio/adc/ad7887.h
+++ b/drivers/staging/iio/adc/ad7887.h
@@ -48,24 +48,23 @@ struct ad7887_platform_data {
bool use_onchip_ref;
};
+/**
+ * struct ad7887_chip_info - chip specifc information
+ * @int_vref_mv: the internal reference voltage
+ * @channel: channel specification
+ */
+
struct ad7887_chip_info {
- u8 bits; /* number of ADC bits */
- u8 storagebits; /* number of bits read from the ADC */
- u8 left_shift; /* number of bits the sample must be shifted */
- char sign; /* [s]igned or [u]nsigned */
- u16 int_vref_mv; /* internal reference voltage */
+ u16 int_vref_mv;
+ struct iio_chan_spec channel[3];
};
struct ad7887_state {
- struct iio_dev *indio_dev;
struct spi_device *spi;
const struct ad7887_chip_info *chip_info;
struct regulator *reg;
- struct work_struct poll_work;
- atomic_t protect_ring;
size_t d_size;
u16 int_vref_mv;
- bool en_dual;
struct spi_transfer xfer[4];
struct spi_message msg[3];
struct spi_message *ring_msg;
diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c
index 5d85efab658c..de14b174cef7 100644
--- a/drivers/staging/iio/adc/ad7887_core.c
+++ b/drivers/staging/iio/adc/ad7887_core.c
@@ -1,18 +1,15 @@
/*
* AD7887 SPI ADC driver
*
- * Copyright 2010 Analog Devices Inc.
+ * Copyright 2010-2011 Analog Devices Inc.
*
- * Licensed under the GPL-2 or later.
+ * Licensed under the GPL-2.
*/
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
-#include <linux/list.h>
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
@@ -33,108 +30,75 @@ static int ad7887_scan_direct(struct ad7887_state *st, unsigned ch)
return (st->data[(ch * 2)] << 8) | st->data[(ch * 2) + 1];
}
-static ssize_t ad7887_scan(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int ad7887_read_raw(struct iio_dev *dev_info,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7887_state *st = dev_info->dev_data;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
+ struct ad7887_state *st = dev_info->dev_data;
+ unsigned int scale_uv;
- mutex_lock(&dev_info->mlock);
- if (iio_ring_enabled(dev_info))
- ret = ad7887_scan_from_ring(st, 1 << this_attr->address);
- else
- ret = ad7887_scan_direct(st, this_attr->address);
- mutex_unlock(&dev_info->mlock);
-
- if (ret < 0)
- return ret;
-
- return sprintf(buf, "%d\n", (ret >> st->chip_info->left_shift) &
- RES_MASK(st->chip_info->bits));
-}
-static IIO_DEV_ATTR_IN_RAW(0, ad7887_scan, 0);
-static IIO_DEV_ATTR_IN_RAW(1, ad7887_scan, 1);
-
-static ssize_t ad7887_show_scale(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- /* Driver currently only support internal vref */
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7887_state *st = iio_dev_get_devdata(dev_info);
- /* Corresponds to Vref / 2^(bits) */
- unsigned int scale_uv = (st->int_vref_mv * 1000) >> st->chip_info->bits;
-
- return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
-}
-static IIO_DEVICE_ATTR(in_scale, S_IRUGO, ad7887_show_scale, NULL, 0);
-
-static ssize_t ad7887_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad7887_state *st = iio_dev_get_devdata(dev_info);
-
- return sprintf(buf, "%s\n", spi_get_device_id(st->spi)->name);
-}
-static IIO_DEVICE_ATTR(name, S_IRUGO, ad7887_show_name, NULL, 0);
-
-static struct attribute *ad7887_attributes[] = {
- &iio_dev_attr_in0_raw.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_dev_attr_in_scale.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
- NULL,
-};
-
-static mode_t ad7887_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 ad7887_state *st = iio_dev_get_devdata(dev_info);
-
- mode_t mode = attr->mode;
-
- if ((attr == &iio_dev_attr_in1_raw.dev_attr.attr) && !st->en_dual)
- mode = 0;
-
- return mode;
+ switch (m) {
+ case 0:
+ mutex_lock(&dev_info->mlock);
+ if (iio_ring_enabled(dev_info))
+ ret = ad7887_scan_from_ring(st, 1 << chan->address);
+ else
+ ret = ad7887_scan_direct(st, chan->address);
+ mutex_unlock(&dev_info->mlock);
+
+ if (ret < 0)
+ return ret;
+ *val = (ret >> st->chip_info->channel[0].scan_type.shift) &
+ RES_MASK(st->chip_info->channel[0].scan_type.realbits);
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ scale_uv = (st->int_vref_mv * 1000)
+ >> st->chip_info->channel[0].scan_type.realbits;
+ *val = scale_uv/1000;
+ *val2 = (scale_uv%1000)*1000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+ return -EINVAL;
}
-static const struct attribute_group ad7887_attribute_group = {
- .attrs = ad7887_attributes,
- .is_visible = ad7887_attr_is_visible,
-};
static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
/*
* More devices added in future
*/
[ID_AD7887] = {
- .bits = 12,
- .storagebits = 16,
- .left_shift = 0,
- .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 1, 1, IIO_ST('u', 12, 16, 0), 0),
+
+ .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 12, 16, 0), 0),
+
+ .channel[2] = IIO_CHAN_SOFT_TIMESTAMP(2),
.int_vref_mv = 2500,
},
};
+static const struct iio_info ad7887_info = {
+ .read_raw = &ad7887_read_raw,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit ad7887_probe(struct spi_device *spi)
{
struct ad7887_platform_data *pdata = spi->dev.platform_data;
struct ad7887_state *st;
- int ret, voltage_uv = 0;
+ int ret, voltage_uv = 0, regdone = 0;
+ struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
- st = kzalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
st->reg = regulator_get(&spi->dev, "vcc");
if (!IS_ERR(st->reg)) {
@@ -148,23 +112,15 @@ static int __devinit ad7887_probe(struct spi_device *spi)
st->chip_info =
&ad7887_chip_info_tbl[spi_get_device_id(spi)->driver_data];
- spi_set_drvdata(spi, st);
-
- atomic_set(&st->protect_ring, 0);
+ spi_set_drvdata(spi, indio_dev);
st->spi = spi;
- st->indio_dev = iio_allocate_device();
- if (st->indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_disable_reg;
- }
-
/* Estabilish that the iio_dev is a child of the spi device */
- st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->attrs = &ad7887_attribute_group;
- st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
- st->indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->dev_data = (void *)(st);
+ indio_dev->info = &ad7887_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
/* Setup default message */
@@ -208,8 +164,6 @@ static int __devinit ad7887_probe(struct spi_device *spi)
spi_message_init(&st->msg[AD7887_CH1]);
spi_message_add_tail(&st->xfer[3], &st->msg[AD7887_CH1]);
- st->en_dual = true;
-
if (pdata && pdata->vref_mv)
st->int_vref_mv = pdata->vref_mv;
else if (voltage_uv)
@@ -217,6 +171,8 @@ static int __devinit ad7887_probe(struct spi_device *spi)
else
dev_warn(&spi->dev, "reference voltage unspecified\n");
+ indio_dev->channels = st->chip_info->channel;
+ indio_dev->num_channels = 3;
} else {
if (pdata && pdata->vref_mv)
st->int_vref_mv = pdata->vref_mv;
@@ -224,50 +180,56 @@ static int __devinit ad7887_probe(struct spi_device *spi)
st->int_vref_mv = st->chip_info->int_vref_mv;
else
dev_warn(&spi->dev, "reference voltage unspecified\n");
- }
+ indio_dev->channels = &st->chip_info->channel[1];
+ indio_dev->num_channels = 2;
+ }
- ret = ad7887_register_ring_funcs_and_init(st->indio_dev);
+ ret = ad7887_register_ring_funcs_and_init(indio_dev);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
- ret = iio_device_register(st->indio_dev);
+ ret = iio_device_register(indio_dev);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
+ regdone = 1;
- ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
+ ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
+ indio_dev->channels,
+ indio_dev->num_channels);
if (ret)
goto error_cleanup_ring;
return 0;
error_cleanup_ring:
- ad7887_ring_cleanup(st->indio_dev);
- iio_device_unregister(st->indio_dev);
-error_free_device:
- iio_free_device(st->indio_dev);
+ ad7887_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);
- kfree(st);
-error_ret:
+ if (regdone)
+ iio_device_unregister(indio_dev);
+ else
+ iio_free_device(indio_dev);
+
return ret;
}
static int ad7887_remove(struct spi_device *spi)
{
- struct ad7887_state *st = spi_get_drvdata(spi);
- struct iio_dev *indio_dev = st->indio_dev;
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct ad7887_state *st = iio_priv(indio_dev);
+
iio_ring_buffer_unregister(indio_dev->ring);
ad7887_ring_cleanup(indio_dev);
- iio_device_unregister(indio_dev);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);
regulator_put(st->reg);
}
- kfree(st);
+ iio_device_unregister(indio_dev);
+
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c
index da77f266c16b..0e4a5f4fd892 100644
--- a/drivers/staging/iio/adc/ad7887_ring.c
+++ b/drivers/staging/iio/adc/ad7887_ring.c
@@ -1,20 +1,17 @@
/*
- * Copyright 2010 Analog Devices Inc.
+ * Copyright 2010-2011 Analog Devices Inc.
* Copyright (C) 2008 Jonathan Cameron
*
- * Licensed under the GPL-2 or later.
+ * Licensed under the GPL-2.
*
* ad7887_ring.c
*/
#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
-#include <linux/list.h>
#include <linux/spi/spi.h>
#include "../iio.h"
@@ -25,64 +22,9 @@
#include "ad7887.h"
-static IIO_SCAN_EL_C(in0, 0, 0, NULL);
-static IIO_SCAN_EL_C(in1, 1, 0, NULL);
-static IIO_SCAN_EL_TIMESTAMP(2);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
-
-static ssize_t ad7887_show_type(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_ring_buffer *ring = dev_get_drvdata(dev);
- struct iio_dev *indio_dev = ring->indio_dev;
- struct ad7887_state *st = indio_dev->dev_data;
-
- return sprintf(buf, "%c%d/%d>>%d\n", st->chip_info->sign,
- st->chip_info->bits, st->chip_info->storagebits,
- st->chip_info->left_shift);
-}
-static IIO_DEVICE_ATTR(in_type, S_IRUGO, ad7887_show_type, NULL, 0);
-
-static struct attribute *ad7887_scan_el_attrs[] = {
- &iio_scan_el_in0.dev_attr.attr,
- &iio_const_attr_in0_index.dev_attr.attr,
- &iio_scan_el_in1.dev_attr.attr,
- &iio_const_attr_in1_index.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- &iio_dev_attr_in_type.dev_attr.attr,
- NULL,
-};
-
-static mode_t ad7887_scan_el_attr_is_visible(struct kobject *kobj,
- struct attribute *attr, int n)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct iio_ring_buffer *ring = dev_get_drvdata(dev);
- struct iio_dev *indio_dev = ring->indio_dev;
- struct ad7887_state *st = indio_dev->dev_data;
-
- mode_t mode = attr->mode;
-
- if ((attr == &iio_scan_el_in1.dev_attr.attr) ||
- (attr == &iio_const_attr_in1_index.dev_attr.attr))
- if (!st->en_dual)
- mode = 0;
-
- return mode;
-}
-
-static struct attribute_group ad7887_scan_el_group = {
- .name = "scan_elements",
- .attrs = ad7887_scan_el_attrs,
- .is_visible = ad7887_scan_el_attr_is_visible,
-};
-
int ad7887_scan_from_ring(struct ad7887_state *st, long mask)
{
- struct iio_ring_buffer *ring = st->indio_dev->ring;
+ struct iio_ring_buffer *ring = iio_priv_to_dev(st)->ring;
int count = 0, ret;
u16 *ring_data;
@@ -91,12 +33,13 @@ int ad7887_scan_from_ring(struct ad7887_state *st, long mask)
goto error_ret;
}
- ring_data = kmalloc(ring->access.get_bytes_per_datum(ring), GFP_KERNEL);
+ ring_data = kmalloc(ring->access->get_bytes_per_datum(ring),
+ GFP_KERNEL);
if (ring_data == NULL) {
ret = -ENOMEM;
goto error_ret;
}
- ret = ring->access.read_last(ring, (u8 *) ring_data);
+ ret = ring->access->read_last(ring, (u8 *) ring_data);
if (ret)
goto error_free_ring_data;
@@ -124,7 +67,8 @@ static int ad7887_ring_preenable(struct iio_dev *indio_dev)
struct ad7887_state *st = indio_dev->dev_data;
struct iio_ring_buffer *ring = indio_dev->ring;
- st->d_size = ring->scan_count * st->chip_info->storagebits / 8;
+ st->d_size = ring->scan_count *
+ st->chip_info->channel[0].scan_type.storagebits / 8;
if (ring->scan_timestamp) {
st->d_size += sizeof(s64);
@@ -133,8 +77,8 @@ static int ad7887_ring_preenable(struct iio_dev *indio_dev)
st->d_size += sizeof(s64) - (st->d_size % sizeof(s64));
}
- if (indio_dev->ring->access.set_bytes_per_datum)
- indio_dev->ring->access.set_bytes_per_datum(indio_dev->ring,
+ if (indio_dev->ring->access->set_bytes_per_datum)
+ indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring,
st->d_size);
switch (ring->scan_mask) {
@@ -163,48 +107,27 @@ static int ad7887_ring_postdisable(struct iio_dev *indio_dev)
}
/**
- * ad7887_poll_func_th() th of trigger launched polling to ring buffer
- *
- * As sampling only occurs on spi comms occurring, leave timestamping until
- * then. Some triggers will generate their own time stamp. Currently
- * there is no way of notifying them when no one cares.
- **/
-static void ad7887_poll_func_th(struct iio_dev *indio_dev, s64 time)
-{
- struct ad7887_state *st = indio_dev->dev_data;
-
- schedule_work(&st->poll_work);
- return;
-}
-/**
- * ad7887_poll_bh_to_ring() bh of trigger launched polling to ring buffer
- * @work_s: the work struct through which this was scheduled
+ * ad7887_trigger_handler() bh of trigger launched polling to ring buffer
*
* Currently there is no option in this driver to disable the saving of
* timestamps within the ring.
- * I think the one copy of this at a time was to avoid problems if the
- * trigger was set far too high and the reads then locked up the computer.
**/
-static void ad7887_poll_bh_to_ring(struct work_struct *work_s)
+static irqreturn_t ad7887_trigger_handler(int irq, void *p)
{
- struct ad7887_state *st = container_of(work_s, struct ad7887_state,
- poll_work);
- struct iio_dev *indio_dev = st->indio_dev;
- struct iio_sw_ring_buffer *sw_ring = iio_to_sw_ring(indio_dev->ring);
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->private_data;
+ struct ad7887_state *st = iio_dev_get_devdata(indio_dev);
struct iio_ring_buffer *ring = indio_dev->ring;
s64 time_ns;
__u8 *buf;
int b_sent;
- unsigned int bytes = ring->scan_count * st->chip_info->storagebits / 8;
-
- /* Ensure only one copy of this function running at a time */
- if (atomic_inc_return(&st->protect_ring) > 1)
- return;
+ unsigned int bytes = ring->scan_count *
+ st->chip_info->channel[0].scan_type.storagebits / 8;
buf = kzalloc(st->d_size, GFP_KERNEL);
if (buf == NULL)
- return;
+ return -ENOMEM;
b_sent = spi_sync(st->spi, st->ring_msg);
if (b_sent)
@@ -215,17 +138,25 @@ static void ad7887_poll_bh_to_ring(struct work_struct *work_s)
memcpy(buf, st->data, bytes);
if (ring->scan_timestamp)
memcpy(buf + st->d_size - sizeof(s64),
- &time_ns, sizeof(time_ns));
+ &time_ns, sizeof(time_ns));
- indio_dev->ring->access.store_to(&sw_ring->buf, buf, time_ns);
+ indio_dev->ring->access->store_to(indio_dev->ring, buf, time_ns);
done:
kfree(buf);
- atomic_dec(&st->protect_ring);
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
}
+static const struct iio_ring_setup_ops ad7887_ring_setup_ops = {
+ .preenable = &ad7887_ring_preenable,
+ .postenable = &iio_triggered_ring_postenable,
+ .predisable = &iio_triggered_ring_predisable,
+ .postdisable = &ad7887_ring_postdisable,
+};
+
int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev)
{
- struct ad7887_state *st = indio_dev->dev_data;
int ret;
indio_dev->ring = iio_sw_rb_allocate(indio_dev);
@@ -234,25 +165,24 @@ int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev)
goto error_ret;
}
/* Effectively select the ring buffer implementation */
- iio_ring_sw_register_funcs(&indio_dev->ring->access);
- ret = iio_alloc_pollfunc(indio_dev, NULL, &ad7887_poll_func_th);
- if (ret)
+ indio_dev->ring->access = &ring_sw_access_funcs;
+ indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
+ &ad7887_trigger_handler,
+ IRQF_ONESHOT,
+ indio_dev,
+ "ad7887_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->preenable = &ad7887_ring_preenable;
- indio_dev->ring->postenable = &iio_triggered_ring_postenable;
- indio_dev->ring->predisable = &iio_triggered_ring_predisable;
- indio_dev->ring->postdisable = &ad7887_ring_postdisable;
- indio_dev->ring->scan_el_attrs = &ad7887_scan_el_group;
- indio_dev->ring->scan_timestamp = true;
-
- INIT_WORK(&st->poll_work, &ad7887_poll_bh_to_ring);
+ indio_dev->ring->setup_ops = &ad7887_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:
@@ -267,6 +197,6 @@ void ad7887_ring_cleanup(struct iio_dev *indio_dev)
iio_trigger_dettach_poll_func(indio_dev->trig,
indio_dev->pollfunc);
}
- kfree(indio_dev->pollfunc);
+ iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
diff --git a/drivers/staging/iio/adc/ad799x.h b/drivers/staging/iio/adc/ad799x.h
index a421362c77f9..0dc9b4c73a33 100644
--- a/drivers/staging/iio/adc/ad799x.h
+++ b/drivers/staging/iio/adc/ad799x.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Michael Hennerich, Analog Devices Inc.
+ * Copyright (C) 2010-2011 Michael Hennerich, Analog Devices Inc.
* Copyright (C) 2008-2010 Jonathan Cameron
*
* This program is free software; you can redistribute it and/or modify
@@ -67,6 +67,8 @@
#define AD7997_8_READ_SINGLE 0x80
#define AD7997_8_READ_SEQUENCE 0x70
+/* TODO: move this into a common header */
+#define RES_MASK(bits) ((1 << (bits)) - 1)
enum {
ad7991,
@@ -83,43 +85,28 @@ struct ad799x_state;
/**
* struct ad799x_chip_info - chip specifc information
- * @num_inputs: number of physical inputs on chip
- * @bits: accuracy of the adc in bits
+ * @channel: channel specification
+ * @num_channels: number of channels
* @int_vref_mv: the internal reference voltage
* @monitor_mode: whether the chip supports monitor interrupts
* @default_config: device default configuration
- * @dev_attrs: pointer to the device attribute group
- * @scan_attrs: pointer to the scan element attribute group
* @event_attrs: pointer to the monitor event attribute group
- * @ad799x_set_scan_mode: function pointer to the device specific mode function
-
*/
+
struct ad799x_chip_info {
- u8 num_inputs;
- u8 bits;
- u8 storagebits;
- char sign;
+ struct iio_chan_spec channel[9];
+ int num_channels;
u16 int_vref_mv;
- bool monitor_mode;
u16 default_config;
- struct attribute_group *dev_attrs;
- struct attribute_group *scan_attrs;
- struct attribute_group *event_attrs;
- int (*ad799x_set_scan_mode) (struct ad799x_state *st,
- unsigned mask);
+ const struct iio_info *info;
};
struct ad799x_state {
- struct iio_dev *indio_dev;
struct i2c_client *client;
const struct ad799x_chip_info *chip_info;
- struct work_struct poll_work;
- struct work_struct work_thresh;
- atomic_t protect_ring;
size_t d_size;
struct iio_trigger *trig;
struct regulator *reg;
- s64 last_timestamp;
u16 int_vref_mv;
unsigned id;
char *name;
@@ -134,7 +121,7 @@ struct ad799x_platform_data {
u16 vref_mv;
};
-int ad799x_set_scan_mode(struct ad799x_state *st, unsigned mask);
+int ad7997_8_set_scan_mode(struct ad799x_state *st, unsigned mask);
#ifdef CONFIG_AD799X_RING_BUFFER
int ad799x_single_channel_from_ring(struct ad799x_state *st, long mask);
diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c
index f04e642e7272..29bfbcf82064 100644
--- a/drivers/staging/iio/adc/ad799x_core.c
+++ b/drivers/staging/iio/adc/ad799x_core.c
@@ -1,6 +1,6 @@
/*
* iio/adc/ad799x.c
- * Copyright (C) 2010 Michael Hennerich, Analog Devices Inc.
+ * Copyright (C) 2010-1011 Michael Hennerich, Analog Devices Inc.
*
* based on iio/adc/max1363
* Copyright (C) 2008-2010 Jonathan Cameron
@@ -23,11 +23,9 @@
*/
#include <linux/interrupt.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/sysfs.h>
-#include <linux/list.h>
#include <linux/i2c.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
@@ -100,130 +98,77 @@ static int ad799x_i2c_write8(struct ad799x_state *st, u8 reg, u8 data)
return ret;
}
-static int ad799x_scan_el_set_state(struct iio_scan_el *scan_el,
- struct iio_dev *indio_dev,
- bool state)
-{
- struct ad799x_state *st = indio_dev->dev_data;
- return ad799x_set_scan_mode(st, st->indio_dev->ring->scan_mask);
-}
-
-/* Here we claim all are 16 bits. This currently does no harm and saves
- * us a lot of scan element listings */
-
-#define AD799X_SCAN_EL(number) \
- IIO_SCAN_EL_C(in##number, number, 0, ad799x_scan_el_set_state);
-
-static AD799X_SCAN_EL(0);
-static AD799X_SCAN_EL(1);
-static AD799X_SCAN_EL(2);
-static AD799X_SCAN_EL(3);
-static AD799X_SCAN_EL(4);
-static AD799X_SCAN_EL(5);
-static AD799X_SCAN_EL(6);
-static AD799X_SCAN_EL(7);
-
-static IIO_SCAN_EL_TIMESTAMP(8);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64)
-
-static ssize_t ad799x_show_type(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_ring_buffer *ring = dev_get_drvdata(dev);
- struct iio_dev *indio_dev = ring->indio_dev;
- struct ad799x_state *st = indio_dev->dev_data;
-
- return sprintf(buf, "%c%d/%d\n", st->chip_info->sign,
- st->chip_info->bits, AD799X_STORAGEBITS);
-}
-static IIO_DEVICE_ATTR(in_type, S_IRUGO, ad799x_show_type, NULL, 0);
-
-static int ad7991_5_9_set_scan_mode(struct ad799x_state *st, unsigned mask)
-{
- return i2c_smbus_write_byte(st->client,
- st->config | (mask << AD799X_CHANNEL_SHIFT));
-}
-
-static int ad7992_3_4_set_scan_mode(struct ad799x_state *st, unsigned mask)
-{
- return ad799x_i2c_write8(st, AD7998_CONF_REG,
- st->config | (mask << AD799X_CHANNEL_SHIFT));
-}
-
-static int ad7997_8_set_scan_mode(struct ad799x_state *st, unsigned mask)
+int ad7997_8_set_scan_mode(struct ad799x_state *st, unsigned mask)
{
return ad799x_i2c_write16(st, AD7998_CONF_REG,
st->config | (mask << AD799X_CHANNEL_SHIFT));
}
-int ad799x_set_scan_mode(struct ad799x_state *st, unsigned mask)
+static int ad799x_scan_direct(struct ad799x_state *st, unsigned ch)
{
+ u16 rxbuf;
+ u8 cmd;
int ret;
- if (st->chip_info->ad799x_set_scan_mode != NULL) {
- ret = st->chip_info->ad799x_set_scan_mode(st, mask);
- return (ret > 0) ? 0 : ret;
+ switch (st->id) {
+ case ad7991:
+ case ad7995:
+ case ad7999:
+ cmd = st->config | ((1 << ch) << AD799X_CHANNEL_SHIFT);
+ break;
+ case ad7992:
+ case ad7993:
+ case ad7994:
+ cmd = (1 << ch) << AD799X_CHANNEL_SHIFT;
+ break;
+ case ad7997:
+ case ad7998:
+ cmd = (ch << AD799X_CHANNEL_SHIFT) | AD7997_8_READ_SINGLE;
+ break;
+ default:
+ return -EINVAL;
}
- return 0;
+ ret = ad799x_i2c_read16(st, cmd, &rxbuf);
+ if (ret < 0)
+ return ret;
+
+ return rxbuf;
}
-static ssize_t ad799x_read_single_channel(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int ad799x_read_raw(struct iio_dev *dev_info,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad799x_state *st = iio_dev_get_devdata(dev_info);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int ret = 0, len = 0;
- u32 data ;
- u16 rxbuf[1];
- u8 cmd;
- long mask;
+ int ret;
+ struct ad799x_state *st = dev_info->dev_data;
+ unsigned int scale_uv;
+
+ switch (m) {
+ case 0:
+ mutex_lock(&dev_info->mlock);
+ if (iio_ring_enabled(dev_info))
+ ret = ad799x_single_channel_from_ring(st,
+ 1 << chan->address);
+ else
+ ret = ad799x_scan_direct(st, chan->address);
+ mutex_unlock(&dev_info->mlock);
- mutex_lock(&dev_info->mlock);
- mask = 1 << this_attr->address;
- /* If ring buffer capture is occurring, query the buffer */
- if (iio_ring_enabled(dev_info)) {
- data = ret = ad799x_single_channel_from_ring(st, mask);
if (ret < 0)
- goto error_ret;
- ret = 0;
- } else {
- switch (st->id) {
- case ad7991:
- case ad7995:
- case ad7999:
- cmd = st->config | (mask << AD799X_CHANNEL_SHIFT);
- break;
- case ad7992:
- case ad7993:
- case ad7994:
- cmd = mask << AD799X_CHANNEL_SHIFT;
- break;
- case ad7997:
- case ad7998:
- cmd = (this_attr->address <<
- AD799X_CHANNEL_SHIFT) | AD7997_8_READ_SINGLE;
- break;
- default:
- cmd = 0;
-
- }
- ret = ad799x_i2c_read16(st, cmd, rxbuf);
- if (ret < 0)
- goto error_ret;
-
- data = rxbuf[0];
+ return ret;
+ *val = (ret >> st->chip_info->channel[0].scan_type.shift) &
+ RES_MASK(st->chip_info->channel[0].scan_type.realbits);
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ scale_uv = (st->int_vref_mv * 1000)
+ >> st->chip_info->channel[0].scan_type.realbits;
+ *val = scale_uv / 1000;
+ *val2 = (scale_uv % 1000) * 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
}
-
- /* Pretty print the result */
- len = sprintf(buf, "%u\n", data & ((1 << (st->chip_info->bits)) - 1));
-
-error_ret:
- mutex_unlock(&dev_info->mlock);
- return ret ? ret : len;
+ return -EINVAL;
}
static ssize_t ad799x_read_frequency(struct device *dev,
@@ -331,18 +276,17 @@ error_ret_mutex:
return ret ? ret : len;
}
-
static ssize_t ad799x_read_channel_config(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
struct ad799x_state *st = iio_dev_get_devdata(dev_info);
- struct iio_event_attr *this_attr = to_iio_event_attr(attr);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
u16 val;
- ret = ad799x_i2c_read16(st, this_attr->mask, &val);
+ ret = ad799x_i2c_read16(st, this_attr->address, &val);
if (ret)
return ret;
@@ -356,7 +300,7 @@ static ssize_t ad799x_write_channel_config(struct device *dev,
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
struct ad799x_state *st = iio_dev_get_devdata(dev_info);
- struct iio_event_attr *this_attr = to_iio_event_attr(attr);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
long val;
int ret;
@@ -366,273 +310,111 @@ static ssize_t ad799x_write_channel_config(struct device *dev,
return ret;
mutex_lock(&dev_info->mlock);
- ret = ad799x_i2c_write16(st, this_attr->mask, val);
+ ret = ad799x_i2c_write16(st, this_attr->address, val);
mutex_unlock(&dev_info->mlock);
return ret ? ret : len;
}
-static void ad799x_interrupt_bh(struct work_struct *work_s)
+static irqreturn_t ad799x_event_handler(int irq, void *private)
{
- struct ad799x_state *st = container_of(work_s,
- struct ad799x_state, work_thresh);
+ struct iio_dev *indio_dev = private;
+ struct ad799x_state *st = iio_dev_get_devdata(private);
u8 status;
- int i;
+ int i, ret;
- if (ad799x_i2c_read8(st, AD7998_ALERT_STAT_REG, &status))
- goto err_out;
+ ret = ad799x_i2c_read8(st, AD7998_ALERT_STAT_REG, &status);
+ if (ret)
+ return ret;
if (!status)
- goto err_out;
+ return -EIO;
ad799x_i2c_write8(st, AD7998_ALERT_STAT_REG, AD7998_ALERT_STAT_CLEAR);
for (i = 0; i < 8; i++) {
if (status & (1 << i))
- iio_push_event(st->indio_dev, 0,
- i & 0x1 ?
- IIO_EVENT_CODE_IN_HIGH_THRESH(i >> 1) :
- IIO_EVENT_CODE_IN_LOW_THRESH(i >> 1),
- st->last_timestamp);
+ 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_get_time_ns());
}
-err_out:
- enable_irq(st->client->irq);
-}
-
-static int ad799x_interrupt(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct ad799x_state *st = dev_info->dev_data;
-
- st->last_timestamp = timestamp;
- schedule_work(&st->work_thresh);
- return 0;
-}
-
-IIO_EVENT_SH(ad799x, &ad799x_interrupt);
-
-/* Direct read attribtues */
-static IIO_DEV_ATTR_IN_RAW(0, ad799x_read_single_channel, 0);
-static IIO_DEV_ATTR_IN_RAW(1, ad799x_read_single_channel, 1);
-static IIO_DEV_ATTR_IN_RAW(2, ad799x_read_single_channel, 2);
-static IIO_DEV_ATTR_IN_RAW(3, ad799x_read_single_channel, 3);
-static IIO_DEV_ATTR_IN_RAW(4, ad799x_read_single_channel, 4);
-static IIO_DEV_ATTR_IN_RAW(5, ad799x_read_single_channel, 5);
-static IIO_DEV_ATTR_IN_RAW(6, ad799x_read_single_channel, 6);
-static IIO_DEV_ATTR_IN_RAW(7, ad799x_read_single_channel, 7);
-
-static ssize_t ad799x_show_scale(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- /* Driver currently only support internal vref */
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad799x_state *st = iio_dev_get_devdata(dev_info);
-
- /* Corresponds to Vref / 2^(bits) */
- unsigned int scale_uv = (st->int_vref_mv * 1000) >> st->chip_info->bits;
-
- return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
-}
-
-static IIO_DEVICE_ATTR(in_scale, S_IRUGO, ad799x_show_scale, NULL, 0);
-
-static ssize_t ad799x_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad799x_state *st = iio_dev_get_devdata(dev_info);
- return sprintf(buf, "%s\n", st->client->name);
+ return IRQ_HANDLED;
}
-static IIO_DEVICE_ATTR(name, S_IRUGO, ad799x_show_name, NULL, 0);
-
-static struct attribute *ad7991_5_9_3_4_device_attrs[] = {
- &iio_dev_attr_in0_raw.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_dev_attr_in2_raw.dev_attr.attr,
- &iio_dev_attr_in3_raw.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
- &iio_dev_attr_in_scale.dev_attr.attr,
- NULL
-};
-
-static struct attribute_group ad7991_5_9_3_4_dev_attr_group = {
- .attrs = ad7991_5_9_3_4_device_attrs,
-};
-
-static struct attribute *ad7991_5_9_3_4_scan_el_attrs[] = {
- &iio_scan_el_in0.dev_attr.attr,
- &iio_const_attr_in0_index.dev_attr.attr,
- &iio_scan_el_in1.dev_attr.attr,
- &iio_const_attr_in1_index.dev_attr.attr,
- &iio_scan_el_in2.dev_attr.attr,
- &iio_const_attr_in2_index.dev_attr.attr,
- &iio_scan_el_in3.dev_attr.attr,
- &iio_const_attr_in3_index.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- &iio_dev_attr_in_type.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group ad7991_5_9_3_4_scan_el_group = {
- .name = "scan_elements",
- .attrs = ad7991_5_9_3_4_scan_el_attrs,
-};
-
-static struct attribute *ad7992_device_attrs[] = {
- &iio_dev_attr_in0_raw.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
- &iio_dev_attr_in_scale.dev_attr.attr,
- NULL
-};
-
-static struct attribute_group ad7992_dev_attr_group = {
- .attrs = ad7992_device_attrs,
-};
-
-static struct attribute *ad7992_scan_el_attrs[] = {
- &iio_scan_el_in0.dev_attr.attr,
- &iio_const_attr_in0_index.dev_attr.attr,
- &iio_scan_el_in1.dev_attr.attr,
- &iio_const_attr_in1_index.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- &iio_dev_attr_in_type.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group ad7992_scan_el_group = {
- .name = "scan_elements",
- .attrs = ad7992_scan_el_attrs,
-};
-
-static struct attribute *ad7997_8_device_attrs[] = {
- &iio_dev_attr_in0_raw.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_dev_attr_in2_raw.dev_attr.attr,
- &iio_dev_attr_in3_raw.dev_attr.attr,
- &iio_dev_attr_in4_raw.dev_attr.attr,
- &iio_dev_attr_in5_raw.dev_attr.attr,
- &iio_dev_attr_in6_raw.dev_attr.attr,
- &iio_dev_attr_in7_raw.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
- &iio_dev_attr_in_scale.dev_attr.attr,
- NULL
-};
-
-static struct attribute_group ad7997_8_dev_attr_group = {
- .attrs = ad7997_8_device_attrs,
-};
-
-static struct attribute *ad7997_8_scan_el_attrs[] = {
- &iio_scan_el_in0.dev_attr.attr,
- &iio_const_attr_in0_index.dev_attr.attr,
- &iio_scan_el_in1.dev_attr.attr,
- &iio_const_attr_in1_index.dev_attr.attr,
- &iio_scan_el_in2.dev_attr.attr,
- &iio_const_attr_in2_index.dev_attr.attr,
- &iio_scan_el_in3.dev_attr.attr,
- &iio_const_attr_in3_index.dev_attr.attr,
- &iio_scan_el_in4.dev_attr.attr,
- &iio_const_attr_in4_index.dev_attr.attr,
- &iio_scan_el_in5.dev_attr.attr,
- &iio_const_attr_in5_index.dev_attr.attr,
- &iio_scan_el_in6.dev_attr.attr,
- &iio_const_attr_in6_index.dev_attr.attr,
- &iio_scan_el_in7.dev_attr.attr,
- &iio_const_attr_in7_index.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- &iio_dev_attr_in_type.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group ad7997_8_scan_el_group = {
- .name = "scan_elements",
- .attrs = ad7997_8_scan_el_attrs,
-};
-
-IIO_EVENT_ATTR_SH(in0_thresh_low_value,
- iio_event_ad799x,
- ad799x_read_channel_config,
- ad799x_write_channel_config,
- AD7998_DATALOW_CH1_REG);
-
-IIO_EVENT_ATTR_SH(in0_thresh_high_value,
- iio_event_ad799x,
- ad799x_read_channel_config,
- ad799x_write_channel_config,
- AD7998_DATAHIGH_CH1_REG);
-
-IIO_EVENT_ATTR_SH(in0_thresh_both_hyst_raw,
- iio_event_ad799x,
- ad799x_read_channel_config,
- ad799x_write_channel_config,
- AD7998_HYST_CH1_REG);
-
-IIO_EVENT_ATTR_SH(in1_thresh_low_value,
- iio_event_ad799x,
- ad799x_read_channel_config,
- ad799x_write_channel_config,
- AD7998_DATALOW_CH2_REG);
-
-IIO_EVENT_ATTR_SH(in1_thresh_high_value,
- iio_event_ad799x,
- ad799x_read_channel_config,
- ad799x_write_channel_config,
- AD7998_DATAHIGH_CH2_REG);
-
-IIO_EVENT_ATTR_SH(in1_thresh_both_hyst_raw,
- iio_event_ad799x,
- ad799x_read_channel_config,
- ad799x_write_channel_config,
- AD7998_HYST_CH2_REG);
-
-IIO_EVENT_ATTR_SH(in2_thresh_low_value,
- iio_event_ad799x,
- ad799x_read_channel_config,
- ad799x_write_channel_config,
- AD7998_DATALOW_CH3_REG);
-
-IIO_EVENT_ATTR_SH(in2_thresh_high_value,
- iio_event_ad799x,
- ad799x_read_channel_config,
- ad799x_write_channel_config,
- AD7998_DATAHIGH_CH3_REG);
-
-IIO_EVENT_ATTR_SH(in2_thresh_both_hyst_raw,
- iio_event_ad799x,
- ad799x_read_channel_config,
- ad799x_write_channel_config,
- AD7998_HYST_CH3_REG);
-
-IIO_EVENT_ATTR_SH(in3_thresh_low_value,
- iio_event_ad799x,
- ad799x_read_channel_config,
- ad799x_write_channel_config,
- AD7998_DATALOW_CH4_REG);
-
-IIO_EVENT_ATTR_SH(in3_thresh_high_value,
- iio_event_ad799x,
- ad799x_read_channel_config,
- ad799x_write_channel_config,
- AD7998_DATAHIGH_CH4_REG);
-
-IIO_EVENT_ATTR_SH(in3_thresh_both_hyst_raw,
- iio_event_ad799x,
- ad799x_read_channel_config,
- ad799x_write_channel_config,
- AD7998_HYST_CH4_REG);
+static IIO_DEVICE_ATTR(in0_thresh_low_value,
+ S_IRUGO | S_IWUSR,
+ ad799x_read_channel_config,
+ ad799x_write_channel_config,
+ AD7998_DATALOW_CH1_REG);
+
+static IIO_DEVICE_ATTR(in0_thresh_high_value,
+ S_IRUGO | S_IWUSR,
+ ad799x_read_channel_config,
+ ad799x_write_channel_config,
+ AD7998_DATAHIGH_CH1_REG);
+
+static IIO_DEVICE_ATTR(in0_thresh_both_hyst_raw,
+ S_IRUGO | S_IWUSR,
+ ad799x_read_channel_config,
+ ad799x_write_channel_config,
+ AD7998_HYST_CH1_REG);
+
+static IIO_DEVICE_ATTR(in1_thresh_low_value,
+ S_IRUGO | S_IWUSR,
+ ad799x_read_channel_config,
+ ad799x_write_channel_config,
+ AD7998_DATALOW_CH2_REG);
+
+static IIO_DEVICE_ATTR(in1_thresh_high_value,
+ S_IRUGO | S_IWUSR,
+ ad799x_read_channel_config,
+ ad799x_write_channel_config,
+ AD7998_DATAHIGH_CH2_REG);
+
+static IIO_DEVICE_ATTR(in1_thresh_both_hyst_raw,
+ S_IRUGO | S_IWUSR,
+ ad799x_read_channel_config,
+ ad799x_write_channel_config,
+ AD7998_HYST_CH2_REG);
+
+static IIO_DEVICE_ATTR(in2_thresh_low_value,
+ S_IRUGO | S_IWUSR,
+ ad799x_read_channel_config,
+ ad799x_write_channel_config,
+ AD7998_DATALOW_CH3_REG);
+
+static IIO_DEVICE_ATTR(in2_thresh_high_value,
+ S_IRUGO | S_IWUSR,
+ ad799x_read_channel_config,
+ ad799x_write_channel_config,
+ AD7998_DATAHIGH_CH3_REG);
+
+static IIO_DEVICE_ATTR(in2_thresh_both_hyst_raw,
+ S_IRUGO | S_IWUSR,
+ ad799x_read_channel_config,
+ ad799x_write_channel_config,
+ AD7998_HYST_CH3_REG);
+
+static IIO_DEVICE_ATTR(in3_thresh_low_value,
+ S_IRUGO | S_IWUSR,
+ ad799x_read_channel_config,
+ ad799x_write_channel_config,
+ AD7998_DATALOW_CH4_REG);
+
+static IIO_DEVICE_ATTR(in3_thresh_high_value,
+ S_IRUGO | S_IWUSR,
+ ad799x_read_channel_config,
+ ad799x_write_channel_config,
+ AD7998_DATAHIGH_CH4_REG);
+
+static IIO_DEVICE_ATTR(in3_thresh_both_hyst_raw,
+ S_IRUGO | S_IWUSR,
+ ad799x_read_channel_config,
+ ad799x_write_channel_config,
+ AD7998_HYST_CH4_REG);
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
ad799x_read_frequency,
@@ -640,18 +422,18 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("15625 7812 3906 1953 976 488 244 0");
static struct attribute *ad7993_4_7_8_event_attributes[] = {
- &iio_event_attr_in0_thresh_low_value.dev_attr.attr,
- &iio_event_attr_in0_thresh_high_value.dev_attr.attr,
- &iio_event_attr_in0_thresh_both_hyst_raw.dev_attr.attr,
- &iio_event_attr_in1_thresh_low_value.dev_attr.attr,
- &iio_event_attr_in1_thresh_high_value.dev_attr.attr,
- &iio_event_attr_in1_thresh_both_hyst_raw.dev_attr.attr,
- &iio_event_attr_in2_thresh_low_value.dev_attr.attr,
- &iio_event_attr_in2_thresh_high_value.dev_attr.attr,
- &iio_event_attr_in2_thresh_both_hyst_raw.dev_attr.attr,
- &iio_event_attr_in3_thresh_low_value.dev_attr.attr,
- &iio_event_attr_in3_thresh_high_value.dev_attr.attr,
- &iio_event_attr_in3_thresh_both_hyst_raw.dev_attr.attr,
+ &iio_dev_attr_in0_thresh_low_value.dev_attr.attr,
+ &iio_dev_attr_in0_thresh_high_value.dev_attr.attr,
+ &iio_dev_attr_in0_thresh_both_hyst_raw.dev_attr.attr,
+ &iio_dev_attr_in1_thresh_low_value.dev_attr.attr,
+ &iio_dev_attr_in1_thresh_high_value.dev_attr.attr,
+ &iio_dev_attr_in1_thresh_both_hyst_raw.dev_attr.attr,
+ &iio_dev_attr_in2_thresh_low_value.dev_attr.attr,
+ &iio_dev_attr_in2_thresh_high_value.dev_attr.attr,
+ &iio_dev_attr_in2_thresh_both_hyst_raw.dev_attr.attr,
+ &iio_dev_attr_in3_thresh_low_value.dev_attr.attr,
+ &iio_dev_attr_in3_thresh_high_value.dev_attr.attr,
+ &iio_dev_attr_in3_thresh_both_hyst_raw.dev_attr.attr,
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
NULL,
@@ -662,12 +444,12 @@ static struct attribute_group ad7993_4_7_8_event_attrs_group = {
};
static struct attribute *ad7992_event_attributes[] = {
- &iio_event_attr_in0_thresh_low_value.dev_attr.attr,
- &iio_event_attr_in0_thresh_high_value.dev_attr.attr,
- &iio_event_attr_in0_thresh_both_hyst_raw.dev_attr.attr,
- &iio_event_attr_in1_thresh_low_value.dev_attr.attr,
- &iio_event_attr_in1_thresh_high_value.dev_attr.attr,
- &iio_event_attr_in1_thresh_both_hyst_raw.dev_attr.attr,
+ &iio_dev_attr_in0_thresh_low_value.dev_attr.attr,
+ &iio_dev_attr_in0_thresh_high_value.dev_attr.attr,
+ &iio_dev_attr_in0_thresh_both_hyst_raw.dev_attr.attr,
+ &iio_dev_attr_in1_thresh_low_value.dev_attr.attr,
+ &iio_dev_attr_in1_thresh_high_value.dev_attr.attr,
+ &iio_dev_attr_in1_thresh_both_hyst_raw.dev_attr.attr,
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
NULL,
@@ -677,93 +459,192 @@ static struct attribute_group ad7992_event_attrs_group = {
.attrs = ad7992_event_attributes,
};
+static const struct iio_info ad7991_info = {
+ .read_raw = &ad799x_read_raw,
+ .driver_module = THIS_MODULE,
+};
+
+static const struct iio_info ad7992_info = {
+ .read_raw = &ad799x_read_raw,
+ .num_interrupt_lines = 1,
+ .event_attrs = &ad7992_event_attrs_group,
+ .driver_module = THIS_MODULE,
+};
+
+static const struct iio_info ad7993_4_7_8_info = {
+ .read_raw = &ad799x_read_raw,
+ .num_interrupt_lines = 1,
+ .event_attrs = &ad7993_4_7_8_event_attrs_group,
+ .driver_module = THIS_MODULE,
+};
+
static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
[ad7991] = {
- .num_inputs = 4,
- .bits = 12,
- .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 12, 16, 0), 0),
+ .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 1, 1, IIO_ST('u', 12, 16, 0), 0),
+ .channel[2] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 2, 2, IIO_ST('u', 12, 16, 0), 0),
+ .channel[3] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 3, 3, IIO_ST('u', 12, 16, 0), 0),
+ .channel[4] = IIO_CHAN_SOFT_TIMESTAMP(4),
+ .num_channels = 5,
.int_vref_mv = 4096,
- .dev_attrs = &ad7991_5_9_3_4_dev_attr_group,
- .scan_attrs = &ad7991_5_9_3_4_scan_el_group,
- .ad799x_set_scan_mode = ad7991_5_9_set_scan_mode,
+ .info = &ad7991_info,
},
[ad7995] = {
- .num_inputs = 4,
- .bits = 10,
- .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 10, 16, 0), 0),
+ .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 1, 1, IIO_ST('u', 10, 16, 0), 0),
+ .channel[2] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 2, 2, IIO_ST('u', 10, 16, 0), 0),
+ .channel[3] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 3, 3, IIO_ST('u', 10, 16, 0), 0),
+ .channel[4] = IIO_CHAN_SOFT_TIMESTAMP(4),
+ .num_channels = 5,
.int_vref_mv = 1024,
- .dev_attrs = &ad7991_5_9_3_4_dev_attr_group,
- .scan_attrs = &ad7991_5_9_3_4_scan_el_group,
- .ad799x_set_scan_mode = ad7991_5_9_set_scan_mode,
+ .info = &ad7991_info,
},
[ad7999] = {
- .num_inputs = 4,
- .bits = 10,
- .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 10, 16, 0), 0),
+ .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 1, 1, IIO_ST('u', 10, 16, 0), 0),
+ .channel[2] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 2, 2, IIO_ST('u', 10, 16, 0), 0),
+ .channel[3] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 3, 3, IIO_ST('u', 10, 16, 0), 0),
+ .channel[4] = IIO_CHAN_SOFT_TIMESTAMP(4),
+ .num_channels = 5,
.int_vref_mv = 1024,
- .dev_attrs = &ad7991_5_9_3_4_dev_attr_group,
- .scan_attrs = &ad7991_5_9_3_4_scan_el_group,
- .ad799x_set_scan_mode = ad7991_5_9_set_scan_mode,
+ .info = &ad7991_info,
},
[ad7992] = {
- .num_inputs = 2,
- .bits = 12,
- .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 12, 16, 0), 0),
+ .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 1, 1, IIO_ST('u', 12, 16, 0), 0),
+ .channel[2] = IIO_CHAN_SOFT_TIMESTAMP(2),
+ .num_channels = 3,
.int_vref_mv = 4096,
- .monitor_mode = true,
.default_config = AD7998_ALERT_EN,
- .dev_attrs = &ad7992_dev_attr_group,
- .scan_attrs = &ad7992_scan_el_group,
- .event_attrs = &ad7992_event_attrs_group,
- .ad799x_set_scan_mode = ad7992_3_4_set_scan_mode,
+ .info = &ad7992_info,
},
[ad7993] = {
- .num_inputs = 4,
- .bits = 10,
- .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 10, 16, 0), 0),
+ .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 1, 1, IIO_ST('u', 10, 16, 0), 0),
+ .channel[2] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 2, 2, IIO_ST('u', 10, 16, 0), 0),
+ .channel[3] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 3, 3, IIO_ST('u', 10, 16, 0), 0),
+ .channel[4] = IIO_CHAN_SOFT_TIMESTAMP(4),
+ .num_channels = 5,
.int_vref_mv = 1024,
- .monitor_mode = true,
.default_config = AD7998_ALERT_EN,
- .dev_attrs = &ad7991_5_9_3_4_dev_attr_group,
- .scan_attrs = &ad7991_5_9_3_4_scan_el_group,
- .event_attrs = &ad7993_4_7_8_event_attrs_group,
- .ad799x_set_scan_mode = ad7992_3_4_set_scan_mode,
+ .info = &ad7993_4_7_8_info,
},
[ad7994] = {
- .num_inputs = 4,
- .bits = 12,
- .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 12, 16, 0), 0),
+ .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 1, 1, IIO_ST('u', 12, 16, 0), 0),
+ .channel[2] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 2, 2, IIO_ST('u', 12, 16, 0), 0),
+ .channel[3] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 3, 3, IIO_ST('u', 12, 16, 0), 0),
+ .channel[4] = IIO_CHAN_SOFT_TIMESTAMP(4),
+ .num_channels = 5,
.int_vref_mv = 4096,
- .monitor_mode = true,
.default_config = AD7998_ALERT_EN,
- .dev_attrs = &ad7991_5_9_3_4_dev_attr_group,
- .scan_attrs = &ad7991_5_9_3_4_scan_el_group,
- .event_attrs = &ad7993_4_7_8_event_attrs_group,
- .ad799x_set_scan_mode = ad7992_3_4_set_scan_mode,
+ .info = &ad7993_4_7_8_info,
},
[ad7997] = {
- .num_inputs = 8,
- .bits = 10,
- .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 10, 16, 0), 0),
+ .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 1, 1, IIO_ST('u', 10, 16, 0), 0),
+ .channel[2] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 2, 2, IIO_ST('u', 10, 16, 0), 0),
+ .channel[3] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 3, 3, IIO_ST('u', 10, 16, 0), 0),
+ .channel[4] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 4, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 4, 4, IIO_ST('u', 10, 16, 0), 0),
+ .channel[5] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 5, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 5, 5, IIO_ST('u', 10, 16, 0), 0),
+ .channel[6] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 6, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 6, 6, IIO_ST('u', 10, 16, 0), 0),
+ .channel[7] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 7, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 7, 7, IIO_ST('u', 10, 16, 0), 0),
+ .channel[8] = IIO_CHAN_SOFT_TIMESTAMP(8),
+ .num_channels = 9,
.int_vref_mv = 1024,
- .monitor_mode = true,
.default_config = AD7998_ALERT_EN,
- .dev_attrs = &ad7997_8_dev_attr_group,
- .scan_attrs = &ad7997_8_scan_el_group,
- .event_attrs = &ad7993_4_7_8_event_attrs_group,
- .ad799x_set_scan_mode = ad7997_8_set_scan_mode,
+ .info = &ad7993_4_7_8_info,
},
[ad7998] = {
- .num_inputs = 8,
- .bits = 12,
- .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, 0, IIO_ST('u', 12, 16, 0), 0),
+ .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 1, 1, IIO_ST('u', 12, 16, 0), 0),
+ .channel[2] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 2, 2, IIO_ST('u', 12, 16, 0), 0),
+ .channel[3] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 3, 3, IIO_ST('u', 12, 16, 0), 0),
+ .channel[4] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 4, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 4, 4, IIO_ST('u', 12, 16, 0), 0),
+ .channel[5] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 5, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 5, 5, IIO_ST('u', 12, 16, 0), 0),
+ .channel[6] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 6, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 6, 6, IIO_ST('u', 12, 16, 0), 0),
+ .channel[7] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 7, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 7, 7, IIO_ST('u', 12, 16, 0), 0),
+ .channel[8] = IIO_CHAN_SOFT_TIMESTAMP(8),
+ .num_channels = 9,
.int_vref_mv = 4096,
- .monitor_mode = true,
.default_config = AD7998_ALERT_EN,
- .dev_attrs = &ad7997_8_dev_attr_group,
- .scan_attrs = &ad7997_8_scan_el_group,
- .event_attrs = &ad7993_4_7_8_event_attrs_group,
- .ad799x_set_scan_mode = ad7997_8_set_scan_mode,
+ .info = &ad7993_4_7_8_info,
},
};
@@ -772,16 +653,16 @@ static int __devinit ad799x_probe(struct i2c_client *client,
{
int ret, regdone = 0;
struct ad799x_platform_data *pdata = client->dev.platform_data;
- struct ad799x_state *st = kzalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ struct ad799x_state *st;
+ struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
+
+ if (indio_dev == NULL)
+ return -ENOMEM;
+ st = iio_priv(indio_dev);
/* this is only used for device removal purposes */
- i2c_set_clientdata(client, st);
+ i2c_set_clientdata(client, indio_dev);
- atomic_set(&st->protect_ring, 0);
st->id = id->driver_data;
st->chip_info = &ad799x_chip_info_tbl[st->id];
st->config = st->chip_info->default_config;
@@ -801,94 +682,76 @@ static int __devinit ad799x_probe(struct i2c_client *client,
}
st->client = client;
- st->indio_dev = iio_allocate_device();
- if (st->indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_disable_reg;
- }
-
- /* Estabilish that the iio_dev is a child of the i2c device */
- st->indio_dev->dev.parent = &client->dev;
- st->indio_dev->attrs = st->chip_info->dev_attrs;
- st->indio_dev->event_attrs = st->chip_info->event_attrs;
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->name = id->name;
+ indio_dev->info = st->chip_info->info;
+ indio_dev->name = id->name;
+ indio_dev->dev_data = (void *)(st);
- st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
- st->indio_dev->modes = INDIO_DIRECT_MODE;
- st->indio_dev->num_interrupt_lines = 1;
-
- ret = ad799x_set_scan_mode(st, 0);
- if (ret)
- goto error_free_device;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = st->chip_info->channel;
+ indio_dev->num_channels = st->chip_info->num_channels;
- ret = ad799x_register_ring_funcs_and_init(st->indio_dev);
+ ret = ad799x_register_ring_funcs_and_init(indio_dev);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
- ret = iio_device_register(st->indio_dev);
+ ret = iio_device_register(indio_dev);
if (ret)
goto error_cleanup_ring;
regdone = 1;
- ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
+ ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
+ indio_dev->channels,
+ indio_dev->num_channels);
if (ret)
goto error_cleanup_ring;
- if (client->irq > 0 && st->chip_info->monitor_mode) {
- INIT_WORK(&st->work_thresh, ad799x_interrupt_bh);
-
- ret = iio_register_interrupt_line(client->irq,
- st->indio_dev,
- 0,
- IRQF_TRIGGER_FALLING,
- client->name);
+ if (client->irq > 0) {
+ ret = request_threaded_irq(client->irq,
+ NULL,
+ ad799x_event_handler,
+ IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ client->name,
+ indio_dev);
if (ret)
goto error_cleanup_ring;
-
- /*
- * The event handler list element refer to iio_event_ad799x.
- * All event attributes bind to the same event handler.
- * So, only register event handler once.
- */
- iio_add_event_to_list(&iio_event_ad799x,
- &st->indio_dev->interrupts[0]->ev_list);
}
return 0;
+
error_cleanup_ring:
- ad799x_ring_cleanup(st->indio_dev);
-error_free_device:
- if (!regdone)
- iio_free_device(st->indio_dev);
- else
- iio_device_unregister(st->indio_dev);
+ ad799x_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);
- kfree(st);
-error_ret:
+ if (regdone)
+ iio_device_unregister(indio_dev);
+ else
+ iio_free_device(indio_dev);
+
return ret;
}
static __devexit int ad799x_remove(struct i2c_client *client)
{
- struct ad799x_state *st = i2c_get_clientdata(client);
- struct iio_dev *indio_dev = st->indio_dev;
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct ad799x_state *st = iio_priv(indio_dev);
- if (client->irq > 0 && st->chip_info->monitor_mode)
- iio_unregister_interrupt_line(indio_dev, 0);
+ if (client->irq > 0)
+ free_irq(client->irq, indio_dev);
iio_ring_buffer_unregister(indio_dev->ring);
ad799x_ring_cleanup(indio_dev);
- iio_device_unregister(indio_dev);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);
regulator_put(st->reg);
}
- kfree(st);
+ iio_device_unregister(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c
index 0875a7ef67a5..1ae8857b3d25 100644
--- a/drivers/staging/iio/adc/ad799x_ring.c
+++ b/drivers/staging/iio/adc/ad799x_ring.c
@@ -10,7 +10,6 @@
*/
#include <linux/interrupt.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/kernel.h>
@@ -29,7 +28,7 @@
int ad799x_single_channel_from_ring(struct ad799x_state *st, long mask)
{
- struct iio_ring_buffer *ring = st->indio_dev->ring;
+ struct iio_ring_buffer *ring = iio_priv_to_dev(st)->ring;
int count = 0, ret;
u16 *ring_data;
@@ -38,12 +37,13 @@ int ad799x_single_channel_from_ring(struct ad799x_state *st, long mask)
goto error_ret;
}
- ring_data = kmalloc(ring->access.get_bytes_per_datum(ring), GFP_KERNEL);
+ ring_data = kmalloc(ring->access->get_bytes_per_datum(ring),
+ GFP_KERNEL);
if (ring_data == NULL) {
ret = -ENOMEM;
goto error_ret;
}
- ret = ring->access.read_last(ring, (u8 *) ring_data);
+ ret = ring->access->read_last(ring, (u8 *) ring_data);
if (ret)
goto error_free_ring_data;
/* Need a count of channels prior to this one */
@@ -72,7 +72,7 @@ error_ret:
static int ad799x_ring_preenable(struct iio_dev *indio_dev)
{
struct iio_ring_buffer *ring = indio_dev->ring;
- struct ad799x_state *st = indio_dev->dev_data;
+ struct ad799x_state *st = iio_dev_get_devdata(indio_dev);
/*
* Need to figure out the current mode based upon the requested
@@ -80,7 +80,7 @@ static int ad799x_ring_preenable(struct iio_dev *indio_dev)
*/
if (st->id == ad7997 || st->id == ad7998)
- ad799x_set_scan_mode(st, ring->scan_mask);
+ ad7997_8_set_scan_mode(st, ring->scan_mask);
st->d_size = ring->scan_count * 2;
@@ -91,56 +91,34 @@ static int ad799x_ring_preenable(struct iio_dev *indio_dev)
st->d_size += sizeof(s64) - (st->d_size % sizeof(s64));
}
- if (indio_dev->ring->access.set_bytes_per_datum)
- indio_dev->ring->access.set_bytes_per_datum(indio_dev->ring,
+ if (indio_dev->ring->access->set_bytes_per_datum)
+ indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring,
st->d_size);
return 0;
}
/**
- * ad799x_poll_func_th() th of trigger launched polling to ring buffer
- *
- * As sampling only occurs on i2c comms occurring, leave timestamping until
- * then. Some triggers will generate their own time stamp. Currently
- * there is no way of notifying them when no one cares.
- **/
-static void ad799x_poll_func_th(struct iio_dev *indio_dev, s64 time)
-{
- struct ad799x_state *st = indio_dev->dev_data;
-
- schedule_work(&st->poll_work);
-
- return;
-}
-/**
- * ad799x_poll_bh_to_ring() bh of trigger launched polling to ring buffer
- * @work_s: the work struct through which this was scheduled
+ * ad799x_trigger_handler() bh of trigger launched polling to ring buffer
*
* Currently there is no option in this driver to disable the saving of
* timestamps within the ring.
- * I think the one copy of this at a time was to avoid problems if the
- * trigger was set far too high and the reads then locked up the computer.
**/
-static void ad799x_poll_bh_to_ring(struct work_struct *work_s)
+
+static irqreturn_t ad799x_trigger_handler(int irq, void *p)
{
- struct ad799x_state *st = container_of(work_s, struct ad799x_state,
- poll_work);
- struct iio_dev *indio_dev = st->indio_dev;
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->private_data;
+ struct ad799x_state *st = iio_dev_get_devdata(indio_dev);
struct iio_ring_buffer *ring = indio_dev->ring;
- struct iio_sw_ring_buffer *ring_sw = iio_to_sw_ring(indio_dev->ring);
s64 time_ns;
__u8 *rxbuf;
int b_sent;
u8 cmd;
- /* Ensure only one copy of this function running at a time */
- if (atomic_inc_return(&st->protect_ring) > 1)
- return;
-
rxbuf = kmalloc(st->d_size, GFP_KERNEL);
if (rxbuf == NULL)
- return;
+ goto out;
switch (st->id) {
case ad7991:
@@ -173,16 +151,25 @@ static void ad799x_poll_bh_to_ring(struct work_struct *work_s)
memcpy(rxbuf + st->d_size - sizeof(s64),
&time_ns, sizeof(time_ns));
- ring->access.store_to(&ring_sw->buf, rxbuf, time_ns);
+ ring->access->store_to(indio_dev->ring, rxbuf, time_ns);
done:
kfree(rxbuf);
- atomic_dec(&st->protect_ring);
+ if (b_sent < 0)
+ return b_sent;
+out:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
}
+static const struct iio_ring_setup_ops ad799x_buf_setup_ops = {
+ .preenable = &ad799x_ring_preenable,
+ .postenable = &iio_triggered_ring_postenable,
+ .predisable = &iio_triggered_ring_predisable,
+};
int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev)
{
- struct ad799x_state *st = indio_dev->dev_data;
int ret = 0;
indio_dev->ring = iio_sw_rb_allocate(indio_dev);
@@ -191,25 +178,27 @@ int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev)
goto error_ret;
}
/* Effectively select the ring buffer implementation */
- iio_ring_sw_register_funcs(&st->indio_dev->ring->access);
- ret = iio_alloc_pollfunc(indio_dev, NULL, &ad799x_poll_func_th);
- if (ret)
+ indio_dev->ring->access = &ring_sw_access_funcs;
+ indio_dev->pollfunc = iio_alloc_pollfunc(NULL,
+ &ad799x_trigger_handler,
+ IRQF_ONESHOT,
+ indio_dev,
+ "%s_consumer%d",
+ indio_dev->name,
+ 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->preenable = &ad799x_ring_preenable;
- indio_dev->ring->postenable = &iio_triggered_ring_postenable;
- indio_dev->ring->predisable = &iio_triggered_ring_predisable;
+ indio_dev->ring->setup_ops = &ad799x_buf_setup_ops;
indio_dev->ring->scan_timestamp = true;
- INIT_WORK(&st->poll_work, &ad799x_poll_bh_to_ring);
-
- indio_dev->ring->scan_el_attrs = st->chip_info->scan_attrs;
-
/* 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:
@@ -224,6 +213,6 @@ void ad799x_ring_cleanup(struct iio_dev *indio_dev)
iio_trigger_dettach_poll_func(indio_dev->trig,
indio_dev->pollfunc);
}
- kfree(indio_dev->pollfunc);
+ iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
diff --git a/drivers/staging/iio/adc/adt7310.c b/drivers/staging/iio/adc/adt7310.c
index 771a409ee94c..68eca0b99ac0 100644
--- a/drivers/staging/iio/adc/adt7310.c
+++ b/drivers/staging/iio/adc/adt7310.c
@@ -7,15 +7,12 @@
*/
#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/spi/spi.h>
-#include <linux/rtc.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -82,11 +79,8 @@
*/
struct adt7310_chip_info {
- const char *name;
struct spi_device *spi_dev;
struct iio_dev *indio_dev;
- struct work_struct thresh_work;
- s64 last_timestamp;
u8 config;
};
@@ -380,24 +374,12 @@ static ssize_t adt7310_show_value(struct device *dev,
static IIO_DEVICE_ATTR(value, S_IRUGO, adt7310_show_value, NULL, 0);
-static ssize_t adt7310_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7310_chip_info *chip = dev_info->dev_data;
- return sprintf(buf, "%s\n", chip->name);
-}
-
-static IIO_DEVICE_ATTR(name, S_IRUGO, adt7310_show_name, NULL, 0);
-
static struct attribute *adt7310_attributes[] = {
&iio_dev_attr_available_modes.dev_attr.attr,
&iio_dev_attr_mode.dev_attr.attr,
&iio_dev_attr_resolution.dev_attr.attr,
&iio_dev_attr_id.dev_attr.attr,
&iio_dev_attr_value.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
NULL,
};
@@ -405,53 +387,39 @@ static const struct attribute_group adt7310_attribute_group = {
.attrs = adt7310_attributes,
};
-/*
- * temperature bound events
- */
-
-#define IIO_EVENT_CODE_ADT7310_ABOVE_ALARM IIO_BUFFER_EVENT_CODE(0)
-#define IIO_EVENT_CODE_ADT7310_BELLOW_ALARM IIO_BUFFER_EVENT_CODE(1)
-#define IIO_EVENT_CODE_ADT7310_ABOVE_CRIT IIO_BUFFER_EVENT_CODE(2)
-
-static void adt7310_interrupt_bh(struct work_struct *work_s)
+static irqreturn_t adt7310_event_handler(int irq, void *private)
{
- struct adt7310_chip_info *chip =
- container_of(work_s, struct adt7310_chip_info, thresh_work);
+ struct iio_dev *indio_dev = private;
+ struct adt7310_chip_info *chip = iio_dev_get_devdata(indio_dev);
+ s64 timestamp = iio_get_time_ns();
u8 status;
+ int ret;
- if (adt7310_spi_read_byte(chip, ADT7310_STATUS, &status))
- return;
+ ret = adt7310_spi_read_byte(chip, ADT7310_STATUS, &status);
+ if (ret)
+ return ret;
if (status & ADT7310_STAT_T_HIGH)
- iio_push_event(chip->indio_dev, 0,
- IIO_EVENT_CODE_ADT7310_ABOVE_ALARM,
- chip->last_timestamp);
+ iio_push_event(indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ timestamp);
if (status & ADT7310_STAT_T_LOW)
- iio_push_event(chip->indio_dev, 0,
- IIO_EVENT_CODE_ADT7310_BELLOW_ALARM,
- chip->last_timestamp);
+ iio_push_event(indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ timestamp);
if (status & ADT7310_STAT_T_CRIT)
- iio_push_event(chip->indio_dev, 0,
- IIO_EVENT_CODE_ADT7310_ABOVE_CRIT,
- chip->last_timestamp);
+ iio_push_event(indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ timestamp);
+ return IRQ_HANDLED;
}
-static int adt7310_interrupt(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct adt7310_chip_info *chip = dev_info->dev_data;
-
- chip->last_timestamp = timestamp;
- schedule_work(&chip->thresh_work);
-
- return 0;
-}
-
-IIO_EVENT_SH(adt7310, &adt7310_interrupt);
-IIO_EVENT_SH(adt7310_ct, &adt7310_interrupt);
-
static ssize_t adt7310_show_event_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -729,49 +697,62 @@ static inline ssize_t adt7310_set_t_hyst(struct device *dev,
return len;
}
-IIO_EVENT_ATTR_SH(event_mode, iio_event_adt7310,
- adt7310_show_event_mode, adt7310_set_event_mode, 0);
-IIO_EVENT_ATTR_SH(available_event_modes, iio_event_adt7310,
- adt7310_show_available_event_modes, NULL, 0);
-IIO_EVENT_ATTR_SH(fault_queue, iio_event_adt7310,
- adt7310_show_fault_queue, adt7310_set_fault_queue, 0);
-IIO_EVENT_ATTR_SH(t_alarm_high, iio_event_adt7310,
- adt7310_show_t_alarm_high, adt7310_set_t_alarm_high, 0);
-IIO_EVENT_ATTR_SH(t_alarm_low, iio_event_adt7310,
- adt7310_show_t_alarm_low, adt7310_set_t_alarm_low, 0);
-IIO_EVENT_ATTR_SH(t_crit, iio_event_adt7310_ct,
- adt7310_show_t_crit, adt7310_set_t_crit, 0);
-IIO_EVENT_ATTR_SH(t_hyst, iio_event_adt7310,
- adt7310_show_t_hyst, adt7310_set_t_hyst, 0);
+static IIO_DEVICE_ATTR(event_mode,
+ S_IRUGO | S_IWUSR,
+ adt7310_show_event_mode, adt7310_set_event_mode, 0);
+static IIO_DEVICE_ATTR(available_event_modes,
+ S_IRUGO | S_IWUSR,
+ adt7310_show_available_event_modes, NULL, 0);
+static IIO_DEVICE_ATTR(fault_queue,
+ S_IRUGO | S_IWUSR,
+ adt7310_show_fault_queue, adt7310_set_fault_queue, 0);
+static IIO_DEVICE_ATTR(t_alarm_high,
+ S_IRUGO | S_IWUSR,
+ adt7310_show_t_alarm_high, adt7310_set_t_alarm_high, 0);
+static IIO_DEVICE_ATTR(t_alarm_low,
+ S_IRUGO | S_IWUSR,
+ adt7310_show_t_alarm_low, adt7310_set_t_alarm_low, 0);
+static IIO_DEVICE_ATTR(t_crit,
+ S_IRUGO | S_IWUSR,
+ adt7310_show_t_crit, adt7310_set_t_crit, 0);
+static IIO_DEVICE_ATTR(t_hyst,
+ S_IRUGO | S_IWUSR,
+ adt7310_show_t_hyst, adt7310_set_t_hyst, 0);
static struct attribute *adt7310_event_int_attributes[] = {
- &iio_event_attr_event_mode.dev_attr.attr,
- &iio_event_attr_available_event_modes.dev_attr.attr,
- &iio_event_attr_fault_queue.dev_attr.attr,
- &iio_event_attr_t_alarm_high.dev_attr.attr,
- &iio_event_attr_t_alarm_low.dev_attr.attr,
- &iio_event_attr_t_hyst.dev_attr.attr,
+ &iio_dev_attr_event_mode.dev_attr.attr,
+ &iio_dev_attr_available_event_modes.dev_attr.attr,
+ &iio_dev_attr_fault_queue.dev_attr.attr,
+ &iio_dev_attr_t_alarm_high.dev_attr.attr,
+ &iio_dev_attr_t_alarm_low.dev_attr.attr,
+ &iio_dev_attr_t_hyst.dev_attr.attr,
NULL,
};
static struct attribute *adt7310_event_ct_attributes[] = {
- &iio_event_attr_event_mode.dev_attr.attr,
- &iio_event_attr_available_event_modes.dev_attr.attr,
- &iio_event_attr_fault_queue.dev_attr.attr,
- &iio_event_attr_t_crit.dev_attr.attr,
- &iio_event_attr_t_hyst.dev_attr.attr,
+ &iio_dev_attr_event_mode.dev_attr.attr,
+ &iio_dev_attr_available_event_modes.dev_attr.attr,
+ &iio_dev_attr_fault_queue.dev_attr.attr,
+ &iio_dev_attr_t_crit.dev_attr.attr,
+ &iio_dev_attr_t_hyst.dev_attr.attr,
NULL,
};
static struct attribute_group adt7310_event_attribute_group[ADT7310_IRQS] = {
{
.attrs = adt7310_event_int_attributes,
- },
- {
+ }, {
.attrs = adt7310_event_ct_attributes,
}
};
+static const struct iio_info adt7310_info = {
+ .attrs = &adt7310_attribute_group,
+ .num_interrupt_lines = ADT7310_IRQS,
+ .event_attrs = adt7310_event_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
/*
* device probe and remove
*/
@@ -792,20 +773,17 @@ static int __devinit adt7310_probe(struct spi_device *spi_dev)
dev_set_drvdata(&spi_dev->dev, chip);
chip->spi_dev = spi_dev;
- chip->name = spi_dev->modalias;
- chip->indio_dev = iio_allocate_device();
+ chip->indio_dev = iio_allocate_device(0);
if (chip->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_chip;
}
chip->indio_dev->dev.parent = &spi_dev->dev;
- chip->indio_dev->attrs = &adt7310_attribute_group;
- chip->indio_dev->event_attrs = adt7310_event_attribute_group;
+ chip->indio_dev->name = spi_get_device_id(spi_dev)->name;
+ chip->indio_dev->info = &adt7310_info;
chip->indio_dev->dev_data = (void *)chip;
- chip->indio_dev->driver_module = THIS_MODULE;
- chip->indio_dev->num_interrupt_lines = ADT7310_IRQS;
chip->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(chip->indio_dev);
@@ -818,45 +796,29 @@ static int __devinit adt7310_probe(struct spi_device *spi_dev)
irq_flags = adt7310_platform_data[2];
else
irq_flags = IRQF_TRIGGER_LOW;
- ret = iio_register_interrupt_line(spi_dev->irq,
- chip->indio_dev,
- 0,
- irq_flags,
- chip->name);
+ ret = request_threaded_irq(spi_dev->irq,
+ NULL,
+ &adt7310_event_handler,
+ irq_flags,
+ chip->indio_dev->name,
+ chip->indio_dev);
if (ret)
goto error_unreg_dev;
-
- /*
- * The event handler list element refer to iio_event_adt7310.
- * All event attributes bind to the same event handler.
- * One event handler can only be added to one event list.
- */
- iio_add_event_to_list(&iio_event_adt7310,
- &chip->indio_dev->interrupts[0]->ev_list);
}
/* INT bound temperature alarm event. line 1 */
if (adt7310_platform_data[0]) {
- ret = iio_register_interrupt_line(adt7310_platform_data[0],
- chip->indio_dev,
- 1,
- adt7310_platform_data[1],
- chip->name);
+ ret = request_threaded_irq(adt7310_platform_data[0],
+ NULL,
+ &adt7310_event_handler,
+ adt7310_platform_data[1],
+ chip->indio_dev->name,
+ chip->indio_dev);
if (ret)
goto error_unreg_ct_irq;
-
- /*
- * The event handler list element refer to iio_event_adt7310.
- * All event attributes bind to the same event handler.
- * One event handler can only be added to one event list.
- */
- iio_add_event_to_list(&iio_event_adt7310_ct,
- &chip->indio_dev->interrupts[1]->ev_list);
}
if (spi_dev->irq && adt7310_platform_data[0]) {
- INIT_WORK(&chip->thresh_work, adt7310_interrupt_bh);
-
ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config);
if (ret) {
ret = -EIO;
@@ -879,14 +841,14 @@ static int __devinit adt7310_probe(struct spi_device *spi_dev)
}
dev_info(&spi_dev->dev, "%s temperature sensor registered.\n",
- chip->name);
+ chip->indio_dev->name);
return 0;
error_unreg_int_irq:
- iio_unregister_interrupt_line(chip->indio_dev, 1);
+ free_irq(adt7310_platform_data[0], chip->indio_dev);
error_unreg_ct_irq:
- iio_unregister_interrupt_line(chip->indio_dev, 0);
+ free_irq(spi_dev->irq, chip->indio_dev);
error_unreg_dev:
iio_device_unregister(chip->indio_dev);
error_free_dev:
@@ -905,9 +867,9 @@ static int __devexit adt7310_remove(struct spi_device *spi_dev)
dev_set_drvdata(&spi_dev->dev, NULL);
if (adt7310_platform_data[0])
- iio_unregister_interrupt_line(indio_dev, 1);
+ free_irq(adt7310_platform_data[0], chip->indio_dev);
if (spi_dev->irq)
- iio_unregister_interrupt_line(indio_dev, 0);
+ free_irq(spi_dev->irq, chip->indio_dev);
iio_device_unregister(indio_dev);
iio_free_device(chip->indio_dev);
kfree(chip);
diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c
index c345f27ec7fc..c40a84f9c2ff 100644
--- a/drivers/staging/iio/adc/adt7410.c
+++ b/drivers/staging/iio/adc/adt7410.c
@@ -7,15 +7,12 @@
*/
#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/i2c.h>
-#include <linux/rtc.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -77,11 +74,8 @@
*/
struct adt7410_chip_info {
- const char *name;
struct i2c_client *client;
struct iio_dev *indio_dev;
- struct work_struct thresh_work;
- s64 last_timestamp;
u8 config;
};
@@ -348,24 +342,12 @@ static ssize_t adt7410_show_value(struct device *dev,
static IIO_DEVICE_ATTR(value, S_IRUGO, adt7410_show_value, NULL, 0);
-static ssize_t adt7410_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7410_chip_info *chip = dev_info->dev_data;
- return sprintf(buf, "%s\n", chip->name);
-}
-
-static IIO_DEVICE_ATTR(name, S_IRUGO, adt7410_show_name, NULL, 0);
-
static struct attribute *adt7410_attributes[] = {
&iio_dev_attr_available_modes.dev_attr.attr,
&iio_dev_attr_mode.dev_attr.attr,
&iio_dev_attr_resolution.dev_attr.attr,
&iio_dev_attr_id.dev_attr.attr,
&iio_dev_attr_value.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
NULL,
};
@@ -373,55 +355,38 @@ static const struct attribute_group adt7410_attribute_group = {
.attrs = adt7410_attributes,
};
-/*
- * temperature bound events
- */
-
-#define IIO_EVENT_CODE_ADT7410_ABOVE_ALARM IIO_BUFFER_EVENT_CODE(0)
-#define IIO_EVENT_CODE_ADT7410_BELLOW_ALARM IIO_BUFFER_EVENT_CODE(1)
-#define IIO_EVENT_CODE_ADT7410_ABOVE_CRIT IIO_BUFFER_EVENT_CODE(2)
-
-static void adt7410_interrupt_bh(struct work_struct *work_s)
+static irqreturn_t adt7410_event_handler(int irq, void *private)
{
- struct adt7410_chip_info *chip =
- container_of(work_s, struct adt7410_chip_info, thresh_work);
+ struct iio_dev *indio_dev = private;
+ struct adt7410_chip_info *chip = iio_dev_get_devdata(indio_dev);
+ s64 timestamp = iio_get_time_ns();
u8 status;
if (adt7410_i2c_read_byte(chip, ADT7410_STATUS, &status))
- return;
-
- enable_irq(chip->client->irq);
+ return IRQ_HANDLED;
if (status & ADT7410_STAT_T_HIGH)
- iio_push_event(chip->indio_dev, 0,
- IIO_EVENT_CODE_ADT7410_ABOVE_ALARM,
- chip->last_timestamp);
+ iio_push_event(indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ timestamp);
if (status & ADT7410_STAT_T_LOW)
- iio_push_event(chip->indio_dev, 0,
- IIO_EVENT_CODE_ADT7410_BELLOW_ALARM,
- chip->last_timestamp);
+ iio_push_event(indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ timestamp);
if (status & ADT7410_STAT_T_CRIT)
- iio_push_event(chip->indio_dev, 0,
- IIO_EVENT_CODE_ADT7410_ABOVE_CRIT,
- chip->last_timestamp);
-}
+ iio_push_event(indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ timestamp);
-static int adt7410_interrupt(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct adt7410_chip_info *chip = dev_info->dev_data;
-
- chip->last_timestamp = timestamp;
- schedule_work(&chip->thresh_work);
-
- return 0;
+ return IRQ_HANDLED;
}
-IIO_EVENT_SH(adt7410, &adt7410_interrupt);
-IIO_EVENT_SH(adt7410_ct, &adt7410_interrupt);
-
static ssize_t adt7410_show_event_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -699,49 +664,62 @@ static inline ssize_t adt7410_set_t_hyst(struct device *dev,
return ret;
}
-IIO_EVENT_ATTR_SH(event_mode, iio_event_adt7410,
- adt7410_show_event_mode, adt7410_set_event_mode, 0);
-IIO_EVENT_ATTR_SH(available_event_modes, iio_event_adt7410,
- adt7410_show_available_event_modes, NULL, 0);
-IIO_EVENT_ATTR_SH(fault_queue, iio_event_adt7410,
- adt7410_show_fault_queue, adt7410_set_fault_queue, 0);
-IIO_EVENT_ATTR_SH(t_alarm_high, iio_event_adt7410,
- adt7410_show_t_alarm_high, adt7410_set_t_alarm_high, 0);
-IIO_EVENT_ATTR_SH(t_alarm_low, iio_event_adt7410,
- adt7410_show_t_alarm_low, adt7410_set_t_alarm_low, 0);
-IIO_EVENT_ATTR_SH(t_crit, iio_event_adt7410_ct,
- adt7410_show_t_crit, adt7410_set_t_crit, 0);
-IIO_EVENT_ATTR_SH(t_hyst, iio_event_adt7410,
- adt7410_show_t_hyst, adt7410_set_t_hyst, 0);
+static IIO_DEVICE_ATTR(event_mode,
+ S_IRUGO | S_IWUSR,
+ adt7410_show_event_mode, adt7410_set_event_mode, 0);
+static IIO_DEVICE_ATTR(available_event_modes,
+ S_IRUGO,
+ adt7410_show_available_event_modes, NULL, 0);
+static IIO_DEVICE_ATTR(fault_queue,
+ S_IRUGO | S_IWUSR,
+ adt7410_show_fault_queue, adt7410_set_fault_queue, 0);
+static IIO_DEVICE_ATTR(t_alarm_high,
+ S_IRUGO | S_IWUSR,
+ adt7410_show_t_alarm_high, adt7410_set_t_alarm_high, 0);
+static IIO_DEVICE_ATTR(t_alarm_low,
+ S_IRUGO | S_IWUSR,
+ adt7410_show_t_alarm_low, adt7410_set_t_alarm_low, 0);
+static IIO_DEVICE_ATTR(t_crit,
+ S_IRUGO | S_IWUSR,
+ adt7410_show_t_crit, adt7410_set_t_crit, 0);
+static IIO_DEVICE_ATTR(t_hyst,
+ S_IRUGO | S_IWUSR,
+ adt7410_show_t_hyst, adt7410_set_t_hyst, 0);
static struct attribute *adt7410_event_int_attributes[] = {
- &iio_event_attr_event_mode.dev_attr.attr,
- &iio_event_attr_available_event_modes.dev_attr.attr,
- &iio_event_attr_fault_queue.dev_attr.attr,
- &iio_event_attr_t_alarm_high.dev_attr.attr,
- &iio_event_attr_t_alarm_low.dev_attr.attr,
- &iio_event_attr_t_hyst.dev_attr.attr,
+ &iio_dev_attr_event_mode.dev_attr.attr,
+ &iio_dev_attr_available_event_modes.dev_attr.attr,
+ &iio_dev_attr_fault_queue.dev_attr.attr,
+ &iio_dev_attr_t_alarm_high.dev_attr.attr,
+ &iio_dev_attr_t_alarm_low.dev_attr.attr,
+ &iio_dev_attr_t_hyst.dev_attr.attr,
NULL,
};
static struct attribute *adt7410_event_ct_attributes[] = {
- &iio_event_attr_event_mode.dev_attr.attr,
- &iio_event_attr_available_event_modes.dev_attr.attr,
- &iio_event_attr_fault_queue.dev_attr.attr,
- &iio_event_attr_t_crit.dev_attr.attr,
- &iio_event_attr_t_hyst.dev_attr.attr,
+ &iio_dev_attr_event_mode.dev_attr.attr,
+ &iio_dev_attr_available_event_modes.dev_attr.attr,
+ &iio_dev_attr_fault_queue.dev_attr.attr,
+ &iio_dev_attr_t_crit.dev_attr.attr,
+ &iio_dev_attr_t_hyst.dev_attr.attr,
NULL,
};
static struct attribute_group adt7410_event_attribute_group[ADT7410_IRQS] = {
{
.attrs = adt7410_event_int_attributes,
- },
- {
+ }, {
.attrs = adt7410_event_ct_attributes,
}
};
+static const struct iio_info adt7410_info = {
+ .attrs = &adt7410_attribute_group,
+ .num_interrupt_lines = ADT7410_IRQS,
+ .event_attrs = adt7410_event_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
/*
* device probe and remove
*/
@@ -762,20 +740,16 @@ static int __devinit adt7410_probe(struct i2c_client *client,
i2c_set_clientdata(client, chip);
chip->client = client;
- chip->name = id->name;
- chip->indio_dev = iio_allocate_device();
+ chip->indio_dev = iio_allocate_device(0);
if (chip->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_chip;
}
-
+ chip->indio_dev->name = id->name;
chip->indio_dev->dev.parent = &client->dev;
- chip->indio_dev->attrs = &adt7410_attribute_group;
- chip->indio_dev->event_attrs = adt7410_event_attribute_group;
+ chip->indio_dev->info = &adt7410_info;
chip->indio_dev->dev_data = (void *)chip;
- chip->indio_dev->driver_module = THIS_MODULE;
- chip->indio_dev->num_interrupt_lines = ADT7410_IRQS;
chip->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(chip->indio_dev);
@@ -784,44 +758,29 @@ static int __devinit adt7410_probe(struct i2c_client *client,
/* CT critcal temperature event. line 0 */
if (client->irq) {
- ret = iio_register_interrupt_line(client->irq,
- chip->indio_dev,
- 0,
- IRQF_TRIGGER_LOW,
- chip->name);
+ ret = request_threaded_irq(client->irq,
+ NULL,
+ &adt7410_event_handler,
+ IRQF_TRIGGER_LOW,
+ id->name,
+ chip->indio_dev);
if (ret)
goto error_unreg_dev;
-
- /*
- * The event handler list element refer to iio_event_adt7410.
- * All event attributes bind to the same event handler.
- * One event handler can only be added to one event list.
- */
- iio_add_event_to_list(&iio_event_adt7410,
- &chip->indio_dev->interrupts[0]->ev_list);
}
/* INT bound temperature alarm event. line 1 */
if (adt7410_platform_data[0]) {
- ret = iio_register_interrupt_line(adt7410_platform_data[0],
- chip->indio_dev,
- 1,
- adt7410_platform_data[1],
- chip->name);
+ ret = request_threaded_irq(adt7410_platform_data[0],
+ NULL,
+ &adt7410_event_handler,
+ adt7410_platform_data[1],
+ id->name,
+ chip->indio_dev);
if (ret)
goto error_unreg_ct_irq;
-
- /*
- * The event handler list element refer to iio_event_adt7410.
- * All event attributes bind to the same event handler.
- * One event handler can only be added to one event list.
- */
- iio_add_event_to_list(&iio_event_adt7410_ct,
- &chip->indio_dev->interrupts[1]->ev_list);
}
if (client->irq && adt7410_platform_data[0]) {
- INIT_WORK(&chip->thresh_work, adt7410_interrupt_bh);
ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
if (ret) {
@@ -850,9 +809,9 @@ static int __devinit adt7410_probe(struct i2c_client *client,
return 0;
error_unreg_int_irq:
- iio_unregister_interrupt_line(chip->indio_dev, 1);
+ free_irq(adt7410_platform_data[0], chip->indio_dev);
error_unreg_ct_irq:
- iio_unregister_interrupt_line(chip->indio_dev, 0);
+ free_irq(client->irq, chip->indio_dev);
error_unreg_dev:
iio_device_unregister(chip->indio_dev);
error_free_dev:
@@ -870,9 +829,9 @@ static int __devexit adt7410_remove(struct i2c_client *client)
unsigned long *adt7410_platform_data = client->dev.platform_data;
if (adt7410_platform_data[0])
- iio_unregister_interrupt_line(indio_dev, 1);
+ free_irq(adt7410_platform_data[0], chip->indio_dev);
if (client->irq)
- iio_unregister_interrupt_line(indio_dev, 0);
+ free_irq(client->irq, chip->indio_dev);
iio_device_unregister(indio_dev);
iio_free_device(chip->indio_dev);
kfree(chip);
diff --git a/drivers/staging/iio/adc/adt75.c b/drivers/staging/iio/adc/adt75.c
index aff4d31eb89c..1171fb9c178f 100644
--- a/drivers/staging/iio/adc/adt75.c
+++ b/drivers/staging/iio/adc/adt75.c
@@ -7,15 +7,11 @@
*/
#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
-#include <linux/list.h>
#include <linux/i2c.h>
-#include <linux/rtc.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -54,11 +50,8 @@
*/
struct adt75_chip_info {
- const char *name;
struct i2c_client *client;
struct iio_dev *indio_dev;
- struct work_struct thresh_work;
- s64 last_timestamp;
u8 config;
};
@@ -249,23 +242,11 @@ static ssize_t adt75_show_value(struct device *dev,
static IIO_DEVICE_ATTR(value, S_IRUGO, adt75_show_value, NULL, 0);
-static ssize_t adt75_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt75_chip_info *chip = dev_info->dev_data;
- return sprintf(buf, "%s\n", chip->name);
-}
-
-static IIO_DEVICE_ATTR(name, S_IRUGO, adt75_show_name, NULL, 0);
-
static struct attribute *adt75_attributes[] = {
&iio_dev_attr_available_modes.dev_attr.attr,
&iio_dev_attr_mode.dev_attr.attr,
&iio_dev_attr_oneshot.dev_attr.attr,
&iio_dev_attr_value.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
NULL,
};
@@ -277,35 +258,20 @@ static const struct attribute_group adt75_attribute_group = {
* temperature bound events
*/
-#define IIO_EVENT_CODE_ADT75_OTI IIO_BUFFER_EVENT_CODE(0)
+#define IIO_EVENT_CODE_ADT75_OTI IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_TEMP, \
+ 0, \
+ IIO_EV_TYPE_THRESH, \
+ IIO_EV_DIR_FALLING)
-static void adt75_interrupt_bh(struct work_struct *work_s)
+static irqreturn_t adt75_event_handler(int irq, void *private)
{
- struct adt75_chip_info *chip =
- container_of(work_s, struct adt75_chip_info, thresh_work);
-
- enable_irq(chip->client->irq);
+ iio_push_event(private, 0,
+ IIO_EVENT_CODE_ADT75_OTI,
+ iio_get_time_ns());
- iio_push_event(chip->indio_dev, 0,
- IIO_EVENT_CODE_ADT75_OTI,
- chip->last_timestamp);
+ return IRQ_HANDLED;
}
-static int adt75_interrupt(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct adt75_chip_info *chip = dev_info->dev_data;
-
- chip->last_timestamp = timestamp;
- schedule_work(&chip->thresh_work);
-
- return 0;
-}
-
-IIO_EVENT_SH(adt75, &adt75_interrupt);
-
static ssize_t adt75_show_oti_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -458,16 +424,16 @@ static ssize_t adt75_set_fault_queue(struct device *dev,
}
static inline ssize_t adt75_show_t_bound(struct device *dev,
struct device_attribute *attr,
- u8 bound_reg,
char *buf)
{
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct iio_dev *dev_info = dev_get_drvdata(dev);
struct adt75_chip_info *chip = dev_info->dev_data;
u16 data;
char sign = ' ';
int ret;
- ret = adt75_i2c_read(chip, bound_reg, (u8 *)&data);
+ ret = adt75_i2c_read(chip, this_attr->address, (u8 *)&data);
if (ret)
return -EIO;
@@ -485,10 +451,10 @@ static inline ssize_t adt75_show_t_bound(struct device *dev,
static inline ssize_t adt75_set_t_bound(struct device *dev,
struct device_attribute *attr,
- u8 bound_reg,
const char *buf,
size_t len)
{
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct iio_dev *dev_info = dev_get_drvdata(dev);
struct adt75_chip_info *chip = dev_info->dev_data;
long tmp1, tmp2;
@@ -525,67 +491,42 @@ static inline ssize_t adt75_set_t_bound(struct device *dev,
data <<= ADT75_VALUE_OFFSET;
data = swab16(data);
- ret = adt75_i2c_write(chip, bound_reg, (u8)data);
+ ret = adt75_i2c_write(chip, this_attr->address, (u8)data);
if (ret)
return -EIO;
return ret;
}
-static ssize_t adt75_show_t_os(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return adt75_show_t_bound(dev, attr,
- ADT75_T_OS, buf);
-}
-
-static inline ssize_t adt75_set_t_os(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return adt75_set_t_bound(dev, attr,
- ADT75_T_OS, buf, len);
-}
-static ssize_t adt75_show_t_hyst(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return adt75_show_t_bound(dev, attr,
- ADT75_T_HYST, buf);
-}
-
-static inline ssize_t adt75_set_t_hyst(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return adt75_set_t_bound(dev, attr,
- ADT75_T_HYST, buf, len);
-}
-
-IIO_EVENT_ATTR_SH(oti_mode, iio_event_adt75,
- adt75_show_oti_mode, adt75_set_oti_mode, 0);
-IIO_EVENT_ATTR_SH(available_oti_modes, iio_event_adt75,
- adt75_show_available_oti_modes, NULL, 0);
-IIO_EVENT_ATTR_SH(smbus_alart, iio_event_adt75,
- adt75_show_smbus_alart, adt75_set_smbus_alart, 0);
-IIO_EVENT_ATTR_SH(fault_queue, iio_event_adt75,
- adt75_show_fault_queue, adt75_set_fault_queue, 0);
-IIO_EVENT_ATTR_SH(t_os, iio_event_adt75,
- adt75_show_t_os, adt75_set_t_os, 0);
-IIO_EVENT_ATTR_SH(t_hyst, iio_event_adt75,
- adt75_show_t_hyst, adt75_set_t_hyst, 0);
+static IIO_DEVICE_ATTR(oti_mode,
+ S_IRUGO | S_IWUSR,
+ adt75_show_oti_mode, adt75_set_oti_mode, 0);
+static IIO_DEVICE_ATTR(available_oti_modes,
+ S_IRUGO,
+ adt75_show_available_oti_modes, NULL, 0);
+static IIO_DEVICE_ATTR(smbus_alart,
+ S_IRUGO | S_IWUSR,
+ adt75_show_smbus_alart, adt75_set_smbus_alart, 0);
+static IIO_DEVICE_ATTR(fault_queue,
+ S_IRUGO | S_IWUSR,
+ adt75_show_fault_queue, adt75_set_fault_queue, 0);
+static IIO_DEVICE_ATTR(t_os_value,
+ S_IRUGO | S_IWUSR,
+ adt75_show_t_bound, adt75_set_t_bound,
+ ADT75_T_OS);
+static IIO_DEVICE_ATTR(t_hyst_value,
+ S_IRUGO | S_IWUSR,
+ adt75_show_t_bound, adt75_set_t_bound,
+ ADT75_T_HYST);
static struct attribute *adt75_event_attributes[] = {
- &iio_event_attr_oti_mode.dev_attr.attr,
- &iio_event_attr_available_oti_modes.dev_attr.attr,
- &iio_event_attr_smbus_alart.dev_attr.attr,
- &iio_event_attr_fault_queue.dev_attr.attr,
- &iio_event_attr_t_os.dev_attr.attr,
- &iio_event_attr_t_hyst.dev_attr.attr,
+ &iio_dev_attr_oti_mode.dev_attr.attr,
+ &iio_dev_attr_available_oti_modes.dev_attr.attr,
+ &iio_dev_attr_smbus_alart.dev_attr.attr,
+ &iio_dev_attr_fault_queue.dev_attr.attr,
+ &iio_dev_attr_t_os_value.dev_attr.attr,
+ &iio_dev_attr_t_hyst_value.dev_attr.attr,
NULL,
};
@@ -593,6 +534,13 @@ static struct attribute_group adt75_event_attribute_group = {
.attrs = adt75_event_attributes,
};
+static const struct iio_info adt75_info = {
+ .attrs = &adt75_attribute_group,
+ .num_interrupt_lines = 1,
+ .event_attrs = &adt75_event_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
/*
* device probe and remove
*/
@@ -612,20 +560,17 @@ static int __devinit adt75_probe(struct i2c_client *client,
i2c_set_clientdata(client, chip);
chip->client = client;
- chip->name = id->name;
- chip->indio_dev = iio_allocate_device();
+ chip->indio_dev = iio_allocate_device(0);
if (chip->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_chip;
}
+ chip->indio_dev->name = id->name;
chip->indio_dev->dev.parent = &client->dev;
- chip->indio_dev->attrs = &adt75_attribute_group;
- chip->indio_dev->event_attrs = &adt75_event_attribute_group;
+ chip->indio_dev->info = &adt75_info;
chip->indio_dev->dev_data = (void *)chip;
- chip->indio_dev->driver_module = THIS_MODULE;
- chip->indio_dev->num_interrupt_lines = 1;
chip->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(chip->indio_dev);
@@ -633,24 +578,15 @@ static int __devinit adt75_probe(struct i2c_client *client,
goto error_free_dev;
if (client->irq > 0) {
- ret = iio_register_interrupt_line(client->irq,
- chip->indio_dev,
- 0,
- IRQF_TRIGGER_LOW,
- chip->name);
+ ret = request_threaded_irq(client->irq,
+ NULL,
+ &adt75_event_handler,
+ IRQF_TRIGGER_LOW,
+ chip->indio_dev->name,
+ chip->indio_dev);
if (ret)
goto error_unreg_dev;
- /*
- * The event handler list element refer to iio_event_adt75.
- * All event attributes bind to the same event handler.
- * So, only register event handler once.
- */
- iio_add_event_to_list(&iio_event_adt75,
- &chip->indio_dev->interrupts[0]->ev_list);
-
- INIT_WORK(&chip->thresh_work, adt75_interrupt_bh);
-
ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config);
if (ret) {
ret = -EIO;
@@ -668,11 +604,11 @@ static int __devinit adt75_probe(struct i2c_client *client,
}
dev_info(&client->dev, "%s temperature sensor registered.\n",
- id->name);
+ chip->indio_dev->name);
return 0;
error_unreg_irq:
- iio_unregister_interrupt_line(chip->indio_dev, 0);
+ free_irq(client->irq, chip->indio_dev);
error_unreg_dev:
iio_device_unregister(chip->indio_dev);
error_free_dev:
@@ -689,7 +625,7 @@ static int __devexit adt75_remove(struct i2c_client *client)
struct iio_dev *indio_dev = chip->indio_dev;
if (client->irq)
- iio_unregister_interrupt_line(indio_dev, 0);
+ free_irq(client->irq, chip->indio_dev);
iio_device_unregister(indio_dev);
iio_free_device(chip->indio_dev);
kfree(chip);
diff --git a/drivers/staging/iio/adc/max1363.h b/drivers/staging/iio/adc/max1363.h
index 8f0fe1ced2ce..360bfc5398fc 100644
--- a/drivers/staging/iio/adc/max1363.h
+++ b/drivers/staging/iio/adc/max1363.h
@@ -67,70 +67,6 @@ struct max1363_mode {
long modemask;
};
-#define MAX1363_MODE_SINGLE(_num, _mask) { \
- .conf = MAX1363_CHANNEL_SEL(_num) \
- | MAX1363_CONFIG_SCAN_SINGLE_1 \
- | MAX1363_CONFIG_SE, \
- .modemask = _mask, \
- }
-
-#define MAX1363_MODE_SCAN_TO_CHANNEL(_num, _mask) { \
- .conf = MAX1363_CHANNEL_SEL(_num) \
- | MAX1363_CONFIG_SCAN_TO_CS \
- | MAX1363_CONFIG_SE, \
- .modemask = _mask, \
- }
-
-
-/* note not available for max1363 hence naming */
-#define MAX1236_MODE_SCAN_MID_TO_CHANNEL(_mid, _num, _mask) { \
- .conf = MAX1363_CHANNEL_SEL(_num) \
- | MAX1236_SCAN_MID_TO_CHANNEL \
- | MAX1363_CONFIG_SE, \
- .modemask = _mask \
-}
-
-#define MAX1363_MODE_DIFF_SINGLE(_nump, _numm, _mask) { \
- .conf = MAX1363_CHANNEL_SEL(_nump) \
- | MAX1363_CONFIG_SCAN_SINGLE_1 \
- | MAX1363_CONFIG_DE, \
- .modemask = _mask \
- }
-
-/* Can't think how to automate naming so specify for now */
-#define MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(_num, _numvals, _mask) { \
- .conf = MAX1363_CHANNEL_SEL(_num) \
- | MAX1363_CONFIG_SCAN_TO_CS \
- | MAX1363_CONFIG_DE, \
- .modemask = _mask \
- }
-
-/* note only available for max1363 hence naming */
-#define MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(_num, _numvals, _mask) { \
- .conf = MAX1363_CHANNEL_SEL(_num) \
- | MAX1236_SCAN_MID_TO_CHANNEL \
- | MAX1363_CONFIG_SE, \
- .modemask = _mask \
-}
-
-/* This may seem an overly long winded way to do this, but at least it makes
- * clear what all the various options actually do. Alternative suggestions
- * that don't require user to have intimate knowledge of the chip welcomed.
- */
-enum max1363_channels {
- max1363_in0, max1363_in1, max1363_in2, max1363_in3,
- max1363_in4, max1363_in5, max1363_in6, max1363_in7,
- max1363_in8, max1363_in9, max1363_in10, max1363_in11,
-
- max1363_in0min1, max1363_in2min3,
- max1363_in4min5, max1363_in6min7,
- max1363_in8min9, max1363_in10min11,
-
- max1363_in1min0, max1363_in3min2,
- max1363_in5min4, max1363_in7min6,
- max1363_in9min8, max1363_in11min10,
-};
-
/* This must be maintained along side the max1363_mode_table in max1363_core */
enum max1363_modes {
/* Single read of a single channel */
@@ -152,37 +88,34 @@ enum max1363_modes {
/**
* struct max1363_chip_info - chip specifc information
* @name: indentification string for chip
- * @num_inputs: number of physical inputs on chip
* @bits: accuracy of the adc in bits
* @int_vref_mv: the internal reference voltage
- * @monitor_mode: whether the chip supports monitor interrupts
+ * @info: iio core function callbacks structure
* @mode_list: array of available scan modes
* @num_modes: the number of scan modes available
* @default_mode: the scan mode in which the chip starts up
+ * @channel: channel specification
+ * @num_channels: number of channels
*/
struct max1363_chip_info {
- u8 num_inputs;
- u8 bits;
- u16 int_vref_mv;
- bool monitor_mode;
+ const struct iio_info *info;
+ struct iio_chan_spec *channels;
+ int num_channels;
const enum max1363_modes *mode_list;
- int num_modes;
enum max1363_modes default_mode;
- struct attribute_group *dev_attrs;
- struct attribute_group *scan_attrs;
+ u16 int_vref_mv;
+ u8 num_modes;
+ u8 bits;
};
/**
* struct max1363_state - driver instance specific data
- * @indio_dev: the industrial I/O device
* @client: i2c_client
* @setupbyte: cache of current device setup byte
* @configbyte: cache of current device config byte
* @chip_info: chip model specific constants, available modes etc
* @current_mode: the scan mode of this chip
* @requestedmask: a valid requested set of channels
- * @poll_work: bottom half of polling interrupt handler
- * @protect_ring: used to ensure only one polling bh running at a time
* @reg: supply regulator
* @monitor_on: whether monitor mode is enabled
* @monitor_speed: parameter corresponding to device monitor speed setting
@@ -190,20 +123,14 @@ struct max1363_chip_info {
* @mask_low: bitmask for enabled low thresholds
* @thresh_high: high threshold values
* @thresh_low: low threshold values
- * @last_timestamp: timestamp of last event interrupt
- * @thresh_work: bh work structure for event handling
*/
struct max1363_state {
- struct iio_dev *indio_dev;
struct i2c_client *client;
u8 setupbyte;
u8 configbyte;
const struct max1363_chip_info *chip_info;
const struct max1363_mode *current_mode;
u32 requestedmask;
- struct work_struct poll_work;
- atomic_t protect_ring;
- struct iio_trigger *trig;
struct regulator *reg;
/* Using monitor modes and buffer at the same time is
@@ -215,8 +142,6 @@ struct max1363_state {
/* 4x unipolar first then the fours bipolar ones */
s16 thresh_high[8];
s16 thresh_low[8];
- s64 last_timestamp;
- struct work_struct thresh_work;
};
const struct max1363_mode
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c
index de83c3b37a2d..98cebd26310f 100644
--- a/drivers/staging/iio/adc/max1363_core.c
+++ b/drivers/staging/iio/adc/max1363_core.c
@@ -22,7 +22,6 @@
*/
#include <linux/interrupt.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/sysfs.h>
@@ -39,38 +38,50 @@
#include "adc.h"
#include "max1363.h"
-/* Here we claim all are 16 bits. This currently does no harm and saves
- * us a lot of scan element listings */
-
-#define MAX1363_SCAN_EL(number) \
- IIO_SCAN_EL_C(in##number, number, 0, NULL);
-#define MAX1363_SCAN_EL_D(p, n, number) \
- IIO_SCAN_NAMED_EL_C(in##p##m##in##n, in##p-in##n, number, 0, NULL);
-
-static MAX1363_SCAN_EL(0);
-static MAX1363_SCAN_EL(1);
-static MAX1363_SCAN_EL(2);
-static MAX1363_SCAN_EL(3);
-static MAX1363_SCAN_EL(4);
-static MAX1363_SCAN_EL(5);
-static MAX1363_SCAN_EL(6);
-static MAX1363_SCAN_EL(7);
-static MAX1363_SCAN_EL(8);
-static MAX1363_SCAN_EL(9);
-static MAX1363_SCAN_EL(10);
-static MAX1363_SCAN_EL(11);
-static MAX1363_SCAN_EL_D(0, 1, 12);
-static MAX1363_SCAN_EL_D(2, 3, 13);
-static MAX1363_SCAN_EL_D(4, 5, 14);
-static MAX1363_SCAN_EL_D(6, 7, 15);
-static MAX1363_SCAN_EL_D(8, 9, 16);
-static MAX1363_SCAN_EL_D(10, 11, 17);
-static MAX1363_SCAN_EL_D(1, 0, 18);
-static MAX1363_SCAN_EL_D(3, 2, 19);
-static MAX1363_SCAN_EL_D(5, 4, 20);
-static MAX1363_SCAN_EL_D(7, 6, 21);
-static MAX1363_SCAN_EL_D(9, 8, 22);
-static MAX1363_SCAN_EL_D(11, 10, 23);
+#define MAX1363_MODE_SINGLE(_num, _mask) { \
+ .conf = MAX1363_CHANNEL_SEL(_num) \
+ | MAX1363_CONFIG_SCAN_SINGLE_1 \
+ | MAX1363_CONFIG_SE, \
+ .modemask = _mask, \
+ }
+
+#define MAX1363_MODE_SCAN_TO_CHANNEL(_num, _mask) { \
+ .conf = MAX1363_CHANNEL_SEL(_num) \
+ | MAX1363_CONFIG_SCAN_TO_CS \
+ | MAX1363_CONFIG_SE, \
+ .modemask = _mask, \
+ }
+
+/* note not available for max1363 hence naming */
+#define MAX1236_MODE_SCAN_MID_TO_CHANNEL(_mid, _num, _mask) { \
+ .conf = MAX1363_CHANNEL_SEL(_num) \
+ | MAX1236_SCAN_MID_TO_CHANNEL \
+ | MAX1363_CONFIG_SE, \
+ .modemask = _mask \
+}
+
+#define MAX1363_MODE_DIFF_SINGLE(_nump, _numm, _mask) { \
+ .conf = MAX1363_CHANNEL_SEL(_nump) \
+ | MAX1363_CONFIG_SCAN_SINGLE_1 \
+ | MAX1363_CONFIG_DE, \
+ .modemask = _mask \
+ }
+
+/* Can't think how to automate naming so specify for now */
+#define MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(_num, _numvals, _mask) { \
+ .conf = MAX1363_CHANNEL_SEL(_num) \
+ | MAX1363_CONFIG_SCAN_TO_CS \
+ | MAX1363_CONFIG_DE, \
+ .modemask = _mask \
+ }
+
+/* note only available for max1363 hence naming */
+#define MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(_num, _numvals, _mask) { \
+ .conf = MAX1363_CHANNEL_SEL(_num) \
+ | MAX1236_SCAN_MID_TO_CHANNEL \
+ | MAX1363_CONFIG_SE, \
+ .modemask = _mask \
+}
static const struct max1363_mode max1363_mode_table[] = {
/* All of the single channel options first */
@@ -147,76 +158,13 @@ const struct max1363_mode
return NULL;
}
-static ssize_t max1363_show_precision_u(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_ring_buffer *ring = dev_get_drvdata(dev);
- struct iio_dev *dev_info = ring->indio_dev;
- struct max1363_state *st = iio_dev_get_devdata(dev_info);
- return sprintf(buf, "u%d/16\n", st->chip_info->bits);
-}
-
-static ssize_t max1363_show_precision_s(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_ring_buffer *ring = dev_get_drvdata(dev);
- struct iio_dev *dev_info = ring->indio_dev;
- struct max1363_state *st = iio_dev_get_devdata(dev_info);
- return sprintf(buf, "s%d/16\n", st->chip_info->bits);
-}
-
-#define MAX1363_SCAN_TYPE(n) \
- DEVICE_ATTR(in##n##_type, S_IRUGO, \
- max1363_show_precision_u, NULL);
-#define MAX1363_SCAN_TYPE_D(p, n) \
- struct device_attribute dev_attr_in##p##m##in##n##_type = \
- __ATTR(in##p-in##n##_type, S_IRUGO, \
- max1363_show_precision_s, NULL);
-
-static MAX1363_SCAN_TYPE(0);
-static MAX1363_SCAN_TYPE(1);
-static MAX1363_SCAN_TYPE(2);
-static MAX1363_SCAN_TYPE(3);
-static MAX1363_SCAN_TYPE(4);
-static MAX1363_SCAN_TYPE(5);
-static MAX1363_SCAN_TYPE(6);
-static MAX1363_SCAN_TYPE(7);
-static MAX1363_SCAN_TYPE(8);
-static MAX1363_SCAN_TYPE(9);
-static MAX1363_SCAN_TYPE(10);
-static MAX1363_SCAN_TYPE(11);
-
-static MAX1363_SCAN_TYPE_D(0, 1);
-static MAX1363_SCAN_TYPE_D(2, 3);
-static MAX1363_SCAN_TYPE_D(4, 5);
-static MAX1363_SCAN_TYPE_D(6, 7);
-static MAX1363_SCAN_TYPE_D(8, 9);
-static MAX1363_SCAN_TYPE_D(10, 11);
-static MAX1363_SCAN_TYPE_D(1, 0);
-static MAX1363_SCAN_TYPE_D(3, 2);
-static MAX1363_SCAN_TYPE_D(5, 4);
-static MAX1363_SCAN_TYPE_D(7, 6);
-static MAX1363_SCAN_TYPE_D(9, 8);
-static MAX1363_SCAN_TYPE_D(11, 10);
-
static int max1363_write_basic_config(struct i2c_client *client,
unsigned char d1,
unsigned char d2)
{
- int ret;
- u8 *tx_buf = kmalloc(2, GFP_KERNEL);
-
- if (!tx_buf)
- return -ENOMEM;
- tx_buf[0] = d1;
- tx_buf[1] = d2;
-
- ret = i2c_master_send(client, tx_buf, 2);
- kfree(tx_buf);
+ u8 tx_buf[2] = {d1, d2};
- return (ret > 0) ? 0 : ret;
+ return i2c_master_send(client, tx_buf, 2);
}
int max1363_set_scan_mode(struct max1363_state *st)
@@ -231,20 +179,19 @@ int max1363_set_scan_mode(struct max1363_state *st)
st->configbyte);
}
-static ssize_t max1363_read_single_channel(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int max1363_read_single_chan(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ long m)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct max1363_state *st = iio_dev_get_devdata(dev_info);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- struct i2c_client *client = st->client;
- int ret = 0, len = 0;
- s32 data ;
+ int ret = 0;
+ s32 data;
char rxbuf[2];
long mask;
+ struct max1363_state *st = iio_priv(indio_dev);
+ struct i2c_client *client = st->client;
- mutex_lock(&dev_info->mlock);
+ mutex_lock(&indio_dev->mlock);
/*
* If monitor mode is enabled, the method for reading a single
* channel will have to be rather different and has not yet
@@ -256,8 +203,8 @@ static ssize_t max1363_read_single_channel(struct device *dev,
}
/* If ring buffer capture is occurring, query the buffer */
- if (iio_ring_enabled(dev_info)) {
- mask = max1363_mode_table[this_attr->address].modemask;
+ if (iio_ring_enabled(indio_dev)) {
+ mask = max1363_mode_table[chan->address].modemask;
data = max1363_single_channel_from_ring(mask, st);
if (data < 0) {
ret = data;
@@ -265,13 +212,11 @@ static ssize_t max1363_read_single_channel(struct device *dev,
}
} else {
/* Check to see if current scan mode is correct */
- if (st->current_mode !=
- &max1363_mode_table[this_attr->address]) {
+ if (st->current_mode != &max1363_mode_table[chan->address]) {
/* Update scan mode if needed */
- st->current_mode
- = &max1363_mode_table[this_attr->address];
+ st->current_mode = &max1363_mode_table[chan->address];
ret = max1363_set_scan_mode(st);
- if (ret)
+ if (ret < 0)
goto error_ret;
}
if (st->chip_info->bits != 8) {
@@ -281,7 +226,6 @@ static ssize_t max1363_read_single_channel(struct device *dev,
ret = data;
goto error_ret;
}
-
data = (s32)(rxbuf[1]) | ((s32)(rxbuf[0] & 0x0F)) << 8;
} else {
/* Get reading */
@@ -293,72 +237,44 @@ static ssize_t max1363_read_single_channel(struct device *dev,
data = rxbuf[0];
}
}
- /* Pretty print the result */
- len = sprintf(buf, "%u\n", data);
-
+ *val = data;
error_ret:
- mutex_unlock(&dev_info->mlock);
- return ret ? ret : len;
-}
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
-/* Direct read attribtues */
-static IIO_DEV_ATTR_IN_RAW(0, max1363_read_single_channel, _s0);
-static IIO_DEV_ATTR_IN_RAW(1, max1363_read_single_channel, _s1);
-static IIO_DEV_ATTR_IN_RAW(2, max1363_read_single_channel, _s2);
-static IIO_DEV_ATTR_IN_RAW(3, max1363_read_single_channel, _s3);
-static IIO_DEV_ATTR_IN_RAW(4, max1363_read_single_channel, _s4);
-static IIO_DEV_ATTR_IN_RAW(5, max1363_read_single_channel, _s5);
-static IIO_DEV_ATTR_IN_RAW(6, max1363_read_single_channel, _s6);
-static IIO_DEV_ATTR_IN_RAW(7, max1363_read_single_channel, _s7);
-static IIO_DEV_ATTR_IN_RAW(8, max1363_read_single_channel, _s8);
-static IIO_DEV_ATTR_IN_RAW(9, max1363_read_single_channel, _s9);
-static IIO_DEV_ATTR_IN_RAW(10, max1363_read_single_channel, _s10);
-static IIO_DEV_ATTR_IN_RAW(11, max1363_read_single_channel, _s11);
-
-static IIO_DEV_ATTR_IN_DIFF_RAW(0, 1, max1363_read_single_channel, d0m1);
-static IIO_DEV_ATTR_IN_DIFF_RAW(2, 3, max1363_read_single_channel, d2m3);
-static IIO_DEV_ATTR_IN_DIFF_RAW(4, 5, max1363_read_single_channel, d4m5);
-static IIO_DEV_ATTR_IN_DIFF_RAW(6, 7, max1363_read_single_channel, d6m7);
-static IIO_DEV_ATTR_IN_DIFF_RAW(8, 9, max1363_read_single_channel, d8m9);
-static IIO_DEV_ATTR_IN_DIFF_RAW(10, 11, max1363_read_single_channel, d10m11);
-static IIO_DEV_ATTR_IN_DIFF_RAW(1, 0, max1363_read_single_channel, d1m0);
-static IIO_DEV_ATTR_IN_DIFF_RAW(3, 2, max1363_read_single_channel, d3m2);
-static IIO_DEV_ATTR_IN_DIFF_RAW(5, 4, max1363_read_single_channel, d5m4);
-static IIO_DEV_ATTR_IN_DIFF_RAW(7, 6, max1363_read_single_channel, d7m6);
-static IIO_DEV_ATTR_IN_DIFF_RAW(9, 8, max1363_read_single_channel, d9m8);
-static IIO_DEV_ATTR_IN_DIFF_RAW(11, 10, max1363_read_single_channel, d11m10);
-
-
-static ssize_t max1363_show_scale(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- /* Driver currently only support internal vref */
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct max1363_state *st = iio_dev_get_devdata(dev_info);
- /* Corresponds to Vref / 2^(bits) */
-
- if ((1 << (st->chip_info->bits + 1))
- > st->chip_info->int_vref_mv)
- return sprintf(buf, "0.5\n");
- else
- return sprintf(buf, "%d\n",
- st->chip_info->int_vref_mv >> st->chip_info->bits);
}
-static IIO_DEVICE_ATTR(in_scale, S_IRUGO, max1363_show_scale, NULL, 0);
-
-static ssize_t max1363_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int max1363_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct max1363_state *st = iio_dev_get_devdata(dev_info);
- return sprintf(buf, "%s\n", st->client->name);
+ struct max1363_state *st = iio_priv(indio_dev);
+ int ret;
+ switch (m) {
+ case 0:
+ ret = max1363_read_single_chan(indio_dev, chan, val, m);
+ if (ret)
+ return ret;
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ if ((1 << (st->chip_info->bits + 1)) >
+ st->chip_info->int_vref_mv) {
+ *val = 0;
+ *val2 = 500000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ } else {
+ *val = (st->chip_info->int_vref_mv)
+ >> st->chip_info->bits;
+ return IIO_VAL_INT;
+ }
+ default:
+ return -EINVAL;
+ }
+ return 0;
}
-static IIO_DEVICE_ATTR(name, S_IRUGO, max1363_show_name, NULL, 0);
-
/* Applies to max1363 */
static const enum max1363_modes max1363_mode_list[] = {
_s0, _s1, _s2, _s3,
@@ -367,48 +283,76 @@ static const enum max1363_modes max1363_mode_list[] = {
d0m1to2m3, d1m0to3m2,
};
-static struct attribute *max1363_device_attrs[] = {
- &iio_dev_attr_in0_raw.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_dev_attr_in2_raw.dev_attr.attr,
- &iio_dev_attr_in3_raw.dev_attr.attr,
- &iio_dev_attr_in0min1_raw.dev_attr.attr,
- &iio_dev_attr_in2min3_raw.dev_attr.attr,
- &iio_dev_attr_in1min0_raw.dev_attr.attr,
- &iio_dev_attr_in3min2_raw.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
- &iio_dev_attr_in_scale.dev_attr.attr,
- NULL
+#define MAX1363_EV_M \
+ (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) \
+ | IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING))
+#define MAX1363_INFO_MASK (1 << IIO_CHAN_INFO_SCALE_SHARED)
+
+static struct iio_chan_spec max1363_channels[] = {
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, MAX1363_INFO_MASK,
+ _s0, 0, IIO_ST('u', 12, 16, 0), MAX1363_EV_M),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, MAX1363_INFO_MASK,
+ _s1, 1, IIO_ST('u', 12, 16, 0), MAX1363_EV_M),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, MAX1363_INFO_MASK,
+ _s2, 2, IIO_ST('u', 12, 16, 0), MAX1363_EV_M),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, MAX1363_INFO_MASK,
+ _s3, 3, IIO_ST('u', 12, 16, 0), MAX1363_EV_M),
+ IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 0, 1, MAX1363_INFO_MASK,
+ d0m1, 4, IIO_ST('s', 12, 16, 0), MAX1363_EV_M),
+ IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 2, 3, MAX1363_INFO_MASK,
+ d2m3, 5, IIO_ST('s', 12, 16, 0), MAX1363_EV_M),
+ IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 1, 0, MAX1363_INFO_MASK,
+ d1m0, 6, IIO_ST('s', 12, 16, 0), MAX1363_EV_M),
+ IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 3, 2, MAX1363_INFO_MASK,
+ d3m2, 7, IIO_ST('s', 12, 16, 0), MAX1363_EV_M),
+ IIO_CHAN_SOFT_TIMESTAMP(8)
};
-static struct attribute_group max1363_dev_attr_group = {
- .attrs = max1363_device_attrs,
+static struct iio_chan_spec max1361_channels[] = {
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, MAX1363_INFO_MASK,
+ _s0, 0, IIO_ST('u', 10, 16, 0), MAX1363_EV_M),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, MAX1363_INFO_MASK,
+ _s1, 1, IIO_ST('u', 10, 16, 0), MAX1363_EV_M),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, MAX1363_INFO_MASK,
+ _s2, 2, IIO_ST('u', 10, 16, 0), MAX1363_EV_M),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, MAX1363_INFO_MASK,
+ _s3, 3, IIO_ST('u', 10, 16, 0), MAX1363_EV_M),
+ IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 0, 1, MAX1363_INFO_MASK,
+ d0m1, 4, IIO_ST('s', 10, 16, 0), MAX1363_EV_M),
+ IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 2, 3, MAX1363_INFO_MASK,
+ d2m3, 5, IIO_ST('s', 10, 16, 0), MAX1363_EV_M),
+ IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 1, 0, MAX1363_INFO_MASK,
+ d1m0, 6, IIO_ST('s', 10, 16, 0), MAX1363_EV_M),
+ IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 3, 2, MAX1363_INFO_MASK,
+ d3m2, 7, IIO_ST('s', 10, 16, 0), MAX1363_EV_M),
+ IIO_CHAN_SOFT_TIMESTAMP(8)
};
-static struct attribute *max1363_scan_el_attrs[] = {
- &iio_scan_el_in0.dev_attr.attr, &dev_attr_in0_type.attr,
- &iio_const_attr_in0_index.dev_attr.attr,
- &iio_scan_el_in1.dev_attr.attr, &dev_attr_in1_type.attr,
- &iio_const_attr_in1_index.dev_attr.attr,
- &iio_scan_el_in2.dev_attr.attr, &dev_attr_in2_type.attr,
- &iio_const_attr_in2_index.dev_attr.attr,
- &iio_scan_el_in3.dev_attr.attr, &dev_attr_in3_type.attr,
- &iio_const_attr_in3_index.dev_attr.attr,
- &iio_scan_el_in0min1.dev_attr.attr, &dev_attr_in0min1_type.attr,
- &iio_const_attr_in0min1_index.dev_attr.attr,
- &iio_scan_el_in2min3.dev_attr.attr, &dev_attr_in2min3_type.attr,
- &iio_const_attr_in2min3_index.dev_attr.attr,
- &iio_scan_el_in1min0.dev_attr.attr, &dev_attr_in1min0_type.attr,
- &iio_const_attr_in1min0_index.dev_attr.attr,
- &iio_scan_el_in3min2.dev_attr.attr, &dev_attr_in3min2_type.attr,
- &iio_const_attr_in3min2_index.dev_attr.attr,
- NULL,
-};
+#define MAX1363_CHAN_U(num, address, scan_index, bits) \
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, num, 0, MAX1363_INFO_MASK, \
+ address, scan_index, IIO_ST('u', bits, \
+ (bits == 8) ? 8 : 16, 0), 0)
+/* bipolar channel */
+#define MAX1363_CHAN_B(num, num2, address, scan_index, bits) \
+ IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, num, num2, MAX1363_INFO_MASK,\
+ address, scan_index, IIO_ST('s', bits, \
+ (bits == 8) ? 8 : 16, 0), 0)
+
+#define MAX1363_4X_CHANS(bits) { \
+ MAX1363_CHAN_U(0, _s0, 0, bits), \
+ MAX1363_CHAN_U(1, _s1, 1, bits), \
+ MAX1363_CHAN_U(2, _s2, 2, bits), \
+ MAX1363_CHAN_U(3, _s3, 3, bits), \
+ MAX1363_CHAN_B(0, 1, d0m1, 4, bits), \
+ MAX1363_CHAN_B(2, 3, d2m3, 5, bits), \
+ MAX1363_CHAN_B(1, 0, d1m0, 6, bits), \
+ MAX1363_CHAN_B(3, 2, d3m2, 7, bits), \
+ IIO_CHAN_SOFT_TIMESTAMP(8) \
+ }
-static struct attribute_group max1363_scan_el_group = {
- .name = "scan_elements",
- .attrs = max1363_scan_el_attrs,
-};
+static struct iio_chan_spec max1036_channels[] = MAX1363_4X_CHANS(8);
+static struct iio_chan_spec max1136_channels[] = MAX1363_4X_CHANS(10);
+static struct iio_chan_spec max1236_channels[] = MAX1363_4X_CHANS(12);
/* Appies to max1236, max1237 */
static const enum max1363_modes max1236_mode_list[] = {
@@ -432,97 +376,36 @@ static const enum max1363_modes max1238_mode_list[] = {
d6m7to8m9, d6m7to10m11, d7m6to9m8, d7m6to11m10,
};
-static struct attribute *max1238_device_attrs[] = {
- &iio_dev_attr_in0_raw.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_dev_attr_in2_raw.dev_attr.attr,
- &iio_dev_attr_in3_raw.dev_attr.attr,
- &iio_dev_attr_in4_raw.dev_attr.attr,
- &iio_dev_attr_in5_raw.dev_attr.attr,
- &iio_dev_attr_in6_raw.dev_attr.attr,
- &iio_dev_attr_in7_raw.dev_attr.attr,
- &iio_dev_attr_in8_raw.dev_attr.attr,
- &iio_dev_attr_in9_raw.dev_attr.attr,
- &iio_dev_attr_in10_raw.dev_attr.attr,
- &iio_dev_attr_in11_raw.dev_attr.attr,
- &iio_dev_attr_in0min1_raw.dev_attr.attr,
- &iio_dev_attr_in2min3_raw.dev_attr.attr,
- &iio_dev_attr_in4min5_raw.dev_attr.attr,
- &iio_dev_attr_in6min7_raw.dev_attr.attr,
- &iio_dev_attr_in8min9_raw.dev_attr.attr,
- &iio_dev_attr_in10min11_raw.dev_attr.attr,
- &iio_dev_attr_in1min0_raw.dev_attr.attr,
- &iio_dev_attr_in3min2_raw.dev_attr.attr,
- &iio_dev_attr_in5min4_raw.dev_attr.attr,
- &iio_dev_attr_in7min6_raw.dev_attr.attr,
- &iio_dev_attr_in9min8_raw.dev_attr.attr,
- &iio_dev_attr_in11min10_raw.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
- &iio_dev_attr_in_scale.dev_attr.attr,
- NULL
-};
-
-static struct attribute_group max1238_dev_attr_group = {
- .attrs = max1238_device_attrs,
-};
-
-static struct attribute *max1238_scan_el_attrs[] = {
- &iio_scan_el_in0.dev_attr.attr, &dev_attr_in0_type.attr,
- &iio_const_attr_in0_index.dev_attr.attr,
- &iio_scan_el_in1.dev_attr.attr, &dev_attr_in1_type.attr,
- &iio_const_attr_in1_index.dev_attr.attr,
- &iio_scan_el_in2.dev_attr.attr, &dev_attr_in2_type.attr,
- &iio_const_attr_in2_index.dev_attr.attr,
- &iio_scan_el_in3.dev_attr.attr, &dev_attr_in3_type.attr,
- &iio_const_attr_in3_index.dev_attr.attr,
- &iio_scan_el_in4.dev_attr.attr, &dev_attr_in4_type.attr,
- &iio_const_attr_in4_index.dev_attr.attr,
- &iio_scan_el_in5.dev_attr.attr, &dev_attr_in5_type.attr,
- &iio_const_attr_in5_index.dev_attr.attr,
- &iio_scan_el_in6.dev_attr.attr, &dev_attr_in6_type.attr,
- &iio_const_attr_in6_index.dev_attr.attr,
- &iio_scan_el_in7.dev_attr.attr, &dev_attr_in7_type.attr,
- &iio_const_attr_in7_index.dev_attr.attr,
- &iio_scan_el_in8.dev_attr.attr, &dev_attr_in8_type.attr,
- &iio_const_attr_in8_index.dev_attr.attr,
- &iio_scan_el_in9.dev_attr.attr, &dev_attr_in9_type.attr,
- &iio_const_attr_in9_index.dev_attr.attr,
- &iio_scan_el_in10.dev_attr.attr, &dev_attr_in10_type.attr,
- &iio_const_attr_in10_index.dev_attr.attr,
- &iio_scan_el_in11.dev_attr.attr, &dev_attr_in11_type.attr,
- &iio_const_attr_in11_index.dev_attr.attr,
- &iio_scan_el_in0min1.dev_attr.attr, &dev_attr_in0min1_type.attr,
- &iio_const_attr_in0min1_index.dev_attr.attr,
- &iio_scan_el_in2min3.dev_attr.attr, &dev_attr_in2min3_type.attr,
- &iio_const_attr_in2min3_index.dev_attr.attr,
- &iio_scan_el_in4min5.dev_attr.attr, &dev_attr_in4min5_type.attr,
- &iio_const_attr_in4min5_index.dev_attr.attr,
- &iio_scan_el_in6min7.dev_attr.attr, &dev_attr_in6min7_type.attr,
- &iio_const_attr_in6min7_index.dev_attr.attr,
- &iio_scan_el_in8min9.dev_attr.attr, &dev_attr_in8min9_type.attr,
- &iio_const_attr_in8min9_index.dev_attr.attr,
- &iio_scan_el_in10min11.dev_attr.attr, &dev_attr_in10min11_type.attr,
- &iio_const_attr_in10min11_index.dev_attr.attr,
- &iio_scan_el_in1min0.dev_attr.attr, &dev_attr_in1min0_type.attr,
- &iio_const_attr_in1min0_index.dev_attr.attr,
- &iio_scan_el_in3min2.dev_attr.attr, &dev_attr_in3min2_type.attr,
- &iio_const_attr_in3min2_index.dev_attr.attr,
- &iio_scan_el_in5min4.dev_attr.attr, &dev_attr_in5min4_type.attr,
- &iio_const_attr_in5min4_index.dev_attr.attr,
- &iio_scan_el_in7min6.dev_attr.attr, &dev_attr_in7min6_type.attr,
- &iio_const_attr_in7min6_index.dev_attr.attr,
- &iio_scan_el_in9min8.dev_attr.attr, &dev_attr_in9min8_type.attr,
- &iio_const_attr_in9min8_index.dev_attr.attr,
- &iio_scan_el_in11min10.dev_attr.attr, &dev_attr_in11min10_type.attr,
- &iio_const_attr_in11min10_index.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group max1238_scan_el_group = {
- .name = "scan_elements",
- .attrs = max1238_scan_el_attrs,
-};
-
+#define MAX1363_12X_CHANS(bits) { \
+ MAX1363_CHAN_U(0, _s0, 0, bits), \
+ MAX1363_CHAN_U(1, _s1, 1, bits), \
+ MAX1363_CHAN_U(2, _s2, 2, bits), \
+ MAX1363_CHAN_U(3, _s3, 3, bits), \
+ MAX1363_CHAN_U(4, _s4, 4, bits), \
+ MAX1363_CHAN_U(5, _s5, 5, bits), \
+ MAX1363_CHAN_U(6, _s6, 6, bits), \
+ MAX1363_CHAN_U(7, _s7, 7, bits), \
+ MAX1363_CHAN_U(8, _s8, 8, bits), \
+ MAX1363_CHAN_U(9, _s9, 9, bits), \
+ MAX1363_CHAN_U(10, _s10, 10, bits), \
+ MAX1363_CHAN_U(11, _s11, 11, bits), \
+ MAX1363_CHAN_B(0, 1, d0m1, 12, bits), \
+ MAX1363_CHAN_B(2, 3, d2m3, 13, bits), \
+ MAX1363_CHAN_B(4, 5, d4m5, 14, bits), \
+ MAX1363_CHAN_B(6, 7, d6m7, 15, bits), \
+ MAX1363_CHAN_B(8, 9, d8m9, 16, bits), \
+ MAX1363_CHAN_B(10, 11, d10m11, 17, bits), \
+ MAX1363_CHAN_B(1, 0, d1m0, 18, bits), \
+ MAX1363_CHAN_B(3, 2, d3m2, 19, bits), \
+ MAX1363_CHAN_B(5, 4, d5m4, 20, bits), \
+ MAX1363_CHAN_B(7, 6, d7m6, 21, bits), \
+ MAX1363_CHAN_B(9, 8, d9m8, 22, bits), \
+ MAX1363_CHAN_B(11, 10, d11m10, 23, bits), \
+ IIO_CHAN_SOFT_TIMESTAMP(24) \
+ }
+static struct iio_chan_spec max1038_channels[] = MAX1363_12X_CHANS(8);
+static struct iio_chan_spec max1138_channels[] = MAX1363_12X_CHANS(10);
+static struct iio_chan_spec max1238_channels[] = MAX1363_12X_CHANS(12);
static const enum max1363_modes max11607_mode_list[] = {
_s0, _s1, _s2, _s3,
@@ -542,72 +425,43 @@ static const enum max1363_modes max11608_mode_list[] = {
d1m0to3m2, d1m0to5m4, d1m0to7m6,
};
-static struct attribute *max11608_device_attrs[] = {
- &iio_dev_attr_in0_raw.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_dev_attr_in2_raw.dev_attr.attr,
- &iio_dev_attr_in3_raw.dev_attr.attr,
- &iio_dev_attr_in4_raw.dev_attr.attr,
- &iio_dev_attr_in5_raw.dev_attr.attr,
- &iio_dev_attr_in6_raw.dev_attr.attr,
- &iio_dev_attr_in7_raw.dev_attr.attr,
- &iio_dev_attr_in0min1_raw.dev_attr.attr,
- &iio_dev_attr_in2min3_raw.dev_attr.attr,
- &iio_dev_attr_in4min5_raw.dev_attr.attr,
- &iio_dev_attr_in6min7_raw.dev_attr.attr,
- &iio_dev_attr_in1min0_raw.dev_attr.attr,
- &iio_dev_attr_in3min2_raw.dev_attr.attr,
- &iio_dev_attr_in5min4_raw.dev_attr.attr,
- &iio_dev_attr_in7min6_raw.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
- &iio_dev_attr_in_scale.dev_attr.attr,
- NULL
-};
+#define MAX1363_8X_CHANS(bits) { \
+ MAX1363_CHAN_U(0, _s0, 0, bits), \
+ MAX1363_CHAN_U(1, _s1, 1, bits), \
+ MAX1363_CHAN_U(2, _s2, 2, bits), \
+ MAX1363_CHAN_U(3, _s3, 3, bits), \
+ MAX1363_CHAN_U(4, _s4, 4, bits), \
+ MAX1363_CHAN_U(5, _s5, 5, bits), \
+ MAX1363_CHAN_U(6, _s6, 6, bits), \
+ MAX1363_CHAN_U(7, _s7, 7, bits), \
+ MAX1363_CHAN_B(0, 1, d0m1, 8, bits), \
+ MAX1363_CHAN_B(2, 3, d2m3, 9, bits), \
+ MAX1363_CHAN_B(4, 5, d4m5, 10, bits), \
+ MAX1363_CHAN_B(6, 7, d6m7, 11, bits), \
+ MAX1363_CHAN_B(1, 0, d1m0, 12, bits), \
+ MAX1363_CHAN_B(3, 2, d3m2, 13, bits), \
+ MAX1363_CHAN_B(5, 4, d5m4, 14, bits), \
+ MAX1363_CHAN_B(7, 6, d7m6, 15, bits), \
+ IIO_CHAN_SOFT_TIMESTAMP(16) \
+ }
+static struct iio_chan_spec max11602_channels[] = MAX1363_8X_CHANS(8);
+static struct iio_chan_spec max11608_channels[] = MAX1363_8X_CHANS(10);
+static struct iio_chan_spec max11614_channels[] = MAX1363_8X_CHANS(12);
-static struct attribute_group max11608_dev_attr_group = {
- .attrs = max11608_device_attrs,
+static const enum max1363_modes max11644_mode_list[] = {
+ _s0, _s1, s0to1, d0m1, d1m0,
};
-static struct attribute *max11608_scan_el_attrs[] = {
- &iio_scan_el_in0.dev_attr.attr, &dev_attr_in0_type.attr,
- &iio_const_attr_in0_index.dev_attr.attr,
- &iio_scan_el_in1.dev_attr.attr, &dev_attr_in1_type.attr,
- &iio_const_attr_in1_index.dev_attr.attr,
- &iio_scan_el_in2.dev_attr.attr, &dev_attr_in2_type.attr,
- &iio_const_attr_in2_index.dev_attr.attr,
- &iio_scan_el_in3.dev_attr.attr, &dev_attr_in3_type.attr,
- &iio_const_attr_in3_index.dev_attr.attr,
- &iio_scan_el_in4.dev_attr.attr, &dev_attr_in4_type.attr,
- &iio_const_attr_in4_index.dev_attr.attr,
- &iio_scan_el_in5.dev_attr.attr, &dev_attr_in5_type.attr,
- &iio_const_attr_in5_index.dev_attr.attr,
- &iio_scan_el_in6.dev_attr.attr, &dev_attr_in6_type.attr,
- &iio_const_attr_in6_index.dev_attr.attr,
- &iio_scan_el_in7.dev_attr.attr, &dev_attr_in7_type.attr,
- &iio_const_attr_in7_index.dev_attr.attr,
- &iio_scan_el_in0min1.dev_attr.attr, &dev_attr_in0min1_type.attr,
- &iio_const_attr_in0min1_index.dev_attr.attr,
- &iio_scan_el_in2min3.dev_attr.attr, &dev_attr_in2min3_type.attr,
- &iio_const_attr_in2min3_index.dev_attr.attr,
- &iio_scan_el_in4min5.dev_attr.attr, &dev_attr_in4min5_type.attr,
- &iio_const_attr_in4min5_index.dev_attr.attr,
- &iio_scan_el_in6min7.dev_attr.attr, &dev_attr_in6min7_type.attr,
- &iio_const_attr_in6min7_index.dev_attr.attr,
- &iio_scan_el_in1min0.dev_attr.attr, &dev_attr_in1min0_type.attr,
- &iio_const_attr_in1min0_index.dev_attr.attr,
- &iio_scan_el_in3min2.dev_attr.attr, &dev_attr_in3min2_type.attr,
- &iio_const_attr_in3min2_index.dev_attr.attr,
- &iio_scan_el_in5min4.dev_attr.attr, &dev_attr_in5min4_type.attr,
- &iio_const_attr_in5min4_index.dev_attr.attr,
- &iio_scan_el_in7min6.dev_attr.attr, &dev_attr_in7min6_type.attr,
- &iio_const_attr_in7min6_index.dev_attr.attr,
- NULL
-};
+#define MAX1363_2X_CHANS(bits) { \
+ MAX1363_CHAN_U(0, _s0, 0, bits), \
+ MAX1363_CHAN_U(1, _s1, 1, bits), \
+ MAX1363_CHAN_B(0, 1, d0m1, 2, bits), \
+ MAX1363_CHAN_B(1, 0, d1m0, 3, bits), \
+ IIO_CHAN_SOFT_TIMESTAMP(4) \
+ }
-static struct attribute_group max11608_scan_el_group = {
- .name = "scan_elements",
- .attrs = max11608_scan_el_attrs,
-};
+static struct iio_chan_spec max11646_channels[] = MAX1363_2X_CHANS(10);
+static struct iio_chan_spec max11644_channels[] = MAX1363_2X_CHANS(12);
enum { max1361,
max1362,
@@ -643,354 +497,10 @@ enum { max1361,
max11615,
max11616,
max11617,
-};
-
-/* max1363 and max1368 tested - rest from data sheet */
-static const struct max1363_chip_info max1363_chip_info_tbl[] = {
- [max1361] = {
- .num_inputs = 4,
- .bits = 10,
- .int_vref_mv = 2048,
- .monitor_mode = 1,
- .mode_list = max1363_mode_list,
- .num_modes = ARRAY_SIZE(max1363_mode_list),
- .default_mode = s0to3,
- .dev_attrs = &max1363_dev_attr_group,
- .scan_attrs = &max1363_scan_el_group,
- },
- [max1362] = {
- .num_inputs = 4,
- .bits = 10,
- .int_vref_mv = 4096,
- .monitor_mode = 1,
- .mode_list = max1363_mode_list,
- .num_modes = ARRAY_SIZE(max1363_mode_list),
- .default_mode = s0to3,
- .dev_attrs = &max1363_dev_attr_group,
- .scan_attrs = &max1363_scan_el_group,
- },
- [max1363] = {
- .num_inputs = 4,
- .bits = 12,
- .int_vref_mv = 2048,
- .monitor_mode = 1,
- .mode_list = max1363_mode_list,
- .num_modes = ARRAY_SIZE(max1363_mode_list),
- .default_mode = s0to3,
- .dev_attrs = &max1363_dev_attr_group,
- .scan_attrs = &max1363_scan_el_group,
- },
- [max1364] = {
- .num_inputs = 4,
- .bits = 12,
- .int_vref_mv = 4096,
- .monitor_mode = 1,
- .mode_list = max1363_mode_list,
- .num_modes = ARRAY_SIZE(max1363_mode_list),
- .default_mode = s0to3,
- .dev_attrs = &max1363_dev_attr_group,
- .scan_attrs = &max1363_scan_el_group,
- },
- [max1036] = {
- .num_inputs = 4,
- .bits = 8,
- .int_vref_mv = 4096,
- .mode_list = max1236_mode_list,
- .num_modes = ARRAY_SIZE(max1236_mode_list),
- .default_mode = s0to3,
- .dev_attrs = &max1363_dev_attr_group,
- .scan_attrs = &max1363_scan_el_group,
- },
- [max1037] = {
- .num_inputs = 4,
- .bits = 8,
- .int_vref_mv = 2048,
- .mode_list = max1236_mode_list,
- .num_modes = ARRAY_SIZE(max1236_mode_list),
- .default_mode = s0to3,
- .dev_attrs = &max1363_dev_attr_group,
- .scan_attrs = &max1363_scan_el_group,
- },
- [max1038] = {
- .num_inputs = 12,
- .bits = 8,
- .int_vref_mv = 4096,
- .mode_list = max1238_mode_list,
- .num_modes = ARRAY_SIZE(max1238_mode_list),
- .default_mode = s0to11,
- .dev_attrs = &max1238_dev_attr_group,
- .scan_attrs = &max1238_scan_el_group,
- },
- [max1039] = {
- .num_inputs = 12,
- .bits = 8,
- .int_vref_mv = 2048,
- .mode_list = max1238_mode_list,
- .num_modes = ARRAY_SIZE(max1238_mode_list),
- .default_mode = s0to11,
- .dev_attrs = &max1238_dev_attr_group,
- .scan_attrs = &max1238_scan_el_group,
- },
- [max1136] = {
- .num_inputs = 4,
- .bits = 10,
- .int_vref_mv = 4096,
- .mode_list = max1236_mode_list,
- .num_modes = ARRAY_SIZE(max1236_mode_list),
- .default_mode = s0to3,
- .dev_attrs = &max1363_dev_attr_group,
- .scan_attrs = &max1363_scan_el_group,
- },
- [max1137] = {
- .num_inputs = 4,
- .bits = 10,
- .int_vref_mv = 2048,
- .mode_list = max1236_mode_list,
- .num_modes = ARRAY_SIZE(max1236_mode_list),
- .default_mode = s0to3,
- .dev_attrs = &max1363_dev_attr_group,
- .scan_attrs = &max1363_scan_el_group,
- },
- [max1138] = {
- .num_inputs = 12,
- .bits = 10,
- .int_vref_mv = 4096,
- .mode_list = max1238_mode_list,
- .num_modes = ARRAY_SIZE(max1238_mode_list),
- .default_mode = s0to11,
- .dev_attrs = &max1238_dev_attr_group,
- .scan_attrs = &max1238_scan_el_group,
- },
- [max1139] = {
- .num_inputs = 12,
- .bits = 10,
- .int_vref_mv = 2048,
- .mode_list = max1238_mode_list,
- .num_modes = ARRAY_SIZE(max1238_mode_list),
- .default_mode = s0to11,
- .dev_attrs = &max1238_dev_attr_group,
- .scan_attrs = &max1238_scan_el_group,
- },
- [max1236] = {
- .num_inputs = 4,
- .bits = 12,
- .int_vref_mv = 4096,
- .mode_list = max1236_mode_list,
- .num_modes = ARRAY_SIZE(max1236_mode_list),
- .default_mode = s0to3,
- .dev_attrs = &max1363_dev_attr_group,
- .scan_attrs = &max1363_scan_el_group,
- },
- [max1237] = {
- .num_inputs = 4,
- .bits = 12,
- .int_vref_mv = 2048,
- .mode_list = max1236_mode_list,
- .num_modes = ARRAY_SIZE(max1236_mode_list),
- .default_mode = s0to3,
- .dev_attrs = &max1363_dev_attr_group,
- .scan_attrs = &max1363_scan_el_group,
- },
- [max1238] = {
- .num_inputs = 12,
- .bits = 12,
- .int_vref_mv = 4096,
- .mode_list = max1238_mode_list,
- .num_modes = ARRAY_SIZE(max1238_mode_list),
- .default_mode = s0to11,
- .dev_attrs = &max1238_dev_attr_group,
- .scan_attrs = &max1238_scan_el_group,
- },
- [max1239] = {
- .num_inputs = 12,
- .bits = 12,
- .int_vref_mv = 2048,
- .mode_list = max1238_mode_list,
- .num_modes = ARRAY_SIZE(max1238_mode_list),
- .default_mode = s0to11,
- .dev_attrs = &max1238_dev_attr_group,
- .scan_attrs = &max1238_scan_el_group,
- },
- [max11600] = {
- .num_inputs = 4,
- .bits = 8,
- .int_vref_mv = 4096,
- .mode_list = max11607_mode_list,
- .num_modes = ARRAY_SIZE(max11607_mode_list),
- .default_mode = s0to3,
- .dev_attrs = &max1363_dev_attr_group,
- .scan_attrs = &max1363_scan_el_group,
- },
- [max11601] = {
- .num_inputs = 4,
- .bits = 8,
- .int_vref_mv = 2048,
- .mode_list = max11607_mode_list,
- .num_modes = ARRAY_SIZE(max11607_mode_list),
- .default_mode = s0to3,
- .dev_attrs = &max1363_dev_attr_group,
- .scan_attrs = &max1363_scan_el_group,
- },
- [max11602] = {
- .num_inputs = 8,
- .bits = 8,
- .int_vref_mv = 4096,
- .mode_list = max11608_mode_list,
- .num_modes = ARRAY_SIZE(max11608_mode_list),
- .default_mode = s0to7,
- .dev_attrs = &max11608_dev_attr_group,
- .scan_attrs = &max11608_scan_el_group,
- },
- [max11603] = {
- .num_inputs = 8,
- .bits = 8,
- .int_vref_mv = 2048,
- .mode_list = max11608_mode_list,
- .num_modes = ARRAY_SIZE(max11608_mode_list),
- .default_mode = s0to7,
- .dev_attrs = &max11608_dev_attr_group,
- .scan_attrs = &max11608_scan_el_group,
- },
- [max11604] = {
- .num_inputs = 12,
- .bits = 8,
- .int_vref_mv = 4098,
- .mode_list = max1238_mode_list,
- .num_modes = ARRAY_SIZE(max1238_mode_list),
- .default_mode = s0to11,
- .dev_attrs = &max1238_dev_attr_group,
- .scan_attrs = &max1238_scan_el_group,
- },
- [max11605] = {
- .num_inputs = 12,
- .bits = 8,
- .int_vref_mv = 2048,
- .mode_list = max1238_mode_list,
- .num_modes = ARRAY_SIZE(max1238_mode_list),
- .default_mode = s0to11,
- .dev_attrs = &max1238_dev_attr_group,
- .scan_attrs = &max1238_scan_el_group,
- },
- [max11606] = {
- .num_inputs = 4,
- .bits = 10,
- .int_vref_mv = 4096,
- .mode_list = max11607_mode_list,
- .num_modes = ARRAY_SIZE(max11607_mode_list),
- .default_mode = s0to3,
- .dev_attrs = &max1363_dev_attr_group,
- .scan_attrs = &max1363_scan_el_group,
- },
- [max11607] = {
- .num_inputs = 4,
- .bits = 10,
- .int_vref_mv = 2048,
- .mode_list = max11607_mode_list,
- .num_modes = ARRAY_SIZE(max11607_mode_list),
- .default_mode = s0to3,
- .dev_attrs = &max1363_dev_attr_group,
- .scan_attrs = &max1363_scan_el_group,
- },
- [max11608] = {
- .num_inputs = 8,
- .bits = 10,
- .int_vref_mv = 4096,
- .mode_list = max11608_mode_list,
- .num_modes = ARRAY_SIZE(max11608_mode_list),
- .default_mode = s0to7,
- .dev_attrs = &max11608_dev_attr_group,
- .scan_attrs = &max11608_scan_el_group,
- },
- [max11609] = {
- .num_inputs = 8,
- .bits = 10,
- .int_vref_mv = 2048,
- .mode_list = max11608_mode_list,
- .num_modes = ARRAY_SIZE(max11608_mode_list),
- .default_mode = s0to7,
- .dev_attrs = &max11608_dev_attr_group,
- .scan_attrs = &max11608_scan_el_group,
- },
- [max11610] = {
- .num_inputs = 12,
- .bits = 10,
- .int_vref_mv = 4098,
- .mode_list = max1238_mode_list,
- .num_modes = ARRAY_SIZE(max1238_mode_list),
- .default_mode = s0to11,
- .dev_attrs = &max1238_dev_attr_group,
- .scan_attrs = &max1238_scan_el_group,
- },
- [max11611] = {
- .num_inputs = 12,
- .bits = 10,
- .int_vref_mv = 2048,
- .mode_list = max1238_mode_list,
- .num_modes = ARRAY_SIZE(max1238_mode_list),
- .default_mode = s0to11,
- .dev_attrs = &max1238_dev_attr_group,
- .scan_attrs = &max1238_scan_el_group,
- },
- [max11612] = {
- .num_inputs = 4,
- .bits = 12,
- .int_vref_mv = 4096,
- .mode_list = max11607_mode_list,
- .num_modes = ARRAY_SIZE(max11607_mode_list),
- .default_mode = s0to3,
- .dev_attrs = &max1363_dev_attr_group,
- .scan_attrs = &max1363_scan_el_group,
- },
- [max11613] = {
- .num_inputs = 4,
- .bits = 12,
- .int_vref_mv = 2048,
- .mode_list = max11607_mode_list,
- .num_modes = ARRAY_SIZE(max11607_mode_list),
- .default_mode = s0to3,
- .dev_attrs = &max1363_dev_attr_group,
- .scan_attrs = &max1363_scan_el_group,
- },
- [max11614] = {
- .num_inputs = 8,
- .bits = 12,
- .int_vref_mv = 4096,
- .mode_list = max11608_mode_list,
- .num_modes = ARRAY_SIZE(max11608_mode_list),
- .default_mode = s0to7,
- .dev_attrs = &max11608_dev_attr_group,
- .scan_attrs = &max11608_scan_el_group,
- },
- [max11615] = {
- .num_inputs = 8,
- .bits = 12,
- .int_vref_mv = 2048,
- .mode_list = max11608_mode_list,
- .num_modes = ARRAY_SIZE(max11608_mode_list),
- .default_mode = s0to7,
- .dev_attrs = &max11608_dev_attr_group,
- .scan_attrs = &max11608_scan_el_group,
- },
- [max11616] = {
- .num_inputs = 12,
- .bits = 12,
- .int_vref_mv = 4098,
- .mode_list = max1238_mode_list,
- .num_modes = ARRAY_SIZE(max1238_mode_list),
- .default_mode = s0to11,
- .dev_attrs = &max1238_dev_attr_group,
- .scan_attrs = &max1238_scan_el_group,
- },
- [max11617] = {
- .num_inputs = 12,
- .bits = 12,
- .int_vref_mv = 2048,
- .mode_list = max1238_mode_list,
- .num_modes = ARRAY_SIZE(max1238_mode_list),
- .default_mode = s0to11,
- .dev_attrs = &max1238_dev_attr_group,
- .scan_attrs = &max1238_scan_el_group,
- }
+ max11644,
+ max11645,
+ max11646,
+ max11647
};
static const int max1363_monitor_speeds[] = { 133000, 665000, 33300, 16600,
@@ -1000,8 +510,7 @@ static ssize_t max1363_monitor_show_freq(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct max1363_state *st = iio_dev_get_devdata(dev_info);
+ struct max1363_state *st = iio_priv(dev_get_drvdata(dev));
return sprintf(buf, "%d\n", max1363_monitor_speeds[st->monitor_speed]);
}
@@ -1010,8 +519,8 @@ static ssize_t max1363_monitor_store_freq(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct max1363_state *st = iio_dev_get_devdata(dev_info);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct max1363_state *st = iio_priv(indio_dev);
int i, ret;
unsigned long val;
bool found = false;
@@ -1027,9 +536,9 @@ static ssize_t max1363_monitor_store_freq(struct device *dev,
if (!found)
return -EINVAL;
- mutex_lock(&dev_info->mlock);
+ mutex_lock(&indio_dev->mlock);
st->monitor_speed = i;
- mutex_unlock(&dev_info->mlock);
+ mutex_unlock(&indio_dev->mlock);
return 0;
}
@@ -1041,52 +550,24 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR,
static IIO_CONST_ATTR(sampling_frequency_available,
"133000 665000 33300 16600 8300 4200 2000 1000");
-static ssize_t max1363_show_thresh(struct device *dev,
- struct device_attribute *attr,
- char *buf,
- bool high)
+static int max1363_read_thresh(struct iio_dev *indio_dev,
+ int event_code,
+ int *val)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct max1363_state *st = iio_dev_get_devdata(dev_info);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
- if (high)
- return sprintf(buf, "%d\n",
- st->thresh_high[this_attr->address]);
+ struct max1363_state *st = iio_priv(indio_dev);
+ if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING)
+ *val = st->thresh_low[IIO_EVENT_CODE_EXTRACT_NUM(event_code)];
else
- return sprintf(buf, "%d\n",
- st->thresh_low[this_attr->address & 0x7]);
-}
-
-static ssize_t max1363_show_thresh_low(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return max1363_show_thresh(dev, attr, buf, false);
+ *val = st->thresh_high[IIO_EVENT_CODE_EXTRACT_NUM(event_code)];
+ return 0;
}
-static ssize_t max1363_show_thresh_high(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int max1363_write_thresh(struct iio_dev *indio_dev,
+ int event_code,
+ int val)
{
- return max1363_show_thresh(dev, attr, buf, true);
-}
-
-static ssize_t max1363_store_thresh_unsigned(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len,
- bool high)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct max1363_state *st = iio_dev_get_devdata(dev_info);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- unsigned long val;
- int ret;
-
- ret = strict_strtoul(buf, 10, &val);
- if (ret)
- return -EINVAL;
+ struct max1363_state *st = iio_priv(indio_dev);
+ /* make it handle signed correctly as well */
switch (st->chip_info->bits) {
case 10:
if (val > 0x3FF)
@@ -1098,220 +579,60 @@ static ssize_t max1363_store_thresh_unsigned(struct device *dev,
break;
}
- switch (high) {
- case 1:
- st->thresh_high[this_attr->address] = val;
- break;
- case 0:
- st->thresh_low[this_attr->address & 0x7] = val;
- break;
- }
-
- return len;
-}
-
-static ssize_t max1363_store_thresh_high_unsigned(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return max1363_store_thresh_unsigned(dev, attr, buf, len, true);
-}
-
-static ssize_t max1363_store_thresh_low_unsigned(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return max1363_store_thresh_unsigned(dev, attr, buf, len, false);
-}
-
-static ssize_t max1363_store_thresh_signed(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len,
- bool high)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct max1363_state *st = iio_dev_get_devdata(dev_info);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- long val;
- int ret;
-
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- return -EINVAL;
- switch (st->chip_info->bits) {
- case 10:
- if (val < -512 || val > 511)
- return -EINVAL;
- break;
- case 12:
- if (val < -2048 || val > 2047)
- return -EINVAL;
- break;
- }
-
- switch (high) {
- case 1:
- st->thresh_high[this_attr->address] = val;
+ switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
+ case IIO_EV_DIR_FALLING:
+ st->thresh_low[IIO_EVENT_CODE_EXTRACT_NUM(event_code)] = val;
break;
- case 0:
- st->thresh_low[this_attr->address & 0x7] = val;
+ case IIO_EV_DIR_RISING:
+ st->thresh_high[IIO_EVENT_CODE_EXTRACT_NUM(event_code)] = val;
break;
}
- return len;
-}
-
-static ssize_t max1363_store_thresh_high_signed(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return max1363_store_thresh_signed(dev, attr, buf, len, true);
-}
-
-static ssize_t max1363_store_thresh_low_signed(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return max1363_store_thresh_signed(dev, attr, buf, len, false);
-}
-
-static IIO_DEVICE_ATTR(in0_thresh_high_value, S_IRUGO | S_IWUSR,
- max1363_show_thresh_high,
- max1363_store_thresh_high_unsigned, 0);
-static IIO_DEVICE_ATTR(in0_thresh_low_value, S_IRUGO | S_IWUSR,
- max1363_show_thresh_low,
- max1363_store_thresh_low_unsigned, 0);
-static IIO_DEVICE_ATTR(in1_thresh_high_value, S_IRUGO | S_IWUSR,
- max1363_show_thresh_high,
- max1363_store_thresh_high_unsigned, 1);
-static IIO_DEVICE_ATTR(in1_thresh_low_value, S_IRUGO | S_IWUSR,
- max1363_show_thresh_low,
- max1363_store_thresh_low_unsigned, 1);
-static IIO_DEVICE_ATTR(in2_thresh_high_value, S_IRUGO | S_IWUSR,
- max1363_show_thresh_high,
- max1363_store_thresh_high_unsigned, 2);
-static IIO_DEVICE_ATTR(in2_thresh_low_value, S_IRUGO | S_IWUSR,
- max1363_show_thresh_low,
- max1363_store_thresh_low_unsigned, 2);
-static IIO_DEVICE_ATTR(in3_thresh_high_value, S_IRUGO | S_IWUSR,
- max1363_show_thresh_high,
- max1363_store_thresh_high_unsigned, 3);
-static IIO_DEVICE_ATTR(in3_thresh_low_value, S_IRUGO | S_IWUSR,
- max1363_show_thresh_low,
- max1363_store_thresh_low_unsigned, 3);
-
-static IIO_DEVICE_ATTR_NAMED(in0min1_thresh_high_value,
- in0-in1_thresh_high_value,
- S_IRUGO | S_IWUSR, max1363_show_thresh_high,
- max1363_store_thresh_high_signed, 4);
-static IIO_DEVICE_ATTR_NAMED(in0min1_thresh_low_value,
- in0-in1_thresh_low_value,
- S_IRUGO | S_IWUSR, max1363_show_thresh_low,
- max1363_store_thresh_low_signed, 4);
-static IIO_DEVICE_ATTR_NAMED(in2min3_thresh_high_value,
- in2-in3_thresh_high_value,
- S_IRUGO | S_IWUSR, max1363_show_thresh_high,
- max1363_store_thresh_high_signed, 5);
-static IIO_DEVICE_ATTR_NAMED(in2min3_thresh_low_value,
- in2-in3_thresh_low_value,
- S_IRUGO | S_IWUSR, max1363_show_thresh_low,
- max1363_store_thresh_low_signed, 5);
-static IIO_DEVICE_ATTR_NAMED(in1min0_thresh_high_value,
- in1-in0_thresh_high_value,
- S_IRUGO | S_IWUSR, max1363_show_thresh_high,
- max1363_store_thresh_high_signed, 6);
-static IIO_DEVICE_ATTR_NAMED(in1min0_thresh_low_value,
- in1-in0_thresh_low_value,
- S_IRUGO | S_IWUSR, max1363_show_thresh_low,
- max1363_store_thresh_low_signed, 6);
-static IIO_DEVICE_ATTR_NAMED(in3min2_thresh_high_value,
- in3-in2_thresh_high_value,
- S_IRUGO | S_IWUSR, max1363_show_thresh_high,
- max1363_store_thresh_high_signed, 7);
-static IIO_DEVICE_ATTR_NAMED(in3min2_thresh_low_value,
- in3-in2_thresh_low_value,
- S_IRUGO | S_IWUSR, max1363_show_thresh_low,
- max1363_store_thresh_low_signed, 7);
-
-static int max1363_int_th(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int not_test)
-{
- struct max1363_state *st = dev_info->dev_data;
-
- st->last_timestamp = timestamp;
- schedule_work(&st->thresh_work);
return 0;
}
-static void max1363_thresh_handler_bh(struct work_struct *work_s)
+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)
+};
+
+static irqreturn_t max1363_event_handler(int irq, void *private)
{
- struct max1363_state *st = container_of(work_s, struct max1363_state,
- thresh_work);
+ struct iio_dev *indio_dev = private;
+ struct max1363_state *st = iio_priv(indio_dev);
+ s64 timestamp = iio_get_time_ns();
+ unsigned long mask, loc;
u8 rx;
u8 tx[2] = { st->setupbyte,
MAX1363_MON_INT_ENABLE | (st->monitor_speed << 1) | 0xF0 };
i2c_master_recv(st->client, &rx, 1);
- if (rx & (1 << 0))
- iio_push_event(st->indio_dev, 0,
- IIO_EVENT_CODE_IN_LOW_THRESH(3),
- st->last_timestamp);
- if (rx & (1 << 1))
- iio_push_event(st->indio_dev, 0,
- IIO_EVENT_CODE_IN_HIGH_THRESH(3),
- st->last_timestamp);
- if (rx & (1 << 2))
- iio_push_event(st->indio_dev, 0,
- IIO_EVENT_CODE_IN_LOW_THRESH(2),
- st->last_timestamp);
- if (rx & (1 << 3))
- iio_push_event(st->indio_dev, 0,
- IIO_EVENT_CODE_IN_HIGH_THRESH(2),
- st->last_timestamp);
- if (rx & (1 << 4))
- iio_push_event(st->indio_dev, 0,
- IIO_EVENT_CODE_IN_LOW_THRESH(1),
- st->last_timestamp);
- if (rx & (1 << 5))
- iio_push_event(st->indio_dev, 0,
- IIO_EVENT_CODE_IN_HIGH_THRESH(1),
- st->last_timestamp);
- if (rx & (1 << 6))
- iio_push_event(st->indio_dev, 0,
- IIO_EVENT_CODE_IN_LOW_THRESH(0),
- st->last_timestamp);
- if (rx & (1 << 7))
- iio_push_event(st->indio_dev, 0,
- IIO_EVENT_CODE_IN_HIGH_THRESH(0),
- st->last_timestamp);
- enable_irq(st->client->irq);
+ mask = rx;
+ for_each_set_bit(loc, &mask, 8)
+ iio_push_event(indio_dev, 0, max1363_event_codes[loc],
+ timestamp);
i2c_master_send(st->client, tx, 2);
+
+ return IRQ_HANDLED;
}
-static ssize_t max1363_read_interrupt_config(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int max1363_read_event_config(struct iio_dev *indio_dev,
+ int event_code)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct max1363_state *st = iio_dev_get_devdata(dev_info);
- struct iio_event_attr *this_attr = to_iio_event_attr(attr);
- int val;
+ struct max1363_state *st = iio_priv(indio_dev);
- mutex_lock(&dev_info->mlock);
- if (this_attr->mask & 0x8)
- val = (1 << (this_attr->mask & 0x7)) & st->mask_low;
+ int val;
+ int number = IIO_EVENT_CODE_EXTRACT_NUM(event_code);
+ mutex_lock(&indio_dev->mlock);
+ if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING)
+ val = (1 << number) & st->mask_low;
else
- val = (1 << this_attr->mask) & st->mask_high;
- mutex_unlock(&dev_info->mlock);
+ val = (1 << number) & st->mask_high;
+ mutex_unlock(&indio_dev->mlock);
- return sprintf(buf, "%d\n", !!val);
+ return val;
}
static int max1363_monitor_mode_update(struct max1363_state *st, int enabled)
@@ -1428,6 +749,7 @@ error_ret:
* To keep this manageable we always use one of 3 scan modes.
* Scan 0...3, 0-1,2-3 and 1-0,3-2
*/
+
static inline int __max1363_check_event_mask(int thismask, int checkmask)
{
int ret = 0;
@@ -1448,206 +770,54 @@ error_ret:
return ret;
}
-static ssize_t max1363_write_interrupt_config(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+static int max1363_write_event_config(struct iio_dev *indio_dev,
+ int event_code,
+ int state)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct max1363_state *st = iio_dev_get_devdata(dev_info);
- struct iio_event_attr *this_attr = to_iio_event_attr(attr);
- unsigned long val;
- int ret;
+ int ret = 0;
+ struct max1363_state *st = iio_priv(indio_dev);
u16 unifiedmask;
- ret = strict_strtoul(buf, 10, &val);
- if (ret)
- return -EINVAL;
- mutex_lock(&st->indio_dev->mlock);
+ int number = IIO_EVENT_CODE_EXTRACT_NUM(event_code);
+
+ mutex_lock(&indio_dev->mlock);
unifiedmask = st->mask_low | st->mask_high;
- if (this_attr->mask & 0x08) {
- /* If we are disabling no need to test */
- if (val == 0)
- st->mask_low &= ~(1 << (this_attr->mask & 0x7));
+ if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING) {
+
+ if (state == 0)
+ st->mask_low &= ~(1 << number);
else {
- ret = __max1363_check_event_mask(this_attr->mask & 0x7,
- unifiedmask);
+ ret = __max1363_check_event_mask((1 << number),
+ unifiedmask);
if (ret)
goto error_ret;
- st->mask_low |= (1 << (this_attr->mask & 0x7));
+ st->mask_low |= (1 << number);
}
} else {
- if (val == 0)
- st->mask_high &= ~(1 << (this_attr->mask));
+ if (state == 0)
+ st->mask_high &= ~(1 << number);
else {
- ret = __max1363_check_event_mask(this_attr->mask,
- unifiedmask);
+ ret = __max1363_check_event_mask((1 << number),
+ unifiedmask);
if (ret)
goto error_ret;
- st->mask_high |= (1 << this_attr->mask);
+ st->mask_high |= (1 << number);
}
}
- if (st->monitor_on && !st->mask_high && !st->mask_low)
- iio_remove_event_from_list(this_attr->listel,
- &dev_info->interrupts[0]->ev_list);
- if (!st->monitor_on && val)
- iio_add_event_to_list(this_attr->listel,
- &dev_info->interrupts[0]->ev_list);
max1363_monitor_mode_update(st, !!(st->mask_high | st->mask_low));
error_ret:
- mutex_unlock(&st->indio_dev->mlock);
+ mutex_unlock(&indio_dev->mlock);
- return len;
+ return ret;
}
-IIO_EVENT_SH(max1363_thresh, max1363_int_th);
-
-#define MAX1363_HIGH_THRESH(a) a
-#define MAX1363_LOW_THRESH(a) (a | 0x8)
-
-IIO_EVENT_ATTR_SH(in0_thresh_high_en,
- iio_event_max1363_thresh,
- max1363_read_interrupt_config,
- max1363_write_interrupt_config,
- MAX1363_HIGH_THRESH(0));
-
-IIO_EVENT_ATTR_SH(in0_thresh_low_en,
- iio_event_max1363_thresh,
- max1363_read_interrupt_config,
- max1363_write_interrupt_config,
- MAX1363_LOW_THRESH(0));
-
-IIO_EVENT_ATTR_SH(in1_thresh_high_en,
- iio_event_max1363_thresh,
- max1363_read_interrupt_config,
- max1363_write_interrupt_config,
- MAX1363_HIGH_THRESH(1));
-
-IIO_EVENT_ATTR_SH(in1_thresh_low_en,
- iio_event_max1363_thresh,
- max1363_read_interrupt_config,
- max1363_write_interrupt_config,
- MAX1363_LOW_THRESH(1));
-
-IIO_EVENT_ATTR_SH(in2_thresh_high_en,
- iio_event_max1363_thresh,
- max1363_read_interrupt_config,
- max1363_write_interrupt_config,
- MAX1363_HIGH_THRESH(2));
-
-IIO_EVENT_ATTR_SH(in2_thresh_low_en,
- iio_event_max1363_thresh,
- max1363_read_interrupt_config,
- max1363_write_interrupt_config,
- MAX1363_LOW_THRESH(2));
-
-IIO_EVENT_ATTR_SH(in3_thresh_high_en,
- iio_event_max1363_thresh,
- max1363_read_interrupt_config,
- max1363_write_interrupt_config,
- MAX1363_HIGH_THRESH(3));
-
-IIO_EVENT_ATTR_SH(in3_thresh_low_en,
- iio_event_max1363_thresh,
- max1363_read_interrupt_config,
- max1363_write_interrupt_config,
- MAX1363_LOW_THRESH(3));
-
-IIO_EVENT_ATTR_NAMED_SH(in0min1_thresh_high_en,
- in0-in1_thresh_high_en,
- iio_event_max1363_thresh,
- max1363_read_interrupt_config,
- max1363_write_interrupt_config,
- MAX1363_HIGH_THRESH(4));
-
-IIO_EVENT_ATTR_NAMED_SH(in0min1_thresh_low_en,
- in0-in1_thresh_low_en,
- iio_event_max1363_thresh,
- max1363_read_interrupt_config,
- max1363_write_interrupt_config,
- MAX1363_LOW_THRESH(4));
-
-IIO_EVENT_ATTR_NAMED_SH(in3min2_thresh_high_en,
- in3-in2_thresh_high_en,
- iio_event_max1363_thresh,
- max1363_read_interrupt_config,
- max1363_write_interrupt_config,
- MAX1363_HIGH_THRESH(5));
-
-IIO_EVENT_ATTR_NAMED_SH(in3min2_thresh_low_en,
- in3-in2_thresh_low_en,
- iio_event_max1363_thresh,
- max1363_read_interrupt_config,
- max1363_write_interrupt_config,
- MAX1363_LOW_THRESH(5));
-
-IIO_EVENT_ATTR_NAMED_SH(in1min0_thresh_high_en,
- in1-in0_thresh_high_en,
- iio_event_max1363_thresh,
- max1363_read_interrupt_config,
- max1363_write_interrupt_config,
- MAX1363_HIGH_THRESH(6));
-
-IIO_EVENT_ATTR_NAMED_SH(in1min0_thresh_low_en,
- in1-in0_thresh_low_en,
- iio_event_max1363_thresh,
- max1363_read_interrupt_config,
- max1363_write_interrupt_config,
- MAX1363_LOW_THRESH(6));
-
-IIO_EVENT_ATTR_NAMED_SH(in2min3_thresh_high_en,
- in2-in3_thresh_high_en,
- iio_event_max1363_thresh,
- max1363_read_interrupt_config,
- max1363_write_interrupt_config,
- MAX1363_HIGH_THRESH(7));
-
-IIO_EVENT_ATTR_NAMED_SH(in2min3_thresh_low_en,
- in2-in3_thresh_low_en,
- iio_event_max1363_thresh,
- max1363_read_interrupt_config,
- max1363_write_interrupt_config,
- MAX1363_LOW_THRESH(7));
-
/*
* As with scan_elements, only certain sets of these can
* be combined.
*/
static struct attribute *max1363_event_attributes[] = {
- &iio_dev_attr_in0_thresh_high_value.dev_attr.attr,
- &iio_dev_attr_in0_thresh_low_value.dev_attr.attr,
- &iio_dev_attr_in1_thresh_high_value.dev_attr.attr,
- &iio_dev_attr_in1_thresh_low_value.dev_attr.attr,
- &iio_dev_attr_in2_thresh_high_value.dev_attr.attr,
- &iio_dev_attr_in2_thresh_low_value.dev_attr.attr,
- &iio_dev_attr_in3_thresh_high_value.dev_attr.attr,
- &iio_dev_attr_in3_thresh_low_value.dev_attr.attr,
- &iio_dev_attr_in0min1_thresh_high_value.dev_attr.attr,
- &iio_dev_attr_in0min1_thresh_low_value.dev_attr.attr,
- &iio_dev_attr_in2min3_thresh_high_value.dev_attr.attr,
- &iio_dev_attr_in2min3_thresh_low_value.dev_attr.attr,
- &iio_dev_attr_in1min0_thresh_high_value.dev_attr.attr,
- &iio_dev_attr_in1min0_thresh_low_value.dev_attr.attr,
- &iio_dev_attr_in3min2_thresh_high_value.dev_attr.attr,
- &iio_dev_attr_in3min2_thresh_low_value.dev_attr.attr,
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
- &iio_event_attr_in0_thresh_high_en.dev_attr.attr,
- &iio_event_attr_in0_thresh_low_en.dev_attr.attr,
- &iio_event_attr_in1_thresh_high_en.dev_attr.attr,
- &iio_event_attr_in1_thresh_low_en.dev_attr.attr,
- &iio_event_attr_in2_thresh_high_en.dev_attr.attr,
- &iio_event_attr_in2_thresh_low_en.dev_attr.attr,
- &iio_event_attr_in3_thresh_high_en.dev_attr.attr,
- &iio_event_attr_in3_thresh_low_en.dev_attr.attr,
- &iio_event_attr_in0min1_thresh_high_en.dev_attr.attr,
- &iio_event_attr_in0min1_thresh_low_en.dev_attr.attr,
- &iio_event_attr_in3min2_thresh_high_en.dev_attr.attr,
- &iio_event_attr_in3min2_thresh_low_en.dev_attr.attr,
- &iio_event_attr_in1min0_thresh_high_en.dev_attr.attr,
- &iio_event_attr_in1min0_thresh_low_en.dev_attr.attr,
- &iio_event_attr_in2min3_thresh_high_en.dev_attr.attr,
- &iio_event_attr_in2min3_thresh_low_en.dev_attr.attr,
NULL,
};
@@ -1655,6 +825,411 @@ static struct attribute_group max1363_event_attribute_group = {
.attrs = max1363_event_attributes,
};
+#define MAX1363_EVENT_FUNCS \
+
+
+static const struct iio_info max1238_info = {
+ .read_raw = &max1363_read_raw,
+ .driver_module = THIS_MODULE,
+};
+
+static const struct iio_info max1363_info = {
+ .read_event_value = &max1363_read_thresh,
+ .write_event_value = &max1363_write_thresh,
+ .read_event_config = &max1363_read_event_config,
+ .write_event_config = &max1363_write_event_config,
+ .read_raw = &max1363_read_raw,
+ .driver_module = THIS_MODULE,
+ .num_interrupt_lines = 1,
+ .event_attrs = &max1363_event_attribute_group,
+};
+
+/* max1363 and max1368 tested - rest from data sheet */
+static const struct max1363_chip_info max1363_chip_info_tbl[] = {
+ [max1361] = {
+ .bits = 10,
+ .int_vref_mv = 2048,
+ .mode_list = max1363_mode_list,
+ .num_modes = ARRAY_SIZE(max1363_mode_list),
+ .default_mode = s0to3,
+ .channels = max1361_channels,
+ .num_channels = ARRAY_SIZE(max1361_channels),
+ .info = &max1363_info,
+ },
+ [max1362] = {
+ .bits = 10,
+ .int_vref_mv = 4096,
+ .mode_list = max1363_mode_list,
+ .num_modes = ARRAY_SIZE(max1363_mode_list),
+ .default_mode = s0to3,
+ .channels = max1361_channels,
+ .num_channels = ARRAY_SIZE(max1361_channels),
+ .info = &max1363_info,
+ },
+ [max1363] = {
+ .bits = 12,
+ .int_vref_mv = 2048,
+ .mode_list = max1363_mode_list,
+ .num_modes = ARRAY_SIZE(max1363_mode_list),
+ .default_mode = s0to3,
+ .channels = max1363_channels,
+ .num_channels = ARRAY_SIZE(max1363_channels),
+ .info = &max1363_info,
+ },
+ [max1364] = {
+ .bits = 12,
+ .int_vref_mv = 4096,
+ .mode_list = max1363_mode_list,
+ .num_modes = ARRAY_SIZE(max1363_mode_list),
+ .default_mode = s0to3,
+ .channels = max1363_channels,
+ .num_channels = ARRAY_SIZE(max1363_channels),
+ .info = &max1363_info,
+ },
+ [max1036] = {
+ .bits = 8,
+ .int_vref_mv = 4096,
+ .mode_list = max1236_mode_list,
+ .num_modes = ARRAY_SIZE(max1236_mode_list),
+ .default_mode = s0to3,
+ .info = &max1238_info,
+ .channels = max1036_channels,
+ .num_channels = ARRAY_SIZE(max1036_channels),
+ },
+ [max1037] = {
+ .bits = 8,
+ .int_vref_mv = 2048,
+ .mode_list = max1236_mode_list,
+ .num_modes = ARRAY_SIZE(max1236_mode_list),
+ .default_mode = s0to3,
+ .info = &max1238_info,
+ .channels = max1036_channels,
+ .num_channels = ARRAY_SIZE(max1036_channels),
+ },
+ [max1038] = {
+ .bits = 8,
+ .int_vref_mv = 4096,
+ .mode_list = max1238_mode_list,
+ .num_modes = ARRAY_SIZE(max1238_mode_list),
+ .default_mode = s0to11,
+ .info = &max1238_info,
+ .channels = max1038_channels,
+ .num_channels = ARRAY_SIZE(max1038_channels),
+ },
+ [max1039] = {
+ .bits = 8,
+ .int_vref_mv = 2048,
+ .mode_list = max1238_mode_list,
+ .num_modes = ARRAY_SIZE(max1238_mode_list),
+ .default_mode = s0to11,
+ .info = &max1238_info,
+ .channels = max1038_channels,
+ .num_channels = ARRAY_SIZE(max1038_channels),
+ },
+ [max1136] = {
+ .bits = 10,
+ .int_vref_mv = 4096,
+ .mode_list = max1236_mode_list,
+ .num_modes = ARRAY_SIZE(max1236_mode_list),
+ .default_mode = s0to3,
+ .info = &max1238_info,
+ .channels = max1136_channels,
+ .num_channels = ARRAY_SIZE(max1136_channels),
+ },
+ [max1137] = {
+ .bits = 10,
+ .int_vref_mv = 2048,
+ .mode_list = max1236_mode_list,
+ .num_modes = ARRAY_SIZE(max1236_mode_list),
+ .default_mode = s0to3,
+ .info = &max1238_info,
+ .channels = max1136_channels,
+ .num_channels = ARRAY_SIZE(max1136_channels),
+ },
+ [max1138] = {
+ .bits = 10,
+ .int_vref_mv = 4096,
+ .mode_list = max1238_mode_list,
+ .num_modes = ARRAY_SIZE(max1238_mode_list),
+ .default_mode = s0to11,
+ .info = &max1238_info,
+ .channels = max1138_channels,
+ .num_channels = ARRAY_SIZE(max1138_channels),
+ },
+ [max1139] = {
+ .bits = 10,
+ .int_vref_mv = 2048,
+ .mode_list = max1238_mode_list,
+ .num_modes = ARRAY_SIZE(max1238_mode_list),
+ .default_mode = s0to11,
+ .info = &max1238_info,
+ .channels = max1138_channels,
+ .num_channels = ARRAY_SIZE(max1138_channels),
+ },
+ [max1236] = {
+ .bits = 12,
+ .int_vref_mv = 4096,
+ .mode_list = max1236_mode_list,
+ .num_modes = ARRAY_SIZE(max1236_mode_list),
+ .default_mode = s0to3,
+ .info = &max1238_info,
+ .channels = max1236_channels,
+ .num_channels = ARRAY_SIZE(max1236_channels),
+ },
+ [max1237] = {
+ .bits = 12,
+ .int_vref_mv = 2048,
+ .mode_list = max1236_mode_list,
+ .num_modes = ARRAY_SIZE(max1236_mode_list),
+ .default_mode = s0to3,
+ .info = &max1238_info,
+ .channels = max1236_channels,
+ .num_channels = ARRAY_SIZE(max1236_channels),
+ },
+ [max1238] = {
+ .bits = 12,
+ .int_vref_mv = 4096,
+ .mode_list = max1238_mode_list,
+ .num_modes = ARRAY_SIZE(max1238_mode_list),
+ .default_mode = s0to11,
+ .info = &max1238_info,
+ .channels = max1238_channels,
+ .num_channels = ARRAY_SIZE(max1238_channels),
+ },
+ [max1239] = {
+ .bits = 12,
+ .int_vref_mv = 2048,
+ .mode_list = max1238_mode_list,
+ .num_modes = ARRAY_SIZE(max1238_mode_list),
+ .default_mode = s0to11,
+ .info = &max1238_info,
+ .channels = max1238_channels,
+ .num_channels = ARRAY_SIZE(max1238_channels),
+ },
+ [max11600] = {
+ .bits = 8,
+ .int_vref_mv = 4096,
+ .mode_list = max11607_mode_list,
+ .num_modes = ARRAY_SIZE(max11607_mode_list),
+ .default_mode = s0to3,
+ .info = &max1238_info,
+ .channels = max1036_channels,
+ .num_channels = ARRAY_SIZE(max1036_channels),
+ },
+ [max11601] = {
+ .bits = 8,
+ .int_vref_mv = 2048,
+ .mode_list = max11607_mode_list,
+ .num_modes = ARRAY_SIZE(max11607_mode_list),
+ .default_mode = s0to3,
+ .info = &max1238_info,
+ .channels = max1036_channels,
+ .num_channels = ARRAY_SIZE(max1036_channels),
+ },
+ [max11602] = {
+ .bits = 8,
+ .int_vref_mv = 4096,
+ .mode_list = max11608_mode_list,
+ .num_modes = ARRAY_SIZE(max11608_mode_list),
+ .default_mode = s0to7,
+ .info = &max1238_info,
+ .channels = max11602_channels,
+ .num_channels = ARRAY_SIZE(max11602_channels),
+ },
+ [max11603] = {
+ .bits = 8,
+ .int_vref_mv = 2048,
+ .mode_list = max11608_mode_list,
+ .num_modes = ARRAY_SIZE(max11608_mode_list),
+ .default_mode = s0to7,
+ .info = &max1238_info,
+ .channels = max11602_channels,
+ .num_channels = ARRAY_SIZE(max11602_channels),
+ },
+ [max11604] = {
+ .bits = 8,
+ .int_vref_mv = 4098,
+ .mode_list = max1238_mode_list,
+ .num_modes = ARRAY_SIZE(max1238_mode_list),
+ .default_mode = s0to11,
+ .info = &max1238_info,
+ .channels = max1238_channels,
+ .num_channels = ARRAY_SIZE(max1238_channels),
+ },
+ [max11605] = {
+ .bits = 8,
+ .int_vref_mv = 2048,
+ .mode_list = max1238_mode_list,
+ .num_modes = ARRAY_SIZE(max1238_mode_list),
+ .default_mode = s0to11,
+ .info = &max1238_info,
+ .channels = max1238_channels,
+ .num_channels = ARRAY_SIZE(max1238_channels),
+ },
+ [max11606] = {
+ .bits = 10,
+ .int_vref_mv = 4096,
+ .mode_list = max11607_mode_list,
+ .num_modes = ARRAY_SIZE(max11607_mode_list),
+ .default_mode = s0to3,
+ .info = &max1238_info,
+ .channels = max1136_channels,
+ .num_channels = ARRAY_SIZE(max1136_channels),
+ },
+ [max11607] = {
+ .bits = 10,
+ .int_vref_mv = 2048,
+ .mode_list = max11607_mode_list,
+ .num_modes = ARRAY_SIZE(max11607_mode_list),
+ .default_mode = s0to3,
+ .info = &max1238_info,
+ .channels = max1136_channels,
+ .num_channels = ARRAY_SIZE(max1136_channels),
+ },
+ [max11608] = {
+ .bits = 10,
+ .int_vref_mv = 4096,
+ .mode_list = max11608_mode_list,
+ .num_modes = ARRAY_SIZE(max11608_mode_list),
+ .default_mode = s0to7,
+ .info = &max1238_info,
+ .channels = max11608_channels,
+ .num_channels = ARRAY_SIZE(max11608_channels),
+ },
+ [max11609] = {
+ .bits = 10,
+ .int_vref_mv = 2048,
+ .mode_list = max11608_mode_list,
+ .num_modes = ARRAY_SIZE(max11608_mode_list),
+ .default_mode = s0to7,
+ .info = &max1238_info,
+ .channels = max11608_channels,
+ .num_channels = ARRAY_SIZE(max11608_channels),
+ },
+ [max11610] = {
+ .bits = 10,
+ .int_vref_mv = 4098,
+ .mode_list = max1238_mode_list,
+ .num_modes = ARRAY_SIZE(max1238_mode_list),
+ .default_mode = s0to11,
+ .info = &max1238_info,
+ .channels = max1238_channels,
+ .num_channels = ARRAY_SIZE(max1238_channels),
+ },
+ [max11611] = {
+ .bits = 10,
+ .int_vref_mv = 2048,
+ .mode_list = max1238_mode_list,
+ .num_modes = ARRAY_SIZE(max1238_mode_list),
+ .default_mode = s0to11,
+ .info = &max1238_info,
+ .channels = max1238_channels,
+ .num_channels = ARRAY_SIZE(max1238_channels),
+ },
+ [max11612] = {
+ .bits = 12,
+ .int_vref_mv = 4096,
+ .mode_list = max11607_mode_list,
+ .num_modes = ARRAY_SIZE(max11607_mode_list),
+ .default_mode = s0to3,
+ .info = &max1238_info,
+ .channels = max1363_channels,
+ .num_channels = ARRAY_SIZE(max1363_channels),
+ },
+ [max11613] = {
+ .bits = 12,
+ .int_vref_mv = 2048,
+ .mode_list = max11607_mode_list,
+ .num_modes = ARRAY_SIZE(max11607_mode_list),
+ .default_mode = s0to3,
+ .info = &max1238_info,
+ .channels = max1363_channels,
+ .num_channels = ARRAY_SIZE(max1363_channels),
+ },
+ [max11614] = {
+ .bits = 12,
+ .int_vref_mv = 4096,
+ .mode_list = max11608_mode_list,
+ .num_modes = ARRAY_SIZE(max11608_mode_list),
+ .default_mode = s0to7,
+ .info = &max1238_info,
+ .channels = max11614_channels,
+ .num_channels = ARRAY_SIZE(max11614_channels),
+ },
+ [max11615] = {
+ .bits = 12,
+ .int_vref_mv = 2048,
+ .mode_list = max11608_mode_list,
+ .num_modes = ARRAY_SIZE(max11608_mode_list),
+ .default_mode = s0to7,
+ .info = &max1238_info,
+ .channels = max11614_channels,
+ .num_channels = ARRAY_SIZE(max11614_channels),
+ },
+ [max11616] = {
+ .bits = 12,
+ .int_vref_mv = 4098,
+ .mode_list = max1238_mode_list,
+ .num_modes = ARRAY_SIZE(max1238_mode_list),
+ .default_mode = s0to11,
+ .info = &max1238_info,
+ .channels = max1238_channels,
+ .num_channels = ARRAY_SIZE(max1238_channels),
+ },
+ [max11617] = {
+ .bits = 12,
+ .int_vref_mv = 2048,
+ .mode_list = max1238_mode_list,
+ .num_modes = ARRAY_SIZE(max1238_mode_list),
+ .default_mode = s0to11,
+ .info = &max1238_info,
+ .channels = max1238_channels,
+ .num_channels = ARRAY_SIZE(max1238_channels),
+ },
+ [max11644] = {
+ .bits = 12,
+ .int_vref_mv = 2048,
+ .mode_list = max11644_mode_list,
+ .num_modes = ARRAY_SIZE(max11644_mode_list),
+ .default_mode = s0to1,
+ .info = &max1238_info,
+ .channels = max11644_channels,
+ .num_channels = ARRAY_SIZE(max11644_channels),
+ },
+ [max11645] = {
+ .bits = 12,
+ .int_vref_mv = 4096,
+ .mode_list = max11644_mode_list,
+ .num_modes = ARRAY_SIZE(max11644_mode_list),
+ .default_mode = s0to1,
+ .info = &max1238_info,
+ .channels = max11644_channels,
+ .num_channels = ARRAY_SIZE(max11644_channels),
+ },
+ [max11646] = {
+ .bits = 10,
+ .int_vref_mv = 2048,
+ .mode_list = max11644_mode_list,
+ .num_modes = ARRAY_SIZE(max11644_mode_list),
+ .default_mode = s0to1,
+ .info = &max1238_info,
+ .channels = max11646_channels,
+ .num_channels = ARRAY_SIZE(max11646_channels),
+ },
+ [max11647] = {
+ .bits = 10,
+ .int_vref_mv = 4096,
+ .mode_list = max11644_mode_list,
+ .num_modes = ARRAY_SIZE(max11644_mode_list),
+ .default_mode = s0to1,
+ .info = &max1238_info,
+ .channels = max11646_channels,
+ .num_channels = ARRAY_SIZE(max11646_channels),
+ },
+};
+
+
+
static int max1363_initial_setup(struct max1363_state *st)
{
st->setupbyte = MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD
@@ -1675,126 +1250,116 @@ static int __devinit max1363_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret, i, regdone = 0;
- struct max1363_state *st = kzalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ struct max1363_state *st;
+ struct iio_dev *indio_dev;
+ struct regulator *reg;
- /* this is only used for device removal purposes */
- i2c_set_clientdata(client, st);
-
- atomic_set(&st->protect_ring, 0);
-
- st->chip_info = &max1363_chip_info_tbl[id->driver_data];
- st->reg = regulator_get(&client->dev, "vcc");
- if (!IS_ERR(st->reg)) {
- ret = regulator_enable(st->reg);
+ reg = regulator_get(&client->dev, "vcc");
+ if (!IS_ERR(reg)) {
+ ret = regulator_enable(reg);
if (ret)
goto error_put_reg;
}
- st->client = client;
- st->indio_dev = iio_allocate_device();
- if (st->indio_dev == NULL) {
+ indio_dev = iio_allocate_device(sizeof(struct max1363_state));
+ if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_disable_reg;
}
+ st = iio_priv(indio_dev);
+ st->reg = reg;
+ /* this is only used for device removal purposes */
+ i2c_set_clientdata(client, indio_dev);
- st->indio_dev->available_scan_masks
- = kzalloc(sizeof(*st->indio_dev->available_scan_masks)*
+ st->chip_info = &max1363_chip_info_tbl[id->driver_data];
+ st->client = client;
+
+ indio_dev->available_scan_masks
+ = kzalloc(sizeof(*indio_dev->available_scan_masks)*
(st->chip_info->num_modes + 1), GFP_KERNEL);
- if (!st->indio_dev->available_scan_masks) {
+ if (!indio_dev->available_scan_masks) {
ret = -ENOMEM;
goto error_free_device;
}
for (i = 0; i < st->chip_info->num_modes; i++)
- st->indio_dev->available_scan_masks[i] =
+ indio_dev->available_scan_masks[i] =
max1363_mode_table[st->chip_info->mode_list[i]]
.modemask;
/* Estabilish that the iio_dev is a child of the i2c device */
- st->indio_dev->dev.parent = &client->dev;
- st->indio_dev->attrs = st->chip_info->dev_attrs;
-
- /* Todo: this shouldn't be here. */
- st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
- st->indio_dev->modes = INDIO_DIRECT_MODE;
- if (st->chip_info->monitor_mode && client->irq) {
- st->indio_dev->num_interrupt_lines = 1;
- st->indio_dev->event_attrs
- = &max1363_event_attribute_group;
- }
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->name = id->name;
+ indio_dev->info = st->chip_info->info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
ret = max1363_initial_setup(st);
- if (ret)
+ if (ret < 0)
goto error_free_available_scan_masks;
- ret = max1363_register_ring_funcs_and_init(st->indio_dev);
+ ret = max1363_register_ring_funcs_and_init(indio_dev);
if (ret)
goto error_free_available_scan_masks;
- ret = iio_device_register(st->indio_dev);
+ ret = iio_device_register(indio_dev);
if (ret)
goto error_cleanup_ring;
regdone = 1;
- ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
+ ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
+ st->chip_info->channels,
+ st->chip_info->num_channels);
if (ret)
goto error_cleanup_ring;
- if (st->chip_info->monitor_mode && client->irq) {
- ret = iio_register_interrupt_line(client->irq,
- st->indio_dev,
- 0,
- IRQF_TRIGGER_RISING,
- client->name);
+ if (client->irq) {
+ ret = request_threaded_irq(st->client->irq,
+ NULL,
+ &max1363_event_handler,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ "max1363_event",
+ indio_dev);
+
if (ret)
goto error_uninit_ring;
-
- INIT_WORK(&st->thresh_work, max1363_thresh_handler_bh);
}
return 0;
error_uninit_ring:
- iio_ring_buffer_unregister(st->indio_dev->ring);
+ iio_ring_buffer_unregister(indio_dev->ring);
error_cleanup_ring:
- max1363_ring_cleanup(st->indio_dev);
+ max1363_ring_cleanup(indio_dev);
error_free_available_scan_masks:
- kfree(st->indio_dev->available_scan_masks);
+ kfree(indio_dev->available_scan_masks);
error_free_device:
if (!regdone)
- iio_free_device(st->indio_dev);
+ iio_free_device(indio_dev);
else
- iio_device_unregister(st->indio_dev);
+ iio_device_unregister(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);
- kfree(st);
-error_ret:
return ret;
}
static int max1363_remove(struct i2c_client *client)
{
- struct max1363_state *st = i2c_get_clientdata(client);
- struct iio_dev *indio_dev = st->indio_dev;
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct max1363_state *st = iio_priv(indio_dev);
+ struct regulator *reg = st->reg;
- if (st->chip_info->monitor_mode && client->irq)
- iio_unregister_interrupt_line(st->indio_dev, 0);
+ if (client->irq)
+ free_irq(st->client->irq, indio_dev);
iio_ring_buffer_unregister(indio_dev->ring);
max1363_ring_cleanup(indio_dev);
- kfree(st->indio_dev->available_scan_masks);
- iio_device_unregister(indio_dev);
- if (!IS_ERR(st->reg)) {
- regulator_disable(st->reg);
- regulator_put(st->reg);
+ kfree(indio_dev->available_scan_masks);
+ if (!IS_ERR(reg)) {
+ regulator_disable(reg);
+ regulator_put(reg);
}
- kfree(st);
+ iio_device_unregister(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c
index d36fcc62e976..f43befd1f776 100644
--- a/drivers/staging/iio/adc/max1363_ring.c
+++ b/drivers/staging/iio/adc/max1363_ring.c
@@ -9,8 +9,6 @@
*/
#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/kernel.h>
@@ -27,10 +25,9 @@
#include "max1363.h"
-/* Todo: test this */
int max1363_single_channel_from_ring(long mask, struct max1363_state *st)
{
- struct iio_ring_buffer *ring = st->indio_dev->ring;
+ struct iio_ring_buffer *ring = iio_priv_to_dev(st)->ring;
int count = 0, ret;
u8 *ring_data;
if (!(st->current_mode->modemask & mask)) {
@@ -38,12 +35,13 @@ int max1363_single_channel_from_ring(long mask, struct max1363_state *st)
goto error_ret;
}
- ring_data = kmalloc(ring->access.get_bytes_per_datum(ring), GFP_KERNEL);
+ ring_data = kmalloc(ring->access->get_bytes_per_datum(ring),
+ GFP_KERNEL);
if (ring_data == NULL) {
ret = -ENOMEM;
goto error_ret;
}
- ret = ring->access.read_last(ring, ring_data);
+ ret = ring->access->read_last(ring, ring_data);
if (ret)
goto error_free_ring_data;
/* Need a count of channels prior to this one */
@@ -65,6 +63,7 @@ error_ret:
return ret;
}
+
/**
* max1363_ring_preenable() - setup the parameters of the ring before enabling
*
@@ -74,9 +73,9 @@ error_ret:
**/
static int max1363_ring_preenable(struct iio_dev *indio_dev)
{
- struct max1363_state *st = indio_dev->dev_data;
+ struct max1363_state *st = iio_priv(indio_dev);
struct iio_ring_buffer *ring = indio_dev->ring;
- size_t d_size;
+ size_t d_size = 0;
unsigned long numvals;
/*
@@ -91,50 +90,26 @@ static int max1363_ring_preenable(struct iio_dev *indio_dev)
max1363_set_scan_mode(st);
numvals = hweight_long(st->current_mode->modemask);
- if (ring->access.set_bytes_per_datum) {
+ if (ring->access->set_bytes_per_datum) {
+ if (ring->scan_timestamp)
+ d_size += sizeof(s64);
if (st->chip_info->bits != 8)
- d_size = numvals*2 + sizeof(s64);
+ d_size += numvals*2;
else
- d_size = numvals + sizeof(s64);
- if (d_size % 8)
+ d_size += numvals;
+ if (ring->scan_timestamp && (d_size % 8))
d_size += 8 - (d_size % 8);
- ring->access.set_bytes_per_datum(ring, d_size);
+ ring->access->set_bytes_per_datum(ring, d_size);
}
return 0;
}
-
-/**
- * max1363_poll_func_th() - th of trigger launched polling to ring buffer
- *
- * As sampling only occurs on i2c comms occurring, leave timestamping until
- * then. Some triggers will generate their own time stamp. Currently
- * there is no way of notifying them when no one cares.
- **/
-static void max1363_poll_func_th(struct iio_dev *indio_dev, s64 time)
+static irqreturn_t max1363_trigger_handler(int irq, void *p)
{
- struct max1363_state *st = indio_dev->dev_data;
-
- schedule_work(&st->poll_work);
-
- return;
-}
-/**
- * max1363_poll_bh_to_ring() - bh of trigger launched polling to ring buffer
- * @work_s: the work struct through which this was scheduled
- *
- * Currently there is no option in this driver to disable the saving of
- * timestamps within the ring.
- * I think the one copy of this at a time was to avoid problems if the
- * trigger was set far too high and the reads then locked up the computer.
- **/
-static void max1363_poll_bh_to_ring(struct work_struct *work_s)
-{
- struct max1363_state *st = container_of(work_s, struct max1363_state,
- poll_work);
- struct iio_dev *indio_dev = st->indio_dev;
- struct iio_sw_ring_buffer *sw_ring = iio_to_sw_ring(indio_dev->ring);
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->private_data;
+ struct max1363_state *st = iio_priv(indio_dev);
s64 time_ns;
__u8 *rxbuf;
int b_sent;
@@ -149,20 +124,16 @@ static void max1363_poll_bh_to_ring(struct work_struct *work_s)
if (d_size % sizeof(s64))
d_size += sizeof(s64) - (d_size % sizeof(s64));
- /* Ensure only one copy of this function running at a time */
- if (atomic_inc_return(&st->protect_ring) > 1)
- return;
-
/* Monitor mode prevents reading. Whilst not currently implemented
* might as well have this test in here in the meantime as it does
* no harm.
*/
if (numvals == 0)
- return;
+ return IRQ_HANDLED;
rxbuf = kmalloc(d_size, GFP_KERNEL);
if (rxbuf == NULL)
- return;
+ return -ENOMEM;
if (st->chip_info->bits != 8)
b_sent = i2c_master_recv(st->client, rxbuf, numvals*2);
else
@@ -174,16 +145,23 @@ static void max1363_poll_bh_to_ring(struct work_struct *work_s)
memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
- indio_dev->ring->access.store_to(&sw_ring->buf, rxbuf, time_ns);
+ indio_dev->ring->access->store_to(indio_dev->ring, rxbuf, time_ns);
done:
+ iio_trigger_notify_done(indio_dev->trig);
kfree(rxbuf);
- atomic_dec(&st->protect_ring);
+
+ return IRQ_HANDLED;
}
+static const struct iio_ring_setup_ops max1363_ring_setup_ops = {
+ .postenable = &iio_triggered_ring_postenable,
+ .preenable = &max1363_ring_preenable,
+ .predisable = &iio_triggered_ring_predisable,
+};
int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev)
{
- struct max1363_state *st = indio_dev->dev_data;
+ struct max1363_state *st = iio_priv(indio_dev);
int ret = 0;
indio_dev->ring = iio_sw_rb_allocate(indio_dev);
@@ -191,22 +169,27 @@ int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev)
ret = -ENOMEM;
goto error_ret;
}
- /* Effectively select the ring buffer implementation */
- iio_ring_sw_register_funcs(&indio_dev->ring->access);
- ret = iio_alloc_pollfunc(indio_dev, NULL, &max1363_poll_func_th);
- if (ret)
+ indio_dev->pollfunc = iio_alloc_pollfunc(NULL,
+ &max1363_trigger_handler,
+ IRQF_ONESHOT,
+ indio_dev,
+ "%s_consumer%d",
+ st->client->name,
+ indio_dev->id);
+ if (indio_dev->pollfunc == NULL) {
+ ret = -ENOMEM;
goto error_deallocate_sw_rb;
-
+ }
+ /* Effectively select the ring buffer implementation */
+ indio_dev->ring->access = &ring_sw_access_funcs;
/* Ring buffer functions - here trigger setup related */
- indio_dev->ring->scan_el_attrs = st->chip_info->scan_attrs;
- indio_dev->ring->postenable = &iio_triggered_ring_postenable;
- indio_dev->ring->preenable = &max1363_ring_preenable;
- indio_dev->ring->predisable = &iio_triggered_ring_predisable;
- INIT_WORK(&st->poll_work, &max1363_poll_bh_to_ring);
+ indio_dev->ring->setup_ops = &max1363_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:
@@ -221,6 +204,6 @@ void max1363_ring_cleanup(struct iio_dev *indio_dev)
iio_trigger_dettach_poll_func(indio_dev->trig,
indio_dev->pollfunc);
}
- kfree(indio_dev->pollfunc);
+ iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c
index d1b5b13629d9..7097deb0f309 100644
--- a/drivers/staging/iio/addac/adt7316.c
+++ b/drivers/staging/iio/addac/adt7316.c
@@ -174,10 +174,7 @@
*/
struct adt7316_chip_info {
- const char *name;
struct iio_dev *indio_dev;
- struct work_struct thresh_work;
- s64 last_timestamp;
struct adt7316_bus bus;
u16 ldac_pin;
u16 int_mask; /* 0x2f */
@@ -403,7 +400,7 @@ static ssize_t adt7316_show_ad_channel(struct device *dev,
return sprintf(buf, "5 - AIN4\n");
default:
return sprintf(buf, "N/A\n");
- };
+ }
}
static ssize_t adt7316_store_ad_channel(struct device *dev,
@@ -465,7 +462,7 @@ static ssize_t adt7316_show_all_ad_channels(struct device *dev,
if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
return sprintf(buf, "0 - VDD\n1 - Internal Temperature\n"
- "2 - External Temperature or AIN2\n"
+ "2 - External Temperature or AIN1\n"
"3 - AIN2\n4 - AIN3\n5 - AIN4\n");
else
return sprintf(buf, "0 - VDD\n1 - Internal Temperature\n"
@@ -893,7 +890,7 @@ static ssize_t adt7316_show_DAC_update_mode(struct device *dev,
return sprintf(buf, "2 - auto at MSB DAC ABCD writing\n");
default: /* ADT7316_DA_EN_MODE_LDAC */
return sprintf(buf, "3 - manual\n");
- };
+ }
}
}
@@ -1205,7 +1202,7 @@ static ssize_t adt7316_show_ad(struct adt7316_chip_info *chip,
return sprintf(buf, "%d\n", data);
else
break;
- };
+ }
if (data & ADT7316_T_VALUE_SIGN) {
/* convert supplement to positive value */
@@ -1674,18 +1671,6 @@ static ssize_t adt7316_show_bus_type(struct device *dev,
static IIO_DEVICE_ATTR(bus_type, S_IRUGO, adt7316_show_bus_type, NULL, 0);
-static ssize_t adt7316_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = dev_info->dev_data;
-
- return sprintf(buf, "%s\n", chip->name);
-}
-
-static IIO_DEVICE_ATTR(name, S_IRUGO, adt7316_show_name, NULL, 0);
-
static struct attribute *adt7316_attributes[] = {
&iio_dev_attr_all_modes.dev_attr.attr,
&iio_dev_attr_mode.dev_attr.attr,
@@ -1722,7 +1707,6 @@ static struct attribute *adt7316_attributes[] = {
&iio_dev_attr_manufactorer_id.dev_attr.attr,
&iio_dev_attr_device_rev.dev_attr.attr,
&iio_dev_attr_bus_type.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
NULL,
};
@@ -1771,7 +1755,6 @@ static struct attribute *adt7516_attributes[] = {
&iio_dev_attr_manufactorer_id.dev_attr.attr,
&iio_dev_attr_device_rev.dev_attr.attr,
&iio_dev_attr_bus_type.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
NULL,
};
@@ -1779,70 +1762,77 @@ static const struct attribute_group adt7516_attribute_group = {
.attrs = adt7516_attributes,
};
-
-/*
- * temperature bound events
- */
-
-#define IIO_EVENT_CODE_ADT7316_IN_TEMP_HIGH IIO_BUFFER_EVENT_CODE(0)
-#define IIO_EVENT_CODE_ADT7316_IN_TEMP_LOW IIO_BUFFER_EVENT_CODE(1)
-#define IIO_EVENT_CODE_ADT7316_EX_TEMP_HIGH IIO_BUFFER_EVENT_CODE(2)
-#define IIO_EVENT_CODE_ADT7316_EX_TEMP_LOW IIO_BUFFER_EVENT_CODE(3)
-#define IIO_EVENT_CODE_ADT7316_EX_TEMP_FAULT IIO_BUFFER_EVENT_CODE(4)
-#define IIO_EVENT_CODE_ADT7516_AIN1 IIO_BUFFER_EVENT_CODE(5)
-#define IIO_EVENT_CODE_ADT7516_AIN2 IIO_BUFFER_EVENT_CODE(6)
-#define IIO_EVENT_CODE_ADT7516_AIN3 IIO_BUFFER_EVENT_CODE(7)
-#define IIO_EVENT_CODE_ADT7516_AIN4 IIO_BUFFER_EVENT_CODE(8)
-#define IIO_EVENT_CODE_ADT7316_VDD IIO_BUFFER_EVENT_CODE(9)
-
-static void adt7316_interrupt_bh(struct work_struct *work_s)
-{
- struct adt7316_chip_info *chip =
- container_of(work_s, struct adt7316_chip_info, thresh_work);
+static irqreturn_t adt7316_event_handler(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct adt7316_chip_info *chip = iio_dev_get_devdata(indio_dev);
u8 stat1, stat2;
- int i, ret, count;
+ int ret;
+ s64 time;
ret = chip->bus.read(chip->bus.client, ADT7316_INT_STAT1, &stat1);
if (!ret) {
- if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
- count = 8;
- else
- count = 5;
+ if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX)
+ stat1 &= 0x1F;
- for (i = 0; i < count; i++) {
- if (stat1 & (1 << i))
- iio_push_event(chip->indio_dev, 0,
- IIO_EVENT_CODE_ADT7316_IN_TEMP_HIGH + i,
- chip->last_timestamp);
+ time = iio_get_time_ns();
+ if (stat1 & (1 << 0))
+ iio_push_event(chip->indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ time);
+ if (stat1 & (1 << 1))
+ iio_push_event(chip->indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ time);
+ if (stat1 & (1 << 2))
+ iio_push_event(chip->indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP, 1,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ time);
+ if (stat1 & (1 << 3))
+ iio_push_event(chip->indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP, 1,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ time);
+ if (stat1 & (1 << 5))
+ iio_push_event(chip->indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_IN, 1,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_EITHER),
+ time);
+ if (stat1 & (1 << 6))
+ iio_push_event(chip->indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_IN, 2,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_EITHER),
+ time);
+ if (stat1 & (1 << 7))
+ iio_push_event(chip->indio_dev, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_IN, 3,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_EITHER),
+ time);
}
- }
-
ret = chip->bus.read(chip->bus.client, ADT7316_INT_STAT2, &stat2);
if (!ret) {
if (stat2 & ADT7316_INT_MASK2_VDD)
iio_push_event(chip->indio_dev, 0,
- IIO_EVENT_CODE_ADT7316_VDD,
- chip->last_timestamp);
+ IIO_UNMOD_EVENT_CODE(IIO_IN,
+ 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ iio_get_time_ns());
}
- enable_irq(chip->bus.irq);
-}
-
-static int adt7316_interrupt(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct adt7316_chip_info *chip = dev_info->dev_data;
-
- chip->last_timestamp = timestamp;
- schedule_work(&chip->thresh_work);
-
- return 0;
+ return IRQ_HANDLED;
}
-IIO_EVENT_SH(adt7316, &adt7316_interrupt);
-
/*
* Show mask of enabled interrupts in Hex.
*/
@@ -1901,9 +1891,9 @@ static ssize_t adt7316_set_int_mask(struct device *dev,
}
static inline ssize_t adt7316_show_ad_bound(struct device *dev,
struct device_attribute *attr,
- u8 bound_reg,
char *buf)
{
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct iio_dev *dev_info = dev_get_drvdata(dev);
struct adt7316_chip_info *chip = dev_info->dev_data;
u8 val;
@@ -1911,10 +1901,10 @@ static inline ssize_t adt7316_show_ad_bound(struct device *dev,
int ret;
if ((chip->id & ID_FAMILY_MASK) == ID_ADT73XX &&
- bound_reg > ADT7316_EX_TEMP_LOW)
+ this_attr->address > ADT7316_EX_TEMP_LOW)
return -EPERM;
- ret = chip->bus.read(chip->bus.client, bound_reg, &val);
+ ret = chip->bus.read(chip->bus.client, this_attr->address, &val);
if (ret)
return -EIO;
@@ -1931,10 +1921,10 @@ static inline ssize_t adt7316_show_ad_bound(struct device *dev,
static inline ssize_t adt7316_set_ad_bound(struct device *dev,
struct device_attribute *attr,
- u8 bound_reg,
const char *buf,
size_t len)
{
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct iio_dev *dev_info = dev_get_drvdata(dev);
struct adt7316_chip_info *chip = dev_info->dev_data;
long data;
@@ -1942,7 +1932,7 @@ static inline ssize_t adt7316_set_ad_bound(struct device *dev,
int ret;
if ((chip->id & ID_FAMILY_MASK) == ID_ADT73XX &&
- bound_reg > ADT7316_EX_TEMP_LOW)
+ this_attr->address > ADT7316_EX_TEMP_LOW)
return -EPERM;
ret = strict_strtol(buf, 10, &data);
@@ -1963,183 +1953,13 @@ static inline ssize_t adt7316_set_ad_bound(struct device *dev,
val = (u8)data;
- ret = chip->bus.write(chip->bus.client, bound_reg, val);
+ ret = chip->bus.write(chip->bus.client, this_attr->address, val);
if (ret)
return -EIO;
return len;
}
-static ssize_t adt7316_show_in_temp_high(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return adt7316_show_ad_bound(dev, attr,
- ADT7316_IN_TEMP_HIGH, buf);
-}
-
-static inline ssize_t adt7316_set_in_temp_high(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return adt7316_set_ad_bound(dev, attr,
- ADT7316_IN_TEMP_HIGH, buf, len);
-}
-
-static ssize_t adt7316_show_in_temp_low(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return adt7316_show_ad_bound(dev, attr,
- ADT7316_IN_TEMP_LOW, buf);
-}
-
-static inline ssize_t adt7316_set_in_temp_low(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return adt7316_set_ad_bound(dev, attr,
- ADT7316_IN_TEMP_LOW, buf, len);
-}
-
-static ssize_t adt7316_show_ex_temp_ain1_high(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return adt7316_show_ad_bound(dev, attr,
- ADT7316_EX_TEMP_HIGH, buf);
-}
-
-static inline ssize_t adt7316_set_ex_temp_ain1_high(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return adt7316_set_ad_bound(dev, attr,
- ADT7316_EX_TEMP_HIGH, buf, len);
-}
-
-static ssize_t adt7316_show_ex_temp_ain1_low(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return adt7316_show_ad_bound(dev, attr,
- ADT7316_EX_TEMP_LOW, buf);
-}
-
-static inline ssize_t adt7316_set_ex_temp_ain1_low(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return adt7316_set_ad_bound(dev, attr,
- ADT7316_EX_TEMP_LOW, buf, len);
-}
-
-static ssize_t adt7316_show_ain2_high(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return adt7316_show_ad_bound(dev, attr,
- ADT7516_AIN2_HIGH, buf);
-}
-
-static inline ssize_t adt7316_set_ain2_high(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return adt7316_set_ad_bound(dev, attr,
- ADT7516_AIN2_HIGH, buf, len);
-}
-
-static ssize_t adt7316_show_ain2_low(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return adt7316_show_ad_bound(dev, attr,
- ADT7516_AIN2_LOW, buf);
-}
-
-static inline ssize_t adt7316_set_ain2_low(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return adt7316_set_ad_bound(dev, attr,
- ADT7516_AIN2_LOW, buf, len);
-}
-
-static ssize_t adt7316_show_ain3_high(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return adt7316_show_ad_bound(dev, attr,
- ADT7516_AIN3_HIGH, buf);
-}
-
-static inline ssize_t adt7316_set_ain3_high(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return adt7316_set_ad_bound(dev, attr,
- ADT7516_AIN3_HIGH, buf, len);
-}
-
-static ssize_t adt7316_show_ain3_low(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return adt7316_show_ad_bound(dev, attr,
- ADT7516_AIN3_LOW, buf);
-}
-
-static inline ssize_t adt7316_set_ain3_low(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return adt7316_set_ad_bound(dev, attr,
- ADT7516_AIN3_LOW, buf, len);
-}
-
-static ssize_t adt7316_show_ain4_high(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return adt7316_show_ad_bound(dev, attr,
- ADT7516_AIN4_HIGH, buf);
-}
-
-static inline ssize_t adt7316_set_ain4_high(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return adt7316_set_ad_bound(dev, attr,
- ADT7516_AIN4_HIGH, buf, len);
-}
-
-static ssize_t adt7316_show_ain4_low(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return adt7316_show_ad_bound(dev, attr,
- ADT7516_AIN4_LOW, buf);
-}
-
-static inline ssize_t adt7316_set_ain4_low(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return adt7316_set_ad_bound(dev, attr,
- ADT7516_AIN4_LOW, buf, len);
-}
-
static ssize_t adt7316_show_int_enabled(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -2173,47 +1993,72 @@ static ssize_t adt7316_set_int_enabled(struct device *dev,
return len;
}
-
-IIO_EVENT_ATTR_SH(int_mask, iio_event_adt7316,
- adt7316_show_int_mask, adt7316_set_int_mask, 0);
-IIO_EVENT_ATTR_SH(in_temp_high, iio_event_adt7316,
- adt7316_show_in_temp_high, adt7316_set_in_temp_high, 0);
-IIO_EVENT_ATTR_SH(in_temp_low, iio_event_adt7316,
- adt7316_show_in_temp_low, adt7316_set_in_temp_low, 0);
-IIO_EVENT_ATTR_SH(ex_temp_high, iio_event_adt7316,
- adt7316_show_ex_temp_ain1_high,
- adt7316_set_ex_temp_ain1_high, 0);
-IIO_EVENT_ATTR_SH(ex_temp_low, iio_event_adt7316,
- adt7316_show_ex_temp_ain1_low,
- adt7316_set_ex_temp_ain1_low, 0);
-IIO_EVENT_ATTR_SH(ex_temp_ain1_high, iio_event_adt7316,
- adt7316_show_ex_temp_ain1_high,
- adt7316_set_ex_temp_ain1_high, 0);
-IIO_EVENT_ATTR_SH(ex_temp_ain1_low, iio_event_adt7316,
- adt7316_show_ex_temp_ain1_low,
- adt7316_set_ex_temp_ain1_low, 0);
-IIO_EVENT_ATTR_SH(ain2_high, iio_event_adt7316,
- adt7316_show_ain2_high, adt7316_set_ain2_high, 0);
-IIO_EVENT_ATTR_SH(ain2_low, iio_event_adt7316,
- adt7316_show_ain2_low, adt7316_set_ain2_low, 0);
-IIO_EVENT_ATTR_SH(ain3_high, iio_event_adt7316,
- adt7316_show_ain3_high, adt7316_set_ain3_high, 0);
-IIO_EVENT_ATTR_SH(ain3_low, iio_event_adt7316,
- adt7316_show_ain3_low, adt7316_set_ain3_low, 0);
-IIO_EVENT_ATTR_SH(ain4_high, iio_event_adt7316,
- adt7316_show_ain4_high, adt7316_set_ain4_high, 0);
-IIO_EVENT_ATTR_SH(ain4_low, iio_event_adt7316,
- adt7316_show_ain4_low, adt7316_set_ain4_low, 0);
-IIO_EVENT_ATTR_SH(int_enabled, iio_event_adt7316,
- adt7316_show_int_enabled, adt7316_set_int_enabled, 0);
+static IIO_DEVICE_ATTR(int_mask,
+ S_IRUGO | S_IWUSR,
+ adt7316_show_int_mask, adt7316_set_int_mask,
+ 0);
+static IIO_DEVICE_ATTR(in_temp_high_value,
+ S_IRUGO | S_IWUSR,
+ adt7316_show_ad_bound, adt7316_set_ad_bound,
+ ADT7316_IN_TEMP_HIGH);
+static IIO_DEVICE_ATTR(in_temp_low_value,
+ S_IRUGO | S_IWUSR,
+ adt7316_show_ad_bound, adt7316_set_ad_bound,
+ ADT7316_IN_TEMP_LOW);
+static IIO_DEVICE_ATTR(ex_temp_high_value,
+ S_IRUGO | S_IWUSR,
+ adt7316_show_ad_bound, adt7316_set_ad_bound,
+ ADT7316_EX_TEMP_HIGH);
+static IIO_DEVICE_ATTR(ex_temp_low_value,
+ S_IRUGO | S_IWUSR,
+ adt7316_show_ad_bound, adt7316_set_ad_bound,
+ ADT7316_EX_TEMP_LOW);
+
+/* NASTY duplication to be fixed */
+static IIO_DEVICE_ATTR(ex_temp_ain1_high_value,
+ S_IRUGO | S_IWUSR,
+ adt7316_show_ad_bound, adt7316_set_ad_bound,
+ ADT7316_EX_TEMP_HIGH);
+static IIO_DEVICE_ATTR(ex_temp_ain1_low_value,
+ S_IRUGO | S_IWUSR,
+ adt7316_show_ad_bound, adt7316_set_ad_bound,
+ ADT7316_EX_TEMP_LOW);
+static IIO_DEVICE_ATTR(ain2_high_value,
+ S_IRUGO | S_IWUSR,
+ adt7316_show_ad_bound, adt7316_set_ad_bound,
+ ADT7516_AIN2_HIGH);
+static IIO_DEVICE_ATTR(ain2_low_value,
+ S_IRUGO | S_IWUSR,
+ adt7316_show_ad_bound, adt7316_set_ad_bound,
+ ADT7516_AIN2_LOW);
+static IIO_DEVICE_ATTR(ain3_high_value,
+ S_IRUGO | S_IWUSR,
+ adt7316_show_ad_bound, adt7316_set_ad_bound,
+ ADT7516_AIN3_HIGH);
+static IIO_DEVICE_ATTR(ain3_low_value,
+ S_IRUGO | S_IWUSR,
+ adt7316_show_ad_bound, adt7316_set_ad_bound,
+ ADT7516_AIN3_LOW);
+static IIO_DEVICE_ATTR(ain4_high_value,
+ S_IRUGO | S_IWUSR,
+ adt7316_show_ad_bound, adt7316_set_ad_bound,
+ ADT7516_AIN4_HIGH);
+static IIO_DEVICE_ATTR(ain4_low_value,
+ S_IRUGO | S_IWUSR,
+ adt7316_show_ad_bound, adt7316_set_ad_bound,
+ ADT7516_AIN4_LOW);
+static IIO_DEVICE_ATTR(int_enabled,
+ S_IRUGO | S_IWUSR,
+ adt7316_show_int_enabled,
+ adt7316_set_int_enabled, 0);
static struct attribute *adt7316_event_attributes[] = {
- &iio_event_attr_int_mask.dev_attr.attr,
- &iio_event_attr_in_temp_high.dev_attr.attr,
- &iio_event_attr_in_temp_low.dev_attr.attr,
- &iio_event_attr_ex_temp_high.dev_attr.attr,
- &iio_event_attr_ex_temp_low.dev_attr.attr,
- &iio_event_attr_int_enabled.dev_attr.attr,
+ &iio_dev_attr_int_mask.dev_attr.attr,
+ &iio_dev_attr_in_temp_high_value.dev_attr.attr,
+ &iio_dev_attr_in_temp_low_value.dev_attr.attr,
+ &iio_dev_attr_ex_temp_high_value.dev_attr.attr,
+ &iio_dev_attr_ex_temp_low_value.dev_attr.attr,
+ &iio_dev_attr_int_enabled.dev_attr.attr,
NULL,
};
@@ -2222,18 +2067,18 @@ static struct attribute_group adt7316_event_attribute_group = {
};
static struct attribute *adt7516_event_attributes[] = {
- &iio_event_attr_int_mask.dev_attr.attr,
- &iio_event_attr_in_temp_high.dev_attr.attr,
- &iio_event_attr_in_temp_low.dev_attr.attr,
- &iio_event_attr_ex_temp_ain1_high.dev_attr.attr,
- &iio_event_attr_ex_temp_ain1_low.dev_attr.attr,
- &iio_event_attr_ain2_high.dev_attr.attr,
- &iio_event_attr_ain2_low.dev_attr.attr,
- &iio_event_attr_ain3_high.dev_attr.attr,
- &iio_event_attr_ain3_low.dev_attr.attr,
- &iio_event_attr_ain4_high.dev_attr.attr,
- &iio_event_attr_ain4_low.dev_attr.attr,
- &iio_event_attr_int_enabled.dev_attr.attr,
+ &iio_dev_attr_int_mask.dev_attr.attr,
+ &iio_dev_attr_in_temp_high_value.dev_attr.attr,
+ &iio_dev_attr_in_temp_low_value.dev_attr.attr,
+ &iio_dev_attr_ex_temp_ain1_high_value.dev_attr.attr,
+ &iio_dev_attr_ex_temp_ain1_low_value.dev_attr.attr,
+ &iio_dev_attr_ain2_high_value.dev_attr.attr,
+ &iio_dev_attr_ain2_low_value.dev_attr.attr,
+ &iio_dev_attr_ain3_high_value.dev_attr.attr,
+ &iio_dev_attr_ain3_low_value.dev_attr.attr,
+ &iio_dev_attr_ain4_high_value.dev_attr.attr,
+ &iio_dev_attr_ain4_low_value.dev_attr.attr,
+ &iio_dev_attr_int_enabled.dev_attr.attr,
NULL,
};
@@ -2261,6 +2106,20 @@ int adt7316_enable(struct device *dev)
EXPORT_SYMBOL(adt7316_enable);
#endif
+static const struct iio_info adt7316_info = {
+ .attrs = &adt7316_attribute_group,
+ .num_interrupt_lines = 1,
+ .event_attrs = &adt7316_event_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
+static const struct iio_info adt7516_info = {
+ .attrs = &adt7516_attribute_group,
+ .num_interrupt_lines = 1,
+ .event_attrs = &adt7516_event_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
/*
* device probe and remove
*/
@@ -2280,7 +2139,6 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus,
dev_set_drvdata(dev, chip);
chip->bus = *bus;
- chip->name = name;
if (name[4] == '3')
chip->id = ID_ADT7316 + (name[6] - '6');
@@ -2299,23 +2157,19 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus,
if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
chip->int_mask |= ADT7516_AIN_INT_MASK;
- chip->indio_dev = iio_allocate_device();
+ chip->indio_dev = iio_allocate_device(0);
if (chip->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_chip;
}
chip->indio_dev->dev.parent = dev;
- if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) {
- chip->indio_dev->attrs = &adt7516_attribute_group;
- chip->indio_dev->event_attrs = &adt7516_event_attribute_group;
- } else {
- chip->indio_dev->attrs = &adt7316_attribute_group;
- chip->indio_dev->event_attrs = &adt7316_event_attribute_group;
- }
+ if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
+ chip->indio_dev->info = &adt7516_info;
+ else
+ chip->indio_dev->info = &adt7316_info;
+ chip->indio_dev->name = name;
chip->indio_dev->dev_data = (void *)chip;
- chip->indio_dev->driver_module = THIS_MODULE;
- chip->indio_dev->num_interrupt_lines = 1;
chip->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(chip->indio_dev);
@@ -2326,24 +2180,15 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus,
if (adt7316_platform_data[0])
chip->bus.irq_flags = adt7316_platform_data[0];
- ret = iio_register_interrupt_line(chip->bus.irq,
- chip->indio_dev,
- 0,
- chip->bus.irq_flags,
- chip->name);
+ ret = request_threaded_irq(chip->bus.irq,
+ NULL,
+ &adt7316_event_handler,
+ chip->bus.irq_flags | IRQF_ONESHOT,
+ chip->indio_dev->name,
+ chip->indio_dev);
if (ret)
goto error_unreg_dev;
- /*
- * The event handler list element refer to iio_event_adt7316.
- * All event attributes bind to the same event handler.
- * So, only register event handler once.
- */
- iio_add_event_to_list(&iio_event_adt7316,
- &chip->indio_dev->interrupts[0]->ev_list);
-
- INIT_WORK(&chip->thresh_work, adt7316_interrupt_bh);
-
if (chip->bus.irq_flags & IRQF_TRIGGER_HIGH)
chip->config1 |= ADT7316_INT_POLARITY;
}
@@ -2361,12 +2206,12 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus,
}
dev_info(dev, "%s temperature sensor, ADC and DAC registered.\n",
- chip->name);
+ chip->indio_dev->name);
return 0;
error_unreg_irq:
- iio_unregister_interrupt_line(chip->indio_dev, 0);
+ free_irq(chip->bus.irq, chip->indio_dev);
error_unreg_dev:
iio_device_unregister(chip->indio_dev);
error_free_dev:
@@ -2383,12 +2228,11 @@ int __devexit adt7316_remove(struct device *dev)
struct iio_dev *dev_info = dev_get_drvdata(dev);
struct adt7316_chip_info *chip = dev_info->dev_data;
- struct iio_dev *indio_dev = chip->indio_dev;
dev_set_drvdata(dev, NULL);
if (chip->bus.irq)
- iio_unregister_interrupt_line(indio_dev, 0);
- iio_device_unregister(indio_dev);
+ free_irq(chip->bus.irq, chip->indio_dev);
+ iio_device_unregister(chip->indio_dev);
iio_free_device(chip->indio_dev);
kfree(chip);
diff --git a/drivers/staging/iio/chrdev.h b/drivers/staging/iio/chrdev.h
index 4fcb99c816f9..3e31ee6220ed 100644
--- a/drivers/staging/iio/chrdev.h
+++ b/drivers/staging/iio/chrdev.h
@@ -45,23 +45,10 @@ struct iio_event_data {
* struct iio_detected_event_list - list element for events that have occurred
* @list: linked list header
* @ev: the event itself
- * @shared_pointer: used when the event is shared - i.e. can be escallated
- * on demand (eg ring buffer 50%->100% full)
*/
struct iio_detected_event_list {
struct list_head list;
struct iio_event_data ev;
- struct iio_shared_ev_pointer *shared_pointer;
-};
-/**
- * struct iio_shared_ev_pointer - allows shared events to identify if currently
- * in the detected event list
- * @ev_p: pointer to detected event list element (null if not in list)
- * @lock: protect this element to prevent simultaneous edit and remove
- */
-struct iio_shared_ev_pointer {
- struct iio_detected_event_list *ev_p;
- spinlock_t lock;
};
/**
@@ -73,43 +60,16 @@ struct iio_shared_ev_pointer {
* @det_events: list of detected events
* @max_events: maximum number of events before new ones are dropped
* @current_events: number of events in detected list
- * @owner: ensure the driver module owns the file, not iio
- * @private: driver specific data
- * @_name: used internally to store the sysfs name for minor id
- * attribute
- * @_attrname: the event interface's attribute name
*/
struct iio_event_interface {
struct device dev;
struct iio_handler handler;
wait_queue_head_t wait;
struct mutex event_list_lock;
- struct iio_detected_event_list det_events;
+ struct list_head det_events;
int max_events;
int current_events;
- struct module *owner;
- void *private;
- char _name[35];
- char _attrname[20];
-};
-
-/**
- * struct iio_event_handler_list - element in list of handlers for events
- * @list: list header
- * @refcount: as the handler may be shared between multiple device
- * side events, reference counting ensures clean removal
- * @exist_lock: prevents race conditions related to refcount usage.
- * @handler: event handler function - called on event if this
- * event_handler is enabled.
- *
- * Each device has one list of these per interrupt line.
- **/
-struct iio_event_handler_list {
- struct list_head list;
- int refcount;
- struct mutex exist_lock;
- int (*handler)(struct iio_dev *dev_info, int index, s64 timestamp,
- int no_test);
+ struct list_head dev_attr_list;
};
#endif
diff --git a/drivers/staging/iio/dac/Kconfig b/drivers/staging/iio/dac/Kconfig
index 67defcb359b1..d5a5556cf985 100644
--- a/drivers/staging/iio/dac/Kconfig
+++ b/drivers/staging/iio/dac/Kconfig
@@ -21,6 +21,27 @@ config AD5446
To compile this driver as a module, choose M here: the
module will be called ad5446.
+config AD5504
+ tristate "Analog Devices AD5504/AD5501 DAC SPI driver"
+ depends on SPI
+ help
+ Say yes here to build support for Analog Devices AD5504, AD5501,
+ High Voltage Digital to Analog Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5504.
+
+config AD5791
+ tristate "Analog Devices AD5760/AD5780/AD5781/AD5791 DAC SPI driver"
+ depends on SPI
+ help
+ Say yes here to build support for Analog Devices AD5760, AD5780,
+ AD5781, AD5791 High Resolution Voltage Output Digital to
+ Analog Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5791.
+
config MAX517
tristate "Maxim MAX517/518/519 DAC driver"
depends on I2C && EXPERIMENTAL
diff --git a/drivers/staging/iio/dac/Makefile b/drivers/staging/iio/dac/Makefile
index 1197aef54abb..83196de7a54c 100644
--- a/drivers/staging/iio/dac/Makefile
+++ b/drivers/staging/iio/dac/Makefile
@@ -3,5 +3,7 @@
#
obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o
+obj-$(CONFIG_AD5504) += ad5504.o
obj-$(CONFIG_AD5446) += ad5446.o
+obj-$(CONFIG_AD5791) += ad5791.o
obj-$(CONFIG_MAX517) += max517.o
diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c
index 8623a72e046c..86cb08ce199b 100644
--- a/drivers/staging/iio/dac/ad5446.c
+++ b/drivers/staging/iio/dac/ad5446.c
@@ -106,17 +106,6 @@ static ssize_t ad5446_show_scale(struct device *dev,
}
static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5446_show_scale, NULL, 0);
-static ssize_t ad5446_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad5446_state *st = iio_dev_get_devdata(dev_info);
-
- return sprintf(buf, "%s\n", spi_get_device_id(st->spi)->name);
-}
-static IIO_DEVICE_ATTR(name, S_IRUGO, ad5446_show_name, NULL, 0);
-
static ssize_t ad5446_write_powerdown_mode(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
@@ -204,7 +193,6 @@ static struct attribute *ad5446_attributes[] = {
&iio_dev_attr_out0_powerdown.dev_attr.attr,
&iio_dev_attr_out_powerdown_mode.dev_attr.attr,
&iio_const_attr_out_powerdown_mode_available.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
NULL,
};
@@ -245,6 +233,12 @@ static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
.left_shift = 0,
.store_sample = ad5446_store_sample,
},
+ [ID_AD5541A] = {
+ .bits = 16,
+ .storagebits = 16,
+ .left_shift = 0,
+ .store_sample = ad5542_store_sample,
+ },
[ID_AD5542A] = {
.bits = 16,
.storagebits = 16,
@@ -340,6 +334,11 @@ static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
},
};
+static const struct iio_info ad5446_info = {
+ .attrs = &ad5446_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit ad5446_probe(struct spi_device *spi)
{
struct ad5446_state *st;
@@ -367,7 +366,7 @@ static int __devinit ad5446_probe(struct spi_device *spi)
st->spi = spi;
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_disable_reg;
@@ -375,9 +374,9 @@ static int __devinit ad5446_probe(struct spi_device *spi)
/* Estabilish that the iio_dev is a child of the spi device */
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->attrs = &ad5446_attribute_group;
+ st->indio_dev->name = spi_get_device_id(spi)->name;
+ st->indio_dev->info = &ad5446_info;
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
/* Setup default message */
@@ -442,6 +441,7 @@ static const struct spi_device_id ad5446_id[] = {
{"ad5444", ID_AD5444},
{"ad5446", ID_AD5446},
{"ad5512a", ID_AD5512A},
+ {"ad5541a", ID_AD5541A},
{"ad5542a", ID_AD5542A},
{"ad5543", ID_AD5543},
{"ad5553", ID_AD5553},
diff --git a/drivers/staging/iio/dac/ad5446.h b/drivers/staging/iio/dac/ad5446.h
index 7ac63ab8a11d..e6ffd2bb7c7d 100644
--- a/drivers/staging/iio/dac/ad5446.h
+++ b/drivers/staging/iio/dac/ad5446.h
@@ -92,6 +92,7 @@ struct ad5446_chip_info {
enum ad5446_supported_device_ids {
ID_AD5444,
ID_AD5446,
+ ID_AD5541A,
ID_AD5542A,
ID_AD5543,
ID_AD5512A,
diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c
new file mode 100644
index 000000000000..ed029cdff300
--- /dev/null
+++ b/drivers/staging/iio/dac/ad5504.c
@@ -0,0 +1,404 @@
+/*
+ * AD5504, AD5501 High Voltage Digital to Analog Converter
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/regulator/consumer.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "dac.h"
+#include "ad5504.h"
+
+static int ad5504_spi_write(struct spi_device *spi, u8 addr, u16 val)
+{
+ u16 tmp = cpu_to_be16(AD5504_CMD_WRITE |
+ AD5504_ADDR(addr) |
+ (val & AD5504_RES_MASK));
+
+ return spi_write(spi, (u8 *)&tmp, 2);
+}
+
+static int ad5504_spi_read(struct spi_device *spi, u8 addr, u16 *val)
+{
+ u16 tmp = cpu_to_be16(AD5504_CMD_READ | AD5504_ADDR(addr));
+ int ret;
+ struct spi_transfer t = {
+ .tx_buf = &tmp,
+ .rx_buf = val,
+ .len = 2,
+ };
+ struct spi_message m;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+ ret = spi_sync(spi, &m);
+
+ *val = be16_to_cpu(*val) & AD5504_RES_MASK;
+
+ return ret;
+}
+
+static ssize_t ad5504_write_dac(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ long readin;
+ int ret;
+
+ ret = strict_strtol(buf, 10, &readin);
+ if (ret)
+ return ret;
+
+ ret = ad5504_spi_write(st->spi, this_attr->address, readin);
+ return ret ? ret : len;
+}
+
+static ssize_t ad5504_read_dac(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ int ret;
+ u16 val;
+
+ ret = ad5504_spi_read(st->spi, this_attr->address, &val);
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t ad5504_read_powerdown_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+
+ const char mode[][14] = {"20kohm_to_gnd", "three_state"};
+
+ return sprintf(buf, "%s\n", mode[st->pwr_down_mode]);
+}
+
+static ssize_t ad5504_write_powerdown_mode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+ int ret;
+
+ if (sysfs_streq(buf, "20kohm_to_gnd"))
+ st->pwr_down_mode = AD5504_DAC_PWRDN_20K;
+ else if (sysfs_streq(buf, "three_state"))
+ st->pwr_down_mode = AD5504_DAC_PWRDN_3STATE;
+ else
+ ret = -EINVAL;
+
+ return ret ? ret : len;
+}
+
+static ssize_t ad5504_read_dac_powerdown(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+
+ return sprintf(buf, "%d\n",
+ !(st->pwr_down_mask & (1 << this_attr->address)));
+}
+
+static ssize_t ad5504_write_dac_powerdown(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ long readin;
+ int ret;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+
+ ret = strict_strtol(buf, 10, &readin);
+ if (ret)
+ return ret;
+
+ if (readin == 0)
+ st->pwr_down_mask |= (1 << this_attr->address);
+ else if (readin == 1)
+ st->pwr_down_mask &= ~(1 << this_attr->address);
+ else
+ ret = -EINVAL;
+
+ ret = ad5504_spi_write(st->spi, AD5504_ADDR_CTRL,
+ AD5504_DAC_PWRDWN_MODE(st->pwr_down_mode) |
+ AD5504_DAC_PWR(st->pwr_down_mask));
+
+ /* writes to the CTRL register must be followed by a NOOP */
+ ad5504_spi_write(st->spi, AD5504_ADDR_NOOP, 0);
+
+ return ret ? ret : len;
+}
+
+static ssize_t ad5504_show_scale(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+ /* Corresponds to Vref / 2^(bits) */
+ unsigned int scale_uv = (st->vref_mv * 1000) >> AD5505_BITS;
+
+ return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
+}
+static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5504_show_scale, NULL, 0);
+
+#define IIO_DEV_ATTR_OUT_RW_RAW(_num, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(out##_num##_raw, \
+ S_IRUGO | S_IWUSR, _show, _store, _addr)
+
+static IIO_DEV_ATTR_OUT_RW_RAW(0, ad5504_read_dac,
+ ad5504_write_dac, AD5504_ADDR_DAC0);
+static IIO_DEV_ATTR_OUT_RW_RAW(1, ad5504_read_dac,
+ ad5504_write_dac, AD5504_ADDR_DAC1);
+static IIO_DEV_ATTR_OUT_RW_RAW(2, ad5504_read_dac,
+ ad5504_write_dac, AD5504_ADDR_DAC2);
+static IIO_DEV_ATTR_OUT_RW_RAW(3, ad5504_read_dac,
+ ad5504_write_dac, AD5504_ADDR_DAC3);
+
+static IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO |
+ S_IWUSR, ad5504_read_powerdown_mode,
+ ad5504_write_powerdown_mode, 0);
+
+static IIO_CONST_ATTR(out_powerdown_mode_available,
+ "20kohm_to_gnd three_state");
+
+#define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(out##_num##_powerdown, \
+ S_IRUGO | S_IWUSR, _show, _store, _addr)
+
+static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5504_read_dac_powerdown,
+ ad5504_write_dac_powerdown, 0);
+static IIO_DEV_ATTR_DAC_POWERDOWN(1, ad5504_read_dac_powerdown,
+ ad5504_write_dac_powerdown, 1);
+static IIO_DEV_ATTR_DAC_POWERDOWN(2, ad5504_read_dac_powerdown,
+ ad5504_write_dac_powerdown, 2);
+static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5504_read_dac_powerdown,
+ ad5504_write_dac_powerdown, 3);
+
+static struct attribute *ad5504_attributes[] = {
+ &iio_dev_attr_out0_raw.dev_attr.attr,
+ &iio_dev_attr_out1_raw.dev_attr.attr,
+ &iio_dev_attr_out2_raw.dev_attr.attr,
+ &iio_dev_attr_out3_raw.dev_attr.attr,
+ &iio_dev_attr_out0_powerdown.dev_attr.attr,
+ &iio_dev_attr_out1_powerdown.dev_attr.attr,
+ &iio_dev_attr_out2_powerdown.dev_attr.attr,
+ &iio_dev_attr_out3_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_powerdown_mode.dev_attr.attr,
+ &iio_const_attr_out_powerdown_mode_available.dev_attr.attr,
+ &iio_dev_attr_out_scale.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group ad5504_attribute_group = {
+ .attrs = ad5504_attributes,
+};
+
+static struct attribute *ad5501_attributes[] = {
+ &iio_dev_attr_out0_raw.dev_attr.attr,
+ &iio_dev_attr_out0_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_powerdown_mode.dev_attr.attr,
+ &iio_const_attr_out_powerdown_mode_available.dev_attr.attr,
+ &iio_dev_attr_out_scale.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group ad5501_attribute_group = {
+ .attrs = ad5501_attributes,
+};
+
+static IIO_CONST_ATTR(temp0_thresh_rising_value, "110000");
+static IIO_CONST_ATTR(temp0_thresh_rising_en, "1");
+
+static struct attribute *ad5504_ev_attributes[] = {
+ &iio_const_attr_temp0_thresh_rising_value.dev_attr.attr,
+ &iio_const_attr_temp0_thresh_rising_en.dev_attr.attr,
+ NULL,
+};
+
+static struct attribute_group ad5504_ev_attribute_group = {
+ .attrs = ad5504_ev_attributes,
+};
+
+static irqreturn_t ad5504_event_handler(int irq, void *private)
+{
+ iio_push_event(private, 0,
+ IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_TEMP,
+ 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ iio_get_time_ns());
+
+ return IRQ_HANDLED;
+}
+
+static const struct iio_info ad5504_info = {
+ .attrs = &ad5504_attribute_group,
+ .num_interrupt_lines = 1,
+ .event_attrs = &ad5504_ev_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
+static const struct iio_info ad5501_info = {
+ .attrs = &ad5501_attribute_group,
+ .num_interrupt_lines = 1,
+ .event_attrs = &ad5504_ev_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
+static int __devinit ad5504_probe(struct spi_device *spi)
+{
+ struct ad5504_platform_data *pdata = spi->dev.platform_data;
+ struct ad5504_state *st;
+ int ret, voltage_uv = 0;
+
+ st = kzalloc(sizeof(*st), GFP_KERNEL);
+ if (st == NULL) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+
+ spi_set_drvdata(spi, st);
+
+ 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);
+ }
+
+ if (voltage_uv)
+ st->vref_mv = voltage_uv / 1000;
+ else if (pdata)
+ st->vref_mv = pdata->vref_mv;
+ else
+ dev_warn(&spi->dev, "reference voltage unspecified\n");
+
+ st->spi = spi;
+ st->indio_dev = iio_allocate_device(0);
+ if (st->indio_dev == NULL) {
+ ret = -ENOMEM;
+ goto error_disable_reg;
+ }
+ st->indio_dev->dev.parent = &spi->dev;
+ st->indio_dev->name = spi_get_device_id(st->spi)->name;
+ if (spi_get_device_id(st->spi)->driver_data == ID_AD5501)
+ st->indio_dev->info = &ad5501_info;
+ else
+ st->indio_dev->info = &ad5504_info;
+ st->indio_dev->dev_data = (void *)(st);
+ st->indio_dev->modes = INDIO_DIRECT_MODE;
+
+ ret = iio_device_register(st->indio_dev);
+ if (ret)
+ goto error_free_dev;
+
+ if (spi->irq) {
+ ret = request_threaded_irq(spi->irq,
+ NULL,
+ &ad5504_event_handler,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ spi_get_device_id(st->spi)->name,
+ st->indio_dev);
+ if (ret)
+ goto error_unreg_iio_device;
+ }
+
+ return 0;
+
+error_unreg_iio_device:
+ iio_device_unregister(st->indio_dev);
+error_free_dev:
+ iio_free_device(st->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);
+
+ kfree(st);
+error_ret:
+ return ret;
+}
+
+static int __devexit ad5504_remove(struct spi_device *spi)
+{
+ struct ad5504_state *st = spi_get_drvdata(spi);
+
+ if (spi->irq)
+ free_irq(spi->irq, st->indio_dev);
+
+ iio_device_unregister(st->indio_dev);
+
+ if (!IS_ERR(st->reg)) {
+ regulator_disable(st->reg);
+ regulator_put(st->reg);
+ }
+
+ kfree(st);
+
+ return 0;
+}
+
+static const struct spi_device_id ad5504_id[] = {
+ {"ad5504", ID_AD5504},
+ {"ad5501", ID_AD5501},
+ {}
+};
+
+static struct spi_driver ad5504_driver = {
+ .driver = {
+ .name = "ad5504",
+ .owner = THIS_MODULE,
+ },
+ .probe = ad5504_probe,
+ .remove = __devexit_p(ad5504_remove),
+ .id_table = ad5504_id,
+};
+
+static __init int ad5504_spi_init(void)
+{
+ return spi_register_driver(&ad5504_driver);
+}
+module_init(ad5504_spi_init);
+
+static __exit void ad5504_spi_exit(void)
+{
+ spi_unregister_driver(&ad5504_driver);
+}
+module_exit(ad5504_spi_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD5501/AD5501 DAC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/dac/ad5504.h b/drivers/staging/iio/dac/ad5504.h
new file mode 100644
index 000000000000..13ef35399137
--- /dev/null
+++ b/drivers/staging/iio/dac/ad5504.h
@@ -0,0 +1,70 @@
+/*
+ * AD5504 SPI DAC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef SPI_AD5504_H_
+#define SPI_AD5504_H_
+
+#define AD5505_BITS 12
+#define AD5504_RES_MASK ((1 << (AD5505_BITS)) - 1)
+
+#define AD5504_CMD_READ (1 << 15)
+#define AD5504_CMD_WRITE (0 << 15)
+#define AD5504_ADDR(addr) ((addr) << 12)
+
+/* Registers */
+#define AD5504_ADDR_NOOP 0
+#define AD5504_ADDR_DAC0 1
+#define AD5504_ADDR_DAC1 2
+#define AD5504_ADDR_DAC2 3
+#define AD5504_ADDR_DAC3 4
+#define AD5504_ADDR_ALL_DAC 5
+#define AD5504_ADDR_CTRL 7
+
+/* Control Register */
+#define AD5504_DAC_PWR(ch) ((ch) << 2)
+#define AD5504_DAC_PWRDWN_MODE(mode) ((mode) << 6)
+#define AD5504_DAC_PWRDN_20K 0
+#define AD5504_DAC_PWRDN_3STATE 1
+
+/*
+ * TODO: struct ad5504_platform_data needs to go into include/linux/iio
+ */
+
+struct ad5504_platform_data {
+ u16 vref_mv;
+};
+
+/**
+ * struct ad5446_state - driver instance specific data
+ * @indio_dev: the industrial I/O device
+ * @us: spi_device
+ * @reg: supply regulator
+ * @vref_mv: actual reference voltage used
+ * @pwr_down_mask power down mask
+ * @pwr_down_mode current power down mode
+ */
+
+struct ad5504_state {
+ struct iio_dev *indio_dev;
+ struct spi_device *spi;
+ struct regulator *reg;
+ unsigned short vref_mv;
+ unsigned pwr_down_mask;
+ unsigned pwr_down_mode;
+};
+
+/**
+ * ad5504_supported_device_ids:
+ */
+
+enum ad5504_supported_device_ids {
+ ID_AD5504,
+ ID_AD5501,
+};
+
+#endif /* SPI_AD5504_H_ */
diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/staging/iio/dac/ad5624r_spi.c
index a945b18ff843..c679981f0143 100644
--- a/drivers/staging/iio/dac/ad5624r_spi.c
+++ b/drivers/staging/iio/dac/ad5624r_spi.c
@@ -174,17 +174,6 @@ static ssize_t ad5624r_show_scale(struct device *dev,
}
static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5624r_show_scale, NULL, 0);
-static ssize_t ad5624r_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
-
- return sprintf(buf, "%s\n", spi_get_device_id(st->us)->name);
-}
-static IIO_DEVICE_ATTR(name, S_IRUGO, ad5624r_show_name, NULL, 0);
-
static IIO_DEV_ATTR_OUT_RAW(0, ad5624r_write_dac, AD5624R_ADDR_DAC0);
static IIO_DEV_ATTR_OUT_RAW(1, ad5624r_write_dac, AD5624R_ADDR_DAC1);
static IIO_DEV_ATTR_OUT_RAW(2, ad5624r_write_dac, AD5624R_ADDR_DAC2);
@@ -222,7 +211,6 @@ static struct attribute *ad5624r_attributes[] = {
&iio_dev_attr_out_powerdown_mode.dev_attr.attr,
&iio_const_attr_out_powerdown_mode_available.dev_attr.attr,
&iio_dev_attr_out_scale.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
NULL,
};
@@ -230,6 +218,11 @@ static const struct attribute_group ad5624r_attribute_group = {
.attrs = ad5624r_attributes,
};
+static const struct iio_info ad5624r_info = {
+ .attrs = &ad5624r_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit ad5624r_probe(struct spi_device *spi)
{
struct ad5624r_state *st;
@@ -260,15 +253,15 @@ static int __devinit ad5624r_probe(struct spi_device *spi)
st->vref_mv = st->chip_info->int_vref_mv;
st->us = spi;
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_disable_reg;
}
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->attrs = &ad5624r_attribute_group;
+ st->indio_dev->name = spi_get_device_id(spi)->name;
+ st->indio_dev->info = &ad5624r_info;
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(st->indio_dev);
diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c
new file mode 100644
index 000000000000..4eda25cba870
--- /dev/null
+++ b/drivers/staging/iio/dac/ad5791.c
@@ -0,0 +1,444 @@
+/*
+ * AD5760, AD5780, AD5781, AD5791 Voltage Output Digital to Analog Converter
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/regulator/consumer.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "dac.h"
+#include "ad5791.h"
+
+static int ad5791_spi_write(struct spi_device *spi, u8 addr, u32 val)
+{
+ union {
+ u32 d32;
+ u8 d8[4];
+ } data;
+
+ data.d32 = cpu_to_be32(AD5791_CMD_WRITE |
+ AD5791_ADDR(addr) |
+ (val & AD5791_DAC_MASK));
+
+ return spi_write(spi, &data.d8[1], 3);
+}
+
+static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val)
+{
+ union {
+ u32 d32;
+ u8 d8[4];
+ } data[3];
+ int ret;
+ struct spi_message msg;
+ struct spi_transfer xfers[] = {
+ {
+ .tx_buf = &data[0].d8[1],
+ .bits_per_word = 8,
+ .len = 3,
+ .cs_change = 1,
+ }, {
+ .tx_buf = &data[1].d8[1],
+ .rx_buf = &data[2].d8[1],
+ .bits_per_word = 8,
+ .len = 3,
+ },
+ };
+
+ data[0].d32 = cpu_to_be32(AD5791_CMD_READ |
+ AD5791_ADDR(addr));
+ data[1].d32 = cpu_to_be32(AD5791_ADDR(AD5791_ADDR_NOOP));
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfers[0], &msg);
+ spi_message_add_tail(&xfers[1], &msg);
+ ret = spi_sync(spi, &msg);
+
+ *val = be32_to_cpu(data[2].d32);
+
+ return ret;
+}
+
+static ssize_t ad5791_write_dac(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ long readin;
+ int ret;
+
+ ret = strict_strtol(buf, 10, &readin);
+ if (ret)
+ return ret;
+
+ readin += (1 << (st->chip_info->bits - 1));
+ readin &= AD5791_RES_MASK(st->chip_info->bits);
+ readin <<= st->chip_info->left_shift;
+
+ ret = ad5791_spi_write(st->spi, this_attr->address, readin);
+ return ret ? ret : len;
+}
+
+static ssize_t ad5791_read_dac(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ int ret;
+ int val;
+
+ ret = ad5791_spi_read(st->spi, this_attr->address, &val);
+ if (ret)
+ return ret;
+
+ val &= AD5791_DAC_MASK;
+ val >>= st->chip_info->left_shift;
+ val -= (1 << (st->chip_info->bits - 1));
+
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t ad5791_read_powerdown_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+
+ const char mode[][14] = {"6kohm_to_gnd", "three_state"};
+
+ return sprintf(buf, "%s\n", mode[st->pwr_down_mode]);
+}
+
+static ssize_t ad5791_write_powerdown_mode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+ int ret;
+
+ if (sysfs_streq(buf, "6kohm_to_gnd"))
+ st->pwr_down_mode = AD5791_DAC_PWRDN_6K;
+ else if (sysfs_streq(buf, "three_state"))
+ st->pwr_down_mode = AD5791_DAC_PWRDN_3STATE;
+ else
+ ret = -EINVAL;
+
+ return ret ? ret : len;
+}
+
+static ssize_t ad5791_read_dac_powerdown(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+
+ return sprintf(buf, "%d\n", st->pwr_down);
+}
+
+static ssize_t ad5791_write_dac_powerdown(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ long readin;
+ int ret;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+
+ ret = strict_strtol(buf, 10, &readin);
+ if (ret)
+ return ret;
+
+ if (readin == 0) {
+ st->pwr_down = false;
+ st->ctrl &= ~(AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI);
+ } else if (readin == 1) {
+ st->pwr_down = true;
+ if (st->pwr_down_mode == AD5791_DAC_PWRDN_6K)
+ st->ctrl |= AD5791_CTRL_OPGND;
+ else if (st->pwr_down_mode == AD5791_DAC_PWRDN_3STATE)
+ st->ctrl |= AD5791_CTRL_DACTRI;
+ } else
+ ret = -EINVAL;
+
+ ret = ad5791_spi_write(st->spi, AD5791_ADDR_CTRL, st->ctrl);
+
+ return ret ? ret : len;
+}
+
+static ssize_t ad5791_show_scale(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+ /* Corresponds to Vref / 2^(bits) */
+ unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits;
+
+ return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
+}
+static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5791_show_scale, NULL, 0);
+
+static ssize_t ad5791_show_name(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+
+ return sprintf(buf, "%s\n", spi_get_device_id(st->spi)->name);
+}
+static IIO_DEVICE_ATTR(name, S_IRUGO, ad5791_show_name, NULL, 0);
+
+#define IIO_DEV_ATTR_OUT_RW_RAW(_num, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(out##_num##_raw, \
+ S_IRUGO | S_IWUSR, _show, _store, _addr)
+
+static IIO_DEV_ATTR_OUT_RW_RAW(0, ad5791_read_dac,
+ ad5791_write_dac, AD5791_ADDR_DAC0);
+
+static IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO |
+ S_IWUSR, ad5791_read_powerdown_mode,
+ ad5791_write_powerdown_mode, 0);
+
+static IIO_CONST_ATTR(out_powerdown_mode_available,
+ "6kohm_to_gnd three_state");
+
+#define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(out##_num##_powerdown, \
+ S_IRUGO | S_IWUSR, _show, _store, _addr)
+
+static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5791_read_dac_powerdown,
+ ad5791_write_dac_powerdown, 0);
+
+static struct attribute *ad5791_attributes[] = {
+ &iio_dev_attr_out0_raw.dev_attr.attr,
+ &iio_dev_attr_out0_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_powerdown_mode.dev_attr.attr,
+ &iio_const_attr_out_powerdown_mode_available.dev_attr.attr,
+ &iio_dev_attr_out_scale.dev_attr.attr,
+ &iio_dev_attr_name.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group ad5791_attribute_group = {
+ .attrs = ad5791_attributes,
+};
+
+static int ad5791_get_lin_comp(unsigned int span)
+{
+ if (span <= 10000)
+ return AD5791_LINCOMP_0_10;
+ else if (span <= 12000)
+ return AD5791_LINCOMP_10_12;
+ else if (span <= 16000)
+ return AD5791_LINCOMP_12_16;
+ else if (span <= 19000)
+ return AD5791_LINCOMP_16_19;
+ else
+ return AD5791_LINCOMP_19_20;
+}
+
+static int ad5780_get_lin_comp(unsigned int span)
+{
+ if (span <= 10000)
+ return AD5780_LINCOMP_0_10;
+ else
+ return AD5780_LINCOMP_10_20;
+}
+
+static const struct ad5791_chip_info ad5791_chip_info_tbl[] = {
+ [ID_AD5760] = {
+ .bits = 16,
+ .left_shift = 4,
+ .get_lin_comp = ad5780_get_lin_comp,
+ },
+ [ID_AD5780] = {
+ .bits = 18,
+ .left_shift = 2,
+ .get_lin_comp = ad5780_get_lin_comp,
+ },
+ [ID_AD5781] = {
+ .bits = 18,
+ .left_shift = 2,
+ .get_lin_comp = ad5791_get_lin_comp,
+ },
+ [ID_AD5791] = {
+ .bits = 20,
+ .left_shift = 0,
+ .get_lin_comp = ad5791_get_lin_comp,
+ },
+};
+
+static const struct iio_info ad5791_info = {
+ .attrs = &ad5791_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
+static int __devinit ad5791_probe(struct spi_device *spi)
+{
+ struct ad5791_platform_data *pdata = spi->dev.platform_data;
+ struct ad5791_state *st;
+ int ret, pos_voltage_uv = 0, neg_voltage_uv = 0;
+
+ st = kzalloc(sizeof(*st), GFP_KERNEL);
+ if (st == NULL) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+
+ spi_set_drvdata(spi, st);
+
+ st->reg_vdd = regulator_get(&spi->dev, "vdd");
+ if (!IS_ERR(st->reg_vdd)) {
+ ret = regulator_enable(st->reg_vdd);
+ if (ret)
+ goto error_put_reg_pos;
+
+ pos_voltage_uv = regulator_get_voltage(st->reg_vdd);
+ }
+
+ st->reg_vss = regulator_get(&spi->dev, "vss");
+ if (!IS_ERR(st->reg_vss)) {
+ ret = regulator_enable(st->reg_vss);
+ if (ret)
+ goto error_put_reg_neg;
+
+ neg_voltage_uv = regulator_get_voltage(st->reg_vss);
+ }
+
+ if (!IS_ERR(st->reg_vss) && !IS_ERR(st->reg_vdd))
+ st->vref_mv = (pos_voltage_uv - neg_voltage_uv) / 1000;
+ else if (pdata)
+ st->vref_mv = pdata->vref_pos_mv - pdata->vref_neg_mv;
+ else
+ dev_warn(&spi->dev, "reference voltage unspecified\n");
+
+ ret = ad5791_spi_write(spi, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET);
+ if (ret)
+ goto error_disable_reg_neg;
+
+ st->chip_info =
+ &ad5791_chip_info_tbl[spi_get_device_id(spi)->driver_data];
+
+
+ st->ctrl = AD5761_CTRL_LINCOMP(st->chip_info->get_lin_comp(st->vref_mv))
+ | ((pdata && pdata->use_rbuf_gain2) ? 0 : AD5791_CTRL_RBUF) |
+ AD5791_CTRL_BIN2SC;
+
+ ret = ad5791_spi_write(spi, AD5791_ADDR_CTRL, st->ctrl |
+ AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI);
+ if (ret)
+ goto error_disable_reg_neg;
+
+ st->pwr_down = true;
+
+ st->spi = spi;
+ st->indio_dev = iio_allocate_device(0);
+ if (st->indio_dev == NULL) {
+ ret = -ENOMEM;
+ goto error_disable_reg_neg;
+ }
+ st->indio_dev->dev.parent = &spi->dev;
+ st->indio_dev->dev_data = (void *)(st);
+ st->indio_dev->info = &ad5791_info;
+ st->indio_dev->modes = INDIO_DIRECT_MODE;
+
+ ret = iio_device_register(st->indio_dev);
+ if (ret)
+ goto error_free_dev;
+
+ return 0;
+
+error_free_dev:
+ iio_free_device(st->indio_dev);
+
+error_disable_reg_neg:
+ if (!IS_ERR(st->reg_vss))
+ regulator_disable(st->reg_vss);
+error_put_reg_neg:
+ if (!IS_ERR(st->reg_vss))
+ regulator_put(st->reg_vss);
+
+ if (!IS_ERR(st->reg_vdd))
+ regulator_disable(st->reg_vdd);
+error_put_reg_pos:
+ if (!IS_ERR(st->reg_vdd))
+ regulator_put(st->reg_vdd);
+
+ kfree(st);
+error_ret:
+ return ret;
+}
+
+static int __devexit ad5791_remove(struct spi_device *spi)
+{
+ struct ad5791_state *st = spi_get_drvdata(spi);
+
+ iio_device_unregister(st->indio_dev);
+
+ if (!IS_ERR(st->reg_vdd)) {
+ regulator_disable(st->reg_vdd);
+ regulator_put(st->reg_vdd);
+ }
+
+ if (!IS_ERR(st->reg_vss)) {
+ regulator_disable(st->reg_vss);
+ regulator_put(st->reg_vss);
+ }
+
+ kfree(st);
+
+ return 0;
+}
+
+static const struct spi_device_id ad5791_id[] = {
+ {"ad5760", ID_AD5760},
+ {"ad5780", ID_AD5780},
+ {"ad5781", ID_AD5781},
+ {"ad5791", ID_AD5791},
+ {}
+};
+
+static struct spi_driver ad5791_driver = {
+ .driver = {
+ .name = "ad5791",
+ .owner = THIS_MODULE,
+ },
+ .probe = ad5791_probe,
+ .remove = __devexit_p(ad5791_remove),
+ .id_table = ad5791_id,
+};
+
+static __init int ad5791_spi_init(void)
+{
+ return spi_register_driver(&ad5791_driver);
+}
+module_init(ad5791_spi_init);
+
+static __exit void ad5791_spi_exit(void)
+{
+ spi_unregister_driver(&ad5791_driver);
+}
+module_exit(ad5791_spi_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD5760/AD5780/AD5781/AD5791 DAC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/dac/ad5791.h b/drivers/staging/iio/dac/ad5791.h
new file mode 100644
index 000000000000..f09ad9a430c3
--- /dev/null
+++ b/drivers/staging/iio/dac/ad5791.h
@@ -0,0 +1,116 @@
+/*
+ * AD5791 SPI DAC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef SPI_AD5791_H_
+#define SPI_AD5791_H_
+
+#define AD5791_RES_MASK(x) ((1 << (x)) - 1)
+#define AD5791_DAC_MASK AD5791_RES_MASK(20)
+#define AD5791_DAC_MSB (1 << 19)
+
+#define AD5791_CMD_READ (1 << 23)
+#define AD5791_CMD_WRITE (0 << 23)
+#define AD5791_ADDR(addr) ((addr) << 20)
+
+/* Registers */
+#define AD5791_ADDR_NOOP 0
+#define AD5791_ADDR_DAC0 1
+#define AD5791_ADDR_CTRL 2
+#define AD5791_ADDR_CLRCODE 3
+#define AD5791_ADDR_SW_CTRL 4
+
+/* Control Register */
+#define AD5791_CTRL_RBUF (1 << 1)
+#define AD5791_CTRL_OPGND (1 << 2)
+#define AD5791_CTRL_DACTRI (1 << 3)
+#define AD5791_CTRL_BIN2SC (1 << 4)
+#define AD5791_CTRL_SDODIS (1 << 5)
+#define AD5761_CTRL_LINCOMP(x) ((x) << 6)
+
+#define AD5791_LINCOMP_0_10 0
+#define AD5791_LINCOMP_10_12 1
+#define AD5791_LINCOMP_12_16 2
+#define AD5791_LINCOMP_16_19 3
+#define AD5791_LINCOMP_19_20 12
+
+#define AD5780_LINCOMP_0_10 0
+#define AD5780_LINCOMP_10_20 12
+
+/* Software Control Register */
+#define AD5791_SWCTRL_LDAC (1 << 0)
+#define AD5791_SWCTRL_CLR (1 << 1)
+#define AD5791_SWCTRL_RESET (1 << 2)
+
+#define AD5791_DAC_PWRDN_6K 0
+#define AD5791_DAC_PWRDN_3STATE 1
+
+/*
+ * TODO: struct ad5791_platform_data needs to go into include/linux/iio
+ */
+
+/**
+ * struct ad5791_platform_data - platform specific information
+ * @vref_pos_mv: Vdd Positive Analog Supply Volatge (mV)
+ * @vref_neg_mv: Vdd Negative Analog Supply Volatge (mV)
+ * @use_rbuf_gain2: ext. amplifier connected in gain of two configuration
+ */
+
+struct ad5791_platform_data {
+ u16 vref_pos_mv;
+ u16 vref_neg_mv;
+ bool use_rbuf_gain2;
+};
+
+/**
+ * struct ad5791_chip_info - chip specific information
+ * @bits: accuracy of the DAC in bits
+ * @left_shift: number of bits the datum must be shifted
+ * @get_lin_comp: function pointer to the device specific function
+ */
+
+struct ad5791_chip_info {
+ u8 bits;
+ u8 left_shift;
+ int (*get_lin_comp) (unsigned int span);
+};
+
+/**
+ * struct ad5791_state - driver instance specific data
+ * @indio_dev: the industrial I/O device
+ * @us: spi_device
+ * @reg_vdd: positive supply regulator
+ * @reg_vss: negative supply regulator
+ * @chip_info: chip model specific constants
+ * @vref_mv: actual reference voltage used
+ * @pwr_down_mode current power down mode
+ */
+
+struct ad5791_state {
+ struct iio_dev *indio_dev;
+ struct spi_device *spi;
+ struct regulator *reg_vdd;
+ struct regulator *reg_vss;
+ const struct ad5791_chip_info *chip_info;
+ unsigned short vref_mv;
+ unsigned ctrl;
+ unsigned pwr_down_mode;
+ bool pwr_down;
+};
+
+/**
+ * ad5791_supported_device_ids:
+ */
+
+enum ad5791_supported_device_ids {
+ ID_AD5760,
+ ID_AD5780,
+ ID_AD5781,
+ ID_AD5791,
+};
+
+#endif /* SPI_AD5791_H_ */
diff --git a/drivers/staging/iio/dac/max517.c b/drivers/staging/iio/dac/max517.c
index 7071f713604a..2fe34d21b6aa 100644
--- a/drivers/staging/iio/dac/max517.c
+++ b/drivers/staging/iio/dac/max517.c
@@ -189,6 +189,16 @@ static int max517_resume(struct i2c_client *client)
return i2c_master_send(client, &outbuf, 1);
}
+static const struct iio_info max517_info = {
+ .attrs = &max517_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
+static const struct iio_info max518_info = {
+ .attrs = &max518_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int max517_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -206,7 +216,7 @@ static int max517_probe(struct i2c_client *client,
data->client = client;
- data->indio_dev = iio_allocate_device();
+ data->indio_dev = iio_allocate_device(0);
if (data->indio_dev == NULL) {
err = -ENOMEM;
goto exit_free_data;
@@ -217,11 +227,10 @@ static int max517_probe(struct i2c_client *client,
/* reduced attribute set for MAX517 */
if (id->driver_data == ID_MAX517)
- data->indio_dev->attrs = &max517_attribute_group;
+ data->indio_dev->info = &max517_info;
else
- data->indio_dev->attrs = &max518_attribute_group;
+ data->indio_dev->info = &max518_info;
data->indio_dev->dev_data = (void *)(data);
- data->indio_dev->driver_module = THIS_MODULE;
data->indio_dev->modes = INDIO_DIRECT_MODE;
/*
diff --git a/drivers/staging/iio/dds/Kconfig b/drivers/staging/iio/dds/Kconfig
index 06b6f3a8e420..e07431d80093 100644
--- a/drivers/staging/iio/dds/Kconfig
+++ b/drivers/staging/iio/dds/Kconfig
@@ -21,11 +21,11 @@ config AD9832
module will be called ad9832.
config AD9834
- tristate "Analog Devices ad9833/4/ driver"
+ tristate "Analog Devices AD9833/4/7/8 driver"
depends on SPI
help
Say yes here to build support for Analog Devices DDS chip
- AD9833 and AD9834, provides direct access via sysfs.
+ AD9833, AD9834, AD9837 and AD9838, provides direct access via sysfs.
To compile this driver as a module, choose M here: the
module will be called ad9834.
diff --git a/drivers/staging/iio/dds/ad5930.c b/drivers/staging/iio/dds/ad5930.c
index f80039c5d539..490c3637bc8e 100644
--- a/drivers/staging/iio/dds/ad5930.c
+++ b/drivers/staging/iio/dds/ad5930.c
@@ -87,6 +87,12 @@ static const struct attribute_group ad5930_attribute_group = {
.attrs = ad5930_attributes,
};
+static const struct iio_info ad5930_info = {
+ .attrs = &ad5930_attribute_group,
+
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit ad5930_probe(struct spi_device *spi)
{
struct ad5930_state *st;
@@ -102,18 +108,14 @@ static int __devinit ad5930_probe(struct spi_device *spi)
mutex_init(&st->lock);
st->sdev = spi;
- st->idev = iio_allocate_device();
+ st->idev = iio_allocate_device(0);
if (st->idev == NULL) {
ret = -ENOMEM;
goto error_free_st;
}
st->idev->dev.parent = &spi->dev;
- st->idev->num_interrupt_lines = 0;
- st->idev->event_attrs = NULL;
-
- st->idev->attrs = &ad5930_attribute_group;
st->idev->dev_data = (void *)(st);
- st->idev->driver_module = THIS_MODULE;
+ st->idev->info = &ad5930_info;
st->idev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(st->idev);
diff --git a/drivers/staging/iio/dds/ad9832.c b/drivers/staging/iio/dds/ad9832.c
index 3e8491f60cfe..e8fe1426a329 100644
--- a/drivers/staging/iio/dds/ad9832.c
+++ b/drivers/staging/iio/dds/ad9832.c
@@ -153,17 +153,6 @@ error_ret:
return ret ? ret : len;
}
-static ssize_t ad9832_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad9832_state *st = iio_dev_get_devdata(dev_info);
-
- return sprintf(buf, "%s\n", spi_get_device_id(st->spi)->name);
-}
-static IIO_DEVICE_ATTR(name, S_IRUGO, ad9832_show_name, NULL, 0);
-
/**
* see dds.h for further information
*/
@@ -199,7 +188,6 @@ static struct attribute *ad9832_attributes[] = {
&iio_dev_attr_dds0_freqsymbol.dev_attr.attr,
&iio_dev_attr_dds0_phasesymbol.dev_attr.attr,
&iio_dev_attr_dds0_out_enable.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
NULL,
};
@@ -207,6 +195,11 @@ static const struct attribute_group ad9832_attribute_group = {
.attrs = ad9832_attributes,
};
+static const struct iio_info ad9832_info = {
+ .attrs = &ad9832_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit ad9832_probe(struct spi_device *spi)
{
struct ad9832_platform_data *pdata = spi->dev.platform_data;
@@ -236,16 +229,16 @@ static int __devinit ad9832_probe(struct spi_device *spi)
spi_set_drvdata(spi, st);
st->spi = spi;
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_disable_reg;
}
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->attrs = &ad9832_attribute_group;
+ st->indio_dev->name = spi_get_device_id(spi)->name;
+ st->indio_dev->info = &ad9832_info;
st->indio_dev->dev_data = (void *) st;
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
/* Setup default messages */
diff --git a/drivers/staging/iio/dds/ad9834.c b/drivers/staging/iio/dds/ad9834.c
index eb1a681874f9..0ebe8d58e92e 100644
--- a/drivers/staging/iio/dds/ad9834.c
+++ b/drivers/staging/iio/dds/ad9834.c
@@ -1,9 +1,9 @@
/*
- * AD9834 SPI DAC driver
+ * AD9833/AD9834/AD9837/AD9838 SPI DDS driver
*
- * Copyright 2010 Analog Devices Inc.
+ * Copyright 2010-2011 Analog Devices Inc.
*
- * Licensed under the GPL-2 or later.
+ * Licensed under the GPL-2.
*/
#include <linux/interrupt.h>
@@ -47,7 +47,7 @@ static int ad9834_write_frequency(struct ad9834_state *st,
(AD9834_FREQ_BITS / 2)) &
RES_MASK(AD9834_FREQ_BITS / 2)));
- return spi_sync(st->spi, &st->freq_msg);;
+ return spi_sync(st->spi, &st->freq_msg);
}
static int ad9834_write_phase(struct ad9834_state *st,
@@ -148,7 +148,7 @@ static ssize_t ad9834_store_wavetype(struct device *dev,
struct ad9834_state *st = dev_info->dev_data;
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret = 0;
- bool is_ad9833 = st->devid == ID_AD9833;
+ bool is_ad9833_7 = (st->devid == ID_AD9833) || (st->devid == ID_AD9837);
mutex_lock(&dev_info->mlock);
@@ -156,10 +156,10 @@ static ssize_t ad9834_store_wavetype(struct device *dev,
case 0:
if (sysfs_streq(buf, "sine")) {
st->control &= ~AD9834_MODE;
- if (is_ad9833)
+ if (is_ad9833_7)
st->control &= ~AD9834_OPBITEN;
} else if (sysfs_streq(buf, "triangle")) {
- if (is_ad9833) {
+ if (is_ad9833_7) {
st->control &= ~AD9834_OPBITEN;
st->control |= AD9834_MODE;
} else if (st->control & AD9834_OPBITEN) {
@@ -167,7 +167,7 @@ static ssize_t ad9834_store_wavetype(struct device *dev,
} else {
st->control |= AD9834_MODE;
}
- } else if (is_ad9833 && sysfs_streq(buf, "square")) {
+ } else if (is_ad9833_7 && sysfs_streq(buf, "square")) {
st->control &= ~AD9834_MODE;
st->control |= AD9834_OPBITEN;
} else {
@@ -198,17 +198,6 @@ static ssize_t ad9834_store_wavetype(struct device *dev,
return ret ? ret : len;
}
-static ssize_t ad9834_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
- struct ad9834_state *st = iio_dev_get_devdata(dev_info);
-
- return sprintf(buf, "%s\n", spi_get_device_id(st->spi)->name);
-}
-static IIO_DEVICE_ATTR(name, S_IRUGO, ad9834_show_name, NULL, 0);
-
static ssize_t ad9834_show_out0_wavetype_available(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -217,7 +206,7 @@ static ssize_t ad9834_show_out0_wavetype_available(struct device *dev,
struct ad9834_state *st = iio_dev_get_devdata(dev_info);
char *str;
- if (st->devid == ID_AD9833)
+ if ((st->devid == ID_AD9833) || (st->devid == ID_AD9837))
str = "sine triangle square";
else if (st->control & AD9834_OPBITEN)
str = "sine";
@@ -288,7 +277,6 @@ static struct attribute *ad9834_attributes[] = {
&iio_dev_attr_dds0_out1_wavetype.dev_attr.attr,
&iio_dev_attr_dds0_out0_wavetype_available.dev_attr.attr,
&iio_dev_attr_dds0_out1_wavetype_available.dev_attr.attr,
- &iio_dev_attr_name.dev_attr.attr,
NULL,
};
@@ -301,13 +289,12 @@ static mode_t ad9834_attr_is_visible(struct kobject *kobj,
mode_t mode = attr->mode;
- if (st->devid == ID_AD9834)
- return mode;
-
- if ((attr == &iio_dev_attr_dds0_out1_enable.dev_attr.attr) ||
+ if (((st->devid == ID_AD9833) || (st->devid == ID_AD9837)) &&
+ ((attr == &iio_dev_attr_dds0_out1_enable.dev_attr.attr) ||
(attr == &iio_dev_attr_dds0_out1_wavetype.dev_attr.attr) ||
(attr ==
- &iio_dev_attr_dds0_out1_wavetype_available.dev_attr.attr))
+ &iio_dev_attr_dds0_out1_wavetype_available.dev_attr.attr) ||
+ (attr == &iio_dev_attr_dds0_pincontrol_en.dev_attr.attr)))
mode = 0;
return mode;
@@ -318,6 +305,11 @@ static const struct attribute_group ad9834_attribute_group = {
.is_visible = ad9834_attr_is_visible,
};
+static const struct iio_info ad9834_info = {
+ .attrs = &ad9834_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit ad9834_probe(struct spi_device *spi)
{
struct ad9834_platform_data *pdata = spi->dev.platform_data;
@@ -349,16 +341,16 @@ static int __devinit ad9834_probe(struct spi_device *spi)
st->spi = spi;
st->devid = spi_get_device_id(spi)->driver_data;
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_disable_reg;
}
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->attrs = &ad9834_attribute_group;
+ st->indio_dev->name = spi_get_device_id(spi)->name;
+ st->indio_dev->info = &ad9834_info;
st->indio_dev->dev_data = (void *) st;
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
/* Setup default messages */
@@ -445,6 +437,8 @@ static int __devexit ad9834_remove(struct spi_device *spi)
static const struct spi_device_id ad9834_id[] = {
{"ad9833", ID_AD9833},
{"ad9834", ID_AD9834},
+ {"ad9837", ID_AD9837},
+ {"ad9838", ID_AD9838},
{}
};
@@ -472,6 +466,6 @@ static void __exit ad9834_exit(void)
module_exit(ad9834_exit);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("Analog Devices AD9833/AD9834 DDS");
+MODULE_DESCRIPTION("Analog Devices AD9833/AD9834/AD9837/AD9838 DDS");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:ad9834");
diff --git a/drivers/staging/iio/dds/ad9834.h b/drivers/staging/iio/dds/ad9834.h
index 0fc3b8859e9e..2abd63587e03 100644
--- a/drivers/staging/iio/dds/ad9834.h
+++ b/drivers/staging/iio/dds/ad9834.h
@@ -1,9 +1,9 @@
/*
- * AD9834 SPI DDS driver
+ * AD9833/AD9834/AD9837/AD9838 SPI DDS driver
*
- * Copyright 2010 Analog Devices Inc.
+ * Copyright 2010-2011 Analog Devices Inc.
*
- * Licensed under the GPL-2 or later.
+ * Licensed under the GPL-2.
*/
#ifndef IIO_DDS_AD9834_H_
#define IIO_DDS_AD9834_H_
@@ -107,6 +107,8 @@ struct ad9834_platform_data {
enum ad9834_supported_device_ids {
ID_AD9833,
ID_AD9834,
+ ID_AD9837,
+ ID_AD9838,
};
#endif /* IIO_DDS_AD9834_H_ */
diff --git a/drivers/staging/iio/dds/ad9850.c b/drivers/staging/iio/dds/ad9850.c
index b259bfeaf5aa..b580d852a1ee 100644
--- a/drivers/staging/iio/dds/ad9850.c
+++ b/drivers/staging/iio/dds/ad9850.c
@@ -73,6 +73,11 @@ static const struct attribute_group ad9850_attribute_group = {
.attrs = ad9850_attributes,
};
+static const struct iio_info ad9850_info = {
+ .attrs = &ad9850_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit ad9850_probe(struct spi_device *spi)
{
struct ad9850_state *st;
@@ -88,18 +93,15 @@ static int __devinit ad9850_probe(struct spi_device *spi)
mutex_init(&st->lock);
st->sdev = spi;
- st->idev = iio_allocate_device();
+ st->idev = iio_allocate_device(0);
if (st->idev == NULL) {
ret = -ENOMEM;
goto error_free_st;
}
st->idev->dev.parent = &spi->dev;
- st->idev->num_interrupt_lines = 0;
- st->idev->event_attrs = NULL;
- st->idev->attrs = &ad9850_attribute_group;
+ st->idev->info = &ad9850_info;
st->idev->dev_data = (void *)(st);
- st->idev->driver_module = THIS_MODULE;
st->idev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(st->idev);
diff --git a/drivers/staging/iio/dds/ad9852.c b/drivers/staging/iio/dds/ad9852.c
index 594fb6a94331..08020f96300a 100644
--- a/drivers/staging/iio/dds/ad9852.c
+++ b/drivers/staging/iio/dds/ad9852.c
@@ -222,6 +222,11 @@ static const struct attribute_group ad9852_attribute_group = {
.attrs = ad9852_attributes,
};
+static const struct iio_info ad9852_info = {
+ .attrs = &ad9852_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit ad9852_probe(struct spi_device *spi)
{
struct ad9852_state *st;
@@ -237,18 +242,15 @@ static int __devinit ad9852_probe(struct spi_device *spi)
mutex_init(&st->lock);
st->sdev = spi;
- st->idev = iio_allocate_device();
+ st->idev = iio_allocate_device(0);
if (st->idev == NULL) {
ret = -ENOMEM;
goto error_free_st;
}
st->idev->dev.parent = &spi->dev;
- st->idev->num_interrupt_lines = 0;
- st->idev->event_attrs = NULL;
- st->idev->attrs = &ad9852_attribute_group;
+ st->idev->info = &ad9852_info;
st->idev->dev_data = (void *)(st);
- st->idev->driver_module = THIS_MODULE;
st->idev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(st->idev);
diff --git a/drivers/staging/iio/dds/ad9910.c b/drivers/staging/iio/dds/ad9910.c
index e8fb75cb66ec..97d75d755824 100644
--- a/drivers/staging/iio/dds/ad9910.c
+++ b/drivers/staging/iio/dds/ad9910.c
@@ -357,6 +357,11 @@ static const struct attribute_group ad9910_attribute_group = {
.attrs = ad9910_attributes,
};
+static const struct iio_info ad9910_info = {
+ .attrs = &ad9910_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit ad9910_probe(struct spi_device *spi)
{
struct ad9910_state *st;
@@ -372,18 +377,15 @@ static int __devinit ad9910_probe(struct spi_device *spi)
mutex_init(&st->lock);
st->sdev = spi;
- st->idev = iio_allocate_device();
+ st->idev = iio_allocate_device(0);
if (st->idev == NULL) {
ret = -ENOMEM;
goto error_free_st;
}
st->idev->dev.parent = &spi->dev;
- st->idev->num_interrupt_lines = 0;
- st->idev->event_attrs = NULL;
- st->idev->attrs = &ad9910_attribute_group;
+ st->idev->info = &ad9910_info;
st->idev->dev_data = (void *)(st);
- st->idev->driver_module = THIS_MODULE;
st->idev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(st->idev);
diff --git a/drivers/staging/iio/dds/ad9951.c b/drivers/staging/iio/dds/ad9951.c
index 57eddf6d4713..d4dfcd41d5f9 100644
--- a/drivers/staging/iio/dds/ad9951.c
+++ b/drivers/staging/iio/dds/ad9951.c
@@ -166,6 +166,11 @@ static const struct attribute_group ad9951_attribute_group = {
.attrs = ad9951_attributes,
};
+static const struct iio_info ad9951_info = {
+ .attrs = &ad9951_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit ad9951_probe(struct spi_device *spi)
{
struct ad9951_state *st;
@@ -181,18 +186,15 @@ static int __devinit ad9951_probe(struct spi_device *spi)
mutex_init(&st->lock);
st->sdev = spi;
- st->idev = iio_allocate_device();
+ st->idev = iio_allocate_device(0);
if (st->idev == NULL) {
ret = -ENOMEM;
goto error_free_st;
}
st->idev->dev.parent = &spi->dev;
- st->idev->num_interrupt_lines = 0;
- st->idev->event_attrs = NULL;
- st->idev->attrs = &ad9951_attribute_group;
+ st->idev->info = &ad9951_info;
st->idev->dev_data = (void *)(st);
- st->idev->driver_module = THIS_MODULE;
st->idev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(st->idev);
diff --git a/drivers/staging/iio/gyro/Kconfig b/drivers/staging/iio/gyro/Kconfig
index 8b78fa0e6316..ae2e7d3095ae 100644
--- a/drivers/staging/iio/gyro/Kconfig
+++ b/drivers/staging/iio/gyro/Kconfig
@@ -35,3 +35,13 @@ config ADIS16260
This driver can also be built as a module. If so, the module
will be called adis16260.
+
+config ADXRS450
+ tristate "Analog Devices ADXRS450 Digital Output Gyroscope SPI driver"
+ depends on SPI
+ help
+ Say yes here to build support for Analog Devices ADXRS450 programmable
+ digital output gyroscope.
+
+ This driver can also be built as a module. If so, the module
+ will be called adxrs450.
diff --git a/drivers/staging/iio/gyro/Makefile b/drivers/staging/iio/gyro/Makefile
index 2764c15025a5..2212240f7de3 100644
--- a/drivers/staging/iio/gyro/Makefile
+++ b/drivers/staging/iio/gyro/Makefile
@@ -17,3 +17,6 @@ obj-$(CONFIG_ADIS16260) += adis16260.o
adis16251-y := adis16251_core.o
obj-$(CONFIG_ADIS16251) += adis16251.o
+
+adxrs450-y := adxrs450_core.o
+obj-$(CONFIG_ADXRS450) += adxrs450.o
diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c
index ae53e71d1c2f..edf9e3bf3efd 100644
--- a/drivers/staging/iio/gyro/adis16060_core.c
+++ b/drivers/staging/iio/gyro/adis16060_core.c
@@ -133,6 +133,11 @@ static const struct attribute_group adis16060_attribute_group = {
.attrs = adis16060_attributes,
};
+static const struct iio_info adis16060_info = {
+ .attrs = &adis16060_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit adis16060_r_probe(struct spi_device *spi)
{
int ret, regdone = 0;
@@ -147,16 +152,15 @@ static int __devinit adis16060_r_probe(struct spi_device *spi)
st->us_r = spi;
mutex_init(&st->buf_lock);
/* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_st;
}
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->attrs = &adis16060_attribute_group;
+ st->indio_dev->info = &adis16060_info;
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(st->indio_dev);
diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c
index ef9e304a226d..d42690bea066 100644
--- a/drivers/staging/iio/gyro/adis16080_core.c
+++ b/drivers/staging/iio/gyro/adis16080_core.c
@@ -110,14 +110,12 @@ 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 IIO_CONST_ATTR(name, "adis16080");
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,
- &iio_const_attr_name.dev_attr.attr,
NULL
};
@@ -125,6 +123,11 @@ static const struct attribute_group adis16080_attribute_group = {
.attrs = adis16080_attributes,
};
+static const struct iio_info adis16080_info = {
+ .attrs = &adis16080_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit adis16080_probe(struct spi_device *spi)
{
int ret, regdone = 0;
@@ -140,16 +143,16 @@ static int __devinit adis16080_probe(struct spi_device *spi)
st->us = spi;
mutex_init(&st->buf_lock);
/* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_st;
}
+ st->indio_dev->name = spi->dev.driver->name;
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->attrs = &adis16080_attribute_group;
+ st->indio_dev->info = &adis16080_info;
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(st->indio_dev);
diff --git a/drivers/staging/iio/gyro/adis16130_core.c b/drivers/staging/iio/gyro/adis16130_core.c
index 70e2831f8fb8..14d5a34ab441 100644
--- a/drivers/staging/iio/gyro/adis16130_core.c
+++ b/drivers/staging/iio/gyro/adis16130_core.c
@@ -155,8 +155,6 @@ static ssize_t adis16130_bitsmode_write(struct device *dev,
static IIO_DEVICE_ATTR(temp_raw, S_IRUGO, adis16130_val_read, NULL,
ADIS16130_TEMPDATA);
-static IIO_CONST_ATTR(name, "adis16130");
-
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,
@@ -167,7 +165,6 @@ static IIO_CONST_ATTR(gyro_z_type_available, "s16 s24");
static struct attribute *adis16130_attributes[] = {
&iio_dev_attr_temp_raw.dev_attr.attr,
- &iio_const_attr_name.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,
@@ -178,6 +175,11 @@ static const struct attribute_group adis16130_attribute_group = {
.attrs = adis16130_attributes,
};
+static const struct iio_info adis16130_info = {
+ .attrs = &adis16130_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit adis16130_probe(struct spi_device *spi)
{
int ret;
@@ -191,16 +193,16 @@ static int __devinit adis16130_probe(struct spi_device *spi)
st->us = spi;
mutex_init(&st->buf_lock);
/* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_st;
}
+ st->indio_dev->name = spi->dev.driver->name;
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->attrs = &adis16130_attribute_group;
+ st->indio_dev->info = &adis16130_info;
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
st->mode = 1;
diff --git a/drivers/staging/iio/gyro/adis16260.h b/drivers/staging/iio/gyro/adis16260.h
index 1369501b4096..702dc982f62f 100644
--- a/drivers/staging/iio/gyro/adis16260.h
+++ b/drivers/staging/iio/gyro/adis16260.h
@@ -85,9 +85,6 @@
/**
* struct adis16260_state - device instance specific data
* @us: actual spi_device
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter: used to check if new interrupt has been triggered
- * @last_timestamp: passing timestamp from th to bh of interrupt handler
* @indio_dev: industrial I/O device structure
* @trig: data ready trigger registered with iio
* @tx: transmit buffer
@@ -97,8 +94,6 @@
**/
struct adis16260_state {
struct spi_device *us;
- struct work_struct work_trigger_to_ring;
- s64 last_timestamp;
struct iio_dev *indio_dev;
struct iio_trigger *trig;
u8 *tx;
@@ -107,7 +102,7 @@ struct adis16260_state {
unsigned negate:1;
};
-int adis16260_set_irq(struct device *dev, bool enable);
+int adis16260_set_irq(struct iio_dev *indio_dev, bool enable);
#ifdef CONFIG_IIO_RING_BUFFER
/* At the moment triggers are only used for ring buffer
diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c
index 69a29ec93101..3dc9a272749d 100644
--- a/drivers/staging/iio/gyro/adis16260_core.c
+++ b/drivers/staging/iio/gyro/adis16260_core.c
@@ -28,20 +28,19 @@
#define DRIVER_NAME "adis16260"
-static int adis16260_check_status(struct device *dev);
+static int adis16260_check_status(struct iio_dev *indio_dev);
/**
* adis16260_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_dev for the device
* @reg_address: the address of the register to be written
* @val: the value to write
**/
-static int adis16260_spi_write_reg_8(struct device *dev,
+static int adis16260_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 adis16260_state *st = iio_dev_get_devdata(indio_dev);
mutex_lock(&st->buf_lock);
@@ -56,18 +55,17 @@ static int adis16260_spi_write_reg_8(struct device *dev,
/**
* adis16260_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_dev for the device
* @reg_address: the address of the lower of the two registers. Second register
* is assumed to have address one greater.
* @val: value to be written
**/
-static int adis16260_spi_write_reg_16(struct device *dev,
+static int adis16260_spi_write_reg_16(struct iio_dev *indio_dev,
u8 lower_reg_address,
u16 value)
{
int ret;
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16260_state *st = iio_dev_get_devdata(indio_dev);
struct spi_transfer xfers[] = {
{
@@ -80,7 +78,6 @@ static int adis16260_spi_write_reg_16(struct device *dev,
.tx_buf = st->tx + 2,
.bits_per_word = 8,
.len = 2,
- .cs_change = 1,
.delay_usecs = 20,
},
};
@@ -102,17 +99,16 @@ static int adis16260_spi_write_reg_16(struct device *dev,
/**
* adis16260_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_dev for the device
* @reg_address: the address of the lower of the two registers. Second register
* is assumed to have address one greater.
* @val: somewhere to pass back the value read
**/
-static int adis16260_spi_read_reg_16(struct device *dev,
+static int adis16260_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 adis16260_state *st = iio_dev_get_devdata(indio_dev);
int ret;
struct spi_transfer xfers[] = {
@@ -126,7 +122,6 @@ static int adis16260_spi_read_reg_16(struct device *dev,
.rx_buf = st->rx,
.bits_per_word = 8,
.len = 2,
- .cs_change = 1,
.delay_usecs = 30,
},
};
@@ -152,92 +147,6 @@ error_ret:
return ret;
}
-static ssize_t adis16260_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 = adis16260_spi_read_reg_16(dev, this_attr->address, (u16 *)&val);
- if (ret)
- return ret;
-
- if (val & ADIS16260_ERROR_ACTIVE)
- adis16260_check_status(dev);
- val = ((s16)(val << shift) >> shift);
- return sprintf(buf, "%d\n", val);
-}
-
-static ssize_t adis16260_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 = adis16260_spi_read_reg_16(dev, this_attr->address, &val);
- if (ret)
- return ret;
-
- if (val & ADIS16260_ERROR_ACTIVE)
- adis16260_check_status(dev);
-
- return sprintf(buf, "%u\n", val & 0x0FFF);
-}
-
-static ssize_t adis16260_read_12bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ssize_t ret;
-
- /* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
- ret = adis16260_spi_read_signed(dev, attr, buf, 12);
- mutex_unlock(&indio_dev->mlock);
-
- return ret;
-}
-
-static ssize_t adis16260_read_14bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ssize_t ret;
-
- /* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
- ret = adis16260_spi_read_signed(dev, attr, buf, 14);
- mutex_unlock(&indio_dev->mlock);
-
- return ret;
-}
-
-static ssize_t adis16260_write_16bit(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int ret;
- long val;
-
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- goto error_ret;
- ret = adis16260_spi_write_reg_16(dev, this_attr->address, val);
-
-error_ret:
- return ret ? ret : len;
-}
-
static ssize_t adis16260_read_frequency_available(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -259,7 +168,7 @@ static ssize_t adis16260_read_frequency(struct device *dev,
int ret, len = 0;
u16 t;
int sps;
- ret = adis16260_spi_read_reg_16(dev,
+ ret = adis16260_spi_read_reg_16(indio_dev,
ADIS16260_SMPL_PRD,
&t);
if (ret)
@@ -305,7 +214,7 @@ static ssize_t adis16260_write_frequency(struct device *dev,
st->us->max_speed_hz = ADIS16260_SPI_SLOW;
else
st->us->max_speed_hz = ADIS16260_SPI_FAST;
- ret = adis16260_spi_write_reg_8(dev,
+ ret = adis16260_spi_write_reg_8(indio_dev,
ADIS16260_SMPL_PRD,
t);
@@ -314,33 +223,14 @@ static ssize_t adis16260_write_frequency(struct device *dev,
return ret ? ret : len;
}
-static ssize_t adis16260_read_gyro_scale(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct adis16260_state *st = iio_dev_get_devdata(indio_dev);
- ssize_t ret = 0;
-
- if (st->negate)
- ret = sprintf(buf, "-");
- /* Take the iio_dev status lock */
- if (spi_get_device_id(st->us)->driver_data)
- ret += sprintf(buf + ret, "%s\n", "0.00031974432");
- else
- ret += sprintf(buf + ret, "%s\n", "0.00127862821");
-
- return ret;
-}
-
-static int adis16260_reset(struct device *dev)
+static int adis16260_reset(struct iio_dev *indio_dev)
{
int ret;
- ret = adis16260_spi_write_reg_8(dev,
+ ret = adis16260_spi_write_reg_8(indio_dev,
ADIS16260_GLOB_CMD,
ADIS16260_GLOB_CMD_SW_RESET);
if (ret)
- dev_err(dev, "problem resetting device");
+ dev_err(&indio_dev->dev, "problem resetting device");
return ret;
}
@@ -349,22 +239,23 @@ static ssize_t adis16260_write_reset(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
if (len < 1)
return -EINVAL;
switch (buf[0]) {
case '1':
case 'y':
case 'Y':
- return adis16260_reset(dev);
+ return adis16260_reset(indio_dev);
}
return -EINVAL;
}
-int adis16260_set_irq(struct device *dev, bool enable)
+int adis16260_set_irq(struct iio_dev *indio_dev, bool enable)
{
int ret;
u16 msc;
- ret = adis16260_spi_read_reg_16(dev, ADIS16260_MSC_CTRL, &msc);
+ ret = adis16260_spi_read_reg_16(indio_dev, ADIS16260_MSC_CTRL, &msc);
if (ret)
goto error_ret;
@@ -374,7 +265,7 @@ int adis16260_set_irq(struct device *dev, bool enable)
else
msc &= ~ADIS16260_MSC_CTRL_DATA_RDY_EN;
- ret = adis16260_spi_write_reg_16(dev, ADIS16260_MSC_CTRL, msc);
+ ret = adis16260_spi_write_reg_16(indio_dev, ADIS16260_MSC_CTRL, msc);
if (ret)
goto error_ret;
@@ -383,41 +274,44 @@ error_ret:
}
/* Power down the device */
-static int adis16260_stop_device(struct device *dev)
+static int adis16260_stop_device(struct iio_dev *indio_dev)
{
int ret;
u16 val = ADIS16260_SLP_CNT_POWER_OFF;
- ret = adis16260_spi_write_reg_16(dev, ADIS16260_SLP_CNT, val);
+ ret = adis16260_spi_write_reg_16(indio_dev, ADIS16260_SLP_CNT, val);
if (ret)
- dev_err(dev, "problem with turning device off: SLP_CNT");
+ dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");
return ret;
}
-static int adis16260_self_test(struct device *dev)
+static int adis16260_self_test(struct iio_dev *indio_dev)
{
int ret;
- ret = adis16260_spi_write_reg_16(dev,
+ ret = adis16260_spi_write_reg_16(indio_dev,
ADIS16260_MSC_CTRL,
ADIS16260_MSC_CTRL_MEM_TEST);
if (ret) {
- dev_err(dev, "problem starting self test");
+ dev_err(&indio_dev->dev, "problem starting self test");
goto err_ret;
}
- adis16260_check_status(dev);
+ adis16260_check_status(indio_dev);
err_ret:
return ret;
}
-static int adis16260_check_status(struct device *dev)
+static int adis16260_check_status(struct iio_dev *indio_dev)
{
u16 status;
int ret;
+ struct device *dev = &indio_dev->dev;
- ret = adis16260_spi_read_reg_16(dev, ADIS16260_DIAG_STAT, &status);
+ ret = adis16260_spi_read_reg_16(indio_dev,
+ ADIS16260_DIAG_STAT,
+ &status);
if (ret < 0) {
dev_err(dev, "Reading status failed\n");
@@ -443,130 +337,240 @@ error_ret:
return ret;
}
-static int adis16260_initial_setup(struct adis16260_state *st)
+static int adis16260_initial_setup(struct iio_dev *indio_dev)
{
int ret;
- struct device *dev = &st->indio_dev->dev;
+ struct device *dev = &indio_dev->dev;
/* Disable IRQ */
- ret = adis16260_set_irq(dev, false);
+ ret = adis16260_set_irq(indio_dev, false);
if (ret) {
dev_err(dev, "disable irq failed");
goto err_ret;
}
/* Do self test */
- ret = adis16260_self_test(dev);
+ ret = adis16260_self_test(indio_dev);
if (ret) {
dev_err(dev, "self test failure");
goto err_ret;
}
/* Read status register to check the result */
- ret = adis16260_check_status(dev);
+ ret = adis16260_check_status(indio_dev);
if (ret) {
- adis16260_reset(dev);
+ adis16260_reset(indio_dev);
dev_err(dev, "device not playing ball -> reset");
msleep(ADIS16260_STARTUP_DELAY);
- ret = adis16260_check_status(dev);
+ ret = adis16260_check_status(indio_dev);
if (ret) {
dev_err(dev, "giving up");
goto err_ret;
}
}
- printk(KERN_INFO DRIVER_NAME ": at CS%d (irq %d)\n",
- st->us->chip_select, st->us->irq);
-
err_ret:
return ret;
}
-static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply,
- adis16260_read_12bit_unsigned,
- ADIS16260_SUPPLY_OUT);
-static IIO_CONST_ATTR_IN_NAMED_SCALE(0, supply, "0.0018315");
-
-static IIO_DEV_ATTR_TEMP_RAW(adis16260_read_12bit_unsigned);
-static IIO_CONST_ATTR_TEMP_OFFSET("25");
-static IIO_CONST_ATTR_TEMP_SCALE("0.1453");
-
-static IIO_DEV_ATTR_IN_RAW(1, adis16260_read_12bit_unsigned,
- ADIS16260_AUX_ADC);
-static IIO_CONST_ATTR(in1_scale, "0.0006105");
-
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
adis16260_read_frequency,
adis16260_write_frequency);
static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16260_write_reset, 0);
-
static IIO_DEVICE_ATTR(sampling_frequency_available,
S_IRUGO, adis16260_read_frequency_available, NULL, 0);
-static IIO_CONST_ATTR_NAME("adis16260");
+enum adis16260_channel {
+ gyro,
+ temp,
+ in_supply,
+ in_aux,
+ angle,
+};
+#define ADIS16260_GYRO_CHANNEL_SET(axis, mod) \
+ struct iio_chan_spec adis16260_channels_##axis[] = { \
+ IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, mod, \
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | \
+ (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | \
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \
+ gyro, ADIS16260_SCAN_GYRO, \
+ IIO_ST('s', 14, 16, 0), 0), \
+ IIO_CHAN(IIO_ANGL, 1, 0, 0, NULL, 0, mod, \
+ 0, \
+ angle, ADIS16260_SCAN_ANGL, \
+ IIO_ST('u', 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), \
+ temp, ADIS16260_SCAN_TEMP, \
+ IIO_ST('u', 12, 16, 0), 0), \
+ IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0, \
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \
+ in_supply, ADIS16260_SCAN_SUPPLY, \
+ IIO_ST('u', 12, 16, 0), 0), \
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, \
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \
+ in_aux, ADIS16260_SCAN_AUX_ADC, \
+ IIO_ST('u', 12, 16, 0), 0), \
+ IIO_CHAN_SOFT_TIMESTAMP(5) \
+ }
-static struct attribute *adis16260_event_attributes[] = {
- NULL
+static const ADIS16260_GYRO_CHANNEL_SET(x, IIO_MOD_X);
+static const ADIS16260_GYRO_CHANNEL_SET(y, IIO_MOD_Y);
+static const ADIS16260_GYRO_CHANNEL_SET(z, IIO_MOD_Z);
+
+static const u8 adis16260_addresses[5][3] = {
+ [gyro] = { ADIS16260_GYRO_OUT,
+ ADIS16260_GYRO_OFF,
+ ADIS16260_GYRO_SCALE },
+ [angle] = { ADIS16260_ANGL_OUT },
+ [in_supply] = { ADIS16260_SUPPLY_OUT },
+ [in_aux] = { ADIS16260_AUX_ADC },
+ [temp] = { ADIS16260_TEMP_OUT },
};
+static int adis16260_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2,
+ long mask)
+{
+ struct adis16260_state *st = iio_dev_get_devdata(indio_dev);
+ int ret;
+ int bits;
+ u8 addr;
+ s16 val16;
+
+ switch (mask) {
+ case 0:
+ mutex_lock(&indio_dev->mlock);
+ addr = adis16260_addresses[chan->address][0];
+ ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16);
+ if (ret)
+ return ret;
-static struct attribute_group adis16260_event_attribute_group = {
- .attrs = adis16260_event_attributes,
+ if (val16 & ADIS16260_ERROR_ACTIVE) {
+ ret = adis16260_check_status(indio_dev);
+ if (ret)
+ return ret;
+ }
+ val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
+ if (chan->scan_type.sign == 's')
+ val16 = (s16)(val16 <<
+ (16 - chan->scan_type.realbits)) >>
+ (16 - chan->scan_type.realbits);
+ *val = val16;
+ mutex_unlock(&indio_dev->mlock);
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ switch (chan->type) {
+ case IIO_GYRO:
+ *val = 0;
+ if (spi_get_device_id(st->us)->driver_data)
+ *val2 = 320;
+ else
+ *val2 = 1278;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_IN:
+ *val = 0;
+ if (chan->channel == 0)
+ *val2 = 18315;
+ else
+ *val2 = 610500;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_TEMP:
+ *val = 0;
+ *val2 = 145300;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ *val = 25;
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ switch (chan->type) {
+ case IIO_GYRO:
+ bits = 12;
+ break;
+ default:
+ return -EINVAL;
+ };
+ mutex_lock(&indio_dev->mlock);
+ addr = adis16260_addresses[chan->address][1];
+ ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16);
+ if (ret) {
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+ }
+ val16 &= (1 << bits) - 1;
+ val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
+ *val = val16;
+ mutex_unlock(&indio_dev->mlock);
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ switch (chan->type) {
+ case IIO_GYRO:
+ bits = 12;
+ break;
+ default:
+ return -EINVAL;
+ };
+ mutex_lock(&indio_dev->mlock);
+ addr = adis16260_addresses[chan->address][2];
+ ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16);
+ if (ret) {
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+ }
+ *val = (1 << bits) - 1;
+ mutex_unlock(&indio_dev->mlock);
+ return IIO_VAL_INT;
+ }
+ return -EINVAL;
+}
+
+static int adis16260_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
+{
+ int bits = 12;
+ s16 val16;
+ u8 addr;
+ switch (mask) {
+ case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ val16 = val & ((1 << bits) - 1);
+ addr = adis16260_addresses[chan->address][1];
+ return adis16260_spi_write_reg_16(indio_dev, addr, val16);
+ case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ val16 = val & ((1 << bits) - 1);
+ addr = adis16260_addresses[chan->address][2];
+ return adis16260_spi_write_reg_16(indio_dev, addr, val16);
+ }
+ return -EINVAL;
+}
+
+static struct attribute *adis16260_attributes[] = {
+ &iio_dev_attr_sampling_frequency.dev_attr.attr,
+ &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+ &iio_dev_attr_reset.dev_attr.attr,
+ NULL
};
-#define ADIS16260_GYRO_ATTR_SET(axis) \
- IIO_DEV_ATTR_GYRO##axis(adis16260_read_14bit_signed, \
- ADIS16260_GYRO_OUT); \
- static IIO_DEV_ATTR_GYRO##axis##_SCALE(S_IRUGO, \
- adis16260_read_gyro_scale, \
- NULL, \
- 0); \
- static IIO_DEV_ATTR_GYRO##axis##_CALIBSCALE(S_IRUGO | S_IWUSR, \
- adis16260_read_12bit_unsigned, \
- adis16260_write_16bit, \
- ADIS16260_GYRO_SCALE); \
- static IIO_DEV_ATTR_GYRO##axis##_CALIBBIAS(S_IWUSR | S_IRUGO, \
- adis16260_read_12bit_signed, \
- adis16260_write_16bit, \
- ADIS16260_GYRO_OFF); \
- static IIO_DEV_ATTR_ANGL##axis(adis16260_read_14bit_signed, \
- ADIS16260_ANGL_OUT);
-
-static ADIS16260_GYRO_ATTR_SET();
-static ADIS16260_GYRO_ATTR_SET(_X);
-static ADIS16260_GYRO_ATTR_SET(_Y);
-static ADIS16260_GYRO_ATTR_SET(_Z);
-
-#define ADIS16260_ATTR_GROUP(axis) \
- struct attribute *adis16260_attributes##axis[] = { \
- &iio_dev_attr_in0_supply_raw.dev_attr.attr, \
- &iio_const_attr_in0_supply_scale.dev_attr.attr, \
- &iio_dev_attr_gyro##axis##_raw.dev_attr.attr, \
- &iio_dev_attr_gyro##axis##_scale.dev_attr.attr, \
- &iio_dev_attr_gyro##axis##_calibscale.dev_attr.attr, \
- &iio_dev_attr_gyro##axis##_calibbias.dev_attr.attr, \
- &iio_dev_attr_angl##axis##_raw.dev_attr.attr, \
- &iio_dev_attr_temp_raw.dev_attr.attr, \
- &iio_const_attr_temp_offset.dev_attr.attr, \
- &iio_const_attr_temp_scale.dev_attr.attr, \
- &iio_dev_attr_in1_raw.dev_attr.attr, \
- &iio_const_attr_in1_scale.dev_attr.attr, \
- &iio_dev_attr_sampling_frequency.dev_attr.attr, \
- &iio_dev_attr_sampling_frequency_available.dev_attr.attr, \
- &iio_dev_attr_reset.dev_attr.attr, \
- &iio_const_attr_name.dev_attr.attr, \
- NULL \
- }; \
- static const struct attribute_group adis16260_attribute_group##axis \
- = { \
- .attrs = adis16260_attributes##axis, \
- };
+static const struct attribute_group adis16260_attribute_group = {
+ .attrs = adis16260_attributes,
+};
-static ADIS16260_ATTR_GROUP();
-static ADIS16260_ATTR_GROUP(_x);
-static ADIS16260_ATTR_GROUP(_y);
-static ADIS16260_ATTR_GROUP(_z);
+static const struct iio_info adis16260_info = {
+ .attrs = &adis16260_attribute_group,
+ .read_raw = &adis16260_read_raw,
+ .write_raw = &adis16260_write_raw,
+ .driver_module = THIS_MODULE,
+};
static int __devinit adis16260_probe(struct spi_device *spi)
{
@@ -596,35 +600,35 @@ static int __devinit adis16260_probe(struct spi_device *spi)
st->us = spi;
mutex_init(&st->buf_lock);
/* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_tx;
}
+ st->indio_dev->name = spi_get_device_id(st->us)->name;
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->num_interrupt_lines = 1;
- st->indio_dev->event_attrs = &adis16260_event_attribute_group;
+ st->indio_dev->info = &adis16260_info;
+ st->indio_dev->num_channels
+ = ARRAY_SIZE(adis16260_channels_x);
if (pd && pd->direction)
switch (pd->direction) {
case 'x':
- st->indio_dev->attrs = &adis16260_attribute_group_x;
+ st->indio_dev->channels = adis16260_channels_x;
break;
case 'y':
- st->indio_dev->attrs = &adis16260_attribute_group_y;
+ st->indio_dev->channels = adis16260_channels_y;
break;
case 'z':
- st->indio_dev->attrs = &adis16260_attribute_group_z;
+ st->indio_dev->channels = adis16260_channels_z;
break;
default:
- st->indio_dev->attrs = &adis16260_attribute_group;
- break;
+ return -EINVAL;
}
else
- st->indio_dev->attrs = &adis16260_attribute_group;
+ st->indio_dev->channels = adis16260_channels_x;
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
ret = adis16260_configure_ring(st->indio_dev);
@@ -635,37 +639,28 @@ static int __devinit adis16260_probe(struct spi_device *spi)
if (ret)
goto error_unreg_ring_funcs;
regdone = 1;
- ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
+ ret = iio_ring_buffer_register_ex(st->indio_dev->ring, 0,
+ st->indio_dev->channels,
+ ARRAY_SIZE(adis16260_channels_x));
if (ret) {
printk(KERN_ERR "failed to initialize the ring\n");
goto error_unreg_ring_funcs;
}
if (spi->irq) {
- ret = iio_register_interrupt_line(spi->irq,
- st->indio_dev,
- 0,
- IRQF_TRIGGER_RISING,
- "adis16260");
- if (ret)
- goto error_uninitialize_ring;
-
ret = adis16260_probe_trigger(st->indio_dev);
if (ret)
- goto error_unregister_line;
+ goto error_uninitialize_ring;
}
/* Get the device into a sane initial state */
- ret = adis16260_initial_setup(st);
+ ret = adis16260_initial_setup(st->indio_dev);
if (ret)
goto error_remove_trigger;
return 0;
error_remove_trigger:
adis16260_remove_trigger(st->indio_dev);
-error_unregister_line:
- if (spi->irq)
- iio_unregister_interrupt_line(st->indio_dev, 0);
error_uninitialize_ring:
iio_ring_buffer_unregister(st->indio_dev->ring);
error_unreg_ring_funcs:
@@ -691,15 +686,13 @@ static int adis16260_remove(struct spi_device *spi)
struct adis16260_state *st = spi_get_drvdata(spi);
struct iio_dev *indio_dev = st->indio_dev;
- ret = adis16260_stop_device(&(indio_dev->dev));
+ ret = adis16260_stop_device(indio_dev);
if (ret)
goto err_ret;
flush_scheduled_work();
adis16260_remove_trigger(indio_dev);
- if (spi->irq)
- iio_unregister_interrupt_line(indio_dev, 0);
iio_ring_buffer_unregister(st->indio_dev->ring);
iio_device_unregister(indio_dev);
diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c
index 23428894b1ee..a0925044eaa5 100644
--- a/drivers/staging/iio/gyro/adis16260_ring.c
+++ b/drivers/staging/iio/gyro/adis16260_ring.c
@@ -17,57 +17,6 @@
#include "../trigger.h"
#include "adis16260.h"
-static IIO_SCAN_EL_C(in_supply, ADIS16260_SCAN_SUPPLY,
- ADIS16260_SUPPLY_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in_supply, u, 12, 16);
-static IIO_SCAN_EL_C(gyro, ADIS16260_SCAN_GYRO, ADIS16260_GYRO_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(gyro, s, 14, 16);
-static IIO_SCAN_EL_C(in0, ADIS16260_SCAN_AUX_ADC, ADIS16260_AUX_ADC, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in0, u, 12, 16);
-static IIO_SCAN_EL_C(temp, ADIS16260_SCAN_TEMP, ADIS16260_TEMP_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(temp, u, 12, 16);
-static IIO_SCAN_EL_C(angl, ADIS16260_SCAN_ANGL, ADIS16260_ANGL_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(angl, u, 14, 16);
-static IIO_SCAN_EL_TIMESTAMP(5);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
-
-static struct attribute *adis16260_scan_el_attrs[] = {
- &iio_scan_el_in_supply.dev_attr.attr,
- &iio_const_attr_in_supply_index.dev_attr.attr,
- &iio_const_attr_in_supply_type.dev_attr.attr,
- &iio_scan_el_gyro.dev_attr.attr,
- &iio_const_attr_gyro_index.dev_attr.attr,
- &iio_const_attr_gyro_type.dev_attr.attr,
- &iio_scan_el_in0.dev_attr.attr,
- &iio_const_attr_in0_index.dev_attr.attr,
- &iio_const_attr_in0_type.dev_attr.attr,
- &iio_scan_el_temp.dev_attr.attr,
- &iio_const_attr_temp_index.dev_attr.attr,
- &iio_const_attr_temp_type.dev_attr.attr,
- &iio_scan_el_angl.dev_attr.attr,
- &iio_const_attr_angl_index.dev_attr.attr,
- &iio_const_attr_angl_type.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group adis16260_scan_el_group = {
- .attrs = adis16260_scan_el_attrs,
- .name = "scan_elements",
-};
-
-/**
- * adis16260_poll_func_th() top half interrupt handler called by trigger
- * @private_data: iio_dev
- **/
-static void adis16260_poll_func_th(struct iio_dev *indio_dev, s64 time)
-{
- struct adis16260_state *st = iio_dev_get_devdata(indio_dev);
- st->last_timestamp = time;
- schedule_work(&st->work_trigger_to_ring);
-}
/**
* adis16260_read_ring_data() read data registers which will be placed into ring
@@ -117,56 +66,55 @@ static int adis16260_read_ring_data(struct device *dev, u8 *rx)
return ret;
}
-
-static void adis16260_trigger_bh_to_ring(struct work_struct *work_s)
+static irqreturn_t adis16260_trigger_handler(int irq, void *p)
{
- struct adis16260_state *st
- = container_of(work_s, struct adis16260_state,
- work_trigger_to_ring);
- struct iio_ring_buffer *ring = st->indio_dev->ring;
-
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->private_data;
+ struct adis16260_state *st = iio_dev_get_devdata(indio_dev);
+ struct iio_ring_buffer *ring = indio_dev->ring;
int i = 0;
s16 *data;
- size_t datasize = ring->access.get_bytes_per_datum(ring);
+ size_t datasize = ring->access->get_bytes_per_datum(ring);
data = kmalloc(datasize , GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
- return;
+ return -ENOMEM;
}
- if (ring->scan_count)
- if (adis16260_read_ring_data(&st->indio_dev->dev, st->rx) >= 0)
- for (; i < ring->scan_count; i++)
- data[i] = be16_to_cpup(
- (__be16 *)&(st->rx[i*2]));
+ if (ring->scan_count &&
+ adis16260_read_ring_data(&st->indio_dev->dev, st->rx) >= 0)
+ for (; i < ring->scan_count; i++)
+ data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
if (ring->scan_timestamp)
- *((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
+ *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
- ring->access.store_to(ring,
- (u8 *)data,
- st->last_timestamp);
+ ring->access->store_to(ring, (u8 *)data, pf->timestamp);
iio_trigger_notify_done(st->indio_dev->trig);
kfree(data);
- return;
+ return IRQ_HANDLED;
}
void adis16260_unconfigure_ring(struct iio_dev *indio_dev)
{
- kfree(indio_dev->pollfunc);
+ iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
+static const struct iio_ring_setup_ops adis16260_ring_setup_ops = {
+ .preenable = &iio_sw_ring_preenable,
+ .postenable = &iio_triggered_ring_postenable,
+ .predisable = &iio_triggered_ring_predisable,
+};
+
int adis16260_configure_ring(struct iio_dev *indio_dev)
{
int ret = 0;
- struct adis16260_state *st = indio_dev->dev_data;
struct iio_ring_buffer *ring;
- INIT_WORK(&st->work_trigger_to_ring, adis16260_trigger_bh_to_ring);
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
@@ -175,25 +123,29 @@ int adis16260_configure_ring(struct iio_dev *indio_dev)
}
indio_dev->ring = ring;
/* Effectively select the ring buffer implementation */
- iio_ring_sw_register_funcs(&ring->access);
+ ring->access = &ring_sw_access_funcs;
ring->bpe = 2;
- ring->scan_el_attrs = &adis16260_scan_el_group;
ring->scan_timestamp = true;
- ring->preenable = &iio_sw_ring_preenable;
- ring->postenable = &iio_triggered_ring_postenable;
- ring->predisable = &iio_triggered_ring_predisable;
+ ring->setup_ops = &adis16260_ring_setup_ops;
ring->owner = THIS_MODULE;
/* Set default scan mode */
- iio_scan_mask_set(ring, iio_scan_el_in_supply.number);
- iio_scan_mask_set(ring, iio_scan_el_gyro.number);
- iio_scan_mask_set(ring, iio_scan_el_in0.number);
- iio_scan_mask_set(ring, iio_scan_el_temp.number);
- iio_scan_mask_set(ring, iio_scan_el_angl.number);
-
- ret = iio_alloc_pollfunc(indio_dev, NULL, &adis16260_poll_func_th);
- if (ret)
+ iio_scan_mask_set(ring, ADIS16260_SCAN_SUPPLY);
+ iio_scan_mask_set(ring, ADIS16260_SCAN_GYRO);
+ iio_scan_mask_set(ring, ADIS16260_SCAN_AUX_ADC);
+ iio_scan_mask_set(ring, ADIS16260_SCAN_TEMP);
+ iio_scan_mask_set(ring, ADIS16260_SCAN_ANGL);
+
+ indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
+ &adis16260_trigger_handler,
+ IRQF_ONESHOT,
+ indio_dev,
+ "adis16260_consumer%d",
+ indio_dev->id);
+ if (indio_dev->pollfunc == NULL) {
+ ret = -ENOMEM;
goto error_iio_sw_rb_free;
+ }
indio_dev->modes |= INDIO_RING_TRIGGERED;
return 0;
diff --git a/drivers/staging/iio/gyro/adis16260_trigger.c b/drivers/staging/iio/gyro/adis16260_trigger.c
index 4a744c11ca6c..4f10fb543356 100644
--- a/drivers/staging/iio/gyro/adis16260_trigger.c
+++ b/drivers/staging/iio/gyro/adis16260_trigger.c
@@ -13,35 +13,6 @@
#include "adis16260.h"
/**
- * adis16260_data_rdy_trig_poll() the event handler for the data rdy trig
- **/
-static int adis16260_data_rdy_trig_poll(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct adis16260_state *st = iio_dev_get_devdata(dev_info);
- struct iio_trigger *trig = st->trig;
-
- iio_trigger_poll(trig, timestamp);
-
- return IRQ_HANDLED;
-}
-
-IIO_EVENT_SH(data_rdy_trig, &adis16260_data_rdy_trig_poll);
-
-static IIO_TRIGGER_NAME_ATTR;
-
-static struct attribute *adis16260_trigger_attrs[] = {
- &dev_attr_name.attr,
- NULL,
-};
-
-static const struct attribute_group adis16260_trigger_attr_group = {
- .attrs = adis16260_trigger_attrs,
-};
-
-/**
* adis16260_data_rdy_trigger_set_state() set datardy interrupt state
**/
static int adis16260_data_rdy_trigger_set_state(struct iio_trigger *trig,
@@ -49,31 +20,9 @@ static int adis16260_data_rdy_trigger_set_state(struct iio_trigger *trig,
{
struct adis16260_state *st = trig->private_data;
struct iio_dev *indio_dev = st->indio_dev;
- int ret = 0;
dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
- ret = adis16260_set_irq(&st->indio_dev->dev, state);
- if (state == false) {
- iio_remove_event_from_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]
- ->ev_list);
- flush_scheduled_work();
- } else {
- iio_add_event_to_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]->ev_list);
- }
- return ret;
-}
-
-/**
- * adis16260_trig_try_reen() try renabling irq for data rdy trigger
- * @trig: the datardy trigger
- **/
-static int adis16260_trig_try_reen(struct iio_trigger *trig)
-{
- struct adis16260_state *st = trig->private_data;
- enable_irq(st->us->irq);
- return 0;
+ return adis16260_set_irq(indio_dev, state);
}
int adis16260_probe_trigger(struct iio_dev *indio_dev)
@@ -81,34 +30,40 @@ int adis16260_probe_trigger(struct iio_dev *indio_dev)
int ret;
struct adis16260_state *st = indio_dev->dev_data;
- st->trig = iio_allocate_trigger();
- st->trig->name = kasprintf(GFP_KERNEL,
- "adis16260-dev%d",
- indio_dev->id);
- if (!st->trig->name) {
+ st->trig = iio_allocate_trigger("%s-dev%d",
+ spi_get_device_id(st->us)->name,
+ indio_dev->id);
+ if (st->trig == NULL) {
ret = -ENOMEM;
- goto error_free_trig;
+ goto error_ret;
}
+
+ ret = request_irq(st->us->irq,
+ &iio_trigger_generic_data_rdy_poll,
+ IRQF_TRIGGER_RISING,
+ "adis16260",
+ st->trig);
+ if (ret)
+ goto error_free_trig;
+
st->trig->dev.parent = &st->us->dev;
st->trig->owner = THIS_MODULE;
st->trig->private_data = st;
st->trig->set_trigger_state = &adis16260_data_rdy_trigger_set_state;
- st->trig->try_reenable = &adis16260_trig_try_reen;
- st->trig->control_attrs = &adis16260_trigger_attr_group;
ret = iio_trigger_register(st->trig);
/* select default trigger */
indio_dev->trig = st->trig;
if (ret)
- goto error_free_trig_name;
+ goto error_free_irq;
return 0;
-error_free_trig_name:
- kfree(st->trig->name);
+error_free_irq:
+ free_irq(st->us->irq, st->trig);
error_free_trig:
iio_free_trigger(st->trig);
-
+error_ret:
return ret;
}
@@ -117,6 +72,6 @@ void adis16260_remove_trigger(struct iio_dev *indio_dev)
struct adis16260_state *state = indio_dev->dev_data;
iio_trigger_unregister(state->trig);
- kfree(state->trig->name);
+ free_irq(state->us->irq, state->trig);
iio_free_trigger(state->trig);
}
diff --git a/drivers/staging/iio/gyro/adxrs450.h b/drivers/staging/iio/gyro/adxrs450.h
new file mode 100644
index 000000000000..c92f6945f00f
--- /dev/null
+++ b/drivers/staging/iio/gyro/adxrs450.h
@@ -0,0 +1,58 @@
+#ifndef SPI_ADXRS450_H_
+#define SPI_ADXRS450_H_
+
+#define ADXRS450_STARTUP_DELAY 50 /* ms */
+
+/* The MSB for the spi commands */
+#define ADXRS450_SENSOR_DATA 0x20
+#define ADXRS450_WRITE_DATA 0x40
+#define ADXRS450_READ_DATA 0x80
+
+#define ADXRS450_RATE1 0x00 /* Rate Registers */
+#define ADXRS450_TEMP1 0x02 /* Temperature Registers */
+#define ADXRS450_LOCST1 0x04 /* Low CST Memory Registers */
+#define ADXRS450_HICST1 0x06 /* High CST Memory Registers */
+#define ADXRS450_QUAD1 0x08 /* Quad Memory Registers */
+#define ADXRS450_FAULT1 0x0A /* Fault Registers */
+#define ADXRS450_PID1 0x0C /* Part ID Register 1 */
+#define ADXRS450_SNH 0x0E /* Serial Number Registers, 4 bytes */
+#define ADXRS450_SNL 0x10
+#define ADXRS450_DNC1 0x12 /* Dynamic Null Correction Registers */
+/* Check bits */
+#define ADXRS450_P 0x01
+#define ADXRS450_CHK 0x02
+#define ADXRS450_CST 0x04
+#define ADXRS450_PWR 0x08
+#define ADXRS450_POR 0x10
+#define ADXRS450_NVM 0x20
+#define ADXRS450_Q 0x40
+#define ADXRS450_PLL 0x80
+#define ADXRS450_UV 0x100
+#define ADXRS450_OV 0x200
+#define ADXRS450_AMP 0x400
+#define ADXRS450_FAIL 0x800
+
+#define ADXRS450_WRERR_MASK (0x7 << 29)
+
+#define ADXRS450_MAX_RX 4
+#define ADXRS450_MAX_TX 4
+
+#define ADXRS450_GET_ST(a) ((a >> 26) & 0x3)
+
+/**
+ * struct adxrs450_state - device instance specific data
+ * @us: actual spi_device
+ * @indio_dev: industrial I/O device structure
+ * @tx: transmit buffer
+ * @rx: recieve buffer
+ * @buf_lock: mutex to protect tx and rx
+ **/
+struct adxrs450_state {
+ struct spi_device *us;
+ struct iio_dev *indio_dev;
+ u8 *tx;
+ u8 *rx;
+ struct mutex buf_lock;
+};
+
+#endif /* SPI_ADXRS450_H_ */
diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c
new file mode 100644
index 000000000000..3714e4aadc23
--- /dev/null
+++ b/drivers/staging/iio/gyro/adxrs450_core.c
@@ -0,0 +1,455 @@
+/*
+ * ADXRS450 Digital Output Gyroscope Driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/list.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "gyro.h"
+#include "../adc/adc.h"
+
+#include "adxrs450.h"
+
+/**
+ * adxrs450_spi_read_reg_16() - read 2 bytes from a register pair
+ * @dev: device associated with child of actual iio_dev
+ * @reg_address: the address of the lower of the two registers,which should be an even address,
+ * 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)
+{
+ struct spi_message msg;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct adxrs450_state *st = iio_dev_get_devdata(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);
+ st->tx[1] = reg_address << 1;
+ st->tx[2] = 0;
+ st->tx[3] = 0;
+
+ 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);
+ if (ret) {
+ dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n",
+ reg_address);
+ goto error_ret;
+ }
+
+ *val = (be32_to_cpu(*(u32 *)st->rx) >> 5) & 0xFFFF;
+
+error_ret:
+ mutex_unlock(&st->buf_lock);
+ return ret;
+}
+
+/**
+ * adxrs450_spi_write_reg_16() - write 2 bytes data to a register pair
+ * @dev: device associated with child of actual actual iio_dev
+ * @reg_address: the address of the lower of the two registers,which should be an even address,
+ * 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)
+{
+ struct spi_message msg;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct adxrs450_state *st = iio_dev_get_devdata(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;
+ st->tx[1] = reg_address << 1 | val >> 15;
+ st->tx[2] = val >> 7;
+ st->tx[3] = val << 1;
+
+ if (!(hweight32(be32_to_cpu(*(u32 *)st->tx)) & 1))
+ st->tx[3] |= ADXRS450_P;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfers, &msg);
+ ret = spi_sync(st->us, &msg);
+ if (ret)
+ dev_err(&st->us->dev, "problem while writing 16 bit register 0x%02x\n",
+ reg_address);
+ msleep(1); /* enforce sequential transfer delay 0.1ms */
+ mutex_unlock(&st->buf_lock);
+ return ret;
+}
+
+/**
+ * adxrs450_spi_sensor_data() - read 2 bytes sensor data
+ * @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)
+{
+ struct spi_message msg;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct adxrs450_state *st = iio_dev_get_devdata(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;
+ st->tx[1] = 0;
+ st->tx[2] = 0;
+ st->tx[3] = 0;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfers[0], &msg);
+ spi_message_add_tail(&xfers[1], &msg);
+ ret = spi_sync(st->us, &msg);
+ if (ret) {
+ dev_err(&st->us->dev, "Problem while reading sensor data\n");
+ goto error_ret;
+ }
+
+ *val = (be32_to_cpu(*(u32 *)st->rx) >> 10) & 0xFFFF;
+
+error_ret:
+ mutex_unlock(&st->buf_lock);
+ return ret;
+}
+
+/**
+ * adxrs450_spi_initial() - use for initializing procedure.
+ * @st: device instance specific data
+ * @val: somewhere to pass back the value read
+ **/
+static int adxrs450_spi_initial(struct adxrs450_state *st,
+ u32 *val, char chk)
+{
+ struct spi_message msg;
+ 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_SENSOR_DATA;
+ st->tx[1] = 0;
+ st->tx[2] = 0;
+ st->tx[3] = 0;
+ if (chk)
+ st->tx[3] |= (ADXRS450_CHK | ADXRS450_P);
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfers, &msg);
+ ret = spi_sync(st->us, &msg);
+ if (ret) {
+ dev_err(&st->us->dev, "Problem while reading initializing data\n");
+ goto error_ret;
+ }
+
+ *val = be32_to_cpu(*(u32 *)st->rx);
+
+error_ret:
+ mutex_unlock(&st->buf_lock);
+ 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 adxrs450_state *st)
+{
+ u32 t;
+ u16 data;
+ int ret;
+ struct device *dev = &st->indio_dev->dev;
+
+ msleep(ADXRS450_STARTUP_DELAY*2);
+ ret = adxrs450_spi_initial(st, &t, 1);
+ if (ret)
+ return ret;
+ if (t != 0x01)
+ dev_warn(&st->us->dev, "The initial power on response "
+ "is not correct! Restart without reset?\n");
+
+ msleep(ADXRS450_STARTUP_DELAY);
+ ret = adxrs450_spi_initial(st, &t, 0);
+ if (ret)
+ return ret;
+
+ msleep(ADXRS450_STARTUP_DELAY);
+ ret = adxrs450_spi_initial(st, &t, 0);
+ if (ret)
+ return ret;
+ if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) {
+ dev_err(&st->us->dev, "The second response is not correct!\n");
+ return -EIO;
+
+ }
+ ret = adxrs450_spi_initial(st, &t, 0);
+ if (ret)
+ return ret;
+ if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) {
+ dev_err(&st->us->dev, "The third response is not correct!\n");
+ return -EIO;
+
+ }
+ ret = adxrs450_spi_read_reg_16(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);
+ 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);
+ if (ret)
+ return ret;
+ t = data;
+ ret = adxrs450_spi_read_reg_16(dev, ADXRS450_SNH, &data);
+ if (ret)
+ return ret;
+ t |= data << 16;
+ dev_info(&st->us->dev, "The Serial Number is 0x%x\n", t);
+
+ 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 const struct attribute_group adxrs450_attribute_group = {
+ .attrs = adxrs450_attributes,
+};
+
+static const struct iio_info adxrs450_info = {
+ .attrs = &adxrs450_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
+static int __devinit adxrs450_probe(struct spi_device *spi)
+{
+ int ret, regdone = 0;
+ struct adxrs450_state *st = kzalloc(sizeof *st, GFP_KERNEL);
+ if (!st) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+ /* This is only used for removal purposes */
+ spi_set_drvdata(spi, st);
+
+ /* Allocate the comms buffers */
+ st->rx = kzalloc(sizeof(*st->rx)*ADXRS450_MAX_RX, GFP_KERNEL);
+ if (st->rx == NULL) {
+ ret = -ENOMEM;
+ goto error_free_st;
+ }
+ st->tx = kzalloc(sizeof(*st->tx)*ADXRS450_MAX_TX, GFP_KERNEL);
+ if (st->tx == NULL) {
+ ret = -ENOMEM;
+ goto error_free_rx;
+ }
+ st->us = spi;
+ mutex_init(&st->buf_lock);
+ /* setup the industrialio driver allocated elements */
+ st->indio_dev = iio_allocate_device(0);
+ if (st->indio_dev == NULL) {
+ ret = -ENOMEM;
+ goto error_free_tx;
+ }
+
+ st->indio_dev->dev.parent = &spi->dev;
+ st->indio_dev->info = &adxrs450_info;
+ st->indio_dev->dev_data = (void *)(st);
+ st->indio_dev->modes = INDIO_DIRECT_MODE;
+
+ ret = iio_device_register(st->indio_dev);
+ if (ret)
+ goto error_free_dev;
+ regdone = 1;
+
+ /* Get the device into a sane initial state */
+ ret = adxrs450_initial_setup(st);
+ if (ret)
+ goto error_initial;
+ return 0;
+
+error_initial:
+error_free_dev:
+ if (regdone)
+ iio_device_unregister(st->indio_dev);
+ else
+ iio_free_device(st->indio_dev);
+error_free_tx:
+ kfree(st->tx);
+error_free_rx:
+ kfree(st->rx);
+error_free_st:
+ kfree(st);
+error_ret:
+ return ret;
+}
+
+static int adxrs450_remove(struct spi_device *spi)
+{
+ struct adxrs450_state *st = spi_get_drvdata(spi);
+
+ iio_device_unregister(st->indio_dev);
+ kfree(st->tx);
+ kfree(st->rx);
+ kfree(st);
+
+ return 0;
+}
+
+static struct spi_driver adxrs450_driver = {
+ .driver = {
+ .name = "adxrs450",
+ .owner = THIS_MODULE,
+ },
+ .probe = adxrs450_probe,
+ .remove = __devexit_p(adxrs450_remove),
+};
+
+static __init int adxrs450_init(void)
+{
+ return spi_register_driver(&adxrs450_driver);
+}
+module_init(adxrs450_init);
+
+static __exit void adxrs450_exit(void)
+{
+ spi_unregister_driver(&adxrs450_driver);
+}
+module_exit(adxrs450_exit);
+
+MODULE_AUTHOR("Cliff Cai <cliff.cai@xxxxxxxxxx>");
+MODULE_DESCRIPTION("Analog Devices ADXRS450 Gyroscope SPI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/gyro/gyro.h b/drivers/staging/iio/gyro/gyro.h
index b4ea5bf161ff..b5495613407b 100644
--- a/drivers/staging/iio/gyro/gyro.h
+++ b/drivers/staging/iio/gyro/gyro.h
@@ -57,6 +57,9 @@
#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)
diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h
index 7127f26f8d26..38f1425f4645 100644
--- a/drivers/staging/iio/iio.h
+++ b/drivers/staging/iio/iio.h
@@ -12,6 +12,7 @@
#include <linux/device.h>
#include <linux/cdev.h>
+#include <linux/irq.h>
#include "sysfs.h"
#include "chrdev.h"
@@ -24,9 +25,158 @@
/* Event interface flags */
#define IIO_BUSY_BIT_POS 1
-struct iio_dev;
+/* naughty temporary hack to match these against the event version
+ - need to flattern these together */
+enum iio_chan_type {
+ /* real channel types */
+ IIO_IN,
+ IIO_CURRENT,
+ IIO_POWER,
+ IIO_ACCEL,
+ IIO_IN_DIFF,
+ IIO_GYRO,
+ IIO_MAGN,
+ IIO_LIGHT,
+ IIO_INTENSITY,
+ IIO_PROXIMITY,
+ IIO_TEMP,
+ IIO_INCLI,
+ IIO_ROT,
+ IIO_ANGL,
+ IIO_TIMESTAMP,
+};
+
+#define IIO_MOD_X 0
+#define IIO_MOD_LIGHT_BOTH 0
+#define IIO_MOD_Y 1
+#define IIO_MOD_LIGHT_IR 1
+#define IIO_MOD_Z 2
+#define IIO_MOD_X_AND_Y 3
+#define IIO_MOD_X_ANX_Z 4
+#define IIO_MOD_Y_AND_Z 5
+#define IIO_MOD_X_AND_Y_AND_Z 6
+#define IIO_MOD_X_OR_Y 7
+#define IIO_MOD_X_OR_Z 8
+#define IIO_MOD_Y_OR_Z 9
+#define IIO_MOD_X_OR_Y_OR_Z 10
+
+/* Could add the raw attributes as well - allowing buffer only devices */
+enum iio_chan_info_enum {
+ IIO_CHAN_INFO_SCALE_SHARED,
+ IIO_CHAN_INFO_SCALE_SEPARATE,
+ IIO_CHAN_INFO_OFFSET_SHARED,
+ IIO_CHAN_INFO_OFFSET_SEPARATE,
+ IIO_CHAN_INFO_CALIBSCALE_SHARED,
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE,
+ IIO_CHAN_INFO_CALIBBIAS_SHARED,
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE,
+ IIO_CHAN_INFO_PEAK_SHARED,
+ IIO_CHAN_INFO_PEAK_SEPARATE,
+ IIO_CHAN_INFO_PEAK_SCALE_SHARED,
+ IIO_CHAN_INFO_PEAK_SCALE_SEPARATE,
+};
/**
+ * struct iio_chan_spec - specification of a single channel
+ * @type: What type of measurement is the channel making.
+ * @channel: What number or name do we wish to asign the channel.
+ * @channel2: If there is a second number for a differential
+ * channel then this is it. If modified is set then the
+ * value here specifies the modifier.
+ * @address: Driver specific identifier.
+ * @scan_index: Monotonic index to give ordering in scans when read
+ * from a buffer.
+ * @scan_type: Sign: 's' or 'u' to specify signed or unsigned
+ * realbits: Number of valid bits of data
+ * storage_bits: Realbits + padding
+ * shift: Shift right by this before masking out
+ * realbits.
+ * @info_mask: What information is to be exported about this channel.
+ * This includes calibbias, scale etc.
+ * @event_mask: What events can this channel produce.
+ * @extend_name: Allows labeling of channel attributes with an
+ * informative name. Note this has no effect codes etc,
+ * unlike modifiers.
+ * @processed_val: Flag to specify the data access attribute should be
+ * *_input rather than *_raw.
+ * @modified: Does a modifier apply to this channel. What these are
+ * depends on the channel type. Modifier is set in
+ * channel2. Examples are IIO_MOD_X for axial sensors about
+ * the 'x' axis.
+ * @indexed: Specify the channel has a numerical index. If not,
+ * the value in channel will be suppressed for attribute
+ * but not for event codes. Typically set it to 0 when
+ * the index is false.
+ */
+struct iio_chan_spec {
+ enum iio_chan_type type;
+ int channel;
+ int channel2;
+ unsigned long address;
+ int scan_index;
+ struct {
+ char sign;
+ u8 realbits;
+ u8 storagebits;
+ u8 shift;
+ } scan_type;
+ const long info_mask;
+ const long event_mask;
+ const 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 }
+
+#define IIO_CHAN(_type, _mod, _indexed, _proc, _name, _chan, _chan2, \
+ _inf_mask, _address, _si, _stype, _event_mask) \
+ { .type = _type, \
+ .modified = _mod, \
+ .indexed = _indexed, \
+ .processed_val = _proc, \
+ .extend_name = _name, \
+ .channel = _chan, \
+ .channel2 = _chan2, \
+ .info_mask = _inf_mask, \
+ .address = _address, \
+ .scan_index = _si, \
+ .scan_type = _stype, \
+ .event_mask = _event_mask }
+
+#define IIO_CHAN_SOFT_TIMESTAMP(_si) \
+ { .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
**/
static inline s64 iio_get_time_ns(void)
@@ -41,26 +191,6 @@ static inline s64 iio_get_time_ns(void)
return timespec_to_ns(&ts);
}
-/**
- * iio_add_event_to_list() - Wraps adding to event lists
- * @el: the list element of the event to be handled.
- * @head: the list associated with the event handler being used.
- *
- * Does reference counting to allow shared handlers.
- **/
-void iio_add_event_to_list(struct iio_event_handler_list *el,
- struct list_head *head);
-
-/**
- * iio_remove_event_from_list() - Wraps removing from event list
- * @el: element to be removed
- * @head: associate list head for the interrupt handler.
- *
- * Does reference counting to allow shared handlers.
- **/
-void iio_remove_event_from_list(struct iio_event_handler_list *el,
- struct list_head *head);
-
/* Device operating modes */
#define INDIO_DIRECT_MODE 0x01
#define INDIO_RING_TRIGGERED 0x02
@@ -70,6 +200,62 @@ void iio_remove_event_from_list(struct iio_event_handler_list *el,
/* Vast majority of this is set by the industrialio subsystem on a
* call to iio_device_register. */
+#define IIO_VAL_INT 1
+#define IIO_VAL_INT_PLUS_MICRO 2
+
+/**
+ * struct iio_info - constant information about device
+ * @driver_module: module structure used to ensure correct
+ * ownership of chrdevs etc
+ * @num_interrupt_lines:number of physical interrupt lines from device
+ * @event_attrs: event control attributes
+ * @attrs: general purpose device attributes
+ * @read_raw: function to request a value from the device.
+ * mask specifies which value. Note 0 means a reading of
+ * the channel in question. Return value will specify the
+ * type of value returned by the device. val and val2 will
+ * contain the elements making up the returned value.
+ * @write_raw: function to write a value to the device.
+ * Parameters are the same as for read_raw.
+ * @read_event_config: find out if the event is enabled.
+ * @write_event_config: set if the event is enabled.
+ * @read_event_value: read a value associated with the event. Meaning
+ * is event dependant. event_code specifies which event.
+ * @write_event_value: write the value associate with the event.
+ * Meaning is event dependent.
+ **/
+struct iio_info {
+ struct module *driver_module;
+ int num_interrupt_lines;
+ struct attribute_group *event_attrs;
+ const struct attribute_group *attrs;
+
+ int (*read_raw)(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long mask);
+
+ int (*write_raw)(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask);
+
+ int (*read_event_config)(struct iio_dev *indio_dev,
+ int event_code);
+
+ int (*write_event_config)(struct iio_dev *indio_dev,
+ int event_code,
+ int state);
+
+ int (*read_event_value)(struct iio_dev *indio_dev,
+ int event_code,
+ int *val);
+ int (*write_event_value)(struct iio_dev *indio_dev,
+ int event_code,
+ int val);
+};
/**
* struct iio_dev - industrial I/O device
@@ -79,13 +265,6 @@ void iio_remove_event_from_list(struct iio_event_handler_list *el,
* @currentmode: [DRIVER] current operating mode
* @dev: [DRIVER] device structure, should be assigned a parent
* and owner
- * @attrs: [DRIVER] general purpose device attributes
- * @driver_module: [DRIVER] module structure used to ensure correct
- * ownership of chrdevs etc
- * @num_interrupt_lines:[DRIVER] number of physical interrupt lines from device
- * @interrupts: [INTERN] interrupt line specific event lists etc
- * @event_attrs: [DRIVER] event control attributes
- * @event_conf_attrs: [DRIVER] event configuration attributes
* @event_interfaces: [INTERN] event chrdevs associated with interrupt lines
* @ring: [DRIVER] any ring buffer present
* @mlock: [INTERN] lock used to prevent simultaneous device state
@@ -93,6 +272,11 @@ void iio_remove_event_from_list(struct iio_event_handler_list *el,
* @available_scan_masks: [DRIVER] optional array of allowed bitmasks
* @trig: [INTERN] current device trigger (ring buffer modes)
* @pollfunc: [DRIVER] function run on trigger being received
+ * @channels: [DRIVER] channel specification structure table
+ * @num_channels: [DRIVER] number of chanels specified in @channels.
+ * @channel_attr_list: [INTERN] keep track of automatically created channel
+ * attributes.
+ * @name: [DRIVER] name of the device.
**/
struct iio_dev {
int id;
@@ -100,13 +284,6 @@ struct iio_dev {
int modes;
int currentmode;
struct device dev;
- const struct attribute_group *attrs;
- struct module *driver_module;
-
- int num_interrupt_lines;
- struct iio_interrupt **interrupts;
- struct attribute_group *event_attrs;
- struct attribute_group *event_conf_attrs;
struct iio_event_interface *event_interfaces;
@@ -116,6 +293,13 @@ struct iio_dev {
u32 *available_scan_masks;
struct iio_trigger *trig;
struct iio_poll_func *pollfunc;
+
+ struct iio_chan_spec const *channels;
+ int num_channels;
+
+ struct list_head channel_attr_list;
+ const char *name;
+ const struct iio_info *info;
};
/**
@@ -131,47 +315,6 @@ int iio_device_register(struct iio_dev *dev_info);
void iio_device_unregister(struct iio_dev *dev_info);
/**
- * struct iio_interrupt - wrapper used to allow easy handling of multiple
- * physical interrupt lines
- * @dev_info: the iio device for which the is an interrupt line
- * @line_number: associated line number
- * @id: ida allocated unique id number
- * @irq: associate interrupt number
- * @ev_list: event handler list for associated events
- * @ev_list_lock: ensure only one access to list at a time
- **/
-struct iio_interrupt {
- struct iio_dev *dev_info;
- int line_number;
- int id;
- int irq;
- struct list_head ev_list;
- spinlock_t ev_list_lock;
-};
-
-#define to_iio_interrupt(i) container_of(i, struct iio_interrupt, ev_list)
-
-/**
- * iio_register_interrupt_line() - Tell IIO about interrupt lines
- *
- * @irq: Typically provided via platform data
- * @dev_info: IIO device info structure for device
- * @line_number: Which interrupt line of the device is this?
- * @type: Interrupt type (e.g. edge triggered etc)
- * @name: Identifying name.
- **/
-int iio_register_interrupt_line(unsigned int irq,
- struct iio_dev *dev_info,
- int line_number,
- unsigned long type,
- const char *name);
-
-void iio_unregister_interrupt_line(struct iio_dev *dev_info,
- int line_number);
-
-
-
-/**
* iio_push_event() - try to add event to the list for userspace reading
* @dev_info: IIO device structure
* @ev_line: Which event line (hardware interrupt)
@@ -183,50 +326,6 @@ int iio_push_event(struct iio_dev *dev_info,
int ev_code,
s64 timestamp);
-/**
- * __iio_push_event() - tries to add an event to the list associated with a chrdev
- * @ev_int: the event interface to which we are pushing the event
- * @ev_code: the outgoing event code
- * @timestamp: timestamp of the event
- * @shared_pointer_p: the shared event pointer
- **/
-int __iio_push_event(struct iio_event_interface *ev_int,
- int ev_code,
- s64 timestamp,
- struct iio_shared_ev_pointer*
- shared_pointer_p);
-/**
- * __iio_change_event() - change an event code in case of event escalation
- * @ev: the event to be changed
- * @ev_code: new event code
- * @timestamp: new timestamp
- **/
-void __iio_change_event(struct iio_detected_event_list *ev,
- int ev_code,
- s64 timestamp);
-
-/**
- * iio_setup_ev_int() - configure an event interface (chrdev)
- * @name: name used for resulting sysfs directory etc.
- * @ev_int: interface we are configuring
- * @owner: module that is responsible for registering this ev_int
- * @dev: device whose ev_int this is
- **/
-int iio_setup_ev_int(struct iio_event_interface *ev_int,
- const char *name,
- struct module *owner,
- struct device *dev);
-
-void iio_free_ev_int(struct iio_event_interface *ev_int);
-
-/**
- * iio_allocate_chrdev() - Allocate a chrdev
- * @handler: struct that contains relevant file handling for chrdev
- * @dev_info: iio_dev for which chrdev is being created
- **/
-int iio_allocate_chrdev(struct iio_handler *handler, struct iio_dev *dev_info);
-void iio_deallocate_chrdev(struct iio_handler *handler);
-
/* 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!*/
@@ -264,10 +363,25 @@ 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
/**
* iio_allocate_device() - allocate an iio_dev from a driver
+ * @sizeof_priv: Space to allocate for private structure.
**/
-struct iio_dev *iio_allocate_device(void);
+struct iio_dev *iio_allocate_device(int sizeof_priv);
+
+static inline void *iio_priv(const struct iio_dev *dev)
+{
+ return (char *)dev + ALIGN(sizeof(struct iio_dev), IIO_ALIGN);
+}
+
+static inline struct iio_dev *iio_priv_to_dev(void *priv)
+{
+ return (struct iio_dev *)((char *)priv -
+ ALIGN(sizeof(struct iio_dev), IIO_ALIGN));
+}
/**
* iio_free_device() - free an iio_dev from a driver
diff --git a/drivers/staging/iio/imu/Kconfig b/drivers/staging/iio/imu/Kconfig
index 31a6233a2068..e0e01446117e 100644
--- a/drivers/staging/iio/imu/Kconfig
+++ b/drivers/staging/iio/imu/Kconfig
@@ -3,29 +3,13 @@
#
comment "Inertial measurement units"
-config ADIS16300
- tristate "Analog Devices ADIS16300 IMU SPI driver"
- depends on SPI
- select IIO_SW_RING if IIO_RING_BUFFER
- select IIO_TRIGGER if IIO_RING_BUFFER
- help
- Say yes here to build support for Analog Devices adis16300 four degrees
- of freedom inertial sensor.
-
-config ADIS16350
- tristate "Analog Devices ADIS16350/54/55/60/62/64/65 IMU SPI driver"
- depends on SPI
- select IIO_TRIGGER if IIO_RING_BUFFER
- select IIO_SW_RING if IIO_RING_BUFFER
- help
- Say yes here to build support for Analog Devices adis16350/54/55/60/62/64/65
- high precision tri-axis inertial sensor.
-
config ADIS16400
- tristate "Analog Devices ADIS16400/5 IMU SPI driver"
+ tristate "Analog Devices ADIS16400 and similar IMU SPI driver"
depends on SPI
select IIO_SW_RING if IIO_RING_BUFFER
select IIO_TRIGGER if IIO_RING_BUFFER
help
- Say yes here to build support for Analog Devices adis16400/5 triaxial
- inertial sensor with Magnetometer.
+ Say yes here to build support for Analog Devices adis16300, adis16350,
+ adis16354, adis16355, adis16360, adis16362, adis16364, adis16365,
+ adis16400 and adis16405 triaxial inertial sensors (adis16400 series
+ also have magnetometers).
diff --git a/drivers/staging/iio/imu/Makefile b/drivers/staging/iio/imu/Makefile
index f3b450b66113..d46a691912ed 100644
--- a/drivers/staging/iio/imu/Makefile
+++ b/drivers/staging/iio/imu/Makefile
@@ -2,14 +2,6 @@
# Makefile for Inertial Measurement Units
#
-adis16300-y := adis16300_core.o
-adis16300-$(CONFIG_IIO_RING_BUFFER) += adis16300_ring.o adis16300_trigger.o
-obj-$(CONFIG_ADIS16300) += adis16300.o
-
-adis16350-y := adis16350_core.o
-adis16350-$(CONFIG_IIO_RING_BUFFER) += adis16350_ring.o adis16350_trigger.o
-obj-$(CONFIG_ADIS16350) += adis16350.o
-
adis16400-y := adis16400_core.o
adis16400-$(CONFIG_IIO_RING_BUFFER) += adis16400_ring.o adis16400_trigger.o
obj-$(CONFIG_ADIS16400) += adis16400.o
diff --git a/drivers/staging/iio/imu/adis16300.h b/drivers/staging/iio/imu/adis16300.h
deleted file mode 100644
index c0957591aed7..000000000000
--- a/drivers/staging/iio/imu/adis16300.h
+++ /dev/null
@@ -1,184 +0,0 @@
-#ifndef SPI_ADIS16300_H_
-#define SPI_ADIS16300_H_
-
-#define ADIS16300_STARTUP_DELAY 220 /* ms */
-
-#define ADIS16300_READ_REG(a) a
-#define ADIS16300_WRITE_REG(a) ((a) | 0x80)
-
-#define ADIS16300_FLASH_CNT 0x00 /* Flash memory write count */
-#define ADIS16300_SUPPLY_OUT 0x02 /* Power supply measurement */
-#define ADIS16300_XGYRO_OUT 0x04 /* X-axis gyroscope output */
-#define ADIS16300_XACCL_OUT 0x0A /* X-axis accelerometer output */
-#define ADIS16300_YACCL_OUT 0x0C /* Y-axis accelerometer output */
-#define ADIS16300_ZACCL_OUT 0x0E /* Z-axis accelerometer output */
-#define ADIS16300_TEMP_OUT 0x10 /* Temperature output */
-#define ADIS16300_XINCLI_OUT 0x12 /* X-axis inclinometer output measurement */
-#define ADIS16300_YINCLI_OUT 0x14 /* Y-axis inclinometer output measurement */
-#define ADIS16300_AUX_ADC 0x16 /* Auxiliary ADC measurement */
-
-/* Calibration parameters */
-#define ADIS16300_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */
-#define ADIS16300_XACCL_OFF 0x20 /* X-axis acceleration bias offset factor */
-#define ADIS16300_YACCL_OFF 0x22 /* Y-axis acceleration bias offset factor */
-#define ADIS16300_ZACCL_OFF 0x24 /* Z-axis acceleration bias offset factor */
-
-#define ADIS16300_GPIO_CTRL 0x32 /* Auxiliary digital input/output control */
-#define ADIS16300_MSC_CTRL 0x34 /* Miscellaneous control */
-#define ADIS16300_SMPL_PRD 0x36 /* Internal sample period (rate) control */
-#define ADIS16300_SENS_AVG 0x38 /* Dynamic range and digital filter control */
-#define ADIS16300_SLP_CNT 0x3A /* Sleep mode control */
-#define ADIS16300_DIAG_STAT 0x3C /* System status */
-
-/* Alarm functions */
-#define ADIS16300_GLOB_CMD 0x3E /* System command */
-#define ADIS16300_ALM_MAG1 0x26 /* Alarm 1 amplitude threshold */
-#define ADIS16300_ALM_MAG2 0x28 /* Alarm 2 amplitude threshold */
-#define ADIS16300_ALM_SMPL1 0x2A /* Alarm 1 sample size */
-#define ADIS16300_ALM_SMPL2 0x2C /* Alarm 2 sample size */
-#define ADIS16300_ALM_CTRL 0x2E /* Alarm control */
-#define ADIS16300_AUX_DAC 0x30 /* Auxiliary DAC data */
-
-#define ADIS16300_ERROR_ACTIVE (1<<14)
-#define ADIS16300_NEW_DATA (1<<15)
-
-/* MSC_CTRL */
-#define ADIS16300_MSC_CTRL_MEM_TEST (1<<11)
-#define ADIS16300_MSC_CTRL_INT_SELF_TEST (1<<10)
-#define ADIS16300_MSC_CTRL_NEG_SELF_TEST (1<<9)
-#define ADIS16300_MSC_CTRL_POS_SELF_TEST (1<<8)
-#define ADIS16300_MSC_CTRL_GYRO_BIAS (1<<7)
-#define ADIS16300_MSC_CTRL_ACCL_ALIGN (1<<6)
-#define ADIS16300_MSC_CTRL_DATA_RDY_EN (1<<2)
-#define ADIS16300_MSC_CTRL_DATA_RDY_POL_HIGH (1<<1)
-#define ADIS16300_MSC_CTRL_DATA_RDY_DIO2 (1<<0)
-
-/* SMPL_PRD */
-#define ADIS16300_SMPL_PRD_TIME_BASE (1<<7)
-#define ADIS16300_SMPL_PRD_DIV_MASK 0x7F
-
-/* DIAG_STAT */
-#define ADIS16300_DIAG_STAT_ZACCL_FAIL (1<<15)
-#define ADIS16300_DIAG_STAT_YACCL_FAIL (1<<14)
-#define ADIS16300_DIAG_STAT_XACCL_FAIL (1<<13)
-#define ADIS16300_DIAG_STAT_XGYRO_FAIL (1<<10)
-#define ADIS16300_DIAG_STAT_ALARM2 (1<<9)
-#define ADIS16300_DIAG_STAT_ALARM1 (1<<8)
-#define ADIS16300_DIAG_STAT_FLASH_CHK (1<<6)
-#define ADIS16300_DIAG_STAT_SELF_TEST (1<<5)
-#define ADIS16300_DIAG_STAT_OVERFLOW (1<<4)
-#define ADIS16300_DIAG_STAT_SPI_FAIL (1<<3)
-#define ADIS16300_DIAG_STAT_FLASH_UPT (1<<2)
-#define ADIS16300_DIAG_STAT_POWER_HIGH (1<<1)
-#define ADIS16300_DIAG_STAT_POWER_LOW (1<<0)
-
-/* GLOB_CMD */
-#define ADIS16300_GLOB_CMD_SW_RESET (1<<7)
-#define ADIS16300_GLOB_CMD_P_AUTO_NULL (1<<4)
-#define ADIS16300_GLOB_CMD_FLASH_UPD (1<<3)
-#define ADIS16300_GLOB_CMD_DAC_LATCH (1<<2)
-#define ADIS16300_GLOB_CMD_FAC_CALIB (1<<1)
-#define ADIS16300_GLOB_CMD_AUTO_NULL (1<<0)
-
-/* SLP_CNT */
-#define ADIS16300_SLP_CNT_POWER_OFF (1<<8)
-
-#define ADIS16300_MAX_TX 18
-#define ADIS16300_MAX_RX 18
-
-#define ADIS16300_SPI_SLOW (u32)(300 * 1000)
-#define ADIS16300_SPI_BURST (u32)(1000 * 1000)
-#define ADIS16300_SPI_FAST (u32)(2000 * 1000)
-
-/**
- * struct adis16300_state - device instance specific data
- * @us: actual spi_device
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter: used to check if new interrupt has been triggered
- * @last_timestamp: passing timestamp from th to bh of interrupt handler
- * @indio_dev: industrial I/O device structure
- * @trig: data ready trigger registered with iio
- * @tx: transmit buffer
- * @rx: receive buffer
- * @buf_lock: mutex to protect tx and rx
- **/
-struct adis16300_state {
- struct spi_device *us;
- struct work_struct work_trigger_to_ring;
- s64 last_timestamp;
- struct iio_dev *indio_dev;
- struct iio_trigger *trig;
- u8 *tx;
- u8 *rx;
- struct mutex buf_lock;
-};
-
-int adis16300_set_irq(struct device *dev, bool enable);
-
-#ifdef CONFIG_IIO_RING_BUFFER
-/* At the moment triggers are only used for ring buffer
- * filling. This may change!
- */
-
-#define ADIS16300_SCAN_SUPPLY 0
-#define ADIS16300_SCAN_GYRO_X 1
-#define ADIS16300_SCAN_ACC_X 2
-#define ADIS16300_SCAN_ACC_Y 3
-#define ADIS16300_SCAN_ACC_Z 4
-#define ADIS16300_SCAN_TEMP 5
-#define ADIS16300_SCAN_ADC_0 6
-#define ADIS16300_SCAN_INCLI_X 7
-#define ADIS16300_SCAN_INCLI_Y 8
-
-void adis16300_remove_trigger(struct iio_dev *indio_dev);
-int adis16300_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16300_read_data_from_ring(struct device *dev,
- struct device_attribute *attr,
- char *buf);
-
-
-int adis16300_configure_ring(struct iio_dev *indio_dev);
-void adis16300_unconfigure_ring(struct iio_dev *indio_dev);
-
-int adis16300_initialize_ring(struct iio_ring_buffer *ring);
-void adis16300_uninitialize_ring(struct iio_ring_buffer *ring);
-#else /* CONFIG_IIO_RING_BUFFER */
-
-static inline void adis16300_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16300_probe_trigger(struct iio_dev *indio_dev)
-{
- return 0;
-}
-
-static inline ssize_t
-adis16300_read_data_from_ring(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return 0;
-}
-
-static int adis16300_configure_ring(struct iio_dev *indio_dev)
-{
- return 0;
-}
-
-static inline void adis16300_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16300_initialize_ring(struct iio_ring_buffer *ring)
-{
- return 0;
-}
-
-static inline void adis16300_uninitialize_ring(struct iio_ring_buffer *ring)
-{
-}
-
-#endif /* CONFIG_IIO_RING_BUFFER */
-#endif /* SPI_ADIS16300_H_ */
diff --git a/drivers/staging/iio/imu/adis16300_core.c b/drivers/staging/iio/imu/adis16300_core.c
deleted file mode 100644
index 7ad13f4d3d74..000000000000
--- a/drivers/staging/iio/imu/adis16300_core.c
+++ /dev/null
@@ -1,756 +0,0 @@
-/*
- * ADIS16300 Four Degrees of Freedom Inertial Sensor Driver
- *
- * Copyright 2010 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
-
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../ring_generic.h"
-#include "../accel/accel.h"
-#include "../accel/inclinometer.h"
-#include "../gyro/gyro.h"
-#include "../adc/adc.h"
-
-#include "adis16300.h"
-
-#define DRIVER_NAME "adis16300"
-
-static int adis16300_check_status(struct device *dev);
-
-/**
- * adis16300_spi_write_reg_8() - write single byte to a register
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-static int adis16300_spi_write_reg_8(struct device *dev,
- u8 reg_address,
- u8 val)
-{
- int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct adis16300_state *st = iio_dev_get_devdata(indio_dev);
-
- mutex_lock(&st->buf_lock);
- st->tx[0] = ADIS16300_WRITE_REG(reg_address);
- st->tx[1] = val;
-
- ret = spi_write(st->us, st->tx, 2);
- mutex_unlock(&st->buf_lock);
-
- return ret;
-}
-
-/**
- * adis16300_spi_write_reg_16() - write 2 bytes to a pair of registers
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @reg_address: the address of the lower of the two registers. Second register
- * is assumed to have address one greater.
- * @val: value to be written
- **/
-static int adis16300_spi_write_reg_16(struct device *dev,
- u8 lower_reg_address,
- u16 value)
-{
- int ret;
- struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct adis16300_state *st = iio_dev_get_devdata(indio_dev);
- struct spi_transfer xfers[] = {
- {
- .tx_buf = st->tx,
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 1,
- .delay_usecs = 75,
- }, {
- .tx_buf = st->tx + 2,
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 1,
- .delay_usecs = 75,
- },
- };
-
- mutex_lock(&st->buf_lock);
- st->tx[0] = ADIS16300_WRITE_REG(lower_reg_address);
- st->tx[1] = value & 0xFF;
- st->tx[2] = ADIS16300_WRITE_REG(lower_reg_address + 1);
- st->tx[3] = (value >> 8) & 0xFF;
-
- spi_message_init(&msg);
- spi_message_add_tail(&xfers[0], &msg);
- spi_message_add_tail(&xfers[1], &msg);
- ret = spi_sync(st->us, &msg);
- mutex_unlock(&st->buf_lock);
-
- return ret;
-}
-
-/**
- * adis16300_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @reg_address: the address of the lower of the two registers. Second register
- * is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int adis16300_spi_read_reg_16(struct device *dev,
- u8 lower_reg_address,
- u16 *val)
-{
- struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct adis16300_state *st = iio_dev_get_devdata(indio_dev);
- int ret;
- struct spi_transfer xfers[] = {
- {
- .tx_buf = st->tx,
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 1,
- .delay_usecs = 75,
- }, {
- .rx_buf = st->rx,
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 1,
- .delay_usecs = 75,
- },
- };
-
- mutex_lock(&st->buf_lock);
- st->tx[0] = ADIS16300_READ_REG(lower_reg_address);
- st->tx[1] = 0;
- st->tx[2] = 0;
- st->tx[3] = 0;
-
- spi_message_init(&msg);
- spi_message_add_tail(&xfers[0], &msg);
- spi_message_add_tail(&xfers[1], &msg);
- ret = spi_sync(st->us, &msg);
- if (ret) {
- dev_err(&st->us->dev,
- "problem when reading 16 bit register 0x%02X",
- lower_reg_address);
- goto error_ret;
- }
- *val = (st->rx[0] << 8) | st->rx[1];
-
-error_ret:
- mutex_unlock(&st->buf_lock);
- return ret;
-}
-
-static ssize_t adis16300_spi_read_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf,
- unsigned bits)
-{
- int ret;
- s16 val = 0;
- unsigned shift = 16 - bits;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
- ret = adis16300_spi_read_reg_16(dev, this_attr->address, (u16 *)&val);
- if (ret)
- return ret;
-
- if (val & ADIS16300_ERROR_ACTIVE)
- adis16300_check_status(dev);
- val = ((s16)(val << shift) >> shift);
- return sprintf(buf, "%d\n", val);
-}
-
-static ssize_t adis16300_read_12bit_unsigned(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int ret;
- u16 val = 0;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
- ret = adis16300_spi_read_reg_16(dev, this_attr->address, &val);
- if (ret)
- return ret;
-
- if (val & ADIS16300_ERROR_ACTIVE)
- adis16300_check_status(dev);
-
- return sprintf(buf, "%u\n", val & 0x0FFF);
-}
-
-static ssize_t adis16300_read_14bit_unsigned(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int ret;
- u16 val = 0;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
- ret = adis16300_spi_read_reg_16(dev, this_attr->address, &val);
- if (ret)
- return ret;
-
- if (val & ADIS16300_ERROR_ACTIVE)
- adis16300_check_status(dev);
-
- return sprintf(buf, "%u\n", val & 0x3FFF);
-}
-
-static ssize_t adis16300_read_14bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ssize_t ret;
-
- /* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
- ret = adis16300_spi_read_signed(dev, attr, buf, 14);
- mutex_unlock(&indio_dev->mlock);
-
- return ret;
-}
-
-static ssize_t adis16300_read_12bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ssize_t ret;
-
- /* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
- ret = adis16300_spi_read_signed(dev, attr, buf, 12);
- mutex_unlock(&indio_dev->mlock);
-
- return ret;
-}
-
-static ssize_t adis16300_read_13bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ssize_t ret;
-
- /* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
- ret = adis16300_spi_read_signed(dev, attr, buf, 13);
- mutex_unlock(&indio_dev->mlock);
-
- return ret;
-}
-
-static ssize_t adis16300_write_16bit(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int ret;
- long val;
-
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- goto error_ret;
- ret = adis16300_spi_write_reg_16(dev, this_attr->address, val);
-
-error_ret:
- return ret ? ret : len;
-}
-
-static ssize_t adis16300_read_frequency(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int ret, len = 0;
- u16 t;
- int sps;
- ret = adis16300_spi_read_reg_16(dev,
- ADIS16300_SMPL_PRD,
- &t);
- if (ret)
- return ret;
- sps = (t & ADIS16300_SMPL_PRD_TIME_BASE) ? 53 : 1638;
- sps /= (t & ADIS16300_SMPL_PRD_DIV_MASK) + 1;
- len = sprintf(buf, "%d SPS\n", sps);
- return len;
-}
-
-static ssize_t adis16300_write_frequency(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct adis16300_state *st = iio_dev_get_devdata(indio_dev);
- long val;
- int ret;
- u8 t;
-
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- return ret;
-
- mutex_lock(&indio_dev->mlock);
-
- t = (1638 / val);
- if (t > 0)
- t--;
- t &= ADIS16300_SMPL_PRD_DIV_MASK;
- if ((t & ADIS16300_SMPL_PRD_DIV_MASK) >= 0x0A)
- st->us->max_speed_hz = ADIS16300_SPI_SLOW;
- else
- st->us->max_speed_hz = ADIS16300_SPI_FAST;
-
- ret = adis16300_spi_write_reg_8(dev,
- ADIS16300_SMPL_PRD,
- t);
-
- mutex_unlock(&indio_dev->mlock);
-
- return ret ? ret : len;
-}
-
-static int adis16300_reset(struct device *dev)
-{
- int ret;
- ret = adis16300_spi_write_reg_8(dev,
- ADIS16300_GLOB_CMD,
- ADIS16300_GLOB_CMD_SW_RESET);
- if (ret)
- dev_err(dev, "problem resetting device");
-
- return ret;
-}
-
-static ssize_t adis16300_write_reset(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
-{
- if (len < 1)
- return -1;
- switch (buf[0]) {
- case '1':
- case 'y':
- case 'Y':
- return adis16300_reset(dev);
- }
- return -1;
-}
-
-int adis16300_set_irq(struct device *dev, bool enable)
-{
- int ret;
- u16 msc;
- ret = adis16300_spi_read_reg_16(dev, ADIS16300_MSC_CTRL, &msc);
- if (ret)
- goto error_ret;
-
- msc |= ADIS16300_MSC_CTRL_DATA_RDY_POL_HIGH;
- msc &= ~ADIS16300_MSC_CTRL_DATA_RDY_DIO2;
- if (enable)
- msc |= ADIS16300_MSC_CTRL_DATA_RDY_EN;
- else
- msc &= ~ADIS16300_MSC_CTRL_DATA_RDY_EN;
-
- ret = adis16300_spi_write_reg_16(dev, ADIS16300_MSC_CTRL, msc);
- if (ret)
- goto error_ret;
-
-error_ret:
- return ret;
-}
-
-/* Power down the device */
-static int adis16300_stop_device(struct device *dev)
-{
- int ret;
- u16 val = ADIS16300_SLP_CNT_POWER_OFF;
-
- ret = adis16300_spi_write_reg_16(dev, ADIS16300_SLP_CNT, val);
- if (ret)
- dev_err(dev, "problem with turning device off: SLP_CNT");
-
- return ret;
-}
-
-static int adis16300_self_test(struct device *dev)
-{
- int ret;
- ret = adis16300_spi_write_reg_16(dev,
- ADIS16300_MSC_CTRL,
- ADIS16300_MSC_CTRL_MEM_TEST);
- if (ret) {
- dev_err(dev, "problem starting self test");
- goto err_ret;
- }
-
- adis16300_check_status(dev);
-
-err_ret:
- return ret;
-}
-
-static int adis16300_check_status(struct device *dev)
-{
- u16 status;
- int ret;
-
- ret = adis16300_spi_read_reg_16(dev, ADIS16300_DIAG_STAT, &status);
-
- if (ret < 0) {
- dev_err(dev, "Reading status failed\n");
- goto error_ret;
- }
- ret = status;
- if (status & ADIS16300_DIAG_STAT_ZACCL_FAIL)
- dev_err(dev, "Z-axis accelerometer self-test failure\n");
- if (status & ADIS16300_DIAG_STAT_YACCL_FAIL)
- dev_err(dev, "Y-axis accelerometer self-test failure\n");
- if (status & ADIS16300_DIAG_STAT_XACCL_FAIL)
- dev_err(dev, "X-axis accelerometer self-test failure\n");
- if (status & ADIS16300_DIAG_STAT_XGYRO_FAIL)
- dev_err(dev, "X-axis gyroscope self-test failure\n");
- if (status & ADIS16300_DIAG_STAT_ALARM2)
- dev_err(dev, "Alarm 2 active\n");
- if (status & ADIS16300_DIAG_STAT_ALARM1)
- dev_err(dev, "Alarm 1 active\n");
- if (status & ADIS16300_DIAG_STAT_FLASH_CHK)
- dev_err(dev, "Flash checksum error\n");
- if (status & ADIS16300_DIAG_STAT_SELF_TEST)
- dev_err(dev, "Self test error\n");
- if (status & ADIS16300_DIAG_STAT_OVERFLOW)
- dev_err(dev, "Sensor overrange\n");
- if (status & ADIS16300_DIAG_STAT_SPI_FAIL)
- dev_err(dev, "SPI failure\n");
- if (status & ADIS16300_DIAG_STAT_FLASH_UPT)
- dev_err(dev, "Flash update failed\n");
- if (status & ADIS16300_DIAG_STAT_POWER_HIGH)
- dev_err(dev, "Power supply above 5.25V\n");
- if (status & ADIS16300_DIAG_STAT_POWER_LOW)
- dev_err(dev, "Power supply below 4.75V\n");
-
-error_ret:
- return ret;
-}
-
-static int adis16300_initial_setup(struct adis16300_state *st)
-{
- int ret;
- u16 smp_prd;
- struct device *dev = &st->indio_dev->dev;
-
- /* use low spi speed for init */
- st->us->max_speed_hz = ADIS16300_SPI_SLOW;
- st->us->mode = SPI_MODE_3;
- spi_setup(st->us);
-
- /* Disable IRQ */
- ret = adis16300_set_irq(dev, false);
- if (ret) {
- dev_err(dev, "disable irq failed");
- goto err_ret;
- }
-
- /* Do self test */
- ret = adis16300_self_test(dev);
- if (ret) {
- dev_err(dev, "self test failure");
- goto err_ret;
- }
-
- /* Read status register to check the result */
- ret = adis16300_check_status(dev);
- if (ret) {
- adis16300_reset(dev);
- dev_err(dev, "device not playing ball -> reset");
- msleep(ADIS16300_STARTUP_DELAY);
- ret = adis16300_check_status(dev);
- if (ret) {
- dev_err(dev, "giving up");
- goto err_ret;
- }
- }
-
- printk(KERN_INFO DRIVER_NAME ": at CS%d (irq %d)\n",
- st->us->chip_select, st->us->irq);
-
- /* use high spi speed if possible */
- ret = adis16300_spi_read_reg_16(dev, ADIS16300_SMPL_PRD, &smp_prd);
- if (!ret && (smp_prd & ADIS16300_SMPL_PRD_DIV_MASK) < 0x0A) {
- st->us->max_speed_hz = ADIS16300_SPI_SLOW;
- spi_setup(st->us);
- }
-
-err_ret:
- return ret;
-}
-
-static IIO_DEV_ATTR_GYRO_X_CALIBBIAS(S_IWUSR | S_IRUGO,
- adis16300_read_12bit_signed,
- adis16300_write_16bit,
- ADIS16300_XGYRO_OFF);
-
-static IIO_DEV_ATTR_ACCEL_X_CALIBBIAS(S_IWUSR | S_IRUGO,
- adis16300_read_12bit_signed,
- adis16300_write_16bit,
- ADIS16300_XACCL_OFF);
-
-static IIO_DEV_ATTR_ACCEL_Y_CALIBBIAS(S_IWUSR | S_IRUGO,
- adis16300_read_12bit_signed,
- adis16300_write_16bit,
- ADIS16300_YACCL_OFF);
-
-static IIO_DEV_ATTR_ACCEL_Z_CALIBBIAS(S_IWUSR | S_IRUGO,
- adis16300_read_12bit_signed,
- adis16300_write_16bit,
- ADIS16300_ZACCL_OFF);
-
-static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16300_read_14bit_unsigned,
- ADIS16300_SUPPLY_OUT);
-static IIO_CONST_ATTR_IN_NAMED_SCALE(0, supply, "0.00242");
-
-static IIO_DEV_ATTR_GYRO_X(adis16300_read_14bit_signed,
- ADIS16300_XGYRO_OUT);
-static IIO_CONST_ATTR_GYRO_SCALE("0.000872664");
-
-static IIO_DEV_ATTR_ACCEL_X(adis16300_read_14bit_signed,
- ADIS16300_XACCL_OUT);
-static IIO_DEV_ATTR_ACCEL_Y(adis16300_read_14bit_signed,
- ADIS16300_YACCL_OUT);
-static IIO_DEV_ATTR_ACCEL_Z(adis16300_read_14bit_signed,
- ADIS16300_ZACCL_OUT);
-static IIO_CONST_ATTR_ACCEL_SCALE("0.00588399");
-
-static IIO_DEV_ATTR_INCLI_X(adis16300_read_13bit_signed,
- ADIS16300_XINCLI_OUT);
-static IIO_DEV_ATTR_INCLI_Y(adis16300_read_13bit_signed,
- ADIS16300_YINCLI_OUT);
-static IIO_CONST_ATTR_INCLI_SCALE("0.00076794487");
-
-static IIO_DEV_ATTR_TEMP_RAW(adis16300_read_12bit_unsigned);
-static IIO_CONST_ATTR_TEMP_OFFSET("198.16");
-static IIO_CONST_ATTR_TEMP_SCALE("0.14");
-
-static IIO_DEV_ATTR_IN_RAW(1, adis16300_read_12bit_unsigned,
- ADIS16300_AUX_ADC);
-static IIO_CONST_ATTR(in1_scale, "0.000806");
-
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
- adis16300_read_frequency,
- adis16300_write_frequency);
-
-static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16300_write_reset, 0);
-
-static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("409 546 819 1638");
-
-static IIO_CONST_ATTR_NAME("adis16300");
-
-static struct attribute *adis16300_event_attributes[] = {
- NULL
-};
-
-static struct attribute_group adis16300_event_attribute_group = {
- .attrs = adis16300_event_attributes,
-};
-
-static struct attribute *adis16300_attributes[] = {
- &iio_dev_attr_gyro_x_calibbias.dev_attr.attr,
- &iio_dev_attr_accel_x_calibbias.dev_attr.attr,
- &iio_dev_attr_accel_y_calibbias.dev_attr.attr,
- &iio_dev_attr_accel_z_calibbias.dev_attr.attr,
- &iio_dev_attr_in0_supply_raw.dev_attr.attr,
- &iio_const_attr_in0_supply_scale.dev_attr.attr,
- &iio_dev_attr_gyro_x_raw.dev_attr.attr,
- &iio_const_attr_gyro_scale.dev_attr.attr,
- &iio_dev_attr_accel_x_raw.dev_attr.attr,
- &iio_dev_attr_accel_y_raw.dev_attr.attr,
- &iio_dev_attr_accel_z_raw.dev_attr.attr,
- &iio_const_attr_accel_scale.dev_attr.attr,
- &iio_dev_attr_incli_x_raw.dev_attr.attr,
- &iio_dev_attr_incli_y_raw.dev_attr.attr,
- &iio_const_attr_incli_scale.dev_attr.attr,
- &iio_dev_attr_temp_raw.dev_attr.attr,
- &iio_const_attr_temp_offset.dev_attr.attr,
- &iio_const_attr_temp_scale.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_const_attr_in1_scale.dev_attr.attr,
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
- &iio_const_attr_sampling_frequency_available.dev_attr.attr,
- &iio_dev_attr_reset.dev_attr.attr,
- &iio_const_attr_name.dev_attr.attr,
- NULL
-};
-
-static const struct attribute_group adis16300_attribute_group = {
- .attrs = adis16300_attributes,
-};
-
-static int __devinit adis16300_probe(struct spi_device *spi)
-{
- int ret, regdone = 0;
- struct adis16300_state *st = kzalloc(sizeof *st, GFP_KERNEL);
- if (!st) {
- ret = -ENOMEM;
- goto error_ret;
- }
- /* this is only used for removal purposes */
- spi_set_drvdata(spi, st);
-
- /* Allocate the comms buffers */
- st->rx = kzalloc(sizeof(*st->rx)*ADIS16300_MAX_RX, GFP_KERNEL);
- if (st->rx == NULL) {
- ret = -ENOMEM;
- goto error_free_st;
- }
- st->tx = kzalloc(sizeof(*st->tx)*ADIS16300_MAX_TX, GFP_KERNEL);
- if (st->tx == NULL) {
- ret = -ENOMEM;
- goto error_free_rx;
- }
- st->us = spi;
- mutex_init(&st->buf_lock);
- /* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
- if (st->indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_free_tx;
- }
-
- st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->num_interrupt_lines = 1;
- st->indio_dev->event_attrs = &adis16300_event_attribute_group;
- st->indio_dev->attrs = &adis16300_attribute_group;
- st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
- st->indio_dev->modes = INDIO_DIRECT_MODE;
-
- ret = adis16300_configure_ring(st->indio_dev);
- if (ret)
- goto error_free_dev;
-
- ret = iio_device_register(st->indio_dev);
- if (ret)
- goto error_unreg_ring_funcs;
- regdone = 1;
-
- ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
- if (ret) {
- printk(KERN_ERR "failed to initialize the ring\n");
- goto error_unreg_ring_funcs;
- }
-
- if (spi->irq) {
- ret = iio_register_interrupt_line(spi->irq,
- st->indio_dev,
- 0,
- IRQF_TRIGGER_RISING,
- "adis16300");
- if (ret)
- goto error_uninitialize_ring;
-
- ret = adis16300_probe_trigger(st->indio_dev);
- if (ret)
- goto error_unregister_line;
- }
-
- /* Get the device into a sane initial state */
- ret = adis16300_initial_setup(st);
- if (ret)
- goto error_remove_trigger;
- return 0;
-
-error_remove_trigger:
- adis16300_remove_trigger(st->indio_dev);
-error_unregister_line:
- if (spi->irq)
- iio_unregister_interrupt_line(st->indio_dev, 0);
-error_uninitialize_ring:
- iio_ring_buffer_unregister(st->indio_dev->ring);
-error_unreg_ring_funcs:
- adis16300_unconfigure_ring(st->indio_dev);
-error_free_dev:
- if (regdone)
- iio_device_unregister(st->indio_dev);
- else
- iio_free_device(st->indio_dev);
-error_free_tx:
- kfree(st->tx);
-error_free_rx:
- kfree(st->rx);
-error_free_st:
- kfree(st);
-error_ret:
- return ret;
-}
-
-static int adis16300_remove(struct spi_device *spi)
-{
- int ret;
- struct adis16300_state *st = spi_get_drvdata(spi);
- struct iio_dev *indio_dev = st->indio_dev;
-
- ret = adis16300_stop_device(&(indio_dev->dev));
- if (ret)
- goto err_ret;
-
- flush_scheduled_work();
-
- adis16300_remove_trigger(indio_dev);
- if (spi->irq)
- iio_unregister_interrupt_line(indio_dev, 0);
-
- iio_ring_buffer_unregister(indio_dev->ring);
- iio_device_unregister(indio_dev);
- adis16300_unconfigure_ring(indio_dev);
- kfree(st->tx);
- kfree(st->rx);
- kfree(st);
-
- return 0;
-
-err_ret:
- return ret;
-}
-
-static struct spi_driver adis16300_driver = {
- .driver = {
- .name = "adis16300",
- .owner = THIS_MODULE,
- },
- .probe = adis16300_probe,
- .remove = __devexit_p(adis16300_remove),
-};
-
-static __init int adis16300_init(void)
-{
- return spi_register_driver(&adis16300_driver);
-}
-module_init(adis16300_init);
-
-static __exit void adis16300_exit(void)
-{
- spi_unregister_driver(&adis16300_driver);
-}
-module_exit(adis16300_exit);
-
-MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
-MODULE_DESCRIPTION("Analog Devices ADIS16300 IMU SPI driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/imu/adis16300_ring.c b/drivers/staging/iio/imu/adis16300_ring.c
deleted file mode 100644
index 114fdf4fd47d..000000000000
--- a/drivers/staging/iio/imu/adis16300_ring.c
+++ /dev/null
@@ -1,238 +0,0 @@
-#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 "adis16300.h"
-
-static IIO_SCAN_EL_C(in0_supply, ADIS16300_SCAN_SUPPLY,
- ADIS16300_SUPPLY_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in0_supply, u, 12, 16);
-static IIO_SCAN_EL_C(gyro_x, ADIS16300_SCAN_GYRO_X, ADIS16300_XGYRO_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(gyro, s, 14, 16);
-
-static IIO_SCAN_EL_C(accel_x, ADIS16300_SCAN_ACC_X, ADIS16300_XACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_y, ADIS16300_SCAN_ACC_Y, ADIS16300_YACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_z, ADIS16300_SCAN_ACC_Z, ADIS16300_ZACCL_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(accel, s, 14, 16);
-
-static IIO_SCAN_EL_C(temp, ADIS16300_SCAN_TEMP, ADIS16300_TEMP_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(temp, s, 12, 16);
-
-static IIO_SCAN_EL_C(in1, ADIS16300_SCAN_ADC_0, ADIS16300_AUX_ADC, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in1, u, 12, 16);
-
-static IIO_SCAN_EL_C(incli_x, ADIS16300_SCAN_INCLI_X,
- ADIS16300_XINCLI_OUT, NULL);
-static IIO_SCAN_EL_C(incli_y, ADIS16300_SCAN_INCLI_Y,
- ADIS16300_YINCLI_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(incli, s, 13, 16);
-
-static IIO_SCAN_EL_TIMESTAMP(9);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
-
-static struct attribute *adis16300_scan_el_attrs[] = {
- &iio_scan_el_in0_supply.dev_attr.attr,
- &iio_const_attr_in0_supply_index.dev_attr.attr,
- &iio_const_attr_in0_supply_type.dev_attr.attr,
- &iio_scan_el_gyro_x.dev_attr.attr,
- &iio_const_attr_gyro_x_index.dev_attr.attr,
- &iio_const_attr_gyro_type.dev_attr.attr,
- &iio_scan_el_temp.dev_attr.attr,
- &iio_const_attr_temp_index.dev_attr.attr,
- &iio_const_attr_temp_type.dev_attr.attr,
- &iio_scan_el_accel_x.dev_attr.attr,
- &iio_const_attr_accel_x_index.dev_attr.attr,
- &iio_scan_el_accel_y.dev_attr.attr,
- &iio_const_attr_accel_y_index.dev_attr.attr,
- &iio_scan_el_accel_z.dev_attr.attr,
- &iio_const_attr_accel_z_index.dev_attr.attr,
- &iio_const_attr_accel_type.dev_attr.attr,
- &iio_scan_el_incli_x.dev_attr.attr,
- &iio_const_attr_incli_x_index.dev_attr.attr,
- &iio_scan_el_incli_y.dev_attr.attr,
- &iio_const_attr_incli_y_index.dev_attr.attr,
- &iio_const_attr_incli_type.dev_attr.attr,
- &iio_scan_el_in1.dev_attr.attr,
- &iio_const_attr_in1_index.dev_attr.attr,
- &iio_const_attr_in1_type.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group adis16300_scan_el_group = {
- .attrs = adis16300_scan_el_attrs,
- .name = "scan_elements",
-};
-
-/**
- * adis16300_poll_func_th() top half interrupt handler called by trigger
- * @private_data: iio_dev
- **/
-static void adis16300_poll_func_th(struct iio_dev *indio_dev, s64 time)
-{
- struct adis16300_state *st = iio_dev_get_devdata(indio_dev);
- st->last_timestamp = time;
- schedule_work(&st->work_trigger_to_ring);
- /* Indicate that this interrupt is being handled */
-
- /* Technically this is trigger related, but without this
- * handler running there is currently no way for the interrupt
- * to clear.
- */
-}
-
-/**
- * adis16300_spi_read_burst() - read all data registers
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @rx: somewhere to pass back the value read (min size is 24 bytes)
- **/
-static int adis16300_spi_read_burst(struct device *dev, u8 *rx)
-{
- struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct adis16300_state *st = iio_dev_get_devdata(indio_dev);
- u32 old_speed_hz = st->us->max_speed_hz;
- int ret;
-
- struct spi_transfer xfers[] = {
- {
- .tx_buf = st->tx,
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 0,
- }, {
- .rx_buf = rx,
- .bits_per_word = 8,
- .len = 18,
- .cs_change = 0,
- },
- };
-
- mutex_lock(&st->buf_lock);
- st->tx[0] = ADIS16300_READ_REG(ADIS16300_GLOB_CMD);
- st->tx[1] = 0;
-
- spi_message_init(&msg);
- spi_message_add_tail(&xfers[0], &msg);
- spi_message_add_tail(&xfers[1], &msg);
-
- st->us->max_speed_hz = ADIS16300_SPI_BURST;
- spi_setup(st->us);
-
- ret = spi_sync(st->us, &msg);
- if (ret)
- dev_err(&st->us->dev, "problem when burst reading");
-
- st->us->max_speed_hz = old_speed_hz;
- spi_setup(st->us);
- mutex_unlock(&st->buf_lock);
- return ret;
-}
-
-/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
- * specific to be rolled into the core.
- */
-static void adis16300_trigger_bh_to_ring(struct work_struct *work_s)
-{
- struct adis16300_state *st
- = container_of(work_s, struct adis16300_state,
- work_trigger_to_ring);
- struct iio_ring_buffer *ring = st->indio_dev->ring;
-
- int i = 0;
- s16 *data;
- size_t datasize = ring->access.get_bytes_per_datum(ring);
-
- data = kmalloc(datasize , GFP_KERNEL);
- if (data == NULL) {
- dev_err(&st->us->dev, "memory alloc failed in ring bh");
- return;
- }
-
- if (ring->scan_count)
- if (adis16300_spi_read_burst(&st->indio_dev->dev, st->rx) >= 0)
- for (; i < ring->scan_count; i++)
- data[i] = be16_to_cpup(
- (__be16 *)&(st->rx[i*2]));
-
- /* Guaranteed to be aligned with 8 byte boundary */
- if (ring->scan_timestamp)
- *((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
-
- ring->access.store_to(ring,
- (u8 *)data,
- st->last_timestamp);
-
- iio_trigger_notify_done(st->indio_dev->trig);
- kfree(data);
-
- return;
-}
-
-void adis16300_unconfigure_ring(struct iio_dev *indio_dev)
-{
- kfree(indio_dev->pollfunc);
- iio_sw_rb_free(indio_dev->ring);
-}
-
-int adis16300_configure_ring(struct iio_dev *indio_dev)
-{
- int ret = 0;
- struct adis16300_state *st = indio_dev->dev_data;
- struct iio_ring_buffer *ring;
- INIT_WORK(&st->work_trigger_to_ring, adis16300_trigger_bh_to_ring);
-
- ring = iio_sw_rb_allocate(indio_dev);
- if (!ring) {
- ret = -ENOMEM;
- return ret;
- }
- indio_dev->ring = ring;
- /* Effectively select the ring buffer implementation */
- iio_ring_sw_register_funcs(&ring->access);
- ring->bpe = 2;
- ring->scan_el_attrs = &adis16300_scan_el_group;
- ring->scan_timestamp = true;
- ring->preenable = &iio_sw_ring_preenable;
- ring->postenable = &iio_triggered_ring_postenable;
- ring->predisable = &iio_triggered_ring_predisable;
- ring->owner = THIS_MODULE;
-
- /* Set default scan mode */
- iio_scan_mask_set(ring, iio_scan_el_in0_supply.number);
- iio_scan_mask_set(ring, iio_scan_el_gyro_x.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_x.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_y.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_z.number);
- iio_scan_mask_set(ring, iio_scan_el_temp.number);
- iio_scan_mask_set(ring, iio_scan_el_in1.number);
- iio_scan_mask_set(ring, iio_scan_el_incli_x.number);
- iio_scan_mask_set(ring, iio_scan_el_incli_y.number);
-
- ret = iio_alloc_pollfunc(indio_dev, NULL, &adis16300_poll_func_th);
- if (ret)
- goto error_iio_sw_rb_free;
-
- indio_dev->modes |= INDIO_RING_TRIGGERED;
- return 0;
-
-error_iio_sw_rb_free:
- iio_sw_rb_free(indio_dev->ring);
- return ret;
-}
-
diff --git a/drivers/staging/iio/imu/adis16300_trigger.c b/drivers/staging/iio/imu/adis16300_trigger.c
deleted file mode 100644
index d6677b64edb9..000000000000
--- a/drivers/staging/iio/imu/adis16300_trigger.c
+++ /dev/null
@@ -1,125 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
-#include <linux/spi/spi.h>
-
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../trigger.h"
-#include "adis16300.h"
-
-/**
- * adis16300_data_rdy_trig_poll() the event handler for the data rdy trig
- **/
-static int adis16300_data_rdy_trig_poll(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct adis16300_state *st = iio_dev_get_devdata(dev_info);
- struct iio_trigger *trig = st->trig;
-
- iio_trigger_poll(trig, timestamp);
-
- return IRQ_HANDLED;
-}
-
-IIO_EVENT_SH(data_rdy_trig, &adis16300_data_rdy_trig_poll);
-
-static IIO_TRIGGER_NAME_ATTR;
-
-static struct attribute *adis16300_trigger_attrs[] = {
- &dev_attr_name.attr,
- NULL,
-};
-
-static const struct attribute_group adis16300_trigger_attr_group = {
- .attrs = adis16300_trigger_attrs,
-};
-
-/**
- * adis16300_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16300_data_rdy_trigger_set_state(struct iio_trigger *trig,
- bool state)
-{
- struct adis16300_state *st = trig->private_data;
- struct iio_dev *indio_dev = st->indio_dev;
- int ret = 0;
-
- dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
- ret = adis16300_set_irq(&st->indio_dev->dev, state);
- if (state == false) {
- iio_remove_event_from_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]
- ->ev_list);
- /* possible quirk with handler currently worked around
- by ensuring the work queue is empty */
- flush_scheduled_work();
- } else {
- iio_add_event_to_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]->ev_list);
- }
- return ret;
-}
-
-/**
- * adis16300_trig_try_reen() try renabling irq for data rdy trigger
- * @trig: the datardy trigger
- **/
-static int adis16300_trig_try_reen(struct iio_trigger *trig)
-{
- struct adis16300_state *st = trig->private_data;
- enable_irq(st->us->irq);
- /* irq reenabled so success! */
- return 0;
-}
-
-int adis16300_probe_trigger(struct iio_dev *indio_dev)
-{
- int ret;
- struct adis16300_state *st = indio_dev->dev_data;
-
- st->trig = iio_allocate_trigger();
- st->trig->name = kasprintf(GFP_KERNEL,
- "adis16300-dev%d",
- indio_dev->id);
- if (!st->trig->name) {
- ret = -ENOMEM;
- goto error_free_trig;
- }
- st->trig->dev.parent = &st->us->dev;
- st->trig->owner = THIS_MODULE;
- st->trig->private_data = st;
- st->trig->set_trigger_state = &adis16300_data_rdy_trigger_set_state;
- st->trig->try_reenable = &adis16300_trig_try_reen;
- st->trig->control_attrs = &adis16300_trigger_attr_group;
- ret = iio_trigger_register(st->trig);
-
- /* select default trigger */
- indio_dev->trig = st->trig;
- if (ret)
- goto error_free_trig_name;
-
- return 0;
-
-error_free_trig_name:
- kfree(st->trig->name);
-error_free_trig:
- iio_free_trigger(st->trig);
-
- return ret;
-}
-
-void adis16300_remove_trigger(struct iio_dev *indio_dev)
-{
- struct adis16300_state *state = indio_dev->dev_data;
-
- iio_trigger_unregister(state->trig);
- kfree(state->trig->name);
- iio_free_trigger(state->trig);
-}
diff --git a/drivers/staging/iio/imu/adis16350.h b/drivers/staging/iio/imu/adis16350.h
deleted file mode 100644
index b1ad48662a2c..000000000000
--- a/drivers/staging/iio/imu/adis16350.h
+++ /dev/null
@@ -1,177 +0,0 @@
-#ifndef SPI_ADIS16350_H_
-#define SPI_ADIS16350_H_
-
-#define ADIS16350_STARTUP_DELAY 220 /* ms */
-
-#define ADIS16350_READ_REG(a) a
-#define ADIS16350_WRITE_REG(a) ((a) | 0x80)
-
-#define ADIS16350_FLASH_CNT 0x00 /* Flash memory write count */
-#define ADIS16350_SUPPLY_OUT 0x02 /* Power supply measurement */
-#define ADIS16350_XGYRO_OUT 0x04 /* X-axis gyroscope output */
-#define ADIS16350_YGYRO_OUT 0x06 /* Y-axis gyroscope output */
-#define ADIS16350_ZGYRO_OUT 0x08 /* Z-axis gyroscope output */
-#define ADIS16350_XACCL_OUT 0x0A /* X-axis accelerometer output */
-#define ADIS16350_YACCL_OUT 0x0C /* Y-axis accelerometer output */
-#define ADIS16350_ZACCL_OUT 0x0E /* Z-axis accelerometer output */
-#define ADIS16350_XTEMP_OUT 0x10 /* X-axis gyroscope temperature measurement */
-#define ADIS16350_YTEMP_OUT 0x12 /* Y-axis gyroscope temperature measurement */
-#define ADIS16350_ZTEMP_OUT 0x14 /* Z-axis gyroscope temperature measurement */
-#define ADIS16350_AUX_ADC 0x16 /* Auxiliary ADC measurement */
-
-/* Calibration parameters */
-#define ADIS16350_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */
-#define ADIS16350_YGYRO_OFF 0x1C /* Y-axis gyroscope bias offset factor */
-#define ADIS16350_ZGYRO_OFF 0x1E /* Z-axis gyroscope bias offset factor */
-#define ADIS16350_XACCL_OFF 0x20 /* X-axis acceleration bias offset factor */
-#define ADIS16350_YACCL_OFF 0x22 /* Y-axis acceleration bias offset factor */
-#define ADIS16350_ZACCL_OFF 0x24 /* Z-axis acceleration bias offset factor */
-
-#define ADIS16350_GPIO_CTRL 0x32 /* Auxiliary digital input/output control */
-#define ADIS16350_MSC_CTRL 0x34 /* Miscellaneous control */
-#define ADIS16350_SMPL_PRD 0x36 /* Internal sample period (rate) control */
-#define ADIS16350_SENS_AVG 0x38 /* Dynamic range and digital filter control */
-#define ADIS16350_SLP_CNT 0x3A /* Sleep mode control */
-#define ADIS16350_DIAG_STAT 0x3C /* System status */
-
-/* Alarm functions */
-#define ADIS16350_GLOB_CMD 0x3E /* System command */
-#define ADIS16350_ALM_MAG1 0x26 /* Alarm 1 amplitude threshold */
-#define ADIS16350_ALM_MAG2 0x28 /* Alarm 2 amplitude threshold */
-#define ADIS16350_ALM_SMPL1 0x2A /* Alarm 1 sample size */
-#define ADIS16350_ALM_SMPL2 0x2C /* Alarm 2 sample size */
-#define ADIS16350_ALM_CTRL 0x2E /* Alarm control */
-#define ADIS16350_AUX_DAC 0x30 /* Auxiliary DAC data */
-
-#define ADIS16350_ERROR_ACTIVE (1<<14)
-#define ADIS16350_NEW_DATA (1<<15)
-
-/* MSC_CTRL */
-#define ADIS16350_MSC_CTRL_MEM_TEST (1<<11)
-#define ADIS16350_MSC_CTRL_INT_SELF_TEST (1<<10)
-#define ADIS16350_MSC_CTRL_NEG_SELF_TEST (1<<9)
-#define ADIS16350_MSC_CTRL_POS_SELF_TEST (1<<8)
-#define ADIS16350_MSC_CTRL_GYRO_BIAS (1<<7)
-#define ADIS16350_MSC_CTRL_ACCL_ALIGN (1<<6)
-#define ADIS16350_MSC_CTRL_DATA_RDY_EN (1<<2)
-#define ADIS16350_MSC_CTRL_DATA_RDY_POL_HIGH (1<<1)
-#define ADIS16350_MSC_CTRL_DATA_RDY_DIO2 (1<<0)
-
-/* SMPL_PRD */
-#define ADIS16350_SMPL_PRD_TIME_BASE (1<<7)
-#define ADIS16350_SMPL_PRD_DIV_MASK 0x7F
-
-/* DIAG_STAT */
-#define ADIS16350_DIAG_STAT_ZACCL_FAIL (1<<15)
-#define ADIS16350_DIAG_STAT_YACCL_FAIL (1<<14)
-#define ADIS16350_DIAG_STAT_XACCL_FAIL (1<<13)
-#define ADIS16350_DIAG_STAT_XGYRO_FAIL (1<<12)
-#define ADIS16350_DIAG_STAT_YGYRO_FAIL (1<<11)
-#define ADIS16350_DIAG_STAT_ZGYRO_FAIL (1<<10)
-#define ADIS16350_DIAG_STAT_ALARM2 (1<<9)
-#define ADIS16350_DIAG_STAT_ALARM1 (1<<8)
-#define ADIS16350_DIAG_STAT_FLASH_CHK (1<<6)
-#define ADIS16350_DIAG_STAT_SELF_TEST (1<<5)
-#define ADIS16350_DIAG_STAT_OVERFLOW (1<<4)
-#define ADIS16350_DIAG_STAT_SPI_FAIL (1<<3)
-#define ADIS16350_DIAG_STAT_FLASH_UPT (1<<2)
-#define ADIS16350_DIAG_STAT_POWER_HIGH (1<<1)
-#define ADIS16350_DIAG_STAT_POWER_LOW (1<<0)
-
-/* GLOB_CMD */
-#define ADIS16350_GLOB_CMD_SW_RESET (1<<7)
-#define ADIS16350_GLOB_CMD_P_AUTO_NULL (1<<4)
-#define ADIS16350_GLOB_CMD_FLASH_UPD (1<<3)
-#define ADIS16350_GLOB_CMD_DAC_LATCH (1<<2)
-#define ADIS16350_GLOB_CMD_FAC_CALIB (1<<1)
-#define ADIS16350_GLOB_CMD_AUTO_NULL (1<<0)
-
-/* SLP_CNT */
-#define ADIS16350_SLP_CNT_POWER_OFF (1<<8)
-
-#define ADIS16350_MAX_TX 24
-#define ADIS16350_MAX_RX 24
-
-#define ADIS16350_SPI_SLOW (u32)(300 * 1000)
-#define ADIS16350_SPI_BURST (u32)(1000 * 1000)
-#define ADIS16350_SPI_FAST (u32)(2000 * 1000)
-
-/**
- * struct adis16350_state - device instance specific data
- * @us: actual spi_device
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter: used to check if new interrupt has been triggered
- * @last_timestamp: passing timestamp from th to bh of interrupt handler
- * @indio_dev: industrial I/O device structure
- * @trig: data ready trigger registered with iio
- * @tx: transmit buffer
- * @rx: receive buffer
- * @buf_lock: mutex to protect tx and rx
- **/
-struct adis16350_state {
- struct spi_device *us;
- struct work_struct work_trigger_to_ring;
- s64 last_timestamp;
- struct iio_dev *indio_dev;
- struct iio_trigger *trig;
- u8 *tx;
- u8 *rx;
- struct mutex buf_lock;
-};
-
-int adis16350_set_irq(struct device *dev, bool enable);
-
-#ifdef CONFIG_IIO_RING_BUFFER
-
-#define ADIS16350_SCAN_SUPPLY 0
-#define ADIS16350_SCAN_GYRO_X 1
-#define ADIS16350_SCAN_GYRO_Y 2
-#define ADIS16350_SCAN_GYRO_Z 3
-#define ADIS16350_SCAN_ACC_X 4
-#define ADIS16350_SCAN_ACC_Y 5
-#define ADIS16350_SCAN_ACC_Z 6
-#define ADIS16350_SCAN_TEMP_X 7
-#define ADIS16350_SCAN_TEMP_Y 8
-#define ADIS16350_SCAN_TEMP_Z 9
-#define ADIS16350_SCAN_ADC_0 10
-
-void adis16350_remove_trigger(struct iio_dev *indio_dev);
-int adis16350_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16350_read_data_from_ring(struct device *dev,
- struct device_attribute *attr,
- char *buf);
-
-
-int adis16350_configure_ring(struct iio_dev *indio_dev);
-void adis16350_unconfigure_ring(struct iio_dev *indio_dev);
-
-#else /* CONFIG_IIO_RING_BUFFER */
-
-static inline void adis16350_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16350_probe_trigger(struct iio_dev *indio_dev)
-{
- return 0;
-}
-
-static inline ssize_t
-adis16350_read_data_from_ring(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return 0;
-}
-
-static inline int adis16350_configure_ring(struct iio_dev *indio_dev)
-{
- return 0;
-}
-
-static inline void adis16350_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-#endif /* CONFIG_IIO_RING_BUFFER */
-#endif /* SPI_ADIS16350_H_ */
diff --git a/drivers/staging/iio/imu/adis16350_core.c b/drivers/staging/iio/imu/adis16350_core.c
deleted file mode 100644
index cf7176bc766b..000000000000
--- a/drivers/staging/iio/imu/adis16350_core.c
+++ /dev/null
@@ -1,757 +0,0 @@
-/*
- * ADIS16350/54/55/60/62/64/65 high precision tri-axis inertial sensor
- *
- * Copyright 2010 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
-
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../ring_generic.h"
-#include "../accel/accel.h"
-#include "../adc/adc.h"
-#include "../gyro/gyro.h"
-
-#include "adis16350.h"
-
-#define DRIVER_NAME "adis16350"
-
-static int adis16350_check_status(struct device *dev);
-
-/**
- * adis16350_spi_write_reg_8() - write single byte to a register
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-static int adis16350_spi_write_reg_8(struct device *dev,
- u8 reg_address,
- u8 val)
-{
- int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct adis16350_state *st = iio_dev_get_devdata(indio_dev);
-
- mutex_lock(&st->buf_lock);
- st->tx[0] = ADIS16350_WRITE_REG(reg_address);
- st->tx[1] = val;
-
- ret = spi_write(st->us, st->tx, 2);
- mutex_unlock(&st->buf_lock);
-
- return ret;
-}
-
-/**
- * adis16350_spi_write_reg_16() - write 2 bytes to a pair of registers
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @reg_address: the address of the lower of the two registers. Second register
- * is assumed to have address one greater.
- * @val: value to be written
- **/
-static int adis16350_spi_write_reg_16(struct device *dev,
- u8 lower_reg_address,
- u16 value)
-{
- int ret;
- struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct adis16350_state *st = iio_dev_get_devdata(indio_dev);
- struct spi_transfer xfers[] = {
- {
- .tx_buf = st->tx,
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 1,
- .delay_usecs = 35,
- }, {
- .tx_buf = st->tx + 2,
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 1,
- .delay_usecs = 35,
- },
- };
-
- mutex_lock(&st->buf_lock);
- st->tx[0] = ADIS16350_WRITE_REG(lower_reg_address);
- st->tx[1] = value & 0xFF;
- st->tx[2] = ADIS16350_WRITE_REG(lower_reg_address + 1);
- st->tx[3] = (value >> 8) & 0xFF;
-
- spi_message_init(&msg);
- spi_message_add_tail(&xfers[0], &msg);
- spi_message_add_tail(&xfers[1], &msg);
- ret = spi_sync(st->us, &msg);
- mutex_unlock(&st->buf_lock);
-
- return ret;
-}
-
-/**
- * adis16350_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @reg_address: the address of the lower of the two registers. Second register
- * is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int adis16350_spi_read_reg_16(struct device *dev,
- u8 lower_reg_address,
- u16 *val)
-{
- struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct adis16350_state *st = iio_dev_get_devdata(indio_dev);
- int ret;
- struct spi_transfer xfers[] = {
- {
- .tx_buf = st->tx,
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 1,
- .delay_usecs = 35,
- }, {
- .rx_buf = st->rx,
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 1,
- .delay_usecs = 35,
- },
- };
-
- mutex_lock(&st->buf_lock);
- st->tx[0] = ADIS16350_READ_REG(lower_reg_address);
- st->tx[1] = 0;
- st->tx[2] = 0;
- st->tx[3] = 0;
-
- spi_message_init(&msg);
- spi_message_add_tail(&xfers[0], &msg);
- spi_message_add_tail(&xfers[1], &msg);
- ret = spi_sync(st->us, &msg);
- if (ret) {
- dev_err(&st->us->dev,
- "problem when reading 16 bit register 0x%02X",
- lower_reg_address);
- goto error_ret;
- }
- *val = (st->rx[0] << 8) | st->rx[1];
-
-error_ret:
- mutex_unlock(&st->buf_lock);
- return ret;
-}
-
-
-static ssize_t adis16350_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 = adis16350_spi_read_reg_16(dev, this_attr->address, (u16 *)&val);
- if (ret)
- return ret;
-
- if (val & ADIS16350_ERROR_ACTIVE)
- adis16350_check_status(dev);
- val = ((s16)(val << shift) >> shift);
- return sprintf(buf, "%d\n", val);
-}
-
-static ssize_t adis16350_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 = adis16350_spi_read_reg_16(dev, this_attr->address, &val);
- if (ret)
- return ret;
-
- if (val & ADIS16350_ERROR_ACTIVE)
- adis16350_check_status(dev);
-
- return sprintf(buf, "%u\n", val & 0x0FFF);
-}
-
-static ssize_t adis16350_read_14bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ssize_t ret;
-
- /* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
- ret = adis16350_spi_read_signed(dev, attr, buf, 14);
- mutex_unlock(&indio_dev->mlock);
-
- return ret;
-}
-
-static ssize_t adis16350_read_12bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ssize_t ret;
-
- /* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
- ret = adis16350_spi_read_signed(dev, attr, buf, 12);
- mutex_unlock(&indio_dev->mlock);
-
- return ret;
-}
-
-static ssize_t adis16350_write_16bit(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int ret;
- long val;
-
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- goto error_ret;
- ret = adis16350_spi_write_reg_16(dev, this_attr->address, val);
-
-error_ret:
- return ret ? ret : len;
-}
-
-static ssize_t adis16350_read_frequency(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int ret, len = 0;
- u16 t;
- int sps;
- ret = adis16350_spi_read_reg_16(dev,
- ADIS16350_SMPL_PRD,
- &t);
- if (ret)
- return ret;
- sps = (t & ADIS16350_SMPL_PRD_TIME_BASE) ? 53 : 1638;
- sps /= (t & ADIS16350_SMPL_PRD_DIV_MASK) + 1;
- len = sprintf(buf, "%d SPS\n", sps);
- return len;
-}
-
-static ssize_t adis16350_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 adis16350_state *st = iio_dev_get_devdata(indio_dev);
- long val;
- int ret;
- u8 t;
-
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- return ret;
-
- mutex_lock(&indio_dev->mlock);
-
- t = (1638 / val);
- if (t > 0)
- t--;
- t &= ADIS16350_SMPL_PRD_DIV_MASK;
- if ((t & ADIS16350_SMPL_PRD_DIV_MASK) >= 0x0A)
- st->us->max_speed_hz = ADIS16350_SPI_SLOW;
- else
- st->us->max_speed_hz = ADIS16350_SPI_FAST;
-
- ret = adis16350_spi_write_reg_8(dev,
- ADIS16350_SMPL_PRD,
- t);
-
- mutex_unlock(&indio_dev->mlock);
-
- return ret ? ret : len;
-}
-
-static int adis16350_reset(struct device *dev)
-{
- int ret;
- ret = adis16350_spi_write_reg_8(dev,
- ADIS16350_GLOB_CMD,
- ADIS16350_GLOB_CMD_SW_RESET);
- if (ret)
- dev_err(dev, "problem resetting device");
-
- return ret;
-}
-
-static ssize_t adis16350_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 adis16350_reset(dev);
- }
- return -1;
-}
-
-int adis16350_set_irq(struct device *dev, bool enable)
-{
- int ret;
- u16 msc;
- ret = adis16350_spi_read_reg_16(dev, ADIS16350_MSC_CTRL, &msc);
- if (ret)
- goto error_ret;
-
- msc |= ADIS16350_MSC_CTRL_DATA_RDY_POL_HIGH;
- msc &= ~ADIS16350_MSC_CTRL_DATA_RDY_DIO2;
-
- if (enable)
- msc |= ADIS16350_MSC_CTRL_DATA_RDY_EN;
- else
- msc &= ~ADIS16350_MSC_CTRL_DATA_RDY_EN;
-
- ret = adis16350_spi_write_reg_16(dev, ADIS16350_MSC_CTRL, msc);
- if (ret)
- goto error_ret;
-
-error_ret:
- return ret;
-}
-
-/* Power down the device */
-static int adis16350_stop_device(struct device *dev)
-{
- int ret;
- u16 val = ADIS16350_SLP_CNT_POWER_OFF;
-
- ret = adis16350_spi_write_reg_16(dev, ADIS16350_SLP_CNT, val);
- if (ret)
- dev_err(dev, "problem with turning device off: SLP_CNT");
-
- return ret;
-}
-
-static int adis16350_self_test(struct device *dev)
-{
- int ret;
- ret = adis16350_spi_write_reg_16(dev,
- ADIS16350_MSC_CTRL,
- ADIS16350_MSC_CTRL_MEM_TEST);
- if (ret) {
- dev_err(dev, "problem starting self test");
- goto err_ret;
- }
-
- adis16350_check_status(dev);
-
-err_ret:
- return ret;
-}
-
-static int adis16350_check_status(struct device *dev)
-{
- u16 status;
- int ret;
-
- ret = adis16350_spi_read_reg_16(dev, ADIS16350_DIAG_STAT, &status);
-
- if (ret < 0) {
- dev_err(dev, "Reading status failed\n");
- goto error_ret;
- }
- ret = status;
- if (status & ADIS16350_DIAG_STAT_ZACCL_FAIL)
- dev_err(dev, "Z-axis accelerometer self-test failure\n");
- if (status & ADIS16350_DIAG_STAT_YACCL_FAIL)
- dev_err(dev, "Y-axis accelerometer self-test failure\n");
- if (status & ADIS16350_DIAG_STAT_XACCL_FAIL)
- dev_err(dev, "X-axis accelerometer self-test failure\n");
- if (status & ADIS16350_DIAG_STAT_XGYRO_FAIL)
- dev_err(dev, "X-axis gyroscope self-test failure\n");
- if (status & ADIS16350_DIAG_STAT_YGYRO_FAIL)
- dev_err(dev, "Y-axis gyroscope self-test failure\n");
- if (status & ADIS16350_DIAG_STAT_ZGYRO_FAIL)
- dev_err(dev, "Z-axis gyroscope self-test failure\n");
- if (status & ADIS16350_DIAG_STAT_ALARM2)
- dev_err(dev, "Alarm 2 active\n");
- if (status & ADIS16350_DIAG_STAT_ALARM1)
- dev_err(dev, "Alarm 1 active\n");
- if (status & ADIS16350_DIAG_STAT_FLASH_CHK)
- dev_err(dev, "Flash checksum error\n");
- if (status & ADIS16350_DIAG_STAT_SELF_TEST)
- dev_err(dev, "Self test error\n");
- if (status & ADIS16350_DIAG_STAT_OVERFLOW)
- dev_err(dev, "Sensor overrange\n");
- if (status & ADIS16350_DIAG_STAT_SPI_FAIL)
- dev_err(dev, "SPI failure\n");
- if (status & ADIS16350_DIAG_STAT_FLASH_UPT)
- dev_err(dev, "Flash update failed\n");
- if (status & ADIS16350_DIAG_STAT_POWER_HIGH)
- dev_err(dev, "Power supply above 5.25V\n");
- if (status & ADIS16350_DIAG_STAT_POWER_LOW)
- dev_err(dev, "Power supply below 4.75V\n");
-
-error_ret:
- return ret;
-}
-
-static int adis16350_initial_setup(struct adis16350_state *st)
-{
- int ret;
- u16 smp_prd;
- struct device *dev = &st->indio_dev->dev;
-
- /* use low spi speed for init */
- st->us->max_speed_hz = ADIS16350_SPI_SLOW;
- st->us->mode = SPI_MODE_3;
- spi_setup(st->us);
-
- /* Disable IRQ */
- ret = adis16350_set_irq(dev, false);
- if (ret) {
- dev_err(dev, "disable irq failed");
- goto err_ret;
- }
-
- /* Do self test */
- ret = adis16350_self_test(dev);
- if (ret) {
- dev_err(dev, "self test failure");
- goto err_ret;
- }
-
- /* Read status register to check the result */
- ret = adis16350_check_status(dev);
- if (ret) {
- adis16350_reset(dev);
- dev_err(dev, "device not playing ball -> reset");
- msleep(ADIS16350_STARTUP_DELAY);
- ret = adis16350_check_status(dev);
- if (ret) {
- dev_err(dev, "giving up");
- goto err_ret;
- }
- }
-
- printk(KERN_INFO DRIVER_NAME ": at CS%d (irq %d)\n",
- st->us->chip_select, st->us->irq);
-
- /* use high spi speed if possible */
- ret = adis16350_spi_read_reg_16(dev, ADIS16350_SMPL_PRD, &smp_prd);
- if (!ret && (smp_prd & ADIS16350_SMPL_PRD_DIV_MASK) < 0x0A) {
- st->us->max_speed_hz = ADIS16350_SPI_SLOW;
- spi_setup(st->us);
- }
-
-err_ret:
- return ret;
-}
-
-static IIO_DEV_ATTR_GYRO_X_CALIBBIAS(S_IWUSR | S_IRUGO,
- adis16350_read_12bit_signed,
- adis16350_write_16bit,
- ADIS16350_XGYRO_OFF);
-
-static IIO_DEV_ATTR_GYRO_Y_CALIBBIAS(S_IWUSR | S_IRUGO,
- adis16350_read_12bit_signed,
- adis16350_write_16bit,
- ADIS16350_YGYRO_OFF);
-
-static IIO_DEV_ATTR_GYRO_Z_CALIBBIAS(S_IWUSR | S_IRUGO,
- adis16350_read_12bit_signed,
- adis16350_write_16bit,
- ADIS16350_ZGYRO_OFF);
-
-static IIO_DEV_ATTR_ACCEL_X_CALIBBIAS(S_IWUSR | S_IRUGO,
- adis16350_read_12bit_signed,
- adis16350_write_16bit,
- ADIS16350_XACCL_OFF);
-
-static IIO_DEV_ATTR_ACCEL_Y_CALIBBIAS(S_IWUSR | S_IRUGO,
- adis16350_read_12bit_signed,
- adis16350_write_16bit,
- ADIS16350_YACCL_OFF);
-
-static IIO_DEV_ATTR_ACCEL_Z_CALIBBIAS(S_IWUSR | S_IRUGO,
- adis16350_read_12bit_signed,
- adis16350_write_16bit,
- ADIS16350_ZACCL_OFF);
-
-static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16350_read_12bit_unsigned,
- ADIS16350_SUPPLY_OUT);
-static IIO_CONST_ATTR_IN_NAMED_SCALE(0, supply, "0.002418");
-
-static IIO_DEV_ATTR_GYRO_X(adis16350_read_14bit_signed,
- ADIS16350_XGYRO_OUT);
-static IIO_DEV_ATTR_GYRO_Y(adis16350_read_14bit_signed,
- ADIS16350_YGYRO_OUT);
-static IIO_DEV_ATTR_GYRO_Z(adis16350_read_14bit_signed,
- ADIS16350_ZGYRO_OUT);
-static IIO_CONST_ATTR_GYRO_SCALE("0.00127862821");
-
-static IIO_DEV_ATTR_ACCEL_X(adis16350_read_14bit_signed,
- ADIS16350_XACCL_OUT);
-static IIO_DEV_ATTR_ACCEL_Y(adis16350_read_14bit_signed,
- ADIS16350_YACCL_OUT);
-static IIO_DEV_ATTR_ACCEL_Z(adis16350_read_14bit_signed,
- ADIS16350_ZACCL_OUT);
-static IIO_CONST_ATTR_ACCEL_SCALE("0.0247323713");
-
-static IIO_DEVICE_ATTR(temp_x_raw, S_IRUGO, adis16350_read_12bit_signed,
- NULL, ADIS16350_XTEMP_OUT);
-static IIO_DEVICE_ATTR(temp_y_raw, S_IRUGO, adis16350_read_12bit_signed,
- NULL, ADIS16350_YTEMP_OUT);
-static IIO_DEVICE_ATTR(temp_z_raw, S_IRUGO, adis16350_read_12bit_signed,
- NULL, ADIS16350_ZTEMP_OUT);
-static IIO_CONST_ATTR_TEMP_SCALE("0.14534");
-static IIO_CONST_ATTR_TEMP_OFFSET("198.16");
-
-static IIO_DEV_ATTR_IN_RAW(1, adis16350_read_12bit_unsigned,
- ADIS16350_AUX_ADC);
-static IIO_CONST_ATTR(in1_scale, "0.000806");
-
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
- adis16350_read_frequency,
- adis16350_write_frequency);
-
-static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL,
- adis16350_write_reset, 0);
-
-static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("409 546 819 1638");
-
-static IIO_CONST_ATTR_NAME("adis16350");
-
-static struct attribute *adis16350_attributes[] = {
- &iio_dev_attr_gyro_x_calibbias.dev_attr.attr,
- &iio_dev_attr_gyro_y_calibbias.dev_attr.attr,
- &iio_dev_attr_gyro_z_calibbias.dev_attr.attr,
- &iio_dev_attr_accel_x_calibbias.dev_attr.attr,
- &iio_dev_attr_accel_y_calibbias.dev_attr.attr,
- &iio_dev_attr_accel_z_calibbias.dev_attr.attr,
- &iio_dev_attr_in0_supply_raw.dev_attr.attr,
- &iio_const_attr_in0_supply_scale.dev_attr.attr,
- &iio_dev_attr_gyro_x_raw.dev_attr.attr,
- &iio_dev_attr_gyro_y_raw.dev_attr.attr,
- &iio_dev_attr_gyro_z_raw.dev_attr.attr,
- &iio_const_attr_gyro_scale.dev_attr.attr,
- &iio_dev_attr_accel_x_raw.dev_attr.attr,
- &iio_dev_attr_accel_y_raw.dev_attr.attr,
- &iio_dev_attr_accel_z_raw.dev_attr.attr,
- &iio_const_attr_accel_scale.dev_attr.attr,
- &iio_dev_attr_temp_x_raw.dev_attr.attr,
- &iio_dev_attr_temp_y_raw.dev_attr.attr,
- &iio_dev_attr_temp_z_raw.dev_attr.attr,
- &iio_const_attr_temp_scale.dev_attr.attr,
- &iio_const_attr_temp_offset.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_const_attr_in1_scale.dev_attr.attr,
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
- &iio_const_attr_sampling_frequency_available.dev_attr.attr,
- &iio_dev_attr_reset.dev_attr.attr,
- &iio_const_attr_name.dev_attr.attr,
- NULL
-};
-
-static const struct attribute_group adis16350_attribute_group = {
- .attrs = adis16350_attributes,
-};
-
-static struct attribute *adis16350_event_attributes[] = {
- NULL,
-};
-
-static struct attribute_group adis16350_event_attribute_group = {
- .attrs = adis16350_event_attributes,
-};
-
-static int __devinit adis16350_probe(struct spi_device *spi)
-{
- int ret, regdone = 0;
- struct adis16350_state *st = kzalloc(sizeof *st, GFP_KERNEL);
- if (!st) {
- ret = -ENOMEM;
- goto error_ret;
- }
- /* this is only used for removal purposes */
- spi_set_drvdata(spi, st);
-
- /* Allocate the comms buffers */
- st->rx = kzalloc(sizeof(*st->rx)*ADIS16350_MAX_RX, GFP_KERNEL);
- if (st->rx == NULL) {
- ret = -ENOMEM;
- goto error_free_st;
- }
- st->tx = kzalloc(sizeof(*st->tx)*ADIS16350_MAX_TX, GFP_KERNEL);
- if (st->tx == NULL) {
- ret = -ENOMEM;
- goto error_free_rx;
- }
- st->us = spi;
- mutex_init(&st->buf_lock);
- /* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
- if (st->indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_free_tx;
- }
-
- st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->num_interrupt_lines = 1;
- st->indio_dev->event_attrs = &adis16350_event_attribute_group;
- st->indio_dev->attrs = &adis16350_attribute_group;
- st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
- st->indio_dev->modes = INDIO_DIRECT_MODE;
-
- ret = adis16350_configure_ring(st->indio_dev);
- if (ret)
- goto error_free_dev;
-
- ret = iio_device_register(st->indio_dev);
- if (ret)
- goto error_unreg_ring_funcs;
- regdone = 1;
-
- ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
- if (ret) {
- printk(KERN_ERR "failed to initialize the ring\n");
- goto error_unreg_ring_funcs;
- }
-
- if (spi->irq) {
- ret = iio_register_interrupt_line(spi->irq,
- st->indio_dev,
- 0,
- IRQF_TRIGGER_RISING,
- "adis16350");
- if (ret)
- goto error_uninitialize_ring;
-
- ret = adis16350_probe_trigger(st->indio_dev);
- if (ret)
- goto error_unregister_line;
- }
-
- /* Get the device into a sane initial state */
- ret = adis16350_initial_setup(st);
- if (ret)
- goto error_remove_trigger;
- return 0;
-
-error_remove_trigger:
- adis16350_remove_trigger(st->indio_dev);
-error_unregister_line:
- if (spi->irq)
- iio_unregister_interrupt_line(st->indio_dev, 0);
-error_uninitialize_ring:
- iio_ring_buffer_unregister(st->indio_dev->ring);
-error_unreg_ring_funcs:
- adis16350_unconfigure_ring(st->indio_dev);
-error_free_dev:
- if (regdone)
- iio_device_unregister(st->indio_dev);
- else
- iio_free_device(st->indio_dev);
-error_free_tx:
- kfree(st->tx);
-error_free_rx:
- kfree(st->rx);
-error_free_st:
- kfree(st);
-error_ret:
- return ret;
-}
-
-static int adis16350_remove(struct spi_device *spi)
-{
- int ret;
- struct adis16350_state *st = spi_get_drvdata(spi);
- struct iio_dev *indio_dev = st->indio_dev;
-
- ret = adis16350_stop_device(&(indio_dev->dev));
- if (ret)
- goto err_ret;
-
- flush_scheduled_work();
-
- adis16350_remove_trigger(indio_dev);
- if (spi->irq)
- iio_unregister_interrupt_line(indio_dev, 0);
-
- iio_ring_buffer_unregister(indio_dev->ring);
- iio_device_unregister(indio_dev);
- adis16350_unconfigure_ring(indio_dev);
- kfree(st->tx);
- kfree(st->rx);
- kfree(st);
-
- return 0;
-
-err_ret:
- return ret;
-}
-
-static const struct spi_device_id adis16350_id[] = {
- {"adis16350", 0},
- {"adis16354", 0},
- {"adis16355", 0},
- {"adis16360", 0},
- {"adis16362", 0},
- {"adis16364", 0},
- {"adis16365", 0},
- {}
-};
-
-static struct spi_driver adis16350_driver = {
- .driver = {
- .name = "adis16350",
- .owner = THIS_MODULE,
- },
- .probe = adis16350_probe,
- .remove = __devexit_p(adis16350_remove),
- .id_table = adis16350_id,
-};
-
-static __init int adis16350_init(void)
-{
- return spi_register_driver(&adis16350_driver);
-}
-module_init(adis16350_init);
-
-static __exit void adis16350_exit(void)
-{
- spi_unregister_driver(&adis16350_driver);
-}
-module_exit(adis16350_exit);
-
-MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
-MODULE_DESCRIPTION("Analog Devices ADIS16350/54/55/60/62/64/65 IMU SPI driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/imu/adis16350_ring.c b/drivers/staging/iio/imu/adis16350_ring.c
deleted file mode 100644
index 56b70cfb5822..000000000000
--- a/drivers/staging/iio/imu/adis16350_ring.c
+++ /dev/null
@@ -1,236 +0,0 @@
-#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 "adis16350.h"
-
-static IIO_SCAN_EL_C(in0_supply, ADIS16350_SCAN_SUPPLY,
- ADIS16350_SUPPLY_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in0_supply, u, 12, 16);
-
-static IIO_SCAN_EL_C(gyro_x, ADIS16350_SCAN_GYRO_X, ADIS16350_XGYRO_OUT, NULL);
-static IIO_SCAN_EL_C(gyro_y, ADIS16350_SCAN_GYRO_Y, ADIS16350_YGYRO_OUT, NULL);
-static IIO_SCAN_EL_C(gyro_z, ADIS16350_SCAN_GYRO_Z, ADIS16350_ZGYRO_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(gyro, s, 14, 16);
-
-static IIO_SCAN_EL_C(accel_x, ADIS16350_SCAN_ACC_X, ADIS16350_XACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_y, ADIS16350_SCAN_ACC_Y, ADIS16350_YACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_z, ADIS16350_SCAN_ACC_Z, ADIS16350_ZACCL_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(accel, s, 14, 16);
-
-static IIO_SCAN_EL_C(temp_x, ADIS16350_SCAN_TEMP_X, ADIS16350_XTEMP_OUT, NULL);
-static IIO_SCAN_EL_C(temp_y, ADIS16350_SCAN_TEMP_Y, ADIS16350_YTEMP_OUT, NULL);
-static IIO_SCAN_EL_C(temp_z, ADIS16350_SCAN_TEMP_Z, ADIS16350_ZTEMP_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(temp, s, 12, 16);
-
-static IIO_SCAN_EL_C(in1, ADIS16350_SCAN_ADC_0, ADIS16350_AUX_ADC, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in1, u, 12, 16);
-
-static IIO_SCAN_EL_TIMESTAMP(11);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
-
-static struct attribute *adis16350_scan_el_attrs[] = {
- &iio_scan_el_in0_supply.dev_attr.attr,
- &iio_const_attr_in0_supply_index.dev_attr.attr,
- &iio_const_attr_in0_supply_type.dev_attr.attr,
- &iio_scan_el_gyro_x.dev_attr.attr,
- &iio_const_attr_gyro_x_index.dev_attr.attr,
- &iio_scan_el_gyro_y.dev_attr.attr,
- &iio_const_attr_gyro_y_index.dev_attr.attr,
- &iio_scan_el_gyro_z.dev_attr.attr,
- &iio_const_attr_gyro_z_index.dev_attr.attr,
- &iio_const_attr_gyro_type.dev_attr.attr,
- &iio_scan_el_accel_x.dev_attr.attr,
- &iio_const_attr_accel_x_index.dev_attr.attr,
- &iio_scan_el_accel_y.dev_attr.attr,
- &iio_const_attr_accel_y_index.dev_attr.attr,
- &iio_scan_el_accel_z.dev_attr.attr,
- &iio_const_attr_accel_z_index.dev_attr.attr,
- &iio_const_attr_accel_type.dev_attr.attr,
- &iio_scan_el_temp_x.dev_attr.attr,
- &iio_const_attr_temp_x_index.dev_attr.attr,
- &iio_scan_el_temp_y.dev_attr.attr,
- &iio_const_attr_temp_y_index.dev_attr.attr,
- &iio_scan_el_temp_z.dev_attr.attr,
- &iio_const_attr_temp_z_index.dev_attr.attr,
- &iio_const_attr_temp_type.dev_attr.attr,
- &iio_scan_el_in1.dev_attr.attr,
- &iio_const_attr_in1_index.dev_attr.attr,
- &iio_const_attr_in1_type.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group adis16350_scan_el_group = {
- .attrs = adis16350_scan_el_attrs,
- .name = "scan_elements",
-};
-
-/**
- * adis16350_poll_func_th() top half interrupt handler called by trigger
- * @private_data: iio_dev
- **/
-static void adis16350_poll_func_th(struct iio_dev *indio_dev, s64 time)
-{
- struct adis16350_state *st = iio_dev_get_devdata(indio_dev);
- st->last_timestamp = time;
- schedule_work(&st->work_trigger_to_ring);
-}
-
-/**
- * adis16350_spi_read_burst() - read all data registers
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @rx: somewhere to pass back the value read (min size is 24 bytes)
- **/
-static int adis16350_spi_read_burst(struct device *dev, u8 *rx)
-{
- struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct adis16350_state *st = iio_dev_get_devdata(indio_dev);
- u32 old_speed_hz = st->us->max_speed_hz;
- int ret;
-
- struct spi_transfer xfers[] = {
- {
- .tx_buf = st->tx,
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 0,
- }, {
- .rx_buf = rx,
- .bits_per_word = 8,
- .len = 22,
- .cs_change = 0,
- },
- };
-
- mutex_lock(&st->buf_lock);
- st->tx[0] = ADIS16350_READ_REG(ADIS16350_GLOB_CMD);
- st->tx[1] = 0;
-
- spi_message_init(&msg);
- spi_message_add_tail(&xfers[0], &msg);
- spi_message_add_tail(&xfers[1], &msg);
-
- st->us->max_speed_hz = ADIS16350_SPI_BURST;
- spi_setup(st->us);
-
- ret = spi_sync(st->us, &msg);
- if (ret)
- dev_err(&st->us->dev, "problem when burst reading");
-
- st->us->max_speed_hz = old_speed_hz;
- spi_setup(st->us);
- mutex_unlock(&st->buf_lock);
- return ret;
-}
-
-/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
- * specific to be rolled into the core.
- */
-static void adis16350_trigger_bh_to_ring(struct work_struct *work_s)
-{
- struct adis16350_state *st
- = container_of(work_s, struct adis16350_state,
- work_trigger_to_ring);
- struct iio_ring_buffer *ring = st->indio_dev->ring;
-
- int i = 0;
- s16 *data;
- size_t datasize = ring->access.get_bytes_per_datum(ring);
-
- data = kmalloc(datasize , GFP_KERNEL);
- if (data == NULL) {
- dev_err(&st->us->dev, "memory alloc failed in ring bh");
- return;
- }
-
- if (ring->scan_count)
- if (adis16350_spi_read_burst(&st->indio_dev->dev, st->rx) >= 0)
- for (; i < ring->scan_count; i++)
- data[i] = be16_to_cpup(
- (__be16 *)&(st->rx[i*2]));
-
- /* Guaranteed to be aligned with 8 byte boundary */
- if (ring->scan_timestamp)
- *((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
-
- ring->access.store_to(ring,
- (u8 *)data,
- st->last_timestamp);
-
- iio_trigger_notify_done(st->indio_dev->trig);
- kfree(data);
-
- return;
-}
-
-void adis16350_unconfigure_ring(struct iio_dev *indio_dev)
-{
- kfree(indio_dev->pollfunc);
- iio_sw_rb_free(indio_dev->ring);
-}
-
-int adis16350_configure_ring(struct iio_dev *indio_dev)
-{
- int ret = 0;
- struct adis16350_state *st = indio_dev->dev_data;
- struct iio_ring_buffer *ring;
- INIT_WORK(&st->work_trigger_to_ring, adis16350_trigger_bh_to_ring);
-
- ring = iio_sw_rb_allocate(indio_dev);
- if (!ring) {
- ret = -ENOMEM;
- return ret;
- }
- indio_dev->ring = ring;
- /* Effectively select the ring buffer implementation */
- iio_ring_sw_register_funcs(&ring->access);
- ring->bpe = 2;
- ring->scan_el_attrs = &adis16350_scan_el_group;
- ring->scan_timestamp = true;
- ring->preenable = &iio_sw_ring_preenable;
- ring->postenable = &iio_triggered_ring_postenable;
- ring->predisable = &iio_triggered_ring_predisable;
- ring->owner = THIS_MODULE;
-
- /* Set default scan mode */
- iio_scan_mask_set(ring, iio_scan_el_in0_supply.number);
- iio_scan_mask_set(ring, iio_scan_el_gyro_x.number);
- iio_scan_mask_set(ring, iio_scan_el_gyro_y.number);
- iio_scan_mask_set(ring, iio_scan_el_gyro_z.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_x.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_y.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_z.number);
- iio_scan_mask_set(ring, iio_scan_el_temp_x.number);
- iio_scan_mask_set(ring, iio_scan_el_temp_y.number);
- iio_scan_mask_set(ring, iio_scan_el_temp_z.number);
- iio_scan_mask_set(ring, iio_scan_el_in1.number);
-
- ret = iio_alloc_pollfunc(indio_dev, NULL, &adis16350_poll_func_th);
- if (ret)
- goto error_iio_sw_rb_free;
-
- indio_dev->modes |= INDIO_RING_TRIGGERED;
- return 0;
-
-error_iio_sw_rb_free:
- iio_sw_rb_free(indio_dev->ring);
- return ret;
-}
-
diff --git a/drivers/staging/iio/imu/adis16350_trigger.c b/drivers/staging/iio/imu/adis16350_trigger.c
deleted file mode 100644
index 739b7ecb2e7c..000000000000
--- a/drivers/staging/iio/imu/adis16350_trigger.c
+++ /dev/null
@@ -1,125 +0,0 @@
-#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 "adis16350.h"
-
-/**
- * adis16350_data_rdy_trig_poll() the event handler for the data rdy trig
- **/
-static int adis16350_data_rdy_trig_poll(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct adis16350_state *st = iio_dev_get_devdata(dev_info);
- struct iio_trigger *trig = st->trig;
-
- iio_trigger_poll(trig, timestamp);
-
- return IRQ_HANDLED;
-}
-
-IIO_EVENT_SH(data_rdy_trig, &adis16350_data_rdy_trig_poll);
-
-static IIO_TRIGGER_NAME_ATTR;
-
-static struct attribute *adis16350_trigger_attrs[] = {
- &dev_attr_name.attr,
- NULL,
-};
-
-static const struct attribute_group adis16350_trigger_attr_group = {
- .attrs = adis16350_trigger_attrs,
-};
-
-/**
- * adis16350_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16350_data_rdy_trigger_set_state(struct iio_trigger *trig,
- bool state)
-{
- struct adis16350_state *st = trig->private_data;
- struct iio_dev *indio_dev = st->indio_dev;
- int ret = 0;
-
- dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
- ret = adis16350_set_irq(&st->indio_dev->dev, state);
- if (state == false) {
- iio_remove_event_from_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]
- ->ev_list);
- /* possible quirk with handler currently worked around
- by ensuring the work queue is empty */
- flush_scheduled_work();
- } else {
- iio_add_event_to_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]->ev_list);
- }
- return ret;
-}
-
-/**
- * adis16350_trig_try_reen() try renabling irq for data rdy trigger
- * @trig: the datardy trigger
- **/
-static int adis16350_trig_try_reen(struct iio_trigger *trig)
-{
- struct adis16350_state *st = trig->private_data;
- enable_irq(st->us->irq);
- /* irq reenabled so success! */
- return 0;
-}
-
-int adis16350_probe_trigger(struct iio_dev *indio_dev)
-{
- int ret;
- struct adis16350_state *st = indio_dev->dev_data;
-
- st->trig = iio_allocate_trigger();
- st->trig->name = kasprintf(GFP_KERNEL,
- "adis16350-dev%d",
- indio_dev->id);
- if (!st->trig->name) {
- ret = -ENOMEM;
- goto error_free_trig;
- }
- st->trig->dev.parent = &st->us->dev;
- st->trig->owner = THIS_MODULE;
- st->trig->private_data = st;
- st->trig->set_trigger_state = &adis16350_data_rdy_trigger_set_state;
- st->trig->try_reenable = &adis16350_trig_try_reen;
- st->trig->control_attrs = &adis16350_trigger_attr_group;
- ret = iio_trigger_register(st->trig);
-
- /* select default trigger */
- indio_dev->trig = st->trig;
- if (ret)
- goto error_free_trig_name;
-
- return 0;
-
-error_free_trig_name:
- kfree(st->trig->name);
-error_free_trig:
- iio_free_trigger(st->trig);
-
- return ret;
-}
-
-void adis16350_remove_trigger(struct iio_dev *indio_dev)
-{
- struct adis16350_state *state = indio_dev->dev_data;
-
- iio_trigger_unregister(state->trig);
- kfree(state->trig->name);
- iio_free_trigger(state->trig);
-}
diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h
index e328bcc5922f..db184d11dfc0 100644
--- a/drivers/staging/iio/imu/adis16400.h
+++ b/drivers/staging/iio/imu/adis16400.h
@@ -37,6 +37,10 @@
#define ADIS16400_TEMP_OUT 0x16 /* Temperature output */
#define ADIS16400_AUX_ADC 0x18 /* Auxiliary ADC measurement */
+#define ADIS16350_XTEMP_OUT 0x10 /* X-axis gyroscope temperature measurement */
+#define ADIS16350_YTEMP_OUT 0x12 /* Y-axis gyroscope temperature measurement */
+#define ADIS16350_ZTEMP_OUT 0x14 /* Z-axis gyroscope temperature measurement */
+
/* Calibration parameters */
#define ADIS16400_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */
#define ADIS16400_YGYRO_OFF 0x1C /* Y-axis gyroscope bias offset factor */
@@ -68,7 +72,6 @@
#define ADIS16400_AUX_DAC 0x4A /* Auxiliary DAC data */
#define ADIS16400_PRODUCT_ID 0x56 /* Product identifier */
-#define ADIS16400_PRODUCT_ID_DEFAULT 0x4015 /* Datasheet says 0x4105, I get 0x4015 */
#define ADIS16400_ERROR_ACTIVE (1<<14)
#define ADIS16400_NEW_DATA (1<<14)
@@ -123,13 +126,21 @@
#define ADIS16400_SPI_BURST (u32)(1000 * 1000)
#define ADIS16400_SPI_FAST (u32)(2000 * 1000)
+#define ADIS16400_HAS_PROD_ID 1
+#define ADIS16400_NO_BURST 2
+struct adis16400_chip_info {
+ const struct iio_chan_spec *channels;
+ const int num_channels;
+ const int product_id;
+ const long flags;
+ unsigned int gyro_scale_micro;
+ unsigned int accel_scale_micro;
+ unsigned long default_scan_mask;
+};
+
/**
* struct adis16400_state - device instance specific data
* @us: actual spi_device
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter: used to check if new interrupt has been triggered
- * @last_timestamp: passing timestamp from th to bh of interrupt handler
- * @indio_dev: industrial I/O device structure
* @trig: data ready trigger registered with iio
* @tx: transmit buffer
* @rx: receive buffer
@@ -137,16 +148,15 @@
**/
struct adis16400_state {
struct spi_device *us;
- struct work_struct work_trigger_to_ring;
- s64 last_timestamp;
- struct iio_dev *indio_dev;
struct iio_trigger *trig;
- u8 *tx;
- u8 *rx;
struct mutex buf_lock;
+ struct adis16400_chip_info *variant;
+
+ u8 tx[ADIS16400_MAX_TX] ____cacheline_aligned;
+ u8 rx[ADIS16400_MAX_RX] ____cacheline_aligned;
};
-int adis16400_set_irq(struct device *dev, bool enable);
+int adis16400_set_irq(struct iio_dev *indio_dev, bool enable);
#ifdef CONFIG_IIO_RING_BUFFER
/* At the moment triggers are only used for ring buffer
@@ -161,10 +171,16 @@ int adis16400_set_irq(struct device *dev, bool enable);
#define ADIS16400_SCAN_ACC_Y 5
#define ADIS16400_SCAN_ACC_Z 6
#define ADIS16400_SCAN_MAGN_X 7
+#define ADIS16350_SCAN_TEMP_X 7
#define ADIS16400_SCAN_MAGN_Y 8
+#define ADIS16350_SCAN_TEMP_Y 8
#define ADIS16400_SCAN_MAGN_Z 9
+#define ADIS16350_SCAN_TEMP_Z 9
#define ADIS16400_SCAN_TEMP 10
+#define ADIS16350_SCAN_ADC_0 10
#define ADIS16400_SCAN_ADC_0 11
+#define ADIS16300_SCAN_INCLI_X 12
+#define ADIS16300_SCAN_INCLI_Y 13
void adis16400_remove_trigger(struct iio_dev *indio_dev);
int adis16400_probe_trigger(struct iio_dev *indio_dev);
diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
index 540bde69cc3b..fe89802e3fe7 100644
--- a/drivers/staging/iio/imu/adis16400_core.c
+++ b/drivers/staging/iio/imu/adis16400_core.c
@@ -38,7 +38,17 @@
#define DRIVER_NAME "adis16400"
-static int adis16400_check_status(struct device *dev);
+enum adis16400_chip_variant {
+ ADIS16300,
+ ADIS16350,
+ ADIS16360,
+ ADIS16362,
+ ADIS16364,
+ ADIS16365,
+ ADIS16400,
+};
+
+static int adis16400_check_status(struct iio_dev *indio_dev);
/* At the moment the spi framework doesn't allow global setting of cs_change.
* It's in the likely to be added comment at the top of spi.h.
@@ -51,13 +61,12 @@ static int adis16400_check_status(struct device *dev);
* @reg_address: the address of the register to be written
* @val: the value to write
**/
-static int adis16400_spi_write_reg_8(struct device *dev,
- u8 reg_address,
- u8 val)
+static int adis16400_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 adis16400_state *st = iio_dev_get_devdata(indio_dev);
+ struct adis16400_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
st->tx[0] = ADIS16400_WRITE_REG(reg_address);
@@ -76,14 +85,13 @@ static int adis16400_spi_write_reg_8(struct device *dev,
* is assumed to have address one greater.
* @val: value to be written
**/
-static int adis16400_spi_write_reg_16(struct device *dev,
+static int adis16400_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 adis16400_state *st = iio_dev_get_devdata(indio_dev);
+ struct adis16400_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[] = {
{
.tx_buf = st->tx,
@@ -114,18 +122,17 @@ static int adis16400_spi_write_reg_16(struct device *dev,
/**
* adis16400_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @indio_dev: iio 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 adis16400_spi_read_reg_16(struct device *dev,
+static int adis16400_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 adis16400_state *st = iio_dev_get_devdata(indio_dev);
+ struct adis16400_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
{
@@ -163,100 +170,15 @@ error_ret:
return ret;
}
-static ssize_t adis16400_spi_read_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf,
- unsigned bits)
-{
- int ret;
- s16 val = 0;
- unsigned shift = 16 - bits;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
- ret = adis16400_spi_read_reg_16(dev, this_attr->address, (u16 *)&val);
- if (ret)
- return ret;
-
- if (val & ADIS16400_ERROR_ACTIVE)
- adis16400_check_status(dev);
- val = ((s16)(val << shift) >> shift);
- return sprintf(buf, "%d\n", val);
-}
-
-static ssize_t adis16400_read_12bit_unsigned(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int ret;
- u16 val = 0;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
- ret = adis16400_spi_read_reg_16(dev, this_attr->address, &val);
- if (ret)
- return ret;
-
- if (val & ADIS16400_ERROR_ACTIVE)
- adis16400_check_status(dev);
-
- return sprintf(buf, "%u\n", val & 0x0FFF);
-}
-
-static ssize_t adis16400_read_14bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ssize_t ret;
-
- /* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
- ret = adis16400_spi_read_signed(dev, attr, buf, 14);
- mutex_unlock(&indio_dev->mlock);
-
- return ret;
-}
-
-static ssize_t adis16400_read_12bit_signed(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ssize_t ret;
-
- /* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
- ret = adis16400_spi_read_signed(dev, attr, buf, 12);
- mutex_unlock(&indio_dev->mlock);
-
- return ret;
-}
-
-static ssize_t adis16400_write_16bit(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int ret;
- long val;
-
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- goto error_ret;
- ret = adis16400_spi_write_reg_16(dev, this_attr->address, val);
-
-error_ret:
- return ret ? ret : len;
-}
-
static ssize_t adis16400_read_frequency(struct device *dev,
struct device_attribute *attr,
char *buf)
{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
int ret, len = 0;
u16 t;
int sps;
- ret = adis16400_spi_read_reg_16(dev,
+ ret = adis16400_spi_read_reg_16(indio_dev,
ADIS16400_SMPL_PRD,
&t);
if (ret)
@@ -273,7 +195,7 @@ static ssize_t adis16400_write_frequency(struct device *dev,
size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct adis16400_state *st = iio_dev_get_devdata(indio_dev);
+ struct adis16400_state *st = iio_priv(indio_dev);
long val;
int ret;
u8 t;
@@ -293,7 +215,7 @@ static ssize_t adis16400_write_frequency(struct device *dev,
else
st->us->max_speed_hz = ADIS16400_SPI_FAST;
- ret = adis16400_spi_write_reg_8(dev,
+ ret = adis16400_spi_write_reg_8(indio_dev,
ADIS16400_SMPL_PRD,
t);
@@ -302,14 +224,14 @@ static ssize_t adis16400_write_frequency(struct device *dev,
return ret ? ret : len;
}
-static int adis16400_reset(struct device *dev)
+static int adis16400_reset(struct iio_dev *indio_dev)
{
int ret;
- ret = adis16400_spi_write_reg_8(dev,
+ ret = adis16400_spi_write_reg_8(indio_dev,
ADIS16400_GLOB_CMD,
ADIS16400_GLOB_CMD_SW_RESET);
if (ret)
- dev_err(dev, "problem resetting device");
+ dev_err(&indio_dev->dev, "problem resetting device");
return ret;
}
@@ -318,22 +240,24 @@ 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);
+
if (len < 1)
return -1;
switch (buf[0]) {
case '1':
case 'y':
case 'Y':
- return adis16400_reset(dev);
+ return adis16400_reset(indio_dev);
}
return -1;
}
-int adis16400_set_irq(struct device *dev, bool enable)
+int adis16400_set_irq(struct iio_dev *indio_dev, bool enable)
{
int ret;
u16 msc;
- ret = adis16400_spi_read_reg_16(dev, ADIS16400_MSC_CTRL, &msc);
+ ret = adis16400_spi_read_reg_16(indio_dev, ADIS16400_MSC_CTRL, &msc);
if (ret)
goto error_ret;
@@ -343,7 +267,7 @@ int adis16400_set_irq(struct device *dev, bool enable)
else
msc &= ~ADIS16400_MSC_CTRL_DATA_RDY_EN;
- ret = adis16400_spi_write_reg_16(dev, ADIS16400_MSC_CTRL, msc);
+ ret = adis16400_spi_write_reg_16(indio_dev, ADIS16400_MSC_CTRL, msc);
if (ret)
goto error_ret;
@@ -352,41 +276,45 @@ error_ret:
}
/* Power down the device */
-static int adis16400_stop_device(struct device *dev)
+static int adis16400_stop_device(struct iio_dev *indio_dev)
{
int ret;
u16 val = ADIS16400_SLP_CNT_POWER_OFF;
- ret = adis16400_spi_write_reg_16(dev, ADIS16400_SLP_CNT, val);
+ ret = adis16400_spi_write_reg_16(indio_dev, ADIS16400_SLP_CNT, val);
if (ret)
- dev_err(dev, "problem with turning device off: SLP_CNT");
+ dev_err(&indio_dev->dev,
+ "problem with turning device off: SLP_CNT");
return ret;
}
-static int adis16400_self_test(struct device *dev)
+static int adis16400_self_test(struct iio_dev *indio_dev)
{
int ret;
- ret = adis16400_spi_write_reg_16(dev,
+ ret = adis16400_spi_write_reg_16(indio_dev,
ADIS16400_MSC_CTRL,
ADIS16400_MSC_CTRL_MEM_TEST);
if (ret) {
- dev_err(dev, "problem starting self test");
+ dev_err(&indio_dev->dev, "problem starting self test");
goto err_ret;
}
+
msleep(ADIS16400_MTEST_DELAY);
- adis16400_check_status(dev);
+ adis16400_check_status(indio_dev);
err_ret:
return ret;
}
-static int adis16400_check_status(struct device *dev)
+static int adis16400_check_status(struct iio_dev *indio_dev)
{
u16 status;
int ret;
+ struct device *dev = &indio_dev->dev;
- ret = adis16400_spi_read_reg_16(dev, ADIS16400_DIAG_STAT, &status);
+ ret = adis16400_spi_read_reg_16(indio_dev,
+ ADIS16400_DIAG_STAT, &status);
if (ret < 0) {
dev_err(dev, "Reading status failed\n");
@@ -428,11 +356,12 @@ error_ret:
return ret;
}
-static int adis16400_initial_setup(struct adis16400_state *st)
+static int adis16400_initial_setup(struct iio_dev *indio_dev)
{
int ret;
u16 prod_id, smp_prd;
- struct device *dev = &st->indio_dev->dev;
+ struct device *dev = &indio_dev->dev;
+ struct adis16400_state *st = iio_priv(indio_dev);
/* use low spi speed for init */
st->us->max_speed_hz = ADIS16400_SPI_SLOW;
@@ -440,45 +369,46 @@ static int adis16400_initial_setup(struct adis16400_state *st)
spi_setup(st->us);
/* Disable IRQ */
- ret = adis16400_set_irq(dev, false);
+ ret = adis16400_set_irq(indio_dev, false);
if (ret) {
dev_err(dev, "disable irq failed");
goto err_ret;
}
/* Do self test */
- ret = adis16400_self_test(dev);
+ ret = adis16400_self_test(indio_dev);
if (ret) {
dev_err(dev, "self test failure");
goto err_ret;
}
/* Read status register to check the result */
- ret = adis16400_check_status(dev);
+ ret = adis16400_check_status(indio_dev);
if (ret) {
- adis16400_reset(dev);
+ adis16400_reset(indio_dev);
dev_err(dev, "device not playing ball -> reset");
msleep(ADIS16400_STARTUP_DELAY);
- ret = adis16400_check_status(dev);
+ ret = adis16400_check_status(indio_dev);
if (ret) {
dev_err(dev, "giving up");
goto err_ret;
}
}
+ if (st->variant->flags & ADIS16400_HAS_PROD_ID) {
+ ret = adis16400_spi_read_reg_16(indio_dev,
+ ADIS16400_PRODUCT_ID, &prod_id);
+ if (ret)
+ goto err_ret;
- ret = adis16400_spi_read_reg_16(dev, ADIS16400_PRODUCT_ID, &prod_id);
- if (ret)
- goto err_ret;
-
- if ((prod_id & 0xF000) != ADIS16400_PRODUCT_ID_DEFAULT)
- dev_warn(dev, "unknown product id");
-
-
- dev_info(dev, ": prod_id 0x%04x at CS%d (irq %d)\n",
- prod_id, st->us->chip_select, st->us->irq);
+ if ((prod_id & 0xF000) != st->variant->product_id)
+ dev_warn(dev, "incorrect id");
+ printk(KERN_INFO DRIVER_NAME ": prod_id 0x%04x at CS%d (irq %d)\n",
+ prod_id, st->us->chip_select, st->us->irq);
+ }
/* use high spi speed if possible */
- ret = adis16400_spi_read_reg_16(dev, ADIS16400_SMPL_PRD, &smp_prd);
+ ret = adis16400_spi_read_reg_16(indio_dev,
+ ADIS16400_SMPL_PRD, &smp_prd);
if (!ret && (smp_prd & ADIS16400_SMPL_PRD_DIV_MASK) < 0x0A) {
st->us->max_speed_hz = ADIS16400_SPI_SLOW;
spi_setup(st->us);
@@ -490,58 +420,6 @@ err_ret:
return ret;
}
-#define ADIS16400_DEV_ATTR_CALIBBIAS(_channel, _reg) \
- IIO_DEV_ATTR_##_channel##_CALIBBIAS(S_IWUSR | S_IRUGO, \
- adis16400_read_12bit_signed, \
- adis16400_write_16bit, \
- _reg)
-
-static ADIS16400_DEV_ATTR_CALIBBIAS(GYRO_X, ADIS16400_XGYRO_OFF);
-static ADIS16400_DEV_ATTR_CALIBBIAS(GYRO_Y, ADIS16400_YGYRO_OFF);
-static ADIS16400_DEV_ATTR_CALIBBIAS(GYRO_Z, ADIS16400_ZGYRO_OFF);
-
-static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_X, ADIS16400_XACCL_OFF);
-static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_Y, ADIS16400_YACCL_OFF);
-static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_Z, ADIS16400_ZACCL_OFF);
-
-
-static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16400_read_14bit_signed,
- ADIS16400_SUPPLY_OUT);
-static IIO_CONST_ATTR_IN_NAMED_SCALE(0, supply, "0.002418 V");
-
-static IIO_DEV_ATTR_GYRO_X(adis16400_read_14bit_signed,
- ADIS16400_XGYRO_OUT);
-static IIO_DEV_ATTR_GYRO_Y(adis16400_read_14bit_signed,
- ADIS16400_YGYRO_OUT);
-static IIO_DEV_ATTR_GYRO_Z(adis16400_read_14bit_signed,
- ADIS16400_ZGYRO_OUT);
-static IIO_CONST_ATTR(gyro_scale, "0.0008726646");
-
-static IIO_DEV_ATTR_ACCEL_X(adis16400_read_14bit_signed,
- ADIS16400_XACCL_OUT);
-static IIO_DEV_ATTR_ACCEL_Y(adis16400_read_14bit_signed,
- ADIS16400_YACCL_OUT);
-static IIO_DEV_ATTR_ACCEL_Z(adis16400_read_14bit_signed,
- ADIS16400_ZACCL_OUT);
-static IIO_CONST_ATTR(accel_scale, "0.0326561445");
-
-static IIO_DEV_ATTR_MAGN_X(adis16400_read_14bit_signed,
- ADIS16400_XMAGN_OUT);
-static IIO_DEV_ATTR_MAGN_Y(adis16400_read_14bit_signed,
- ADIS16400_YMAGN_OUT);
-static IIO_DEV_ATTR_MAGN_Z(adis16400_read_14bit_signed,
- ADIS16400_ZMAGN_OUT);
-static IIO_CONST_ATTR(magn_scale, "0.0005 Gs");
-
-
-static IIO_DEV_ATTR_TEMP_RAW(adis16400_read_12bit_signed);
-static IIO_CONST_ATTR_TEMP_OFFSET("198.16 K");
-static IIO_CONST_ATTR_TEMP_SCALE("0.14 K");
-
-static IIO_DEV_ATTR_IN_RAW(1, adis16400_read_12bit_unsigned,
- ADIS16400_AUX_ADC);
-static IIO_CONST_ATTR(in1_scale, "0.000806 V");
-
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
adis16400_read_frequency,
adis16400_write_frequency);
@@ -550,46 +428,273 @@ static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16400_write_reset, 0);
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("409 546 819 1638");
-static IIO_CONST_ATTR_NAME("adis16400");
+enum adis16400_chan {
+ in_supply,
+ gyro_x,
+ gyro_y,
+ gyro_z,
+ accel_x,
+ accel_y,
+ accel_z,
+ magn_x,
+ magn_y,
+ magn_z,
+ temp,
+ temp0, temp1, temp2,
+ in1
+};
-static struct attribute *adis16400_event_attributes[] = {
- NULL
+static u8 adis16400_addresses[16][2] = {
+ [in_supply] = { ADIS16400_SUPPLY_OUT, 0 },
+ [gyro_x] = { ADIS16400_XGYRO_OUT, ADIS16400_XGYRO_OFF },
+ [gyro_y] = { ADIS16400_YGYRO_OUT, ADIS16400_YGYRO_OFF },
+ [gyro_z] = { ADIS16400_ZGYRO_OUT, ADIS16400_ZGYRO_OFF },
+ [accel_x] = { ADIS16400_XACCL_OUT, ADIS16400_XACCL_OFF },
+ [accel_y] = { ADIS16400_YACCL_OUT, ADIS16400_YACCL_OFF },
+ [accel_z] = { ADIS16400_ZACCL_OUT, ADIS16400_ZACCL_OFF },
+ [magn_x] = { ADIS16400_XMAGN_OUT, 0 },
+ [magn_y] = { ADIS16400_YMAGN_OUT, 0 },
+ [magn_z] = { ADIS16400_ZMAGN_OUT, 0 },
+ [temp] = { ADIS16400_TEMP_OUT, 0 },
+ [temp0] = { ADIS16350_XTEMP_OUT },
+ [temp1] = { ADIS16350_YTEMP_OUT },
+ [temp2] = { ADIS16350_ZTEMP_OUT },
+ [in1] = { ADIS16400_AUX_ADC , 0 },
};
-static struct attribute_group adis16400_event_attribute_group = {
- .attrs = adis16400_event_attributes,
+static int adis16400_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):
+ mutex_lock(&indio_dev->mlock);
+ ret = adis16400_spi_write_reg_16(indio_dev,
+ adis16400_addresses[chan->address][1],
+ val);
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int adis16400_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long mask)
+{
+ struct adis16400_state *st = iio_priv(indio_dev);
+ int ret;
+ s16 val16;
+ int shift;
+
+ switch (mask) {
+ case 0:
+ mutex_lock(&indio_dev->mlock);
+ ret = adis16400_spi_read_reg_16(indio_dev,
+ adis16400_addresses[chan->address][0],
+ &val16);
+ if (ret) {
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+ }
+ val16 &= (1 << chan->scan_type.realbits) - 1;
+ if (chan->scan_type.sign == 's') {
+ shift = 16 - chan->scan_type.realbits;
+ val16 = (s16)(val16 << shift) >> shift;
+ }
+ *val = val16;
+ mutex_unlock(&indio_dev->mlock);
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ switch (chan->type) {
+ case IIO_GYRO:
+ *val = 0;
+ *val2 = st->variant->gyro_scale_micro;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_IN:
+ *val = 0;
+ if (chan->channel == 0)
+ *val2 = 2418;
+ else
+ *val2 = 806;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_ACCEL:
+ *val = 0;
+ *val2 = st->variant->accel_scale_micro;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_MAGN:
+ *val = 0;
+ *val2 = 500;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_TEMP:
+ *val = 0;
+ *val2 = 140000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+ case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ mutex_lock(&indio_dev->mlock);
+ ret = adis16400_spi_read_reg_16(indio_dev,
+ adis16400_addresses[chan->address][1],
+ &val16);
+ mutex_unlock(&indio_dev->mlock);
+ if (ret)
+ return ret;
+ val16 = ((val16 & 0xFFF) << 4) >> 4;
+ *val = val16;
+ return IIO_VAL_INT;
+ case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ /* currently only temperature */
+ *val = 198;
+ *val2 = 160000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static struct iio_chan_spec adis16400_channels[] = {
+ IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ in_supply, ADIS16400_SCAN_SUPPLY,
+ IIO_ST('u', 14, 16, 0), 0),
+ 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_MAGN, 1, 0, 0, NULL, 0, IIO_MOD_X,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ magn_x, ADIS16400_SCAN_MAGN_X, IIO_ST('s', 14, 16, 0), 0),
+ IIO_CHAN(IIO_MAGN, 1, 0, 0, NULL, 0, IIO_MOD_Y,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ magn_y, ADIS16400_SCAN_MAGN_Y, IIO_ST('s', 14, 16, 0), 0),
+ IIO_CHAN(IIO_MAGN, 1, 0, 0, NULL, 0, IIO_MOD_Z,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ magn_z, ADIS16400_SCAN_MAGN_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),
+ temp, ADIS16400_SCAN_TEMP, IIO_ST('s', 12, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ in1, ADIS16400_SCAN_ADC_0, IIO_ST('s', 12, 16, 0), 0),
+ IIO_CHAN_SOFT_TIMESTAMP(12)
+};
+
+static struct iio_chan_spec adis16350_channels[] = {
+ IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ 0, ADIS16400_SCAN_SUPPLY, IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_X,
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 1, 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),
+ 2, 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),
+ 3, 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),
+ 4, 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),
+ 0, 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),
+ 0, ADIS16400_SCAN_ACC_Z, IIO_ST('s', 14, 16, 0), 0),
+ IIO_CHAN(IIO_TEMP, 0, 1, 0, "x", 0, 0,
+ (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ 0, ADIS16350_SCAN_TEMP_X, IIO_ST('s', 12, 16, 0), 0),
+ IIO_CHAN(IIO_TEMP, 0, 1, 0, "y", 1, 0,
+ (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ 0, ADIS16350_SCAN_TEMP_Y, IIO_ST('s', 12, 16, 0), 0),
+ IIO_CHAN(IIO_TEMP, 0, 1, 0, "z", 2, 0,
+ (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ 0, ADIS16350_SCAN_TEMP_Z, IIO_ST('s', 12, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ 0, ADIS16350_SCAN_ADC_0, IIO_ST('s', 12, 16, 0), 0),
+ IIO_CHAN_SOFT_TIMESTAMP(11)
+};
+
+static struct iio_chan_spec adis16300_channels[] = {
+ IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ 0, ADIS16400_SCAN_SUPPLY, IIO_ST('u', 12, 16, 0), 0),
+ IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_X,
+ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 1, ADIS16400_SCAN_GYRO_X, 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),
+ 4, 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),
+ 0, 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),
+ 0, 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),
+ 0, ADIS16400_SCAN_TEMP, IIO_ST('s', 12, 16, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ 0, ADIS16350_SCAN_ADC_0, IIO_ST('s', 12, 16, 0), 0),
+ IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, ADIS16300_SCAN_INCLI_X, IIO_ST('s', 13, 16, 0), 0),
+ IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ 0, ADIS16300_SCAN_INCLI_Y, IIO_ST('s', 13, 16, 0), 0),
+ IIO_CHAN_SOFT_TIMESTAMP(14)
};
static struct attribute *adis16400_attributes[] = {
- &iio_dev_attr_gyro_x_calibbias.dev_attr.attr,
- &iio_dev_attr_gyro_y_calibbias.dev_attr.attr,
- &iio_dev_attr_gyro_z_calibbias.dev_attr.attr,
- &iio_dev_attr_accel_x_calibbias.dev_attr.attr,
- &iio_dev_attr_accel_y_calibbias.dev_attr.attr,
- &iio_dev_attr_accel_z_calibbias.dev_attr.attr,
- &iio_dev_attr_in0_supply_raw.dev_attr.attr,
- &iio_const_attr_in0_supply_scale.dev_attr.attr,
- &iio_dev_attr_gyro_x_raw.dev_attr.attr,
- &iio_dev_attr_gyro_y_raw.dev_attr.attr,
- &iio_dev_attr_gyro_z_raw.dev_attr.attr,
- &iio_const_attr_gyro_scale.dev_attr.attr,
- &iio_dev_attr_accel_x_raw.dev_attr.attr,
- &iio_dev_attr_accel_y_raw.dev_attr.attr,
- &iio_dev_attr_accel_z_raw.dev_attr.attr,
- &iio_const_attr_accel_scale.dev_attr.attr,
- &iio_dev_attr_magn_x_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_magn_scale.dev_attr.attr,
- &iio_dev_attr_temp_raw.dev_attr.attr,
- &iio_const_attr_temp_offset.dev_attr.attr,
- &iio_const_attr_temp_scale.dev_attr.attr,
- &iio_dev_attr_in1_raw.dev_attr.attr,
- &iio_const_attr_in1_scale.dev_attr.attr,
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_reset.dev_attr.attr,
- &iio_const_attr_name.dev_attr.attr,
NULL
};
@@ -597,101 +702,147 @@ static const struct attribute_group adis16400_attribute_group = {
.attrs = adis16400_attributes,
};
+static struct adis16400_chip_info adis16400_chips[] = {
+ [ADIS16300] = {
+ .channels = adis16300_channels,
+ .num_channels = ARRAY_SIZE(adis16300_channels),
+ .gyro_scale_micro = 873,
+ .accel_scale_micro = 5884,
+ .default_scan_mask = (1 << ADIS16400_SCAN_SUPPLY) |
+ (1 << ADIS16400_SCAN_GYRO_X) | (1 << ADIS16400_SCAN_ACC_X) |
+ (1 << ADIS16400_SCAN_ACC_Y) | (1 << ADIS16400_SCAN_ACC_Z) |
+ (1 << ADIS16400_SCAN_TEMP) | (1 << ADIS16400_SCAN_ADC_0) |
+ (1 << ADIS16300_SCAN_INCLI_X) | (1 << ADIS16300_SCAN_INCLI_Y) |
+ (1 << 14),
+ },
+ [ADIS16350] = {
+ .channels = adis16350_channels,
+ .num_channels = ARRAY_SIZE(adis16350_channels),
+ .gyro_scale_micro = 872664,
+ .accel_scale_micro = 24732,
+ .default_scan_mask = 0x7FF,
+ .flags = ADIS16400_NO_BURST,
+ },
+ [ADIS16360] = {
+ .channels = adis16350_channels,
+ .num_channels = ARRAY_SIZE(adis16350_channels),
+ .flags = ADIS16400_HAS_PROD_ID,
+ .product_id = 0x3FE8,
+ .gyro_scale_micro = 1279,
+ .accel_scale_micro = 24732,
+ .default_scan_mask = 0x7FF,
+ },
+ [ADIS16362] = {
+ .channels = adis16350_channels,
+ .num_channels = ARRAY_SIZE(adis16350_channels),
+ .flags = ADIS16400_HAS_PROD_ID,
+ .product_id = 0x3FEA,
+ .gyro_scale_micro = 1279,
+ .accel_scale_micro = 24732,
+ .default_scan_mask = 0x7FF,
+ },
+ [ADIS16364] = {
+ .channels = adis16350_channels,
+ .num_channels = ARRAY_SIZE(adis16350_channels),
+ .flags = ADIS16400_HAS_PROD_ID,
+ .product_id = 0x3FEC,
+ .gyro_scale_micro = 1279,
+ .accel_scale_micro = 24732,
+ .default_scan_mask = 0x7FF,
+ },
+ [ADIS16365] = {
+ .channels = adis16350_channels,
+ .num_channels = ARRAY_SIZE(adis16350_channels),
+ .flags = ADIS16400_HAS_PROD_ID,
+ .product_id = 0x3FED,
+ .gyro_scale_micro = 1279,
+ .accel_scale_micro = 24732,
+ .default_scan_mask = 0x7FF,
+ },
+ [ADIS16400] = {
+ .channels = adis16400_channels,
+ .num_channels = ARRAY_SIZE(adis16400_channels),
+ .flags = ADIS16400_HAS_PROD_ID,
+ .product_id = 0x4015,
+ .gyro_scale_micro = 873,
+ .accel_scale_micro = 32656,
+ .default_scan_mask = 0xFFF,
+ }
+};
+
+static const struct iio_info adis16400_info = {
+ .driver_module = THIS_MODULE,
+ .read_raw = &adis16400_read_raw,
+ .write_raw = &adis16400_write_raw,
+ .attrs = &adis16400_attribute_group,
+};
+
static int __devinit adis16400_probe(struct spi_device *spi)
{
int ret, regdone = 0;
- struct adis16400_state *st = kzalloc(sizeof *st, GFP_KERNEL);
- if (!st) {
+ struct adis16400_state *st;
+ struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
+ if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
}
+ st = iio_priv(indio_dev);
/* this is only used for removal purposes */
- spi_set_drvdata(spi, st);
+ spi_set_drvdata(spi, indio_dev);
- /* Allocate the comms buffers */
- st->rx = kzalloc(sizeof(*st->rx)*ADIS16400_MAX_RX, GFP_KERNEL);
- if (st->rx == NULL) {
- ret = -ENOMEM;
- goto error_free_st;
- }
- st->tx = kzalloc(sizeof(*st->tx)*ADIS16400_MAX_TX, GFP_KERNEL);
- if (st->tx == NULL) {
- ret = -ENOMEM;
- goto error_free_rx;
- }
st->us = spi;
mutex_init(&st->buf_lock);
- /* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
- if (st->indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_free_tx;
- }
- st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->num_interrupt_lines = 1;
- st->indio_dev->event_attrs = &adis16400_event_attribute_group;
- st->indio_dev->attrs = &adis16400_attribute_group;
- st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
- st->indio_dev->modes = INDIO_DIRECT_MODE;
-
- ret = adis16400_configure_ring(st->indio_dev);
+ /* setup the industrialio driver allocated elements */
+ st->variant = &adis16400_chips[spi_get_device_id(spi)->driver_data];
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->channels = st->variant->channels;
+ indio_dev->num_channels = st->variant->num_channels;
+ indio_dev->info = &adis16400_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ ret = adis16400_configure_ring(indio_dev);
if (ret)
goto error_free_dev;
- ret = iio_device_register(st->indio_dev);
+ ret = iio_device_register(indio_dev);
if (ret)
goto error_unreg_ring_funcs;
regdone = 1;
- ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
+ ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
+ st->variant->channels,
+ st->variant->num_channels);
if (ret) {
dev_err(&spi->dev, "failed to initialize the ring\n");
goto error_unreg_ring_funcs;
}
if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) {
- ret = iio_register_interrupt_line(spi->irq,
- st->indio_dev,
- 0,
- IRQF_TRIGGER_RISING,
- "adis16400");
+ ret = adis16400_probe_trigger(indio_dev);
if (ret)
goto error_uninitialize_ring;
-
- ret = adis16400_probe_trigger(st->indio_dev);
- if (ret)
- goto error_unregister_line;
}
/* Get the device into a sane initial state */
- ret = adis16400_initial_setup(st);
+ ret = adis16400_initial_setup(indio_dev);
if (ret)
goto error_remove_trigger;
return 0;
error_remove_trigger:
- if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
- adis16400_remove_trigger(st->indio_dev);
-error_unregister_line:
- if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
- iio_unregister_interrupt_line(st->indio_dev, 0);
+ if (indio_dev->modes & INDIO_RING_TRIGGERED)
+ adis16400_remove_trigger(indio_dev);
error_uninitialize_ring:
- iio_ring_buffer_unregister(st->indio_dev->ring);
+ iio_ring_buffer_unregister(indio_dev->ring);
error_unreg_ring_funcs:
- adis16400_unconfigure_ring(st->indio_dev);
+ adis16400_unconfigure_ring(indio_dev);
error_free_dev:
if (regdone)
- iio_device_unregister(st->indio_dev);
+ iio_device_unregister(indio_dev);
else
- iio_free_device(st->indio_dev);
-error_free_tx:
- kfree(st->tx);
-error_free_rx:
- kfree(st->rx);
-error_free_st:
- kfree(st);
+ iio_free_device(indio_dev);
error_ret:
return ret;
}
@@ -700,25 +851,16 @@ error_ret:
static int adis16400_remove(struct spi_device *spi)
{
int ret;
- struct adis16400_state *st = spi_get_drvdata(spi);
- struct iio_dev *indio_dev = st->indio_dev;
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
- ret = adis16400_stop_device(&(indio_dev->dev));
+ ret = adis16400_stop_device(indio_dev);
if (ret)
goto err_ret;
- flush_scheduled_work();
-
adis16400_remove_trigger(indio_dev);
- if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
- iio_unregister_interrupt_line(indio_dev, 0);
-
- iio_ring_buffer_unregister(st->indio_dev->ring);
+ iio_ring_buffer_unregister(indio_dev->ring);
adis16400_unconfigure_ring(indio_dev);
iio_device_unregister(indio_dev);
- kfree(st->tx);
- kfree(st->rx);
- kfree(st);
return 0;
@@ -726,11 +868,26 @@ err_ret:
return ret;
}
+static const struct spi_device_id adis16400_id[] = {
+ {"adis16300", ADIS16300},
+ {"adis16350", ADIS16350},
+ {"adis16354", ADIS16350},
+ {"adis16355", ADIS16350},
+ {"adis16360", ADIS16360},
+ {"adis16362", ADIS16362},
+ {"adis16364", ADIS16364},
+ {"adis16365", ADIS16365},
+ {"adis16400", ADIS16400},
+ {"adis16405", ADIS16400},
+ {}
+};
+
static struct spi_driver adis16400_driver = {
.driver = {
.name = "adis16400",
.owner = THIS_MODULE,
},
+ .id_table = adis16400_id,
.probe = adis16400_probe,
.remove = __devexit_p(adis16400_remove),
};
diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c
index da28cb4288af..3612373ddede 100644
--- a/drivers/staging/iio/imu/adis16400_ring.c
+++ b/drivers/staging/iio/imu/adis16400_ring.c
@@ -9,6 +9,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/bitops.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -17,93 +18,6 @@
#include "../trigger.h"
#include "adis16400.h"
-static IIO_SCAN_EL_C(in0_supply, ADIS16400_SCAN_SUPPLY,
- ADIS16400_SUPPLY_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in0_supply, u, 14, 16);
-
-static IIO_SCAN_EL_C(gyro_x, ADIS16400_SCAN_GYRO_X, ADIS16400_XGYRO_OUT, NULL);
-static IIO_SCAN_EL_C(gyro_y, ADIS16400_SCAN_GYRO_Y, ADIS16400_YGYRO_OUT, NULL);
-static IIO_SCAN_EL_C(gyro_z, ADIS16400_SCAN_GYRO_Z, ADIS16400_ZGYRO_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(gyro, s, 14, 16);
-
-static IIO_SCAN_EL_C(accel_x, ADIS16400_SCAN_ACC_X, ADIS16400_XACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_y, ADIS16400_SCAN_ACC_Y, ADIS16400_YACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_z, ADIS16400_SCAN_ACC_Z, ADIS16400_ZACCL_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(accel, s, 14, 16);
-
-static IIO_SCAN_EL_C(magn_x, ADIS16400_SCAN_MAGN_X, ADIS16400_XMAGN_OUT, NULL);
-static IIO_SCAN_EL_C(magn_y, ADIS16400_SCAN_MAGN_Y, ADIS16400_YMAGN_OUT, NULL);
-static IIO_SCAN_EL_C(magn_z, ADIS16400_SCAN_MAGN_Z, ADIS16400_ZMAGN_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(magn, s, 14, 16);
-
-static IIO_SCAN_EL_C(temp, ADIS16400_SCAN_TEMP, ADIS16400_TEMP_OUT, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(temp, s, 12, 16);
-
-static IIO_SCAN_EL_C(in1, ADIS16400_SCAN_ADC_0, ADIS16400_AUX_ADC, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(in1, u, 12, 16);
-
-static IIO_SCAN_EL_TIMESTAMP(12);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
-
-static struct attribute *adis16400_scan_el_attrs[] = {
- &iio_scan_el_in0_supply.dev_attr.attr,
- &iio_const_attr_in0_supply_index.dev_attr.attr,
- &iio_const_attr_in0_supply_type.dev_attr.attr,
- &iio_scan_el_gyro_x.dev_attr.attr,
- &iio_const_attr_gyro_x_index.dev_attr.attr,
- &iio_scan_el_gyro_y.dev_attr.attr,
- &iio_const_attr_gyro_y_index.dev_attr.attr,
- &iio_scan_el_gyro_z.dev_attr.attr,
- &iio_const_attr_gyro_z_index.dev_attr.attr,
- &iio_const_attr_gyro_type.dev_attr.attr,
- &iio_scan_el_accel_x.dev_attr.attr,
- &iio_const_attr_accel_x_index.dev_attr.attr,
- &iio_scan_el_accel_y.dev_attr.attr,
- &iio_const_attr_accel_y_index.dev_attr.attr,
- &iio_scan_el_accel_z.dev_attr.attr,
- &iio_const_attr_accel_z_index.dev_attr.attr,
- &iio_const_attr_accel_type.dev_attr.attr,
- &iio_scan_el_magn_x.dev_attr.attr,
- &iio_const_attr_magn_x_index.dev_attr.attr,
- &iio_scan_el_magn_y.dev_attr.attr,
- &iio_const_attr_magn_y_index.dev_attr.attr,
- &iio_scan_el_magn_z.dev_attr.attr,
- &iio_const_attr_magn_z_index.dev_attr.attr,
- &iio_const_attr_magn_type.dev_attr.attr,
- &iio_scan_el_temp.dev_attr.attr,
- &iio_const_attr_temp_index.dev_attr.attr,
- &iio_const_attr_temp_type.dev_attr.attr,
- &iio_scan_el_in1.dev_attr.attr,
- &iio_const_attr_in1_index.dev_attr.attr,
- &iio_const_attr_in1_type.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group adis16400_scan_el_group = {
- .attrs = adis16400_scan_el_attrs,
- .name = "scan_elements",
-};
-
-/**
- * adis16400_poll_func_th() top half interrupt handler called by trigger
- * @private_data: iio_dev
- **/
-static void adis16400_poll_func_th(struct iio_dev *indio_dev, s64 time)
-{
- struct adis16400_state *st = iio_dev_get_devdata(indio_dev);
- st->last_timestamp = time;
- schedule_work(&st->work_trigger_to_ring);
- /* Indicate that this interrupt is being handled */
-
- /* Technically this is trigger related, but without this
- * handler running there is currently no way for the interrupt
- * to clear.
- */
-}
-
/**
* adis16400_spi_read_burst() - read all data registers
* @dev: device associated with child of actual device (iio_dev or iio_trig)
@@ -113,7 +27,7 @@ static int adis16400_spi_read_burst(struct device *dev, u8 *rx)
{
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct adis16400_state *st = iio_dev_get_devdata(indio_dev);
+ struct adis16400_state *st = iio_priv(indio_dev);
u32 old_speed_hz = st->us->max_speed_hz;
int ret;
@@ -150,62 +64,126 @@ static int adis16400_spi_read_burst(struct device *dev, u8 *rx)
return ret;
}
+static const u16 read_all_tx_array[] = {
+ cpu_to_be16(ADIS16400_READ_REG(ADIS16400_SUPPLY_OUT)),
+ cpu_to_be16(ADIS16400_READ_REG(ADIS16400_XGYRO_OUT)),
+ cpu_to_be16(ADIS16400_READ_REG(ADIS16400_YGYRO_OUT)),
+ cpu_to_be16(ADIS16400_READ_REG(ADIS16400_ZGYRO_OUT)),
+ cpu_to_be16(ADIS16400_READ_REG(ADIS16400_XACCL_OUT)),
+ cpu_to_be16(ADIS16400_READ_REG(ADIS16400_YACCL_OUT)),
+ cpu_to_be16(ADIS16400_READ_REG(ADIS16400_ZACCL_OUT)),
+ cpu_to_be16(ADIS16400_READ_REG(ADIS16350_XTEMP_OUT)),
+ cpu_to_be16(ADIS16400_READ_REG(ADIS16350_YTEMP_OUT)),
+ cpu_to_be16(ADIS16400_READ_REG(ADIS16350_ZTEMP_OUT)),
+ cpu_to_be16(ADIS16400_READ_REG(ADIS16400_AUX_ADC)),
+};
+
+static int adis16350_spi_read_all(struct device *dev, u8 *rx)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct adis16400_state *st = iio_priv(indio_dev);
+
+ struct spi_message msg;
+ int i, j = 0, ret;
+ struct spi_transfer *xfers;
+
+ xfers = kzalloc(sizeof(*xfers)*indio_dev->ring->scan_count + 1,
+ GFP_KERNEL);
+ if (xfers == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(read_all_tx_array); i++)
+ if (indio_dev->ring->scan_mask & (1 << i)) {
+ xfers[j].tx_buf = &read_all_tx_array[i];
+ xfers[j].bits_per_word = 16;
+ xfers[j].len = 2;
+ xfers[j + 1].rx_buf = rx + j*2;
+ j++;
+ }
+ xfers[j].bits_per_word = 16;
+ xfers[j].len = 2;
+
+ spi_message_init(&msg);
+ for (j = 0; j < indio_dev->ring->scan_count + 1; j++)
+ spi_message_add_tail(&xfers[j], &msg);
+
+ ret = spi_sync(st->us, &msg);
+ kfree(xfers);
+
+ return ret;
+}
+
/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
* specific to be rolled into the core.
*/
-static void adis16400_trigger_bh_to_ring(struct work_struct *work_s)
+static irqreturn_t adis16400_trigger_handler(int irq, void *p)
{
- struct adis16400_state *st
- = container_of(work_s, struct adis16400_state,
- work_trigger_to_ring);
- struct iio_ring_buffer *ring = st->indio_dev->ring;
-
- int i = 0, j;
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->private_data;
+ struct adis16400_state *st = iio_priv(indio_dev);
+ struct iio_ring_buffer *ring = indio_dev->ring;
+ int i = 0, j, ret = 0;
s16 *data;
- size_t datasize = ring->access.get_bytes_per_datum(ring);
+ size_t datasize = ring->access->get_bytes_per_datum(ring);
unsigned long mask = ring->scan_mask;
data = kmalloc(datasize , GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
- return;
+ return -ENOMEM;
}
- if (ring->scan_count)
- if (adis16400_spi_read_burst(&st->indio_dev->dev, st->rx) >= 0)
- for (; i < ring->scan_count; i++) {
+ if (ring->scan_count) {
+ if (st->variant->flags & ADIS16400_NO_BURST) {
+ ret = adis16350_spi_read_all(&indio_dev->dev, st->rx);
+ if (ret < 0)
+ goto err;
+ for (; i < ring->scan_count; i++)
+ data[i] = *(s16 *)(st->rx + i*2);
+ } else {
+ ret = adis16400_spi_read_burst(&indio_dev->dev, st->rx);
+ if (ret < 0)
+ goto err;
+ for (; i < indio_dev->ring->scan_count; i++) {
j = __ffs(mask);
mask &= ~(1 << j);
- data[i] = be16_to_cpup(
+ data[i] = be16_to_cpup(
(__be16 *)&(st->rx[j*2]));
}
-
+ }
+ }
/* Guaranteed to be aligned with 8 byte boundary */
if (ring->scan_timestamp)
- *((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
+ *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
+ ring->access->store_to(indio_dev->ring, (u8 *) data, pf->timestamp);
- ring->access.store_to(ring,
- (u8 *) data,
- st->last_timestamp);
+ iio_trigger_notify_done(indio_dev->trig);
- iio_trigger_notify_done(st->indio_dev->trig);
kfree(data);
+ return IRQ_HANDLED;
- return;
+err:
+ kfree(data);
+ return ret;
}
void adis16400_unconfigure_ring(struct iio_dev *indio_dev)
{
- kfree(indio_dev->pollfunc);
+ iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->ring);
}
+static const struct iio_ring_setup_ops adis16400_ring_setup_ops = {
+ .preenable = &iio_sw_ring_preenable,
+ .postenable = &iio_triggered_ring_postenable,
+ .predisable = &iio_triggered_ring_predisable,
+};
+
int adis16400_configure_ring(struct iio_dev *indio_dev)
{
int ret = 0;
- struct adis16400_state *st = indio_dev->dev_data;
+ struct adis16400_state *st = iio_priv(indio_dev);
struct iio_ring_buffer *ring;
- INIT_WORK(&st->work_trigger_to_ring, adis16400_trigger_bh_to_ring);
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
@@ -214,36 +192,29 @@ int adis16400_configure_ring(struct iio_dev *indio_dev)
}
indio_dev->ring = ring;
/* Effectively select the ring buffer implementation */
- iio_ring_sw_register_funcs(&ring->access);
+ ring->access = &ring_sw_access_funcs;
ring->bpe = 2;
- ring->scan_el_attrs = &adis16400_scan_el_group;
ring->scan_timestamp = true;
- ring->preenable = &iio_sw_ring_preenable;
- ring->postenable = &iio_triggered_ring_postenable;
- ring->predisable = &iio_triggered_ring_predisable;
+ ring->setup_ops = &adis16400_ring_setup_ops;
ring->owner = THIS_MODULE;
-
/* Set default scan mode */
- iio_scan_mask_set(ring, iio_scan_el_in0_supply.number);
- iio_scan_mask_set(ring, iio_scan_el_gyro_x.number);
- iio_scan_mask_set(ring, iio_scan_el_gyro_y.number);
- iio_scan_mask_set(ring, iio_scan_el_gyro_z.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_x.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_y.number);
- iio_scan_mask_set(ring, iio_scan_el_accel_z.number);
- iio_scan_mask_set(ring, iio_scan_el_magn_x.number);
- iio_scan_mask_set(ring, iio_scan_el_magn_y.number);
- iio_scan_mask_set(ring, iio_scan_el_magn_z.number);
- iio_scan_mask_set(ring, iio_scan_el_temp.number);
- iio_scan_mask_set(ring, iio_scan_el_in1.number);
-
- ret = iio_alloc_pollfunc(indio_dev, NULL, &adis16400_poll_func_th);
- if (ret)
+ ring->scan_mask = st->variant->default_scan_mask;
+ ring->scan_count = hweight_long(st->variant->default_scan_mask);
+
+ indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
+ &adis16400_trigger_handler,
+ IRQF_ONESHOT,
+ indio_dev,
+ "%s_consumer%d",
+ indio_dev->name,
+ indio_dev->id);
+ if (indio_dev->pollfunc == NULL) {
+ ret = -ENOMEM;
goto error_iio_sw_rb_free;
+ }
indio_dev->modes |= INDIO_RING_TRIGGERED;
return 0;
-
error_iio_sw_rb_free:
iio_sw_rb_free(indio_dev->ring);
return ret;
diff --git a/drivers/staging/iio/imu/adis16400_trigger.c b/drivers/staging/iio/imu/adis16400_trigger.c
index 36b5ff5be983..c6ec41a02a69 100644
--- a/drivers/staging/iio/imu/adis16400_trigger.c
+++ b/drivers/staging/iio/imu/adis16400_trigger.c
@@ -13,113 +13,63 @@
#include "adis16400.h"
/**
- * adis16400_data_rdy_trig_poll() the event handler for the data rdy trig
- **/
-static int adis16400_data_rdy_trig_poll(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
-{
- struct adis16400_state *st = iio_dev_get_devdata(dev_info);
- struct iio_trigger *trig = st->trig;
-
- iio_trigger_poll(trig, timestamp);
-
- return IRQ_HANDLED;
-}
-
-IIO_EVENT_SH(data_rdy_trig, &adis16400_data_rdy_trig_poll);
-
-static IIO_TRIGGER_NAME_ATTR;
-
-static struct attribute *adis16400_trigger_attrs[] = {
- &dev_attr_name.attr,
- NULL,
-};
-
-static const struct attribute_group adis16400_trigger_attr_group = {
- .attrs = adis16400_trigger_attrs,
-};
-
-/**
* adis16400_data_rdy_trigger_set_state() set datardy interrupt state
**/
static int adis16400_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
- struct adis16400_state *st = trig->private_data;
- struct iio_dev *indio_dev = st->indio_dev;
- int ret = 0;
+ struct iio_dev *indio_dev = trig->private_data;
dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
- ret = adis16400_set_irq(&st->indio_dev->dev, state);
- if (state == false) {
- iio_remove_event_from_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]
- ->ev_list);
- /* possible quirk with handler currently worked around
- by ensuring the work queue is empty */
- flush_scheduled_work();
- } else {
- iio_add_event_to_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]->ev_list);
- }
- return ret;
-}
-
-/**
- * adis16400_trig_try_reen() try renabling irq for data rdy trigger
- * @trig: the datardy trigger
- **/
-static int adis16400_trig_try_reen(struct iio_trigger *trig)
-{
- struct adis16400_state *st = trig->private_data;
- enable_irq(st->us->irq);
- /* irq reenabled so success! */
- return 0;
+ return adis16400_set_irq(indio_dev, state);
}
int adis16400_probe_trigger(struct iio_dev *indio_dev)
{
int ret;
- struct adis16400_state *st = indio_dev->dev_data;
+ struct adis16400_state *st = iio_priv(indio_dev);
- st->trig = iio_allocate_trigger();
- st->trig->name = kasprintf(GFP_KERNEL,
- "adis16400-dev%d",
- indio_dev->id);
- if (!st->trig->name) {
+ st->trig = iio_allocate_trigger("%s-dev%d",
+ spi_get_device_id(st->us)->name,
+ indio_dev->id);
+ if (st->trig == NULL) {
ret = -ENOMEM;
- goto error_free_trig;
+ goto error_ret;
}
+
+ ret = request_irq(st->us->irq,
+ &iio_trigger_generic_data_rdy_poll,
+ IRQF_TRIGGER_RISING,
+ "adis16400",
+ st->trig);
+ if (ret)
+ goto error_free_trig;
st->trig->dev.parent = &st->us->dev;
st->trig->owner = THIS_MODULE;
- st->trig->private_data = st;
+ st->trig->private_data = indio_dev;
st->trig->set_trigger_state = &adis16400_data_rdy_trigger_set_state;
- st->trig->try_reenable = &adis16400_trig_try_reen;
- st->trig->control_attrs = &adis16400_trigger_attr_group;
ret = iio_trigger_register(st->trig);
/* select default trigger */
indio_dev->trig = st->trig;
if (ret)
- goto error_free_trig_name;
+ goto error_free_irq;
return 0;
-error_free_trig_name:
- kfree(st->trig->name);
+error_free_irq:
+ free_irq(st->us->irq, st->trig);
error_free_trig:
iio_free_trigger(st->trig);
-
+error_ret:
return ret;
}
void adis16400_remove_trigger(struct iio_dev *indio_dev)
{
- struct adis16400_state *state = indio_dev->dev_data;
+ struct adis16400_state *st = iio_priv(indio_dev);
- iio_trigger_unregister(state->trig);
- kfree(state->trig->name);
- iio_free_trigger(state->trig);
+ iio_trigger_unregister(st->trig);
+ free_irq(st->us->irq, st->trig);
+ iio_free_trigger(st->trig);
}
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index 1795ee1e8207..94d3bfaa061d 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -16,7 +16,6 @@
#include <linux/err.h>
#include <linux/device.h>
#include <linux/fs.h>
-#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/wait.h>
@@ -44,27 +43,55 @@ struct bus_type iio_bus_type = {
};
EXPORT_SYMBOL(iio_bus_type);
-void __iio_change_event(struct iio_detected_event_list *ev,
- int ev_code,
- s64 timestamp)
-{
- ev->ev.id = ev_code;
- ev->ev.timestamp = timestamp;
-}
-EXPORT_SYMBOL(__iio_change_event);
+static const char * const iio_chan_type_name_spec_shared[] = {
+ [IIO_TIMESTAMP] = "timestamp",
+ [IIO_ACCEL] = "accel",
+ [IIO_IN] = "in",
+ [IIO_CURRENT] = "current",
+ [IIO_POWER] = "power",
+ [IIO_IN_DIFF] = "in-in",
+ [IIO_GYRO] = "gyro",
+ [IIO_TEMP] = "temp",
+ [IIO_MAGN] = "magn",
+ [IIO_INCLI] = "incli",
+ [IIO_ROT] = "rot",
+ [IIO_INTENSITY] = "intensity",
+ [IIO_LIGHT] = "illuminance",
+ [IIO_ANGL] = "angl",
+};
+
+static const char * const iio_chan_type_name_spec_complex[] = {
+ [IIO_IN_DIFF] = "in%d-in%d",
+};
-/* Used both in the interrupt line put events and the ring buffer ones */
+static const char * const iio_modifier_names_light[] = {
+ [IIO_MOD_LIGHT_BOTH] = "both",
+ [IIO_MOD_LIGHT_IR] = "ir",
+};
-/* Note that in it's current form someone has to be listening before events
- * are queued. Hence a client MUST open the chrdev before the ring buffer is
- * switched on.
- */
-int __iio_push_event(struct iio_event_interface *ev_int,
- int ev_code,
- s64 timestamp,
- struct iio_shared_ev_pointer *
- shared_pointer_p)
+static const char * const iio_modifier_names_axial[] = {
+ [IIO_MOD_X] = "x",
+ [IIO_MOD_Y] = "y",
+ [IIO_MOD_Z] = "z",
+};
+
+/* relies on pairs of these shared then separate */
+static const char * const iio_chan_info_postfix[] = {
+ [IIO_CHAN_INFO_SCALE_SHARED/2] = "scale",
+ [IIO_CHAN_INFO_OFFSET_SHARED/2] = "offset",
+ [IIO_CHAN_INFO_CALIBSCALE_SHARED/2] = "calibscale",
+ [IIO_CHAN_INFO_CALIBBIAS_SHARED/2] = "calibbias",
+ [IIO_CHAN_INFO_PEAK_SHARED/2] = "peak_raw",
+ [IIO_CHAN_INFO_PEAK_SCALE_SHARED/2] = "peak_scale",
+};
+
+int iio_push_event(struct iio_dev *dev_info,
+ int ev_line,
+ int ev_code,
+ s64 timestamp)
{
+ struct iio_event_interface *ev_int
+ = &dev_info->event_interfaces[ev_line];
struct iio_detected_event_list *ev;
int ret = 0;
@@ -83,11 +110,8 @@ int __iio_push_event(struct iio_event_interface *ev_int,
}
ev->ev.id = ev_code;
ev->ev.timestamp = timestamp;
- ev->shared_pointer = shared_pointer_p;
- if (ev->shared_pointer)
- shared_pointer_p->ev_p = ev;
- list_add_tail(&ev->list, &ev_int->det_events.list);
+ list_add_tail(&ev->list, &ev_int->det_events);
ev_int->current_events++;
mutex_unlock(&ev_int->event_list_lock);
wake_up_interruptible(&ev_int->wait);
@@ -97,85 +121,8 @@ int __iio_push_event(struct iio_event_interface *ev_int,
error_ret:
return ret;
}
-EXPORT_SYMBOL(__iio_push_event);
-
-int iio_push_event(struct iio_dev *dev_info,
- int ev_line,
- int ev_code,
- s64 timestamp)
-{
- return __iio_push_event(&dev_info->event_interfaces[ev_line],
- ev_code, timestamp, NULL);
-}
EXPORT_SYMBOL(iio_push_event);
-/* Generic interrupt line interrupt handler */
-static irqreturn_t iio_interrupt_handler(int irq, void *_int_info)
-{
- struct iio_interrupt *int_info = _int_info;
- struct iio_dev *dev_info = int_info->dev_info;
- struct iio_event_handler_list *p;
- s64 time_ns;
- unsigned long flags;
-
- spin_lock_irqsave(&int_info->ev_list_lock, flags);
- if (list_empty(&int_info->ev_list)) {
- spin_unlock_irqrestore(&int_info->ev_list_lock, flags);
- return IRQ_NONE;
- }
-
- time_ns = iio_get_time_ns();
- list_for_each_entry(p, &int_info->ev_list, list) {
- disable_irq_nosync(irq);
- p->handler(dev_info, 1, time_ns, !(p->refcount > 1));
- }
- spin_unlock_irqrestore(&int_info->ev_list_lock, flags);
-
- return IRQ_HANDLED;
-}
-
-static struct iio_interrupt *iio_allocate_interrupt(void)
-{
- struct iio_interrupt *i = kmalloc(sizeof *i, GFP_KERNEL);
- if (i) {
- spin_lock_init(&i->ev_list_lock);
- INIT_LIST_HEAD(&i->ev_list);
- }
- return i;
-}
-
-/* Confirming the validity of supplied irq is left to drivers.*/
-int iio_register_interrupt_line(unsigned int irq,
- struct iio_dev *dev_info,
- int line_number,
- unsigned long type,
- const char *name)
-{
- int ret;
-
- dev_info->interrupts[line_number] = iio_allocate_interrupt();
- if (dev_info->interrupts[line_number] == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
- dev_info->interrupts[line_number]->line_number = line_number;
- dev_info->interrupts[line_number]->irq = irq;
- dev_info->interrupts[line_number]->dev_info = dev_info;
-
- /* Possibly only request on demand?
- * Can see this may complicate the handling of interrupts.
- * However, with this approach we might end up handling lots of
- * events no-one cares about.*/
- ret = request_irq(irq,
- &iio_interrupt_handler,
- type,
- name,
- dev_info->interrupts[line_number]);
-
-error_ret:
- return ret;
-}
-EXPORT_SYMBOL(iio_register_interrupt_line);
/* This turns up an awful lot */
ssize_t iio_read_const_attr(struct device *dev,
@@ -186,54 +133,6 @@ ssize_t iio_read_const_attr(struct device *dev,
}
EXPORT_SYMBOL(iio_read_const_attr);
-/* Before this runs the interrupt generator must have been disabled */
-void iio_unregister_interrupt_line(struct iio_dev *dev_info, int line_number)
-{
- /* make sure the interrupt handlers are all done */
- flush_scheduled_work();
- free_irq(dev_info->interrupts[line_number]->irq,
- dev_info->interrupts[line_number]);
- kfree(dev_info->interrupts[line_number]);
-}
-EXPORT_SYMBOL(iio_unregister_interrupt_line);
-
-/* Reference counted add and remove */
-void iio_add_event_to_list(struct iio_event_handler_list *el,
- struct list_head *head)
-{
- unsigned long flags;
- struct iio_interrupt *inter = to_iio_interrupt(head);
-
- /* take mutex to protect this element */
- mutex_lock(&el->exist_lock);
- if (el->refcount == 0) {
- /* Take the event list spin lock */
- spin_lock_irqsave(&inter->ev_list_lock, flags);
- list_add(&el->list, head);
- spin_unlock_irqrestore(&inter->ev_list_lock, flags);
- }
- el->refcount++;
- mutex_unlock(&el->exist_lock);
-}
-EXPORT_SYMBOL(iio_add_event_to_list);
-
-void iio_remove_event_from_list(struct iio_event_handler_list *el,
- struct list_head *head)
-{
- unsigned long flags;
- struct iio_interrupt *inter = to_iio_interrupt(head);
-
- mutex_lock(&el->exist_lock);
- el->refcount--;
- if (el->refcount == 0) {
- /* Take the event list spin lock */
- spin_lock_irqsave(&inter->ev_list_lock, flags);
- list_del_init(&el->list);
- spin_unlock_irqrestore(&inter->ev_list_lock, flags);
- }
- mutex_unlock(&el->exist_lock);
-}
-EXPORT_SYMBOL(iio_remove_event_from_list);
static ssize_t iio_event_chrdev_read(struct file *filep,
char __user *buf,
@@ -246,7 +145,7 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
size_t len;
mutex_lock(&ev_int->event_list_lock);
- if (list_empty(&ev_int->det_events.list)) {
+ if (list_empty(&ev_int->det_events)) {
if (filep->f_flags & O_NONBLOCK) {
ret = -EAGAIN;
goto error_mutex_unlock;
@@ -255,14 +154,14 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
/* Blocking on device; waiting for something to be there */
ret = wait_event_interruptible(ev_int->wait,
!list_empty(&ev_int
- ->det_events.list));
+ ->det_events));
if (ret)
goto error_ret;
/* Single access device so no one else can get the data */
mutex_lock(&ev_int->event_list_lock);
}
- el = list_first_entry(&ev_int->det_events.list,
+ el = list_first_entry(&ev_int->det_events,
struct iio_detected_event_list,
list);
len = sizeof el->ev;
@@ -273,18 +172,6 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
list_del(&el->list);
ev_int->current_events--;
mutex_unlock(&ev_int->event_list_lock);
- /*
- * Possible concurency issue if an update of this event is on its way
- * through. May lead to new event being removed whilst the reported
- * event was the unescalated event. In typical use case this is not a
- * problem as userspace will say read half the buffer due to a 50%
- * full event which would make the correct 100% full incorrect anyway.
- */
- if (el->shared_pointer) {
- spin_lock(&el->shared_pointer->lock);
- (el->shared_pointer->ev_p) = NULL;
- spin_unlock(&el->shared_pointer->lock);
- }
kfree(el);
return len;
@@ -309,7 +196,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
* clear out any awaiting events. The mask will prevent
* any new __iio_push_event calls running.
*/
- list_for_each_entry_safe(el, t, &ev_int->det_events.list, list) {
+ list_for_each_entry_safe(el, t, &ev_int->det_events, list) {
list_del(&el->list);
kfree(el);
}
@@ -381,10 +268,11 @@ void iio_device_free_chrdev_minor(int val)
spin_unlock(&iio_ida_lock);
}
-int iio_setup_ev_int(struct iio_event_interface *ev_int,
- const char *name,
- struct module *owner,
- struct device *dev)
+static int iio_setup_ev_int(struct iio_event_interface *ev_int,
+ const char *dev_name,
+ int index,
+ struct module *owner,
+ struct device *dev)
{
int ret, minor;
@@ -399,7 +287,7 @@ int iio_setup_ev_int(struct iio_event_interface *ev_int,
goto error_device_put;
}
ev_int->dev.devt = MKDEV(MAJOR(iio_devt), minor);
- dev_set_name(&ev_int->dev, "%s", name);
+ dev_set_name(&ev_int->dev, "%s:event%d", dev_name, index);
ret = device_add(&ev_int->dev);
if (ret)
@@ -412,7 +300,7 @@ int iio_setup_ev_int(struct iio_event_interface *ev_int,
/* discussion point - make this variable? */
ev_int->max_events = 10;
ev_int->current_events = 0;
- INIT_LIST_HEAD(&ev_int->det_events.list);
+ INIT_LIST_HEAD(&ev_int->det_events);
init_waitqueue_head(&ev_int->wait);
ev_int->handler.private = ev_int;
ev_int->handler.flags = 0;
@@ -433,7 +321,7 @@ error_device_put:
return ret;
}
-void iio_free_ev_int(struct iio_event_interface *ev_int)
+static void iio_free_ev_int(struct iio_event_interface *ev_int)
{
device_unregister(&ev_int->dev);
put_device(&ev_int->dev);
@@ -488,24 +376,397 @@ static void __exit iio_exit(void)
bus_unregister(&iio_bus_type);
}
-static int iio_device_register_sysfs(struct iio_dev *dev_info)
+static ssize_t iio_read_channel_info(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
- int ret = 0;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ int val, val2;
+ int ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
+ &val, &val2, this_attr->address);
- ret = sysfs_create_group(&dev_info->dev.kobj, dev_info->attrs);
- if (ret) {
- dev_err(dev_info->dev.parent,
- "Failed to register sysfs hooks\n");
+ if (ret < 0)
+ return ret;
+
+ if (ret == IIO_VAL_INT)
+ return sprintf(buf, "%d\n", val);
+ else if (ret == IIO_VAL_INT_PLUS_MICRO) {
+ if (val2 < 0)
+ return sprintf(buf, "-%d.%06u\n", val, -val2);
+ else
+ return sprintf(buf, "%d.%06u\n", val, val2);
+ } else
+ return 0;
+}
+
+static ssize_t iio_write_channel_info(struct device *dev,
+ struct device_attribute *attr,
+ 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, integer = 0, micro = 0, micro_mult = 100000;
+ bool integer_part = true, negative = false;
+
+ /* Assumes decimal - precision based on number of digits */
+ if (!indio_dev->info->write_raw)
+ return -EINVAL;
+ if (buf[0] == '-') {
+ negative = true;
+ buf++;
+ }
+ while (*buf) {
+ if ('0' <= *buf && *buf <= '9') {
+ if (integer_part)
+ integer = integer*10 + *buf - '0';
+ else {
+ micro += micro_mult*(*buf - '0');
+ if (micro_mult == 1)
+ break;
+ micro_mult /= 10;
+ }
+ } else if (*buf == '\n') {
+ if (*(buf + 1) == '\0')
+ break;
+ else
+ return -EINVAL;
+ } else if (*buf == '.') {
+ integer_part = false;
+ } else {
+ return -EINVAL;
+ }
+ buf++;
+ }
+ if (negative) {
+ if (integer)
+ integer = -integer;
+ else
+ micro = -micro;
+ }
+
+ ret = indio_dev->info->write_raw(indio_dev, this_attr->c,
+ integer, micro, this_attr->address);
+ if (ret)
+ return ret;
+
+ return len;
+}
+
+static int __iio_build_postfix(struct iio_chan_spec const *chan,
+ bool generic,
+ const char *postfix,
+ char **result)
+{
+ char *all_post;
+ /* 3 options - generic, extend_name, modified - if generic, extend_name
+ * and modified cannot apply.*/
+
+ if (generic || (!chan->modified && !chan->extend_name)) {
+ all_post = kasprintf(GFP_KERNEL, "%s", postfix);
+ } else if (chan->modified) {
+ const char *intermediate;
+ switch (chan->type) {
+ case IIO_INTENSITY:
+ intermediate
+ = iio_modifier_names_light[chan->channel2];
+ break;
+ case IIO_ACCEL:
+ case IIO_GYRO:
+ case IIO_MAGN:
+ case IIO_INCLI:
+ case IIO_ROT:
+ case IIO_ANGL:
+ intermediate
+ = iio_modifier_names_axial[chan->channel2];
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (chan->extend_name)
+ all_post = kasprintf(GFP_KERNEL, "%s_%s_%s",
+ intermediate,
+ chan->extend_name,
+ postfix);
+ else
+ all_post = kasprintf(GFP_KERNEL, "%s_%s",
+ intermediate,
+ postfix);
+ } else
+ all_post = kasprintf(GFP_KERNEL, "%s_%s", chan->extend_name,
+ postfix);
+ if (all_post == NULL)
+ return -ENOMEM;
+ *result = all_post;
+ return 0;
+}
+
+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)
+{
+ int ret;
+ char *name_format, *full_postfix;
+ sysfs_attr_init(&dev_attr->attr);
+ ret = __iio_build_postfix(chan, generic, postfix, &full_postfix);
+ if (ret)
+ goto error_ret;
+
+ /* Special case for types that uses both channel numbers in naming */
+ if (chan->type == IIO_IN_DIFF && !generic)
+ name_format
+ = kasprintf(GFP_KERNEL, "%s_%s",
+ iio_chan_type_name_spec_complex[chan->type],
+ full_postfix);
+ else if (generic || !chan->indexed)
+ name_format
+ = kasprintf(GFP_KERNEL, "%s_%s",
+ iio_chan_type_name_spec_shared[chan->type],
+ full_postfix);
+ else
+ name_format
+ = kasprintf(GFP_KERNEL, "%s%d_%s",
+ iio_chan_type_name_spec_shared[chan->type],
+ chan->channel,
+ full_postfix);
+
+ if (name_format == NULL) {
+ ret = -ENOMEM;
+ goto error_free_full_postfix;
+ }
+ dev_attr->attr.name = kasprintf(GFP_KERNEL,
+ name_format,
+ chan->channel,
+ chan->channel2);
+ if (dev_attr->attr.name == NULL) {
+ ret = -ENOMEM;
+ goto error_free_name_format;
+ }
+
+ if (readfunc) {
+ dev_attr->attr.mode |= S_IRUGO;
+ dev_attr->show = readfunc;
+ }
+
+ if (writefunc) {
+ dev_attr->attr.mode |= S_IWUSR;
+ dev_attr->store = writefunc;
+ }
+ kfree(name_format);
+ kfree(full_postfix);
+
+ return 0;
+
+error_free_name_format:
+ kfree(name_format);
+error_free_full_postfix:
+ kfree(full_postfix);
+error_ret:
+ return ret;
+}
+
+void __iio_device_attr_deinit(struct device_attribute *dev_attr)
+{
+ kfree(dev_attr->attr.name);
+}
+
+int __iio_add_chan_devattr(const char *postfix,
+ const char *group,
+ 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),
+ int mask,
+ bool generic,
+ struct device *dev,
+ struct list_head *attr_list)
+{
+ int ret;
+ struct iio_dev_attr *iio_attr, *t;
+
+ iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL);
+ if (iio_attr == NULL) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+ ret = __iio_device_attr_init(&iio_attr->dev_attr,
+ postfix, chan,
+ readfunc, writefunc, generic);
+ if (ret)
+ goto error_iio_dev_attr_free;
+ iio_attr->c = chan;
+ iio_attr->address = mask;
+ list_for_each_entry(t, attr_list, l)
+ if (strcmp(t->dev_attr.attr.name,
+ iio_attr->dev_attr.attr.name) == 0) {
+ if (!generic)
+ dev_err(dev, "tried to double register : %s\n",
+ t->dev_attr.attr.name);
+ ret = -EBUSY;
+ goto error_device_attr_deinit;
+ }
+
+ ret = sysfs_add_file_to_group(&dev->kobj,
+ &iio_attr->dev_attr.attr, group);
+ if (ret < 0)
+ goto error_device_attr_deinit;
+
+ list_add(&iio_attr->l, attr_list);
+
+ return 0;
+
+error_device_attr_deinit:
+ __iio_device_attr_deinit(&iio_attr->dev_attr);
+error_iio_dev_attr_free:
+ kfree(iio_attr);
+error_ret:
+ return ret;
+}
+
+static int iio_device_add_channel_sysfs(struct iio_dev *dev_info,
+ struct iio_chan_spec const *chan)
+{
+ int ret, i;
+
+
+ if (chan->channel < 0)
+ return 0;
+ if (chan->processed_val)
+ ret = __iio_add_chan_devattr("input", NULL, chan,
+ &iio_read_channel_info,
+ NULL,
+ 0,
+ 0,
+ &dev_info->dev,
+ &dev_info->channel_attr_list);
+ else
+ ret = __iio_add_chan_devattr("raw", NULL, chan,
+ &iio_read_channel_info,
+ NULL,
+ 0,
+ 0,
+ &dev_info->dev,
+ &dev_info->channel_attr_list);
+ if (ret)
goto error_ret;
+
+ for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) {
+ ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2],
+ NULL, chan,
+ &iio_read_channel_info,
+ &iio_write_channel_info,
+ (1 << i),
+ !(i%2),
+ &dev_info->dev,
+ &dev_info->channel_attr_list);
+ if (ret == -EBUSY && (i%2 == 0)) {
+ ret = 0;
+ continue;
+ }
+ if (ret < 0)
+ goto error_ret;
+ }
+error_ret:
+ return ret;
+}
+
+static void iio_device_remove_and_free_read_attr(struct iio_dev *dev_info,
+ struct iio_dev_attr *p)
+{
+ sysfs_remove_file_from_group(&dev_info->dev.kobj,
+ &p->dev_attr.attr, NULL);
+ kfree(p->dev_attr.attr.name);
+ kfree(p);
+}
+
+static ssize_t iio_show_dev_name(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ return sprintf(buf, "%s\n", indio_dev->name);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
+
+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) {
+ 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;
+ }
+ }
+
+ /*
+ * New channel registration method - relies on the fact a group does
+ * not need to be initialized if it is name is NULL.
+ */
+ INIT_LIST_HEAD(&dev_info->channel_attr_list);
+ if (dev_info->channels)
+ for (i = 0; i < dev_info->num_channels; i++) {
+ ret = iio_device_add_channel_sysfs(dev_info,
+ &dev_info
+ ->channels[i]);
+ if (ret < 0)
+ goto error_clear_attrs;
+ }
+ if (dev_info->name) {
+ ret = sysfs_add_file_to_group(&dev_info->dev.kobj,
+ &dev_attr_name.attr,
+ NULL);
+ if (ret)
+ goto error_clear_attrs;
}
+ return 0;
+error_clear_attrs:
+ list_for_each_entry_safe(p, n,
+ &dev_info->channel_attr_list, l) {
+ list_del(&p->l);
+ iio_device_remove_and_free_read_attr(dev_info, p);
+ }
+ if (dev_info->info->attrs)
+ sysfs_remove_group(&dev_info->dev.kobj, dev_info->info->attrs);
error_ret:
return ret;
+
}
static void iio_device_unregister_sysfs(struct iio_dev *dev_info)
{
- sysfs_remove_group(&dev_info->dev.kobj, dev_info->attrs);
+
+ struct iio_dev_attr *p, *n;
+ if (dev_info->name)
+ sysfs_remove_file_from_group(&dev_info->dev.kobj,
+ &dev_attr_name.attr,
+ NULL);
+ list_for_each_entry_safe(p, n, &dev_info->channel_attr_list, l) {
+ list_del(&p->l);
+ iio_device_remove_and_free_read_attr(dev_info, p);
+ }
+
+ if (dev_info->info->attrs)
+ sysfs_remove_group(&dev_info->dev.kobj, dev_info->info->attrs);
}
/* Return a negative errno on failure */
@@ -538,48 +799,209 @@ void iio_free_ida_val(struct ida *this_ida, int id)
}
EXPORT_SYMBOL(iio_free_ida_val);
-static int iio_device_register_id(struct iio_dev *dev_info,
- struct ida *this_ida)
+static const char * const iio_ev_type_text[] = {
+ [IIO_EV_TYPE_THRESH] = "thresh",
+ [IIO_EV_TYPE_MAG] = "mag",
+ [IIO_EV_TYPE_ROC] = "roc"
+};
+
+static const char * const iio_ev_dir_text[] = {
+ [IIO_EV_DIR_EITHER] = "either",
+ [IIO_EV_DIR_RISING] = "rising",
+ [IIO_EV_DIR_FALLING] = "falling"
+};
+
+static ssize_t iio_ev_state_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
{
- dev_info->id = iio_get_new_ida_val(&iio_ida);
- if (dev_info->id < 0)
- return dev_info->id;
- return 0;
+ struct iio_dev *indio_dev = dev_get_drvdata(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;
+
+ ret = indio_dev->info->write_event_config(indio_dev,
+ this_attr->address,
+ val);
+ return (ret < 0) ? ret : len;
}
-static void iio_device_unregister_id(struct iio_dev *dev_info)
+static ssize_t iio_ev_state_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
- iio_free_ida_val(&iio_ida, dev_info->id);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ int val = indio_dev->info->read_event_config(indio_dev,
+ this_attr->address);
+
+ if (val < 0)
+ return val;
+ else
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t iio_ev_value_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ int val, ret;
+
+ ret = indio_dev->info->read_event_value(indio_dev,
+ this_attr->address, &val);
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t iio_ev_value_store(struct device *dev,
+ struct device_attribute *attr,
+ 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);
+ unsigned long val;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ ret = indio_dev->info->write_event_value(indio_dev, this_attr->address,
+ val);
+ if (ret < 0)
+ return ret;
+
+ return len;
+}
+
+static int iio_device_add_event_sysfs(struct iio_dev *dev_info,
+ struct iio_chan_spec const *chan)
+{
+
+ int ret = 0, i, mask;
+ char *postfix;
+ if (!chan->event_mask)
+ return 0;
+
+ for_each_set_bit(i, &chan->event_mask, sizeof(chan->event_mask)*8) {
+ postfix = kasprintf(GFP_KERNEL, "%s_%s_en",
+ iio_ev_type_text[i/IIO_EV_TYPE_MAX],
+ iio_ev_dir_text[i%IIO_EV_TYPE_MAX]);
+ if (postfix == NULL) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+ switch (chan->type) {
+ /* Switch this to a table at some point */
+ case IIO_IN:
+ mask = IIO_UNMOD_EVENT_CODE(chan->type, chan->channel,
+ i/IIO_EV_TYPE_MAX,
+ i%IIO_EV_TYPE_MAX);
+ break;
+ case IIO_ACCEL:
+ mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel,
+ i/IIO_EV_TYPE_MAX,
+ i%IIO_EV_TYPE_MAX);
+ break;
+ case IIO_IN_DIFF:
+ mask = IIO_MOD_EVENT_CODE(chan->type, chan->channel,
+ chan->channel2,
+ i/IIO_EV_TYPE_MAX,
+ i%IIO_EV_TYPE_MAX);
+ break;
+ default:
+ printk(KERN_INFO "currently unhandled type of event\n");
+ }
+ ret = __iio_add_chan_devattr(postfix,
+ NULL,
+ chan,
+ &iio_ev_state_show,
+ iio_ev_state_store,
+ mask,
+ /*HACK. - limits us to one
+ event interface - fix by
+ extending the bitmask - but
+ how far*/
+ 0,
+ &dev_info->event_interfaces[0].dev,
+ &dev_info->event_interfaces[0].
+ dev_attr_list);
+ kfree(postfix);
+ if (ret)
+ goto error_ret;
+
+ postfix = kasprintf(GFP_KERNEL, "%s_%s_value",
+ iio_ev_type_text[i/IIO_EV_TYPE_MAX],
+ iio_ev_dir_text[i%IIO_EV_TYPE_MAX]);
+ if (postfix == NULL) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+ ret = __iio_add_chan_devattr(postfix, NULL, chan,
+ iio_ev_value_show,
+ iio_ev_value_store,
+ mask,
+ 0,
+ &dev_info->event_interfaces[0]
+ .dev,
+ &dev_info->event_interfaces[0]
+ .dev_attr_list);
+ kfree(postfix);
+ if (ret)
+ goto error_ret;
+
+ }
+
+error_ret:
+ return ret;
+}
+
+static inline void __iio_remove_all_event_sysfs(struct iio_dev *dev_info,
+ const char *groupname,
+ int num)
+{
+ struct iio_dev_attr *p, *n;
+ list_for_each_entry_safe(p, n,
+ &dev_info->event_interfaces[num].
+ dev_attr_list, l) {
+ sysfs_remove_file_from_group(&dev_info
+ ->event_interfaces[num].dev.kobj,
+ &p->dev_attr.attr,
+ groupname);
+ kfree(p->dev_attr.attr.name);
+ kfree(p);
+ }
}
static inline int __iio_add_event_config_attrs(struct iio_dev *dev_info, int i)
{
+ int j;
int ret;
- /*p for adding, q for removing */
- struct attribute **attrp, **attrq;
-
- if (dev_info->event_conf_attrs && dev_info->event_conf_attrs[i].attrs) {
- attrp = dev_info->event_conf_attrs[i].attrs;
- while (*attrp) {
- ret = sysfs_add_file_to_group(&dev_info->dev.kobj,
- *attrp,
- dev_info
- ->event_attrs[i].name);
+ INIT_LIST_HEAD(&dev_info->event_interfaces[0].dev_attr_list);
+ /* Dynically created from the channels array */
+ if (dev_info->channels) {
+ for (j = 0; j < dev_info->num_channels; j++) {
+ ret = iio_device_add_event_sysfs(dev_info,
+ &dev_info
+ ->channels[j]);
if (ret)
- goto error_ret;
- attrp++;
+ goto error_clear_attrs;
}
}
return 0;
-error_ret:
- attrq = dev_info->event_conf_attrs[i].attrs;
- while (attrq != attrp) {
- sysfs_remove_file_from_group(&dev_info->dev.kobj,
- *attrq,
- dev_info->event_attrs[i].name);
- attrq++;
- }
+error_clear_attrs:
+ __iio_remove_all_event_sysfs(dev_info, NULL, i);
return ret;
}
@@ -587,20 +1009,7 @@ error_ret:
static inline int __iio_remove_event_config_attrs(struct iio_dev *dev_info,
int i)
{
- struct attribute **attrq;
-
- if (dev_info->event_conf_attrs
- && dev_info->event_conf_attrs[i].attrs) {
- attrq = dev_info->event_conf_attrs[i].attrs;
- while (*attrq) {
- sysfs_remove_file_from_group(&dev_info->dev.kobj,
- *attrq,
- dev_info
- ->event_attrs[i].name);
- attrq++;
- }
- }
-
+ __iio_remove_all_event_sysfs(dev_info, NULL, i);
return 0;
}
@@ -608,39 +1017,23 @@ static int iio_device_register_eventset(struct iio_dev *dev_info)
{
int ret = 0, i, j;
- if (dev_info->num_interrupt_lines == 0)
+ if (dev_info->info->num_interrupt_lines == 0)
return 0;
dev_info->event_interfaces =
kzalloc(sizeof(struct iio_event_interface)
- *dev_info->num_interrupt_lines,
+ *dev_info->info->num_interrupt_lines,
GFP_KERNEL);
if (dev_info->event_interfaces == NULL) {
ret = -ENOMEM;
goto error_ret;
}
- dev_info->interrupts = kzalloc(sizeof(struct iio_interrupt *)
- *dev_info->num_interrupt_lines,
- GFP_KERNEL);
- if (dev_info->interrupts == NULL) {
- ret = -ENOMEM;
- goto error_free_event_interfaces;
- }
-
- for (i = 0; i < dev_info->num_interrupt_lines; i++) {
- dev_info->event_interfaces[i].owner = dev_info->driver_module;
-
- snprintf(dev_info->event_interfaces[i]._name, 20,
- "%s:event%d",
- dev_name(&dev_info->dev),
- i);
-
+ for (i = 0; i < dev_info->info->num_interrupt_lines; i++) {
ret = iio_setup_ev_int(&dev_info->event_interfaces[i],
- (const char *)(dev_info
- ->event_interfaces[i]
- ._name),
- dev_info->driver_module,
+ dev_name(&dev_info->dev),
+ i,
+ dev_info->info->driver_module,
&dev_info->dev);
if (ret) {
dev_err(&dev_info->dev,
@@ -650,10 +1043,13 @@ static int iio_device_register_eventset(struct iio_dev *dev_info)
dev_set_drvdata(&dev_info->event_interfaces[i].dev,
(void *)dev_info);
- ret = sysfs_create_group(&dev_info
- ->event_interfaces[i]
- .dev.kobj,
- &dev_info->event_attrs[i]);
+
+ if (dev_info->info->event_attrs != NULL)
+ ret = sysfs_create_group(&dev_info
+ ->event_interfaces[i]
+ .dev.kobj,
+ &dev_info->info
+ ->event_attrs[i]);
if (ret) {
dev_err(&dev_info->dev,
@@ -662,7 +1058,7 @@ static int iio_device_register_eventset(struct iio_dev *dev_info)
}
}
- for (i = 0; i < dev_info->num_interrupt_lines; i++) {
+ 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;
@@ -673,17 +1069,16 @@ static int iio_device_register_eventset(struct iio_dev *dev_info)
error_unregister_config_attrs:
for (j = 0; j < i; j++)
__iio_remove_event_config_attrs(dev_info, i);
- i = dev_info->num_interrupt_lines - 1;
+ i = dev_info->info->num_interrupt_lines - 1;
error_remove_sysfs_interfaces:
for (j = 0; j < i; j++)
- sysfs_remove_group(&dev_info
+ if (dev_info->info->event_attrs != NULL)
+ sysfs_remove_group(&dev_info
->event_interfaces[j].dev.kobj,
- &dev_info->event_attrs[j]);
+ &dev_info->info->event_attrs[j]);
error_free_setup_ev_ints:
for (j = 0; j < i; j++)
iio_free_ev_int(&dev_info->event_interfaces[j]);
- kfree(dev_info->interrupts);
-error_free_event_interfaces:
kfree(dev_info->event_interfaces);
error_ret:
@@ -694,25 +1089,25 @@ static void iio_device_unregister_eventset(struct iio_dev *dev_info)
{
int i;
- if (dev_info->num_interrupt_lines == 0)
+ if (dev_info->info->num_interrupt_lines == 0)
return;
- for (i = 0; i < dev_info->num_interrupt_lines; i++)
- sysfs_remove_group(&dev_info
- ->event_interfaces[i].dev.kobj,
- &dev_info->event_attrs[i]);
+ for (i = 0; i < dev_info->info->num_interrupt_lines; i++) {
+ __iio_remove_event_config_attrs(dev_info, i);
+ if (dev_info->info->event_attrs != NULL)
+ sysfs_remove_group(&dev_info
+ ->event_interfaces[i].dev.kobj,
+ &dev_info->info->event_attrs[i]);
+ }
- for (i = 0; i < dev_info->num_interrupt_lines; i++)
+ for (i = 0; i < dev_info->info->num_interrupt_lines; i++)
iio_free_ev_int(&dev_info->event_interfaces[i]);
- kfree(dev_info->interrupts);
kfree(dev_info->event_interfaces);
}
static void iio_dev_release(struct device *device)
{
- struct iio_dev *dev = to_iio_dev(device);
-
iio_put();
- kfree(dev);
+ kfree(to_iio_dev(device));
}
static struct device_type iio_dev_type = {
@@ -720,9 +1115,20 @@ static struct device_type iio_dev_type = {
.release = iio_dev_release,
};
-struct iio_dev *iio_allocate_device(void)
+struct iio_dev *iio_allocate_device(int sizeof_priv)
{
- struct iio_dev *dev = kzalloc(sizeof *dev, GFP_KERNEL);
+ struct iio_dev *dev;
+ size_t alloc_size;
+
+ alloc_size = sizeof(struct iio_dev);
+ if (sizeof_priv) {
+ alloc_size = ALIGN(alloc_size, IIO_ALIGN);
+ alloc_size += sizeof_priv;
+ }
+ /* ensure 32-byte alignment of whole construct ? */
+ alloc_size += IIO_ALIGN - 1;
+
+ dev = kzalloc(alloc_size, GFP_KERNEL);
if (dev) {
dev->dev.type = &iio_dev_type;
@@ -748,8 +1154,9 @@ int iio_device_register(struct iio_dev *dev_info)
{
int ret;
- ret = iio_device_register_id(dev_info, &iio_ida);
- if (ret) {
+ dev_info->id = iio_get_new_ida_val(&iio_ida);
+ if (dev_info->id < 0) {
+ ret = dev_info->id;
dev_err(&dev_info->dev, "Failed to get id\n");
goto error_ret;
}
@@ -780,7 +1187,7 @@ error_free_sysfs:
error_del_device:
device_del(&dev_info->dev);
error_free_ida:
- iio_device_unregister_id(dev_info);
+ iio_free_ida_val(&iio_ida, dev_info->id);
error_ret:
return ret;
}
@@ -792,7 +1199,7 @@ void iio_device_unregister(struct iio_dev *dev_info)
iio_device_unregister_trigger_consumer(dev_info);
iio_device_unregister_eventset(dev_info);
iio_device_unregister_sysfs(dev_info);
- iio_device_unregister_id(dev_info);
+ iio_free_ida_val(&iio_ida, dev_info->id);
device_unregister(&dev_info->dev);
}
EXPORT_SYMBOL(iio_device_unregister);
diff --git a/drivers/staging/iio/industrialio-ring.c b/drivers/staging/iio/industrialio-ring.c
index bd4373ae066b..843eb82a69ba 100644
--- a/drivers/staging/iio/industrialio-ring.c
+++ b/drivers/staging/iio/industrialio-ring.c
@@ -18,37 +18,11 @@
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/slab.h>
+#include <linux/poll.h>
#include "iio.h"
#include "ring_generic.h"
-int iio_push_ring_event(struct iio_ring_buffer *ring_buf,
- int event_code,
- s64 timestamp)
-{
- return __iio_push_event(&ring_buf->ev_int,
- event_code,
- timestamp,
- &ring_buf->shared_ev_pointer);
-}
-EXPORT_SYMBOL(iio_push_ring_event);
-
-int iio_push_or_escallate_ring_event(struct iio_ring_buffer *ring_buf,
- int event_code,
- s64 timestamp)
-{
- if (ring_buf->shared_ev_pointer.ev_p)
- __iio_change_event(ring_buf->shared_ev_pointer.ev_p,
- event_code,
- timestamp);
- else
- return iio_push_ring_event(ring_buf,
- event_code,
- timestamp);
- return 0;
-}
-EXPORT_SYMBOL(iio_push_or_escallate_ring_event);
-
/**
* iio_ring_open() - chrdev file open for ring buffer access
*
@@ -62,8 +36,8 @@ static int iio_ring_open(struct inode *inode, struct file *filp)
struct iio_ring_buffer *rb = hand->private;
filp->private_data = hand->private;
- if (rb->access.mark_in_use)
- rb->access.mark_in_use(rb);
+ if (rb->access->mark_in_use)
+ rb->access->mark_in_use(rb);
return 0;
}
@@ -81,184 +55,316 @@ static int iio_ring_release(struct inode *inode, struct file *filp)
struct iio_ring_buffer *rb = hand->private;
clear_bit(IIO_BUSY_BIT_POS, &rb->access_handler.flags);
- if (rb->access.unmark_in_use)
- rb->access.unmark_in_use(rb);
+ if (rb->access->unmark_in_use)
+ rb->access->unmark_in_use(rb);
return 0;
}
/**
- * iio_ring_rip_outer() - chrdev read for ring buffer access
+ * iio_ring_read_first_n_outer() - chrdev read for ring buffer access
*
* This function relies on all ring buffer implementations having an
* iio_ring _bufer as their first element.
**/
-static ssize_t iio_ring_rip_outer(struct file *filp, char __user *buf,
- size_t count, loff_t *f_ps)
+static ssize_t iio_ring_read_first_n_outer(struct file *filp, char __user *buf,
+ size_t n, loff_t *f_ps)
{
struct iio_ring_buffer *rb = filp->private_data;
- int ret, dead_offset;
- /* rip lots must exist. */
- if (!rb->access.rip_lots)
+ if (!rb->access->read_first_n)
return -EINVAL;
- ret = rb->access.rip_lots(rb, count, buf, &dead_offset);
+ return rb->access->read_first_n(rb, n, buf);
+}
- return ret;
+/**
+ * iio_ring_poll() - poll the ring to find out if it has data
+ */
+static unsigned int iio_ring_poll(struct file *filp,
+ struct poll_table_struct *wait)
+{
+ struct iio_ring_buffer *rb = filp->private_data;
+
+ poll_wait(filp, &rb->pollq, wait);
+ if (rb->stufftoread)
+ return POLLIN | POLLRDNORM;
+ /* need a way of knowing if there may be enough data... */
+ return 0;
}
static const struct file_operations iio_ring_fileops = {
- .read = iio_ring_rip_outer,
+ .read = iio_ring_read_first_n_outer,
.release = iio_ring_release,
.open = iio_ring_open,
+ .poll = iio_ring_poll,
.owner = THIS_MODULE,
.llseek = noop_llseek,
};
-/**
- * __iio_request_ring_buffer_event_chrdev() - allocate ring event chrdev
- * @buf: ring buffer whose event chrdev we are allocating
- * @id: id of this ring buffer (typically 0)
- * @owner: the module who owns the ring buffer (for ref counting)
- * @dev: device with which the chrdev is associated
- **/
-static inline int
-__iio_request_ring_buffer_event_chrdev(struct iio_ring_buffer *buf,
- int id,
- struct module *owner,
- struct device *dev)
-{
- int ret;
-
- snprintf(buf->ev_int._name, sizeof(buf->ev_int._name),
- "%s:event%d",
- dev_name(&buf->dev),
- id);
- ret = iio_setup_ev_int(&(buf->ev_int),
- buf->ev_int._name,
- owner,
- dev);
- if (ret)
- goto error_ret;
- return 0;
-
-error_ret:
- return ret;
-}
-
-static inline void
-__iio_free_ring_buffer_event_chrdev(struct iio_ring_buffer *buf)
-{
- iio_free_ev_int(&(buf->ev_int));
-}
-
-static void iio_ring_access_release(struct device *dev)
+void iio_ring_access_release(struct device *dev)
{
struct iio_ring_buffer *buf
- = access_dev_to_iio_ring_buffer(dev);
+ = container_of(dev, struct iio_ring_buffer, dev);
cdev_del(&buf->access_handler.chrdev);
iio_device_free_chrdev_minor(MINOR(dev->devt));
}
-
-static struct device_type iio_ring_access_type = {
- .release = iio_ring_access_release,
-};
+EXPORT_SYMBOL(iio_ring_access_release);
static inline int
-__iio_request_ring_buffer_access_chrdev(struct iio_ring_buffer *buf,
- int id,
- struct module *owner)
+__iio_request_ring_buffer_chrdev(struct iio_ring_buffer *buf,
+ struct module *owner,
+ int id)
{
- int ret, minor;
+ int ret;
buf->access_handler.flags = 0;
+ buf->dev.bus = &iio_bus_type;
+ device_initialize(&buf->dev);
- buf->access_dev.parent = &buf->dev;
- buf->access_dev.bus = &iio_bus_type;
- buf->access_dev.type = &iio_ring_access_type;
- device_initialize(&buf->access_dev);
-
- minor = iio_device_get_chrdev_minor();
- if (minor < 0) {
- ret = minor;
+ ret = iio_device_get_chrdev_minor();
+ if (ret < 0)
goto error_device_put;
- }
- buf->access_dev.devt = MKDEV(MAJOR(iio_devt), minor);
-
- buf->access_id = id;
-
- dev_set_name(&buf->access_dev, "%s:access%d",
- dev_name(&buf->dev),
- buf->access_id);
- ret = device_add(&buf->access_dev);
+ buf->dev.devt = MKDEV(MAJOR(iio_devt), ret);
+ dev_set_name(&buf->dev, "%s:buffer%d",
+ dev_name(buf->dev.parent),
+ id);
+ ret = device_add(&buf->dev);
if (ret < 0) {
- printk(KERN_ERR "failed to add the ring access dev\n");
+ printk(KERN_ERR "failed to add the ring dev\n");
goto error_device_put;
}
-
cdev_init(&buf->access_handler.chrdev, &iio_ring_fileops);
buf->access_handler.chrdev.owner = owner;
-
- ret = cdev_add(&buf->access_handler.chrdev, buf->access_dev.devt, 1);
+ ret = cdev_add(&buf->access_handler.chrdev, buf->dev.devt, 1);
if (ret) {
- printk(KERN_ERR "failed to allocate ring access chrdev\n");
+ printk(KERN_ERR "failed to allocate ring chrdev\n");
goto error_device_unregister;
}
return 0;
error_device_unregister:
- device_unregister(&buf->access_dev);
+ device_unregister(&buf->dev);
error_device_put:
- put_device(&buf->access_dev);
+ put_device(&buf->dev);
return ret;
}
-static void __iio_free_ring_buffer_access_chrdev(struct iio_ring_buffer *buf)
+static void __iio_free_ring_buffer_chrdev(struct iio_ring_buffer *buf)
{
- device_unregister(&buf->access_dev);
+ device_unregister(&buf->dev);
}
void iio_ring_buffer_init(struct iio_ring_buffer *ring,
struct iio_dev *dev_info)
{
- if (ring->access.mark_param_change)
- ring->access.mark_param_change(ring);
ring->indio_dev = dev_info;
- ring->ev_int.private = ring;
ring->access_handler.private = ring;
- ring->shared_ev_pointer.ev_p = NULL;
- spin_lock_init(&ring->shared_ev_pointer.lock);
+ init_waitqueue_head(&ring->pollq);
}
EXPORT_SYMBOL(iio_ring_buffer_init);
-int iio_ring_buffer_register(struct iio_ring_buffer *ring, int id)
+static ssize_t iio_show_scan_index(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", to_iio_dev_attr(attr)->c->scan_index);
+}
+
+static ssize_t iio_show_fixed_type(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ return sprintf(buf, "%c%d/%d>>%u\n",
+ this_attr->c->scan_type.sign,
+ this_attr->c->scan_type.realbits,
+ this_attr->c->scan_type.storagebits,
+ this_attr->c->scan_type.shift);
+}
+
+static ssize_t iio_scan_el_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
int ret;
+ struct iio_ring_buffer *ring = dev_get_drvdata(dev);
+
+ ret = iio_scan_mask_query(ring, to_iio_dev_attr(attr)->address);
+ if (ret < 0)
+ return ret;
+ return sprintf(buf, "%d\n", ret);
+}
- ring->id = id;
+static int iio_scan_mask_clear(struct iio_ring_buffer *ring, int bit)
+{
+ if (bit > IIO_MAX_SCAN_LENGTH)
+ return -EINVAL;
+ ring->scan_mask &= ~(1 << bit);
+ ring->scan_count--;
+ return 0;
+}
+
+static ssize_t iio_scan_el_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ int ret = 0;
+ bool state;
+ struct iio_ring_buffer *ring = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = ring->indio_dev;
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+
+ state = !(buf[0] == '0');
+ mutex_lock(&indio_dev->mlock);
+ if (indio_dev->currentmode == INDIO_RING_TRIGGERED) {
+ ret = -EBUSY;
+ goto error_ret;
+ }
+ ret = iio_scan_mask_query(ring, this_attr->address);
+ if (ret < 0)
+ goto error_ret;
+ if (!state && ret) {
+ ret = iio_scan_mask_clear(ring, this_attr->address);
+ if (ret)
+ goto error_ret;
+ } else if (state && !ret) {
+ ret = iio_scan_mask_set(ring, this_attr->address);
+ if (ret)
+ goto error_ret;
+ }
+
+error_ret:
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret ? ret : len;
+
+}
+
+static ssize_t iio_scan_el_ts_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_ring_buffer *ring = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n", ring->scan_timestamp);
+}
+
+static ssize_t iio_scan_el_ts_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ int ret = 0;
+ struct iio_ring_buffer *ring = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = ring->indio_dev;
+ bool state;
+ state = !(buf[0] == '0');
+ mutex_lock(&indio_dev->mlock);
+ if (indio_dev->currentmode == INDIO_RING_TRIGGERED) {
+ ret = -EBUSY;
+ goto error_ret;
+ }
+ ring->scan_timestamp = state;
+error_ret:
+ mutex_unlock(&indio_dev->mlock);
- dev_set_name(&ring->dev, "%s:buffer%d",
- dev_name(ring->dev.parent),
- ring->id);
- ret = device_add(&ring->dev);
+ return ret ? ret : len;
+}
+
+static int iio_ring_add_channel_sysfs(struct iio_ring_buffer *ring,
+ const struct iio_chan_spec *chan)
+{
+ int ret;
+
+ ret = __iio_add_chan_devattr("index", "scan_elements",
+ chan,
+ &iio_show_scan_index,
+ NULL,
+ 0,
+ 0,
+ &ring->dev,
+ &ring->scan_el_dev_attr_list);
if (ret)
goto error_ret;
- ret = __iio_request_ring_buffer_event_chrdev(ring,
- 0,
- ring->owner,
- &ring->dev);
+ ret = __iio_add_chan_devattr("type", "scan_elements",
+ chan,
+ &iio_show_fixed_type,
+ NULL,
+ 0,
+ 0,
+ &ring->dev,
+ &ring->scan_el_dev_attr_list);
if (ret)
- goto error_remove_device;
+ goto error_ret;
+
+ if (chan->type != IIO_TIMESTAMP)
+ ret = __iio_add_chan_devattr("en", "scan_elements",
+ chan,
+ &iio_scan_el_show,
+ &iio_scan_el_store,
+ chan->scan_index,
+ 0,
+ &ring->dev,
+ &ring->scan_el_dev_attr_list);
+ else
+ ret = __iio_add_chan_devattr("en", "scan_elements",
+ chan,
+ &iio_scan_el_ts_show,
+ &iio_scan_el_ts_store,
+ chan->scan_index,
+ 0,
+ &ring->dev,
+ &ring->scan_el_dev_attr_list);
+error_ret:
+ return ret;
+}
+
+static void iio_ring_remove_and_free_scan_dev_attr(struct iio_ring_buffer *ring,
+ struct iio_dev_attr *p)
+{
+ sysfs_remove_file_from_group(&ring->dev.kobj,
+ &p->dev_attr.attr, "scan_elements");
+ kfree(p->dev_attr.attr.name);
+ kfree(p);
+}
+
+static struct attribute *iio_scan_el_dummy_attrs[] = {
+ NULL
+};
+
+static struct attribute_group iio_scan_el_dummy_group = {
+ .name = "scan_elements",
+ .attrs = iio_scan_el_dummy_attrs
+};
+
+static void __iio_ring_attr_cleanup(struct iio_ring_buffer *ring)
+{
+ struct iio_dev_attr *p, *n;
+ int anydynamic = !list_empty(&ring->scan_el_dev_attr_list);
+ list_for_each_entry_safe(p, n,
+ &ring->scan_el_dev_attr_list, l)
+ iio_ring_remove_and_free_scan_dev_attr(ring, p);
+
+ if (ring->scan_el_attrs)
+ sysfs_remove_group(&ring->dev.kobj,
+ ring->scan_el_attrs);
+ else if (anydynamic)
+ sysfs_remove_group(&ring->dev.kobj,
+ &iio_scan_el_dummy_group);
+}
- ret = __iio_request_ring_buffer_access_chrdev(ring,
- 0,
- ring->owner);
+int iio_ring_buffer_register_ex(struct iio_ring_buffer *ring, int id,
+ const struct iio_chan_spec *channels,
+ int num_channels)
+{
+ int ret, i;
+ ret = __iio_request_ring_buffer_chrdev(ring, ring->owner, id);
if (ret)
- goto error_free_ring_buffer_event_chrdev;
+ goto error_ret;
if (ring->scan_el_attrs) {
ret = sysfs_create_group(&ring->dev.kobj,
@@ -266,29 +372,39 @@ int iio_ring_buffer_register(struct iio_ring_buffer *ring, int id)
if (ret) {
dev_err(&ring->dev,
"Failed to add sysfs scan elements\n");
- goto error_free_ring_buffer_event_chrdev;
+ goto error_free_ring_buffer_chrdev;
}
+ } else if (channels) {
+ ret = sysfs_create_group(&ring->dev.kobj,
+ &iio_scan_el_dummy_group);
+ if (ret)
+ goto error_free_ring_buffer_chrdev;
}
- return ret;
-error_free_ring_buffer_event_chrdev:
- __iio_free_ring_buffer_event_chrdev(ring);
-error_remove_device:
- device_del(&ring->dev);
+ INIT_LIST_HEAD(&ring->scan_el_dev_attr_list);
+ if (channels) {
+ /* new magic */
+ for (i = 0; i < num_channels; i++) {
+ ret = iio_ring_add_channel_sysfs(ring, &channels[i]);
+ if (ret < 0)
+ goto error_cleanup_dynamic;
+ }
+ }
+
+ return 0;
+error_cleanup_dynamic:
+ __iio_ring_attr_cleanup(ring);
+error_free_ring_buffer_chrdev:
+ __iio_free_ring_buffer_chrdev(ring);
error_ret:
return ret;
}
-EXPORT_SYMBOL(iio_ring_buffer_register);
+EXPORT_SYMBOL(iio_ring_buffer_register_ex);
void iio_ring_buffer_unregister(struct iio_ring_buffer *ring)
{
- if (ring->scan_el_attrs)
- sysfs_remove_group(&ring->dev.kobj,
- ring->scan_el_attrs);
-
- __iio_free_ring_buffer_access_chrdev(ring);
- __iio_free_ring_buffer_event_chrdev(ring);
- device_del(&ring->dev);
+ __iio_ring_attr_cleanup(ring);
+ __iio_free_ring_buffer_chrdev(ring);
}
EXPORT_SYMBOL(iio_ring_buffer_unregister);
@@ -296,14 +412,13 @@ ssize_t iio_read_ring_length(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- int len = 0;
struct iio_ring_buffer *ring = dev_get_drvdata(dev);
- if (ring->access.get_length)
- len = sprintf(buf, "%d\n",
- ring->access.get_length(ring));
+ if (ring->access->get_length)
+ return sprintf(buf, "%d\n",
+ ring->access->get_length(ring));
- return len;
+ return 0;
}
EXPORT_SYMBOL(iio_read_ring_length);
@@ -315,18 +430,19 @@ ssize_t iio_write_ring_length(struct device *dev,
int ret;
ulong val;
struct iio_ring_buffer *ring = dev_get_drvdata(dev);
+
ret = strict_strtoul(buf, 10, &val);
if (ret)
return ret;
- if (ring->access.get_length)
- if (val == ring->access.get_length(ring))
+ if (ring->access->get_length)
+ if (val == ring->access->get_length(ring))
return len;
- if (ring->access.set_length) {
- ring->access.set_length(ring, val);
- if (ring->access.mark_param_change)
- ring->access.mark_param_change(ring);
+ if (ring->access->set_length) {
+ ring->access->set_length(ring, val);
+ if (ring->access->mark_param_change)
+ ring->access->mark_param_change(ring);
}
return len;
@@ -337,14 +453,13 @@ ssize_t iio_read_ring_bytes_per_datum(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- int len = 0;
struct iio_ring_buffer *ring = dev_get_drvdata(dev);
- if (ring->access.get_bytes_per_datum)
- len = sprintf(buf, "%d\n",
- ring->access.get_bytes_per_datum(ring));
+ if (ring->access->get_bytes_per_datum)
+ return sprintf(buf, "%d\n",
+ ring->access->get_bytes_per_datum(ring));
- return len;
+ return 0;
}
EXPORT_SYMBOL(iio_read_ring_bytes_per_datum);
@@ -368,8 +483,8 @@ ssize_t iio_store_ring_enable(struct device *dev,
goto done;
}
if (requested_state) {
- if (ring->preenable) {
- ret = ring->preenable(dev_info);
+ if (ring->setup_ops->preenable) {
+ ret = ring->setup_ops->preenable(dev_info);
if (ret) {
printk(KERN_ERR
"Buffer not started:"
@@ -377,8 +492,8 @@ ssize_t iio_store_ring_enable(struct device *dev,
goto error_ret;
}
}
- if (ring->access.request_update) {
- ret = ring->access.request_update(ring);
+ if (ring->access->request_update) {
+ ret = ring->access->request_update(ring);
if (ret) {
printk(KERN_INFO
"Buffer not started:"
@@ -386,16 +501,16 @@ ssize_t iio_store_ring_enable(struct device *dev,
goto error_ret;
}
}
- if (ring->access.mark_in_use)
- ring->access.mark_in_use(ring);
+ if (ring->access->mark_in_use)
+ ring->access->mark_in_use(ring);
/* Definitely possible for devices to support both of these.*/
if (dev_info->modes & INDIO_RING_TRIGGERED) {
if (!dev_info->trig) {
printk(KERN_INFO
"Buffer not started: no trigger\n");
ret = -EINVAL;
- if (ring->access.unmark_in_use)
- ring->access.unmark_in_use(ring);
+ if (ring->access->unmark_in_use)
+ ring->access->unmark_in_use(ring);
goto error_ret;
}
dev_info->currentmode = INDIO_RING_TRIGGERED;
@@ -406,32 +521,31 @@ ssize_t iio_store_ring_enable(struct device *dev,
goto error_ret;
}
- if (ring->postenable) {
-
- ret = ring->postenable(dev_info);
+ if (ring->setup_ops->postenable) {
+ ret = ring->setup_ops->postenable(dev_info);
if (ret) {
printk(KERN_INFO
"Buffer not started:"
"postenable failed\n");
- if (ring->access.unmark_in_use)
- ring->access.unmark_in_use(ring);
+ if (ring->access->unmark_in_use)
+ ring->access->unmark_in_use(ring);
dev_info->currentmode = previous_mode;
- if (ring->postdisable)
- ring->postdisable(dev_info);
+ if (ring->setup_ops->postdisable)
+ ring->setup_ops->postdisable(dev_info);
goto error_ret;
}
}
} else {
- if (ring->predisable) {
- ret = ring->predisable(dev_info);
+ if (ring->setup_ops->predisable) {
+ ret = ring->setup_ops->predisable(dev_info);
if (ret)
goto error_ret;
}
- if (ring->access.unmark_in_use)
- ring->access.unmark_in_use(ring);
+ if (ring->access->unmark_in_use)
+ ring->access->unmark_in_use(ring);
dev_info->currentmode = INDIO_DIRECT_MODE;
- if (ring->postdisable) {
- ret = ring->postdisable(dev_info);
+ if (ring->setup_ops->postdisable) {
+ ret = ring->setup_ops->postdisable(dev_info);
if (ret)
goto error_ret;
}
@@ -445,6 +559,7 @@ error_ret:
return ret;
}
EXPORT_SYMBOL(iio_store_ring_enable);
+
ssize_t iio_show_ring_enable(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -455,89 +570,27 @@ ssize_t iio_show_ring_enable(struct device *dev,
}
EXPORT_SYMBOL(iio_show_ring_enable);
-ssize_t iio_scan_el_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int ret;
- struct iio_ring_buffer *ring = dev_get_drvdata(dev);
- struct iio_scan_el *this_el = to_iio_scan_el(attr);
-
- ret = iio_scan_mask_query(ring, this_el->number);
- if (ret < 0)
- return ret;
- return sprintf(buf, "%d\n", ret);
-}
-EXPORT_SYMBOL(iio_scan_el_show);
-
-ssize_t iio_scan_el_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- int ret = 0;
- bool state;
- struct iio_ring_buffer *ring = dev_get_drvdata(dev);
- struct iio_dev *indio_dev = ring->indio_dev;
- struct iio_scan_el *this_el = to_iio_scan_el(attr);
-
- state = !(buf[0] == '0');
- mutex_lock(&indio_dev->mlock);
- if (indio_dev->currentmode == INDIO_RING_TRIGGERED) {
- ret = -EBUSY;
- goto error_ret;
- }
- ret = iio_scan_mask_query(ring, this_el->number);
- if (ret < 0)
- goto error_ret;
- if (!state && ret) {
- ret = iio_scan_mask_clear(ring, this_el->number);
- if (ret)
- goto error_ret;
- } else if (state && !ret) {
- ret = iio_scan_mask_set(ring, this_el->number);
- if (ret)
- goto error_ret;
- }
- if (this_el->set_state)
- ret = this_el->set_state(this_el, indio_dev, state);
-error_ret:
- mutex_unlock(&indio_dev->mlock);
-
- return ret ? ret : len;
-
-}
-EXPORT_SYMBOL(iio_scan_el_store);
-
-ssize_t iio_scan_el_ts_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_ring_buffer *ring = dev_get_drvdata(dev);
- return sprintf(buf, "%d\n", ring->scan_timestamp);
-}
-EXPORT_SYMBOL(iio_scan_el_ts_show);
-
-ssize_t iio_scan_el_ts_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+int iio_sw_ring_preenable(struct iio_dev *indio_dev)
{
- int ret = 0;
- struct iio_ring_buffer *ring = dev_get_drvdata(dev);
- struct iio_dev *indio_dev = ring->indio_dev;
- bool state;
- state = !(buf[0] == '0');
- mutex_lock(&indio_dev->mlock);
- if (indio_dev->currentmode == INDIO_RING_TRIGGERED) {
- ret = -EBUSY;
- goto error_ret;
- }
- ring->scan_timestamp = state;
-error_ret:
- mutex_unlock(&indio_dev->mlock);
+ struct iio_ring_buffer *ring = indio_dev->ring;
+ size_t size;
+ dev_dbg(&indio_dev->dev, "%s\n", __func__);
+ /* Check if there are any scan elements enabled, if not fail*/
+ if (!(ring->scan_count || ring->scan_timestamp))
+ return -EINVAL;
+ if (ring->scan_timestamp)
+ if (ring->scan_count)
+ /* Timestamp (aligned to s64) and data */
+ size = (((ring->scan_count * ring->bpe)
+ + sizeof(s64) - 1)
+ & ~(sizeof(s64) - 1))
+ + sizeof(s64);
+ else /* Timestamp only */
+ size = sizeof(s64);
+ else /* Data only */
+ size = ring->scan_count * ring->bpe;
+ ring->access->set_bytes_per_datum(ring, size);
- return ret ? ret : len;
+ return 0;
}
-EXPORT_SYMBOL(iio_scan_el_ts_store);
-
+EXPORT_SYMBOL(iio_sw_ring_preenable);
diff --git a/drivers/staging/iio/industrialio-trigger.c b/drivers/staging/iio/industrialio-trigger.c
index 57dd9232cf0d..d504aa251ced 100644
--- a/drivers/staging/iio/industrialio-trigger.c
+++ b/drivers/staging/iio/industrialio-trigger.c
@@ -39,6 +39,19 @@ static LIST_HEAD(iio_trigger_list);
static DEFINE_MUTEX(iio_trigger_list_lock);
/**
+ * iio_trigger_read_name() - retrieve useful identifying name
+ **/
+static ssize_t iio_trigger_read_name(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_trigger *trig = dev_get_drvdata(dev);
+ return sprintf(buf, "%s\n", trig->name);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
+
+/**
* iio_trigger_register_sysfs() - create a device for this trigger
* @trig_info: the trigger
*
@@ -46,20 +59,16 @@ static DEFINE_MUTEX(iio_trigger_list_lock);
**/
static int iio_trigger_register_sysfs(struct iio_trigger *trig_info)
{
- int ret = 0;
-
- if (trig_info->control_attrs)
- ret = sysfs_create_group(&trig_info->dev.kobj,
- trig_info->control_attrs);
-
- return ret;
+ return sysfs_add_file_to_group(&trig_info->dev.kobj,
+ &dev_attr_name.attr,
+ NULL);
}
static void iio_trigger_unregister_sysfs(struct iio_trigger *trig_info)
{
- if (trig_info->control_attrs)
- sysfs_remove_group(&trig_info->dev.kobj,
- trig_info->control_attrs);
+ sysfs_remove_file_from_group(&trig_info->dev.kobj,
+ &dev_attr_name.attr,
+ NULL);
}
@@ -134,14 +143,8 @@ EXPORT_SYMBOL(iio_trigger_register);
void iio_trigger_unregister(struct iio_trigger *trig_info)
{
- struct iio_trigger *cursor;
-
mutex_lock(&iio_trigger_list_lock);
- list_for_each_entry(cursor, &iio_trigger_list, list)
- if (cursor == trig_info) {
- list_del(&cursor->list);
- break;
- }
+ list_del(&trig_info->list);
mutex_unlock(&iio_trigger_list_lock);
iio_trigger_unregister_sysfs(trig_info);
@@ -151,47 +154,55 @@ void iio_trigger_unregister(struct iio_trigger *trig_info)
}
EXPORT_SYMBOL(iio_trigger_unregister);
-struct iio_trigger *iio_trigger_find_by_name(const char *name, size_t len)
+static struct iio_trigger *iio_trigger_find_by_name(const char *name,
+ size_t len)
{
- struct iio_trigger *trig;
- bool found = false;
-
- if (len && name[len - 1] == '\n')
- len--;
+ struct iio_trigger *trig = NULL, *iter;
mutex_lock(&iio_trigger_list_lock);
- list_for_each_entry(trig, &iio_trigger_list, list) {
- if (strncmp(trig->name, name, len) == 0) {
- found = true;
+ list_for_each_entry(iter, &iio_trigger_list, list)
+ if (sysfs_streq(iter->name, name)) {
+ trig = iter;
break;
}
- }
mutex_unlock(&iio_trigger_list_lock);
- return found ? trig : NULL;
+ return trig;
}
-EXPORT_SYMBOL(iio_trigger_find_by_name);
void iio_trigger_poll(struct iio_trigger *trig, s64 time)
{
- struct iio_poll_func *pf_cursor;
-
- list_for_each_entry(pf_cursor, &trig->pollfunc_list, list) {
- if (pf_cursor->poll_func_immediate) {
- pf_cursor->poll_func_immediate(pf_cursor->private_data);
- trig->use_count++;
- }
- }
- list_for_each_entry(pf_cursor, &trig->pollfunc_list, list) {
- if (pf_cursor->poll_func_main) {
- pf_cursor->poll_func_main(pf_cursor->private_data,
- time);
- trig->use_count++;
- }
+ int i;
+ 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);
+irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private)
+{
+ iio_trigger_poll(private, iio_get_time_ns());
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(iio_trigger_generic_data_rdy_poll);
+
+void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time)
+{
+ int i;
+ if (!trig->use_count) {
+ for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++)
+ if (trig->subirqs[i].enabled) {
+ trig->use_count++;
+ handle_nested_irq(trig->subirq_base + i);
+ }
+ }
+}
+EXPORT_SYMBOL(iio_trigger_poll_chained);
+
void iio_trigger_notify_done(struct iio_trigger *trig)
{
trig->use_count--;
@@ -203,18 +214,6 @@ void iio_trigger_notify_done(struct iio_trigger *trig)
}
EXPORT_SYMBOL(iio_trigger_notify_done);
-/**
- * iio_trigger_read_name() - retrieve useful identifying name
- **/
-ssize_t iio_trigger_read_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_trigger *trig = dev_get_drvdata(dev);
- return sprintf(buf, "%s\n", trig->name);
-}
-EXPORT_SYMBOL(iio_trigger_read_name);
-
/* Trigger Consumer related functions */
/* Complexity in here. With certain triggers (datardy) an acknowledgement
@@ -228,18 +227,16 @@ int iio_trigger_attach_poll_func(struct iio_trigger *trig,
struct iio_poll_func *pf)
{
int ret = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&trig->pollfunc_list_lock, flags);
- list_add_tail(&pf->list, &trig->pollfunc_list);
- spin_unlock_irqrestore(&trig->pollfunc_list_lock, flags);
-
- if (trig->set_trigger_state)
+ bool notinuse
+ = bitmap_empty(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER);
+
+ 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 (ret) {
- printk(KERN_ERR "set trigger state failed\n");
- list_del(&pf->list);
- }
+
return ret;
}
EXPORT_SYMBOL(iio_trigger_attach_poll_func);
@@ -247,41 +244,69 @@ EXPORT_SYMBOL(iio_trigger_attach_poll_func);
int iio_trigger_dettach_poll_func(struct iio_trigger *trig,
struct iio_poll_func *pf)
{
- struct iio_poll_func *pf_cursor;
- unsigned long flags;
- int ret = -EINVAL;
-
- spin_lock_irqsave(&trig->pollfunc_list_lock, flags);
- list_for_each_entry(pf_cursor, &trig->pollfunc_list, list)
- if (pf_cursor == pf) {
- ret = 0;
- break;
- }
- if (!ret) {
- if (list_is_singular(&trig->pollfunc_list)
- && trig->set_trigger_state) {
- spin_unlock_irqrestore(&trig->pollfunc_list_lock,
- flags);
- /* May sleep hence cannot hold the spin lock */
- ret = trig->set_trigger_state(trig, false);
- if (ret)
- goto error_ret;
- spin_lock_irqsave(&trig->pollfunc_list_lock, flags);
- }
- /*
- * Now we can delete safe in the knowledge that, if this is
- * the last pollfunc then we have disabled the trigger anyway
- * and so nothing should be able to call the pollfunc.
- */
- list_del(&pf_cursor->list);
+ 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 (ret)
+ goto error_ret;
}
- spin_unlock_irqrestore(&trig->pollfunc_list_lock, flags);
+ iio_trigger_put_irq(trig, pf->irq);
+ free_irq(pf->irq, pf);
error_ret:
return ret;
}
EXPORT_SYMBOL(iio_trigger_dettach_poll_func);
+irqreturn_t iio_pollfunc_store_time(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ pf->timestamp = iio_get_time_ns();
+ return IRQ_WAKE_THREAD;
+}
+EXPORT_SYMBOL(iio_pollfunc_store_time);
+
+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,
+ ...)
+{
+ va_list vargs;
+ struct iio_poll_func *pf;
+
+ pf = kmalloc(sizeof *pf, GFP_KERNEL);
+ if (pf == NULL)
+ return NULL;
+ va_start(vargs, fmt);
+ pf->name = kvasprintf(GFP_KERNEL, fmt, vargs);
+ va_end(vargs);
+ if (pf->name == NULL) {
+ kfree(pf);
+ return NULL;
+ }
+ pf->h = h;
+ pf->thread = thread;
+ pf->type = type;
+ pf->private_data = private;
+
+ return pf;
+}
+EXPORT_SYMBOL_GPL(iio_alloc_pollfunc);
+
+void iio_dealloc_pollfunc(struct iio_poll_func *pf)
+{
+ kfree(pf->name);
+ kfree(pf);
+}
+EXPORT_SYMBOL_GPL(iio_dealloc_pollfunc);
+
/**
* iio_trigger_read_currrent() - trigger consumer sysfs query which trigger
*
@@ -348,6 +373,23 @@ static const struct attribute_group iio_trigger_consumer_attr_group = {
static void iio_trig_release(struct device *device)
{
struct iio_trigger *trig = to_iio_trigger(device);
+ int i;
+
+ if (trig->subirq_base) {
+ for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) {
+ irq_modify_status(trig->subirq_base + i,
+ IRQ_NOAUTOEN,
+ IRQ_NOREQUEST | IRQ_NOPROBE);
+ irq_set_chip(trig->subirq_base + i,
+ NULL);
+ irq_set_handler(trig->subirq_base + i,
+ NULL);
+ }
+
+ irq_free_descs(trig->subirq_base,
+ CONFIG_IIO_CONSUMERS_PER_TRIGGER);
+ }
+ kfree(trig->name);
kfree(trig);
iio_put();
}
@@ -356,18 +398,66 @@ static struct device_type iio_trig_type = {
.release = iio_trig_release,
};
-struct iio_trigger *iio_allocate_trigger(void)
+static void iio_trig_subirqmask(struct irq_data *d)
+{
+ struct irq_chip *chip = irq_data_get_irq_chip(d);
+ struct iio_trigger *trig
+ = container_of(chip,
+ struct iio_trigger, subirq_chip);
+ trig->subirqs[d->irq - trig->subirq_base].enabled = false;
+}
+
+static void iio_trig_subirqunmask(struct irq_data *d)
+{
+ struct irq_chip *chip = irq_data_get_irq_chip(d);
+ struct iio_trigger *trig
+ = container_of(chip,
+ struct iio_trigger, subirq_chip);
+ trig->subirqs[d->irq - trig->subirq_base].enabled = true;
+}
+
+struct iio_trigger *iio_allocate_trigger(const char *fmt, ...)
{
+ va_list vargs;
struct iio_trigger *trig;
trig = kzalloc(sizeof *trig, GFP_KERNEL);
if (trig) {
+ int i;
trig->dev.type = &iio_trig_type;
trig->dev.bus = &iio_bus_type;
device_initialize(&trig->dev);
dev_set_drvdata(&trig->dev, (void *)trig);
- spin_lock_init(&trig->pollfunc_list_lock);
- INIT_LIST_HEAD(&trig->list);
- INIT_LIST_HEAD(&trig->pollfunc_list);
+
+ mutex_init(&trig->pool_lock);
+ trig->subirq_base
+ = irq_alloc_descs(-1, 0,
+ CONFIG_IIO_CONSUMERS_PER_TRIGGER,
+ 0);
+ if (trig->subirq_base < 0) {
+ kfree(trig);
+ return NULL;
+ }
+ va_start(vargs, fmt);
+ trig->name = kvasprintf(GFP_KERNEL, fmt, vargs);
+ va_end(vargs);
+ if (trig->name == NULL) {
+ irq_free_descs(trig->subirq_base,
+ CONFIG_IIO_CONSUMERS_PER_TRIGGER);
+ kfree(trig);
+ return NULL;
+ }
+ trig->subirq_chip.name = trig->name;
+ trig->subirq_chip.irq_mask = &iio_trig_subirqmask;
+ trig->subirq_chip.irq_unmask = &iio_trig_subirqunmask;
+ for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) {
+ irq_set_chip(trig->subirq_base + i,
+ &trig->subirq_chip);
+ irq_set_handler(trig->subirq_base + i,
+ &handle_simple_irq);
+ irq_modify_status(trig->subirq_base + i,
+ IRQ_NOREQUEST | IRQ_NOAUTOEN,
+ IRQ_NOPROBE);
+ }
iio_get();
}
return trig;
@@ -398,20 +488,6 @@ int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info)
}
EXPORT_SYMBOL(iio_device_unregister_trigger_consumer);
-int iio_alloc_pollfunc(struct iio_dev *indio_dev,
- void (*immediate)(struct iio_dev *indio_dev),
- void (*main)(struct iio_dev *private_data, s64 time))
-{
- indio_dev->pollfunc = kzalloc(sizeof(*indio_dev->pollfunc), GFP_KERNEL);
- if (indio_dev->pollfunc == NULL)
- return -ENOMEM;
- indio_dev->pollfunc->poll_func_immediate = immediate;
- indio_dev->pollfunc->poll_func_main = main;
- indio_dev->pollfunc->private_data = indio_dev;
- return 0;
-}
-EXPORT_SYMBOL(iio_alloc_pollfunc);
-
int iio_triggered_ring_postenable(struct iio_dev *indio_dev)
{
return indio_dev->trig
diff --git a/drivers/staging/iio/kfifo_buf.c b/drivers/staging/iio/kfifo_buf.c
index a56c0cbba94b..cc14b96d814c 100644
--- a/drivers/staging/iio/kfifo_buf.c
+++ b/drivers/staging/iio/kfifo_buf.c
@@ -8,6 +8,8 @@
#include "kfifo_buf.h"
+#define iio_to_kfifo(r) container_of(r, struct iio_kfifo, ring)
+
static inline int __iio_allocate_kfifo(struct iio_kfifo *buf,
int bytes_per_datum, int length)
{
@@ -18,7 +20,7 @@ static inline int __iio_allocate_kfifo(struct iio_kfifo *buf,
return kfifo_alloc(&buf->kf, bytes_per_datum*length, GFP_KERNEL);
}
-int iio_request_update_kfifo(struct iio_ring_buffer *r)
+static int iio_request_update_kfifo(struct iio_ring_buffer *r)
{
int ret = 0;
struct iio_kfifo *buf = iio_to_kfifo(r);
@@ -37,31 +39,27 @@ error_ret:
mutex_unlock(&buf->use_lock);
return ret;
}
-EXPORT_SYMBOL(iio_request_update_kfifo);
-void iio_mark_kfifo_in_use(struct iio_ring_buffer *r)
+static void iio_mark_kfifo_in_use(struct iio_ring_buffer *r)
{
struct iio_kfifo *buf = iio_to_kfifo(r);
mutex_lock(&buf->use_lock);
buf->use_count++;
mutex_unlock(&buf->use_lock);
}
-EXPORT_SYMBOL(iio_mark_kfifo_in_use);
-void iio_unmark_kfifo_in_use(struct iio_ring_buffer *r)
+static void iio_unmark_kfifo_in_use(struct iio_ring_buffer *r)
{
struct iio_kfifo *buf = iio_to_kfifo(r);
mutex_lock(&buf->use_lock);
buf->use_count--;
mutex_unlock(&buf->use_lock);
}
-EXPORT_SYMBOL(iio_unmark_kfifo_in_use);
-int iio_get_length_kfifo(struct iio_ring_buffer *r)
+static int iio_get_length_kfifo(struct iio_ring_buffer *r)
{
return r->length;
}
-EXPORT_SYMBOL(iio_get_length_kfifo);
static inline void __iio_init_kfifo(struct iio_kfifo *kf)
{
@@ -108,6 +106,7 @@ struct iio_ring_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev)
kf = kzalloc(sizeof *kf, GFP_KERNEL);
if (!kf)
return NULL;
+ kf->update_needed = true;
iio_ring_buffer_init(&kf->ring, indio_dev);
__iio_init_kfifo(kf);
kf->ring.dev.type = &iio_kfifo_type;
@@ -120,41 +119,37 @@ struct iio_ring_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev)
}
EXPORT_SYMBOL(iio_kfifo_allocate);
-int iio_get_bytes_per_datum_kfifo(struct iio_ring_buffer *r)
+static int iio_get_bytes_per_datum_kfifo(struct iio_ring_buffer *r)
{
return r->bytes_per_datum;
}
-EXPORT_SYMBOL(iio_get_bytes_per_datum_kfifo);
-int iio_set_bytes_per_datum_kfifo(struct iio_ring_buffer *r, size_t bpd)
+static int iio_set_bytes_per_datum_kfifo(struct iio_ring_buffer *r, size_t bpd)
{
if (r->bytes_per_datum != bpd) {
r->bytes_per_datum = bpd;
- if (r->access.mark_param_change)
- r->access.mark_param_change(r);
+ if (r->access->mark_param_change)
+ r->access->mark_param_change(r);
}
return 0;
}
-EXPORT_SYMBOL(iio_set_bytes_per_datum_kfifo);
-int iio_mark_update_needed_kfifo(struct iio_ring_buffer *r)
+static int iio_mark_update_needed_kfifo(struct iio_ring_buffer *r)
{
struct iio_kfifo *kf = iio_to_kfifo(r);
kf->update_needed = true;
return 0;
}
-EXPORT_SYMBOL(iio_mark_update_needed_kfifo);
-int iio_set_length_kfifo(struct iio_ring_buffer *r, int length)
+static int iio_set_length_kfifo(struct iio_ring_buffer *r, int length)
{
if (r->length != length) {
r->length = length;
- if (r->access.mark_param_change)
- r->access.mark_param_change(r);
+ if (r->access->mark_param_change)
+ r->access->mark_param_change(r);
}
return 0;
}
-EXPORT_SYMBOL(iio_set_length_kfifo);
void iio_kfifo_free(struct iio_ring_buffer *r)
{
@@ -163,7 +158,9 @@ void iio_kfifo_free(struct iio_ring_buffer *r)
}
EXPORT_SYMBOL(iio_kfifo_free);
-int iio_store_to_kfifo(struct iio_ring_buffer *r, u8 *data, s64 timestamp)
+static int iio_store_to_kfifo(struct iio_ring_buffer *r,
+ u8 *data,
+ s64 timestamp)
{
int ret;
struct iio_kfifo *kf = iio_to_kfifo(r);
@@ -179,18 +176,30 @@ int iio_store_to_kfifo(struct iio_ring_buffer *r, u8 *data, s64 timestamp)
kfree(datal);
return 0;
}
-EXPORT_SYMBOL(iio_store_to_kfifo);
-int iio_rip_kfifo(struct iio_ring_buffer *r,
- size_t count, char __user *buf, int *deadoffset)
+static int iio_read_first_n_kfifo(struct iio_ring_buffer *r,
+ size_t n, char __user *buf)
{
int ret, copied;
struct iio_kfifo *kf = iio_to_kfifo(r);
- *deadoffset = 0;
- ret = kfifo_to_user(&kf->kf, buf, r->bytes_per_datum*count, &copied);
+ ret = kfifo_to_user(&kf->kf, buf, r->bytes_per_datum*n, &copied);
return copied;
}
-EXPORT_SYMBOL(iio_rip_kfifo);
+
+const struct iio_ring_access_funcs kfifo_access_funcs = {
+ .mark_in_use = &iio_mark_kfifo_in_use,
+ .unmark_in_use = &iio_unmark_kfifo_in_use,
+ .store_to = &iio_store_to_kfifo,
+ .read_first_n = &iio_read_first_n_kfifo,
+ .mark_param_change = &iio_mark_update_needed_kfifo,
+ .request_update = &iio_request_update_kfifo,
+ .get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo,
+ .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo,
+ .get_length = &iio_get_length_kfifo,
+ .set_length = &iio_set_length_kfifo,
+};
+EXPORT_SYMBOL(kfifo_access_funcs);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/iio/kfifo_buf.h b/drivers/staging/iio/kfifo_buf.h
index 8064383bf7c3..aac30539b2c6 100644
--- a/drivers/staging/iio/kfifo_buf.h
+++ b/drivers/staging/iio/kfifo_buf.h
@@ -11,45 +11,7 @@ struct iio_kfifo {
struct mutex use_lock;
};
-#define iio_to_kfifo(r) container_of(r, struct iio_kfifo, ring)
-
-int iio_create_kfifo(struct iio_ring_buffer **r);
-int iio_init_kfifo(struct iio_ring_buffer *r, struct iio_dev *indio_dev);
-void iio_exit_kfifo(struct iio_ring_buffer *r);
-void iio_free_kfifo(struct iio_ring_buffer *r);
-void iio_mark_kfifo_in_use(struct iio_ring_buffer *r);
-void iio_unmark_kfifo_in_use(struct iio_ring_buffer *r);
-
-int iio_store_to_kfifo(struct iio_ring_buffer *r, u8 *data, s64 timestamp);
-int iio_rip_kfifo(struct iio_ring_buffer *r,
- size_t count,
- char __user *buf,
- int *dead_offset);
-
-int iio_request_update_kfifo(struct iio_ring_buffer *r);
-int iio_mark_update_needed_kfifo(struct iio_ring_buffer *r);
-
-int iio_get_bytes_per_datum_kfifo(struct iio_ring_buffer *r);
-int iio_set_bytes_per_datum_kfifo(struct iio_ring_buffer *r, size_t bpd);
-int iio_get_length_kfifo(struct iio_ring_buffer *r);
-int iio_set_length_kfifo(struct iio_ring_buffer *r, int length);
-
-static inline void iio_kfifo_register_funcs(struct iio_ring_access_funcs *ra)
-{
- ra->mark_in_use = &iio_mark_kfifo_in_use;
- ra->unmark_in_use = &iio_unmark_kfifo_in_use;
-
- ra->store_to = &iio_store_to_kfifo;
- ra->rip_lots = &iio_rip_kfifo;
-
- ra->mark_param_change = &iio_mark_update_needed_kfifo;
- ra->request_update = &iio_request_update_kfifo;
-
- ra->get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo;
- ra->set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo;
- ra->get_length = &iio_get_length_kfifo;
- ra->set_length = &iio_set_length_kfifo;
-};
+extern const struct iio_ring_access_funcs kfifo_access_funcs;
struct iio_ring_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev);
void iio_kfifo_free(struct iio_ring_buffer *r);
diff --git a/drivers/staging/iio/light/Kconfig b/drivers/staging/iio/light/Kconfig
index 36d8bbe1a9cc..46d62d1b0370 100644
--- a/drivers/staging/iio/light/Kconfig
+++ b/drivers/staging/iio/light/Kconfig
@@ -1,18 +1,8 @@
-#
+\#
# Light sensors
#
comment "Light sensors"
-config SENSORS_TSL2563
- tristate "TAOS TSL256[0-3] ambient light sensor"
- depends on I2C
- help
- If you say yes here you get support for the Taos TSL2560,
- TSL2561, TSL2562 and TSL2563 ambient light sensors.
-
- This driver can also be built as a module. If so, the module
- will be called tsl2563.
-
config SENSORS_ISL29018
tristate "ISL 29018 light and proximity sensor"
depends on I2C
@@ -24,3 +14,19 @@ config SENSORS_ISL29018
in lux, proximity infrared sensing and normal infrared sensing.
Data from sensor is accessible via sysfs.
+config SENSORS_TSL2563
+ tristate "TAOS TSL2560, TSL2561, TSL2562 and TSL2563 ambient light sensors"
+ depends on I2C
+ help
+ If you say yes here you get support for the Taos TSL2560,
+ TSL2561, TSL2562 and TSL2563 ambient light sensors.
+
+ This driver can also be built as a module. If so, the module
+ will be called tsl2563.
+
+config TSL2583
+ tristate "TAOS TSL2580, TSL2581 and TSL2583 light-to-digital converters"
+ depends on I2C
+ help
+ Provides support for the TAOS tsl2580, tsl2581 and tsl2583 devices.
+ Access ALS data via iio, sysfs.
diff --git a/drivers/staging/iio/light/Makefile b/drivers/staging/iio/light/Makefile
index 9142c0e5a1b6..3011fbfa8dc2 100644
--- a/drivers/staging/iio/light/Makefile
+++ b/drivers/staging/iio/light/Makefile
@@ -4,3 +4,4 @@
obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
obj-$(CONFIG_SENSORS_ISL29018) += isl29018.o
+obj-$(CONFIG_TSL2583) += tsl2583.o
diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
index f919cc1d35e1..4794ffd5e446 100644
--- a/drivers/staging/iio/light/isl29018.c
+++ b/drivers/staging/iio/light/isl29018.c
@@ -402,16 +402,6 @@ static ssize_t show_proxim_ir(struct device *dev,
return get_sensor_data(dev, buf, COMMMAND1_OPMODE_PROX_ONCE);
}
-/* Read name */
-static ssize_t show_name(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct isl29018_chip *chip = indio_dev->dev_data;
-
- return sprintf(buf, "%s\n", chip->client->name);
-}
-
static IIO_DEVICE_ATTR(range, S_IRUGO | S_IWUSR, show_range, store_range, 0);
static IIO_CONST_ATTR(range_available, "1000 4000 16000 64000");
static IIO_CONST_ATTR(adc_resolution_available, "4 8 12 16");
@@ -424,12 +414,10 @@ static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_supression,
static IIO_DEVICE_ATTR(illuminance0_input, S_IRUGO, show_lux, NULL, 0);
static IIO_DEVICE_ATTR(intensity_infrared_raw, S_IRUGO, show_ir, NULL, 0);
static IIO_DEVICE_ATTR(proximity_raw, S_IRUGO, show_proxim_ir, NULL, 0);
-static IIO_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
#define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr)
#define ISL29018_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr)
static struct attribute *isl29018_attributes[] = {
- ISL29018_DEV_ATTR(name),
ISL29018_DEV_ATTR(range),
ISL29018_CONST_ATTR(range_available),
ISL29018_DEV_ATTR(adc_resolution),
@@ -467,6 +455,11 @@ static int isl29018_chip_init(struct i2c_client *client)
return 0;
}
+static const struct iio_info isl29108_info = {
+ .attrs = &isl29108_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit isl29018_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -492,15 +485,15 @@ static int __devinit isl29018_probe(struct i2c_client *client,
if (err)
goto exit_free;
- chip->indio_dev = iio_allocate_device();
+ chip->indio_dev = iio_allocate_device(0);
if (!chip->indio_dev) {
dev_err(&client->dev, "iio allocation fails\n");
goto exit_free;
}
- chip->indio_dev->attrs = &isl29108_group;
+ chip->indio_dev->info = &isl29108_info;
+ chip->indio_dev->name = id->name;
chip->indio_dev->dev.parent = &client->dev;
chip->indio_dev->dev_data = (void *)(chip);
- chip->indio_dev->driver_module = THIS_MODULE;
chip->indio_dev->modes = INDIO_DIRECT_MODE;
err = iio_device_register(chip->indio_dev);
if (err) {
diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c
index dadae7527d5c..9cffa2ecb0ee 100644
--- a/drivers/staging/iio/light/tsl2563.c
+++ b/drivers/staging/iio/light/tsl2563.c
@@ -92,7 +92,7 @@ struct tsl2563_gainlevel_coeff {
u16 max;
};
-static struct tsl2563_gainlevel_coeff tsl2563_gainlevel_table[] = {
+static const struct tsl2563_gainlevel_coeff tsl2563_gainlevel_table[] = {
{
.gaintime = TSL2563_TIMING_400MS | TSL2563_TIMING_GAIN16,
.min = 0,
@@ -115,15 +115,12 @@ static struct tsl2563_gainlevel_coeff tsl2563_gainlevel_table[] = {
struct tsl2563_chip {
struct mutex lock;
struct i2c_client *client;
- struct iio_dev *indio_dev;
struct delayed_work poweroff_work;
- struct work_struct work_thresh;
- s64 event_timestamp;
/* Remember state for suspend and resume functions */
pm_message_t state;
- struct tsl2563_gainlevel_coeff *gainlevel;
+ struct tsl2563_gainlevel_coeff const *gainlevel;
u16 low_thres;
u16 high_thres;
@@ -467,32 +464,6 @@ static unsigned int adc_to_lux(u32 adc0, u32 adc1)
/* Sysfs interface */
/*--------------------------------------------------------------*/
-static ssize_t tsl2563_adc_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2563_chip *chip = indio_dev->dev_data;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int ret;
-
- mutex_lock(&chip->lock);
-
- ret = tsl2563_get_adc(chip);
- if (ret)
- goto out;
-
- switch (this_attr->address) {
- case 0:
- ret = snprintf(buf, PAGE_SIZE, "%d\n", chip->data0);
- break;
- case 1:
- ret = snprintf(buf, PAGE_SIZE, "%d\n", chip->data1);
- break;
- }
-out:
- mutex_unlock(&chip->lock);
- return ret;
-}
/* Apply calibration coefficient to ADC count. */
static u32 calib_adc(u32 adc, u32 calib)
@@ -505,237 +476,165 @@ static u32 calib_adc(u32 adc, u32 calib)
return (u32) scaled;
}
-static ssize_t tsl2563_lux_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static int tsl2563_write_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 tsl2563_chip *chip = indio_dev->dev_data;
- u32 calib0, calib1;
- int ret;
-
- mutex_lock(&chip->lock);
+ struct tsl2563_chip *chip = iio_priv(indio_dev);
- ret = tsl2563_get_adc(chip);
- if (ret)
- goto out;
-
- calib0 = calib_adc(chip->data0, chip->calib0) * chip->cover_comp_gain;
- calib1 = calib_adc(chip->data1, chip->calib1) * chip->cover_comp_gain;
-
- ret = snprintf(buf, PAGE_SIZE, "%d\n", adc_to_lux(calib0, calib1));
-
-out:
- mutex_unlock(&chip->lock);
- return ret;
-}
+ if (chan->channel == 0)
+ chip->calib0 = calib_from_sysfs(val);
+ else
+ chip->calib1 = calib_from_sysfs(val);
-static ssize_t format_calib(char *buf, int len, u32 calib)
-{
- return snprintf(buf, PAGE_SIZE, "%d\n", calib_to_sysfs(calib));
+ return 0;
}
-static ssize_t tsl2563_calib_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static int tsl2563_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2563_chip *chip = indio_dev->dev_data;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int ret;
+ int ret = -EINVAL;
+ u32 calib0, calib1;
+ struct tsl2563_chip *chip = iio_priv(indio_dev);
mutex_lock(&chip->lock);
- switch (this_attr->address) {
+ switch (m) {
case 0:
- ret = format_calib(buf, PAGE_SIZE, chip->calib0);
+ switch (chan->type) {
+ case IIO_LIGHT:
+ ret = tsl2563_get_adc(chip);
+ if (ret)
+ goto error_ret;
+ calib0 = calib_adc(chip->data0, chip->calib0) *
+ chip->cover_comp_gain;
+ calib1 = calib_adc(chip->data1, chip->calib1) *
+ chip->cover_comp_gain;
+ *val = adc_to_lux(calib0, calib1);
+ ret = IIO_VAL_INT;
+ break;
+ case IIO_INTENSITY:
+ ret = tsl2563_get_adc(chip);
+ if (ret)
+ goto error_ret;
+ if (chan->channel == 0)
+ *val = chip->data0;
+ else
+ *val = chip->data1;
+ ret = IIO_VAL_INT;
+ break;
+ default:
+ break;
+ }
break;
- case 1:
- ret = format_calib(buf, PAGE_SIZE, chip->calib1);
+
+ case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ if (chan->channel == 0)
+ *val = calib_to_sysfs(chip->calib0);
+ else
+ *val = calib_to_sysfs(chip->calib1);
+ ret = IIO_VAL_INT;
break;
default:
- ret = -ENODEV;
- }
- mutex_unlock(&chip->lock);
- return ret;
-}
-
-static ssize_t tsl2563_calib_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2563_chip *chip = indio_dev->dev_data;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int value;
- u32 calib;
-
- if (1 != sscanf(buf, "%d", &value))
return -EINVAL;
-
- calib = calib_from_sysfs(value);
-
- switch (this_attr->address) {
- case 0:
- chip->calib0 = calib;
- break;
- case 1:
- chip->calib1 = calib;
- break;
}
- return len;
-}
-
-static IIO_DEVICE_ATTR(intensity0_both_raw, S_IRUGO,
- tsl2563_adc_show, NULL, 0);
-static IIO_DEVICE_ATTR(intensity1_ir_raw, S_IRUGO,
- tsl2563_adc_show, NULL, 1);
-static DEVICE_ATTR(illuminance0_input, S_IRUGO, tsl2563_lux_show, NULL);
-static IIO_DEVICE_ATTR(intensity0_both_calibgain, S_IRUGO | S_IWUSR,
- tsl2563_calib_show, tsl2563_calib_store, 0);
-static IIO_DEVICE_ATTR(intensity1_ir_calibgain, S_IRUGO | S_IWUSR,
- tsl2563_calib_show, tsl2563_calib_store, 1);
-
-static ssize_t tsl2563_show_name(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2563_chip *chip = indio_dev->dev_data;
- return sprintf(buf, "%s\n", chip->client->name);
+error_ret:
+ mutex_unlock(&chip->lock);
+ return ret;
}
-static DEVICE_ATTR(name, S_IRUGO, tsl2563_show_name, NULL);
-
-static struct attribute *tsl2563_attributes[] = {
- &iio_dev_attr_intensity0_both_raw.dev_attr.attr,
- &iio_dev_attr_intensity1_ir_raw.dev_attr.attr,
- &dev_attr_illuminance0_input.attr,
- &iio_dev_attr_intensity0_both_calibgain.dev_attr.attr,
- &iio_dev_attr_intensity1_ir_calibgain.dev_attr.attr,
- &dev_attr_name.attr,
- NULL
+static const struct iio_chan_spec tsl2563_channels[] = {
+ IIO_CHAN(IIO_LIGHT, 0, 1, 1, NULL, 0, 0, 0, 0, 0, {}, 0),
+ IIO_CHAN(IIO_INTENSITY, 1, 1, 0, "both", 0,
+ (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), 0, 0, 0, {},
+ IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |
+ IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)),
+ IIO_CHAN(IIO_INTENSITY, 1, 1, 0, "ir", 1,
+ (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), 0, 0, 0, {},
+ 0)
};
-static const struct attribute_group tsl2563_group = {
- .attrs = tsl2563_attributes,
-};
-
-static ssize_t tsl2563_read_thresh(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int tsl2563_read_thresh(struct iio_dev *indio_dev,
+ int event_code,
+ int *val)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2563_chip *chip = indio_dev->dev_data;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- u16 val = 0;
- switch (this_attr->address) {
- case TSL2563_REG_HIGHLOW:
- val = chip->high_thres;
+ struct tsl2563_chip *chip = iio_priv(indio_dev);
+
+ switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
+ case IIO_EV_DIR_RISING:
+ *val = chip->high_thres;
break;
- case TSL2563_REG_LOWLOW:
- val = chip->low_thres;
+ case IIO_EV_DIR_FALLING:
+ *val = chip->low_thres;
break;
+ default:
+ return -EINVAL;
}
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+
+ return 0;
}
-static ssize_t tsl2563_write_thresh(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+static ssize_t tsl2563_write_thresh(struct iio_dev *indio_dev,
+ int event_code,
+ int val)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2563_chip *chip = indio_dev->dev_data;
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- unsigned long val;
+ struct tsl2563_chip *chip = iio_priv(indio_dev);
int ret;
+ u8 address;
- ret = strict_strtoul(buf, 10, &val);
- if (ret)
- return ret;
+ if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING)
+ address = TSL2563_REG_HIGHLOW;
+ else
+ address = TSL2563_REG_LOWLOW;
mutex_lock(&chip->lock);
- ret = tsl2563_write(chip->client, this_attr->address, val & 0xFF);
+ ret = tsl2563_write(chip->client, address, val & 0xFF);
if (ret)
goto error_ret;
- ret = tsl2563_write(chip->client, this_attr->address + 1,
+ ret = tsl2563_write(chip->client, address + 1,
(val >> 8) & 0xFF);
- switch (this_attr->address) {
- case TSL2563_REG_HIGHLOW:
+ if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING)
chip->high_thres = val;
- break;
- case TSL2563_REG_LOWLOW:
+ else
chip->low_thres = val;
- break;
- }
error_ret:
mutex_unlock(&chip->lock);
- return ret < 0 ? ret : len;
-}
-
-static IIO_DEVICE_ATTR(intensity0_both_raw_thresh_rising_value,
- S_IRUGO | S_IWUSR,
- tsl2563_read_thresh,
- tsl2563_write_thresh,
- TSL2563_REG_HIGHLOW);
-
-static IIO_DEVICE_ATTR(intensity0_both_raw_thresh_falling_value,
- S_IRUGO | S_IWUSR,
- tsl2563_read_thresh,
- tsl2563_write_thresh,
- TSL2563_REG_LOWLOW);
-
-static int tsl2563_int_th(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int not_test)
-{
- struct tsl2563_chip *chip = dev_info->dev_data;
-
- chip->event_timestamp = timestamp;
- schedule_work(&chip->work_thresh);
-
- return 0;
+ return ret;
}
-static void tsl2563_int_bh(struct work_struct *work_s)
+static irqreturn_t tsl2563_event_handler(int irq, void *private)
{
- struct tsl2563_chip *chip
- = container_of(work_s,
- struct tsl2563_chip, work_thresh);
+ struct iio_dev *dev_info = private;
+ struct tsl2563_chip *chip = iio_priv(dev_info);
u8 cmd = TSL2563_CMD | TSL2563_CLEARINT;
- iio_push_event(chip->indio_dev, 0,
+ iio_push_event(dev_info, 0,
IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_LIGHT,
0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_EITHER),
- chip->event_timestamp);
+ iio_get_time_ns());
- /* reenable_irq */
- enable_irq(chip->client->irq);
/* clear the interrupt and push the event */
i2c_master_send(chip->client, &cmd, sizeof(cmd));
-
+ return IRQ_HANDLED;
}
-static ssize_t tsl2563_write_interrupt_config(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+static int tsl2563_write_interrupt_config(struct iio_dev *indio_dev,
+ int event_code,
+ int state)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2563_chip *chip = indio_dev->dev_data;
- struct iio_event_attr *this_attr = to_iio_event_attr(attr);
- int input, ret = 0;
+ struct tsl2563_chip *chip = iio_priv(indio_dev);
+ int ret = 0;
- ret = sscanf(buf, "%d", &input);
- if (ret != 1)
- return -EINVAL;
mutex_lock(&chip->lock);
- if (input && !(chip->intr & 0x30)) {
- iio_add_event_to_list(this_attr->listel,
- &indio_dev->interrupts[0]->ev_list);
+ if (state && !(chip->intr & 0x30)) {
chip->intr &= ~0x30;
chip->intr |= 0x10;
/* ensure the chip is actually on */
@@ -752,11 +651,9 @@ static ssize_t tsl2563_write_interrupt_config(struct device *dev,
chip->int_enabled = true;
}
- if (!input && (chip->intr & 0x30)) {
+ if (!state && (chip->intr & 0x30)) {
chip->intr |= ~0x30;
ret = tsl2563_write(chip->client, TSL2563_REG_INT, chip->intr);
- iio_remove_event_from_list(this_attr->listel,
- &indio_dev->interrupts[0]->ev_list);
chip->int_enabled = false;
/* now the interrupt is not enabled, we can go to sleep */
schedule_delayed_work(&chip->poweroff_work, 5 * HZ);
@@ -764,69 +661,64 @@ static ssize_t tsl2563_write_interrupt_config(struct device *dev,
out:
mutex_unlock(&chip->lock);
- return (ret < 0) ? ret : len;
+ return ret;
}
-static ssize_t tsl2563_read_interrupt_config(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int tsl2563_read_interrupt_config(struct iio_dev *indio_dev,
+ int event_code)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct tsl2563_chip *chip = indio_dev->dev_data;
- int ret;
+ struct tsl2563_chip *chip = iio_priv(indio_dev);
u8 rxbuf;
- ssize_t len;
+ int ret;
mutex_lock(&chip->lock);
- ret = tsl2563_read(chip->client,
- TSL2563_REG_INT,
- &rxbuf,
- sizeof(rxbuf));
+ ret = tsl2563_read(chip->client, TSL2563_REG_INT,
+ &rxbuf, sizeof(rxbuf));
mutex_unlock(&chip->lock);
if (ret < 0)
goto error_ret;
- len = snprintf(buf, PAGE_SIZE, "%d\n", !!(rxbuf & 0x30));
+ ret = !!(rxbuf & 0x30);
error_ret:
- return (ret < 0) ? ret : len;
+ return ret;
}
-IIO_EVENT_ATTR(intensity0_both_thresh_en,
- tsl2563_read_interrupt_config,
- tsl2563_write_interrupt_config,
- 0,
- tsl2563_int_th);
-
-static struct attribute *tsl2563_event_attributes[] = {
- &iio_event_attr_intensity0_both_thresh_en.dev_attr.attr,
- &iio_dev_attr_intensity0_both_raw_thresh_rising_value.dev_attr.attr,
- &iio_dev_attr_intensity0_both_raw_thresh_falling_value.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group tsl2563_event_attribute_group = {
- .attrs = tsl2563_event_attributes,
-};
-
/*--------------------------------------------------------------*/
/* Probe, Attach, Remove */
/*--------------------------------------------------------------*/
static struct i2c_driver tsl2563_i2c_driver;
+static const struct iio_info tsl2563_info_no_irq = {
+ .driver_module = THIS_MODULE,
+};
+
+static const struct iio_info tsl2563_info = {
+ .driver_module = THIS_MODULE,
+ .num_interrupt_lines = 1,
+ .read_raw = &tsl2563_read_raw,
+ .write_raw = &tsl2563_write_raw,
+ .read_event_value = &tsl2563_read_thresh,
+ .write_event_value = &tsl2563_write_thresh,
+ .read_event_config = &tsl2563_read_interrupt_config,
+ .write_event_config = &tsl2563_write_interrupt_config,
+};
+
static int __devinit tsl2563_probe(struct i2c_client *client,
const struct i2c_device_id *device_id)
{
+ struct iio_dev *indio_dev;
struct tsl2563_chip *chip;
struct tsl2563_platform_data *pdata = client->dev.platform_data;
int err = 0;
int ret;
u8 id;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (!chip)
+ indio_dev = iio_allocate_device(sizeof(*chip));
+ if (!indio_dev)
return -ENOMEM;
- INIT_WORK(&chip->work_thresh, tsl2563_int_bh);
+ chip = iio_priv(indio_dev);
+
i2c_set_clientdata(client, chip);
chip->client = client;
@@ -856,30 +748,25 @@ static int __devinit tsl2563_probe(struct i2c_client *client,
chip->cover_comp_gain = 1;
dev_info(&client->dev, "model %d, rev. %d\n", id >> 4, id & 0x0f);
-
- chip->indio_dev = iio_allocate_device();
- if (!chip->indio_dev)
- goto fail1;
- chip->indio_dev->attrs = &tsl2563_group;
- chip->indio_dev->dev.parent = &client->dev;
- chip->indio_dev->dev_data = (void *)(chip);
- chip->indio_dev->driver_module = THIS_MODULE;
- chip->indio_dev->modes = INDIO_DIRECT_MODE;
- if (client->irq) {
- chip->indio_dev->num_interrupt_lines = 1;
- chip->indio_dev->event_attrs
- = &tsl2563_event_attribute_group;
- }
- ret = iio_device_register(chip->indio_dev);
+ indio_dev->name = client->name;
+ indio_dev->channels = tsl2563_channels;
+ indio_dev->num_channels = ARRAY_SIZE(tsl2563_channels);
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ if (client->irq)
+ indio_dev->info = &tsl2563_info;
+ else
+ indio_dev->info = &tsl2563_info_no_irq;
+ ret = iio_device_register(indio_dev);
if (ret)
goto fail1;
-
if (client->irq) {
- ret = iio_register_interrupt_line(client->irq,
- chip->indio_dev,
- 0,
- IRQF_TRIGGER_RISING,
- client->name);
+ ret = request_threaded_irq(client->irq,
+ NULL,
+ &tsl2563_event_handler,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ "tsl2563_event",
+ indio_dev);
if (ret)
goto fail2;
}
@@ -894,9 +781,9 @@ static int __devinit tsl2563_probe(struct i2c_client *client,
return 0;
fail3:
if (client->irq)
- iio_unregister_interrupt_line(chip->indio_dev, 0);
+ free_irq(client->irq, indio_dev);
fail2:
- iio_device_unregister(chip->indio_dev);
+ iio_device_unregister(indio_dev);
fail1:
kfree(chip);
return err;
@@ -905,6 +792,7 @@ fail1:
static int tsl2563_remove(struct i2c_client *client)
{
struct tsl2563_chip *chip = i2c_get_clientdata(client);
+ struct iio_dev *indio_dev = iio_priv_to_dev(chip);
if (!chip->int_enabled)
cancel_delayed_work(&chip->poweroff_work);
/* Ensure that interrupts are disabled - then flush any bottom halves */
@@ -913,10 +801,9 @@ static int tsl2563_remove(struct i2c_client *client)
flush_scheduled_work();
tsl2563_set_power(chip, 0);
if (client->irq)
- iio_unregister_interrupt_line(chip->indio_dev, 0);
- iio_device_unregister(chip->indio_dev);
+ free_irq(client->irq, indio_dev);
+ iio_device_unregister(indio_dev);
- kfree(chip);
return 0;
}
diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c
new file mode 100644
index 000000000000..5694610da1ca
--- /dev/null
+++ b/drivers/staging/iio/light/tsl2583.c
@@ -0,0 +1,964 @@
+/*
+ * Device driver for monitoring ambient light intensity (lux)
+ * within the TAOS tsl258x family of devices (tsl2580, tsl2581).
+ *
+ * Copyright (c) 2011, TAOS Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/mutex.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include "../iio.h"
+
+#define TSL258X_MAX_DEVICE_REGS 32
+
+/* Triton register offsets */
+#define TSL258X_REG_MAX 8
+
+/* Device Registers and Masks */
+#define TSL258X_CNTRL 0x00
+#define TSL258X_ALS_TIME 0X01
+#define TSL258X_INTERRUPT 0x02
+#define TSL258X_GAIN 0x07
+#define TSL258X_REVID 0x11
+#define TSL258X_CHIPID 0x12
+#define TSL258X_ALS_CHAN0LO 0x14
+#define TSL258X_ALS_CHAN0HI 0x15
+#define TSL258X_ALS_CHAN1LO 0x16
+#define TSL258X_ALS_CHAN1HI 0x17
+#define TSL258X_TMR_LO 0x18
+#define TSL258X_TMR_HI 0x19
+
+/* tsl2583 cmd reg masks */
+#define TSL258X_CMD_REG 0x80
+#define TSL258X_CMD_SPL_FN 0x60
+#define TSL258X_CMD_ALS_INT_CLR 0X01
+
+/* tsl2583 cntrl reg masks */
+#define TSL258X_CNTL_ADC_ENBL 0x02
+#define TSL258X_CNTL_PWR_ON 0x01
+
+/* tsl2583 status reg masks */
+#define TSL258X_STA_ADC_VALID 0x01
+#define TSL258X_STA_ADC_INTR 0x10
+
+/* Lux calculation constants */
+#define TSL258X_LUX_CALC_OVER_FLOW 65535
+
+enum {
+ TSL258X_CHIP_UNKNOWN = 0,
+ TSL258X_CHIP_WORKING = 1,
+ TSL258X_CHIP_SUSPENDED = 2
+} TSL258X_CHIP_WORKING_STATUS;
+
+/* Per-device data */
+struct taos_als_info {
+ u16 als_ch0;
+ u16 als_ch1;
+ u16 lux;
+};
+
+struct taos_settings {
+ int als_time;
+ int als_gain;
+ int als_gain_trim;
+ int als_cal_target;
+};
+
+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;
+ int als_saturation;
+ int taos_chip_status;
+ u8 taos_config[8];
+};
+
+/*
+ * Initial values for device - this values can/will be changed by driver.
+ * and applications as needed.
+ * These values are dynamic.
+ */
+static const u8 taos_config[8] = {
+ 0x00, 0xee, 0x00, 0x03, 0x00, 0xFF, 0xFF, 0x00
+}; /* cntrl atime intC Athl0 Athl1 Athh0 Athh1 gain */
+
+struct taos_lux {
+ unsigned int ratio;
+ unsigned int ch0;
+ unsigned int ch1;
+};
+
+/* 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] = {
+ { 9830, 8520, 15729 },
+ { 12452, 10807, 23344 },
+ { 14746, 6383, 11705 },
+ { 17695, 4063, 6554 },
+};
+
+struct gainadj {
+ s16 ch0;
+ s16 ch1;
+};
+
+/* Index = (0 - 3) Used to validate the gain selection index */
+static const struct gainadj gainadj[] = {
+ { 1, 1 },
+ { 8, 8 },
+ { 16, 16 },
+ { 107, 115 }
+};
+
+/*
+ * Provides initial operational parameter defaults.
+ * These defaults may be changed through the device's sysfs files.
+ */
+static void taos_defaults(struct tsl2583_chip *chip)
+{
+ /* Operational parameters */
+ chip->taos_settings.als_time = 100;
+ /* must be a multiple of 50mS */
+ chip->taos_settings.als_gain = 0;
+ /* this is actually an index into the gain table */
+ /* assume clear glass as default */
+ chip->taos_settings.als_gain_trim = 1000;
+ /* default gain trim to account for aperture effects */
+ chip->taos_settings.als_cal_target = 130;
+ /* Known external ALS reading used for calibration */
+}
+
+/*
+ * Read a number of bytes starting at register (reg) location.
+ * Return 0, or i2c_smbus_write_byte ERROR code.
+ */
+static int
+taos_i2c_read(struct i2c_client *client, u8 reg, u8 *val, unsigned int len)
+{
+ int ret;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ /* select register to write */
+ ret = i2c_smbus_write_byte(client, (TSL258X_CMD_REG | reg));
+ if (ret < 0) {
+ dev_err(&client->dev, "taos_i2c_read failed to write"
+ " register %x\n", reg);
+ return ret;
+ }
+ /* read the data */
+ *val = i2c_smbus_read_byte(client);
+ val++;
+ reg++;
+ }
+ return 0;
+}
+
+/*
+ * Reads and calculates current lux value.
+ * The raw ch0 and ch1 values of the ambient light sensed in the last
+ * integration cycle are read from the device.
+ * Time scale factor array values are adjusted based on the integration time.
+ * The raw values are multiplied by a scale factor, and device gain is obtained
+ * using gain index. Limit checks are done next, then the ratio of a multiple
+ * of ch1 value, to the ch0 value, is calculated. The array taos_device_lux[]
+ * declared above is then scanned to find the first ratio value that is just
+ * above the ratio we just calculated. The ch0 and ch1 multiplier constants in
+ * 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)
+{
+ 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);
+ 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");
+ 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");
+ ret = -EBUSY ;
+ goto out_unlock;
+ }
+
+ ret = taos_i2c_read(client, (TSL258X_CMD_REG), &buf[0], 1);
+ if (ret < 0) {
+ dev_err(&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");
+ 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);
+ if (ret < 0) {
+ dev_err(&client->dev, "taos_get_lux failed to read"
+ " register %x\n", reg);
+ goto out_unlock;
+ }
+ }
+
+ /* 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));
+
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "taos_i2c_write_command failed in taos_get_lux, err = %d\n",
+ ret);
+ goto out_unlock; /* have no data, so return failure */
+ }
+
+ /* extract ALS/lux data */
+ ch0 = le16_to_cpup((const __le16 *)&buf[0]);
+ ch1 = le16_to_cpup((const __le16 *)&buf[2]);
+
+ chip->als_cur_info.als_ch0 = ch0;
+ chip->als_cur_info.als_ch1 = ch1;
+
+ if ((ch0 >= chip->als_saturation) || (ch1 >= chip->als_saturation))
+ goto return_max;
+
+ if (ch0 == 0) {
+ /* have no data, so return LAST VALUE */
+ ret = chip->als_cur_info.lux = 0;
+ goto out_unlock;
+ }
+ /* calculate ratio */
+ ratio = (ch1 << 15) / ch0;
+ /* convert to unscaled lux using the pointer to the table */
+ for (p = (struct taos_lux *) taos_device_lux;
+ p->ratio != 0 && p->ratio < ratio; p++)
+ ;
+
+ if (p->ratio == 0) {
+ lux = 0;
+ } else {
+ ch0lux = ((ch0 * p->ch0) +
+ (gainadj[chip->taos_settings.als_gain].ch0 >> 1))
+ / gainadj[chip->taos_settings.als_gain].ch0;
+ ch1lux = ((ch1 * p->ch1) +
+ (gainadj[chip->taos_settings.als_gain].ch1 >> 1))
+ / gainadj[chip->taos_settings.als_gain].ch1;
+ lux = ch0lux - ch1lux;
+ }
+
+ /* note: lux is 31 bit max at this point */
+ if (ch1lux > ch0lux) {
+ dev_dbg(&client->dev, "No Data - Return last value\n");
+ ret = chip->als_cur_info.lux = 0;
+ goto out_unlock;
+ }
+
+ /* adjust for active time scale */
+ if (chip->als_time_scale == 0)
+ lux = 0;
+ else
+ lux = (lux + (chip->als_time_scale >> 1)) /
+ chip->als_time_scale;
+
+ /* adjust for active gain scale */
+ lux >>= 13; /* tables have factor of 8192 builtin for accuracy */
+ lux = (lux * chip->taos_settings.als_gain_trim + 500) / 1000;
+ if (lux > TSL258X_LUX_CALC_OVER_FLOW) { /* check for overflow */
+return_max:
+ lux = TSL258X_LUX_CALC_OVER_FLOW;
+ }
+
+ /* Update the structure with the latest VALID lux. */
+ chip->als_cur_info.lux = lux;
+ ret = lux;
+
+out_unlock:
+ mutex_unlock(&chip->als_mutex);
+ return ret;
+}
+
+/*
+ * Obtain single reading and calculate the als_gain_trim (later used
+ * to derive actual lux).
+ * Return updated gain_trim value.
+ */
+int taos_als_calibrate(struct i2c_client *client)
+{
+ struct tsl2583_chip *chip = i2c_get_clientdata(client);
+ u8 reg_val;
+ unsigned int gain_trim_val;
+ int ret;
+ int lux_val;
+
+ ret = i2c_smbus_write_byte(client, (TSL258X_CMD_REG | TSL258X_CNTRL));
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "taos_als_calibrate failed to reach the CNTRL register, ret=%d\n",
+ ret);
+ return ret;
+ }
+
+ reg_val = i2c_smbus_read_byte(client);
+ if ((reg_val & (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON))
+ != (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) {
+ dev_err(&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));
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "taos_als_calibrate failed to reach the STATUS register, ret=%d\n",
+ ret);
+ return ret;
+ }
+ reg_val = i2c_smbus_read_byte(client);
+
+ if ((reg_val & TSL258X_STA_ADC_VALID) != TSL258X_STA_ADC_VALID) {
+ dev_err(&client->dev,
+ "taos_als_calibrate failed: STATUS - ADC not valid.\n");
+ return -ENODATA;
+ }
+ lux_val = taos_get_lux(client);
+ if (lux_val < 0) {
+ dev_err(&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,
+ "taos_als_calibrate failed: trim_val of %d is out of range\n",
+ gain_trim_val);
+ return -ENODATA;
+ }
+ chip->taos_settings.als_gain_trim = (int) gain_trim_val;
+
+ return (int) gain_trim_val;
+}
+
+/*
+ * Turn the device on.
+ * Configuration must be set before calling this function.
+ */
+static int taos_chip_on(struct i2c_client *client)
+{
+ int i;
+ int ret = 0;
+ u8 *uP;
+ u8 utmp;
+ int als_count;
+ int als_time;
+ struct tsl2583_chip *chip = i2c_get_clientdata(client);
+
+ /* 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;
+ }
+
+ /* determine als integration regster */
+ als_count = (chip->taos_settings.als_time * 100 + 135) / 270;
+ if (als_count == 0)
+ als_count = 1; /* ensure at least one cycle */
+
+ /* convert back to time (encompasses overrides) */
+ als_time = (als_count * 27 + 5) / 10;
+ chip->taos_config[TSL258X_ALS_TIME] = 256 - als_count;
+
+ /* Set the gain based on taos_settings struct */
+ chip->taos_config[TSL258X_GAIN] = chip->taos_settings.als_gain;
+
+ /* set chip struct re scaling and saturation */
+ chip->als_saturation = als_count * 922; /* 90% of full scale */
+ chip->als_time_scale = (als_time + 25) / 50;
+
+ /* 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);
+ if (ret < 0) {
+ dev_err(&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,
+ *uP++);
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "taos_chip_on failed on reg %d.\n", i);
+ return -1;
+ }
+ }
+
+ msleep(3);
+ /* 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,
+ utmp);
+ if (ret < 0) {
+ dev_err(&client->dev, "taos_chip_on failed on 2nd CTRL reg.\n");
+ return -1;
+ }
+ chip->taos_chip_status = TSL258X_CHIP_WORKING;
+
+ return ret;
+}
+
+static int taos_chip_off(struct i2c_client *client)
+{
+ struct tsl2583_chip *chip = i2c_get_clientdata(client);
+ int ret;
+
+ /* turn device off */
+ chip->taos_chip_status = TSL258X_CHIP_SUSPENDED;
+ ret = i2c_smbus_write_byte_data(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;
+
+ return sprintf(buf, "%d\n", chip->taos_chip_status);
+}
+
+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);
+ else
+ taos_chip_on(chip->client);
+
+ return len;
+}
+
+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;
+ char gain[4] = {0};
+
+ switch (chip->taos_settings.als_gain) {
+ case 0:
+ strcpy(gain, "001");
+ break;
+ case 1:
+ strcpy(gain, "008");
+ break;
+ case 2:
+ strcpy(gain, "016");
+ break;
+ case 3:
+ strcpy(gain, "111");
+ break;
+ }
+
+ return sprintf(buf, "%s\n", gain);
+}
+
+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;
+ unsigned long value;
+
+ if (strict_strtoul(buf, 0, &value))
+ return -EINVAL;
+
+ switch (value) {
+ case 1:
+ chip->taos_settings.als_gain = 0;
+ break;
+ case 8:
+ chip->taos_settings.als_gain = 1;
+ break;
+ case 16:
+ chip->taos_settings.als_gain = 2;
+ break;
+ case 111:
+ chip->taos_settings.als_gain = 3;
+ break;
+ default:
+ dev_err(dev, "Invalid Gain Index (must be 1,8,16,111)\n");
+ return -1;
+ }
+
+ return len;
+}
+
+static ssize_t taos_gain_available_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", "1 8 16 111");
+}
+
+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;
+
+ return sprintf(buf, "%d\n", chip->taos_settings.als_time);
+}
+
+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;
+ unsigned long value;
+
+ if (strict_strtoul(buf, 0, &value))
+ return -EINVAL;
+
+ if ((value < 50) || (value > 650))
+ return -EINVAL;
+
+ if (value % 50)
+ return -EINVAL;
+
+ chip->taos_settings.als_time = value;
+
+ return len;
+}
+
+static ssize_t taos_als_time_available_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n",
+ "50 100 150 200 250 300 350 400 450 500 550 600 650");
+}
+
+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;
+
+ return sprintf(buf, "%d\n", chip->taos_settings.als_gain_trim);
+}
+
+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;
+ unsigned long value;
+
+ if (strict_strtoul(buf, 0, &value))
+ return -EINVAL;
+
+ if (value)
+ chip->taos_settings.als_gain_trim = value;
+
+ return len;
+}
+
+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;
+
+ return sprintf(buf, "%d\n", chip->taos_settings.als_cal_target);
+}
+
+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;
+ unsigned long value;
+
+ if (strict_strtoul(buf, 0, &value))
+ return -EINVAL;
+
+ if (value)
+ chip->taos_settings.als_cal_target = value;
+
+ return len;
+}
+
+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;
+
+ lux = taos_get_lux(chip->client);
+
+ return sprintf(buf, "%d\n", lux);
+}
+
+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);
+
+ return len;
+}
+
+static ssize_t taos_luxtable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int i;
+ int offset = 0;
+
+ for (i = 0; i < ARRAY_SIZE(taos_device_lux); i++) {
+ offset += sprintf(buf + offset, "%d,%d,%d,",
+ taos_device_lux[i].ratio,
+ taos_device_lux[i].ch0,
+ taos_device_lux[i].ch1);
+ if (taos_device_lux[i].ratio == 0) {
+ /* We just printed the first "0" entry.
+ * Now get rid of the extra "," and break. */
+ offset--;
+ break;
+ }
+ }
+
+ offset += sprintf(buf + offset, "\n");
+ return offset;
+}
+
+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)];
+ int n;
+
+ get_options(buf, ARRAY_SIZE(value), value);
+
+ /* We now have an array of ints starting at value[1], and
+ * enumerated by value[0].
+ * We expect each group of three ints is one table entry,
+ * and the last table entry is all 0.
+ */
+ n = value[0];
+ if ((n % 3) || n < 6 || n > ((ARRAY_SIZE(taos_device_lux) - 1) * 3)) {
+ dev_info(dev, "LUX TABLE INPUT ERROR 1 Value[0]=%d\n", n);
+ return -EINVAL;
+ }
+ if ((value[(n - 2)] | value[(n - 1)] | value[n]) != 0) {
+ dev_info(dev, "LUX TABLE INPUT ERROR 2 Value[0]=%d\n", n);
+ return -EINVAL;
+ }
+
+ if (chip->taos_chip_status == TSL258X_CHIP_WORKING)
+ taos_chip_off(chip->client);
+
+ /* 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);
+
+ 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);
+
+static DEVICE_ATTR(illuminance0_calibscale, S_IRUGO | S_IWUSR,
+ taos_gain_show, taos_gain_store);
+static DEVICE_ATTR(illuminance0_calibscale_available, S_IRUGO,
+ taos_gain_available_show, NULL);
+
+static DEVICE_ATTR(illuminance0_integration_time, S_IRUGO | S_IWUSR,
+ taos_als_time_show, taos_als_time_store);
+static DEVICE_ATTR(illuminance0_integration_time_available, S_IRUGO,
+ taos_als_time_available_show, NULL);
+
+static DEVICE_ATTR(illuminance0_calibbias, S_IRUGO | S_IWUSR,
+ taos_als_trim_show, taos_als_trim_store);
+
+static DEVICE_ATTR(illuminance0_input_target, S_IRUGO | S_IWUSR,
+ taos_als_cal_target_show, taos_als_cal_target_store);
+
+static DEVICE_ATTR(illuminance0_input, S_IRUGO, taos_lux_show, NULL);
+static DEVICE_ATTR(illuminance0_calibrate, S_IWUSR, NULL, taos_do_calibrate);
+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,
+ &dev_attr_illuminance0_integration_time.attr, /* I time*/
+ &dev_attr_illuminance0_integration_time_available.attr,
+ &dev_attr_illuminance0_calibbias.attr, /* trim */
+ &dev_attr_illuminance0_input_target.attr,
+ &dev_attr_illuminance0_input.attr,
+ &dev_attr_illuminance0_calibrate.attr,
+ &dev_attr_illuminance0_lux_table.attr,
+ NULL
+};
+
+static struct attribute_group tsl2583_attribute_group = {
+ .attrs = sysfs_attrs_ctrl,
+};
+
+/* Use the default register values to identify the Taos device */
+static int taos_tsl258x_device(unsigned char *bufp)
+{
+ return ((bufp[TSL258X_CHIPID] & 0xf0) == 0x90);
+}
+
+static const struct iio_info tsl2583_info = {
+ .attrs = &tsl2583_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
+/*
+ * Client probe function - When a valid device is found, the driver's device
+ * data structure is updated, and initialization completes successfully.
+ */
+static int __devinit taos_probe(struct i2c_client *clientp,
+ const struct i2c_device_id *idp)
+{
+ int i, ret = 0;
+ unsigned char buf[TSL258X_MAX_DEVICE_REGS];
+ static struct tsl2583_chip *chip;
+
+ if (!i2c_check_functionality(clientp->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA)) {
+ dev_err(&clientp->dev,
+ "taos_probe() - i2c smbus byte data "
+ "functions unsupported\n");
+ return -EOPNOTSUPP;
+ }
+
+ chip = kzalloc(sizeof(struct tsl2583_chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ chip->client = clientp;
+ i2c_set_clientdata(clientp, chip);
+
+ mutex_init(&chip->als_mutex);
+ chip->taos_chip_status = TSL258X_CHIP_UNKNOWN;
+ memcpy(chip->taos_config, taos_config, sizeof(chip->taos_config));
+
+ for (i = 0; i < TSL258X_MAX_DEVICE_REGS; i++) {
+ ret = i2c_smbus_write_byte(clientp,
+ (TSL258X_CMD_REG | (TSL258X_CNTRL + i)));
+ if (ret < 0) {
+ dev_err(&clientp->dev, "i2c_smbus_write_bytes() to cmd "
+ "reg failed in taos_probe(), err = %d\n", ret);
+ goto fail1;
+ }
+ 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;
+ }
+ buf[i] = ret;
+ }
+
+ if (!taos_tsl258x_device(buf)) {
+ dev_info(&clientp->dev, "i2c device found but does not match "
+ "expected id in taos_probe()\n");
+ goto fail1;
+ }
+
+ 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;
+ }
+
+ 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);
+ if (ret) {
+ dev_err(&clientp->dev, "iio registration failed\n");
+ goto fail1;
+ }
+
+ /* 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);
+
+ dev_info(&clientp->dev, "Light sensor found.\n");
+
+ return 0;
+
+fail1:
+ kfree(chip);
+
+ return ret;
+}
+
+static int taos_suspend(struct i2c_client *client, pm_message_t state)
+{
+ struct tsl2583_chip *chip = i2c_get_clientdata(client);
+ int ret = 0;
+
+ mutex_lock(&chip->als_mutex);
+
+ if (chip->taos_chip_status == TSL258X_CHIP_WORKING) {
+ ret = taos_chip_off(client);
+ chip->taos_chip_status = TSL258X_CHIP_SUSPENDED;
+ }
+
+ mutex_unlock(&chip->als_mutex);
+ return ret;
+}
+
+static int taos_resume(struct i2c_client *client)
+{
+ struct tsl2583_chip *chip = i2c_get_clientdata(client);
+ int ret = 0;
+
+ mutex_lock(&chip->als_mutex);
+
+ if (chip->taos_chip_status == TSL258X_CHIP_SUSPENDED)
+ ret = taos_chip_on(client);
+
+ mutex_unlock(&chip->als_mutex);
+ return ret;
+}
+
+
+static int __devexit taos_remove(struct i2c_client *client)
+{
+ struct tsl2583_chip *chip = i2c_get_clientdata(client);
+
+ iio_device_unregister(chip->iio_dev);
+
+ kfree(chip);
+ return 0;
+}
+
+static struct i2c_device_id taos_idtable[] = {
+ { "tsl2580", 0 },
+ { "tsl2581", 1 },
+ { "tsl2583", 2 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, taos_idtable);
+
+/* Driver definition */
+static struct i2c_driver taos_driver = {
+ .driver = {
+ .name = "tsl2583",
+ },
+ .id_table = taos_idtable,
+ .suspend = taos_suspend,
+ .resume = taos_resume,
+ .probe = taos_probe,
+ .remove = __devexit_p(taos_remove),
+};
+
+static int __init taos_init(void)
+{
+ return i2c_add_driver(&taos_driver);
+}
+
+static void __exit taos_exit(void)
+{
+ i2c_del_driver(&taos_driver);
+}
+
+module_init(taos_init);
+module_exit(taos_exit);
+
+MODULE_AUTHOR("J. August Brenner<jbrenner@taosinc.com>");
+MODULE_DESCRIPTION("TAOS tsl2583 ambient light sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c
index 420f206cf517..700f96c70273 100644
--- a/drivers/staging/iio/magnetometer/ak8975.c
+++ b/drivers/staging/iio/magnetometer/ak8975.c
@@ -206,7 +206,7 @@ static int ak8975_setup(struct i2c_client *client)
}
/* Precalculate scale factor for each axis and
- store in the device data. */
+ store in the device data. */
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;
@@ -316,6 +316,59 @@ static ssize_t show_scale(struct device *dev, struct device_attribute *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;
+ u8 read_status;
+ u32 timeout_ms = AK8975_MAX_CONVERSION_TIMEOUT;
+ int ret;
+
+ /* Wait for the conversion to complete. */
+ while (timeout_ms) {
+ msleep(AK8975_CONVERSION_DONE_POLL_TIME);
+ if (gpio_get_value(data->eoc_gpio))
+ break;
+ timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME;
+ }
+ if (!timeout_ms) {
+ dev_err(&client->dev, "Conversion timeout happened\n");
+ return -EINVAL;
+ }
+
+ ret = ak8975_read_data(client, AK8975_REG_ST1, 1, &read_status);
+ if (ret < 0) {
+ dev_err(&client->dev, "Error in reading ST1\n");
+ return ret;
+ }
+ return read_status;
+}
+
+static int wait_conversion_complete_polled(struct ak8975_data *data)
+{
+ struct i2c_client *client = data->client;
+ u8 read_status;
+ u32 timeout_ms = AK8975_MAX_CONVERSION_TIMEOUT;
+ int ret;
+
+ /* Wait for the conversion to complete. */
+ while (timeout_ms) {
+ msleep(AK8975_CONVERSION_DONE_POLL_TIME);
+ ret = ak8975_read_data(client, AK8975_REG_ST1, 1, &read_status);
+ if (ret < 0) {
+ dev_err(&client->dev, "Error in reading ST1\n");
+ return ret;
+ }
+ if (read_status)
+ break;
+ timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME;
+ }
+ if (!timeout_ms) {
+ dev_err(&client->dev, "Conversion timeout happened\n");
+ return -EINVAL;
+ }
+ return read_status;
+}
+
/*
* Emits the raw flux value for the x, y, or z axis.
*/
@@ -326,7 +379,6 @@ static ssize_t show_raw(struct device *dev, struct device_attribute *devattr,
struct ak8975_data *data = indio_dev->dev_data;
struct i2c_client *client = data->client;
struct iio_dev_attr *this_attr = to_iio_dev_attr(devattr);
- u32 timeout_ms = AK8975_MAX_CONVERSION_TIMEOUT;
u16 meas_reg;
s16 raw;
u8 read_status;
@@ -352,23 +404,14 @@ static ssize_t show_raw(struct device *dev, struct device_attribute *devattr,
}
/* Wait for the conversion to complete. */
- while (timeout_ms) {
- msleep(AK8975_CONVERSION_DONE_POLL_TIME);
- if (gpio_get_value(data->eoc_gpio))
- break;
- timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME;
- }
- if (!timeout_ms) {
- dev_err(&client->dev, "Conversion timeout happened\n");
- ret = -EINVAL;
+ if (data->eoc_gpio)
+ ret = wait_conversion_complete_gpio(data);
+ else
+ ret = wait_conversion_complete_polled(data);
+ if (ret < 0)
goto exit;
- }
- ret = ak8975_read_data(client, AK8975_REG_ST1, 1, &read_status);
- if (ret < 0) {
- dev_err(&client->dev, "Error in reading ST1\n");
- goto exit;
- }
+ read_status = ret;
if (read_status & AK8975_REG_ST1_DRDY_MASK) {
ret = ak8975_read_data(client, AK8975_REG_ST2, 1, &read_status);
@@ -431,6 +474,11 @@ static struct attribute_group ak8975_attr_group = {
.attrs = ak8975_attr,
};
+static const struct iio_info ak8975_info = {
+ .attrs = &ak8975_attr_group,
+ .driver_module = THIS_MODULE,
+};
+
static int ak8975_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -454,25 +502,26 @@ static int ak8975_probe(struct i2c_client *client,
data->eoc_irq = client->irq;
data->eoc_gpio = irq_to_gpio(client->irq);
- if (!data->eoc_gpio) {
- dev_err(&client->dev, "failed, no valid GPIO\n");
- err = -EINVAL;
- goto exit_free;
- }
-
- err = gpio_request(data->eoc_gpio, "ak_8975");
- if (err < 0) {
- dev_err(&client->dev, "failed to request GPIO %d, error %d\n",
- data->eoc_gpio, err);
- goto exit_free;
- }
+ /* We may not have a GPIO based IRQ to scan, that is fine, we will
+ poll if so */
+ if (data->eoc_gpio > 0) {
+ err = gpio_request(data->eoc_gpio, "ak_8975");
+ if (err < 0) {
+ dev_err(&client->dev,
+ "failed to request GPIO %d, error %d\n",
+ data->eoc_gpio, err);
+ goto exit_free;
+ }
- err = gpio_direction_input(data->eoc_gpio);
- if (err < 0) {
- dev_err(&client->dev, "Failed to configure input direction for"
- " GPIO %d, error %d\n", data->eoc_gpio, err);
- goto exit_gpio;
- }
+ err = gpio_direction_input(data->eoc_gpio);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "Failed to configure input direction for GPIO %d, error %d\n",
+ data->eoc_gpio, err);
+ goto exit_gpio;
+ }
+ } else
+ data->eoc_gpio = 0; /* No GPIO available */
/* Perform some basic start-of-day setup of the device. */
err = ak8975_setup(client);
@@ -482,16 +531,15 @@ static int ak8975_probe(struct i2c_client *client,
}
/* Register with IIO */
- data->indio_dev = iio_allocate_device();
+ data->indio_dev = iio_allocate_device(0);
if (data->indio_dev == NULL) {
err = -ENOMEM;
goto exit_gpio;
}
data->indio_dev->dev.parent = &client->dev;
- data->indio_dev->attrs = &ak8975_attr_group;
+ data->indio_dev->info = &ak8975_info;
data->indio_dev->dev_data = (void *)(data);
- data->indio_dev->driver_module = THIS_MODULE;
data->indio_dev->modes = INDIO_DIRECT_MODE;
err = iio_device_register(data->indio_dev);
@@ -503,7 +551,8 @@ static int ak8975_probe(struct i2c_client *client,
exit_free_iio:
iio_free_device(data->indio_dev);
exit_gpio:
- gpio_free(data->eoc_gpio);
+ if (data->eoc_gpio)
+ gpio_free(data->eoc_gpio);
exit_free:
kfree(data);
exit:
@@ -517,7 +566,8 @@ static int ak8975_remove(struct i2c_client *client)
iio_device_unregister(data->indio_dev);
iio_free_device(data->indio_dev);
- gpio_free(data->eoc_gpio);
+ if (data->eoc_gpio)
+ gpio_free(data->eoc_gpio);
kfree(data);
diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
index 51689177e00e..dd9a3bb6aa01 100644
--- a/drivers/staging/iio/magnetometer/hmc5843.c
+++ b/drivers/staging/iio/magnetometer/hmc5843.c
@@ -529,6 +529,11 @@ static void hmc5843_init_client(struct i2c_client *client)
pr_info("HMC5843 initialized\n");
}
+static const struct iio_info hmc5843_info = {
+ .attrs = &hmc5843_group,
+ .driver_module = THIS_MODULE,
+};
+
static int hmc5843_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -552,15 +557,14 @@ static int hmc5843_probe(struct i2c_client *client,
/* Initialize the HMC5843 chip */
hmc5843_init_client(client);
- data->indio_dev = iio_allocate_device();
+ data->indio_dev = iio_allocate_device(0);
if (!data->indio_dev) {
err = -ENOMEM;
goto exit_free1;
}
- data->indio_dev->attrs = &hmc5843_group;
+ data->indio_dev->info = &hmc5843_info;
data->indio_dev->dev.parent = &client->dev;
data->indio_dev->dev_data = (void *)(data);
- data->indio_dev->driver_module = THIS_MODULE;
data->indio_dev->modes = INDIO_DIRECT_MODE;
err = iio_device_register(data->indio_dev);
if (err)
diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
index 8b86d82c3b32..6c9c23fc4aed 100644
--- a/drivers/staging/iio/meter/ade7753.c
+++ b/drivers/staging/iio/meter/ade7753.c
@@ -463,8 +463,6 @@ static IIO_DEV_ATTR_RESET(ade7753_write_reset);
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500");
-static IIO_CONST_ATTR(name, "ade7753");
-
static struct attribute *ade7753_attributes[] = {
&iio_dev_attr_temp_raw.dev_attr.attr,
&iio_const_attr_temp_offset.dev_attr.attr,
@@ -472,7 +470,6 @@ static struct attribute *ade7753_attributes[] = {
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_reset.dev_attr.attr,
- &iio_const_attr_name.dev_attr.attr,
&iio_dev_attr_phcal.dev_attr.attr,
&iio_dev_attr_cfden.dev_attr.attr,
&iio_dev_attr_aenergy.dev_attr.attr,
@@ -507,6 +504,11 @@ static const struct attribute_group ade7753_attribute_group = {
.attrs = ade7753_attributes,
};
+static const struct iio_info ade7753_info = {
+ .attrs = &ade7753_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit ade7753_probe(struct spi_device *spi)
{
int ret, regdone = 0;
@@ -532,16 +534,16 @@ static int __devinit ade7753_probe(struct spi_device *spi)
st->us = spi;
mutex_init(&st->buf_lock);
/* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_tx;
}
+ st->indio_dev->name = spi->dev.driver->name;
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->attrs = &ade7753_attribute_group;
+ st->indio_dev->info = &ade7753_info;
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(st->indio_dev);
diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c
index 4272818e7dc4..378f2c87086f 100644
--- a/drivers/staging/iio/meter/ade7754.c
+++ b/drivers/staging/iio/meter/ade7754.c
@@ -482,8 +482,6 @@ static IIO_DEV_ATTR_RESET(ade7754_write_reset);
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26000 13000 65000 33000");
-static IIO_CONST_ATTR(name, "ade7754");
-
static struct attribute *ade7754_attributes[] = {
&iio_dev_attr_temp_raw.dev_attr.attr,
&iio_const_attr_temp_offset.dev_attr.attr,
@@ -491,7 +489,6 @@ static struct attribute *ade7754_attributes[] = {
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_reset.dev_attr.attr,
- &iio_const_attr_name.dev_attr.attr,
&iio_dev_attr_aenergy.dev_attr.attr,
&iio_dev_attr_laenergy.dev_attr.attr,
&iio_dev_attr_vaenergy.dev_attr.attr,
@@ -530,7 +527,10 @@ static const struct attribute_group ade7754_attribute_group = {
.attrs = ade7754_attributes,
};
-
+static const struct iio_info ade7754_info = {
+ .attrs = &ade7754_attribute_group,
+ .driver_module = THIS_MODULE,
+};
static int __devinit ade7754_probe(struct spi_device *spi)
{
@@ -557,16 +557,16 @@ static int __devinit ade7754_probe(struct spi_device *spi)
st->us = spi;
mutex_init(&st->buf_lock);
/* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_tx;
}
+ st->indio_dev->name = spi->dev.driver->name;
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->attrs = &ade7754_attribute_group;
+ st->indio_dev->info = &ade7754_info;
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(st->indio_dev);
diff --git a/drivers/staging/iio/meter/ade7758.h b/drivers/staging/iio/meter/ade7758.h
index c6fd94f3b3ee..fd74e156abf9 100644
--- a/drivers/staging/iio/meter/ade7758.h
+++ b/drivers/staging/iio/meter/ade7758.h
@@ -1,3 +1,11 @@
+/*
+ * ADE7758 Poly Phase Multifunction Energy Metering IC driver
+ *
+ * Copyright 2010-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
#ifndef _ADE7758_H
#define _ADE7758_H
@@ -83,43 +91,54 @@
#define ADE7758_MAX_RX 4
#define ADE7758_STARTUP_DELAY 1
-#define ADE7758_SPI_SLOW (u32)(300 * 1000)
-#define ADE7758_SPI_BURST (u32)(1000 * 1000)
-#define ADE7758_SPI_FAST (u32)(2000 * 1000)
+#define AD7758_NUM_WAVSEL 5
+#define AD7758_NUM_PHSEL 3
+#define AD7758_NUM_WAVESRC (AD7758_NUM_WAVSEL * AD7758_NUM_PHSEL)
+
+#define AD7758_PHASE_A 0
+#define AD7758_PHASE_B 1
+#define AD7758_PHASE_C 2
+#define AD7758_CURRENT 0
+#define AD7758_VOLTAGE 1
+#define AD7758_ACT_PWR 2
+#define AD7758_REACT_PWR 3
+#define AD7758_APP_PWR 4
+#define AD7758_WT(p, w) (((w) << 2) | (p))
#define DRIVER_NAME "ade7758"
+
/**
* struct ade7758_state - device instance specific data
* @us: actual spi_device
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter: used to check if new interrupt has been triggered
- * @last_timestamp: passing timestamp from th to bh of interrupt handler
- * @indio_dev: industrial I/O device structure
* @trig: data ready trigger registered with iio
* @tx: transmit buffer
* @rx: receive buffer
* @buf_lock: mutex to protect tx and rx
**/
struct ade7758_state {
- struct spi_device *us;
- struct work_struct work_trigger_to_ring;
- s64 last_timestamp;
- struct iio_dev *indio_dev;
- struct iio_trigger *trig;
- u8 *tx;
- u8 *rx;
- struct mutex buf_lock;
+ struct spi_device *us;
+ struct iio_trigger *trig;
+ u8 *tx;
+ u8 *rx;
+ struct mutex buf_lock;
+ u32 available_scan_masks[AD7758_NUM_WAVESRC];
+ struct iio_chan_spec *ade7758_ring_channels;
+ struct spi_transfer ring_xfer[4];
+ struct spi_message ring_msg;
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ unsigned char rx_buf[8] ____cacheline_aligned;
+ unsigned char tx_buf[8];
+
};
#ifdef CONFIG_IIO_RING_BUFFER
/* At the moment triggers are only used for ring buffer
* filling. This may change!
*/
-enum ade7758_scan {
- ADE7758_SCAN_WFORM,
-};
-
void ade7758_remove_trigger(struct iio_dev *indio_dev);
int ade7758_probe_trigger(struct iio_dev *indio_dev);
@@ -134,6 +153,12 @@ void ade7758_unconfigure_ring(struct iio_dev *indio_dev);
int ade7758_initialize_ring(struct iio_ring_buffer *ring);
void ade7758_uninitialize_ring(struct iio_ring_buffer *ring);
int ade7758_set_irq(struct device *dev, bool enable);
+
+int ade7758_spi_write_reg_8(struct device *dev,
+ u8 reg_address, u8 val);
+int ade7758_spi_read_reg_8(struct device *dev,
+ u8 reg_address, u8 *val);
+
#else /* CONFIG_IIO_RING_BUFFER */
static inline void ade7758_remove_trigger(struct iio_dev *indio_dev)
@@ -144,14 +169,6 @@ static inline int ade7758_probe_trigger(struct iio_dev *indio_dev)
return 0;
}
-static inline ssize_t
-ade7758_read_data_from_ring(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return 0;
-}
-
static int ade7758_configure_ring(struct iio_dev *indio_dev)
{
return 0;
diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c
index b7634cb7aa4f..299b95434e20 100644
--- a/drivers/staging/iio/meter/ade7758_core.c
+++ b/drivers/staging/iio/meter/ade7758_core.c
@@ -1,9 +1,9 @@
/*
- * ADE7758 Polyphase Multifunction Energy Metering IC Driver
+ * ADE7758 Poly Phase Multifunction Energy Metering IC driver
*
- * Copyright 2010 Analog Devices Inc.
+ * Copyright 2010-2011 Analog Devices Inc.
*
- * Licensed under the GPL-2 or later.
+ * Licensed under the GPL-2.
*/
#include <linux/interrupt.h>
@@ -20,6 +20,7 @@
#include "../iio.h"
#include "../sysfs.h"
+#include "../ring_generic.h"
#include "meter.h"
#include "ade7758.h"
@@ -29,7 +30,7 @@ int ade7758_spi_write_reg_8(struct device *dev,
{
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7758_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7758_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
st->tx[0] = ADE7758_WRITE_REG(reg_address);
@@ -48,7 +49,7 @@ static int ade7758_spi_write_reg_16(struct device *dev,
int ret;
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7758_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7758_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[] = {
{
.tx_buf = st->tx,
@@ -77,7 +78,7 @@ static int ade7758_spi_write_reg_24(struct device *dev,
int ret;
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7758_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7758_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[] = {
{
.tx_buf = st->tx,
@@ -100,20 +101,26 @@ static int ade7758_spi_write_reg_24(struct device *dev,
return ret;
}
-static int ade7758_spi_read_reg_8(struct device *dev,
+int ade7758_spi_read_reg_8(struct device *dev,
u8 reg_address,
u8 *val)
{
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7758_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7758_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
{
.tx_buf = st->tx,
+ .bits_per_word = 8,
+ .len = 1,
+ .delay_usecs = 4,
+ },
+ {
+ .tx_buf = &st->tx[1],
.rx_buf = st->rx,
.bits_per_word = 8,
- .len = 2,
+ .len = 1,
},
};
@@ -122,14 +129,15 @@ static int ade7758_spi_read_reg_8(struct device *dev,
st->tx[1] = 0;
spi_message_init(&msg);
- spi_message_add_tail(xfers, &msg);
+ spi_message_add_tail(&xfers[0], &msg);
+ spi_message_add_tail(&xfers[1], &msg);
ret = spi_sync(st->us, &msg);
if (ret) {
dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X",
reg_address);
goto error_ret;
}
- *val = st->rx[1];
+ *val = st->rx[0];
error_ret:
mutex_unlock(&st->buf_lock);
@@ -142,31 +150,40 @@ static int ade7758_spi_read_reg_16(struct device *dev,
{
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7758_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7758_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
{
.tx_buf = st->tx,
+ .bits_per_word = 8,
+ .len = 1,
+ .delay_usecs = 4,
+ },
+ {
+ .tx_buf = &st->tx[1],
.rx_buf = st->rx,
.bits_per_word = 8,
- .len = 3,
+ .len = 2,
},
};
+
mutex_lock(&st->buf_lock);
st->tx[0] = ADE7758_READ_REG(reg_address);
st->tx[1] = 0;
st->tx[2] = 0;
spi_message_init(&msg);
- spi_message_add_tail(xfers, &msg);
+ spi_message_add_tail(&xfers[0], &msg);
+ spi_message_add_tail(&xfers[1], &msg);
ret = spi_sync(st->us, &msg);
if (ret) {
dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
reg_address);
goto error_ret;
}
- *val = (st->rx[1] << 8) | st->rx[2];
+
+ *val = (st->rx[0] << 8) | st->rx[1];
error_ret:
mutex_unlock(&st->buf_lock);
@@ -179,14 +196,20 @@ static int ade7758_spi_read_reg_24(struct device *dev,
{
struct spi_message msg;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7758_state *st = iio_dev_get_devdata(indio_dev);
+ struct ade7758_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
{
.tx_buf = st->tx,
+ .bits_per_word = 8,
+ .len = 1,
+ .delay_usecs = 4,
+ },
+ {
+ .tx_buf = &st->tx[1],
.rx_buf = st->rx,
.bits_per_word = 8,
- .len = 4,
+ .len = 3,
},
};
@@ -197,14 +220,15 @@ static int ade7758_spi_read_reg_24(struct device *dev,
st->tx[3] = 0;
spi_message_init(&msg);
- spi_message_add_tail(xfers, &msg);
+ spi_message_add_tail(&xfers[0], &msg);
+ spi_message_add_tail(&xfers[1], &msg);
ret = spi_sync(st->us, &msg);
if (ret) {
dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X",
reg_address);
goto error_ret;
}
- *val = (st->rx[1] << 16) | (st->rx[2] << 8) | st->rx[3];
+ *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
error_ret:
mutex_unlock(&st->buf_lock);
@@ -292,7 +316,7 @@ error_ret:
return ret ? ret : len;
}
-int ade7758_reset(struct device *dev)
+static int ade7758_reset(struct device *dev)
{
int ret;
u8 val;
@@ -319,7 +343,7 @@ static ssize_t ade7758_write_reset(struct device *dev,
case 'Y':
return ade7758_reset(dev);
}
- return -1;
+ return len;
}
static IIO_DEV_ATTR_VPEAK(S_IWUSR | S_IRUGO,
@@ -461,13 +485,14 @@ static int ade7758_stop_device(struct device *dev)
return ret;
}
-static int ade7758_initial_setup(struct ade7758_state *st)
+static int ade7758_initial_setup(struct iio_dev *indio_dev)
{
+ struct ade7758_state *st = iio_priv(indio_dev);
+ struct device *dev = &indio_dev->dev;
int ret;
- struct device *dev = &st->indio_dev->dev;
/* use low spi speed for init */
- st->us->mode = SPI_MODE_3;
+ st->us->mode = SPI_MODE_1;
spi_setup(st->us);
/* Disable IRQ */
@@ -510,7 +535,6 @@ static ssize_t ade7758_write_frequency(struct device *dev,
size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7758_state *st = iio_dev_get_devdata(indio_dev);
unsigned long val;
int ret;
u8 reg, t;
@@ -521,14 +545,23 @@ static ssize_t ade7758_write_frequency(struct device *dev,
mutex_lock(&indio_dev->mlock);
- t = (26040 / val);
- if (t > 0)
- t >>= 1;
-
- if (t > 1)
- st->us->max_speed_hz = ADE7758_SPI_SLOW;
- else
- st->us->max_speed_hz = ADE7758_SPI_FAST;
+ switch (val) {
+ case 26040:
+ t = 0;
+ break;
+ case 13020:
+ t = 1;
+ break;
+ case 6510:
+ t = 2;
+ break;
+ case 3255:
+ t = 3;
+ break;
+ default:
+ ret = -EINVAL;
+ goto out;
+ }
ret = ade7758_spi_read_reg_8(dev,
ADE7758_WAVMODE,
@@ -549,63 +582,6 @@ out:
return ret ? ret : len;
}
-static ssize_t ade7758_read_waveform_type(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int ret, len = 0;
- u8 t;
- ret = ade7758_spi_read_reg_8(dev,
- ADE7758_WAVMODE,
- &t);
- if (ret)
- return ret;
-
- t = (t >> 2) & 0x7;
-
- len = sprintf(buf, "%d\n", t);
-
- return len;
-}
-
-static ssize_t ade7758_write_waveform_type(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- unsigned long val;
- int ret;
- u8 reg;
-
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- return ret;
-
- if (val > 4)
- return -EINVAL;
-
- mutex_lock(&indio_dev->mlock);
-
- ret = ade7758_spi_read_reg_8(dev,
- ADE7758_WAVMODE,
- &reg);
- if (ret)
- goto out;
-
- reg &= ~(7 << 2);
- reg |= val << 2;
-
- ret = ade7758_spi_write_reg_8(dev,
- ADE7758_WAVMODE,
- reg);
-
-out:
- mutex_unlock(&indio_dev->mlock);
-
- return ret ? ret : len;
-}
-
static IIO_DEV_ATTR_TEMP_RAW(ade7758_read_8bit);
static IIO_CONST_ATTR(temp_offset, "129 C");
static IIO_CONST_ATTR(temp_scale, "4 C");
@@ -633,42 +609,17 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
ade7758_read_frequency,
ade7758_write_frequency);
-/**
- * IIO_DEV_ATTR_WAVEFORM_TYPE - set the type of waveform.
- * @_mode: sysfs file mode/permissions
- * @_show: output method for the attribute
- * @_store: input method for the attribute
- **/
-#define IIO_DEV_ATTR_WAVEFORM_TYPE(_mode, _show, _store) \
- IIO_DEVICE_ATTR(waveform_type, _mode, _show, _store, 0)
-
-static IIO_DEV_ATTR_WAVEFORM_TYPE(S_IWUSR | S_IRUGO,
- ade7758_read_waveform_type,
- ade7758_write_waveform_type);
-
static IIO_DEV_ATTR_RESET(ade7758_write_reset);
-static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26000 13000 65000 33000");
-
-static IIO_CONST_ATTR(name, "ade7758");
-
-static struct attribute *ade7758_event_attributes[] = {
- NULL
-};
-
-static struct attribute_group ade7758_event_attribute_group = {
- .attrs = ade7758_event_attributes,
-};
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26040 13020 6510 3255");
static struct attribute *ade7758_attributes[] = {
&iio_dev_attr_temp_raw.dev_attr.attr,
&iio_const_attr_temp_offset.dev_attr.attr,
&iio_const_attr_temp_scale.dev_attr.attr,
&iio_dev_attr_sampling_frequency.dev_attr.attr,
- &iio_dev_attr_waveform_type.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_reset.dev_attr.attr,
- &iio_const_attr_name.dev_attr.attr,
&iio_dev_attr_awatthr.dev_attr.attr,
&iio_dev_attr_bwatthr.dev_attr.attr,
&iio_dev_attr_cwatthr.dev_attr.attr,
@@ -710,24 +661,95 @@ static const struct attribute_group ade7758_attribute_group = {
.attrs = ade7758_attributes,
};
+static struct iio_chan_spec ade7758_channels[] = {
+ IIO_CHAN(IIO_IN, 0, 1, 0, "raw", 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ AD7758_WT(AD7758_PHASE_A, AD7758_VOLTAGE),
+ 0, IIO_ST('s', 24, 32, 0), 0),
+ IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ AD7758_WT(AD7758_PHASE_A, AD7758_CURRENT),
+ 1, IIO_ST('s', 24, 32, 0), 0),
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ AD7758_WT(AD7758_PHASE_A, AD7758_APP_PWR),
+ 2, IIO_ST('s', 24, 32, 0), 0),
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ AD7758_WT(AD7758_PHASE_A, AD7758_ACT_PWR),
+ 3, IIO_ST('s', 24, 32, 0), 0),
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 0, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ AD7758_WT(AD7758_PHASE_A, AD7758_REACT_PWR),
+ 4, IIO_ST('s', 24, 32, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, "raw", 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ AD7758_WT(AD7758_PHASE_B, AD7758_VOLTAGE),
+ 5, IIO_ST('s', 24, 32, 0), 0),
+ IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ AD7758_WT(AD7758_PHASE_B, AD7758_CURRENT),
+ 6, IIO_ST('s', 24, 32, 0), 0),
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ AD7758_WT(AD7758_PHASE_B, AD7758_APP_PWR),
+ 7, IIO_ST('s', 24, 32, 0), 0),
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ AD7758_WT(AD7758_PHASE_B, AD7758_ACT_PWR),
+ 8, IIO_ST('s', 24, 32, 0), 0),
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 1, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ AD7758_WT(AD7758_PHASE_B, AD7758_REACT_PWR),
+ 9, IIO_ST('s', 24, 32, 0), 0),
+ IIO_CHAN(IIO_IN, 0, 1, 0, "raw", 2, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ AD7758_WT(AD7758_PHASE_C, AD7758_VOLTAGE),
+ 10, IIO_ST('s', 24, 32, 0), 0),
+ IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 2, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ AD7758_WT(AD7758_PHASE_C, AD7758_CURRENT),
+ 11, IIO_ST('s', 24, 32, 0), 0),
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 2, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ AD7758_WT(AD7758_PHASE_C, AD7758_APP_PWR),
+ 12, IIO_ST('s', 24, 32, 0), 0),
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 2, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ AD7758_WT(AD7758_PHASE_C, AD7758_ACT_PWR),
+ 13, IIO_ST('s', 24, 32, 0), 0),
+ IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 2, 0,
+ (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ AD7758_WT(AD7758_PHASE_C, AD7758_REACT_PWR),
+ 14, IIO_ST('s', 24, 32, 0), 0),
+ IIO_CHAN_SOFT_TIMESTAMP(15),
+};
+static const struct iio_info ade7758_info = {
+ .attrs = &ade7758_attribute_group,
+ .driver_module = THIS_MODULE,
+};
static int __devinit ade7758_probe(struct spi_device *spi)
{
- int ret, regdone = 0;
- struct ade7758_state *st = kzalloc(sizeof *st, GFP_KERNEL);
- if (!st) {
- ret = -ENOMEM;
+ int i, ret, regdone = 0;
+ struct ade7758_state *st;
+ struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
+
+ if (indio_dev == NULL) {
+ ret = -ENOMEM;
goto error_ret;
}
+
+ st = iio_priv(indio_dev);
/* this is only used for removal purposes */
- spi_set_drvdata(spi, st);
+ spi_set_drvdata(spi, indio_dev);
/* Allocate the comms buffers */
st->rx = kzalloc(sizeof(*st->rx)*ADE7758_MAX_RX, GFP_KERNEL);
if (st->rx == NULL) {
ret = -ENOMEM;
- goto error_free_st;
+ goto error_free_dev;
}
st->tx = kzalloc(sizeof(*st->tx)*ADE7758_MAX_TX, GFP_KERNEL);
if (st->tx == NULL) {
@@ -735,111 +757,96 @@ static int __devinit ade7758_probe(struct spi_device *spi)
goto error_free_rx;
}
st->us = spi;
+ st->ade7758_ring_channels = &ade7758_channels[0];
mutex_init(&st->buf_lock);
- /* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
- if (st->indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_free_tx;
- }
- st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->num_interrupt_lines = 1;
- st->indio_dev->event_attrs = &ade7758_event_attribute_group;
- st->indio_dev->attrs = &ade7758_attribute_group;
- st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
- st->indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->name = spi->dev.driver->name;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->info = &ade7758_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ for (i = 0; i < AD7758_NUM_WAVESRC; i++)
+ st->available_scan_masks[i] = 1 << i;
+
+ indio_dev->available_scan_masks = st->available_scan_masks;
- ret = ade7758_configure_ring(st->indio_dev);
+ ret = ade7758_configure_ring(indio_dev);
if (ret)
- goto error_free_dev;
+ goto error_free_tx;
- ret = iio_device_register(st->indio_dev);
+ ret = iio_device_register(indio_dev);
if (ret)
goto error_unreg_ring_funcs;
regdone = 1;
- ret = ade7758_initialize_ring(st->indio_dev->ring);
+ ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
+ &ade7758_channels[0],
+ ARRAY_SIZE(ade7758_channels));
if (ret) {
- printk(KERN_ERR "failed to initialize the ring\n");
+ dev_err(&spi->dev, "failed to initialize the ring\n");
goto error_unreg_ring_funcs;
}
- if (spi->irq) {
- ret = iio_register_interrupt_line(spi->irq,
- st->indio_dev,
- 0,
- IRQF_TRIGGER_FALLING,
- "ade7758");
- if (ret)
- goto error_uninitialize_ring;
+ /* Get the device into a sane initial state */
+ ret = ade7758_initial_setup(indio_dev);
+ if (ret)
+ goto error_uninitialize_ring;
- ret = ade7758_probe_trigger(st->indio_dev);
+ if (spi->irq) {
+ ret = ade7758_probe_trigger(indio_dev);
if (ret)
- goto error_unregister_line;
+ goto error_remove_trigger;
}
- /* Get the device into a sane initial state */
- ret = ade7758_initial_setup(st);
- if (ret)
- goto error_remove_trigger;
return 0;
error_remove_trigger:
- if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
- ade7758_remove_trigger(st->indio_dev);
-error_unregister_line:
- if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
- iio_unregister_interrupt_line(st->indio_dev, 0);
+ if (indio_dev->modes & INDIO_RING_TRIGGERED)
+ ade7758_remove_trigger(indio_dev);
error_uninitialize_ring:
- ade7758_uninitialize_ring(st->indio_dev->ring);
+ ade7758_uninitialize_ring(indio_dev->ring);
error_unreg_ring_funcs:
- ade7758_unconfigure_ring(st->indio_dev);
-error_free_dev:
- if (regdone)
- iio_device_unregister(st->indio_dev);
- else
- iio_free_device(st->indio_dev);
+ ade7758_unconfigure_ring(indio_dev);
error_free_tx:
kfree(st->tx);
error_free_rx:
kfree(st->rx);
-error_free_st:
- kfree(st);
+error_free_dev:
+ if (regdone)
+ iio_device_unregister(indio_dev);
+ else
+ iio_free_device(indio_dev);
error_ret:
return ret;
}
static int ade7758_remove(struct spi_device *spi)
{
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct ade7758_state *st = iio_priv(indio_dev);
int ret;
- struct ade7758_state *st = spi_get_drvdata(spi);
- struct iio_dev *indio_dev = st->indio_dev;
- ret = ade7758_stop_device(&(indio_dev->dev));
+ ret = ade7758_stop_device(&indio_dev->dev);
if (ret)
goto err_ret;
- flush_scheduled_work();
-
ade7758_remove_trigger(indio_dev);
- if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
- iio_unregister_interrupt_line(indio_dev, 0);
-
ade7758_uninitialize_ring(indio_dev->ring);
- iio_device_unregister(indio_dev);
ade7758_unconfigure_ring(indio_dev);
kfree(st->tx);
kfree(st->rx);
- kfree(st);
+ iio_device_unregister(indio_dev);
return 0;
-
err_ret:
return ret;
}
+static const struct spi_device_id ade7758_id[] = {
+ {"ade7758", 0},
+ {}
+};
+
static struct spi_driver ade7758_driver = {
.driver = {
.name = "ade7758",
@@ -847,6 +854,7 @@ static struct spi_driver ade7758_driver = {
},
.probe = ade7758_probe,
.remove = __devexit_p(ade7758_remove),
+ .id_table = ade7758_id,
};
static __init int ade7758_init(void)
diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c
index 274b4a07808c..b89b7f882e84 100644
--- a/drivers/staging/iio/meter/ade7758_ring.c
+++ b/drivers/staging/iio/meter/ade7758_ring.c
@@ -1,3 +1,10 @@
+/*
+ * ADE7758 Poly Phase Multifunction Energy Metering IC driver
+ *
+ * Copyright 2010-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
@@ -9,6 +16,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <asm/unaligned.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -18,182 +26,188 @@
#include "ade7758.h"
/**
- * combine_8_to_32() utility function to munge to u8s into u32
+ * ade7758_spi_read_burst() - read data registers
+ * @dev: device associated with child of actual device (iio_dev or iio_trig)
**/
-static inline u32 combine_8_to_32(u8 lower, u8 mid, u8 upper)
+static int ade7758_spi_read_burst(struct device *dev)
{
- u32 _lower = lower;
- u32 _mid = mid;
- u32 _upper = upper;
-
- return _lower | (_mid << 8) | (_upper << 16);
-}
-
-static IIO_SCAN_EL_C(wform, ADE7758_SCAN_WFORM, ADE7758_WFORM, NULL);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(wform, s, 24, 32);
-static IIO_SCAN_EL_TIMESTAMP(1);
-static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
-
-static struct attribute *ade7758_scan_el_attrs[] = {
- &iio_scan_el_wform.dev_attr.attr,
- &iio_const_attr_wform_index.dev_attr.attr,
- &iio_const_attr_wform_type.dev_attr.attr,
- &iio_scan_el_timestamp.dev_attr.attr,
- &iio_const_attr_timestamp_index.dev_attr.attr,
- &iio_const_attr_timestamp_type.dev_attr.attr,
- NULL,
-};
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ade7758_state *st = iio_priv(indio_dev);
+ int ret;
-static struct attribute_group ade7758_scan_el_group = {
- .attrs = ade7758_scan_el_attrs,
- .name = "scan_elements",
-};
+ ret = spi_sync(st->us, &st->ring_msg);
+ if (ret)
+ dev_err(&st->us->dev, "problem when reading WFORM value\n");
-/**
- * ade7758_poll_func_th() top half interrupt handler called by trigger
- * @private_data: iio_dev
- **/
-static void ade7758_poll_func_th(struct iio_dev *indio_dev, s64 time)
-{
- struct ade7758_state *st = iio_dev_get_devdata(indio_dev);
- st->last_timestamp = time;
- schedule_work(&st->work_trigger_to_ring);
- /* Indicate that this interrupt is being handled */
-
- /* Technically this is trigger related, but without this
- * handler running there is currently no way for the interrupt
- * to clear.
- */
+ return ret;
}
-/**
- * ade7758_spi_read_burst() - read all data registers
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @rx: somewhere to pass back the value read (min size is 24 bytes)
- **/
-static int ade7758_spi_read_burst(struct device *dev, u8 *rx)
+static int ade7758_write_waveform_type(struct device *dev, unsigned type)
{
- struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ade7758_state *st = iio_dev_get_devdata(indio_dev);
int ret;
+ u8 reg;
- struct spi_transfer xfers[] = {
- {
- .tx_buf = st->tx,
- .rx_buf = rx,
- .bits_per_word = 8,
- .len = 4,
- }, {
- .tx_buf = st->tx + 4,
- .rx_buf = rx,
- .bits_per_word = 8,
- .len = 4,
- },
- };
-
- mutex_lock(&st->buf_lock);
- st->tx[0] = ADE7758_READ_REG(ADE7758_RSTATUS);
- st->tx[1] = 0;
- st->tx[2] = 0;
- st->tx[3] = 0;
- st->tx[4] = ADE7758_READ_REG(ADE7758_WFORM);
- st->tx[5] = 0;
- st->tx[6] = 0;
- st->tx[7] = 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 = ade7758_spi_read_reg_8(dev,
+ ADE7758_WAVMODE,
+ &reg);
if (ret)
- dev_err(&st->us->dev, "problem when reading WFORM value\n");
+ goto out;
- mutex_unlock(&st->buf_lock);
+ reg &= ~0x1F;
+ reg |= type & 0x1F;
+ ret = ade7758_spi_write_reg_8(dev,
+ ADE7758_WAVMODE,
+ reg);
+out:
return ret;
}
/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
* specific to be rolled into the core.
*/
-static void ade7758_trigger_bh_to_ring(struct work_struct *work_s)
+static irqreturn_t ade7758_trigger_handler(int irq, void *p)
{
- struct ade7758_state *st
- = container_of(work_s, struct ade7758_state,
- work_trigger_to_ring);
- struct iio_ring_buffer *ring = st->indio_dev->ring;
-
- int i = 0;
- s32 *data;
- size_t datasize = ring->access.get_bytes_per_datum(ring);
-
- data = kmalloc(datasize, GFP_KERNEL);
- if (data == NULL) {
- dev_err(&st->us->dev, "memory alloc failed in ring bh");
- return;
- }
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->private_data;
+ struct iio_ring_buffer *ring = indio_dev->ring;
+ struct ade7758_state *st = iio_priv(indio_dev);
+ s64 dat64[2];
+ u32 *dat32 = (u32 *)dat64;
if (ring->scan_count)
- if (ade7758_spi_read_burst(&st->indio_dev->dev, st->rx) >= 0)
- for (; i < ring->scan_count; i++)
- data[i] = combine_8_to_32(st->rx[i*2+2],
- st->rx[i*2+1],
- st->rx[i*2]);
+ if (ade7758_spi_read_burst(&indio_dev->dev) >= 0)
+ *dat32 = get_unaligned_be32(&st->rx_buf[5]) & 0xFFFFFF;
/* Guaranteed to be aligned with 8 byte boundary */
if (ring->scan_timestamp)
- *((s64 *)
- (((u32)data + 4 * ring->scan_count + 4) & ~0x7)) =
- st->last_timestamp;
+ dat64[1] = pf->timestamp;
+
+ ring->access->store_to(ring, (u8 *)dat64, pf->timestamp);
+
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * ade7758_ring_preenable() setup the parameters of the ring before enabling
+ *
+ * The complex nature of the setting of the nuber of bytes per datum is due
+ * to this driver currently ensuring that the timestamp is stored at an 8
+ * byte boundary.
+ **/
+static int ade7758_ring_preenable(struct iio_dev *indio_dev)
+{
+ struct ade7758_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;
- ring->access.store_to(ring,
- (u8 *)data,
- st->last_timestamp);
+ channel = __ffs(ring->scan_mask);
- iio_trigger_notify_done(st->indio_dev->trig);
- kfree(data);
+ d_size = st->ade7758_ring_channels[channel].scan_type.storagebits / 8;
- return;
+ 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);
+
+ ade7758_write_waveform_type(&indio_dev->dev,
+ st->ade7758_ring_channels[channel].address);
+
+ return 0;
}
+static const struct iio_ring_setup_ops ade7758_ring_setup_ops = {
+ .preenable = &ade7758_ring_preenable,
+ .postenable = &iio_triggered_ring_postenable,
+ .predisable = &iio_triggered_ring_predisable,
+};
+
void ade7758_unconfigure_ring(struct iio_dev *indio_dev)
{
- kfree(indio_dev->pollfunc);
+ /* 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);
}
int ade7758_configure_ring(struct iio_dev *indio_dev)
{
+ struct ade7758_state *st = iio_priv(indio_dev);
int ret = 0;
- struct ade7758_state *st = indio_dev->dev_data;
- struct iio_ring_buffer *ring;
- INIT_WORK(&st->work_trigger_to_ring, ade7758_trigger_bh_to_ring);
- ring = iio_sw_rb_allocate(indio_dev);
- if (!ring) {
+ indio_dev->ring = iio_sw_rb_allocate(indio_dev);
+ if (!indio_dev->ring) {
ret = -ENOMEM;
return ret;
}
- indio_dev->ring = ring;
+
/* Effectively select the ring buffer implementation */
- iio_ring_sw_register_funcs(&ring->access);
- ring->bpe = 4;
- ring->scan_el_attrs = &ade7758_scan_el_group;
- ring->scan_timestamp = true;
- ring->preenable = &iio_sw_ring_preenable;
- ring->postenable = &iio_triggered_ring_postenable;
- ring->predisable = &iio_triggered_ring_predisable;
- ring->owner = THIS_MODULE;
-
- /* Set default scan mode */
- iio_scan_mask_set(ring, iio_scan_el_wform.number);
-
- ret = iio_alloc_pollfunc(indio_dev, NULL, &ade7758_poll_func_th);
- if (ret)
+ indio_dev->ring->access = &ring_sw_access_funcs;
+ indio_dev->ring->setup_ops = &ade7758_ring_setup_ops;
+ indio_dev->ring->owner = THIS_MODULE;
+
+ indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
+ &ade7758_trigger_handler,
+ 0,
+ indio_dev,
+ "ade7759_consumer%d",
+ indio_dev->id);
+ if (indio_dev->pollfunc == NULL) {
+ ret = -ENOMEM;
goto error_iio_sw_rb_free;
+ }
indio_dev->modes |= INDIO_RING_TRIGGERED;
+
+ st->tx_buf[0] = ADE7758_READ_REG(ADE7758_RSTATUS);
+ st->tx_buf[1] = 0;
+ st->tx_buf[2] = 0;
+ st->tx_buf[3] = 0;
+ st->tx_buf[4] = ADE7758_READ_REG(ADE7758_WFORM);
+ st->tx_buf[5] = 0;
+ st->tx_buf[6] = 0;
+ st->tx_buf[7] = 0;
+
+ /* build spi ring message */
+ st->ring_xfer[0].tx_buf = &st->tx_buf[0];
+ st->ring_xfer[0].len = 1;
+ st->ring_xfer[0].bits_per_word = 8;
+ st->ring_xfer[0].delay_usecs = 4;
+ st->ring_xfer[1].rx_buf = &st->rx_buf[1];
+ st->ring_xfer[1].len = 3;
+ st->ring_xfer[1].bits_per_word = 8;
+ st->ring_xfer[1].cs_change = 1;
+
+ st->ring_xfer[2].tx_buf = &st->tx_buf[4];
+ st->ring_xfer[2].len = 1;
+ st->ring_xfer[2].bits_per_word = 8;
+ st->ring_xfer[2].delay_usecs = 1;
+ st->ring_xfer[3].rx_buf = &st->rx_buf[5];
+ st->ring_xfer[3].len = 3;
+ st->ring_xfer[3].bits_per_word = 8;
+
+ spi_message_init(&st->ring_msg);
+ spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg);
+ spi_message_add_tail(&st->ring_xfer[1], &st->ring_msg);
+ spi_message_add_tail(&st->ring_xfer[2], &st->ring_msg);
+ spi_message_add_tail(&st->ring_xfer[3], &st->ring_msg);
+
return 0;
error_iio_sw_rb_free:
@@ -201,11 +215,6 @@ error_iio_sw_rb_free:
return ret;
}
-int ade7758_initialize_ring(struct iio_ring_buffer *ring)
-{
- return iio_ring_buffer_register(ring, 0);
-}
-
void ade7758_uninitialize_ring(struct iio_ring_buffer *ring)
{
iio_ring_buffer_unregister(ring);
diff --git a/drivers/staging/iio/meter/ade7758_trigger.c b/drivers/staging/iio/meter/ade7758_trigger.c
index 60abca0c28ff..a5c3248151ed 100644
--- a/drivers/staging/iio/meter/ade7758_trigger.c
+++ b/drivers/staging/iio/meter/ade7758_trigger.c
@@ -1,3 +1,11 @@
+/*
+ * ADE7758 Poly Phase Multifunction Energy Metering IC driver
+ *
+ * Copyright 2010-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/mutex.h>
@@ -15,56 +23,24 @@
/**
* ade7758_data_rdy_trig_poll() the event handler for the data rdy trig
**/
-static int ade7758_data_rdy_trig_poll(struct iio_dev *dev_info,
- int index,
- s64 timestamp,
- int no_test)
+static irqreturn_t ade7758_data_rdy_trig_poll(int irq, void *private)
{
- struct ade7758_state *st = iio_dev_get_devdata(dev_info);
- struct iio_trigger *trig = st->trig;
-
- iio_trigger_poll(trig, timestamp);
+ disable_irq_nosync(irq);
+ iio_trigger_poll(private, iio_get_time_ns());
return IRQ_HANDLED;
}
-IIO_EVENT_SH(data_rdy_trig, &ade7758_data_rdy_trig_poll);
-
-static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
-
-static struct attribute *ade7758_trigger_attrs[] = {
- &dev_attr_name.attr,
- NULL,
-};
-
-static const struct attribute_group ade7758_trigger_attr_group = {
- .attrs = ade7758_trigger_attrs,
-};
-
/**
* ade7758_data_rdy_trigger_set_state() set datardy interrupt state
**/
static int ade7758_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
- struct ade7758_state *st = trig->private_data;
- struct iio_dev *indio_dev = st->indio_dev;
- int ret = 0;
+ struct iio_dev *indio_dev = trig->private_data;
dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
- ret = ade7758_set_irq(&st->indio_dev->dev, state);
- if (state == false) {
- iio_remove_event_from_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]
- ->ev_list);
- /* possible quirk with handler currently worked around
- by ensuring the work queue is empty */
- flush_scheduled_work();
- } else {
- iio_add_event_to_list(&iio_event_data_rdy_trig,
- &indio_dev->interrupts[0]->ev_list);
- }
- return ret;
+ return ade7758_set_irq(&indio_dev->dev, state);
}
/**
@@ -73,7 +49,9 @@ static int ade7758_data_rdy_trigger_set_state(struct iio_trigger *trig,
**/
static int ade7758_trig_try_reen(struct iio_trigger *trig)
{
- struct ade7758_state *st = trig->private_data;
+ struct iio_dev *indio_dev = trig->private_data;
+ struct ade7758_state *st = iio_priv(indio_dev);
+
enable_irq(st->us->irq);
/* irq reenabled so success! */
return 0;
@@ -81,45 +59,52 @@ static int ade7758_trig_try_reen(struct iio_trigger *trig)
int ade7758_probe_trigger(struct iio_dev *indio_dev)
{
+ struct ade7758_state *st = iio_priv(indio_dev);
int ret;
- struct ade7758_state *st = indio_dev->dev_data;
- st->trig = iio_allocate_trigger();
- st->trig->name = kasprintf(GFP_KERNEL,
- "ade7758-dev%d",
- indio_dev->id);
- if (!st->trig->name) {
+ st->trig = iio_allocate_trigger("%s-dev%d",
+ spi_get_device_id(st->us)->name,
+ indio_dev->id);
+ if (st->trig == NULL) {
ret = -ENOMEM;
- goto error_free_trig;
+ goto error_ret;
}
+
+ ret = request_irq(st->us->irq,
+ ade7758_data_rdy_trig_poll,
+ IRQF_TRIGGER_LOW,
+ spi_get_device_id(st->us)->name,
+ st->trig);
+ if (ret)
+ goto error_free_trig;
+
st->trig->dev.parent = &st->us->dev;
st->trig->owner = THIS_MODULE;
- st->trig->private_data = st;
+ 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;
- st->trig->control_attrs = &ade7758_trigger_attr_group;
ret = iio_trigger_register(st->trig);
/* select default trigger */
indio_dev->trig = st->trig;
if (ret)
- goto error_free_trig_name;
+ goto error_free_irq;
return 0;
-error_free_trig_name:
- kfree(st->trig->name);
+error_free_irq:
+ free_irq(st->us->irq, st->trig);
error_free_trig:
iio_free_trigger(st->trig);
-
+error_ret:
return ret;
}
void ade7758_remove_trigger(struct iio_dev *indio_dev)
{
- struct ade7758_state *state = indio_dev->dev_data;
+ struct ade7758_state *st = iio_priv(indio_dev);
- iio_trigger_unregister(state->trig);
- kfree(state->trig->name);
- iio_free_trigger(state->trig);
+ iio_trigger_unregister(st->trig);
+ free_irq(st->us->irq, st->trig);
+ iio_free_trigger(st->trig);
}
diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c
index a9d3203b2e1c..730f6d9074a6 100644
--- a/drivers/staging/iio/meter/ade7759.c
+++ b/drivers/staging/iio/meter/ade7759.c
@@ -422,8 +422,6 @@ static IIO_DEV_ATTR_RESET(ade7759_write_reset);
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500");
-static IIO_CONST_ATTR(name, "ade7759");
-
static struct attribute *ade7759_attributes[] = {
&iio_dev_attr_temp_raw.dev_attr.attr,
&iio_const_attr_temp_offset.dev_attr.attr,
@@ -431,7 +429,6 @@ static struct attribute *ade7759_attributes[] = {
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_reset.dev_attr.attr,
- &iio_const_attr_name.dev_attr.attr,
&iio_dev_attr_phcal.dev_attr.attr,
&iio_dev_attr_cfden.dev_attr.attr,
&iio_dev_attr_aenergy.dev_attr.attr,
@@ -453,6 +450,11 @@ static const struct attribute_group ade7759_attribute_group = {
.attrs = ade7759_attributes,
};
+static const struct iio_info ade7759_info = {
+ .attrs = &ade7759_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit ade7759_probe(struct spi_device *spi)
{
int ret;
@@ -478,18 +480,17 @@ static int __devinit ade7759_probe(struct spi_device *spi)
st->us = spi;
mutex_init(&st->buf_lock);
/* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_tx;
}
+ st->indio_dev->name = spi->dev.driver->name;
st->indio_dev->dev.parent = &spi->dev;
- st->indio_dev->num_interrupt_lines = 1;
- st->indio_dev->attrs = &ade7759_attribute_group;
+ st->indio_dev->info = &ade7759_info;
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(st->indio_dev);
diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c
index 866e585451f0..44cd3ec546ae 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -551,6 +551,11 @@ static const struct attribute_group ade7854_attribute_group = {
.attrs = ade7854_attributes,
};
+static const struct iio_info ade7854_info = {
+ .attrs = &ade7854_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
int ade7854_probe(struct ade7854_state *st, struct device *dev)
{
int ret;
@@ -568,16 +573,15 @@ int ade7854_probe(struct ade7854_state *st, struct device *dev)
}
mutex_init(&st->buf_lock);
/* setup the industrialio driver allocated elements */
- st->indio_dev = iio_allocate_device();
+ st->indio_dev = iio_allocate_device(0);
if (st->indio_dev == NULL) {
ret = -ENOMEM;
goto error_free_tx;
}
st->indio_dev->dev.parent = dev;
- st->indio_dev->attrs = &ade7854_attribute_group;
+ st->indio_dev->info = &ade7854_info;
st->indio_dev->dev_data = (void *)(st);
- st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(st->indio_dev);
diff --git a/drivers/staging/iio/resolver/ad2s120x.c b/drivers/staging/iio/resolver/ad2s120x.c
index 8f497a23976c..f83e1422fd29 100644
--- a/drivers/staging/iio/resolver/ad2s120x.c
+++ b/drivers/staging/iio/resolver/ad2s120x.c
@@ -209,10 +209,14 @@ static struct attribute *ad2s120x_attributes[] = {
};
static const struct attribute_group ad2s120x_attribute_group = {
- .name = DRV_NAME,
.attrs = ad2s120x_attributes,
};
+static const struct iio_info ad2s120x_info = {
+ .attrs = &ad2s120x_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit ad2s120x_probe(struct spi_device *spi)
{
struct ad2s120x_state *st;
@@ -240,18 +244,15 @@ static int __devinit ad2s120x_probe(struct spi_device *spi)
st->sample = pins[0];
st->rdvel = pins[1];
- st->idev = iio_allocate_device();
+ st->idev = iio_allocate_device(0);
if (st->idev == NULL) {
ret = -ENOMEM;
goto error_free_st;
}
st->idev->dev.parent = &spi->dev;
- st->idev->num_interrupt_lines = 0;
- st->idev->event_attrs = NULL;
- st->idev->attrs = &ad2s120x_attribute_group;
+ st->idev->info = &ad2s120x_info;
st->idev->dev_data = (void *)(st);
- st->idev->driver_module = THIS_MODULE;
st->idev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(st->idev);
diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c
index c12f64cc40df..09f4fcfda73a 100644
--- a/drivers/staging/iio/resolver/ad2s1210.c
+++ b/drivers/staging/iio/resolver/ad2s1210.c
@@ -755,6 +755,11 @@ error_ret:
return ret;
}
+static const struct iio_info ad2s1210_info = {
+ .attrs = &ad2s1210_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit ad2s1210_probe(struct spi_device *spi)
{
struct ad2s1210_state *st;
@@ -800,18 +805,15 @@ static int __devinit ad2s1210_probe(struct spi_device *spi)
st->res0 = pins[3];
st->res1 = pins[4];
- st->idev = iio_allocate_device();
+ st->idev = iio_allocate_device(0);
if (st->idev == NULL) {
ret = -ENOMEM;
goto error_free_st;
}
st->idev->dev.parent = &spi->dev;
- st->idev->num_interrupt_lines = 0;
- st->idev->event_attrs = NULL;
- st->idev->attrs = &ad2s1210_attribute_group;
+ st->idev->info = &ad2s1210_info;
st->idev->dev_data = (void *)(st);
- st->idev->driver_module = THIS_MODULE;
st->idev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(st->idev);
diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c
index 4143535242d9..9b72a952f2bc 100644
--- a/drivers/staging/iio/resolver/ad2s90.c
+++ b/drivers/staging/iio/resolver/ad2s90.c
@@ -75,6 +75,11 @@ static const struct attribute_group ad2s90_attribute_group = {
.attrs = ad2s90_attributes,
};
+static const struct iio_info ad2s90_info = {
+ .attrs = &ad2s90_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
static int __devinit ad2s90_probe(struct spi_device *spi)
{
struct ad2s90_state *st;
@@ -90,18 +95,15 @@ static int __devinit ad2s90_probe(struct spi_device *spi)
mutex_init(&st->lock);
st->sdev = spi;
- st->idev = iio_allocate_device();
+ st->idev = iio_allocate_device(0);
if (st->idev == NULL) {
ret = -ENOMEM;
goto error_free_st;
}
st->idev->dev.parent = &spi->dev;
- st->idev->num_interrupt_lines = 0;
- st->idev->event_attrs = NULL;
- st->idev->attrs = &ad2s90_attribute_group;
+ st->idev->info = &ad2s90_info;
st->idev->dev_data = (void *)(st);
- st->idev->driver_module = THIS_MODULE;
st->idev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(st->idev);
diff --git a/drivers/staging/iio/ring_generic.h b/drivers/staging/iio/ring_generic.h
index 32948e55dc81..3f26f7175b6a 100644
--- a/drivers/staging/iio/ring_generic.h
+++ b/drivers/staging/iio/ring_generic.h
@@ -16,35 +16,12 @@
struct iio_ring_buffer;
/**
- * iio_push_ring_event() - ring buffer specific push to event chrdev
- * @ring_buf: ring buffer that is the event source
- * @event_code: event indentification code
- * @timestamp: time of event
- **/
-int iio_push_ring_event(struct iio_ring_buffer *ring_buf,
- int event_code,
- s64 timestamp);
-/**
- * iio_push_or_escallate_ring_event() - escalate or add as appropriate
- * @ring_buf: ring buffer that is the event source
- * @event_code: event indentification code
- * @timestamp: time of event
- *
- * Typical usecase is to escalate a 50% ring full to 75% full if no one has yet
- * read the first event. Clearly the 50% full is no longer of interest in
- * typical use case.
- **/
-int iio_push_or_escallate_ring_event(struct iio_ring_buffer *ring_buf,
- int event_code,
- s64 timestamp);
-
-/**
* struct iio_ring_access_funcs - access functions for ring buffers.
* @mark_in_use: reference counting, typically to prevent module removal
* @unmark_in_use: reduce reference count when no longer using ring buffer
* @store_to: actually store stuff to the ring buffer
* @read_last: get the last element stored
- * @rip_lots: try to get a specified number of elements (must exist)
+ * @read_first_n: try to get a specified number of elements (must exist)
* @mark_param_change: notify ring that some relevant parameter has changed
* Often this means the underlying storage may need to
* change.
@@ -71,10 +48,9 @@ struct iio_ring_access_funcs {
int (*store_to)(struct iio_ring_buffer *ring, u8 *data, s64 timestamp);
int (*read_last)(struct iio_ring_buffer *ring, u8 *data);
- int (*rip_lots)(struct iio_ring_buffer *ring,
- size_t count,
- char __user *buf,
- int *dead_offset);
+ int (*read_first_n)(struct iio_ring_buffer *ring,
+ size_t n,
+ char __user *buf);
int (*mark_param_change)(struct iio_ring_buffer *ring);
int (*request_update)(struct iio_ring_buffer *ring);
@@ -88,58 +64,52 @@ struct iio_ring_access_funcs {
int (*enable)(struct iio_ring_buffer *ring);
};
+struct iio_ring_setup_ops {
+ int (*preenable)(struct iio_dev *);
+ int (*postenable)(struct iio_dev *);
+ int (*predisable)(struct iio_dev *);
+ int (*postdisable)(struct iio_dev *);
+};
+
/**
* struct iio_ring_buffer - general ring buffer structure
* @dev: ring buffer device struct
- * @access_dev: system device struct for the chrdev
* @indio_dev: industrial I/O device structure
* @owner: module that owns the ring buffer (for ref counting)
- * @id: unique id number
- * @access_id: device id number
* @length: [DEVICE] number of datums in ring
* @bytes_per_datum: [DEVICE] size of individual datum including timestamp
* @bpe: [DEVICE] size of individual channel value
- * @loopcount: [INTERN] number of times the ring has looped
* @scan_el_attrs: [DRIVER] control of scan elements if that scan mode
* control method is used
* @scan_count: [INTERN] the number of elements in the current scan mode
* @scan_mask: [INTERN] bitmask used in masking scan mode elements
* @scan_timestamp: [INTERN] does the scan mode include a timestamp
* @access_handler: [INTERN] chrdev access handling
- * @ev_int: [INTERN] chrdev interface for the event chrdev
- * @shared_ev_pointer: [INTERN] the shared event pointer to allow escalation of
- * events
* @access: [DRIVER] ring access functions associated with the
* implementation.
* @preenable: [DRIVER] function to run prior to marking ring enabled
* @postenable: [DRIVER] function to run after marking ring enabled
* @predisable: [DRIVER] function to run prior to marking ring disabled
* @postdisable: [DRIVER] function to run after marking ring disabled
- **/
+ **/
struct iio_ring_buffer {
- struct device dev;
- struct device access_dev;
- struct iio_dev *indio_dev;
- struct module *owner;
- int id;
- int access_id;
- int length;
- int bytes_per_datum;
- int bpe;
- int loopcount;
- struct attribute_group *scan_el_attrs;
- int scan_count;
- u32 scan_mask;
- bool scan_timestamp;
- struct iio_handler access_handler;
- struct iio_event_interface ev_int;
- struct iio_shared_ev_pointer shared_ev_pointer;
- struct iio_ring_access_funcs access;
- int (*preenable)(struct iio_dev *);
- int (*postenable)(struct iio_dev *);
- int (*predisable)(struct iio_dev *);
- int (*postdisable)(struct iio_dev *);
-
+ struct device dev;
+ struct iio_dev *indio_dev;
+ struct module *owner;
+ int length;
+ int bytes_per_datum;
+ int bpe;
+ struct attribute_group *scan_el_attrs;
+ int scan_count;
+ unsigned long scan_mask;
+ bool scan_timestamp;
+ struct iio_handler access_handler;
+ const struct iio_ring_access_funcs *access;
+ const struct iio_ring_setup_ops *setup_ops;
+ struct list_head scan_el_dev_attr_list;
+
+ wait_queue_head_t pollq;
+ bool stufftoread;
};
/**
@@ -161,154 +131,8 @@ static inline void __iio_update_ring_buffer(struct iio_ring_buffer *ring,
{
ring->bytes_per_datum = bytes_per_datum;
ring->length = length;
- ring->loopcount = 0;
}
-/**
- * struct iio_scan_el - an individual element of a scan
- * @dev_attr: control attribute (if directly controllable)
- * @number: unique identifier of element (used for bit mask)
- * @label: useful data for the scan el (often reg address)
- * @set_state: for some devices datardy signals are generated
- * for any enabled lines. This allows unwanted lines
- * to be disabled and hence not get in the way.
- **/
-struct iio_scan_el {
- struct device_attribute dev_attr;
- unsigned int number;
- unsigned int label;
-
- int (*set_state)(struct iio_scan_el *scanel,
- struct iio_dev *dev_info,
- bool state);
-};
-
-#define to_iio_scan_el(_dev_attr) \
- container_of(_dev_attr, struct iio_scan_el, dev_attr);
-
-/**
- * iio_scan_el_store() - sysfs scan element selection interface
- * @dev: the target device
- * @attr: the device attribute that is being processed
- * @buf: input from userspace
- * @len: length of input
- *
- * A generic function used to enable various scan elements. In some
- * devices explicit read commands for each channel mean this is merely
- * a software switch. In others this must actively disable the channel.
- * Complexities occur when this interacts with data ready type triggers
- * which may not reset unless every channel that is enabled is explicitly
- * read.
- **/
-ssize_t iio_scan_el_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t len);
-/**
- * iio_scan_el_show() - sysfs interface to query whether a scan element
- * is enabled or not
- * @dev: the target device
- * @attr: the device attribute that is being processed
- * @buf: output buffer
- **/
-ssize_t iio_scan_el_show(struct device *dev, struct device_attribute *attr,
- char *buf);
-
-/**
- * iio_scan_el_ts_store() - sysfs interface to set whether a timestamp is included
- * in the scan.
- **/
-ssize_t iio_scan_el_ts_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t len);
-/**
- * iio_scan_el_ts_show() - sysfs interface to query if a timestamp is included
- * in the scan.
- **/
-ssize_t iio_scan_el_ts_show(struct device *dev, struct device_attribute *attr,
- char *buf);
-/**
- * IIO_SCAN_EL_C - declare and initialize a scan element with a control func
- *
- * @_name: identifying name. Resulting struct is iio_scan_el_##_name,
- * sysfs element, _name##_en.
- * @_number: unique id number for the scan element.
- * length devices).
- * @_label: indentification variable used by drivers. Often a reg address.
- * @_controlfunc: function used to notify hardware of whether state changes
- **/
-#define __IIO_SCAN_EL_C(_name, _number, _label, _controlfunc) \
- struct iio_scan_el iio_scan_el_##_name = { \
- .dev_attr = __ATTR(_name##_en, \
- S_IRUGO | S_IWUSR, \
- iio_scan_el_show, \
- iio_scan_el_store), \
- .number = _number, \
- .label = _label, \
- .set_state = _controlfunc, \
- }; \
- static IIO_CONST_ATTR(_name##_index, #_number)
-
-#define IIO_SCAN_EL_C(_name, _number, _label, _controlfunc) \
- __IIO_SCAN_EL_C(_name, _number, _label, _controlfunc)
-
-#define __IIO_SCAN_NAMED_EL_C(_name, _string, _number, _label, _cf) \
- struct iio_scan_el iio_scan_el_##_name = { \
- .dev_attr = __ATTR(_string##_en, \
- S_IRUGO | S_IWUSR, \
- iio_scan_el_show, \
- iio_scan_el_store), \
- .number = _number, \
- .label = _label, \
- .set_state = _cf, \
- }; \
- static struct iio_const_attr iio_const_attr_##_name##_index = { \
- .string = #_number, \
- .dev_attr = __ATTR(_string##_index, \
- S_IRUGO, iio_read_const_attr, NULL) \
- }
-
-
-#define IIO_SCAN_NAMED_EL_C(_name, _string, _number, _label, _cf) \
- __IIO_SCAN_NAMED_EL_C(_name, _string, _number, _label, _cf)
-/**
- * IIO_SCAN_EL_TIMESTAMP - declare a special scan element for timestamps
- * @number: specify where in the scan order this is stored.
- *
- * Odd one out. Handled slightly differently from other scan elements.
- **/
-#define IIO_SCAN_EL_TIMESTAMP(number) \
- struct iio_scan_el iio_scan_el_timestamp = { \
- .dev_attr = __ATTR(timestamp_en, \
- S_IRUGO | S_IWUSR, \
- iio_scan_el_ts_show, \
- iio_scan_el_ts_store), \
- }; \
- static IIO_CONST_ATTR(timestamp_index, #number)
-
-/**
- * IIO_CONST_ATTR_SCAN_EL_TYPE - attr to specify the data format of a scan el
- * @name: the scan el name (may be more general and cover a set of scan elements
- * @_sign: either s or u for signed or unsigned
- * @_bits: number of actual bits occuplied by the value
- * @_storagebits: number of bits _bits is padded to when read out of buffer
- **/
-#define IIO_CONST_ATTR_SCAN_EL_TYPE(_name, _sign, _bits, _storagebits) \
- IIO_CONST_ATTR(_name##_type, #_sign#_bits"/"#_storagebits);
-
-/**
- * IIO_CONST_ATTR_SCAN_EL_TYPE_WITH_SHIFT - attr to specify the data format of a scan el
- * @name: the scan el name (may be more general and cover a set of scan elements
- * @_sign: either s or u for signed or unsigned
- * @_bits: number of actual bits occuplied by the value
- * @_storagebits: number of bits _bits is padded to when read out of buffer
- * @_shiftbits: number of bits _shiftbits the result must be shifted
- **/
-#define IIO_CONST_ATTR_SCAN_EL_TYPE_WITH_SHIFT(_name, _sign, _bits, \
- _storagebits, _shiftbits) \
- IIO_CONST_ATTR(_name##_type, #_sign#_bits"/"#_storagebits \
- ">>"#_shiftbits);
-
-#define IIO_SCAN_EL_TYPE_SIGNED 's'
-#define IIO_SCAN_EL_TYPE_UNSIGNED 'u'
-
/*
* These are mainly provided to allow for a change of implementation if a device
* has a large number of scan elements
@@ -375,41 +199,6 @@ static inline int iio_scan_mask_set(struct iio_ring_buffer *ring, int bit)
};
/**
- * iio_scan_mask_clear() - clear a particular element from the scan mask
- * @ring: the ring buffer whose scan mask we are interested in
- * @bit: the bit to clear
- **/
-static inline int iio_scan_mask_clear(struct iio_ring_buffer *ring, int bit)
-{
- if (bit > IIO_MAX_SCAN_LENGTH)
- return -EINVAL;
- ring->scan_mask &= ~(1 << bit);
- ring->scan_count--;
- return 0;
-};
-
-/**
- * iio_scan_mask_count_to_right() - how many scan elements occur before here
- * @ring: the ring buffer whose scan mask we interested in
- * @bit: which number scan element is this
- **/
-static inline int iio_scan_mask_count_to_right(struct iio_ring_buffer *ring,
- int bit)
-{
- int count = 0;
- int mask = (1 << bit);
- if (bit > IIO_MAX_SCAN_LENGTH)
- return -EINVAL;
- while (mask) {
- mask >>= 1;
- if (mask & ring->scan_mask)
- count++;
- }
-
- return count;
-}
-
-/**
* iio_put_ring_buffer() - notify done with buffer
* @ring: the buffer we are done with.
**/
@@ -418,17 +207,19 @@ static inline void iio_put_ring_buffer(struct iio_ring_buffer *ring)
put_device(&ring->dev);
};
-#define to_iio_ring_buffer(d) \
+#define to_iio_ring_buffer(d) \
container_of(d, struct iio_ring_buffer, dev)
-#define access_dev_to_iio_ring_buffer(d) \
- container_of(d, struct iio_ring_buffer, access_dev)
/**
- * iio_ring_buffer_register() - register the buffer with IIO core
+ * iio_ring_buffer_register_ex() - register the buffer with IIO core
* @ring: the buffer to be registered
* @id: the id of the buffer (typically 0)
**/
-int iio_ring_buffer_register(struct iio_ring_buffer *ring, int id);
+int iio_ring_buffer_register_ex(struct iio_ring_buffer *ring, int id,
+ const struct iio_chan_spec *channels,
+ int num_channels);
+
+void iio_ring_access_release(struct device *dev);
/**
* iio_ring_buffer_unregister() - unregister the buffer from IIO core
@@ -476,11 +267,19 @@ ssize_t iio_show_ring_enable(struct device *dev,
#define IIO_RING_ENABLE_ATTR DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, \
iio_show_ring_enable, \
iio_store_ring_enable)
+
+int iio_sw_ring_preenable(struct iio_dev *indio_dev);
+
#else /* CONFIG_IIO_RING_BUFFER */
-static inline int iio_ring_buffer_register(struct iio_ring_buffer *ring, int id)
+
+static inline int iio_ring_buffer_register_ex(struct iio_ring_buffer *ring,
+ int id,
+ struct iio_chan_spec *channels,
+ int num_channels)
{
return 0;
-};
+}
+
static inline void iio_ring_buffer_unregister(struct iio_ring_buffer *ring)
{};
diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c
index b71ce3900649..feb84e27c362 100644
--- a/drivers/staging/iio/ring_sw.c
+++ b/drivers/staging/iio/ring_sw.c
@@ -12,10 +12,41 @@
#include <linux/module.h>
#include <linux/device.h>
#include <linux/workqueue.h>
+#include <linux/sched.h>
#include <linux/poll.h>
#include "ring_sw.h"
#include "trigger.h"
+/**
+ * struct iio_sw_ring_buffer - software ring buffer
+ * @buf: generic ring buffer elements
+ * @data: the ring buffer memory
+ * @read_p: read pointer (oldest available)
+ * @write_p: write pointer
+ * @last_written_p: read pointer (newest available)
+ * @half_p: half buffer length behind write_p (event generation)
+ * @use_count: reference count to prevent resizing when in use
+ * @update_needed: flag to indicated change in size requested
+ * @use_lock: lock to prevent change in size when in use
+ *
+ * Note that the first element of all ring buffers must be a
+ * struct iio_ring_buffer.
+**/
+struct iio_sw_ring_buffer {
+ struct iio_ring_buffer buf;
+ unsigned char *data;
+ unsigned char *read_p;
+ unsigned char *write_p;
+ unsigned char *last_written_p;
+ /* used to act as a point at which to signal an event */
+ unsigned char *half_p;
+ int use_count;
+ int update_needed;
+ spinlock_t use_lock;
+};
+
+#define iio_to_sw_ring(r) container_of(r, struct iio_sw_ring_buffer, buf)
+
static inline int __iio_allocate_sw_ring_buffer(struct iio_sw_ring_buffer *ring,
int bytes_per_datum, int length)
{
@@ -40,23 +71,21 @@ static inline void __iio_free_sw_ring_buffer(struct iio_sw_ring_buffer *ring)
kfree(ring->data);
}
-void iio_mark_sw_rb_in_use(struct iio_ring_buffer *r)
+static void iio_mark_sw_rb_in_use(struct iio_ring_buffer *r)
{
struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r);
spin_lock(&ring->use_lock);
ring->use_count++;
spin_unlock(&ring->use_lock);
}
-EXPORT_SYMBOL(iio_mark_sw_rb_in_use);
-void iio_unmark_sw_rb_in_use(struct iio_ring_buffer *r)
+static void iio_unmark_sw_rb_in_use(struct iio_ring_buffer *r)
{
struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r);
spin_lock(&ring->use_lock);
ring->use_count--;
spin_unlock(&ring->use_lock);
}
-EXPORT_SYMBOL(iio_unmark_sw_rb_in_use);
/* Ring buffer related functionality */
@@ -68,7 +97,6 @@ static int iio_store_to_sw_ring(struct iio_sw_ring_buffer *ring,
unsigned char *data, s64 timestamp)
{
int ret = 0;
- int code;
unsigned char *temp_ptr, *change_test_ptr;
/* initial store */
@@ -123,14 +151,6 @@ static int iio_store_to_sw_ring(struct iio_sw_ring_buffer *ring,
*/
if (change_test_ptr == ring->read_p)
ring->read_p = temp_ptr;
-
- spin_lock(&ring->buf.shared_ev_pointer.lock);
-
- ret = iio_push_or_escallate_ring_event(&ring->buf,
- IIO_EVENT_CODE_RING_100_FULL, timestamp);
- spin_unlock(&ring->buf.shared_ev_pointer.lock);
- if (ret)
- goto error_ret;
}
/* investigate if our event barrier has been passed */
/* There are definite 'issues' with this and chances of
@@ -140,41 +160,35 @@ static int iio_store_to_sw_ring(struct iio_sw_ring_buffer *ring,
if (ring->half_p == ring->data + ring->buf.length*ring->buf.bytes_per_datum)
ring->half_p = ring->data;
if (ring->half_p == ring->read_p) {
- spin_lock(&ring->buf.shared_ev_pointer.lock);
- code = IIO_EVENT_CODE_RING_50_FULL;
- ret = __iio_push_event(&ring->buf.ev_int,
- code,
- timestamp,
- &ring->buf.shared_ev_pointer);
- spin_unlock(&ring->buf.shared_ev_pointer.lock);
+ ring->buf.stufftoread = true;
+ wake_up_interruptible(&ring->buf.pollq);
}
-error_ret:
return ret;
}
-int iio_rip_sw_rb(struct iio_ring_buffer *r,
- size_t count, char __user *buf, int *dead_offset)
+static int iio_read_first_n_sw_rb(struct iio_ring_buffer *r,
+ size_t n, char __user *buf)
{
struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r);
u8 *initial_read_p, *initial_write_p, *current_read_p, *end_read_p;
u8 *data;
- int ret, max_copied;
- int bytes_to_rip;
+ int ret, max_copied, bytes_to_rip, dead_offset;
/* A userspace program has probably made an error if it tries to
* read something that is not a whole number of bpds.
* Return an error.
*/
- if (count % ring->buf.bytes_per_datum) {
+ if (n % ring->buf.bytes_per_datum) {
ret = -EINVAL;
printk(KERN_INFO "Ring buffer read request not whole number of"
"samples: Request bytes %zd, Current bytes per datum %d\n",
- count, ring->buf.bytes_per_datum);
+ n, ring->buf.bytes_per_datum);
goto error_ret;
}
/* Limit size to whole of ring buffer */
- bytes_to_rip = min((size_t)(ring->buf.bytes_per_datum*ring->buf.length), count);
+ bytes_to_rip = min((size_t)(ring->buf.bytes_per_datum*ring->buf.length),
+ n);
data = kmalloc(bytes_to_rip, GFP_KERNEL);
if (data == NULL) {
@@ -240,9 +254,9 @@ int iio_rip_sw_rb(struct iio_ring_buffer *r,
current_read_p = ring->read_p;
if (initial_read_p <= current_read_p)
- *dead_offset = current_read_p - initial_read_p;
+ dead_offset = current_read_p - initial_read_p;
else
- *dead_offset = ring->buf.length*ring->buf.bytes_per_datum
+ dead_offset = ring->buf.length*ring->buf.bytes_per_datum
- (initial_read_p - current_read_p);
/* possible issue if the initial write has been lapped or indeed
@@ -250,7 +264,7 @@ int iio_rip_sw_rb(struct iio_ring_buffer *r,
/* No valid data read.
* In this case the read pointer is already correct having been
* pushed further than we would look. */
- if (max_copied - *dead_offset < 0) {
+ if (max_copied - dead_offset < 0) {
ret = 0;
goto error_free_data_cpy;
}
@@ -266,26 +280,30 @@ int iio_rip_sw_rb(struct iio_ring_buffer *r,
while (ring->read_p != end_read_p)
ring->read_p = end_read_p;
- ret = max_copied - *dead_offset;
+ ret = max_copied - dead_offset;
- if (copy_to_user(buf, data + *dead_offset, ret)) {
+ if (copy_to_user(buf, data + dead_offset, ret)) {
ret = -EFAULT;
goto error_free_data_cpy;
}
+
+ if (bytes_to_rip >= ring->buf.length*ring->buf.bytes_per_datum/2)
+ ring->buf.stufftoread = 0;
+
error_free_data_cpy:
kfree(data);
error_ret:
return ret;
}
-EXPORT_SYMBOL(iio_rip_sw_rb);
-int iio_store_to_sw_rb(struct iio_ring_buffer *r, u8 *data, s64 timestamp)
+static int iio_store_to_sw_rb(struct iio_ring_buffer *r,
+ u8 *data,
+ s64 timestamp)
{
struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r);
return iio_store_to_sw_ring(ring, data, timestamp);
}
-EXPORT_SYMBOL(iio_store_to_sw_rb);
static int iio_read_last_from_sw_ring(struct iio_sw_ring_buffer *ring,
unsigned char *data)
@@ -309,18 +327,18 @@ again:
return 0;
}
-int iio_read_last_from_sw_rb(struct iio_ring_buffer *r,
+static int iio_read_last_from_sw_rb(struct iio_ring_buffer *r,
unsigned char *data)
{
return iio_read_last_from_sw_ring(iio_to_sw_ring(r), data);
}
-EXPORT_SYMBOL(iio_read_last_from_sw_rb);
-int iio_request_update_sw_rb(struct iio_ring_buffer *r)
+static int iio_request_update_sw_rb(struct iio_ring_buffer *r)
{
int ret = 0;
struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r);
+ r->stufftoread = false;
spin_lock(&ring->use_lock);
if (!ring->update_needed)
goto error_ret;
@@ -335,54 +353,49 @@ error_ret:
spin_unlock(&ring->use_lock);
return ret;
}
-EXPORT_SYMBOL(iio_request_update_sw_rb);
-int iio_get_bytes_per_datum_sw_rb(struct iio_ring_buffer *r)
+static int iio_get_bytes_per_datum_sw_rb(struct iio_ring_buffer *r)
{
struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r);
return ring->buf.bytes_per_datum;
}
-EXPORT_SYMBOL(iio_get_bytes_per_datum_sw_rb);
-int iio_set_bytes_per_datum_sw_rb(struct iio_ring_buffer *r, size_t bpd)
+static int iio_set_bytes_per_datum_sw_rb(struct iio_ring_buffer *r, size_t bpd)
{
if (r->bytes_per_datum != bpd) {
r->bytes_per_datum = bpd;
- if (r->access.mark_param_change)
- r->access.mark_param_change(r);
+ if (r->access->mark_param_change)
+ r->access->mark_param_change(r);
}
return 0;
}
-EXPORT_SYMBOL(iio_set_bytes_per_datum_sw_rb);
-int iio_get_length_sw_rb(struct iio_ring_buffer *r)
+static int iio_get_length_sw_rb(struct iio_ring_buffer *r)
{
return r->length;
}
-EXPORT_SYMBOL(iio_get_length_sw_rb);
-int iio_set_length_sw_rb(struct iio_ring_buffer *r, int length)
+static int iio_set_length_sw_rb(struct iio_ring_buffer *r, int length)
{
if (r->length != length) {
r->length = length;
- if (r->access.mark_param_change)
- r->access.mark_param_change(r);
+ if (r->access->mark_param_change)
+ r->access->mark_param_change(r);
}
return 0;
}
-EXPORT_SYMBOL(iio_set_length_sw_rb);
-int iio_mark_update_needed_sw_rb(struct iio_ring_buffer *r)
+static int iio_mark_update_needed_sw_rb(struct iio_ring_buffer *r)
{
struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r);
ring->update_needed = true;
return 0;
}
-EXPORT_SYMBOL(iio_mark_update_needed_sw_rb);
static void iio_sw_rb_release(struct device *dev)
{
struct iio_ring_buffer *r = to_iio_ring_buffer(dev);
+ iio_ring_access_release(&r->dev);
kfree(iio_to_sw_ring(r));
}
@@ -420,13 +433,12 @@ struct iio_ring_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev)
ring = kzalloc(sizeof *ring, GFP_KERNEL);
if (!ring)
return NULL;
+ ring->update_needed = true;
buf = &ring->buf;
iio_ring_buffer_init(buf, indio_dev);
__iio_init_sw_ring_buffer(ring);
buf->dev.type = &iio_sw_ring_type;
- device_initialize(&buf->dev);
buf->dev.parent = &indio_dev->dev;
- buf->dev.bus = &iio_bus_type;
dev_set_drvdata(&buf->dev, (void *)buf);
return buf;
@@ -440,73 +452,20 @@ void iio_sw_rb_free(struct iio_ring_buffer *r)
}
EXPORT_SYMBOL(iio_sw_rb_free);
-int iio_sw_ring_preenable(struct iio_dev *indio_dev)
-{
- struct iio_ring_buffer *ring = indio_dev->ring;
- size_t size;
- dev_dbg(&indio_dev->dev, "%s\n", __func__);
- /* Check if there are any scan elements enabled, if not fail*/
- if (!(ring->scan_count || ring->scan_timestamp))
- return -EINVAL;
- if (ring->scan_timestamp)
- if (ring->scan_count)
- /* Timestamp (aligned to s64) and data */
- size = (((ring->scan_count * ring->bpe)
- + sizeof(s64) - 1)
- & ~(sizeof(s64) - 1))
- + sizeof(s64);
- else /* Timestamp only */
- size = sizeof(s64);
- else /* Data only */
- size = ring->scan_count * ring->bpe;
- ring->access.set_bytes_per_datum(ring, size);
-
- return 0;
-}
-EXPORT_SYMBOL(iio_sw_ring_preenable);
-
-void iio_sw_trigger_bh_to_ring(struct work_struct *work_s)
-{
- struct iio_sw_ring_helper_state *st
- = container_of(work_s, struct iio_sw_ring_helper_state,
- work_trigger_to_ring);
- struct iio_ring_buffer *ring = st->indio_dev->ring;
- int len = 0;
- size_t datasize = ring->access.get_bytes_per_datum(ring);
- char *data = kmalloc(datasize, GFP_KERNEL);
-
- if (data == NULL) {
- dev_err(st->indio_dev->dev.parent,
- "memory alloc failed in ring bh");
- return;
- }
-
- if (ring->scan_count)
- len = st->get_ring_element(st, data);
-
- /* Guaranteed to be aligned with 8 byte boundary */
- if (ring->scan_timestamp)
- *(s64 *)(((phys_addr_t)data + len
- + sizeof(s64) - 1) & ~(sizeof(s64) - 1))
- = st->last_timestamp;
- ring->access.store_to(ring,
- (u8 *)data,
- st->last_timestamp);
-
- iio_trigger_notify_done(st->indio_dev->trig);
- kfree(data);
-
- return;
-}
-EXPORT_SYMBOL(iio_sw_trigger_bh_to_ring);
-
-void iio_sw_poll_func_th(struct iio_dev *indio_dev, s64 time)
-{ struct iio_sw_ring_helper_state *h
- = iio_dev_get_devdata(indio_dev);
- h->last_timestamp = time;
- schedule_work(&h->work_trigger_to_ring);
-}
-EXPORT_SYMBOL(iio_sw_poll_func_th);
+const struct iio_ring_access_funcs ring_sw_access_funcs = {
+ .mark_in_use = &iio_mark_sw_rb_in_use,
+ .unmark_in_use = &iio_unmark_sw_rb_in_use,
+ .store_to = &iio_store_to_sw_rb,
+ .read_last = &iio_read_last_from_sw_rb,
+ .read_first_n = &iio_read_first_n_sw_rb,
+ .mark_param_change = &iio_mark_update_needed_sw_rb,
+ .request_update = &iio_request_update_sw_rb,
+ .get_bytes_per_datum = &iio_get_bytes_per_datum_sw_rb,
+ .set_bytes_per_datum = &iio_set_bytes_per_datum_sw_rb,
+ .get_length = &iio_get_length_sw_rb,
+ .set_length = &iio_set_length_sw_rb,
+};
+EXPORT_SYMBOL(ring_sw_access_funcs);
MODULE_DESCRIPTION("Industrialio I/O software ring buffer");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/iio/ring_sw.h b/drivers/staging/iio/ring_sw.h
index 13341c1e35f2..15271639534b 100644
--- a/drivers/staging/iio/ring_sw.h
+++ b/drivers/staging/iio/ring_sw.h
@@ -23,205 +23,13 @@
#ifndef _IIO_RING_SW_H_
#define _IIO_RING_SW_H_
-/* NEEDS COMMENTS */
-/* The intention is that this should be a separate module from the iio core.
- * This is a bit like supporting algorithms dependent on what the device
- * driver requests - some may support multiple options */
-
-
-#include "iio.h"
#include "ring_generic.h"
-#if defined CONFIG_IIO_SW_RING || defined CONFIG_IIO_SW_RING_MODULE
-
-/**
- * iio_create_sw_rb() - software ring buffer allocation
- * @r: pointer to ring buffer pointer
- **/
-int iio_create_sw_rb(struct iio_ring_buffer **r);
-
-/**
- * iio_init_sw_rb() - initialize the software ring buffer
- * @r: pointer to a software ring buffer created by an
- * iio_create_sw_rb call
- * @indio_dev: industrial I/O device structure
- **/
-int iio_init_sw_rb(struct iio_ring_buffer *r, struct iio_dev *indio_dev);
-
-/**
- * iio_exit_sw_rb() - reverse what was done in iio_init_sw_rb
- * @r: pointer to a software ring buffer created by an
- * iio_create_sw_rb call
- **/
-void iio_exit_sw_rb(struct iio_ring_buffer *r);
-
-/**
- * iio_free_sw_rb() - free memory occupied by the core ring buffer struct
- * @r: pointer to a software ring buffer created by an
- * iio_create_sw_rb call
- **/
-void iio_free_sw_rb(struct iio_ring_buffer *r);
-
-/**
- * iio_mark_sw_rb_in_use() - reference counting to prevent incorrect chances
- * @r: pointer to a software ring buffer created by an
- * iio_create_sw_rb call
- **/
-void iio_mark_sw_rb_in_use(struct iio_ring_buffer *r);
-
-/**
- * iio_unmark_sw_rb_in_use() - notify the ring buffer that we don't care anymore
- * @r: pointer to a software ring buffer created by an
- * iio_create_sw_rb call
- **/
-void iio_unmark_sw_rb_in_use(struct iio_ring_buffer *r);
-
-/**
- * iio_read_last_from_sw_rb() - attempt to read the last stored datum from the rb
- * @r: pointer to a software ring buffer created by an
- * iio_create_sw_rb call
- * @data: where to store the last datum
- **/
-int iio_read_last_from_sw_rb(struct iio_ring_buffer *r, u8 *data);
-
-/**
- * iio_store_to_sw_rb() - store a new datum to the ring buffer
- * @r: pointer to ring buffer instance
- * @data: the datum to be stored including timestamp if relevant
- * @timestamp: timestamp which will be attached to buffer events if relevant
- **/
-int iio_store_to_sw_rb(struct iio_ring_buffer *r, u8 *data, s64 timestamp);
-
-/**
- * iio_rip_sw_rb() - attempt to read data from the ring buffer
- * @r: ring buffer instance
- * @count: number of datum's to try and read
- * @buf: userspace buffer into which data is copied
- * @dead_offset: how much of the stored data was possibly invalidated by
- * the end of the copy.
- **/
-int iio_rip_sw_rb(struct iio_ring_buffer *r,
- size_t count,
- char __user *buf,
- int *dead_offset);
-
-/**
- * iio_request_update_sw_rb() - update params if update needed
- * @r: pointer to a software ring buffer created by an
- * iio_create_sw_rb call
- **/
-int iio_request_update_sw_rb(struct iio_ring_buffer *r);
-
-/**
- * iio_mark_update_needed_sw_rb() - tell the ring buffer it needs a param update
- * @r: pointer to a software ring buffer created by an
- * iio_create_sw_rb call
- **/
-int iio_mark_update_needed_sw_rb(struct iio_ring_buffer *r);
-
-
-/**
- * iio_get_bytes_per_datum_sw_rb() - get the datum size in bytes
- * @r: pointer to a software ring buffer created by an
- * iio_create_sw_rb call
- **/
-int iio_get_bytes_per_datum_sw_rb(struct iio_ring_buffer *r);
-
-/**
- * iio_set_bytes_per_datum_sw_rb() - set the datum size in bytes
- * @r: pointer to a software ring buffer created by an
- * iio_create_sw_rb call
- * @bpd: bytes per datum value
- **/
-int iio_set_bytes_per_datum_sw_rb(struct iio_ring_buffer *r, size_t bpd);
-
/**
- * iio_get_length_sw_rb() - get how many datums the rb may contain
- * @r: pointer to a software ring buffer created by an
- * iio_create_sw_rb call
+ * ring_sw_access_funcs - access functions for a software ring buffer
**/
-int iio_get_length_sw_rb(struct iio_ring_buffer *r);
-
-/**
- * iio_set_length_sw_rb() - set how many datums the rb may contain
- * @r: pointer to a software ring buffer created by an
- * iio_create_sw_rb call
- * @length: max number of data items for the ring buffer
- **/
-int iio_set_length_sw_rb(struct iio_ring_buffer *r, int length);
-
-/**
- * iio_ring_sw_register_funcs() - helper function to set up rb access
- * @ra: pointer to @iio_ring_access_funcs
- **/
-static inline void iio_ring_sw_register_funcs(struct iio_ring_access_funcs *ra)
-{
- ra->mark_in_use = &iio_mark_sw_rb_in_use;
- ra->unmark_in_use = &iio_unmark_sw_rb_in_use;
-
- ra->store_to = &iio_store_to_sw_rb;
- ra->read_last = &iio_read_last_from_sw_rb;
- ra->rip_lots = &iio_rip_sw_rb;
-
- ra->mark_param_change = &iio_mark_update_needed_sw_rb;
- ra->request_update = &iio_request_update_sw_rb;
-
- ra->get_bytes_per_datum = &iio_get_bytes_per_datum_sw_rb;
- ra->set_bytes_per_datum = &iio_set_bytes_per_datum_sw_rb;
-
- ra->get_length = &iio_get_length_sw_rb;
- ra->set_length = &iio_set_length_sw_rb;
-};
-
-/**
- * struct iio_sw_ring_buffer - software ring buffer
- * @buf: generic ring buffer elements
- * @data: the ring buffer memory
- * @read_p: read pointer (oldest available)
- * @write_p: write pointer
- * @last_written_p: read pointer (newest available)
- * @half_p: half buffer length behind write_p (event generation)
- * @use_count: reference count to prevent resizing when in use
- * @update_needed: flag to indicated change in size requested
- * @use_lock: lock to prevent change in size when in use
- *
- * Note that the first element of all ring buffers must be a
- * struct iio_ring_buffer.
-**/
-
-struct iio_sw_ring_buffer {
- struct iio_ring_buffer buf;
- unsigned char *data;
- unsigned char *read_p;
- unsigned char *write_p;
- unsigned char *last_written_p;
- /* used to act as a point at which to signal an event */
- unsigned char *half_p;
- int use_count;
- int update_needed;
- spinlock_t use_lock;
-};
-
-#define iio_to_sw_ring(r) container_of(r, struct iio_sw_ring_buffer, buf)
+extern const struct iio_ring_access_funcs ring_sw_access_funcs;
struct iio_ring_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev);
void iio_sw_rb_free(struct iio_ring_buffer *ring);
-
-int iio_sw_ring_preenable(struct iio_dev *indio_dev);
-
-struct iio_sw_ring_helper_state {
- struct work_struct work_trigger_to_ring;
- struct iio_dev *indio_dev;
- int (*get_ring_element)(struct iio_sw_ring_helper_state *st, u8 *buf);
- s64 last_timestamp;
-};
-
-void iio_sw_poll_func_th(struct iio_dev *indio_dev, s64 time);
-void iio_sw_trigger_bh_to_ring(struct work_struct *work_s);
-
-#else /* CONFIG_IIO_RING_BUFFER*/
-struct iio_sw_ring_helper_state {
- struct iio_dev *indio_dev;
-};
-#endif /* !CONFIG_IIO_RING_BUFFER */
#endif /* _IIO_RING_SW_H_ */
diff --git a/drivers/staging/iio/sysfs.h b/drivers/staging/iio/sysfs.h
index 24b74ddcd083..dd79b5844212 100644
--- a/drivers/staging/iio/sysfs.h
+++ b/drivers/staging/iio/sysfs.h
@@ -15,30 +15,18 @@
#include "iio.h"
/**
- * struct iio_event_attr - event control attribute
- * @dev_attr: underlying device attribute
- * @mask: mask for the event when detecting
- * @listel: list header to allow addition to list of event handlers
-*/
-struct iio_event_attr {
- struct device_attribute dev_attr;
- int mask;
- struct iio_event_handler_list *listel;
-};
-
-#define to_iio_event_attr(_dev_attr) \
- container_of(_dev_attr, struct iio_event_attr, dev_attr)
-
-/**
* 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;
};
#define to_iio_dev_attr(_dev_attr) \
@@ -101,13 +89,6 @@ struct iio_const_attr {
IIO_DEVICE_ATTR(revision, S_IRUGO, _show, NULL, 0)
/**
- * IIO_DEV_ATTR_NAME - chip type dependent identifier
- * @_show: output method for the attribute
- **/
-#define IIO_DEV_ATTR_NAME(_show) \
- IIO_DEVICE_ATTR(name, S_IRUGO, _show, NULL, 0)
-
-/**
* IIO_DEV_ATTR_RESET: resets the device
**/
#define IIO_DEV_ATTR_RESET(_store) \
@@ -180,104 +161,27 @@ struct iio_const_attr {
#define IIO_CONST_ATTR_TEMP_SCALE(_string) \
IIO_CONST_ATTR(temp_scale, _string)
-/**
- * IIO_EVENT_SH - generic shared event handler
- * @_name: event name
- * @_handler: handler function to be called
- *
- * This is used in cases where more than one event may result from a single
- * handler. Often the case that some alarm register must be read and multiple
- * alarms may have been triggered.
- **/
-#define IIO_EVENT_SH(_name, _handler) \
- static struct iio_event_handler_list \
- iio_event_##_name = { \
- .handler = _handler, \
- .refcount = 0, \
- .exist_lock = __MUTEX_INITIALIZER(iio_event_##_name \
- .exist_lock), \
- .list = { \
- .next = &iio_event_##_name.list, \
- .prev = &iio_event_##_name.list, \
- }, \
- };
-
-/**
- * IIO_EVENT_ATTR_SH - generic shared event attribute
- * @_name: event name
- * @_ev_list: event handler list
- * @_show: output method for the attribute
- * @_store: input method for the attribute
- * @_mask: mask used when detecting the event
- *
- * An attribute with an associated IIO_EVENT_SH
- **/
-#define IIO_EVENT_ATTR_SH(_name, _ev_list, _show, _store, _mask) \
- static struct iio_event_attr \
- iio_event_attr_##_name \
- = { .dev_attr = __ATTR(_name, S_IRUGO | S_IWUSR, \
- _show, _store), \
- .mask = _mask, \
- .listel = &_ev_list };
-
-#define IIO_EVENT_ATTR_NAMED_SH(_vname, _name, _ev_list, _show, _store, _mask) \
- static struct iio_event_attr \
- iio_event_attr_##_vname \
- = { .dev_attr = __ATTR(_name, S_IRUGO | S_IWUSR, \
- _show, _store), \
- .mask = _mask, \
- .listel = &_ev_list };
-
-/**
- * IIO_EVENT_ATTR - non-shared event attribute
- * @_name: event name
- * @_show: output method for the attribute
- * @_store: input method for the attribute
- * @_mask: mask used when detecting the event
- * @_handler: handler function to be called
- **/
-#define IIO_EVENT_ATTR(_name, _show, _store, _mask, _handler) \
- IIO_EVENT_SH(_name, _handler); \
- static struct \
- iio_event_attr \
- iio_event_attr_##_name \
- = { .dev_attr = __ATTR(_name, S_IRUGO | S_IWUSR, \
- _show, _store), \
- .mask = _mask, \
- .listel = &iio_event_##_name }; \
-
-/**
- * IIO_EVENT_ATTR_DATA_RDY - event driven by data ready signal
- * @_show: output method for the attribute
- * @_store: input method for the attribute
- * @_mask: mask used when detecting the event
- * @_handler: handler function to be called
- *
- * Not typically implemented in devices where full triggering support
- * has been implemented.
- **/
-#define IIO_EVENT_ATTR_DATA_RDY(_show, _store, _mask, _handler) \
- IIO_EVENT_ATTR(data_rdy, _show, _store, _mask, _handler)
-
-#define IIO_EV_CLASS_BUFFER 0
-#define IIO_EV_CLASS_IN 1
-#define IIO_EV_CLASS_ACCEL 2
-#define IIO_EV_CLASS_GYRO 3
-#define IIO_EV_CLASS_MAGN 4
-#define IIO_EV_CLASS_LIGHT 5
-#define IIO_EV_CLASS_PROXIMITY 6
-
-#define IIO_EV_MOD_X 0
-#define IIO_EV_MOD_Y 1
-#define IIO_EV_MOD_Z 2
-#define IIO_EV_MOD_X_AND_Y 3
-#define IIO_EV_MOD_X_ANX_Z 4
-#define IIO_EV_MOD_Y_AND_Z 5
-#define IIO_EV_MOD_X_AND_Y_AND_Z 6
-#define IIO_EV_MOD_X_OR_Y 7
-#define IIO_EV_MOD_X_OR_Z 8
-#define IIO_EV_MOD_Y_OR_Z 9
-#define IIO_EV_MOD_X_OR_Y_OR_Z 10
+/* 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
@@ -287,6 +191,10 @@ struct iio_const_attr {
#define IIO_EV_DIR_RISING 1
#define IIO_EV_DIR_FALLING 2
+#define IIO_EV_TYPE_MAX 8
+#define IIO_EV_BIT(type, direction) \
+ (1 << (type*IIO_EV_TYPE_MAX + direction))
+
#define IIO_EVENT_CODE(channelclass, orient_bit, number, \
modifier, type, direction) \
(channelclass | (orient_bit << 8) | ((number) << 9) | \
@@ -303,38 +211,12 @@ struct iio_const_attr {
#define IIO_BUFFER_EVENT_CODE(code) \
(IIO_EV_CLASS_BUFFER | (code << 8))
-/**
- * IIO_EVENT_ATTR_RING_50_FULL - ring buffer event to indicate 50% full
- * @_show: output method for the attribute
- * @_store: input method for the attribute
- * @_mask: mask used when detecting the event
- * @_handler: handler function to be called
- **/
-#define IIO_EVENT_ATTR_RING_50_FULL(_show, _store, _mask, _handler) \
- IIO_EVENT_ATTR(ring_50_full, _show, _store, _mask, _handler)
-
-/**
- * IIO_EVENT_ATTR_RING_50_FULL_SH - shared ring event to indicate 50% full
- * @_evlist: event handler list
- * @_show: output method for the attribute
- * @_store: input method for the attribute
- * @_mask: mask used when detecting the event
- **/
-#define IIO_EVENT_ATTR_RING_50_FULL_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(ring_50_full, _evlist, _show, _store, _mask)
+#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 24) & 0xf)
-/**
- * IIO_EVENT_ATTR_RING_75_FULL_SH - shared ring event to indicate 75% full
- * @_evlist: event handler list
- * @_show: output method for the attribute
- * @_store: input method for the attribute
- * @_mask: mask used when detecting the event
- **/
-#define IIO_EVENT_ATTR_RING_75_FULL_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(ring_75_full, _evlist, _show, _store, _mask)
+/* Event code number extraction depends on which type of event we have.
+ * Perhaps review this function in the future*/
+#define IIO_EVENT_CODE_EXTRACT_NUM(mask) ((mask >> 9) & 0x0f)
-#define IIO_EVENT_CODE_RING_50_FULL IIO_BUFFER_EVENT_CODE(0)
-#define IIO_EVENT_CODE_RING_75_FULL IIO_BUFFER_EVENT_CODE(1)
-#define IIO_EVENT_CODE_RING_100_FULL IIO_BUFFER_EVENT_CODE(2)
+#define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 13) & 0x7)
#endif /* _INDUSTRIAL_IO_SYSFS_H_ */
diff --git a/drivers/staging/iio/trigger.h b/drivers/staging/iio/trigger.h
index 469beba3e71d..f329fe10fa2f 100644
--- a/drivers/staging/iio/trigger.h
+++ b/drivers/staging/iio/trigger.h
@@ -6,9 +6,15 @@
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
+#include <linux/irq.h>
+
#ifndef _IIO_TRIGGER_H_
#define _IIO_TRIGGER_H_
+struct iio_subirq {
+ bool enabled;
+};
+
/**
* struct iio_trigger - industrial I/O trigger device
*
@@ -18,14 +24,16 @@
* @private_data: [DRIVER] device specific data
* @list: [INTERN] used in maintenance of global trigger list
* @alloc_list: [DRIVER] used for driver specific trigger list
- * @pollfunc_list_lock: [INTERN] protection of the polling function list
- * @pollfunc_list: [INTERN] list of functions to run on trigger.
- * @control_attrs: [DRIVER] sysfs attributes relevant to trigger type
* @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)
+ * @subirq_chip: [INTERN] associate 'virtual' irq chip.
+ * @subirq_base: [INTERN] base number for irqs provided by trigger.
+ * @subirqs: [INTERN] information about the 'child' irqs.
+ * @pool: [INTERN] bitmap of irqs currently in use.
+ * @pool_lock: [INTERN] protection of the irq pool.
**/
struct iio_trigger {
int id;
@@ -35,14 +43,18 @@ struct iio_trigger {
void *private_data;
struct list_head list;
struct list_head alloc_list;
- spinlock_t pollfunc_list_lock;
- struct list_head pollfunc_list;
- const struct attribute_group *control_attrs;
struct module *owner;
int use_count;
int (*set_trigger_state)(struct iio_trigger *trig, bool state);
int (*try_reenable)(struct iio_trigger *trig);
+
+ struct irq_chip subirq_chip;
+ int subirq_base;
+
+ struct iio_subirq subirqs[CONFIG_IIO_CONSUMERS_PER_TRIGGER];
+ unsigned long pool[BITS_TO_LONGS(CONFIG_IIO_CONSUMERS_PER_TRIGGER)];
+ struct mutex pool_lock;
};
static inline struct iio_trigger *to_iio_trigger(struct device *d)
@@ -63,27 +75,6 @@ static inline void iio_get_trigger(struct iio_trigger *trig)
};
/**
- * iio_trigger_read_name() - sysfs access function to get the trigger name
- * @dev: the system device
- * @attr: device attributes for the device
- * @buf: output buffer to store the trigger name
- **/
-ssize_t iio_trigger_read_name(struct device *dev,
- struct device_attribute *attr,
- char *buf);
-
-#define IIO_TRIGGER_NAME_ATTR DEVICE_ATTR(name, S_IRUGO, \
- iio_trigger_read_name, \
- NULL);
-
-/**
- * iio_trigger_find_by_name() - search global trigger list
- * @name: trigger name to search for
- * @len: trigger name string length to compare
- **/
-struct iio_trigger *iio_trigger_find_by_name(const char *name, size_t len);
-
-/**
* iio_trigger_register() - register a trigger with the IIO core
* @trig_info: trigger to be registered
**/
@@ -119,36 +110,65 @@ int iio_trigger_dettach_poll_func(struct iio_trigger *trig,
* Typically called in relevant hardware interrupt handler.
**/
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 - poll function pair
*
- * @list: associate this with a triggers pollfunc_list
* @private_data: data specific to device (passed into poll func)
- * @poll_func_immediate: function in here is run first. They should be
- * extremely lightweight. Typically used for latch
- * control on sensor supporting it.
- * @poll_func_main: function in here is run after all immediates.
- * Reading from sensor etc typically involves
- * scheduling from here.
- *
- * The two stage approach used here is only important when multiple sensors are
- * being triggered by a single trigger. This really comes into its own with
- * simultaneous sampling devices where a simple latch command can be used to
- * make the device store the values on all inputs.
+ * @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 {
- struct list_head list;
void *private_data;
- void (*poll_func_immediate)(struct iio_dev *indio_dev);
- void (*poll_func_main)(struct iio_dev *private_data, s64 time);
-
+ irqreturn_t (*h)(int irq, void *p);
+ irqreturn_t (*thread)(int irq, void *p);
+ int type;
+ char *name;
+ int irq;
+ s64 timestamp;
};
-int iio_alloc_pollfunc(struct iio_dev *indio_dev,
- void (*immediate)(struct iio_dev *indio_dev),
- void (*main)(struct iio_dev *private_data, s64 time));
+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
@@ -157,8 +177,8 @@ int iio_alloc_pollfunc(struct iio_dev *indio_dev,
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(void);
-
+struct iio_trigger *iio_allocate_trigger(const char *fmt, ...)
+ __attribute__((format(printf, 1, 2)));
void iio_free_trigger(struct iio_trigger *trig);
#endif /* _IIO_TRIGGER_H_ */
diff --git a/drivers/staging/iio/trigger/Kconfig b/drivers/staging/iio/trigger/Kconfig
index c33777e0a8b3..b8abf5473ddc 100644
--- a/drivers/staging/iio/trigger/Kconfig
+++ b/drivers/staging/iio/trigger/Kconfig
@@ -31,6 +31,7 @@ config IIO_SYSFS_TRIGGER
config IIO_BFIN_TMR_TRIGGER
tristate "Blackfin TIMER trigger"
depends on BLACKFIN
+ select BFIN_GPTIMERS
help
Provides support for using a Blackfin timer as IIO triggers.
If unsure, say N (but it's safe to say "Y").
diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
index 583bef0936e8..4f1729565582 100644
--- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
+++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
@@ -106,11 +106,9 @@ static ssize_t iio_bfin_tmr_frequency_show(struct device *dev,
static DEVICE_ATTR(frequency, S_IRUGO | S_IWUSR, iio_bfin_tmr_frequency_show,
iio_bfin_tmr_frequency_store);
-static IIO_TRIGGER_NAME_ATTR;
static struct attribute *iio_bfin_tmr_trigger_attrs[] = {
&dev_attr_frequency.attr,
- &dev_attr_name.attr,
NULL,
};
@@ -118,6 +116,11 @@ static const struct attribute_group iio_bfin_tmr_trigger_attr_group = {
.attrs = iio_bfin_tmr_trigger_attrs,
};
+static const struct attribute_group *iio_bfin_tmr_trigger_attr_groups[] = {
+ &iio_bfin_tmr_trigger_attr_group,
+ NULL
+};
+
static irqreturn_t iio_bfin_tmr_trigger_isr(int irq, void *devid)
{
@@ -165,24 +168,18 @@ static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
st->timer_num = ret;
st->t = &iio_bfin_timer_code[st->timer_num];
- st->trig = iio_allocate_trigger();
+ st->trig = iio_allocate_trigger("bfintmr%d", st->timer_num);
if (!st->trig) {
ret = -ENOMEM;
goto out1;
}
st->trig->private_data = st;
- st->trig->control_attrs = &iio_bfin_tmr_trigger_attr_group;
st->trig->owner = THIS_MODULE;
- st->trig->name = kasprintf(GFP_KERNEL, "bfintmr%d", st->timer_num);
- if (st->trig->name == NULL) {
- ret = -ENOMEM;
- goto out2;
- }
-
+ st->trig->dev.groups = iio_bfin_tmr_trigger_attr_groups;
ret = iio_trigger_register(st->trig);
if (ret)
- goto out3;
+ goto out2;
ret = request_irq(st->irq, iio_bfin_tmr_trigger_isr,
0, st->trig->name, st);
@@ -201,8 +198,6 @@ static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
return 0;
out4:
iio_trigger_unregister(st->trig);
-out3:
- kfree(st->trig->name);
out2:
iio_put_trigger(st->trig);
out1:
@@ -218,7 +213,6 @@ static int __devexit iio_bfin_tmr_trigger_remove(struct platform_device *pdev)
disable_gptimers(st->t->bit);
free_irq(st->irq, st);
iio_trigger_unregister(st->trig);
- kfree(st->trig->name);
iio_put_trigger(st->trig);
kfree(st);
diff --git a/drivers/staging/iio/trigger/iio-trig-gpio.c b/drivers/staging/iio/trigger/iio-trig-gpio.c
index 2ce95e964cfd..b188635c3460 100644
--- a/drivers/staging/iio/trigger/iio-trig-gpio.c
+++ b/drivers/staging/iio/trigger/iio-trig-gpio.c
@@ -47,17 +47,6 @@ static irqreturn_t iio_gpio_trigger_poll(int irq, void *private)
return IRQ_HANDLED;
}
-static IIO_TRIGGER_NAME_ATTR;
-
-static struct attribute *iio_gpio_trigger_attrs[] = {
- &dev_attr_name.attr,
- NULL,
-};
-
-static const struct attribute_group iio_gpio_trigger_attr_group = {
- .attrs = iio_gpio_trigger_attrs,
-};
-
static int iio_gpio_trigger_probe(struct platform_device *pdev)
{
struct iio_gpio_trigger_info *trig_info;
@@ -79,7 +68,7 @@ static int iio_gpio_trigger_probe(struct platform_device *pdev)
for (irq = irq_res->start; irq <= irq_res->end; irq++) {
- trig = iio_allocate_trigger();
+ trig = iio_allocate_trigger("irqtrig%d", irq);
if (!trig) {
ret = -ENOMEM;
goto error_free_completed_registrations;
@@ -90,21 +79,15 @@ static int iio_gpio_trigger_probe(struct platform_device *pdev)
ret = -ENOMEM;
goto error_put_trigger;
}
- trig->control_attrs = &iio_gpio_trigger_attr_group;
trig->private_data = trig_info;
trig_info->irq = irq;
trig->owner = THIS_MODULE;
- trig->name = kasprintf(GFP_KERNEL, "irqtrig%d", irq);
- if (trig->name == NULL) {
- ret = -ENOMEM;
- goto error_free_trig_info;
- }
ret = request_irq(irq, iio_gpio_trigger_poll,
irqflags, trig->name, trig);
if (ret) {
dev_err(&pdev->dev,
"request IRQ-%d failed", irq);
- goto error_free_name;
+ goto error_free_trig_info;
}
ret = iio_trigger_register(trig);
@@ -124,8 +107,6 @@ static int iio_gpio_trigger_probe(struct platform_device *pdev)
/* First clean up the partly allocated trigger */
error_release_irq:
free_irq(irq, trig);
-error_free_name:
- kfree(trig->name);
error_free_trig_info:
kfree(trig_info);
error_put_trigger:
@@ -138,7 +119,6 @@ error_free_completed_registrations:
alloc_list) {
trig_info = trig->private_data;
free_irq(gpio_to_irq(trig_info->irq), trig);
- kfree(trig->name);
kfree(trig_info);
iio_trigger_unregister(trig);
}
@@ -159,7 +139,6 @@ static int iio_gpio_trigger_remove(struct platform_device *pdev)
trig_info = trig->private_data;
iio_trigger_unregister(trig);
free_irq(trig_info->irq, trig);
- kfree(trig->name);
kfree(trig_info);
iio_put_trigger(trig);
}
diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
index 24f174e1cda5..01cf7e20b515 100644
--- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
@@ -72,20 +72,24 @@ error_ret:
return ret;
}
-static IIO_TRIGGER_NAME_ATTR;
static DEVICE_ATTR(frequency, S_IRUGO | S_IWUSR,
iio_trig_periodic_read_freq,
iio_trig_periodic_write_freq);
static struct attribute *iio_trig_prtc_attrs[] = {
&dev_attr_frequency.attr,
- &dev_attr_name.attr,
NULL,
};
+
static const struct attribute_group iio_trig_prtc_attr_group = {
.attrs = iio_trig_prtc_attrs,
};
+static const struct attribute_group *iio_trig_prtc_attr_groups[] = {
+ &iio_trig_prtc_attr_group,
+ NULL
+};
+
static void iio_prtc_trigger_poll(void *private_data)
{
/* Timestamp is not provided currently */
@@ -103,7 +107,7 @@ static int iio_trig_periodic_rtc_probe(struct platform_device *dev)
for (i = 0;; i++) {
if (pdata[i] == NULL)
break;
- trig = iio_allocate_trigger();
+ trig = iio_allocate_trigger("periodic%s", pdata[i]);
if (!trig) {
ret = -ENOMEM;
goto error_free_completed_registrations;
@@ -118,25 +122,19 @@ 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->name = kasprintf(GFP_KERNEL, "periodic%s", pdata[i]);
- if (trig->name == NULL) {
- ret = -ENOMEM;
- goto error_free_trig_info;
- }
-
/* RTC access */
trig_info->rtc
= rtc_class_open(pdata[i]);
if (trig_info->rtc == NULL) {
ret = -EINVAL;
- goto error_free_name;
+ goto error_free_trig_info;
}
trig_info->task.func = iio_prtc_trigger_poll;
trig_info->task.private_data = trig;
ret = rtc_irq_register(trig_info->rtc, &trig_info->task);
if (ret)
goto error_close_rtc;
- trig->control_attrs = &iio_trig_prtc_attr_group;
+ trig->dev.groups = iio_trig_prtc_attr_groups;
ret = iio_trigger_register(trig);
if (ret)
goto error_unregister_rtc_irq;
@@ -146,8 +144,6 @@ error_unregister_rtc_irq:
rtc_irq_unregister(trig_info->rtc, &trig_info->task);
error_close_rtc:
rtc_class_close(trig_info->rtc);
-error_free_name:
- kfree(trig->name);
error_free_trig_info:
kfree(trig_info);
error_put_trigger_and_remove_from_list:
@@ -161,7 +157,6 @@ error_free_completed_registrations:
trig_info = trig->private_data;
rtc_irq_unregister(trig_info->rtc, &trig_info->task);
rtc_class_close(trig_info->rtc);
- kfree(trig->name);
kfree(trig_info);
iio_trigger_unregister(trig);
}
@@ -180,7 +175,6 @@ static int iio_trig_periodic_rtc_remove(struct platform_device *dev)
trig_info = trig->private_data;
rtc_irq_unregister(trig_info->rtc, &trig_info->task);
rtc_class_close(trig_info->rtc);
- kfree(trig->name);
kfree(trig_info);
iio_trigger_unregister(trig);
}
diff --git a/drivers/staging/iio/trigger/iio-trig-sysfs.c b/drivers/staging/iio/trigger/iio-trig-sysfs.c
index 127a2a33e4db..47248cd1fa0d 100644
--- a/drivers/staging/iio/trigger/iio-trig-sysfs.c
+++ b/drivers/staging/iio/trigger/iio-trig-sysfs.c
@@ -9,25 +9,92 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <linux/list.h>
#include "../iio.h"
#include "../trigger.h"
+struct iio_sysfs_trig {
+ struct iio_trigger *trig;
+ int id;
+ struct list_head l;
+};
+
+static LIST_HEAD(iio_sysfs_trig_list);
+static DEFINE_MUTEX(iio_syfs_trig_list_mut);
+
+static int iio_sysfs_trigger_probe(int id);
+static ssize_t iio_sysfs_trig_add(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ int ret;
+ unsigned long input;
+
+ ret = strict_strtoul(buf, 10, &input);
+ if (ret)
+ return ret;
+ ret = iio_sysfs_trigger_probe(input);
+ if (ret)
+ return ret;
+ return len;
+}
+static DEVICE_ATTR(add_trigger, S_IWUSR, NULL, &iio_sysfs_trig_add);
+
+static int iio_sysfs_trigger_remove(int id);
+static ssize_t iio_sysfs_trig_remove(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ int ret;
+ unsigned long input;
+
+ ret = strict_strtoul(buf, 10, &input);
+ if (ret)
+ return ret;
+ ret = iio_sysfs_trigger_remove(input);
+ if (ret)
+ return ret;
+ return len;
+}
+
+static DEVICE_ATTR(remove_trigger, S_IWUSR, NULL, &iio_sysfs_trig_remove);
+
+static struct attribute *iio_sysfs_trig_attrs[] = {
+ &dev_attr_add_trigger.attr,
+ &dev_attr_remove_trigger.attr,
+ NULL,
+};
+
+static const struct attribute_group iio_sysfs_trig_group = {
+ .attrs = iio_sysfs_trig_attrs,
+};
+
+static const struct attribute_group *iio_sysfs_trig_groups[] = {
+ &iio_sysfs_trig_group,
+ NULL
+};
+
+static struct device iio_sysfs_trig_dev = {
+ .bus = &iio_bus_type,
+ .groups = iio_sysfs_trig_groups,
+};
+
static ssize_t iio_sysfs_trigger_poll(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct iio_trigger *trig = dev_get_drvdata(dev);
- iio_trigger_poll(trig, 0);
+ iio_trigger_poll_chained(trig, 0);
return count;
}
static DEVICE_ATTR(trigger_now, S_IWUSR, NULL, iio_sysfs_trigger_poll);
-static IIO_TRIGGER_NAME_ATTR;
static struct attribute *iio_sysfs_trigger_attrs[] = {
&dev_attr_trigger_now.attr,
- &dev_attr_name.attr,
NULL,
};
@@ -35,70 +102,96 @@ static const struct attribute_group iio_sysfs_trigger_attr_group = {
.attrs = iio_sysfs_trigger_attrs,
};
-static int __devinit iio_sysfs_trigger_probe(struct platform_device *pdev)
+static const struct attribute_group *iio_sysfs_trigger_attr_groups[] = {
+ &iio_sysfs_trigger_attr_group,
+ NULL
+};
+
+static int iio_sysfs_trigger_probe(int id)
{
- struct iio_trigger *trig;
+ struct iio_sysfs_trig *t;
int ret;
-
- trig = iio_allocate_trigger();
- if (!trig) {
+ bool foundit = false;
+ mutex_lock(&iio_syfs_trig_list_mut);
+ list_for_each_entry(t, &iio_sysfs_trig_list, l)
+ if (id == t->id) {
+ foundit = true;
+ break;
+ }
+ if (foundit) {
+ ret = -EINVAL;
+ goto out1;
+ }
+ t = kmalloc(sizeof(*t), GFP_KERNEL);
+ if (t == NULL) {
ret = -ENOMEM;
goto out1;
}
-
- trig->control_attrs = &iio_sysfs_trigger_attr_group;
- trig->owner = THIS_MODULE;
- trig->name = kasprintf(GFP_KERNEL, "sysfstrig%d", pdev->id);
- if (trig->name == NULL) {
+ t->id = id;
+ t->trig = iio_allocate_trigger("sysfstrig%d", id);
+ if (!t->trig) {
ret = -ENOMEM;
- goto out2;
+ goto free_t;
}
- ret = iio_trigger_register(trig);
- if (ret)
- goto out3;
-
- platform_set_drvdata(pdev, trig);
+ t->trig->dev.groups = iio_sysfs_trigger_attr_groups;
+ t->trig->owner = THIS_MODULE;
+ t->trig->dev.parent = &iio_sysfs_trig_dev;
+ ret = iio_trigger_register(t->trig);
+ if (ret)
+ goto out2;
+ list_add(&t->l, &iio_sysfs_trig_list);
+ __module_get(THIS_MODULE);
+ mutex_unlock(&iio_syfs_trig_list_mut);
return 0;
-out3:
- kfree(trig->name);
+
out2:
- iio_put_trigger(trig);
+ iio_put_trigger(t->trig);
+free_t:
+ kfree(t);
out1:
-
+ mutex_unlock(&iio_syfs_trig_list_mut);
return ret;
}
-static int __devexit iio_sysfs_trigger_remove(struct platform_device *pdev)
+static int iio_sysfs_trigger_remove(int id)
{
- struct iio_trigger *trig = platform_get_drvdata(pdev);
+ bool foundit = false;
+ struct iio_sysfs_trig *t;
+ mutex_lock(&iio_syfs_trig_list_mut);
+ list_for_each_entry(t, &iio_sysfs_trig_list, l)
+ if (id == t->id) {
+ foundit = true;
+ break;
+ }
+ if (!foundit) {
+ mutex_unlock(&iio_syfs_trig_list_mut);
+ return -EINVAL;
+ }
- iio_trigger_unregister(trig);
- kfree(trig->name);
- iio_put_trigger(trig);
+ iio_trigger_unregister(t->trig);
+ iio_free_trigger(t->trig);
+ list_del(&t->l);
+ kfree(t);
+ module_put(THIS_MODULE);
+ mutex_unlock(&iio_syfs_trig_list_mut);
return 0;
}
-static struct platform_driver iio_sysfs_trigger_driver = {
- .driver = {
- .name = "iio_sysfs_trigger",
- .owner = THIS_MODULE,
- },
- .probe = iio_sysfs_trigger_probe,
- .remove = __devexit_p(iio_sysfs_trigger_remove),
-};
static int __init iio_sysfs_trig_init(void)
{
- return platform_driver_register(&iio_sysfs_trigger_driver);
+ device_initialize(&iio_sysfs_trig_dev);
+ dev_set_name(&iio_sysfs_trig_dev, "iio_sysfs_trigger");
+ return device_add(&iio_sysfs_trig_dev);
}
module_init(iio_sysfs_trig_init);
static void __exit iio_sysfs_trig_exit(void)
{
- platform_driver_unregister(&iio_sysfs_trigger_driver);
+ device_unregister(&iio_sysfs_trig_dev);
}
module_exit(iio_sysfs_trig_exit);