summaryrefslogtreecommitdiffstats
path: root/drivers/staging/iio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/iio')
-rw-r--r--drivers/staging/iio/Documentation/generic_buffer.c318
-rw-r--r--drivers/staging/iio/Documentation/iio_utils.h396
-rw-r--r--drivers/staging/iio/Documentation/lis3l02dqbuffersimple.c238
-rw-r--r--drivers/staging/iio/Documentation/overview.txt17
-rw-r--r--drivers/staging/iio/Documentation/ring.txt6
-rw-r--r--drivers/staging/iio/Documentation/sysfs-bus-iio390
-rw-r--r--drivers/staging/iio/Documentation/sysfs-bus-iio-light64
-rw-r--r--drivers/staging/iio/Documentation/sysfs-class-iio294
-rw-r--r--drivers/staging/iio/Documentation/userspace.txt56
-rw-r--r--drivers/staging/iio/accel/accel.h172
-rw-r--r--drivers/staging/iio/accel/adis16209_core.c48
-rw-r--r--drivers/staging/iio/accel/adis16209_ring.c90
-rw-r--r--drivers/staging/iio/accel/adis16209_trigger.c2
-rw-r--r--drivers/staging/iio/accel/adis16220_core.c26
-rw-r--r--drivers/staging/iio/accel/adis16240_core.c37
-rw-r--r--drivers/staging/iio/accel/adis16240_ring.c72
-rw-r--r--drivers/staging/iio/accel/adis16240_trigger.c2
-rw-r--r--drivers/staging/iio/accel/inclinometer.h2
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_core.c66
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_ring.c79
-rw-r--r--drivers/staging/iio/accel/sca3000.h2
-rw-r--r--drivers/staging/iio/accel/sca3000_core.c71
-rw-r--r--drivers/staging/iio/accel/sca3000_ring.c91
-rw-r--r--drivers/staging/iio/adc/Kconfig35
-rw-r--r--drivers/staging/iio/adc/Makefile8
-rw-r--r--drivers/staging/iio/adc/ad7476.h77
-rw-r--r--drivers/staging/iio/adc/ad7476_core.c293
-rw-r--r--drivers/staging/iio/adc/ad7476_ring.c207
-rw-r--r--drivers/staging/iio/adc/ad799x.h159
-rw-r--r--drivers/staging/iio/adc/ad799x_core.c923
-rw-r--r--drivers/staging/iio/adc/ad799x_ring.c240
-rw-r--r--drivers/staging/iio/adc/adc.h19
-rw-r--r--drivers/staging/iio/adc/max1363_core.c208
-rw-r--r--drivers/staging/iio/adc/max1363_ring.c22
-rw-r--r--drivers/staging/iio/chrdev.h2
-rw-r--r--drivers/staging/iio/gyro/adis16260_core.c36
-rw-r--r--drivers/staging/iio/gyro/adis16260_ring.c68
-rw-r--r--drivers/staging/iio/gyro/adis16260_trigger.c2
-rw-r--r--drivers/staging/iio/gyro/gyro.h46
-rw-r--r--drivers/staging/iio/iio.h106
-rw-r--r--drivers/staging/iio/imu/adis16300_core.c50
-rw-r--r--drivers/staging/iio/imu/adis16300_ring.c95
-rw-r--r--drivers/staging/iio/imu/adis16300_trigger.c2
-rw-r--r--drivers/staging/iio/imu/adis16350_core.c59
-rw-r--r--drivers/staging/iio/imu/adis16350_ring.c113
-rw-r--r--drivers/staging/iio/imu/adis16350_trigger.c2
-rw-r--r--drivers/staging/iio/imu/adis16400_core.c69
-rw-r--r--drivers/staging/iio/imu/adis16400_ring.c122
-rw-r--r--drivers/staging/iio/imu/adis16400_trigger.c2
-rw-r--r--drivers/staging/iio/industrialio-core.c90
-rw-r--r--drivers/staging/iio/industrialio-ring.c61
-rw-r--r--drivers/staging/iio/light/Kconfig12
-rw-r--r--drivers/staging/iio/light/Makefile1
-rw-r--r--drivers/staging/iio/light/isl29018.c563
-rw-r--r--drivers/staging/iio/light/light.h7
-rw-r--r--drivers/staging/iio/light/tsl2563.c35
-rw-r--r--drivers/staging/iio/magnetometer/Kconfig10
-rw-r--r--drivers/staging/iio/magnetometer/Makefile1
-rw-r--r--drivers/staging/iio/magnetometer/ak8975.c558
-rw-r--r--drivers/staging/iio/magnetometer/hmc5843.c61
-rw-r--r--drivers/staging/iio/magnetometer/magnet.h12
-rw-r--r--drivers/staging/iio/ring_generic.h241
-rw-r--r--drivers/staging/iio/ring_sw.c79
-rw-r--r--drivers/staging/iio/ring_sw.h12
-rw-r--r--drivers/staging/iio/sysfs.h162
-rw-r--r--drivers/staging/iio/trigger.h6
-rw-r--r--drivers/staging/iio/trigger/iio-trig-gpio.c2
-rw-r--r--drivers/staging/iio/trigger/iio-trig-periodic-rtc.c12
68 files changed, 5664 insertions, 1765 deletions
diff --git a/drivers/staging/iio/Documentation/generic_buffer.c b/drivers/staging/iio/Documentation/generic_buffer.c
new file mode 100644
index 0000000..df23aeb
--- /dev/null
+++ b/drivers/staging/iio/Documentation/generic_buffer.c
@@ -0,0 +1,318 @@
+/* Industrialio buffer test code.
+ *
+ * Copyright (c) 2008 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is primarily intended as an example application.
+ * Reads the current buffer setup from sysfs and starts a short capture
+ * from the specified device, pretty printing the result after appropriate
+ * conversion.
+ *
+ * Command line parameters
+ * generic_buffer -n <device_name> -t <trigger_name>
+ * If trigger name is not specified the program assumes you want a dataready
+ * trigger associated with the device and goes looking for it.
+ *
+ */
+
+#include <unistd.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+#include <linux/types.h>
+#include "iio_utils.h"
+
+const int buf_len = 128;
+const int num_loops = 2;
+
+/**
+ * size_from_channelarray() - calculate the storage size of a scan
+ * @channels: the channel info array
+ * @num_channels: size of the channel info array
+ *
+ * Has the side effect of filling the channels[i].location values used
+ * in processing the buffer output.
+ **/
+int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
+{
+ int bytes = 0;
+ int i = 0;
+ while (i < num_channels) {
+ if (bytes % channels[i].bytes == 0)
+ channels[i].location = bytes;
+ else
+ channels[i].location = bytes - bytes%channels[i].bytes
+ + channels[i].bytes;
+ bytes = channels[i].location + channels[i].bytes;
+ i++;
+ }
+ return bytes;
+}
+
+/**
+ * process_scan() - print out the values in SI units
+ * @data: pointer to the start of the scan
+ * @infoarray: information about the channels. Note
+ * size_from_channelarray must have been called first to fill the
+ * location offsets.
+ * @num_channels: the number of active channels
+ **/
+void process_scan(char *data,
+ struct iio_channel_info *infoarray,
+ int num_channels)
+{
+ int k;
+ for (k = 0; k < num_channels; k++)
+ 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);
+ }
+ break;
+ case 8:
+ if (infoarray[k].is_signed) {
+ int64_t val = *(int64_t *)
+ (data +
+ infoarray[k].location);
+ if ((val >> infoarray[k].bits_used) & 1)
+ val = (val & infoarray[k].mask) |
+ ~infoarray[k].mask;
+ /* special case for timestamp */
+ if (infoarray[k].scale == 1.0f &&
+ infoarray[k].offset == 0.0f)
+ printf(" %lld", val);
+ else
+ printf("%05f ", ((float)val +
+ infoarray[k].offset)*
+ infoarray[k].scale);
+ }
+ break;
+ default:
+ break;
+ }
+ printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+ int ret, c, i, j, toread;
+
+ FILE *fp_ev;
+ int fp;
+
+ int num_channels;
+ char *trigger_name = NULL, *device_name = NULL;
+ char *dev_dir_name, *buf_dir_name;
+
+ int datardytrigger = 1;
+ char *data;
+ size_t read_size;
+ struct iio_event_data dat;
+ int dev_num, trig_num;
+ char *buffer_access, *buffer_event;
+ int scan_size;
+
+ struct iio_channel_info *infoarray;
+
+ while ((c = getopt(argc, argv, "t:n:")) != -1) {
+ switch (c) {
+ case 'n':
+ device_name = optarg;
+ break;
+ case 't':
+ trigger_name = optarg;
+ datardytrigger = 0;
+ break;
+ case '?':
+ return -1;
+ }
+ }
+
+ /* Find the device requested */
+ dev_num = find_type_by_name(device_name, "device");
+ if (dev_num < 0) {
+ printf("Failed to find the %s\n", device_name);
+ ret = -ENODEV;
+ goto error_ret;
+ }
+ printf("iio device number being used is %d\n", dev_num);
+
+ asprintf(&dev_dir_name, "%sdevice%d", iio_dir, dev_num);
+ if (trigger_name == NULL) {
+ /*
+ * Build the trigger name. If it is device associated it's
+ * name is <device_name>_dev[n] where n matches the device
+ * number found above
+ */
+ ret = asprintf(&trigger_name,
+ "%s-dev%d", device_name, dev_num);
+ if (ret < 0) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+ }
+
+ /* Verify the trigger exists */
+ trig_num = find_type_by_name(trigger_name, "trigger");
+ if (trig_num < 0) {
+ printf("Failed to find the trigger %s\n", trigger_name);
+ ret = -ENODEV;
+ goto error_free_triggername;
+ }
+ printf("iio trigger number being used is %d\n", trig_num);
+
+ /*
+ * Parse the files in scan_elements to identify what channels are
+ * present
+ */
+ ret = build_channel_array(dev_dir_name, &infoarray, &num_channels);
+ if (ret) {
+ printf("Problem reading scan element information \n");
+ goto error_free_triggername;
+ }
+
+ /*
+ * Construct the directory name for the associated buffer.
+ * As we know that the lis3l02dq has only one buffer this may
+ * be built rather than found.
+ */
+ ret = asprintf(&buf_dir_name, "%sdevice%d:buffer0", iio_dir, dev_num);
+ if (ret < 0) {
+ ret = -ENOMEM;
+ goto error_free_triggername;
+ }
+ printf("%s %s\n", dev_dir_name, trigger_name);
+ /* Set the device trigger to be the data rdy trigger found above */
+ ret = write_sysfs_string_and_verify("trigger/current_trigger",
+ dev_dir_name,
+ trigger_name);
+ if (ret < 0) {
+ printf("Failed to write current_trigger file\n");
+ goto error_free_buf_dir_name;
+ }
+
+ /* Setup ring buffer parameters */
+ ret = write_sysfs_int("length", buf_dir_name, buf_len);
+ if (ret < 0)
+ goto error_free_buf_dir_name;
+
+ /* Enable the buffer */
+ ret = write_sysfs_int("enable", buf_dir_name, 1);
+ if (ret < 0)
+ goto error_free_buf_dir_name;
+ scan_size = size_from_channelarray(infoarray, num_channels);
+ data = malloc(scan_size*buf_len);
+ if (!data) {
+ ret = -ENOMEM;
+ goto error_free_buf_dir_name;
+ }
+
+ ret = asprintf(&buffer_access,
+ "/dev/device%d:buffer0:access0",
+ dev_num);
+ if (ret < 0) {
+ ret = -ENOMEM;
+ goto error_free_data;
+ }
+
+ ret = asprintf(&buffer_event, "/dev/device%d:buffer0:event0", dev_num);
+ if (ret < 0) {
+ ret = -ENOMEM;
+ goto error_free_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;
+ }
+
+ /* Wait for events 10 times */
+ for (j = 0; j < num_loops; j++) {
+ read_size = fread(&dat, 1, sizeof(struct iio_event_data),
+ fp_ev);
+ switch (dat.id) {
+ case IIO_EVENT_CODE_RING_100_FULL:
+ toread = 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;
+ }
+ read_size = read(fp,
+ data,
+ toread*scan_size);
+ if (read_size == -EAGAIN) {
+ printf("nothing available\n");
+ continue;
+ }
+ for (i = 0; i < read_size/scan_size; i++)
+ process_scan(data + scan_size*i,
+ infoarray,
+ num_channels);
+ }
+
+ /* Stop the ring buffer */
+ ret = write_sysfs_int("enable", buf_dir_name, 0);
+ if (ret < 0)
+ goto error_close_buffer_event;
+
+ /* Disconnect from the trigger - just write a dummy name.*/
+ write_sysfs_string("trigger/current_trigger",
+ dev_dir_name, "NULL");
+
+error_close_buffer_event:
+ fclose(fp_ev);
+error_close_buffer_access:
+ close(fp);
+error_free_data:
+ free(data);
+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:
+ if (datardytrigger)
+ free(trigger_name);
+error_ret:
+ return ret;
+}
diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h
index 014f6684..0372424 100644
--- a/drivers/staging/iio/Documentation/iio_utils.h
+++ b/drivers/staging/iio/Documentation/iio_utils.h
@@ -10,12 +10,23 @@
/* Made up value to limit allocation sizes */
#include <string.h>
#include <stdlib.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdint.h>
#define IIO_MAX_NAME_LENGTH 30
-#define IIO_EVENT_CODE_RING_50_FULL 200
-#define IIO_EVENT_CODE_RING_75_FULL 201
-#define IIO_EVENT_CODE_RING_100_FULL 202
+#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/";
@@ -25,6 +36,380 @@ struct iio_event_data {
};
/**
+ * iioutils_break_up_name() - extract generic name from full channel name
+ * @full_name: the full channel name
+ * @generic_name: the output generic channel name
+ **/
+static int iioutils_break_up_name(const char *full_name,
+ char **generic_name)
+{
+ char *current;
+ char *w, *r;
+ char *working;
+ current = strdup(full_name);
+ working = strtok(current, "_\0");
+ w = working;
+ r = working;
+
+ while(*r != '\0') {
+ if (!isdigit(*r)) {
+ *w = *r;
+ w++;
+ }
+ r++;
+ }
+ *w = '\0';
+ *generic_name = strdup(working);
+ free(current);
+
+ return 0;
+}
+
+/**
+ * struct iio_channel_info - information about a given channel
+ * @name: channel name
+ * @generic_name: general name for channel type
+ * @scale: scale factor to be applied for conversion to si units
+ * @offset: offset to be applied for conversion to si units
+ * @index: the channel index in the buffer output
+ * @bytes: number of bytes occupied in buffer output
+ * @mask: a bit mask for the raw output
+ * @is_signed: is the raw value stored signed
+ * @enabled: is this channel enabled
+ **/
+struct iio_channel_info {
+ char *name;
+ char *generic_name;
+ float scale;
+ float offset;
+ unsigned index;
+ unsigned bytes;
+ unsigned bits_used;
+ uint64_t mask;
+ unsigned is_signed;
+ unsigned enabled;
+ unsigned location;
+};
+
+/**
+ * iioutils_get_type() - find and process _type attribute data
+ * @is_signed: output whether channel is signed
+ * @bytes: output how many bytes the channel storage occupies
+ * @mask: output a bit mask for the raw data
+ * @device_dir: the iio device directory
+ * @name: the channel name
+ * @generic_name: the channel type name
+ **/
+inline int iioutils_get_type(unsigned *is_signed,
+ unsigned *bytes,
+ unsigned *bits_used,
+ uint64_t *mask,
+ const char *device_dir,
+ const char *name,
+ const char *generic_name)
+{
+ FILE *sysfsfp;
+ int ret;
+ DIR *dp;
+ char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
+ char signchar;
+ unsigned sizeint, padint;
+ const struct dirent *ent;
+
+ ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
+ if (ret < 0) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+ ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
+ if (ret < 0) {
+ ret = -ENOMEM;
+ goto error_free_scan_el_dir;
+ }
+ ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
+ if (ret < 0) {
+ ret = -ENOMEM;
+ goto error_free_builtname;
+ }
+
+ dp = opendir(scan_el_dir);
+ if (dp == NULL) {
+ ret = -errno;
+ goto error_free_builtname_generic;
+ }
+ while (ent = readdir(dp), ent != NULL)
+ /*
+ * Do we allow devices to override a generic name with
+ * a specific one?
+ */
+ if ((strcmp(builtname, ent->d_name) == 0) ||
+ (strcmp(builtname_generic, ent->d_name) == 0)) {
+ ret = asprintf(&filename,
+ "%s/%s", scan_el_dir, ent->d_name);
+ if (ret < 0) {
+ ret = -ENOMEM;
+ goto error_closedir;
+ }
+ sysfsfp = fopen(filename, "r");
+ if (sysfsfp == NULL) {
+ printf("failed to open %s\n", filename);
+ ret = -errno;
+ goto error_free_filename;
+ }
+ fscanf(sysfsfp,
+ "%c%u/%u", &signchar, bits_used, &padint);
+ *bytes = padint / 8;
+ if (sizeint == 64)
+ *mask = ~0;
+ else
+ *mask = (1 << *bits_used) - 1;
+ if (signchar == 's')
+ *is_signed = 1;
+ else
+ *is_signed = 0;
+ }
+error_free_filename:
+ if (filename)
+ free(filename);
+error_closedir:
+ closedir(dp);
+error_free_builtname_generic:
+ free(builtname_generic);
+error_free_builtname:
+ free(builtname);
+error_free_scan_el_dir:
+ free(scan_el_dir);
+error_ret:
+ return ret;
+}
+
+inline int iioutils_get_param_float(float *output,
+ const char *param_name,
+ const char *device_dir,
+ const char *name,
+ const char *generic_name)
+{
+ FILE *sysfsfp;
+ int ret;
+ DIR *dp;
+ char *builtname, *builtname_generic;
+ char *filename = NULL;
+ const struct dirent *ent;
+
+ ret = asprintf(&builtname, "%s_%s", name, param_name);
+ if (ret < 0) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+ ret = asprintf(&builtname_generic,
+ "%s_%s", generic_name, param_name);
+ if (ret < 0) {
+ ret = -ENOMEM;
+ goto error_free_builtname;
+ }
+ dp = opendir(device_dir);
+ if (dp == NULL) {
+ ret = -errno;
+ goto error_free_builtname_generic;
+ }
+ while (ent = readdir(dp), ent != NULL)
+ if ((strcmp(builtname, ent->d_name) == 0) ||
+ (strcmp(builtname_generic, ent->d_name) == 0)) {
+ ret = asprintf(&filename,
+ "%s/%s", device_dir, ent->d_name);
+ if (ret < 0) {
+ ret = -ENOMEM;
+ goto error_closedir;
+ }
+ sysfsfp = fopen(filename, "r");
+ if (!sysfsfp) {
+ ret = -errno;
+ goto error_free_filename;
+ }
+ fscanf(sysfsfp, "%f", output);
+ break;
+ }
+error_free_filename:
+ if (filename)
+ free(filename);
+error_closedir:
+ closedir(dp);
+error_free_builtname_generic:
+ free(builtname_generic);
+error_free_builtname:
+ free(builtname);
+error_ret:
+ return ret;
+}
+
+
+/**
+ * build_channel_array() - function to figure out what channels are present
+ * @device_dir: the IIO device directory in sysfs
+ * @
+ **/
+inline int build_channel_array(const char *device_dir,
+ struct iio_channel_info **ci_array,
+ int *counter)
+{
+ DIR *dp;
+ FILE *sysfsfp;
+ int count = 0, temp, i;
+ struct iio_channel_info *current;
+ int ret;
+ const struct dirent *ent;
+ char *scan_el_dir;
+ char *filename;
+
+ *counter = 0;
+ ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
+ if (ret < 0) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+ dp = opendir(scan_el_dir);
+ if (dp == NULL) {
+ ret = -errno;
+ goto error_free_name;
+ }
+ while (ent = readdir(dp), ent != NULL)
+ if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
+ "_en") == 0) {
+ ret = asprintf(&filename,
+ "%s/%s", scan_el_dir, ent->d_name);
+ if (ret < 0) {
+ ret = -ENOMEM;
+ goto error_close_dir;
+ }
+ sysfsfp = fopen(filename, "r");
+ if (sysfsfp == NULL) {
+ ret = -errno;
+ free(filename);
+ goto error_close_dir;
+ }
+ fscanf(sysfsfp, "%u", &ret);
+ if (ret == 1)
+ (*counter)++;
+ fclose(sysfsfp);
+ free(filename);
+ }
+ *ci_array = malloc(sizeof(**ci_array)*(*counter));
+ if (*ci_array == NULL) {
+ ret = -ENOMEM;
+ goto error_close_dir;
+ }
+ seekdir(dp, 0);
+ while (ent = readdir(dp), ent != NULL) {
+ if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
+ "_en") == 0) {
+ current = &(*ci_array)[count++];
+ ret = asprintf(&filename,
+ "%s/%s", scan_el_dir, ent->d_name);
+ if (ret < 0) {
+ ret = -ENOMEM;
+ /* decrement count to avoid freeing name */
+ count--;
+ goto error_cleanup_array;
+ }
+ sysfsfp = fopen(filename, "r");
+ if (sysfsfp == NULL) {
+ free(filename);
+ ret = -errno;
+ goto error_cleanup_array;
+ }
+ fscanf(sysfsfp, "%u", &current->enabled);
+ fclose(sysfsfp);
+ free(filename);
+ current->scale = 1.0;
+ current->offset = 0;
+ current->name = strndup(ent->d_name,
+ strlen(ent->d_name) -
+ strlen("_en"));
+ if (current->name == NULL) {
+ free(filename);
+ ret = -ENOMEM;
+ goto error_cleanup_array;
+ }
+ /* Get the generic and specific name elements */
+ ret = iioutils_break_up_name(current->name,
+ &current->generic_name);
+ if (ret) {
+ free(filename);
+ goto error_cleanup_array;
+ }
+ ret = asprintf(&filename,
+ "%s/%s_index",
+ scan_el_dir,
+ current->name);
+ if (ret < 0) {
+ free(filename);
+ ret = -ENOMEM;
+ goto error_cleanup_array;
+ }
+ sysfsfp = fopen(filename, "r");
+ fscanf(sysfsfp, "%u", &current->index);
+ fclose(sysfsfp);
+ free(filename);
+ /* Find the scale */
+ ret = iioutils_get_param_float(&current->scale,
+ "scale",
+ device_dir,
+ current->name,
+ current->generic_name);
+ if (ret < 0)
+ goto error_cleanup_array;
+ ret = iioutils_get_param_float(&current->offset,
+ "offset",
+ device_dir,
+ current->name,
+ current->generic_name);
+ if (ret < 0)
+ goto error_cleanup_array;
+ ret = iioutils_get_type(&current->is_signed,
+ &current->bytes,
+ &current->bits_used,
+ &current->mask,
+ device_dir,
+ current->name,
+ current->generic_name);
+ }
+ }
+ /* reorder so that the array is in index order*/
+ current = malloc(sizeof(**ci_array)**counter);
+ if (current == NULL) {
+ ret = -ENOMEM;
+ goto error_cleanup_array;
+ }
+ closedir(dp);
+ count = 0;
+ temp = 0;
+ while (count < *counter)
+ for (i = 0; i < *counter; i++)
+ if ((*ci_array)[i].index == temp) {
+ memcpy(&current[count++],
+ &(*ci_array)[i],
+ sizeof(*current));
+ temp++;
+ break;
+ }
+ free(*ci_array);
+ *ci_array = current;
+
+ return 0;
+
+error_cleanup_array:
+ for (i = count - 1; i >= 0; i++)
+ free((*ci_array)[i].name);
+ free(*ci_array);
+error_close_dir:
+ closedir(dp);
+error_free_name:
+ free(scan_el_dir);
+error_ret:
+ return ret;
+}
+
+/**
* find_type_by_name() - function to match top level types by name
* @name: top level type instance name
* @type: the type of top level instance being sort
@@ -40,7 +425,6 @@ inline int find_type_by_name(const char *name, const char *type)
DIR *dp;
char thisname[IIO_MAX_NAME_LENGTH];
char *filename;
- struct stat Stat;
dp = opendir(iio_dir);
if (dp == NULL) {
@@ -134,7 +518,7 @@ int write_sysfs_int_and_verify(char *filename, char *basedir, int val)
int _write_sysfs_string(char *filename, char *basedir, char *val, int verify)
{
- int ret;
+ int ret = 0;
FILE *sysfsfp;
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
if (temp == NULL) {
@@ -153,6 +537,7 @@ int _write_sysfs_string(char *filename, char *basedir, char *val, int verify)
if (verify) {
sysfsfp = fopen(temp, "r");
if (sysfsfp == NULL) {
+ printf("could not open file to verify\n");
ret = -errno;
goto error_free;
}
@@ -173,6 +558,7 @@ error_free:
return ret;
}
+
/**
* write_sysfs_string_and_verify() - string write, readback and verify
* @filename: name of file to write to
diff --git a/drivers/staging/iio/Documentation/lis3l02dqbuffersimple.c b/drivers/staging/iio/Documentation/lis3l02dqbuffersimple.c
deleted file mode 100644
index 3a58028..0000000
--- a/drivers/staging/iio/Documentation/lis3l02dqbuffersimple.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/* Industrialio ring buffer with a lis3l02dq accelerometer
- *
- * Copyright (c) 2008 Jonathan Cameron
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is primarily intended as an example application.
- */
-
-#include <dirent.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/dir.h>
-#include <linux/types.h>
-#include "iio_utils.h"
-
-const char *device_name = "lis3l02dq";
-const char *trigger_name_base = "lis3l02dq-dev";
-const int num_vals = 3;
-const int scan_ts = 1;
-const int buf_len = 128;
-const int num_loops = 10;
-
-/*
- * Could get this from ring bps, but only after starting the ring
- * which is a bit late for it to be useful.
- *
- * Todo: replace with much more generic version based on scan_elements
- * directory.
- */
-int size_from_scanmode(int num_vals, int timestamp)
-{
- if (num_vals && timestamp)
- return 16;
- else if (timestamp)
- return 8;
- else
- return num_vals*2;
-}
-
-int main(int argc, char **argv)
-{
- int ret;
- int i, j, k, toread;
- FILE *fp_ev;
- int fp;
-
- char *trigger_name, *dev_dir_name, *buf_dir_name;
- char *data;
- size_t read_size;
- struct iio_event_data dat;
- int dev_num, trig_num;
-
- char *buffer_access, *buffer_event;
- const char *iio_dir = "/sys/bus/iio/devices/";
- int scan_size;
- float gain = 1;
-
-
- /* Find out which iio device is the accelerometer. */
- dev_num = find_type_by_name(device_name, "device");
- if (dev_num < 0) {
- printf("Failed to find the %s\n", device_name);
- ret = -ENODEV;
- goto error_ret;
- }
- printf("iio device number being used is %d\n", dev_num);
- asprintf(&dev_dir_name, "%sdevice%d", iio_dir, dev_num);
-
- /*
- * Build the trigger name.
- * In this case we want the lis3l02dq's data ready trigger
- * for this lis3l02dq. The naming is lis3l02dq_dev[n], where
- * n matches the device number found above.
- */
- ret = asprintf(&trigger_name, "%s%d", trigger_name_base, dev_num);
- if (ret < 0) {
- ret = -ENOMEM;
- goto error_free_dev_dir_name;
- }
-
- /*
- * Find the trigger by name.
- * This is techically unecessary here as we only need to
- * refer to the trigger by name and that name is already
- * known.
- */
- trig_num = find_type_by_name(trigger_name, "trigger");
- if (trig_num < 0) {
- printf("Failed to find the %s\n", trigger_name);
- ret = -ENODEV;
- goto error_free_triggername;
- }
- printf("iio trigger number being used is %d\n", trig_num);
-
- /*
- * Read in the scale value - in a more generic case, first
- * check for accel_scale, then the indivual channel scales
- */
- ret = read_sysfs_float("accel_scale", dev_dir_name, &gain);
- if (ret)
- goto error_free_triggername;;
-
- /*
- * Construct the directory name for the associated buffer.
- * As we know that the lis3l02dq has only one buffer this may
- * be built rather than found.
- */
- ret = asprintf(&buf_dir_name, "%sdevice%d:buffer0", iio_dir, dev_num);
- if (ret < 0) {
- ret = -ENOMEM;
- goto error_free_triggername;
- }
- /* Set the device trigger to be the data rdy trigger found above */
- ret = write_sysfs_string_and_verify("trigger/current_trigger",
- dev_dir_name,
- trigger_name);
- if (ret < 0) {
- printf("Failed to write current_trigger file\n");
- goto error_free_buf_dir_name;
- }
-
- /* Setup ring buffer parameters */
- ret = write_sysfs_int("length", buf_dir_name, buf_len);
- if (ret < 0)
- goto error_free_buf_dir_name;
-
- /* Enable the buffer */
- ret = write_sysfs_int("ring_enable", buf_dir_name, 1);
- if (ret < 0)
- goto error_free_buf_dir_name;
-
- data = malloc(size_from_scanmode(num_vals, scan_ts)*buf_len);
- if (!data) {
- ret = -ENOMEM;
- goto error_free_buf_dir_name;
- }
-
- ret = asprintf(&buffer_access,
- "/dev/device%d:buffer0:access0",
- dev_num);
- if (ret < 0) {
- ret = -ENOMEM;
- goto error_free_data;
- }
-
- ret = asprintf(&buffer_event, "/dev/device%d:buffer0:event0", dev_num);
- if (ret < 0) {
- ret = -ENOMEM;
- goto error_free_data;
- }
- /* Attempt to open non blocking the access dev */
- fp = open(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;
- }
-
- /* Wait for events 10 times */
- for (j = 0; j < num_loops; j++) {
- read_size = fread(&dat, 1, sizeof(struct iio_event_data),
- fp_ev);
- switch (dat.id) {
- case IIO_EVENT_CODE_RING_100_FULL:
- toread = 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;
- }
- read_size = read(fp,
- data,
- toread*size_from_scanmode(num_vals, scan_ts));
- if (read_size == -EAGAIN) {
- printf("nothing available\n");
- continue;
- }
- scan_size = size_from_scanmode(num_vals, scan_ts);
- for (i = 0; i < read_size/scan_size; i++) {
- for (k = 0; k < num_vals; k++) {
- __s16 val = *(__s16 *)(&data[i*scan_size
- + (k)*2]);
- printf("%05f ", (float)val*gain);
- }
- printf(" %lld\n",
- *(__s64 *)(&data[(i + 1)
- *size_from_scanmode(num_vals,
- scan_ts)
- - sizeof(__s64)]));
- }
- }
-
- /* Stop the ring buffer */
- ret = write_sysfs_int("ring_enable", buf_dir_name, 0);
- if (ret < 0)
- goto error_close_buffer_event;
-
- /* Disconnect from the trigger - just write a dummy name.*/
- write_sysfs_string("trigger/current_trigger",
- dev_dir_name, "NULL");
-
-error_close_buffer_event:
- fclose(fp_ev);
-error_close_buffer_access:
- close(fp);
-error_free_data:
- free(data);
-error_free_buffer_access:
- free(buffer_access);
-error_free_buffer_event:
- free(buffer_event);
-error_free_buf_dir_name:
- free(buf_dir_name);
-error_free_triggername:
- free(trigger_name);
-error_free_dev_dir_name:
- free(dev_dir_name);
-error_ret:
- return ret;
-}
diff --git a/drivers/staging/iio/Documentation/overview.txt b/drivers/staging/iio/Documentation/overview.txt
index cc6ecad..d97106c 100644
--- a/drivers/staging/iio/Documentation/overview.txt
+++ b/drivers/staging/iio/Documentation/overview.txt
@@ -1,8 +1,8 @@
Overview of IIO
-The Industrial I/O subsytem is intended to provide support for devices
-that in some sense are analog to digital convertors (ADCs). As many
-actual devices combine some ADCs with digital to analog convertors
+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).
@@ -46,18 +46,17 @@ 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 ring buffers acting in a very similar
fashion to the hardware buffers described above.
Other documentation:
-userspace.txt - overview of ring buffer reading from userspace
+userspace.txt - overview of ring buffer reading from userspace.
-device.txt - elemennts of a typical device driver.
+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 ring 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 d2ca683..3696c36 100644
--- a/drivers/staging/iio/Documentation/ring.txt
+++ b/drivers/staging/iio/Documentation/ring.txt
@@ -47,10 +47,8 @@ request_update
If parameters have changed that require reinitialization or configuration of
the ring buffer this will trigger it.
-get_bpd, set_bpd
- Get/set the number of bytes for a given reading (single element, not sample set)
- The value of bps (bytes per set) is created from a combination of this and the
- enabled scan elements.
+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.
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio b/drivers/staging/iio/Documentation/sysfs-bus-iio
new file mode 100644
index 0000000..fdb017a
--- /dev/null
+++ b/drivers/staging/iio/Documentation/sysfs-bus-iio
@@ -0,0 +1,390 @@
+What: /sys/bus/iio/devices/device[n]
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Hardware chip or device accessed by on communication port.
+ Corresponds to a grouping of sensor channels.
+
+What: /sys/bus/iio/devices/trigger[n]
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ An event driven driver of data capture to an in kernel buffer.
+ May be provided by a device driver that also has an IIO device
+ based on hardware generated events (e.g. data ready) or
+ provided by a separate driver for other hardware (e.g.
+ periodic timer, gpio or high resolution timer).
+ Contains trigger type specific elements. These do not
+ generalize well and hence are not documented in this file.
+
+What: /sys/bus/iio/devices/device[n]:buffer
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Link to /sys/class/iio/device[n]/device[n]:buffer. n indicates
+ the device with which this buffer buffer is associated.
+
+What: /sys/.../device[n]/name
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Description of the physical chip / device. Typically a part
+ number.
+
+What: /sys/.../device[n]/sampling_frequency
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Some devices have internal clocks. This parameter sets the
+ resulting sampling frequency. In many devices this
+ parameter has an effect on input filters etc rather than
+ simply controlling when the input is sampled. As this
+ effects datardy triggers, hardware buffers and the sysfs
+ direct access interfaces, it may be found in any of the
+ relevant directories. If it effects all of the above
+ then it is to be found in the base device directory as here.
+
+What: /sys/.../device[n]/sampling_frequency_available
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ When the internal sampling clock can only take a small
+ discrete set of values, this file lists those availale.
+
+What: /sys/.../device[n]/in[m][_name]_raw
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Raw (unscaled no bias removal etc) voltage measurement from
+ channel m. name is used in special cases where this does
+ not correspond to externally available input (e.g. supply
+ voltage monitoring in which case the file is in_supply_raw).
+ If the device supports events on this channel then m must be
+ specified (even on named channels) so as to allow the source
+ of event codes to be identified.
+
+What: /sys/.../device[n]/in[m][_name]_offset
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ If known for a device, offset to be added to in[m]_raw prior
+ to scaling by in[_name][m]_scale in order to obtain voltage in
+ millivolts. Not present if the offset is always 0 or unknown.
+ If m is not present, then voltage offset applies to all in
+ channels. May be writable if a variable offset is controlled
+ by the device. Note that this is different to calibbias which
+ is for devices that apply offsets to compensate for variation
+ between different instances of the part, typically adjusted by
+ using some hardware supported calibration procedure.
+
+What: /sys/.../device[n]/in[m][_name]_offset_available
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ If a small number of discrete offset values are available, this
+ will be a space separated list. If these are independant (but
+ options the same) for individual offsets then m should not be
+ present.
+
+What: /sys/.../device[n]/in[m][_name]_offset_[min|max]
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ If a more or less continuous range of voltage offsets are
+ supported then these specify the minimum and maximum. If shared
+ by all in channels then m is not present.
+
+What: /sys/.../device[n]/in[m][_name]_calibbias
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Hardware applied calibration offset. (assumed to fix production
+ inaccuracies)
+
+What /sys/.../device[n]/in[m][_name]_calibscale
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Hardware applied calibration scale factor. (assumed to fix
+ production inaccuracies)
+
+What: /sys/.../device[n]/in[m][_name]_scale
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ If known for a device, scale to be applied to volt[m]_raw post
+ addition of in[_name][m]_offset in order to obtain the measured
+ voltage in millivolts. If shared across all in channels then
+ m is not present.
+
+What: /sys/.../device[n]/in[m]-in[o]_raw
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Raw (unscaled) differential voltage measurement equivalent to
+ channel m - channel o where these channel numbers apply to the
+ physically equivalent inputs when non differential readings are
+ separately available. In differential only parts, then all that
+ is required is a consistent labelling.
+
+What: /sys/.../device[n]/accel[_x|_y|_z][m]_raw
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Acceleration in direction x, y or z (may be arbitrarily assigned
+ but should match other such assignments on device)
+ channel m (not present if only one accelerometer channel at
+ this orientation). Has all of the equivalent parameters as per
+ in[m]. Units after application of scale and offset are m/s^2.
+
+What: /sys/.../device[n]/gyro[_x|_y|_z][m]_raw
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Angular velocity about axis x, y or z (may be arbitrarily
+ assigned) channel m (not present if only one gyroscope at
+ this orientation).
+ Data converted by application of offset then scale to
+ radians per second. Has all the equivalent parameters as
+ per in[m].
+
+What: /sys/.../device[n]/incli[_x|_y|_z][m]_raw
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Inclination raw reading about axis x, y or z (may be arbitarily
+ assigned) channel m (not present if only one inclinometer at
+ this orientation). Data converted by application of offset
+ and scale to Degrees.
+
+What: /sys/.../device[n]/magn[_x|_y|_z][m]_raw
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Magnetic field along axis x, y or z (may be arbitrarily
+ assigned) channel m (not present if only one magnetometer
+ at this orientation). Data converted by application of
+ offset then scale to Gauss. Has all the equivalent modifiers
+ as per in[m].
+
+What: /sys/.../device[n]/device[n]:event[m]
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Configuration of which hardware generated events are passed up to
+ userspace. Some of these are a bit complex to generalize so this
+ section is a work in progress.
+
+What: /sys/.../device[n]:event[m]/dev
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ major:minor character device numbers for the event line.
+
+Taking accel_x0 as an example
+
+What: /sys/.../device[n]:event[m]/accel_x0_thresh[_rising|_falling]_en
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Event generated when accel_x0 passes a threshold in the specfied
+ (_rising|_falling) direction. If the direction is not specified,
+ then either the device will report an event which ever direction
+ a single threshold value is called in (e.g.
+ accel_x0_<raw|input>_thresh_value) or
+ accel_x0_<raw|input>_thresh_rising_value and
+ accel_x0_<raw|input>_thresh_falling_value may take different
+ values, but the device can only enable both thresholds or
+ neither.
+ Note the driver will assume the last p events requested are
+ to be enabled where p is however many it supports (which may
+ vary depending on the exact set requested. So if you want to be
+ sure you have set what you think you have, check the contents of
+ these attributes after everything is configured. Drivers may
+ have to buffer any parameters so that they are consistent when
+ a given event type is enabled a future point (and not those for
+ whatever event was previously enabled).
+
+What: /sys/.../accel_x0_<raw|input>_thresh[_rising|_falling]_value
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Specifies the value of threshold that the device is comparing
+ against for the events enabled by
+ accel_x0_<raw|input>_thresh[_rising|falling]_en.
+ If seperate exist for the two directions, but direction is
+ not specified for this attribute, then a single threshold value
+ applies to both directions.
+ The raw or input element of the name indicates whether the
+ value is in raw device units or in processed units (as _raw
+ and _input do on sysfs direct channel read attributes).
+
+What: /sys/.../accel_x0_thresh[_rising|_falling]_meanperiod
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Period of time (in seconds) over which the raw channel value
+ is averaged before being compared with the threshold set in
+ accel_x0_thresh[_rising|_falling]_meanperiod. If direction is
+ not specified then this mean period applies to both directions.
+
+What: /sys/.../accel_x0_thresh[_rising|_falling]_period
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Period of time (in seconds) for which the threshold must be
+ passed before an event is generated. If direction is not
+ specified then this period applies to both directions.
+
+What: /sys/.../device[n]:event[m]/accel_x0_mag[_rising|_falling]_en
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Similar to accel_x0_thresh[_rising|_falling]_en, but here the
+ magnitude of the channel is compared to the threshold, not its
+ signed value.
+
+What: /sys/.../accel_x0_<raw|input>_mag[_rising|_falling]_value
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ The value to which the magnitude of the channel is compared.
+
+What: /sys/.../accel_x0_mag[_rising|_falling]_meanperiod
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Period of time (in seconds) over which the value of the channel
+ is averaged before being compared to the threshold
+
+What: /sys/.../accel_x0_mag[_rising|_falling]_period
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Period of time (in seconds) for which the condition must be true
+ before an event occurs.
+
+What: /sys/.../device[n]:event[m]/accel_x0_roc[_rising|_falling]_en
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Similar to accel_x0_thresh[_rising|_falling]_en, but here the
+ first differential is compared with the threshold.
+
+What: /sys/.../accel_x0_<raw|input>_roc[_rising|_falling]_value
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ The value to which the first differential of the channel is
+ compared.
+
+What: /sys/.../accel_x0_roc[_rising|_falling]_meanperiod
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Period of time (in seconds) over which the value of the channel
+ is averaged before being compared to the threshold
+
+What: /sys/.../accel_x0_roc[_rising|_falling]_period
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Period of time (in seconds) for which the condition must be true
+ before an event occurs.
+
+What: /sys/.../device[n]/device[n]:buffer:event/dev
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Buffer for device n event character device major:minor numbers.
+
+What: /sys/.../device[n]/device[n]:buffer:access/dev
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Buffer for device n access character device o major:minor numbers.
+
+What: /sys/.../device[n]:buffer/trigger
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ The name of the trigger source being used, as per string given
+ in /sys/class/iio/trigger[n]/name.
+
+What: /sys/.../device[n]:buffer/length
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Number of scans contained by the buffer.
+
+What: /sys/.../device[n]:buffer/bytes_per_datum
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Bytes per scan. Due to alignment fun, the scan may be larger
+ than implied directly by the scan_element parameters.
+
+What: /sys/.../device[n]:buffer/enable
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Actually start the buffer capture up. Will start trigger
+ if first device and appropriate.
+
+What: /sys/.../device[n]:buffer/alignment
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Minimum data alignment. Scan elements larger than this are
+ aligned to the nearest power of 2 times this. (may not be
+ true in weird hardware buffers that pack data well)
+
+What: /sys/.../device[n]/buffer/scan_elements
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Directory containing interfaces for elements that will be
+ captured for a single triggered sample set in the buffer.
+
+What: /sys/.../device[n]/buffer/scan_elements/accel_x0_en
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Scan element control for triggered data capture.
+
+What: /sys/.../device[n]/buffer/scan_elements/accel[_x0]_type
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Description of the scan element data storage within the buffer
+ and hence the form in which it is read from userspace.
+ Form is [s|u]bits/storagebits. s or u specifies if signed
+ (2's complement) or unsigned. bits is the number of bits of
+ data and storagebits is the space (after padding) that it
+ occupies in the buffer. Note that some devices will have
+ additional information in the unused bits so to get a clean
+ value, the bits value must be used to mask the buffer output
+ value appropriately. The storagebits value also specifies the
+ data alignment. So s48/64 will be a signed 48 bit integer
+ stored in a 64 bit location aligned to a a64 bit boundary.
+ For other storage combinations this attribute will be extended
+ appropriately.
+
+What: /sys/.../device[n]/buffer/scan_elements/accel[_x0]_index
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ A single positive integer specifying the position of this
+ scan element in the buffer. Note these are not dependant on
+ what is enabled and may not be contiguous. Thus for userspace
+ to establish the full layout these must be used in conjunction
+ with all _en attributes to establish which channels are present,
+ and the relevant _type attributes to establish the data storage
+ format.
+
+What: /sys/.../device[n]/buffer/scan_elements/accel[_x0]_shift
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ A bit shift (to right) that must be applied prior to
+ extracting the bits specified by accel[_x0]_precision.
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-light b/drivers/staging/iio/Documentation/sysfs-bus-iio-light
new file mode 100644
index 0000000..5d84856
--- /dev/null
+++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-light
@@ -0,0 +1,64 @@
+
+What: /sys/bus/iio/devices/device[n]/range
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Hardware dependent ADC Full Scale Range used for some ambient
+ light sensors in calculating lux.
+
+What: /sys/bus/iio/devices/device[n]/range_available
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Hardware dependent supported vales for ADC Full Scale Range.
+
+What: /sys/bus/iio/devices/device[n]/adc_resolution
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Hardware dependent ADC resolution of the ambient light sensor
+ used in calculating the lux.
+
+What: /sys/bus/iio/devices/device[n]/adc_resolution_available
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Hardware dependent list of possible values supported for the
+ adc_resolution of the given sensor.
+
+What: /sys/bus/iio/devices/device[n]/illuminance0[_input|_raw]
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ This should return the calculated lux from the light sensor. If
+ it comes back in SI units, it should also include _input else it
+ should include _raw to signify it is not in SI units.
+
+What: /sys/.../device[n]/proximity_on_chip_ambient_infrared_supression
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ Hardware dependent mode for an ALS device to calculate the value
+ in proximity mode. When this is enabled, then the device should
+ use a infrared sensor reading to remove infrared noise from the
+ proximity reading. If this is not enabled, the driver can still
+ do this calculation manually by reading the infrared sensor
+ value and doing the negation in sw.
+
+What: /sys/bus/iio/devices/device[n]/proximity[_input|_raw]
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ This property is supported by proximity sensors and should be
+ used to return the value of a reading by the sensor. If this
+ value is returned in SI units, it should also include _input
+ but if it is not, then it should include _raw.
+
+What: /sys/bus/iio/devices/device[n]/intensity_infrared[_input|_raw]
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ This property is supported by sensors that have an infrared
+ 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.
diff --git a/drivers/staging/iio/Documentation/sysfs-class-iio b/drivers/staging/iio/Documentation/sysfs-class-iio
deleted file mode 100644
index 714b4c5..0000000
--- a/drivers/staging/iio/Documentation/sysfs-class-iio
+++ /dev/null
@@ -1,294 +0,0 @@
-
-What: /sys/bus/iio/devices/device[n]
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Hardware chip or device accessed by on communication port.
- Corresponds to a grouping of sensor channels.
-
-What: /sys/bus/iio/devices/trigger[n]
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- An event driven driver of data capture to an in kernel buffer.
- May be provided by a device driver that also has an IIO device
- based on hardware generated events (e.g. data ready) or
- provided by a separate driver for other hardware (e.g.
- periodic timer, gpio or high resolution timer).
- Contains trigger type specific elements. These do not
- generalize well and hence are not documented in this file.
-
-What: /sys/bus/iio/devices/device[n]:buffer
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Link to /sys/class/iio/device[n]/device[n]:buffer. n indicates the
- device with which this buffer buffer is associated.
-
-What: /sys/.../device[n]/name
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Description of the physical chip / device. Typically a part
- number.
-
-What: /sys/.../device[n]/sampling_frequency
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Some devices have internal clocks. This parameter sets the
- resulting sampling frequency. In many devices this
- parameter has an effect on input filters etc rather than
- simply controlling when the input is sampled. As this
- effects datardy triggers, hardware buffers and the sysfs
- direct access interfaces, it may be found in any of the
- relevant directories. If it effects all of the above
- then it is to be found in the base device directory as here.
-
-What: /sys/.../device[n]/sampling_frequency_available
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- When the internal sampling clock can only take a small
- discrete set of values, this file lists those availale.
-
-What: /sys/.../device[n]/in[_name][m]_raw
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Raw (unscaled no bias removal etc) voltage measurement from
- channel m. name is used in special cases where this does
- not correspond to externally available input (e.g. supply
- voltage monitoring in which case the file is in_supply_raw).
-
-What: /sys/.../device[n]/in[_name][m]_offset
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- If known for a device, offset to be added to in[m]_raw prior
- to scaling by in[_name][m]_scale in order to obtain voltage in
- millivolts. Not present if the offset is always 0 or unknown.
- If m is not present, then voltage offset applies to all in
- channels. May be writable if a variable offset is controlled
- by the device. Note that this is different to calibbias which
- is for devices that apply offsets to compensate for variation
- between different instances of the part, typically adjusted by
- using some hardware supported calibration procedure.
-
-What: /sys/.../device[n]/in[_name][m]_offset_available
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- If a small number of discrete offset values are available, this
- will be a space separated list. If these are independant (but
- options the same) for individual offsets then m should not be
- present.
-
-What: /sys/.../device[n]/in[_name][m]_offset_[min|max]
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- If a more or less continuous range of voltage offsets are supported
- then these specify the minimum and maximum. If shared by all
- in channels then m is not present.
-
-What: /sys/.../device[n]/in[_name][m]_calibbias
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Hardware applied calibration offset. (assumed to fix production
- inaccuracies)
-
-What /sys/.../device[n]/in[_name][m]_calibscale
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Hardware applied calibration scale factor. (assumed to fix production
- inaccuracies)
-
-What: /sys/.../device[n]/in[_name][m]_scale
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- If known for a device, scale to be applied to volt[m]_raw post
- addition of in[_name][m]_offset in order to obtain the measured
- voltage in millivolts. If shared across all in channels then m is not present.
-
-What: /sys/.../device[n]/in[m]-in[o]_raw
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Raw (unscaled) differential voltage measurement equivalent to
- channel m - channel o where these channel numbers apply to the physically
- equivalent inputs when non differential readings are separately available.
- In differential only parts, then all that is required is a consistent
- labelling.
-
-What: /sys/.../device[n]/accel[_x|_y|_z][m]_raw
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Acceleration in direction x, y or z (may be arbitrarily assigned
- but should match other such assignments on device)
- channel m (not present if only one accelerometer channel at
- this orientation). Has all of the equivalent parameters as per in[m].
- Units after application of scale and offset are m/s^2.
-
-What: /sys/.../device[n]/gyro[_x|_y|_z][m]_raw
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Angular velocity about axis x, y or z (may be arbitrarily assigned)
- channel m (not present if only one gyroscope at this orientation).
- Data converted by application of offset then scale to
- radians per second. Has all the equivalent parameters as per in[m].
-
-What: /sys/.../device[n]/incli[_x|_y|_z][m]_raw
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Inclination raw reading about axis x, y or z (may be arbitarily
- assigned) channel m (not present if only one inclinometer at
- this orientation). Data converted by application of offset
- and scale to Degrees.
-
-What: /sys/.../device[n]/magn[_x|_y|_z][m]_raw
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Magnetic field along axis x, y or z (may be arbitrarily assigned)
- channel m (not present if only one magnetometer at this orientation).
- Data converted by application of offset then scale to Gauss
- Has all the equivalent modifiers as per in[m].
-
-What: /sys/.../device[n]/device[n]:event[m]
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Configuration of which hardware generated events are passed up to
- userspace. Some of these are a bit complex to generalize so this
- section is a work in progress.
-
-What: /sys/.../device[n]:event[m]/dev
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- major:minor character device numbers for the event line.
-
-Taking accel_x0 as an example
-
-What: /sys/.../device[n]:event[m]/accel_x0_thresh[_high|_low]_en
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Event generated when accel_x0 passes a threshold in correction direction
- (or stays beyond one). If direction isn't specified, either triggers it.
- Note driver will assume last p events requested are enabled where p is
- however many it supports. So if you want to be sure you have
- set what you think you have, check the contents of these. Drivers
- may have to buffer any parameters so that they are consistent when a
- given event type is enabled a future point (and not those for whatever
- alarm was previously enabled).
-
-What: /sys/.../device[n]:event[m]/accel_x0_roc[_high|_low]_en
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Same as above but based on the first differential of the value.
-
-
-What: /sys/.../device[n]:event[m]/accel_x0[_thresh|_roc][_high|_low]_period
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- A period of time (microsecs) for which the condition must be broken
- before an interrupt is triggered. Applies to all alarms if type is not
- specified.
-
-What: /sys/.../device[n]:event[m]/accel_x0[_thresh|_roc][_high|_low]_value
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- The actual value of the threshold in raw device units obtained by
- reverse application of scale and offfset to the acceleration in m/s^2.
-
-What: /sys/.../device[n]/scan_elements
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Directory containing interfaces for elements that will be captured
- for a single triggered sample set in the buffer.
-
-What: /sys/.../device[n]/scan_elements/[m]_accel_x0_en
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Scan element control for triggered data capture. m implies the
- ordering within the buffer. Next the type is specified with
- modifier and channel number as per the sysfs single channel
- access above.
-
-What: /sys/.../device[n]/scan_elements/accel[_x0]_precision
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Scan element precision within the buffer. Note that the
- data alignment must restrictions must be read from within
- buffer to work out full data alignment for data read
- via buffer_access chrdev. _x0 dropped if shared across all
- acceleration channels.
-
-What: /sys/.../device[n]/scan_elements/accel[_x0]_shift
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- A bit shift (to right) that must be applied prior to
- extracting the bits specified by accel[_x0]_precision.
-
-What: /sys/.../device[n]/device[n]:buffer:event/dev
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Buffer for device n event character device major:minor numbers.
-
-What: /sys/.../device[n]/device[n]:buffer:access/dev
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Buffer for device n access character device o major:minor numbers.
-
-What: /sys/.../device[n]:buffer/trigger
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- The name of the trigger source being used, as per string given
- in /sys/class/iio/trigger[n]/name.
-
-What: /sys/.../device[n]:buffer/length
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Number of scans contained by the buffer.
-
-What: /sys/.../device[n]:buffer/bps
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Bytes per scan. Due to alignment fun, the scan may be larger
- than implied directly by the scan_element parameters.
-
-What: /sys/.../device[n]:buffer/enable
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Actually start the buffer capture up. Will start trigger
- if first device and appropriate.
-
-What: /sys/.../device[n]:buffer/alignment
-KernelVersion: 2.6.35
-Contact: linux-iio@vger.kernel.org
-Description:
- Minimum data alignment. Scan elements larger than this are aligned
- to the nearest power of 2 times this. (may not be true in weird
- hardware buffers that pack data well)
-
diff --git a/drivers/staging/iio/Documentation/userspace.txt b/drivers/staging/iio/Documentation/userspace.txt
index 4838818..ff06e5d 100644
--- a/drivers/staging/iio/Documentation/userspace.txt
+++ b/drivers/staging/iio/Documentation/userspace.txt
@@ -1,60 +1,12 @@
Userspace access to IIO
-Example, ST Microelectronics LIS3L02DQ accelerometer.
-
-Typical sysfs entries (pruned for clarity)
-
-/sys/class/iio
- device0 - iio_dev related elements
- name - driver specific identifier (here lis3l02dq)
- accel_x - polled (or from ring) raw readout of acceleration
- accel_x_gain - hardware gain (calibration)
- accel_x_offset - hardware offset (calibration)
- available_sampling_frequency
-
- available_sampling_frequency - what options are there
- sampling_frequency - control of internal sampling frequency
- scan_elements - controls which channels will be stored in the ring buffer
- scan_en_accel_x
- scan_en_accel_y
- scan_en_timestamp
- device - link to underlying hardware device
- uevent - udev related element
-
- thresh - unified threshold used for detection on all axis
- event_line0_sources - which events are enabled
- accel_x_high - enable x axis high threshold event
- accel_x_low - enable x axis low threshold event
-
- event_line0 - event interface
- dev - major:minor for the chrdev (note major allocation dynamic)
- trigger - consumer attachement
- current_trigger - name based association with a trigger
- ring_buffer0 - ring buffer interface
- bps - byptes per sample (read only), dependant on scan element selection
- length - (rw) specificy length fo software ring buffer (typically ro in hw case)
- ring_enable - turn the ring on. If its the first to be enabled attached to this
- trigger will also enable the trigger.
- ring_access0
- dev - major:minor for ring buffer access chrdev
- ring_event_line0
- dev - major:minor for ring buffer event chrdev
-
- trigger0 - data ready trigger elements
- name - unqiue name of trigger
+The sysfs attributes are documented in sysfs-bus-iio.
Udev will create the following entries under /dev by default:
-ring_access0 - ring access chrdev
-ring_event0 - ring event chrdev
-event_line0 - general event chrdev.
-
-For the example code we assume the following rules have been used to ensure
-unique and consistent naming of these for the lis3l02dq in question:
-
-KERNEL="ring_event_line*", ID="spi1.0", DRIVER="lis3l02dq", NAME="iio/lis3l02dq_ring_event"
-KERNEL="event_line*", ID="spi1.0", DRIVER="lis3l02dq", NAME="iio/lis3l02dq_event"
-KERNEL="ring_access*", ID="spi1.0", DRIVER="lis3l02dq", NAME="iio/lis3l02dq_ring_access"
+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/accel/accel.h b/drivers/staging/iio/accel/accel.h
index 1b6e37f..f5f61b2 100644
--- a/drivers/staging/iio/accel/accel.h
+++ b/drivers/staging/iio/accel/accel.h
@@ -14,158 +14,54 @@
#define IIO_DEV_ATTR_ACCEL_Z_OFFSET(_mode, _show, _store, _addr) \
IIO_DEVICE_ATTR(accel_z_offset, _mode, _show, _store, _addr)
-#define IIO_DEV_ATTR_ACCEL_X_GAIN(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_x_gain, _mode, _show, _store, _addr)
+#define IIO_CONST_ATTR_ACCEL_SCALE(_string) \
+ IIO_CONST_ATTR(accel_scale, _string)
-#define IIO_DEV_ATTR_ACCEL_Y_GAIN(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_y_gain, _mode, _show, _store, _addr)
+#define IIO_DEV_ATTR_ACCEL_SCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(accel_scale, _mode, _show, _store, _addr)
-#define IIO_DEV_ATTR_ACCEL_Z_GAIN(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(accel_z_gain, _mode, _show, _store, _addr)
+#define IIO_DEV_ATTR_ACCEL_X_SCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(accel_x_scale, _mode, _show, _store, _addr)
-#define IIO_DEV_ATTR_ACCEL(_show, _addr) \
- IIO_DEVICE_ATTR(accel_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_X(_show, _addr) \
- IIO_DEVICE_ATTR(accel_x_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_Y(_show, _addr) \
- IIO_DEVICE_ATTR(accel_y_raw, S_IRUGO, _show, NULL, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_Z(_show, _addr) \
- IIO_DEVICE_ATTR(accel_z_raw, S_IRUGO, _show, NULL, _addr)
-
-/* Thresholds are somewhat chip dependent - may need quite a few defs here */
-/* For unified thresholds (shared across all directions */
-
-/**
- * IIO_DEV_ATTR_ACCEL_THRESH: unified threshold
- * @_mode: read/write
- * @_show: read detector threshold value
- * @_store: write detector threshold value
- * @_addr: driver specific data, typically a register address
- *
- * This one is for cases where as single threshold covers all directions
- **/
-#define IIO_DEV_ATTR_ACCEL_THRESH(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(thresh, _mode, _show, _store, _addr)
-
-/**
- * IIO_DEV_ATTR_ACCEL_THRESH_X: independant direction threshold, x axis
- * @_mode: readable / writable
- * @_show: read x axis detector threshold value
- * @_store: write x axis detector threshold value
- * @_addr: device driver dependant, typically a register address
- **/
-#define IIO_DEV_ATTR_ACCEL_THRESH_X(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(thresh_accel_x, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_THRESH_Y(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(thresh_accel_y, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_ACCEL_THRESH_Z(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(thresh_accel_z, _mode, _show, _store, _addr)
-
-/**
- * IIO_EVENT_ATTR_ACCEL_X_HIGH: threshold event, x acceleration
- * @_show: read x acceleration high threshold
- * @_store: write x acceleration high threshold
- * @_mask: device dependant, typically a bit mask
- * @_handler: the iio_handler associated with this attribute
- **/
-#define IIO_EVENT_ATTR_ACCEL_X_HIGH(_show, _store, _mask, _handler) \
- IIO_EVENT_ATTR(accel_x_high, _show, _store, _mask, _handler)
-
-/**
- * IIO_EVENT_ATTR_ACCEL_X_HIGH_SH: threshold event, x accel high, shared handler
- * @_evlist: event list used to share the handler
- * @_show: attribute read
- * @_store: attribute write
- * @_mask: driver specific data, typically a bit mask
- **/
-#define IIO_EVENT_ATTR_ACCEL_X_HIGH_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(accel_x_high, _evlist, _show, _store, _mask)
-
-/**
- * IIO_EVENT_CODE_ACCEL_X_HIGH - event code for x axis high accel threshold
- **/
-#define IIO_EVENT_CODE_ACCEL_X_HIGH IIO_EVENT_CODE_ACCEL_BASE
-
-#define IIO_EVENT_ATTR_ACCEL_Y_HIGH(_show, _store, _mask, _handler) \
- IIO_EVENT_ATTR(accel_y_high, _show, _store, _mask, _handler)
-
-#define IIO_EVENT_ATTR_ACCEL_Y_HIGH_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(accel_y_high, _evlist, _show, _store, _mask)
-
-#define IIO_EVENT_CODE_ACCEL_Y_HIGH (IIO_EVENT_CODE_ACCEL_BASE + 1)
+#define IIO_DEV_ATTR_ACCEL_Y_SCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(accel_y_scale, _mode, _show, _store, _addr)
-#define IIO_EVENT_ATTR_ACCEL_Z_HIGH(_show, _store, _mask, _handler) \
- IIO_EVENT_ATTR(accel_z_high, _show, _store, _mask, _handler)
+#define IIO_DEV_ATTR_ACCEL_Z_SCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(accel_z_scale, _mode, _show, _store, _addr)
-#define IIO_EVENT_ATTR_ACCEL_Z_HIGH_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(accel_z_high, _evlist, _show, _store, _mask)
+#define IIO_DEV_ATTR_ACCEL_CALIBBIAS(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(accel_calibbias, _mode, _show, _store, _addr)
-#define IIO_EVENT_CODE_ACCEL_Z_HIGH (IIO_EVENT_CODE_ACCEL_BASE + 2)
+#define IIO_DEV_ATTR_ACCEL_X_CALIBBIAS(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(accel_x_calibbias, _mode, _show, _store, _addr)
-#define IIO_EVENT_ATTR_ACCEL_X_LOW(_show, _store, _mask, _handler) \
- IIO_EVENT_ATTR(accel_x_low, _show, _store, _mask, _handler)
+#define IIO_DEV_ATTR_ACCEL_Y_CALIBBIAS(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(accel_y_calibbias, _mode, _show, _store, _addr)
-#define IIO_EVENT_ATTR_ACCEL_X_LOW_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(accel_x_low, _evlist, _show, _store, _mask)
+#define IIO_DEV_ATTR_ACCEL_Z_CALIBBIAS(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(accel_z_calibbias, _mode, _show, _store, _addr)
-#define IIO_EVENT_CODE_ACCEL_X_LOW (IIO_EVENT_CODE_ACCEL_BASE + 3)
+#define IIO_DEV_ATTR_ACCEL_CALIBSCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(accel_calibscale, _mode, _show, _store, _addr)
-#define IIO_EVENT_ATTR_ACCEL_Y_LOW(_show, _store, _mask, _handler) \
- IIO_EVENT_ATTR(accel_y_low, _show, _store, _mask, _handler)
+#define IIO_DEV_ATTR_ACCEL_X_CALIBSCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(accel_x_calibscale, _mode, _show, _store, _addr)
-#define IIO_EVENT_ATTR_ACCEL_Y_LOW_SH(_evlist, _show, _store, _mask)\
- IIO_EVENT_ATTR_SH(accel_y_low, _evlist, _show, _store, _mask)
+#define IIO_DEV_ATTR_ACCEL_Y_CALIBSCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(accel_y_calibscale, _mode, _show, _store, _addr)
-#define IIO_EVENT_CODE_ACCEL_Y_LOW (IIO_EVENT_CODE_ACCEL_BASE + 4)
+#define IIO_DEV_ATTR_ACCEL_Z_CALIBSCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(accel_z_calibscale, _mode, _show, _store, _addr)
-#define IIO_EVENT_ATTR_ACCEL_Z_LOW(_show, _store, _mask, _handler) \
- IIO_EVENT_ATTR(accel_z_low, _show, _store, _mask, _handler)
-
-#define IIO_EVENT_ATTR_ACCEL_Z_LOW_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(accel_z_low, _evlist, _show, _store, _mask)
-
-#define IIO_EVENT_CODE_ACCEL_Z_LOW (IIO_EVENT_CODE_ACCEL_BASE + 5)
-
-#define IIO_EVENT_ATTR_FREE_FALL_DETECT(_show, _store, _mask, _handler) \
- IIO_EVENT_ATTR(free_fall, _show, _store, _mask, _handler)
-
-#define IIO_EVENT_ATTR_FREE_FALL_DETECT_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(free_fall, _evlist, _show, _store, _mask)
-
-#define IIO_EVENT_CODE_FREE_FALL (IIO_EVENT_CODE_ACCEL_BASE + 6)
-
-
-#define IIO_EVENT_ATTR_ACCEL_X_ROC_HIGH_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(accel_x_roc_high, _evlist, _show, _store, _mask)
-
-#define IIO_EVENT_CODE_ACCEL_X_ROC_HIGH (IIO_EVENT_CODE_ACCEL_BASE + 10)
-
-#define IIO_EVENT_ATTR_ACCEL_X_ROC_LOW_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(accel_x_roc_low, _evlist, _show, _store, _mask)
-
-#define IIO_EVENT_CODE_ACCEL_X_ROC_LOW (IIO_EVENT_CODE_ACCEL_BASE + 11)
-
-#define IIO_EVENT_ATTR_ACCEL_Y_ROC_HIGH_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(accel_y_roc_high, _evlist, _show, _store, _mask)
-
-#define IIO_EVENT_CODE_ACCEL_Y_ROC_HIGH (IIO_EVENT_CODE_ACCEL_BASE + 12)
-
-#define IIO_EVENT_ATTR_ACCEL_Y_ROC_LOW_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(accel_y_roc_low, _evlist, _show, _store, _mask)
-
-#define IIO_EVENT_CODE_ACCEL_Y_ROC_LOW (IIO_EVENT_CODE_ACCEL_BASE + 13)
+#define IIO_DEV_ATTR_ACCEL(_show, _addr) \
+ IIO_DEVICE_ATTR(accel_raw, S_IRUGO, _show, NULL, _addr)
-#define IIO_EVENT_ATTR_ACCEL_Z_ROC_HIGH_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(accel_z_roc_high, _evlist, _show, _store, _mask)
+#define IIO_DEV_ATTR_ACCEL_X(_show, _addr) \
+ IIO_DEVICE_ATTR(accel_x_raw, S_IRUGO, _show, NULL, _addr)
-#define IIO_EVENT_CODE_ACCEL_Z_ROC_HIGH (IIO_EVENT_CODE_ACCEL_BASE + 14)
+#define IIO_DEV_ATTR_ACCEL_Y(_show, _addr) \
+ IIO_DEVICE_ATTR(accel_y_raw, S_IRUGO, _show, NULL, _addr)
-#define IIO_EVENT_ATTR_ACCEL_Z_ROC_LOW_SH(_evlist, _show, _store, _mask) \
- IIO_EVENT_ATTR_SH(accel_z_roc_low, _evlist, _show, _store, _mask)
+#define IIO_DEV_ATTR_ACCEL_Z(_show, _addr) \
+ IIO_DEVICE_ATTR(accel_z_raw, S_IRUGO, _show, NULL, _addr)
-#define IIO_EVENT_CODE_ACCEL_Z_ROC_LOW (IIO_EVENT_CODE_ACCEL_BASE + 15)
diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c
index 6c6923f..e4ac956 100644
--- a/drivers/staging/iio/accel/adis16209_core.c
+++ b/drivers/staging/iio/accel/adis16209_core.c
@@ -391,51 +391,43 @@ err_ret:
return ret;
}
-static IIO_DEV_ATTR_IN_NAMED_RAW(supply, adis16209_read_14bit_unsigned,
+static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16209_read_14bit_unsigned,
ADIS16209_SUPPLY_OUT);
-static IIO_CONST_ATTR(in_supply_scale, "0.30518");
-static IIO_DEV_ATTR_IN_RAW(0, adis16209_read_12bit_unsigned,
+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(in0_scale, "0.6105");
+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_OFFSET(S_IWUSR | S_IRUGO,
+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_OFFSET(S_IWUSR | S_IRUGO,
+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.24414");
+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_DEV_ATTR_INCLI_X_OFFSET(S_IWUSR | S_IRUGO,
- adis16209_read_14bit_signed,
- adis16209_write_16bit,
- ADIS16209_XACCL_NULL);
-static IIO_DEV_ATTR_INCLI_Y_OFFSET(S_IWUSR | S_IRUGO,
- adis16209_read_14bit_signed,
- adis16209_write_16bit,
- ADIS16209_YACCL_NULL);
-static IIO_CONST_ATTR(incli_scale, "0.025");
+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(adis16209_read_temp);
-static IIO_CONST_ATTR(temp_offset, "25");
-static IIO_CONST_ATTR(temp_scale, "-0.47");
+static IIO_DEV_ATTR_TEMP_RAW(adis16209_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, adis16209_write_reset, 0);
-static IIO_CONST_ATTR(name, "adis16209");
+static IIO_CONST_ATTR_NAME("adis16209");
static struct attribute *adis16209_event_attributes[] = {
NULL
@@ -446,24 +438,22 @@ static struct attribute_group adis16209_event_attribute_group = {
};
static struct attribute *adis16209_attributes[] = {
- &iio_dev_attr_in_supply_raw.dev_attr.attr,
- &iio_const_attr_in_supply_scale.dev_attr.attr,
- &iio_dev_attr_temp.dev_attr.attr,
+ &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_in0_raw.dev_attr.attr,
- &iio_const_attr_in0_scale.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_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_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,
&iio_dev_attr_rot_raw.dev_attr.attr,
NULL
diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c
index 25fde65..033135c 100644
--- a/drivers/staging/iio/accel/adis16209_ring.c
+++ b/drivers/staging/iio/accel/adis16209_ring.c
@@ -17,35 +17,52 @@
#include "../trigger.h"
#include "adis16209.h"
-static IIO_SCAN_EL_C(supply, ADIS16209_SCAN_SUPPLY, IIO_UNSIGNED(14),
+static IIO_SCAN_EL_C(in_supply, ADIS16209_SCAN_SUPPLY,
ADIS16209_SUPPLY_OUT, NULL);
-static IIO_SCAN_EL_C(accel_x, ADIS16209_SCAN_ACC_X, IIO_SIGNED(14),
- ADIS16209_XACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_y, ADIS16209_SCAN_ACC_Y, IIO_SIGNED(14),
- ADIS16209_YACCL_OUT, NULL);
-static IIO_SCAN_EL_C(aux_adc, ADIS16209_SCAN_AUX_ADC, IIO_UNSIGNED(12),
- ADIS16209_AUX_ADC, NULL);
-static IIO_SCAN_EL_C(temp, ADIS16209_SCAN_TEMP, IIO_UNSIGNED(12),
- ADIS16209_TEMP_OUT, NULL);
-static IIO_SCAN_EL_C(incli_x, ADIS16209_SCAN_INCLI_X, IIO_SIGNED(14),
+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, IIO_SIGNED(14),
+static IIO_SCAN_EL_C(incli_y, ADIS16209_SCAN_INCLI_Y,
ADIS16209_YINCL_OUT, NULL);
-static IIO_SCAN_EL_C(rot, ADIS16209_SCAN_ROT, IIO_SIGNED(14),
- ADIS16209_ROT_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_supply.dev_attr.attr,
+ &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_scan_el_aux_adc.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,
};
@@ -115,11 +132,11 @@ static void adis16209_trigger_bh_to_ring(struct work_struct *work_s)
struct adis16209_state *st
= container_of(work_s, struct adis16209_state,
work_trigger_to_ring);
+ struct iio_ring_buffer *ring = st->indio_dev->ring;
int i = 0;
s16 *data;
- size_t datasize = st->indio_dev
- ->ring->access.get_bpd(st->indio_dev->ring);
+ size_t datasize = ring->access.get_bytes_per_datum(ring);
data = kmalloc(datasize , GFP_KERNEL);
if (data == NULL) {
@@ -127,19 +144,19 @@ static void adis16209_trigger_bh_to_ring(struct work_struct *work_s)
return;
}
- if (st->indio_dev->scan_count)
+ if (ring->scan_count)
if (adis16209_read_ring_data(&st->indio_dev->dev, st->rx) >= 0)
- for (; i < st->indio_dev->scan_count; i++)
+ 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 (st->indio_dev->scan_timestamp)
+ if (ring->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
- st->indio_dev->ring->access.store_to(st->indio_dev->ring,
- (u8 *)data,
- st->last_timestamp);
+ ring->access.store_to(ring,
+ (u8 *)data,
+ st->last_timestamp);
iio_trigger_notify_done(st->indio_dev->trig);
kfree(data);
@@ -159,19 +176,6 @@ int adis16209_configure_ring(struct iio_dev *indio_dev)
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);
- /* Set default scan mode */
-
- iio_scan_mask_set(indio_dev, iio_scan_el_supply.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_rot.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_accel_x.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_accel_y.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_temp.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_aux_adc.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_incli_x.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_incli_y.number);
- indio_dev->scan_timestamp = true;
-
- indio_dev->scan_el_attrs = &adis16209_scan_el_group;
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
@@ -182,11 +186,23 @@ int adis16209_configure_ring(struct iio_dev *indio_dev)
/* Effectively select the ring buffer implementation */
iio_ring_sw_register_funcs(&ring->access);
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->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)
goto error_iio_sw_rb_free;
diff --git a/drivers/staging/iio/accel/adis16209_trigger.c b/drivers/staging/iio/accel/adis16209_trigger.c
index 1487eff..d2980dc 100644
--- a/drivers/staging/iio/accel/adis16209_trigger.c
+++ b/drivers/staging/iio/accel/adis16209_trigger.c
@@ -30,7 +30,7 @@ static int adis16209_data_rdy_trig_poll(struct iio_dev *dev_info,
IIO_EVENT_SH(data_rdy_trig, &adis16209_data_rdy_trig_poll);
-static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
+static IIO_TRIGGER_NAME_ATTR;
static struct attribute *adis16209_trigger_attrs[] = {
&dev_attr_name.attr,
diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c
index bb7d765..c86d149 100644
--- a/drivers/staging/iio/accel/adis16220_core.c
+++ b/drivers/staging/iio/accel/adis16220_core.c
@@ -485,9 +485,9 @@ static struct bin_attribute adc2_bin = {
.size = ADIS16220_CAPTURE_SIZE,
};
-static IIO_DEV_ATTR_IN_NAMED_RAW(supply, adis16220_read_12bit_unsigned,
+static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16220_read_12bit_unsigned,
ADIS16220_CAPT_SUPPLY);
-static IIO_CONST_ATTR(in_supply_scale, "0.0012207");
+static IIO_CONST_ATTR_IN_NAMED_SCALE(0, supply, "0.0012207");
static IIO_DEV_ATTR_ACCEL(adis16220_read_16bit, ADIS16220_CAPT_BUFA);
static IIO_DEVICE_ATTR(accel_peak_raw, S_IRUGO, adis16220_read_16bit,
NULL, ADIS16220_CAPT_PEAKA);
@@ -495,12 +495,13 @@ static IIO_DEV_ATTR_ACCEL_OFFSET(S_IWUSR | S_IRUGO,
adis16220_read_16bit,
adis16220_write_16bit,
ADIS16220_ACCL_NULL);
+static IIO_CONST_ATTR_ACCEL_SCALE("0.18704223545");
static IIO_DEV_ATTR_TEMP_RAW(adis16220_read_12bit_unsigned);
-static IIO_CONST_ATTR(temp_offset, "25");
-static IIO_CONST_ATTR(temp_scale, "-0.47");
+static IIO_CONST_ATTR_TEMP_OFFSET("25");
+static IIO_CONST_ATTR_TEMP_SCALE("-0.47");
-static IIO_DEV_ATTR_IN_RAW(0, adis16220_read_16bit, ADIS16220_CAPT_BUF1);
-static IIO_DEV_ATTR_IN_RAW(1, adis16220_read_16bit, ADIS16220_CAPT_BUF2);
+static IIO_DEV_ATTR_IN_RAW(1, adis16220_read_16bit, ADIS16220_CAPT_BUF1);
+static IIO_DEV_ATTR_IN_RAW(2, adis16220_read_16bit, ADIS16220_CAPT_BUF2);
static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL,
adis16220_write_reset, 0);
@@ -518,22 +519,23 @@ static IIO_DEV_ATTR_CAPTURE_COUNT(S_IWUSR | S_IRUGO,
adis16220_write_16bit,
ADIS16220_CAPT_PNTR);
-static IIO_CONST_ATTR_AVAIL_SAMP_FREQ("100200");
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100200");
-static IIO_CONST_ATTR(name, "adis16220");
+static IIO_CONST_ATTR_NAME("adis16220");
static struct attribute *adis16220_attributes[] = {
- &iio_dev_attr_in_supply_raw.dev_attr.attr,
- &iio_const_attr_in_supply_scale.dev_attr.attr,
+ &iio_dev_attr_in0_supply_raw.dev_attr.attr,
+ &iio_const_attr_in0_supply_scale.dev_attr.attr,
&iio_dev_attr_accel_raw.dev_attr.attr,
&iio_dev_attr_accel_offset.dev_attr.attr,
&iio_dev_attr_accel_peak_raw.dev_attr.attr,
+ &iio_const_attr_accel_scale.dev_attr.attr,
&iio_dev_attr_temp_raw.dev_attr.attr,
- &iio_dev_attr_in0_raw.dev_attr.attr,
&iio_dev_attr_in1_raw.dev_attr.attr,
+ &iio_dev_attr_in2_raw.dev_attr.attr,
&iio_const_attr_temp_offset.dev_attr.attr,
&iio_const_attr_temp_scale.dev_attr.attr,
- &iio_const_attr_available_sampling_frequency.dev_attr.attr,
+ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_reset.dev_attr.attr,
&iio_dev_attr_capture.dev_attr.attr,
&iio_dev_attr_capture_count.dev_attr.attr,
diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c
index 3e9531d..d11d164 100644
--- a/drivers/staging/iio/accel/adis16240_core.c
+++ b/drivers/staging/iio/accel/adis16240_core.c
@@ -376,11 +376,14 @@ err_ret:
return ret;
}
-static IIO_DEV_ATTR_IN_NAMED_RAW(supply, adis16240_read_10bit_unsigned,
+static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16240_read_10bit_unsigned,
ADIS16240_SUPPLY_OUT);
-static IIO_DEV_ATTR_IN_RAW(0, adis16240_read_10bit_signed,
+static IIO_DEV_ATTR_IN_RAW(1, adis16240_read_10bit_signed,
ADIS16240_AUX_ADC);
-static IIO_CONST_ATTR(in_supply_scale, "0.00488");
+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,
@@ -400,26 +403,26 @@ static IIO_DEVICE_ATTR(accel_z_peak_raw, S_IRUGO,
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_OFFSET(S_IWUSR | S_IRUGO,
+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_OFFSET(S_IWUSR | S_IRUGO,
+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_OFFSET(S_IWUSR | S_IRUGO,
+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_CONST_ATTR_TEMP_SCALE("0.244");
static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16240_write_reset, 0);
-static IIO_CONST_ATTR_AVAIL_SAMP_FREQ("4096");
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("4096");
-static IIO_CONST_ATTR(name, "adis16240");
+static IIO_CONST_ATTR_NAME("adis16240");
static struct attribute *adis16240_event_attributes[] = {
NULL
@@ -430,22 +433,24 @@ static struct attribute_group adis16240_event_attribute_group = {
};
static struct attribute *adis16240_attributes[] = {
- &iio_dev_attr_in_supply_raw.dev_attr.attr,
- &iio_const_attr_in_supply_scale.dev_attr.attr,
- &iio_dev_attr_in0_raw.dev_attr.attr,
+ &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_offset.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_offset.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_offset.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_available_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
diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c
index cd69a2e..f882e9c 100644
--- a/drivers/staging/iio/accel/adis16240_ring.c
+++ b/drivers/staging/iio/accel/adis16240_ring.c
@@ -17,29 +17,40 @@
#include "../trigger.h"
#include "adis16240.h"
-static IIO_SCAN_EL_C(supply, ADIS16240_SCAN_SUPPLY, IIO_UNSIGNED(10),
+static IIO_SCAN_EL_C(in_supply, ADIS16240_SCAN_SUPPLY,
ADIS16240_SUPPLY_OUT, NULL);
-static IIO_SCAN_EL_C(accel_x, ADIS16240_SCAN_ACC_X, IIO_SIGNED(10),
- ADIS16240_XACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_y, ADIS16240_SCAN_ACC_Y, IIO_SIGNED(10),
- ADIS16240_YACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_z, ADIS16240_SCAN_ACC_Z, IIO_SIGNED(10),
- ADIS16240_ZACCL_OUT, NULL);
-static IIO_SCAN_EL_C(aux_adc, ADIS16240_SCAN_AUX_ADC, IIO_UNSIGNED(10),
- ADIS16240_AUX_ADC, NULL);
-static IIO_SCAN_EL_C(temp, ADIS16240_SCAN_TEMP, IIO_UNSIGNED(10),
- ADIS16240_TEMP_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_supply.dev_attr.attr,
+ &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_scan_el_aux_adc.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,
};
@@ -107,11 +118,11 @@ static void adis16240_trigger_bh_to_ring(struct work_struct *work_s)
struct adis16240_state *st
= container_of(work_s, struct adis16240_state,
work_trigger_to_ring);
+ struct iio_ring_buffer *ring = st->indio_dev->ring;
int i = 0;
s16 *data;
- size_t datasize = st->indio_dev
- ->ring->access.get_bpd(st->indio_dev->ring);
+ size_t datasize = ring->access.get_bytes_per_datum(ring);
data = kmalloc(datasize , GFP_KERNEL);
if (data == NULL) {
@@ -119,17 +130,17 @@ static void adis16240_trigger_bh_to_ring(struct work_struct *work_s)
return;
}
- if (st->indio_dev->scan_count)
+ if (ring->scan_count)
if (adis16240_read_ring_data(&st->indio_dev->dev, st->rx) >= 0)
- for (; i < st->indio_dev->scan_count; i++)
+ 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 (st->indio_dev->scan_timestamp)
+ if (ring->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
- st->indio_dev->ring->access.store_to(st->indio_dev->ring,
+ ring->access.store_to(ring,
(u8 *)data,
st->last_timestamp);
@@ -151,17 +162,6 @@ int adis16240_configure_ring(struct iio_dev *indio_dev)
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);
- /* Set default scan mode */
-
- iio_scan_mask_set(indio_dev, iio_scan_el_supply.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_accel_x.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_accel_y.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_accel_z.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_temp.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_aux_adc.number);
- indio_dev->scan_timestamp = true;
-
- indio_dev->scan_el_attrs = &adis16240_scan_el_group;
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
@@ -172,11 +172,21 @@ int adis16240_configure_ring(struct iio_dev *indio_dev)
/* Effectively select the ring buffer implementation */
iio_ring_sw_register_funcs(&ring->access);
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->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)
goto error_iio_sw_rb_free;
diff --git a/drivers/staging/iio/accel/adis16240_trigger.c b/drivers/staging/iio/accel/adis16240_trigger.c
index 2ba71fd..6cb8681 100644
--- a/drivers/staging/iio/accel/adis16240_trigger.c
+++ b/drivers/staging/iio/accel/adis16240_trigger.c
@@ -30,7 +30,7 @@ static int adis16240_data_rdy_trig_poll(struct iio_dev *dev_info,
IIO_EVENT_SH(data_rdy_trig, &adis16240_data_rdy_trig_poll);
-static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
+static IIO_TRIGGER_NAME_ATTR;
static struct attribute *adis16240_trigger_attrs[] = {
&dev_attr_name.attr,
diff --git a/drivers/staging/iio/accel/inclinometer.h b/drivers/staging/iio/accel/inclinometer.h
index 5b49f83..faf73d7 100644
--- a/drivers/staging/iio/accel/inclinometer.h
+++ b/drivers/staging/iio/accel/inclinometer.h
@@ -21,3 +21,5 @@
#define IIO_DEV_ATTR_INCLI_Z_OFFSET(_mode, _show, _store, _addr) \
IIO_DEVICE_ATTR(incli_z_offset, _mode, _show, _store, _addr)
+#define IIO_CONST_ATTR_INCLI_SCALE(_string) \
+ IIO_CONST_ATTR(incli_scale, _string)
diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c
index 0ee9337..c4b4ab7 100644
--- a/drivers/staging/iio/accel/lis3l02dq_core.c
+++ b/drivers/staging/iio/accel/lis3l02dq_core.c
@@ -497,7 +497,7 @@ static LIS3L02DQ_UNSIGNED_ATTR(accel_y_calibscale,
static LIS3L02DQ_UNSIGNED_ATTR(accel_z_calibscale,
LIS3L02DQ_REG_GAIN_Z_ADDR);
-static IIO_DEVICE_ATTR(accel_mag_either_rising_value,
+static IIO_DEVICE_ATTR(accel_raw_mag_value,
S_IWUSR | S_IRUGO,
lis3l02dq_read_16bit_signed,
lis3l02dq_write_16bit_signed,
@@ -639,32 +639,56 @@ static void lis3l02dq_thresh_handler_bh_no_check(struct work_struct *work_s)
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_HIGH)
iio_push_event(st->help.indio_dev, 0,
- IIO_EVENT_CODE_ACCEL_Z_HIGH,
+ IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ 0,
+ IIO_EV_MOD_Z,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
st->thresh_timestamp);
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_LOW)
iio_push_event(st->help.indio_dev, 0,
- IIO_EVENT_CODE_ACCEL_Z_LOW,
+ IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ 0,
+ IIO_EV_MOD_Z,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
st->thresh_timestamp);
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_HIGH)
iio_push_event(st->help.indio_dev, 0,
- IIO_EVENT_CODE_ACCEL_Y_HIGH,
+ IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ 0,
+ IIO_EV_MOD_Y,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
st->thresh_timestamp);
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_LOW)
iio_push_event(st->help.indio_dev, 0,
- IIO_EVENT_CODE_ACCEL_Y_LOW,
+ IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ 0,
+ IIO_EV_MOD_Y,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
st->thresh_timestamp);
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_HIGH)
iio_push_event(st->help.indio_dev, 0,
- IIO_EVENT_CODE_ACCEL_X_HIGH,
+ IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ 0,
+ IIO_EV_MOD_X,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
st->thresh_timestamp);
if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_LOW)
iio_push_event(st->help.indio_dev, 0,
- IIO_EVENT_CODE_ACCEL_X_LOW,
+ 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);
@@ -679,37 +703,37 @@ static void lis3l02dq_thresh_handler_bh_no_check(struct work_struct *work_s)
/* A shared handler for a number of threshold types */
IIO_EVENT_SH(threshold, &lis3l02dq_thresh_handler_th);
-IIO_EVENT_ATTR_SH(accel_x_mag_pos_rising_en,
+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_mag_pos_rising_en,
+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_mag_pos_rising_en,
+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_mag_neg_rising_en,
+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_mag_neg_rising_en,
+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_mag_neg_rising_en,
+IIO_EVENT_ATTR_SH(accel_z_thresh_falling_en,
iio_event_threshold,
lis3l02dq_read_interrupt_config,
lis3l02dq_write_interrupt_config,
@@ -717,13 +741,13 @@ IIO_EVENT_ATTR_SH(accel_z_mag_neg_rising_en,
static struct attribute *lis3l02dq_event_attributes[] = {
- &iio_event_attr_accel_x_mag_pos_rising_en.dev_attr.attr,
- &iio_event_attr_accel_y_mag_pos_rising_en.dev_attr.attr,
- &iio_event_attr_accel_z_mag_pos_rising_en.dev_attr.attr,
- &iio_event_attr_accel_x_mag_neg_rising_en.dev_attr.attr,
- &iio_event_attr_accel_y_mag_neg_rising_en.dev_attr.attr,
- &iio_event_attr_accel_z_mag_neg_rising_en.dev_attr.attr,
- &iio_dev_attr_accel_mag_either_rising_value.dev_attr.attr,
+ &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
};
@@ -731,7 +755,7 @@ static struct attribute_group lis3l02dq_event_attribute_group = {
.attrs = lis3l02dq_event_attributes,
};
-static IIO_CONST_ATTR(name, "lis3l02dq");
+static IIO_CONST_ATTR_NAME("lis3l02dq");
static IIO_CONST_ATTR(accel_scale, "0.00958");
static struct attribute *lis3l02dq_attributes[] = {
diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c
index a960a8f..330d5d6 100644
--- a/drivers/staging/iio/accel/lis3l02dq_ring.c
+++ b/drivers/staging/iio/accel/lis3l02dq_ring.c
@@ -75,22 +75,30 @@ error_ret:
return ret;
}
-static IIO_SCAN_EL_C(accel_x, 0, IIO_SIGNED(16),
+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, IIO_SIGNED(16),
+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, IIO_SIGNED(16),
+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,
};
@@ -150,38 +158,40 @@ ssize_t lis3l02dq_read_accel_from_ring(struct device *dev,
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;
- while (dev_info->scan_el_attrs->attrs[i]) {
+ while (scan_el_attrs->attrs[i]) {
el = to_iio_scan_el((struct device_attribute *)
- (dev_info->scan_el_attrs->attrs[i]));
+ (scan_el_attrs->attrs[i]));
/* label is in fact the address */
if (el->label == this_attr->address)
break;
i++;
}
- if (!dev_info->scan_el_attrs->attrs[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(dev_info, el->number);
+ ret = iio_scan_mask_query(ring, el->number);
if (ret < 0)
goto error_ret;
if (ret) {
- data = kmalloc(dev_info->ring->access.get_bpd(dev_info->ring),
+ data = kmalloc(ring->access.get_bytes_per_datum(ring),
GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
- ret = dev_info->ring->access.read_last(dev_info->ring,
- (u8 *)data);
+ 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(dev_info, el->number);
+ len = iio_scan_mask_count_to_right(ring, el->number);
if (len < 0) {
ret = len;
goto error_free_data;
@@ -211,11 +221,12 @@ static const u8 read_all_tx_array[] = {
**/
static int lis3l02dq_read_all(struct lis3l02dq_state *st, u8 *rx_array)
{
+ struct iio_ring_buffer *ring = st->help.indio_dev->ring;
struct spi_transfer *xfers;
struct spi_message msg;
int ret, i, j = 0;
- xfers = kzalloc((st->help.indio_dev->scan_count) * 2
+ xfers = kzalloc((ring->scan_count) * 2
* sizeof(*xfers), GFP_KERNEL);
if (!xfers)
return -ENOMEM;
@@ -223,7 +234,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++) {
- if (st->help.indio_dev->scan_mask & (1 << i)) {
+ if (ring->scan_mask & (1 << i)) {
/* lower byte */
xfers[j].tx_buf = st->tx + 2*j;
st->tx[2*j] = read_all_tx_array[i*4];
@@ -251,7 +262,7 @@ static int lis3l02dq_read_all(struct lis3l02dq_state *st, u8 *rx_array)
* values in alternate bytes
*/
spi_message_init(&msg);
- for (j = 0; j < st->help.indio_dev->scan_count * 2; j++)
+ for (j = 0; j < ring->scan_count * 2; j++)
spi_message_add_tail(&xfers[j], &msg);
ret = spi_sync(st->us, &msg);
@@ -279,13 +290,13 @@ static int lis3l02dq_get_ring_element(struct iio_sw_ring_helper_state *h,
u8 *rx_array ;
s16 *data = (s16 *)buf;
- rx_array = kzalloc(4 * (h->indio_dev->scan_count), GFP_KERNEL);
+ rx_array = kzalloc(4 * (h->indio_dev->ring->scan_count), GFP_KERNEL);
if (rx_array == NULL)
return -ENOMEM;
ret = lis3l02dq_read_all(lis3l02dq_h_to_s(h), rx_array);
if (ret < 0)
return ret;
- for (i = 0; i < h->indio_dev->scan_count; i++)
+ for (i = 0; i < h->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);
@@ -379,7 +390,8 @@ static int lis3l02dq_data_rdy_trigger_set_state(struct iio_trigger *trig,
&t);
return ret;
}
-static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
+
+static IIO_TRIGGER_NAME_ATTR;
static struct attribute *lis3l02dq_trigger_attrs[] = {
&dev_attr_name.attr,
@@ -479,28 +491,29 @@ 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);
- /* Set default scan mode */
h->get_ring_element = &lis3l02dq_get_ring_element;
- iio_scan_mask_set(indio_dev, iio_scan_el_accel_x.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_accel_y.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_accel_z.number);
- indio_dev->scan_timestamp = true;
- indio_dev->scan_el_attrs = &lis3l02dq_scan_el_group;
-
- indio_dev->ring = iio_sw_rb_allocate(indio_dev);
- if (!indio_dev->ring)
+ ring = iio_sw_rb_allocate(indio_dev);
+ if (!ring)
return -ENOMEM;
+ indio_dev->ring = ring;
/* Effectively select the ring buffer implementation */
- iio_ring_sw_register_funcs(&indio_dev->ring->access);
- indio_dev->ring->bpe = 2;
- indio_dev->ring->preenable = &iio_sw_ring_preenable;
- indio_dev->ring->postenable = &iio_triggered_ring_postenable;
- indio_dev->ring->predisable = &iio_triggered_ring_predisable;
- indio_dev->ring->owner = THIS_MODULE;
+ iio_ring_sw_register_funcs(&ring->access);
+ 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->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)
diff --git a/drivers/staging/iio/accel/sca3000.h b/drivers/staging/iio/accel/sca3000.h
index 09d9470..2389284 100644
--- a/drivers/staging/iio/accel/sca3000.h
+++ b/drivers/staging/iio/accel/sca3000.h
@@ -91,7 +91,7 @@
#define SCA3000_INT_STATUS_X_TRIGGER 0x02
#define SCA3000_INT_STATUS_Z_TRIGGER 0x01
-/* Used to allow accesss to multiplexed registers */
+/* Used to allow access to multiplexed registers */
#define SCA3000_REG_ADDR_CTRL_SEL 0x18
/* Only available for SCA3000-D03 and SCA3000-D01 */
#define SCA3000_REG_CTRL_SEL_I2C_DISABLE 0x01
diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
index b78b6b6..5b06dea 100644
--- a/drivers/staging/iio/accel/sca3000_core.c
+++ b/drivers/staging/iio/accel/sca3000_core.c
@@ -721,8 +721,8 @@ error_ret:
}
static IIO_DEV_ATTR_TEMP_RAW(sca3000_read_temp);
-static IIO_CONST_ATTR(temp_scale, "0.555556");
-static IIO_CONST_ATTR(temp_offset, "-214.6");
+static IIO_CONST_ATTR_TEMP_SCALE("0.555556");
+static IIO_CONST_ATTR_TEMP_OFFSET("-214.6");
/**
* sca3000_show_thresh() sysfs query of a threshold
@@ -774,19 +774,19 @@ static ssize_t sca3000_write_thresh(struct device *dev,
return ret ? ret : len;
}
-static IIO_DEVICE_ATTR(accel_x_mag_either_rising_value,
+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_mag_either_rising_value,
+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_mag_either_rising_value,
+static IIO_DEVICE_ATTR(accel_z_raw_mag_rising_value,
S_IRUGO | S_IWUSR,
sca3000_show_thresh,
sca3000_write_thresh,
@@ -865,22 +865,38 @@ static void sca3000_interrupt_handler_bh(struct work_struct *work_s)
if (rx[1] & SCA3000_INT_STATUS_FREE_FALL)
iio_push_event(st->indio_dev, 0,
- IIO_EVENT_CODE_FREE_FALL,
+ 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);
if (rx[1] & SCA3000_INT_STATUS_Y_TRIGGER)
iio_push_event(st->indio_dev, 0,
- IIO_EVENT_CODE_ACCEL_Y_HIGH,
+ IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ 0,
+ IIO_EV_MOD_Y,
+ IIO_EV_TYPE_MAG,
+ IIO_EV_DIR_RISING),
st->last_timestamp);
if (rx[1] & SCA3000_INT_STATUS_X_TRIGGER)
iio_push_event(st->indio_dev, 0,
- IIO_EVENT_CODE_ACCEL_X_HIGH,
+ IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ 0,
+ IIO_EV_MOD_X,
+ IIO_EV_TYPE_MAG,
+ IIO_EV_DIR_RISING),
st->last_timestamp);
if (rx[1] & SCA3000_INT_STATUS_Z_TRIGGER)
iio_push_event(st->indio_dev, 0,
- IIO_EVENT_CODE_ACCEL_Z_HIGH,
+ IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
+ 0,
+ IIO_EV_MOD_Z,
+ IIO_EV_TYPE_MAG,
+ IIO_EV_DIR_RISING),
st->last_timestamp);
done:
@@ -1156,25 +1172,31 @@ exit_point:
IIO_EVENT_SH(all, &sca3000_handler_th);
/* Free fall detector related event attribute */
-IIO_EVENT_ATTR_FREE_FALL_DETECT_SH(iio_event_all,
- sca3000_query_free_fall_mode,
- sca3000_set_free_fall_mode,
- 0)
+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_either_rising_en,
+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_either_rising_en,
+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_either_rising_en,
+IIO_EVENT_ATTR_SH(accel_z_mag_rising_en,
iio_event_all,
sca3000_query_mo_det,
sca3000_set_mo_det,
@@ -1192,15 +1214,16 @@ IIO_EVENT_ATTR_RING_75_FULL_SH(iio_event_all,
SCA3000_INT_MASK_RING_THREE_QUARTER);
static struct attribute *sca3000_event_attributes[] = {
- &iio_event_attr_free_fall.dev_attr.attr,
- &iio_event_attr_accel_x_mag_either_rising_en.dev_attr.attr,
- &iio_event_attr_accel_y_mag_either_rising_en.dev_attr.attr,
- &iio_event_attr_accel_z_mag_either_rising_en.dev_attr.attr,
+ &iio_event_attr_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,
- &iio_dev_attr_accel_x_mag_either_rising_value.dev_attr.attr,
- &iio_dev_attr_accel_y_mag_either_rising_value.dev_attr.attr,
- &iio_dev_attr_accel_z_mag_either_rising_value.dev_attr.attr,
NULL,
};
@@ -1358,7 +1381,7 @@ static int __devinit __sca3000_probe(struct spi_device *spi,
* might be worthwhile.
*/
iio_add_event_to_list(
- iio_event_attr_accel_z_mag_either_rising_en.listel,
+ iio_event_attr_accel_z_mag_rising_en.listel,
&st->indio_dev
->interrupts[0]->ev_list);
}
diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c
index 8e8c068..c872fdd 100644
--- a/drivers/staging/iio/accel/sca3000_ring.c
+++ b/drivers/staging/iio/accel/sca3000_ring.c
@@ -53,7 +53,8 @@ static int sca3000_rip_hw_rb(struct iio_ring_buffer *r,
struct iio_dev *indio_dev = hw_ring->private;
struct sca3000_state *st = indio_dev->dev_data;
u8 *rx;
- int ret, num_available, num_read = 0;
+ s16 *samples;
+ int ret, i, num_available, num_read = 0;
int bytes_per_sample = 1;
if (st->bpse == 11)
@@ -87,6 +88,17 @@ static int sca3000_rip_hw_rb(struct iio_ring_buffer *r,
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;
+ }
+ }
+
error_ret:
mutex_unlock(&st->lock);
@@ -100,7 +112,7 @@ static int sca3000_ring_get_length(struct iio_ring_buffer *r)
}
/* only valid if resolution is kept at 11bits */
-static int sca3000_ring_get_bpd(struct iio_ring_buffer *r)
+static int sca3000_ring_get_bytes_per_datum(struct iio_ring_buffer *r)
{
return 6;
}
@@ -111,7 +123,7 @@ static void sca3000_ring_release(struct device *dev)
}
static IIO_RING_ENABLE_ATTR;
-static IIO_RING_BPS_ATTR;
+static IIO_RING_BYTES_PER_DATUM_ATTR;
static IIO_RING_LENGTH_ATTR;
/**
@@ -126,14 +138,18 @@ static ssize_t sca3000_show_ring_bpse(struct device *dev,
{
int len = 0, ret;
u8 *rx;
- struct iio_ring_buffer *r = dev_get_drvdata(dev);
- struct sca3000_state *st = r->indio_dev->dev_data;
+ 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);
if (ret)
goto error_ret;
- len = sprintf(buf, "%d\n", (rx[1] & SCA3000_RING_BUF_8BIT) ? 8 : 11);
+ if (rx[1] & 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);
@@ -153,44 +169,38 @@ static ssize_t sca3000_store_ring_bpse(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_ring_buffer *r = dev_get_drvdata(dev);
- struct sca3000_state *st = r->indio_dev->dev_data;
+ 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;
int ret;
u8 *rx;
- long val;
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- return ret;
mutex_lock(&st->lock);
ret = sca3000_read_data(st, SCA3000_REG_ADDR_MODE, &rx, 1);
- if (!ret)
- switch (val) {
- case 8:
- ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
- rx[1] | SCA3000_RING_BUF_8BIT);
- st->bpse = 8;
- break;
- case 11:
- ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
- rx[1] & ~SCA3000_RING_BUF_8BIT);
- st->bpse = 11;
- break;
- default:
- ret = -EINVAL;
- break;
- }
+ if (ret)
+ goto error_ret;
+ if (strncmp(buf, "s8/8", 4) == 0) {
+ ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
+ rx[1] | SCA3000_RING_BUF_8BIT);
+ st->bpse = 8;
+ } else if (strncmp(buf, "s11/16", 5) == 0) {
+ ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
+ rx[1] & ~SCA3000_RING_BUF_8BIT);
+ st->bpse = 11;
+ } else
+ ret = -EINVAL;
+error_ret:
mutex_unlock(&st->lock);
return ret ? ret : len;
}
-static IIO_SCAN_EL_C(accel_x, 0, 0, 0, NULL);
-static IIO_SCAN_EL_C(accel_y, 1, 0, 0, NULL);
-static IIO_SCAN_EL_C(accel_z, 2, 0, 0, NULL);
-static IIO_CONST_ATTR(accel_precision_available, "8 11");
-static IIO_DEVICE_ATTR(accel_precision,
+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,
@@ -198,10 +208,13 @@ static IIO_DEVICE_ATTR(accel_precision,
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_precision_available.dev_attr.attr,
- &iio_dev_attr_accel_precision.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
};
@@ -218,8 +231,8 @@ static struct attribute_group sca3000_scan_el_group = {
*/
static struct attribute *sca3000_ring_attributes[] = {
&dev_attr_length.attr,
- &dev_attr_bps.attr,
- &dev_attr_ring_enable.attr,
+ &dev_attr_bytes_per_datum.attr,
+ &dev_attr_enable.attr,
NULL,
};
@@ -264,15 +277,15 @@ static inline void sca3000_rb_free(struct iio_ring_buffer *r)
int sca3000_configure_ring(struct iio_dev *indio_dev)
{
- indio_dev->scan_el_attrs = &sca3000_scan_el_group;
indio_dev->ring = sca3000_rb_allocate(indio_dev);
if (indio_dev->ring == NULL)
return -ENOMEM;
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_bpd = &sca3000_ring_get_bpd;
+ indio_dev->ring->access.get_bytes_per_datum = &sca3000_ring_get_bytes_per_datum;
return 0;
}
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index 0835fbc..acb6767 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -26,3 +26,38 @@ config MAX1363_RING_BUFFER
help
Say yes here to include ring buffer support in the MAX1363
ADC driver.
+
+config AD799X
+ tristate "Analog Devices AD799x ADC driver"
+ depends on I2C
+ select IIO_TRIGGER if IIO_RING_BUFFER
+ select AD799X_RING_BUFFER
+ help
+ Say yes here to build support for Analog Devices:
+ ad7991, ad7995, ad7999, ad7992, ad7993, ad7994, ad7997, ad7998
+ i2c analog to digital convertors (ADC). Provides direct access
+ via sysfs.
+
+config AD799X_RING_BUFFER
+ bool "Analog Devices AD799x: use ring buffer"
+ depends on AD799X
+ select IIO_RING_BUFFER
+ select IIO_SW_RING
+ help
+ Say yes here to include ring buffer support in the AD799X
+ ADC driver.
+
+config AD7476
+ tristate "Analog Devices AD7475/6/7/8 AD7466/7/8 and AD7495 ADC driver"
+ depends on SPI
+ select IIO_RING_BUFFER
+ select IIO_SW_RING
+ select IIO_TRIGGER
+ help
+ Say yes here to build support for Analog Devices
+ AD7475, AD7476, AD7477, AD7478, AD7466, AD7467, AD7468, AD7495
+ 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 ad7476.
diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
index 688510f..b62c319b 100644
--- a/drivers/staging/iio/adc/Makefile
+++ b/drivers/staging/iio/adc/Makefile
@@ -6,3 +6,11 @@ max1363-y := max1363_core.o
max1363-y += max1363_ring.o
obj-$(CONFIG_MAX1363) += max1363.o
+
+ad799x-y := ad799x_core.o
+ad799x-$(CONFIG_AD799X_RING_BUFFER) += ad799x_ring.o
+obj-$(CONFIG_AD799X) += ad799x.o
+
+ad7476-y := ad7476_core.o
+ad7476-$(CONFIG_IIO_RING_BUFFER) += ad7476_ring.o
+obj-$(CONFIG_AD7476) += ad7476.o
diff --git a/drivers/staging/iio/adc/ad7476.h b/drivers/staging/iio/adc/ad7476.h
new file mode 100644
index 0000000..b51b49e
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7476.h
@@ -0,0 +1,77 @@
+/*
+ * AD7476/5/7/8 (A) SPI ADC driver
+ *
+ * Copyright 2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+#ifndef IIO_ADC_AD7476_H_
+#define IIO_ADC_AD7476_H_
+
+#define RES_MASK(bits) ((1 << (bits)) - 1)
+
+/*
+ * TODO: struct ad7476_platform_data needs to go into include/linux/iio
+ */
+
+struct ad7476_platform_data {
+ u16 vref_mv;
+};
+
+struct ad7476_chip_info {
+ u8 bits;
+ u8 storagebits;
+ u8 res_shift;
+ char sign;
+ u16 int_vref_mv;
+};
+
+struct ad7476_state {
+ struct iio_dev *indio_dev;
+ struct spi_device *spi;
+ const struct ad7476_chip_info *chip_info;
+ struct regulator *reg;
+ struct work_struct poll_work;
+ atomic_t protect_ring;
+ 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 char data[2] ____cacheline_aligned;
+};
+
+enum ad7476_supported_device_ids {
+ ID_AD7466,
+ ID_AD7467,
+ ID_AD7468,
+ ID_AD7475,
+ ID_AD7476,
+ ID_AD7477,
+ ID_AD7478,
+ ID_AD7495
+};
+
+#ifdef CONFIG_IIO_RING_BUFFER
+int ad7476_scan_from_ring(struct ad7476_state *st);
+int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev);
+void ad7476_ring_cleanup(struct iio_dev *indio_dev);
+#else /* CONFIG_IIO_RING_BUFFER */
+static inline int ad7476_scan_from_ring(struct ad7476_state *st)
+{
+ return 0;
+}
+
+static inline int
+ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev)
+{
+ return 0;
+}
+
+static inline void ad7476_ring_cleanup(struct iio_dev *indio_dev)
+{
+}
+#endif /* CONFIG_IIO_RING_BUFFER */
+#endif /* IIO_ADC_AD7476_H_ */
diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c
new file mode 100644
index 0000000..deb68c8
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7476_core.c
@@ -0,0 +1,293 @@
+/*
+ * AD7466/7/8 AD7476/5/7/8 (A) SPI ADC driver
+ *
+ * Copyright 2010 Analog Devices Inc.
+ *
+ * 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>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "../ring_generic.h"
+#include "adc.h"
+
+#include "ad7476.h"
+
+static int ad7476_scan_direct(struct ad7476_state *st)
+{
+ int ret;
+
+ ret = spi_sync(st->spi, &st->msg);
+ if (ret)
+ return ret;
+
+ return (st->data[0] << 8) | st->data[1];
+}
+
+static ssize_t ad7476_scan(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ 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.%d\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);
+}
+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,
+ },
+ [ID_AD7467] = {
+ .bits = 10,
+ .storagebits = 16,
+ .res_shift = 2,
+ .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ },
+ [ID_AD7468] = {
+ .bits = 8,
+ .storagebits = 16,
+ .res_shift = 4,
+ .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ },
+ [ID_AD7475] = {
+ .bits = 12,
+ .storagebits = 16,
+ .res_shift = 0,
+ .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ },
+ [ID_AD7476] = {
+ .bits = 12,
+ .storagebits = 16,
+ .res_shift = 0,
+ .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ },
+ [ID_AD7477] = {
+ .bits = 10,
+ .storagebits = 16,
+ .res_shift = 2,
+ .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ },
+ [ID_AD7478] = {
+ .bits = 8,
+ .storagebits = 16,
+ .res_shift = 4,
+ .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ },
+ [ID_AD7495] = {
+ .bits = 12,
+ .storagebits = 16,
+ .res_shift = 0,
+ .int_vref_mv = 2500,
+ .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ },
+};
+
+static int __devinit ad7476_probe(struct spi_device *spi)
+{
+ struct ad7476_platform_data *pdata = spi->dev.platform_data;
+ struct ad7476_state *st;
+ int ret, voltage_uv = 0;
+
+ st = kzalloc(sizeof(*st), GFP_KERNEL);
+ if (st == NULL) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+
+ 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 =
+ &ad7476_chip_info_tbl[spi_get_device_id(spi)->driver_data];
+
+ if (st->chip_info->int_vref_mv)
+ st->int_vref_mv = st->chip_info->int_vref_mv;
+ else 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, st);
+
+ 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;
+ }
+
+ /* Estabilish that the iio_dev is a child of the i2c device */
+ st->indio_dev->dev.parent = &spi->dev;
+ st->indio_dev->attrs = &ad7476_attribute_group;
+ st->indio_dev->dev_data = (void *)(st);
+ st->indio_dev->driver_module = THIS_MODULE;
+ st->indio_dev->modes = INDIO_DIRECT_MODE;
+
+ /* Setup default message */
+
+ st->xfer.rx_buf = &st->data;
+ st->xfer.len = st->chip_info->storagebits / 8;
+
+ spi_message_init(&st->msg);
+ spi_message_add_tail(&st->xfer, &st->msg);
+
+ ret = ad7476_register_ring_funcs_and_init(st->indio_dev);
+ if (ret)
+ goto error_free_device;
+
+ ret = iio_device_register(st->indio_dev);
+ if (ret)
+ goto error_free_device;
+
+ ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
+ if (ret)
+ goto error_cleanup_ring;
+ return 0;
+
+error_cleanup_ring:
+ ad7476_ring_cleanup(st->indio_dev);
+ iio_device_unregister(st->indio_dev);
+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);
+error_ret:
+ return ret;
+}
+
+static int ad7476_remove(struct spi_device *spi)
+{
+ struct ad7476_state *st = spi_get_drvdata(spi);
+ struct iio_dev *indio_dev = st->indio_dev;
+ iio_ring_buffer_unregister(indio_dev->ring);
+ ad7476_ring_cleanup(indio_dev);
+ iio_device_unregister(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 ad7476_id[] = {
+ {"ad7466", ID_AD7466},
+ {"ad7467", ID_AD7467},
+ {"ad7468", ID_AD7468},
+ {"ad7475", ID_AD7475},
+ {"ad7476", ID_AD7476},
+ {"ad7476a", ID_AD7476},
+ {"ad7477", ID_AD7477},
+ {"ad7477a", ID_AD7477},
+ {"ad7478", ID_AD7478},
+ {"ad7478a", ID_AD7478},
+ {"ad7495", ID_AD7495},
+ {}
+};
+
+static struct spi_driver ad7476_driver = {
+ .driver = {
+ .name = "ad7476",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = ad7476_probe,
+ .remove = __devexit_p(ad7476_remove),
+ .id_table = ad7476_id,
+};
+
+static int __init ad7476_init(void)
+{
+ return spi_register_driver(&ad7476_driver);
+}
+module_init(ad7476_init);
+
+static void __exit ad7476_exit(void)
+{
+ spi_unregister_driver(&ad7476_driver);
+}
+module_exit(ad7476_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD7475/6/7/8(A) AD7466/7/8 ADC");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:ad7476");
diff --git a/drivers/staging/iio/adc/ad7476_ring.c b/drivers/staging/iio/adc/ad7476_ring.c
new file mode 100644
index 0000000..85de142
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7476_ring.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2010 Analog Devices Inc.
+ * Copyright (C) 2008 Jonathan Cameron
+ *
+ * Licensed under the GPL-2 or later.
+ *
+ * ad7476_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"
+#include "../ring_generic.h"
+#include "../ring_sw.h"
+#include "../trigger.h"
+#include "../sysfs.h"
+
+#include "ad7476.h"
+
+static IIO_SCAN_EL_C(in0, 0, 0, NULL);
+
+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_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);
+ if (ring_data == NULL) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+ ret = ring->access.read_last(ring, ring_data);
+ if (ret)
+ goto error_free_ring_data;
+
+ ret = (ring_data[0] << 8) | ring_data[1];
+
+error_free_ring_data:
+ kfree(ring_data);
+error_ret:
+ return ret;
+}
+
+/**
+ * ad7476_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 ad7476_ring_preenable(struct iio_dev *indio_dev)
+{
+ struct ad7476_state *st = indio_dev->dev_data;
+ size_t d_size;
+
+ if (indio_dev->ring->access.set_bytes_per_datum) {
+ d_size = st->chip_info->storagebits / 8 + sizeof(s64);
+ if (d_size % 8)
+ d_size += 8 - (d_size % 8);
+ indio_dev->ring->access.set_bytes_per_datum(indio_dev->ring,
+ d_size);
+ }
+
+ return 0;
+}
+
+/**
+ * ad7476_poll_func_th() th of trigger launched polling to ring buffer
+ *
+ * As sampling only occurs on i2c comms occuring, 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)
+{
+ 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);
+ s64 time_ns;
+ __u8 *rxbuf;
+ int b_sent;
+ size_t d_size;
+
+ /* Ensure the timestamp is 8 byte aligned */
+ d_size = st->chip_info->storagebits / 8 + sizeof(s64);
+ 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;
+
+ rxbuf = kzalloc(d_size, GFP_KERNEL);
+ if (rxbuf == NULL)
+ return;
+
+ b_sent = spi_read(st->spi, rxbuf, st->chip_info->storagebits / 8);
+ if (b_sent < 0)
+ goto done;
+
+ time_ns = iio_get_time_ns();
+
+ memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
+
+ indio_dev->ring->access.store_to(&sw_ring->buf, rxbuf, time_ns);
+done:
+ kfree(rxbuf);
+ atomic_dec(&st->protect_ring);
+}
+
+int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev)
+{
+ struct ad7476_state *st = indio_dev->dev_data;
+ int ret = 0;
+
+ indio_dev->ring = iio_sw_rb_allocate(indio_dev);
+ if (!indio_dev->ring) {
+ 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, &ad7476_poll_func_th);
+ if (ret)
+ 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;
+
+ 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:
+ return ret;
+}
+
+void ad7476_ring_cleanup(struct iio_dev *indio_dev)
+{
+ /* ensure that the trigger has been detached */
+ if (indio_dev->trig) {
+ iio_put_trigger(indio_dev->trig);
+ iio_trigger_dettach_poll_func(indio_dev->trig,
+ indio_dev->pollfunc);
+ }
+ kfree(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
new file mode 100644
index 0000000..81a20d5
--- /dev/null
+++ b/drivers/staging/iio/adc/ad799x.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2010 Michael Hennerich, Analog Devices Inc.
+ * Copyright (C) 2008-2010 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ad799x.h
+ */
+
+#ifndef _AD799X_H_
+#define _AD799X_H_
+
+#define AD799X_CHANNEL_SHIFT 4
+#define AD799X_STORAGEBITS 16
+/*
+ * AD7991, AD7995 and AD7999 defines
+ */
+
+#define AD7991_REF_SEL 0x08
+#define AD7991_FLTR 0x04
+#define AD7991_BIT_TRIAL_DELAY 0x02
+#define AD7991_SAMPLE_DELAY 0x01
+
+/*
+ * AD7992, AD7993, AD7994, AD7997 and AD7998 defines
+ */
+
+#define AD7998_FLTR 0x08
+#define AD7998_ALERT_EN 0x04
+#define AD7998_BUSY_ALERT 0x02
+#define AD7998_BUSY_ALERT_POL 0x01
+
+#define AD7998_CONV_RES_REG 0x0
+#define AD7998_ALERT_STAT_REG 0x1
+#define AD7998_CONF_REG 0x2
+#define AD7998_CYCLE_TMR_REG 0x3
+#define AD7998_DATALOW_CH1_REG 0x4
+#define AD7998_DATAHIGH_CH1_REG 0x5
+#define AD7998_HYST_CH1_REG 0x6
+#define AD7998_DATALOW_CH2_REG 0x7
+#define AD7998_DATAHIGH_CH2_REG 0x8
+#define AD7998_HYST_CH2_REG 0x9
+#define AD7998_DATALOW_CH3_REG 0xA
+#define AD7998_DATAHIGH_CH3_REG 0xB
+#define AD7998_HYST_CH3_REG 0xC
+#define AD7998_DATALOW_CH4_REG 0xD
+#define AD7998_DATAHIGH_CH4_REG 0xE
+#define AD7998_HYST_CH4_REG 0xF
+
+#define AD7998_CYC_MASK 0x7
+#define AD7998_CYC_DIS 0x0
+#define AD7998_CYC_TCONF_32 0x1
+#define AD7998_CYC_TCONF_64 0x2
+#define AD7998_CYC_TCONF_128 0x3
+#define AD7998_CYC_TCONF_256 0x4
+#define AD7998_CYC_TCONF_512 0x5
+#define AD7998_CYC_TCONF_1024 0x6
+#define AD7998_CYC_TCONF_2048 0x7
+
+#define AD7998_ALERT_STAT_CLEAR 0xFF
+
+/*
+ * AD7997 and AD7997 defines
+ */
+
+#define AD7997_8_READ_SINGLE 0x80
+#define AD7997_8_READ_SEQUENCE 0x70
+
+enum {
+ ad7991,
+ ad7995,
+ ad7999,
+ ad7992,
+ ad7993,
+ ad7994,
+ ad7997,
+ ad7998
+};
+
+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
+ * @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;
+ 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);
+};
+
+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;
+ struct iio_trigger *trig;
+ struct regulator *reg;
+ s64 last_timestamp;
+ u16 int_vref_mv;
+ unsigned id;
+ char *name;
+ u16 config;
+};
+
+/*
+ * TODO: struct ad799x_platform_data needs to go into include/linux/iio
+ */
+
+struct ad799x_platform_data {
+ u16 vref_mv;
+};
+
+int ad799x_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);
+int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev);
+void ad799x_ring_cleanup(struct iio_dev *indio_dev);
+#else /* CONFIG_AD799X_RING_BUFFER */
+int ad799x_single_channel_from_ring(struct ad799x_state *st, long mask)
+{
+ return -EINVAL;
+}
+
+
+static inline int
+ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev)
+{
+ return 0;
+}
+
+static inline void ad799x_ring_cleanup(struct iio_dev *indio_dev)
+{
+}
+#endif /* CONFIG_AD799X_RING_BUFFER */
+#endif /* _AD799X_H_ */
diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c
new file mode 100644
index 0000000..6309d52
--- /dev/null
+++ b/drivers/staging/iio/adc/ad799x_core.c
@@ -0,0 +1,923 @@
+/*
+ * iio/adc/ad799x.c
+ * Copyright (C) 2010 Michael Hennerich, Analog Devices Inc.
+ *
+ * based on iio/adc/max1363
+ * Copyright (C) 2008-2010 Jonathan Cameron
+ *
+ * based on linux/drivers/i2c/chips/max123x
+ * Copyright (C) 2002-2004 Stefan Eletzhofer
+ *
+ * based on linux/drivers/acron/char/pcf8583.c
+ * Copyright (C) 2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ad799x.c
+ *
+ * Support for ad7991, ad7995, ad7999, ad7992, ad7993, ad7994, ad7997,
+ * ad7998 and similar chips.
+ *
+ */
+
+#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>
+#include <linux/types.h>
+#include <linux/err.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+
+#include "../ring_generic.h"
+#include "adc.h"
+#include "ad799x.h"
+
+/*
+ * ad799x register access by I2C
+ */
+static int ad799x_i2c_read16(struct ad799x_state *st, u8 reg, u16 *data)
+{
+ struct i2c_client *client = st->client;
+ int ret = 0;
+
+ ret = i2c_smbus_read_word_data(client, reg);
+ if (ret < 0) {
+ dev_err(&client->dev, "I2C read error\n");
+ return ret;
+ }
+
+ *data = swab16((u16)ret);
+
+ return 0;
+}
+
+static int ad799x_i2c_read8(struct ad799x_state *st, u8 reg, u8 *data)
+{
+ struct i2c_client *client = st->client;
+ int ret = 0;
+
+ ret = i2c_smbus_read_byte_data(client, reg);
+ if (ret < 0) {
+ dev_err(&client->dev, "I2C read error\n");
+ return ret;
+ }
+
+ *data = (u8)ret;
+
+ return 0;
+}
+
+static int ad799x_i2c_write16(struct ad799x_state *st, u8 reg, u16 data)
+{
+ struct i2c_client *client = st->client;
+ int ret = 0;
+
+ ret = i2c_smbus_write_word_data(client, reg, swab16(data));
+ if (ret < 0)
+ dev_err(&client->dev, "I2C write error\n");
+
+ return ret;
+}
+
+static int ad799x_i2c_write8(struct ad799x_state *st, u8 reg, u8 data)
+{
+ struct i2c_client *client = st->client;
+ int ret = 0;
+
+ ret = i2c_smbus_write_byte_data(client, reg, data);
+ if (ret < 0)
+ dev_err(&client->dev, "I2C write error\n");
+
+ 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 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)
+{
+ 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)
+{
+ 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;
+ }
+
+ return 0;
+}
+
+static ssize_t ad799x_read_single_channel(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_dev_attr *this_attr = to_iio_dev_attr(attr);
+ int ret = 0, len = 0;
+ u32 data ;
+ u16 rxbuf[1];
+ u8 cmd;
+ long mask;
+
+ mutex_lock(&dev_info->mlock);
+ mask = 1 << this_attr->address;
+ /* If ring buffer capture is occuring, 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];
+ }
+
+ /* 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;
+}
+
+static ssize_t ad799x_read_frequency(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);
+
+ int ret, len = 0;
+ u8 val;
+ ret = ad799x_i2c_read8(st, AD7998_CYCLE_TMR_REG, &val);
+ if (ret)
+ return ret;
+
+ val &= AD7998_CYC_MASK;
+
+ switch (val) {
+ case AD7998_CYC_DIS:
+ len = sprintf(buf, "0\n");
+ break;
+ case AD7998_CYC_TCONF_32:
+ len = sprintf(buf, "15625\n");
+ break;
+ case AD7998_CYC_TCONF_64:
+ len = sprintf(buf, "7812\n");
+ break;
+ case AD7998_CYC_TCONF_128:
+ len = sprintf(buf, "3906\n");
+ break;
+ case AD7998_CYC_TCONF_256:
+ len = sprintf(buf, "1953\n");
+ break;
+ case AD7998_CYC_TCONF_512:
+ len = sprintf(buf, "976\n");
+ break;
+ case AD7998_CYC_TCONF_1024:
+ len = sprintf(buf, "488\n");
+ break;
+ case AD7998_CYC_TCONF_2048:
+ len = sprintf(buf, "244\n");
+ break;
+ }
+ return len;
+}
+
+static ssize_t ad799x_write_frequency(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct ad799x_state *st = iio_dev_get_devdata(dev_info);
+
+ long val;
+ int ret;
+ u8 t;
+
+ ret = strict_strtol(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ mutex_lock(&dev_info->mlock);
+ ret = ad799x_i2c_read8(st, AD7998_CYCLE_TMR_REG, &t);
+ if (ret)
+ goto error_ret_mutex;
+ /* Wipe the bits clean */
+ t &= ~AD7998_CYC_MASK;
+
+ switch (val) {
+ case 15625:
+ t |= AD7998_CYC_TCONF_32;
+ break;
+ case 7812:
+ t |= AD7998_CYC_TCONF_64;
+ break;
+ case 3906:
+ t |= AD7998_CYC_TCONF_128;
+ break;
+ case 1953:
+ t |= AD7998_CYC_TCONF_256;
+ break;
+ case 976:
+ t |= AD7998_CYC_TCONF_512;
+ break;
+ case 488:
+ t |= AD7998_CYC_TCONF_1024;
+ break;
+ case 244:
+ t |= AD7998_CYC_TCONF_2048;
+ break;
+ case 0:
+ t |= AD7998_CYC_DIS;
+ break;
+ default:
+ ret = -EINVAL;
+ goto error_ret_mutex;
+ }
+
+ ret = ad799x_i2c_write8(st, AD7998_CYCLE_TMR_REG, t);
+
+error_ret_mutex:
+ mutex_unlock(&dev_info->mlock);
+
+ 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);
+
+ int ret;
+ u16 val;
+ ret = ad799x_i2c_read16(st, this_attr->mask, &val);
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t ad799x_write_channel_config(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct ad799x_state *st = iio_dev_get_devdata(dev_info);
+ struct iio_event_attr *this_attr = to_iio_event_attr(attr);
+
+ long val;
+ int ret;
+
+ ret = strict_strtol(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ mutex_lock(&dev_info->mlock);
+ ret = ad799x_i2c_write16(st, this_attr->mask, val);
+ mutex_unlock(&dev_info->mlock);
+
+ return ret ? ret : len;
+}
+
+static void ad799x_interrupt_bh(struct work_struct *work_s)
+{
+ struct ad799x_state *st = container_of(work_s,
+ struct ad799x_state, work_thresh);
+ u8 status;
+ int i;
+
+ if (ad799x_i2c_read8(st, AD7998_ALERT_STAT_REG, &status))
+ goto err_out;
+
+ if (!status)
+ goto err_out;
+
+ 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);
+ }
+
+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.%d\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);
+}
+
+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_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_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_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_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
+ ad799x_read_frequency,
+ ad799x_write_frequency);
+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_sampling_frequency.dev_attr.attr,
+ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+ NULL,
+};
+
+static struct attribute_group ad7993_4_7_8_event_attrs_group = {
+ .attrs = ad7993_4_7_8_event_attributes,
+};
+
+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_sampling_frequency.dev_attr.attr,
+ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+ NULL,
+};
+
+static struct attribute_group ad7992_event_attrs_group = {
+ .attrs = ad7992_event_attributes,
+};
+
+static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
+ [ad7991] = {
+ .num_inputs = 4,
+ .bits = 12,
+ .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .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,
+ },
+ [ad7995] = {
+ .num_inputs = 4,
+ .bits = 10,
+ .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .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,
+ },
+ [ad7999] = {
+ .num_inputs = 4,
+ .bits = 10,
+ .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .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,
+ },
+ [ad7992] = {
+ .num_inputs = 2,
+ .bits = 12,
+ .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .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,
+ },
+ [ad7993] = {
+ .num_inputs = 4,
+ .bits = 10,
+ .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .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,
+ },
+ [ad7994] = {
+ .num_inputs = 4,
+ .bits = 12,
+ .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .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,
+ },
+ [ad7997] = {
+ .num_inputs = 8,
+ .bits = 10,
+ .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .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,
+ },
+ [ad7998] = {
+ .num_inputs = 8,
+ .bits = 12,
+ .sign = IIO_SCAN_EL_TYPE_UNSIGNED,
+ .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,
+ },
+};
+
+static int __devinit ad799x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ 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;
+ }
+
+ /* this is only used for device removal purposes */
+ i2c_set_clientdata(client, st);
+
+ 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;
+
+ /* TODO: Add pdata options for filtering and bit delay */
+
+ if (pdata)
+ st->int_vref_mv = pdata->vref_mv;
+ else
+ st->int_vref_mv = st->chip_info->int_vref_mv;
+
+ st->reg = regulator_get(&client->dev, "vcc");
+ if (!IS_ERR(st->reg)) {
+ ret = regulator_enable(st->reg);
+ if (ret)
+ goto error_put_reg;
+ }
+ 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;
+
+ 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;
+
+ ret = ad799x_register_ring_funcs_and_init(st->indio_dev);
+ if (ret)
+ goto error_free_device;
+
+ ret = iio_device_register(st->indio_dev);
+ if (ret)
+ goto error_cleanup_ring;
+ regdone = 1;
+
+ ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
+ 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 (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);
+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 __devexit int ad799x_remove(struct i2c_client *client)
+{
+ struct ad799x_state *st = i2c_get_clientdata(client);
+ struct iio_dev *indio_dev = st->indio_dev;
+
+ if (client->irq > 0 && st->chip_info->monitor_mode)
+ iio_unregister_interrupt_line(indio_dev, 0);
+
+ 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);
+
+ return 0;
+}
+
+static const struct i2c_device_id ad799x_id[] = {
+ { "ad7991", ad7991 },
+ { "ad7995", ad7995 },
+ { "ad7999", ad7999 },
+ { "ad7992", ad7992 },
+ { "ad7993", ad7993 },
+ { "ad7994", ad7994 },
+ { "ad7997", ad7997 },
+ { "ad7998", ad7998 },
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, ad799x_id);
+
+static struct i2c_driver ad799x_driver = {
+ .driver = {
+ .name = "ad799x",
+ },
+ .probe = ad799x_probe,
+ .remove = __devexit_p(ad799x_remove),
+ .id_table = ad799x_id,
+};
+
+static __init int ad799x_init(void)
+{
+ return i2c_add_driver(&ad799x_driver);
+}
+
+static __exit void ad799x_exit(void)
+{
+ i2c_del_driver(&ad799x_driver);
+}
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD799x ADC");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("i2c:ad799x");
+
+module_init(ad799x_init);
+module_exit(ad799x_exit);
diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c
new file mode 100644
index 0000000..975cdcb
--- /dev/null
+++ b/drivers/staging/iio/adc/ad799x_ring.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2010 Michael Hennerich, Analog Devices Inc.
+ * Copyright (C) 2008-2010 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ad799x_ring.c
+ */
+
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/sysfs.h>
+#include <linux/list.h>
+#include <linux/i2c.h>
+#include <linux/bitops.h>
+
+#include "../iio.h"
+#include "../ring_generic.h"
+#include "../ring_sw.h"
+#include "../trigger.h"
+#include "../sysfs.h"
+
+#include "ad799x.h"
+
+int ad799x_single_channel_from_ring(struct ad799x_state *st, long mask)
+{
+ struct iio_ring_buffer *ring = st->indio_dev->ring;
+ int count = 0, ret;
+ u16 *ring_data;
+
+ if (!(ring->scan_mask & mask)) {
+ ret = -EBUSY;
+ goto error_ret;
+ }
+
+ 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);
+ if (ret)
+ goto error_free_ring_data;
+ /* Need a count of channels prior to this one */
+ mask >>= 1;
+ while (mask) {
+ if (mask & ring->scan_mask)
+ count++;
+ mask >>= 1;
+ }
+
+ ret = be16_to_cpu(ring_data[count]);
+
+error_free_ring_data:
+ kfree(ring_data);
+error_ret:
+ return ret;
+}
+
+/**
+ * ad799x_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 ad799x_ring_preenable(struct iio_dev *indio_dev)
+{
+ struct iio_ring_buffer *ring = indio_dev->ring;
+ struct ad799x_state *st = indio_dev->dev_data;
+ size_t d_size;
+ unsigned long numvals;
+
+ /*
+ * Need to figure out the current mode based upon the requested
+ * scan mask in iio_dev
+ */
+
+ if (st->id == ad7997 || st->id == ad7998)
+ ad799x_set_scan_mode(st, ring->scan_mask);
+
+ numvals = ring->scan_count;
+
+ if (ring->access.set_bytes_per_datum) {
+ d_size = numvals*2 + sizeof(s64);
+ if (d_size % 8)
+ d_size += 8 - (d_size % 8);
+ ring->access.set_bytes_per_datum(ring, d_size);
+ }
+
+ return 0;
+}
+
+/**
+ * ad799x_poll_func_th() th of trigger launched polling to ring buffer
+ *
+ * As sampling only occurs on i2c comms occuring, 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
+ *
+ * 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)
+{
+ struct ad799x_state *st = container_of(work_s, struct ad799x_state,
+ poll_work);
+ struct iio_dev *indio_dev = st->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;
+ size_t d_size;
+ u8 cmd;
+
+ unsigned long numvals = ring->scan_count;
+
+ /* Ensure the timestamp is 8 byte aligned */
+ d_size = numvals*2 + sizeof(s64);
+
+ 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;
+
+ rxbuf = kmalloc(d_size, GFP_KERNEL);
+ if (rxbuf == NULL)
+ return;
+
+ switch (st->id) {
+ case ad7991:
+ case ad7995:
+ case ad7999:
+ cmd = st->config | (ring->scan_mask << AD799X_CHANNEL_SHIFT);
+ break;
+ case ad7992:
+ case ad7993:
+ case ad7994:
+ cmd = (ring->scan_mask << AD799X_CHANNEL_SHIFT) |
+ AD7998_CONV_RES_REG;
+ break;
+ case ad7997:
+ case ad7998:
+ cmd = AD7997_8_READ_SEQUENCE | AD7998_CONV_RES_REG;
+ break;
+ default:
+ cmd = 0;
+ }
+
+ b_sent = i2c_smbus_read_i2c_block_data(st->client,
+ cmd, numvals*2, rxbuf);
+ if (b_sent < 0)
+ goto done;
+
+ time_ns = iio_get_time_ns();
+
+ memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
+
+ ring->access.store_to(&ring_sw->buf, rxbuf, time_ns);
+done:
+ kfree(rxbuf);
+ atomic_dec(&st->protect_ring);
+}
+
+
+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);
+ if (!indio_dev->ring) {
+ ret = -ENOMEM;
+ 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)
+ 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;
+
+ 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:
+ return ret;
+}
+
+void ad799x_ring_cleanup(struct iio_dev *indio_dev)
+{
+ /* ensure that the trigger has been detached */
+ if (indio_dev->trig) {
+ iio_put_trigger(indio_dev->trig);
+ iio_trigger_dettach_poll_func(indio_dev->trig,
+ indio_dev->pollfunc);
+ }
+ kfree(indio_dev->pollfunc);
+ iio_sw_rb_free(indio_dev->ring);
+}
diff --git a/drivers/staging/iio/adc/adc.h b/drivers/staging/iio/adc/adc.h
index 7841e6a..40c5949 100644
--- a/drivers/staging/iio/adc/adc.h
+++ b/drivers/staging/iio/adc/adc.h
@@ -16,8 +16,8 @@
#define IIO_DEV_ATTR_IN_RAW(_num, _show, _addr) \
IIO_DEVICE_ATTR(in##_num##_raw, S_IRUGO, _show, NULL, _addr)
-#define IIO_DEV_ATTR_IN_NAMED_RAW(_name, _show, _addr) \
- IIO_DEVICE_ATTR(in_##_name##_raw, S_IRUGO, _show, NULL, _addr)
+#define IIO_DEV_ATTR_IN_NAMED_RAW(_num, _name, _show, _addr) \
+ IIO_DEVICE_ATTR(in##_num##_##_name##_raw, S_IRUGO, _show, NULL, _addr)
#define IIO_DEV_ATTR_IN_DIFF_RAW(_nump, _numn, _show, _addr) \
IIO_DEVICE_ATTR_NAMED(in##_nump##min##_numn##_raw, \
@@ -27,5 +27,16 @@
NULL, \
_addr)
-#define IIO_EVENT_CODE_IN_HIGH_THRESH(a) (IIO_EVENT_CODE_ADC_BASE + a)
-#define IIO_EVENT_CODE_IN_LOW_THRESH(a) (IIO_EVENT_CODE_ADC_BASE + a + 32)
+
+#define IIO_CONST_ATTR_IN_NAMED_OFFSET(_num, _name, _string) \
+ IIO_CONST_ATTR(in##_num##_##_name##_offset, _string)
+
+#define IIO_CONST_ATTR_IN_NAMED_SCALE(_num, _name, _string) \
+ IIO_CONST_ATTR(in##_num##_##_name##_scale, _string)
+
+#define IIO_EVENT_CODE_IN_HIGH_THRESH(a) \
+ IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, a, IIO_EV_TYPE_THRESH, \
+ IIO_EV_DIR_RISING)
+#define IIO_EVENT_CODE_IN_LOW_THRESH(a) \
+ IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, a, IIO_EV_TYPE_THRESH, \
+ IIO_EV_DIR_FALLING)
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c
index 6435e50..dde097a 100644
--- a/drivers/staging/iio/adc/max1363_core.c
+++ b/drivers/staging/iio/adc/max1363_core.c
@@ -42,11 +42,10 @@
/* Here we claim all are 16 bits. This currently does no harm and saves
* us a lot of scan element listings */
-#define MAX1363_SCAN_EL(number) \
- IIO_SCAN_EL_C(in##number, number, IIO_UNSIGNED(16), 0, NULL);
+#define MAX1363_SCAN_EL(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, IIO_SIGNED(16), 0, NULL);
+ 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);
@@ -148,17 +147,59 @@ const struct max1363_mode
return NULL;
}
-static ssize_t max1363_show_precision(struct device *dev,
+static ssize_t max1363_show_precision_u(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ 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, "%d\n", st->chip_info->bits);
+ return sprintf(buf, "s%d/16\n", st->chip_info->bits);
}
-static IIO_DEVICE_ATTR(in_precision, S_IRUGO, max1363_show_precision,
- NULL, 0);
+#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,
@@ -345,15 +386,22 @@ static struct attribute_group max1363_dev_attr_group = {
};
static struct attribute *max1363_scan_el_attrs[] = {
- &iio_scan_el_in0.dev_attr.attr,
- &iio_scan_el_in1.dev_attr.attr,
- &iio_scan_el_in2.dev_attr.attr,
- &iio_scan_el_in3.dev_attr.attr,
- &iio_scan_el_in0min1.dev_attr.attr,
- &iio_scan_el_in2min3.dev_attr.attr,
- &iio_scan_el_in1min0.dev_attr.attr,
- &iio_scan_el_in3min2.dev_attr.attr,
- &iio_dev_attr_in_precision.dev_attr.attr,
+ &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,
};
@@ -419,31 +467,54 @@ static struct attribute_group max1238_dev_attr_group = {
};
static struct attribute *max1238_scan_el_attrs[] = {
- &iio_scan_el_in0.dev_attr.attr,
- &iio_scan_el_in1.dev_attr.attr,
- &iio_scan_el_in2.dev_attr.attr,
- &iio_scan_el_in3.dev_attr.attr,
- &iio_scan_el_in4.dev_attr.attr,
- &iio_scan_el_in5.dev_attr.attr,
- &iio_scan_el_in6.dev_attr.attr,
- &iio_scan_el_in7.dev_attr.attr,
- &iio_scan_el_in8.dev_attr.attr,
- &iio_scan_el_in9.dev_attr.attr,
- &iio_scan_el_in10.dev_attr.attr,
- &iio_scan_el_in11.dev_attr.attr,
- &iio_scan_el_in0min1.dev_attr.attr,
- &iio_scan_el_in2min3.dev_attr.attr,
- &iio_scan_el_in4min5.dev_attr.attr,
- &iio_scan_el_in6min7.dev_attr.attr,
- &iio_scan_el_in8min9.dev_attr.attr,
- &iio_scan_el_in10min11.dev_attr.attr,
- &iio_scan_el_in1min0.dev_attr.attr,
- &iio_scan_el_in3min2.dev_attr.attr,
- &iio_scan_el_in5min4.dev_attr.attr,
- &iio_scan_el_in7min6.dev_attr.attr,
- &iio_scan_el_in9min8.dev_attr.attr,
- &iio_scan_el_in11min10.dev_attr.attr,
- &iio_dev_attr_in_precision.dev_attr.attr,
+ &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,
};
@@ -498,23 +569,39 @@ static struct attribute_group max11608_dev_attr_group = {
};
static struct attribute *max11608_scan_el_attrs[] = {
- &iio_scan_el_in0.dev_attr.attr,
- &iio_scan_el_in1.dev_attr.attr,
- &iio_scan_el_in2.dev_attr.attr,
- &iio_scan_el_in3.dev_attr.attr,
- &iio_scan_el_in4.dev_attr.attr,
- &iio_scan_el_in5.dev_attr.attr,
- &iio_scan_el_in6.dev_attr.attr,
- &iio_scan_el_in7.dev_attr.attr,
- &iio_scan_el_in0min1.dev_attr.attr,
- &iio_scan_el_in2min3.dev_attr.attr,
- &iio_scan_el_in4min5.dev_attr.attr,
- &iio_scan_el_in6min7.dev_attr.attr,
- &iio_scan_el_in1min0.dev_attr.attr,
- &iio_scan_el_in3min2.dev_attr.attr,
- &iio_scan_el_in5min4.dev_attr.attr,
- &iio_scan_el_in7min6.dev_attr.attr,
- &iio_dev_attr_in_precision.dev_attr.attr,
+ &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
};
static struct attribute_group max11608_scan_el_group = {
@@ -1631,7 +1718,6 @@ static int __devinit max1363_probe(struct i2c_client *client,
st->indio_dev->attrs = st->chip_info->dev_attrs;
/* Todo: this shouldn't be here. */
- st->indio_dev->scan_el_attrs = st->chip_info->scan_attrs;
st->indio_dev->dev_data = (void *)(st);
st->indio_dev->driver_module = THIS_MODULE;
st->indio_dev->modes = INDIO_DIRECT_MODE;
diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c
index 786b17a..5532f3e 100644
--- a/drivers/staging/iio/adc/max1363_ring.c
+++ b/drivers/staging/iio/adc/max1363_ring.c
@@ -30,22 +30,20 @@
/* Todo: test this */
int max1363_single_channel_from_ring(long mask, struct max1363_state *st)
{
- unsigned long numvals;
+ struct iio_ring_buffer *ring = st->indio_dev->ring;
int count = 0, ret;
u8 *ring_data;
if (!(st->current_mode->modemask & mask)) {
ret = -EBUSY;
goto error_ret;
}
- numvals = hweight_long(st->current_mode->modemask);
- ring_data = kmalloc(numvals*2, GFP_KERNEL);
+ ring_data = kmalloc(ring->access.get_bytes_per_datum(ring), GFP_KERNEL);
if (ring_data == NULL) {
ret = -ENOMEM;
goto error_ret;
}
- ret = st->indio_dev->ring->access.read_last(st->indio_dev->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 */
@@ -77,6 +75,7 @@ error_ret:
static int max1363_ring_preenable(struct iio_dev *indio_dev)
{
struct max1363_state *st = indio_dev->dev_data;
+ struct iio_ring_buffer *ring = indio_dev->ring;
size_t d_size;
unsigned long numvals;
@@ -84,7 +83,7 @@ static int max1363_ring_preenable(struct iio_dev *indio_dev)
* Need to figure out the current mode based upon the requested
* scan mask in iio_dev
*/
- st->current_mode = max1363_match_mode(st->indio_dev->scan_mask,
+ st->current_mode = max1363_match_mode(ring->scan_mask,
st->chip_info);
if (!st->current_mode)
return -EINVAL;
@@ -92,14 +91,14 @@ static int max1363_ring_preenable(struct iio_dev *indio_dev)
max1363_set_scan_mode(st);
numvals = hweight_long(st->current_mode->modemask);
- if (indio_dev->ring->access.set_bpd) {
+ if (ring->access.set_bytes_per_datum) {
if (st->chip_info->bits != 8)
d_size = numvals*2 + sizeof(s64);
else
d_size = numvals + sizeof(s64);
if (d_size % 8)
d_size += 8 - (d_size % 8);
- indio_dev->ring->access.set_bpd(indio_dev->ring, d_size);
+ ring->access.set_bytes_per_datum(ring, d_size);
}
return 0;
@@ -135,7 +134,7 @@ 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 *ring = iio_to_sw_ring(indio_dev->ring);
+ struct iio_sw_ring_buffer *sw_ring = iio_to_sw_ring(indio_dev->ring);
s64 time_ns;
__u8 *rxbuf;
int b_sent;
@@ -175,7 +174,7 @@ 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(&ring->buf, rxbuf, time_ns);
+ indio_dev->ring->access.store_to(&sw_ring->buf, rxbuf, time_ns);
done:
kfree(rxbuf);
atomic_dec(&st->protect_ring);
@@ -193,12 +192,13 @@ int max1363_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);
+ iio_ring_sw_register_funcs(&indio_dev->ring->access);
ret = iio_alloc_pollfunc(indio_dev, NULL, &max1363_poll_func_th);
if (ret)
goto error_deallocate_sw_rb;
/* 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;
diff --git a/drivers/staging/iio/chrdev.h b/drivers/staging/iio/chrdev.h
index fd23bd1..98d1a2c 100644
--- a/drivers/staging/iio/chrdev.h
+++ b/drivers/staging/iio/chrdev.h
@@ -73,7 +73,6 @@ 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
- * @attr: this chrdev's minor number sysfs attribute
* @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
@@ -88,7 +87,6 @@ struct iio_event_interface {
struct iio_detected_event_list det_events;
int max_events;
int current_events;
- struct iio_chrdev_minor_attr attr;
struct module *owner;
void *private;
char _name[35];
diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c
index 134dfaa..7d7716e 100644
--- a/drivers/staging/iio/gyro/adis16260_core.c
+++ b/drivers/staging/iio/gyro/adis16260_core.c
@@ -442,29 +442,30 @@ err_ret:
return ret;
}
-static IIO_DEV_ATTR_IN_NAMED_RAW(supply,
+static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply,
adis16260_read_12bit_unsigned,
ADIS16260_SUPPLY_OUT);
-static IIO_CONST_ATTR(in_supply_scale, "0.0018315");
+static IIO_CONST_ATTR_IN_NAMED_SCALE(0, supply, "0.0018315");
static IIO_DEV_ATTR_GYRO(adis16260_read_14bit_signed,
ADIS16260_GYRO_OUT);
-static IIO_DEV_ATTR_GYRO_SCALE(S_IWUSR | S_IRUGO,
+static IIO_CONST_ATTR_GYRO_SCALE("0.00127862821");
+static IIO_DEV_ATTR_GYRO_CALIBSCALE(S_IWUSR | S_IRUGO,
adis16260_read_14bit_signed,
adis16260_write_16bit,
ADIS16260_GYRO_SCALE);
-static IIO_DEV_ATTR_GYRO_OFFSET(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_GYRO_CALIBBIAS(S_IWUSR | S_IRUGO,
adis16260_read_12bit_signed,
adis16260_write_16bit,
ADIS16260_GYRO_OFF);
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_CONST_ATTR_TEMP_OFFSET("25");
+static IIO_CONST_ATTR_TEMP_SCALE("0.1453");
-static IIO_DEV_ATTR_IN_RAW(0, adis16260_read_12bit_unsigned,
+static IIO_DEV_ATTR_IN_RAW(1, adis16260_read_12bit_unsigned,
ADIS16260_AUX_ADC);
-static IIO_CONST_ATTR(in0_scale, "0.0006105");
+static IIO_CONST_ATTR(in1_scale, "0.0006105");
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
adis16260_read_frequency,
@@ -474,9 +475,9 @@ static IIO_DEV_ATTR_ANGL(adis16260_read_14bit_signed,
static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16260_write_reset, 0);
-static IIO_CONST_ATTR_AVAIL_SAMP_FREQ("256 2048");
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("256 2048");
-static IIO_CONST_ATTR(name, "adis16260");
+static IIO_CONST_ATTR_NAME("adis16260");
static struct attribute *adis16260_event_attributes[] = {
NULL
@@ -487,19 +488,20 @@ static struct attribute_group adis16260_event_attribute_group = {
};
static struct attribute *adis16260_attributes[] = {
- &iio_dev_attr_in_supply_raw.dev_attr.attr,
- &iio_const_attr_in_supply_scale.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_raw.dev_attr.attr,
- &iio_dev_attr_gyro_scale.dev_attr.attr,
- &iio_dev_attr_gyro_offset.dev_attr.attr,
+ &iio_const_attr_gyro_scale.dev_attr.attr,
+ &iio_dev_attr_gyro_calibscale.dev_attr.attr,
+ &iio_dev_attr_gyro_calibbias.dev_attr.attr,
&iio_dev_attr_angl_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_in0_raw.dev_attr.attr,
- &iio_const_attr_in0_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_available_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
diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c
index 9ef7f90..2342889 100644
--- a/drivers/staging/iio/gyro/adis16260_ring.c
+++ b/drivers/staging/iio/gyro/adis16260_ring.c
@@ -17,26 +17,39 @@
#include "../trigger.h"
#include "adis16260.h"
-static IIO_SCAN_EL_C(supply, ADIS16260_SCAN_SUPPLY, IIO_UNSIGNED(12),
+static IIO_SCAN_EL_C(in_supply, ADIS16260_SCAN_SUPPLY,
ADIS16260_SUPPLY_OUT, NULL);
-static IIO_SCAN_EL_C(gyro, ADIS16260_SCAN_GYRO, IIO_SIGNED(14),
- ADIS16260_GYRO_OUT, NULL);
-static IIO_SCAN_EL_C(aux_adc, ADIS16260_SCAN_AUX_ADC, IIO_SIGNED(14),
- ADIS16260_AUX_ADC, NULL);
-static IIO_SCAN_EL_C(temp, ADIS16260_SCAN_TEMP, IIO_UNSIGNED(12),
- ADIS16260_TEMP_OUT, NULL);
-static IIO_SCAN_EL_C(angl, ADIS16260_SCAN_ANGL, IIO_UNSIGNED(12),
- ADIS16260_ANGL_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_supply.dev_attr.attr,
+ &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_scan_el_aux_adc.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,
};
@@ -110,11 +123,11 @@ static void adis16260_trigger_bh_to_ring(struct work_struct *work_s)
struct adis16260_state *st
= container_of(work_s, struct adis16260_state,
work_trigger_to_ring);
+ struct iio_ring_buffer *ring = st->indio_dev->ring;
int i = 0;
s16 *data;
- size_t datasize = st->indio_dev
- ->ring->access.get_bpd(st->indio_dev->ring);
+ size_t datasize = ring->access.get_bytes_per_datum(ring);
data = kmalloc(datasize , GFP_KERNEL);
if (data == NULL) {
@@ -122,17 +135,17 @@ static void adis16260_trigger_bh_to_ring(struct work_struct *work_s)
return;
}
- if (st->indio_dev->scan_count)
+ if (ring->scan_count)
if (adis16260_read_ring_data(&st->indio_dev->dev, st->rx) >= 0)
- for (; i < st->indio_dev->scan_count; i++)
+ 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 (st->indio_dev->scan_timestamp)
+ if (ring->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
- st->indio_dev->ring->access.store_to(st->indio_dev->ring,
+ ring->access.store_to(ring,
(u8 *)data,
st->last_timestamp);
@@ -154,16 +167,6 @@ int adis16260_configure_ring(struct iio_dev *indio_dev)
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);
- /* Set default scan mode */
-
- iio_scan_mask_set(indio_dev, iio_scan_el_supply.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_gyro.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_aux_adc.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_temp.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_angl.number);
- indio_dev->scan_timestamp = true;
-
- indio_dev->scan_el_attrs = &adis16260_scan_el_group;
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
@@ -174,11 +177,20 @@ int adis16260_configure_ring(struct iio_dev *indio_dev)
/* Effectively select the ring buffer implementation */
iio_ring_sw_register_funcs(&ring->access);
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->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)
goto error_iio_sw_rb_free;
diff --git a/drivers/staging/iio/gyro/adis16260_trigger.c b/drivers/staging/iio/gyro/adis16260_trigger.c
index de01537..4a744c1 100644
--- a/drivers/staging/iio/gyro/adis16260_trigger.c
+++ b/drivers/staging/iio/gyro/adis16260_trigger.c
@@ -30,7 +30,7 @@ static int adis16260_data_rdy_trig_poll(struct iio_dev *dev_info,
IIO_EVENT_SH(data_rdy_trig, &adis16260_data_rdy_trig_poll);
-static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
+static IIO_TRIGGER_NAME_ATTR;
static struct attribute *adis16260_trigger_attrs[] = {
&dev_attr_name.attr,
diff --git a/drivers/staging/iio/gyro/gyro.h b/drivers/staging/iio/gyro/gyro.h
index f68edab..98b837b 100644
--- a/drivers/staging/iio/gyro/gyro.h
+++ b/drivers/staging/iio/gyro/gyro.h
@@ -3,6 +3,9 @@
/* Gyroscope types of attribute */
+#define IIO_CONST_ATTR_GYRO_OFFSET(_string) \
+ IIO_CONST_ATTR(gyro_offset, _string)
+
#define IIO_DEV_ATTR_GYRO_OFFSET(_mode, _show, _store, _addr) \
IIO_DEVICE_ATTR(gyro_offset, _mode, _show, _store, _addr)
@@ -15,18 +18,45 @@
#define IIO_DEV_ATTR_GYRO_Z_OFFSET(_mode, _show, _store, _addr) \
IIO_DEVICE_ATTR(gyro_z_offset, _mode, _show, _store, _addr)
-#define IIO_DEV_ATTR_GYRO_X_GAIN(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(gyro_x_gain, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_GYRO_Y_GAIN(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(gyro_y_gain, _mode, _show, _store, _addr)
-
-#define IIO_DEV_ATTR_GYRO_Z_GAIN(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(gyro_z_gain, _mode, _show, _store, _addr)
+#define IIO_CONST_ATTR_GYRO_SCALE(_string) \
+ IIO_CONST_ATTR(gyro_scale, _string)
#define IIO_DEV_ATTR_GYRO_SCALE(_mode, _show, _store, _addr) \
IIO_DEVICE_ATTR(gyro_scale, S_IRUGO, _show, _store, _addr)
+#define IIO_DEV_ATTR_GYRO_X_SCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(gyro_x_scale, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO_Y_SCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(gyro_y_scale, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO_Z_SCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(gyro_z_scale, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO_CALIBBIAS(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(gyro_calibbias, S_IRUGO, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO_X_CALIBBIAS(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(gyro_x_calibbias, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO_Y_CALIBBIAS(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(gyro_y_calibbias, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO_Z_CALIBBIAS(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(gyro_z_calibbias, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO_CALIBSCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(gyro_calibscale, S_IRUGO, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO_X_CALIBSCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(gyro_x_calibscale, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO_Y_CALIBSCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(gyro_y_calibscale, _mode, _show, _store, _addr)
+
+#define IIO_DEV_ATTR_GYRO_Z_CALIBSCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(gyro_z_calibscale, _mode, _show, _store, _addr)
+
#define IIO_DEV_ATTR_GYRO(_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 9d0ca12..248bdd2 100644
--- a/drivers/staging/iio/iio.h
+++ b/drivers/staging/iio/iio.h
@@ -90,12 +90,7 @@ void iio_remove_event_from_list(struct iio_event_handler_list *el,
* @ring: [DRIVER] any ring buffer present
* @mlock: [INTERN] lock used to prevent simultaneous device state
* changes
- * @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
* @available_scan_masks: [DRIVER] optional array of allowed bitmasks
- * @scan_timestamp: [INTERN] does the scan mode include a timestamp
* @trig: [INTERN] current device trigger (ring buffer modes)
* @pollfunc: [DRIVER] function run on trigger being recieved
**/
@@ -118,104 +113,11 @@ struct iio_dev {
struct iio_ring_buffer *ring;
struct mutex mlock;
- struct attribute_group *scan_el_attrs;
- int scan_count;
-
- u32 scan_mask;
u32 *available_scan_masks;
- bool scan_timestamp;
struct iio_trigger *trig;
struct iio_poll_func *pollfunc;
};
-/*
- * These are mainly provided to allow for a change of implementation if a device
- * has a large number of scan elements
- */
-#define IIO_MAX_SCAN_LENGTH 31
-
-/* note 0 used as error indicator as it doesn't make sense. */
-static inline u32 iio_scan_mask_match(u32 *av_masks, u32 mask)
-{
- while (*av_masks) {
- if (!(~*av_masks & mask))
- return *av_masks;
- av_masks++;
- }
- return 0;
-}
-
-static inline int iio_scan_mask_query(struct iio_dev *dev_info, int bit)
-{
- u32 mask;
-
- if (bit > IIO_MAX_SCAN_LENGTH)
- return -EINVAL;
-
- if (!dev_info->scan_mask)
- return 0;
-
- if (dev_info->available_scan_masks)
- mask = iio_scan_mask_match(dev_info->available_scan_masks,
- dev_info->scan_mask);
- else
- mask = dev_info->scan_mask;
-
- if (!mask)
- return -EINVAL;
-
- return !!(mask & (1 << bit));
-};
-
-static inline int iio_scan_mask_set(struct iio_dev *dev_info, int bit)
-{
- u32 mask;
- u32 trialmask = dev_info->scan_mask | (1 << bit);
-
- if (bit > IIO_MAX_SCAN_LENGTH)
- return -EINVAL;
- if (dev_info->available_scan_masks) {
- mask = iio_scan_mask_match(dev_info->available_scan_masks,
- trialmask);
- if (!mask)
- return -EINVAL;
- }
- dev_info->scan_mask = trialmask;
- dev_info->scan_count++;
-
- return 0;
-};
-
-static inline int iio_scan_mask_clear(struct iio_dev *dev_info, int bit)
-{
- if (bit > IIO_MAX_SCAN_LENGTH)
- return -EINVAL;
- dev_info->scan_mask &= ~(1 << bit);
- dev_info->scan_count--;
- return 0;
-};
-
-/**
- * iio_scan_mask_count_to_right() - how many scan elements occur before here
- * @dev_info: the iio_device whose scan mode we are querying
- * @bit: which number scan element is this
- **/
-static inline int iio_scan_mask_count_to_right(struct iio_dev *dev_info,
- int bit)
-{
- int count = 0;
- int mask = (1 << bit);
- if (bit > IIO_MAX_SCAN_LENGTH)
- return -EINVAL;
- while (mask) {
- mask >>= 1;
- if (mask & dev_info->scan_mask)
- count++;
- }
-
- return count;
-}
-
/**
* iio_device_register() - register a device with the IIO subsystem
* @dev_info: Device structure filled by the device driver
@@ -233,7 +135,7 @@ void iio_device_unregister(struct iio_dev *dev_info);
* physical interrupt lines
* @dev_info: the iio device for which the is an interrupt line
* @line_number: associated line number
- * @id: idr allocated unique id 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
@@ -400,8 +302,8 @@ static inline bool iio_ring_enabled(struct iio_dev *dev_info)
| INDIO_RING_HARDWARE_BUFFER);
};
-struct idr;
+struct ida;
-int iio_get_new_idr_val(struct idr *this_idr);
-void iio_free_idr_val(struct idr *this_idr, int id);
+int iio_get_new_ida_val(struct ida *this_ida);
+void iio_free_ida_val(struct ida *this_ida, int id);
#endif /* _INDUSTRIAL_IO_H_ */
diff --git a/drivers/staging/iio/imu/adis16300_core.c b/drivers/staging/iio/imu/adis16300_core.c
index f1950d5..7ad13f4 100644
--- a/drivers/staging/iio/imu/adis16300_core.c
+++ b/drivers/staging/iio/imu/adis16300_core.c
@@ -503,28 +503,33 @@ err_ret:
return ret;
}
-static IIO_DEV_ATTR_ACCEL_X_OFFSET(S_IWUSR | S_IRUGO,
+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_OFFSET(S_IWUSR | S_IRUGO,
+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_OFFSET(S_IWUSR | S_IRUGO,
+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(supply, adis16300_read_14bit_unsigned,
+static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16300_read_14bit_unsigned,
ADIS16300_SUPPLY_OUT);
-static IIO_CONST_ATTR(in_supply_scale, "0.00242");
+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.05 deg/s");
+static IIO_CONST_ATTR_GYRO_SCALE("0.000872664");
static IIO_DEV_ATTR_ACCEL_X(adis16300_read_14bit_signed,
ADIS16300_XACCL_OUT);
@@ -532,21 +537,21 @@ static IIO_DEV_ATTR_ACCEL_Y(adis16300_read_14bit_signed,
ADIS16300_YACCL_OUT);
static IIO_DEV_ATTR_ACCEL_Z(adis16300_read_14bit_signed,
ADIS16300_ZACCL_OUT);
-static IIO_CONST_ATTR(accel_scale, "0.0006 g");
+static IIO_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.044 d");
+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 K");
-static IIO_CONST_ATTR(temp_scale, "0.14 K");
+static IIO_CONST_ATTR_TEMP_OFFSET("198.16");
+static IIO_CONST_ATTR_TEMP_SCALE("0.14");
-static IIO_DEV_ATTR_IN_RAW(0, adis16300_read_12bit_unsigned,
+static IIO_DEV_ATTR_IN_RAW(1, adis16300_read_12bit_unsigned,
ADIS16300_AUX_ADC);
-static IIO_CONST_ATTR(in0_scale, "0.000806");
+static IIO_CONST_ATTR(in1_scale, "0.000806");
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
adis16300_read_frequency,
@@ -554,9 +559,9 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16300_write_reset, 0);
-static IIO_CONST_ATTR_AVAIL_SAMP_FREQ("409 546 819 1638");
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("409 546 819 1638");
-static IIO_CONST_ATTR(name, "adis16300");
+static IIO_CONST_ATTR_NAME("adis16300");
static struct attribute *adis16300_event_attributes[] = {
NULL
@@ -567,11 +572,12 @@ static struct attribute_group adis16300_event_attribute_group = {
};
static struct attribute *adis16300_attributes[] = {
- &iio_dev_attr_accel_x_offset.dev_attr.attr,
- &iio_dev_attr_accel_y_offset.dev_attr.attr,
- &iio_dev_attr_accel_z_offset.dev_attr.attr,
- &iio_dev_attr_in_supply_raw.dev_attr.attr,
- &iio_const_attr_in_supply_scale.dev_attr.attr,
+ &iio_dev_attr_gyro_x_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,
@@ -584,10 +590,10 @@ static struct attribute *adis16300_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_in0_raw.dev_attr.attr,
- &iio_const_attr_in0_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_available_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
diff --git a/drivers/staging/iio/imu/adis16300_ring.c b/drivers/staging/iio/imu/adis16300_ring.c
index fc93160..114fdf4 100644
--- a/drivers/staging/iio/imu/adis16300_ring.c
+++ b/drivers/staging/iio/imu/adis16300_ring.c
@@ -17,42 +17,60 @@
#include "../trigger.h"
#include "adis16300.h"
-static IIO_SCAN_EL_C(supply, ADIS16300_SCAN_SUPPLY, IIO_UNSIGNED(14),
+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(gyro_x, ADIS16300_SCAN_GYRO_X, IIO_SIGNED(14),
- ADIS16300_XGYRO_OUT, NULL);
+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(accel_x, ADIS16300_SCAN_ACC_X, IIO_SIGNED(14),
- ADIS16300_XACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_y, ADIS16300_SCAN_ACC_Y, IIO_SIGNED(14),
- ADIS16300_YACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_z, ADIS16300_SCAN_ACC_Z, IIO_SIGNED(14),
- ADIS16300_ZACCL_OUT, NULL);
+static IIO_SCAN_EL_C(temp, ADIS16300_SCAN_TEMP, ADIS16300_TEMP_OUT, NULL);
+static IIO_CONST_ATTR_SCAN_EL_TYPE(temp, s, 12, 16);
-static IIO_SCAN_EL_C(temp, ADIS16300_SCAN_TEMP, IIO_UNSIGNED(12),
- ADIS16300_TEMP_OUT, NULL);
-static IIO_SCAN_EL_C(adc_0, ADIS16300_SCAN_ADC_0, IIO_UNSIGNED(12),
- ADIS16300_AUX_ADC, NULL);
+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, IIO_SIGNED(12),
+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, IIO_SIGNED(12),
+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_supply.dev_attr.attr,
+ &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_scan_el_adc_0.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,
};
@@ -134,11 +152,11 @@ 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 = st->indio_dev
- ->ring->access.get_bpd(st->indio_dev->ring);
+ size_t datasize = ring->access.get_bytes_per_datum(ring);
data = kmalloc(datasize , GFP_KERNEL);
if (data == NULL) {
@@ -146,19 +164,19 @@ static void adis16300_trigger_bh_to_ring(struct work_struct *work_s)
return;
}
- if (st->indio_dev->scan_count)
+ if (ring->scan_count)
if (adis16300_spi_read_burst(&st->indio_dev->dev, st->rx) >= 0)
- for (; i < st->indio_dev->scan_count; i++)
+ 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 (st->indio_dev->scan_timestamp)
+ if (ring->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
- st->indio_dev->ring->access.store_to(st->indio_dev->ring,
- (u8 *)data,
- st->last_timestamp);
+ ring->access.store_to(ring,
+ (u8 *)data,
+ st->last_timestamp);
iio_trigger_notify_done(st->indio_dev->trig);
kfree(data);
@@ -178,20 +196,6 @@ int adis16300_configure_ring(struct iio_dev *indio_dev)
struct adis16300_state *st = indio_dev->dev_data;
struct iio_ring_buffer *ring;
INIT_WORK(&st->work_trigger_to_ring, adis16300_trigger_bh_to_ring);
- /* Set default scan mode */
-
- iio_scan_mask_set(indio_dev, iio_scan_el_supply.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_gyro_x.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_accel_x.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_accel_y.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_accel_z.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_temp.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_adc_0.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_incli_x.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_incli_y.number);
- indio_dev->scan_timestamp = true;
-
- indio_dev->scan_el_attrs = &adis16300_scan_el_group;
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
@@ -202,11 +206,24 @@ int adis16300_configure_ring(struct iio_dev *indio_dev)
/* 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;
diff --git a/drivers/staging/iio/imu/adis16300_trigger.c b/drivers/staging/iio/imu/adis16300_trigger.c
index 64036cd..d6677b6 100644
--- a/drivers/staging/iio/imu/adis16300_trigger.c
+++ b/drivers/staging/iio/imu/adis16300_trigger.c
@@ -30,7 +30,7 @@ static int adis16300_data_rdy_trig_poll(struct iio_dev *dev_info,
IIO_EVENT_SH(data_rdy_trig, &adis16300_data_rdy_trig_poll);
-static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
+static IIO_TRIGGER_NAME_ATTR;
static struct attribute *adis16300_trigger_attrs[] = {
&dev_attr_name.attr,
diff --git a/drivers/staging/iio/imu/adis16350_core.c b/drivers/staging/iio/imu/adis16350_core.c
index 1575b7b..97c1ec8 100644
--- a/drivers/staging/iio/imu/adis16350_core.c
+++ b/drivers/staging/iio/imu/adis16350_core.c
@@ -475,24 +475,39 @@ err_ret:
return ret;
}
-static IIO_DEV_ATTR_ACCEL_X_OFFSET(S_IWUSR | S_IRUGO,
+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_OFFSET(S_IWUSR | S_IRUGO,
+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_OFFSET(S_IWUSR | S_IRUGO,
+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(supply, adis16350_read_12bit_unsigned,
+static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16350_read_12bit_unsigned,
ADIS16350_SUPPLY_OUT);
-static IIO_CONST_ATTR(in_supply_scale, "0.002418");
+static IIO_CONST_ATTR_IN_NAMED_SCALE(0, supply, "0.002418");
static IIO_DEV_ATTR_GYRO_X(adis16350_read_14bit_signed,
ADIS16350_XGYRO_OUT);
@@ -500,7 +515,7 @@ 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.05");
+static IIO_CONST_ATTR_GYRO_SCALE("0.00127862821");
static IIO_DEV_ATTR_ACCEL_X(adis16350_read_14bit_signed,
ADIS16350_XACCL_OUT);
@@ -508,7 +523,7 @@ 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.00333");
+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);
@@ -516,11 +531,12 @@ 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.0005");
+static IIO_CONST_ATTR_TEMP_SCALE("0.14534");
+static IIO_CONST_ATTR_TEMP_OFFSET("198.16");
-static IIO_DEV_ATTR_IN_RAW(0, adis16350_read_12bit_unsigned,
+static IIO_DEV_ATTR_IN_RAW(1, adis16350_read_12bit_unsigned,
ADIS16350_AUX_ADC);
-static IIO_CONST_ATTR(in0_scale, "0.000806");
+static IIO_CONST_ATTR(in1_scale, "0.000806");
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
adis16350_read_frequency,
@@ -529,16 +545,19 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL,
adis16350_write_reset, 0);
-static IIO_CONST_ATTR_AVAIL_SAMP_FREQ("409 546 819 1638");
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("409 546 819 1638");
-static IIO_CONST_ATTR(name, "adis16350");
+static IIO_CONST_ATTR_NAME("adis16350");
static struct attribute *adis16350_attributes[] = {
- &iio_dev_attr_accel_x_offset.dev_attr.attr,
- &iio_dev_attr_accel_y_offset.dev_attr.attr,
- &iio_dev_attr_accel_z_offset.dev_attr.attr,
- &iio_dev_attr_in_supply_raw.dev_attr.attr,
- &iio_const_attr_in_supply_scale.dev_attr.attr,
+ &iio_dev_attr_gyro_x_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,
@@ -551,10 +570,10 @@ static struct attribute *adis16350_attributes[] = {
&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_dev_attr_in0_raw.dev_attr.attr,
- &iio_const_attr_in0_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_available_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
diff --git a/drivers/staging/iio/imu/adis16350_ring.c b/drivers/staging/iio/imu/adis16350_ring.c
index e053e9a..56b70cf 100644
--- a/drivers/staging/iio/imu/adis16350_ring.c
+++ b/drivers/staging/iio/imu/adis16350_ring.c
@@ -17,48 +17,62 @@
#include "../trigger.h"
#include "adis16350.h"
-static IIO_SCAN_EL_C(supply, ADIS16350_SCAN_SUPPLY, IIO_UNSIGNED(12),
+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, IIO_SIGNED(14),
- ADIS16350_XGYRO_OUT, NULL);
-static IIO_SCAN_EL_C(gyro_y, ADIS16350_SCAN_GYRO_Y, IIO_SIGNED(14),
- ADIS16350_YGYRO_OUT, NULL);
-static IIO_SCAN_EL_C(gyro_z, ADIS16350_SCAN_GYRO_Z, IIO_SIGNED(14),
- ADIS16350_ZGYRO_OUT, NULL);
-
-static IIO_SCAN_EL_C(accel_x, ADIS16350_SCAN_ACC_X, IIO_SIGNED(14),
- ADIS16350_XACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_y, ADIS16350_SCAN_ACC_Y, IIO_SIGNED(14),
- ADIS16350_YACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_z, ADIS16350_SCAN_ACC_Z, IIO_SIGNED(14),
- ADIS16350_ZACCL_OUT, NULL);
-
-static IIO_SCAN_EL_C(temp_x, ADIS16350_SCAN_TEMP_X, IIO_SIGNED(12),
- ADIS16350_XTEMP_OUT, NULL);
-static IIO_SCAN_EL_C(temp_y, ADIS16350_SCAN_TEMP_Y, IIO_SIGNED(12),
- ADIS16350_YTEMP_OUT, NULL);
-static IIO_SCAN_EL_C(temp_z, ADIS16350_SCAN_TEMP_Z, IIO_SIGNED(12),
- ADIS16350_ZTEMP_OUT, NULL);
-
-static IIO_SCAN_EL_C(adc_0, ADIS16350_SCAN_ADC_0, IIO_UNSIGNED(12),
- ADIS16350_AUX_ADC, NULL);
+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_supply.dev_attr.attr,
+ &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_scan_el_adc_0.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,
};
@@ -134,11 +148,11 @@ 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 = st->indio_dev
- ->ring->access.get_bpd(st->indio_dev->ring);
+ size_t datasize = ring->access.get_bytes_per_datum(ring);
data = kmalloc(datasize , GFP_KERNEL);
if (data == NULL) {
@@ -146,19 +160,19 @@ static void adis16350_trigger_bh_to_ring(struct work_struct *work_s)
return;
}
- if (st->indio_dev->scan_count)
+ if (ring->scan_count)
if (adis16350_spi_read_burst(&st->indio_dev->dev, st->rx) >= 0)
- for (; i < st->indio_dev->scan_count; i++)
+ 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 (st->indio_dev->scan_timestamp)
+ if (ring->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
- st->indio_dev->ring->access.store_to(st->indio_dev->ring,
- (u8 *)data,
- st->last_timestamp);
+ ring->access.store_to(ring,
+ (u8 *)data,
+ st->last_timestamp);
iio_trigger_notify_done(st->indio_dev->trig);
kfree(data);
@@ -178,22 +192,6 @@ int adis16350_configure_ring(struct iio_dev *indio_dev)
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);
- /* Set default scan mode */
-
- iio_scan_mask_set(indio_dev, iio_scan_el_supply.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_gyro_x.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_gyro_y.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_gyro_z.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_accel_x.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_accel_y.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_accel_z.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_temp_x.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_temp_y.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_temp_z.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_adc_0.number);
- indio_dev->scan_timestamp = true;
-
- indio_dev->scan_el_attrs = &adis16350_scan_el_group;
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
@@ -204,11 +202,26 @@ int adis16350_configure_ring(struct iio_dev *indio_dev)
/* 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;
diff --git a/drivers/staging/iio/imu/adis16350_trigger.c b/drivers/staging/iio/imu/adis16350_trigger.c
index 76edccc..739b7ec 100644
--- a/drivers/staging/iio/imu/adis16350_trigger.c
+++ b/drivers/staging/iio/imu/adis16350_trigger.c
@@ -30,7 +30,7 @@ static int adis16350_data_rdy_trig_poll(struct iio_dev *dev_info,
IIO_EVENT_SH(data_rdy_trig, &adis16350_data_rdy_trig_poll);
-static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
+static IIO_TRIGGER_NAME_ATTR;
static struct attribute *adis16350_trigger_attrs[] = {
&dev_attr_name.attr,
diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
index 6013fee..cfb108a 100644
--- a/drivers/staging/iio/imu/adis16400_core.c
+++ b/drivers/staging/iio/imu/adis16400_core.c
@@ -490,24 +490,24 @@ err_ret:
return ret;
}
-static IIO_DEV_ATTR_ACCEL_X_OFFSET(S_IWUSR | S_IRUGO,
- adis16400_read_12bit_signed,
- adis16400_write_16bit,
- ADIS16400_XACCL_OFF);
-
-static IIO_DEV_ATTR_ACCEL_Y_OFFSET(S_IWUSR | S_IRUGO,
- adis16400_read_12bit_signed,
- adis16400_write_16bit,
- ADIS16400_YACCL_OFF);
-
-static IIO_DEV_ATTR_ACCEL_Z_OFFSET(S_IWUSR | S_IRUGO,
- adis16400_read_12bit_signed,
- adis16400_write_16bit,
- ADIS16400_ZACCL_OFF);
-
-static IIO_DEV_ATTR_IN_NAMED_RAW(supply, adis16400_read_14bit_signed,
+#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_XGYRO_OFF);
+static ADIS16400_DEV_ATTR_CALIBBIAS(GYRO_Z, ADIS16400_XGYRO_OFF);
+
+static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_X, ADIS16400_XACCL_OFF);
+static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_Y, ADIS16400_XACCL_OFF);
+static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_Z, ADIS16400_XACCL_OFF);
+
+
+static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16400_read_14bit_signed,
ADIS16400_SUPPLY_OUT);
-static IIO_CONST_ATTR(in_supply_scale, "0.002418");
+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);
@@ -515,7 +515,7 @@ static IIO_DEV_ATTR_GYRO_Y(adis16400_read_14bit_signed,
ADIS16400_YGYRO_OUT);
static IIO_DEV_ATTR_GYRO_Z(adis16400_read_14bit_signed,
ADIS16400_ZGYRO_OUT);
-static IIO_CONST_ATTR(gyro_scale, "0.05 deg/s");
+static IIO_CONST_ATTR(gyro_scale, "0.0008726646");
static IIO_DEV_ATTR_ACCEL_X(adis16400_read_14bit_signed,
ADIS16400_XACCL_OUT);
@@ -523,7 +523,7 @@ static IIO_DEV_ATTR_ACCEL_Y(adis16400_read_14bit_signed,
ADIS16400_YACCL_OUT);
static IIO_DEV_ATTR_ACCEL_Z(adis16400_read_14bit_signed,
ADIS16400_ZACCL_OUT);
-static IIO_CONST_ATTR(accel_scale, "0.00333 g");
+static IIO_CONST_ATTR(accel_scale, "0.0326561445");
static IIO_DEV_ATTR_MAGN_X(adis16400_read_14bit_signed,
ADIS16400_XMAGN_OUT);
@@ -535,12 +535,12 @@ 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_CONST_ATTR_TEMP_OFFSET("198.16 K");
+static IIO_CONST_ATTR_TEMP_SCALE("0.14 K");
-static IIO_DEV_ATTR_IN_RAW(0, adis16400_read_12bit_unsigned,
+static IIO_DEV_ATTR_IN_RAW(1, adis16400_read_12bit_unsigned,
ADIS16400_AUX_ADC);
-static IIO_CONST_ATTR(in0_scale, "0.000806");
+static IIO_CONST_ATTR(in1_scale, "0.000806 V");
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
adis16400_read_frequency,
@@ -548,9 +548,9 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16400_write_reset, 0);
-static IIO_CONST_ATTR_AVAIL_SAMP_FREQ("409 546 819 1638");
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("409 546 819 1638");
-static IIO_CONST_ATTR(name, "adis16400");
+static IIO_CONST_ATTR_NAME("adis16400");
static struct attribute *adis16400_event_attributes[] = {
NULL
@@ -561,11 +561,14 @@ static struct attribute_group adis16400_event_attribute_group = {
};
static struct attribute *adis16400_attributes[] = {
- &iio_dev_attr_accel_x_offset.dev_attr.attr,
- &iio_dev_attr_accel_y_offset.dev_attr.attr,
- &iio_dev_attr_accel_z_offset.dev_attr.attr,
- &iio_dev_attr_in_supply_raw.dev_attr.attr,
- &iio_const_attr_in_supply_scale.dev_attr.attr,
+ &iio_dev_attr_gyro_x_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,
@@ -581,10 +584,10 @@ static struct attribute *adis16400_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_in0_raw.dev_attr.attr,
- &iio_const_attr_in0_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_available_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
diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c
index 949db76..33293fb 100644
--- a/drivers/staging/iio/imu/adis16400_ring.c
+++ b/drivers/staging/iio/imu/adis16400_ring.c
@@ -17,51 +17,68 @@
#include "../trigger.h"
#include "adis16400.h"
-static IIO_SCAN_EL_C(supply, ADIS16400_SCAN_SUPPLY, IIO_SIGNED(14),
+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, IIO_SIGNED(14),
- ADIS16400_XGYRO_OUT, NULL);
-static IIO_SCAN_EL_C(gyro_y, ADIS16400_SCAN_GYRO_Y, IIO_SIGNED(14),
- ADIS16400_YGYRO_OUT, NULL);
-static IIO_SCAN_EL_C(gyro_z, ADIS16400_SCAN_GYRO_Z, IIO_SIGNED(14),
- ADIS16400_ZGYRO_OUT, NULL);
-
-static IIO_SCAN_EL_C(accel_x, ADIS16400_SCAN_ACC_X, IIO_SIGNED(14),
- ADIS16400_XACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_y, ADIS16400_SCAN_ACC_Y, IIO_SIGNED(14),
- ADIS16400_YACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_z, ADIS16400_SCAN_ACC_Z, IIO_SIGNED(14),
- ADIS16400_ZACCL_OUT, NULL);
-
-static IIO_SCAN_EL_C(magn_x, ADIS16400_SCAN_MAGN_X, IIO_SIGNED(14),
- ADIS16400_XMAGN_OUT, NULL);
-static IIO_SCAN_EL_C(magn_y, ADIS16400_SCAN_MAGN_Y, IIO_SIGNED(14),
- ADIS16400_YMAGN_OUT, NULL);
-static IIO_SCAN_EL_C(magn_z, ADIS16400_SCAN_MAGN_Z, IIO_SIGNED(14),
- ADIS16400_ZMAGN_OUT, NULL);
-
-static IIO_SCAN_EL_C(temp, ADIS16400_SCAN_TEMP, IIO_SIGNED(12),
- ADIS16400_TEMP_OUT, NULL);
-static IIO_SCAN_EL_C(adc_0, ADIS16400_SCAN_ADC_0, IIO_SIGNED(12),
- ADIS16400_AUX_ADC, NULL);
+static IIO_SCAN_EL_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_supply.dev_attr.attr,
+ &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_scan_el_adc_0.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,
};
@@ -143,11 +160,11 @@ static void adis16400_trigger_bh_to_ring(struct work_struct *work_s)
struct adis16400_state *st
= container_of(work_s, struct adis16400_state,
work_trigger_to_ring);
+ struct iio_ring_buffer *ring = st->indio_dev->ring;
int i = 0;
s16 *data;
- size_t datasize = st->indio_dev
- ->ring->access.get_bpd(st->indio_dev->ring);
+ size_t datasize = ring->access.get_bytes_per_datum(ring);
data = kmalloc(datasize , GFP_KERNEL);
if (data == NULL) {
@@ -155,19 +172,19 @@ static void adis16400_trigger_bh_to_ring(struct work_struct *work_s)
return;
}
- if (st->indio_dev->scan_count)
+ if (ring->scan_count)
if (adis16400_spi_read_burst(&st->indio_dev->dev, st->rx) >= 0)
- for (; i < st->indio_dev->scan_count; i++)
+ 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 (st->indio_dev->scan_timestamp)
+ if (ring->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
- st->indio_dev->ring->access.store_to(st->indio_dev->ring,
- (u8 *)data,
- st->last_timestamp);
+ ring->access.store_to(ring,
+ (u8 *) data,
+ st->last_timestamp);
iio_trigger_notify_done(st->indio_dev->trig);
kfree(data);
@@ -187,23 +204,6 @@ int adis16400_configure_ring(struct iio_dev *indio_dev)
struct adis16400_state *st = indio_dev->dev_data;
struct iio_ring_buffer *ring;
INIT_WORK(&st->work_trigger_to_ring, adis16400_trigger_bh_to_ring);
- /* Set default scan mode */
-
- iio_scan_mask_set(indio_dev, iio_scan_el_supply.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_gyro_x.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_gyro_y.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_gyro_z.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_accel_x.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_accel_y.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_accel_z.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_magn_x.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_magn_y.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_magn_z.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_temp.number);
- iio_scan_mask_set(indio_dev, iio_scan_el_adc_0.number);
- indio_dev->scan_timestamp = true;
-
- indio_dev->scan_el_attrs = &adis16400_scan_el_group;
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
@@ -214,11 +214,27 @@ int adis16400_configure_ring(struct iio_dev *indio_dev)
/* Effectively select the ring buffer implementation */
iio_ring_sw_register_funcs(&ring->access);
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->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)
goto error_iio_sw_rb_free;
diff --git a/drivers/staging/iio/imu/adis16400_trigger.c b/drivers/staging/iio/imu/adis16400_trigger.c
index aafe601..36b5ff5 100644
--- a/drivers/staging/iio/imu/adis16400_trigger.c
+++ b/drivers/staging/iio/imu/adis16400_trigger.c
@@ -30,7 +30,7 @@ static int adis16400_data_rdy_trig_poll(struct iio_dev *dev_info,
IIO_EVENT_SH(data_rdy_trig, &adis16400_data_rdy_trig_poll);
-static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
+static IIO_TRIGGER_NAME_ATTR;
static struct attribute *adis16400_trigger_attrs[] = {
&dev_attr_name.attr,
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index 92a212f..f3bf111 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -29,11 +29,11 @@
#define IIO_ID_FORMAT IIO_ID_PREFIX "%d"
/* IDR to assign each registered device a unique id*/
-static DEFINE_IDR(iio_idr);
+static DEFINE_IDA(iio_ida);
/* IDR to allocate character device minor numbers */
-static DEFINE_IDR(iio_chrdev_idr);
+static DEFINE_IDA(iio_chrdev_ida);
/* Lock used to protect both of the above */
-static DEFINE_SPINLOCK(iio_idr_lock);
+static DEFINE_SPINLOCK(iio_ida_lock);
dev_t iio_devt;
EXPORT_SYMBOL(iio_devt);
@@ -59,7 +59,7 @@ EXPORT_SYMBOL(__iio_change_event);
* 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 __iio_push_event(struct iio_event_interface *ev_int,
int ev_code,
s64 timestamp,
struct iio_shared_ev_pointer *
@@ -125,19 +125,10 @@ static irqreturn_t iio_interrupt_handler(int irq, void *_int_info)
}
time_ns = iio_get_time_ns();
- /* detect single element list*/
- if (list_is_singular(&int_info->ev_list)) {
+ list_for_each_entry(p, &int_info->ev_list, list) {
disable_irq_nosync(irq);
- p = list_first_entry(&int_info->ev_list,
- struct iio_event_handler_list,
- list);
- /* single event handler - maybe shared */
p->handler(dev_info, 1, time_ns, !(p->refcount > 1));
- } else
- list_for_each_entry(p, &int_info->ev_list, list) {
- disable_irq_nosync(irq);
- p->handler(dev_info, 1, time_ns, 0);
- }
+ }
spin_unlock_irqrestore(&int_info->ev_list_lock, flags);
return IRQ_HANDLED;
@@ -368,14 +359,14 @@ int iio_device_get_chrdev_minor(void)
{
int ret, val;
-idr_again:
- if (unlikely(idr_pre_get(&iio_chrdev_idr, GFP_KERNEL) == 0))
+ida_again:
+ if (unlikely(ida_pre_get(&iio_chrdev_ida, GFP_KERNEL) == 0))
return -ENOMEM;
- spin_lock(&iio_idr_lock);
- ret = idr_get_new(&iio_chrdev_idr, NULL, &val);
- spin_unlock(&iio_idr_lock);
+ spin_lock(&iio_ida_lock);
+ ret = ida_get_new(&iio_chrdev_ida, &val);
+ spin_unlock(&iio_ida_lock);
if (unlikely(ret == -EAGAIN))
- goto idr_again;
+ goto ida_again;
else if (unlikely(ret))
return ret;
if (val > IIO_DEV_MAX)
@@ -385,9 +376,9 @@ idr_again:
void iio_device_free_chrdev_minor(int val)
{
- spin_lock(&iio_idr_lock);
- idr_remove(&iio_chrdev_idr, val);
- spin_unlock(&iio_idr_lock);
+ spin_lock(&iio_ida_lock);
+ ida_remove(&iio_chrdev_ida, val);
+ spin_unlock(&iio_ida_lock);
}
int iio_setup_ev_int(struct iio_event_interface *ev_int,
@@ -508,62 +499,49 @@ static int iio_device_register_sysfs(struct iio_dev *dev_info)
goto error_ret;
}
- if (dev_info->scan_el_attrs) {
- ret = sysfs_create_group(&dev_info->dev.kobj,
- dev_info->scan_el_attrs);
- if (ret)
- dev_err(&dev_info->dev,
- "Failed to add sysfs scan els\n");
- }
-
error_ret:
return ret;
}
static void iio_device_unregister_sysfs(struct iio_dev *dev_info)
{
- if (dev_info->scan_el_attrs)
- sysfs_remove_group(&dev_info->dev.kobj,
- dev_info->scan_el_attrs);
-
sysfs_remove_group(&dev_info->dev.kobj, dev_info->attrs);
}
/* Return a negative errno on failure */
-int iio_get_new_idr_val(struct idr *this_idr)
+int iio_get_new_ida_val(struct ida *this_ida)
{
int ret;
int val;
-idr_again:
- if (unlikely(idr_pre_get(this_idr, GFP_KERNEL) == 0))
+ida_again:
+ if (unlikely(ida_pre_get(this_ida, GFP_KERNEL) == 0))
return -ENOMEM;
- spin_lock(&iio_idr_lock);
- ret = idr_get_new(this_idr, NULL, &val);
- spin_unlock(&iio_idr_lock);
+ spin_lock(&iio_ida_lock);
+ ret = ida_get_new(this_ida, &val);
+ spin_unlock(&iio_ida_lock);
if (unlikely(ret == -EAGAIN))
- goto idr_again;
+ goto ida_again;
else if (unlikely(ret))
return ret;
return val;
}
-EXPORT_SYMBOL(iio_get_new_idr_val);
+EXPORT_SYMBOL(iio_get_new_ida_val);
-void iio_free_idr_val(struct idr *this_idr, int id)
+void iio_free_ida_val(struct ida *this_ida, int id)
{
- spin_lock(&iio_idr_lock);
- idr_remove(this_idr, id);
- spin_unlock(&iio_idr_lock);
+ spin_lock(&iio_ida_lock);
+ ida_remove(this_ida, id);
+ spin_unlock(&iio_ida_lock);
}
-EXPORT_SYMBOL(iio_free_idr_val);
+EXPORT_SYMBOL(iio_free_ida_val);
static int iio_device_register_id(struct iio_dev *dev_info,
- struct idr *this_idr)
+ struct ida *this_ida)
{
-
- dev_info->id = iio_get_new_idr_val(&iio_idr);
+ dev_info->id = iio_get_new_ida_val(&iio_ida);
if (dev_info->id < 0)
return dev_info->id;
return 0;
@@ -571,7 +549,7 @@ static int iio_device_register_id(struct iio_dev *dev_info,
static void iio_device_unregister_id(struct iio_dev *dev_info)
{
- iio_free_idr_val(&iio_idr, dev_info->id);
+ iio_free_ida_val(&iio_ida, dev_info->id);
}
static inline int __iio_add_event_config_attrs(struct iio_dev *dev_info, int i)
@@ -770,7 +748,7 @@ int iio_device_register(struct iio_dev *dev_info)
{
int ret;
- ret = iio_device_register_id(dev_info, &iio_idr);
+ ret = iio_device_register_id(dev_info, &iio_ida);
if (ret) {
dev_err(&dev_info->dev, "Failed to get id\n");
goto error_ret;
@@ -779,7 +757,7 @@ int iio_device_register(struct iio_dev *dev_info)
ret = device_add(&dev_info->dev);
if (ret)
- goto error_free_idr;
+ goto error_free_ida;
ret = iio_device_register_sysfs(dev_info);
if (ret) {
dev_err(dev_info->dev.parent,
@@ -801,7 +779,7 @@ error_free_sysfs:
iio_device_unregister_sysfs(dev_info);
error_del_device:
device_del(&dev_info->dev);
-error_free_idr:
+error_free_ida:
iio_device_unregister_id(dev_info);
error_ret:
return ret;
diff --git a/drivers/staging/iio/industrialio-ring.c b/drivers/staging/iio/industrialio-ring.c
index 1c5f672..9a98fcd 100644
--- a/drivers/staging/iio/industrialio-ring.c
+++ b/drivers/staging/iio/industrialio-ring.c
@@ -15,10 +15,8 @@
*/
#include <linux/kernel.h>
#include <linux/device.h>
-#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/poll.h>
-#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/slab.h>
@@ -53,7 +51,7 @@ int iio_push_or_escallate_ring_event(struct iio_ring_buffer *ring_buf,
EXPORT_SYMBOL(iio_push_or_escallate_ring_event);
/**
- * iio_ring_open() chrdev file open for ring buffer access
+ * iio_ring_open() - chrdev file open for ring buffer access
*
* This function relies on all ring buffer implementations having an
* iio_ring_buffer as their first element.
@@ -72,7 +70,7 @@ static int iio_ring_open(struct inode *inode, struct file *filp)
}
/**
- * iio_ring_release() -chrdev file close ring buffer access
+ * iio_ring_release() - chrdev file close ring buffer access
*
* This function relies on all ring buffer implementations having an
* iio_ring_buffer as their first element.
@@ -91,7 +89,7 @@ static int iio_ring_release(struct inode *inode, struct file *filp)
}
/**
- * iio_ring_rip_outer() chrdev read for ring buffer access
+ * iio_ring_rip_outer() - chrdev read for ring buffer access
*
* This function relies on all ring buffer implementations having an
* iio_ring _bufer as their first element.
@@ -107,7 +105,7 @@ static ssize_t iio_ring_rip_outer(struct file *filp, char __user *buf,
return -EINVAL;
copied = rb->access.rip_lots(rb, count, &data, &dead_offset);
- if (copied < 0) {
+ if (copied <= 0) {
ret = copied;
goto error_ret;
}
@@ -137,8 +135,9 @@ static const struct file_operations iio_ring_fileops = {
};
/**
- * __iio_request_ring_buffer_event_chrdev() allocate ring event chrdev
+ * __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
**/
@@ -280,6 +279,16 @@ int iio_ring_buffer_register(struct iio_ring_buffer *ring, int id)
if (ret)
goto error_free_ring_buffer_event_chrdev;
+ if (ring->scan_el_attrs) {
+ ret = sysfs_create_group(&ring->dev.kobj,
+ ring->scan_el_attrs);
+ if (ret) {
+ dev_err(&ring->dev,
+ "Failed to add sysfs scan elements\n");
+ goto error_free_ring_buffer_event_chrdev;
+ }
+ }
+
return ret;
error_free_ring_buffer_event_chrdev:
__iio_free_ring_buffer_event_chrdev(ring);
@@ -292,6 +301,10 @@ EXPORT_SYMBOL(iio_ring_buffer_register);
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);
@@ -313,7 +326,7 @@ ssize_t iio_read_ring_length(struct device *dev,
}
EXPORT_SYMBOL(iio_read_ring_length);
- ssize_t iio_write_ring_length(struct device *dev,
+ssize_t iio_write_ring_length(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len)
@@ -339,20 +352,20 @@ EXPORT_SYMBOL(iio_read_ring_length);
}
EXPORT_SYMBOL(iio_write_ring_length);
-ssize_t iio_read_ring_bps(struct device *dev,
+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_bpd)
+ if (ring->access.get_bytes_per_datum)
len = sprintf(buf, "%d\n",
- ring->access.get_bpd(ring));
+ ring->access.get_bytes_per_datum(ring));
return len;
}
-EXPORT_SYMBOL(iio_read_ring_bps);
+EXPORT_SYMBOL(iio_read_ring_bytes_per_datum);
ssize_t iio_store_ring_enable(struct device *dev,
struct device_attribute *attr,
@@ -466,10 +479,10 @@ ssize_t iio_scan_el_show(struct device *dev,
char *buf)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ 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(indio_dev, this_el->number);
+ ret = iio_scan_mask_query(ring, this_el->number);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", ret);
@@ -483,7 +496,8 @@ ssize_t iio_scan_el_store(struct device *dev,
{
int ret = 0;
bool state;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ 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');
@@ -492,19 +506,17 @@ ssize_t iio_scan_el_store(struct device *dev,
ret = -EBUSY;
goto error_ret;
}
- ret = iio_scan_mask_query(indio_dev, this_el->number);
+ ret = iio_scan_mask_query(ring, this_el->number);
if (ret < 0)
goto error_ret;
if (!state && ret) {
- ret = iio_scan_mask_clear(indio_dev, this_el->number);
+ ret = iio_scan_mask_clear(ring, this_el->number);
if (ret)
goto error_ret;
- indio_dev->scan_count--;
} else if (state && !ret) {
- ret = iio_scan_mask_set(indio_dev, this_el->number);
+ ret = iio_scan_mask_set(ring, this_el->number);
if (ret)
goto error_ret;
- indio_dev->scan_count++;
}
if (this_el->set_state)
ret = this_el->set_state(this_el, indio_dev, state);
@@ -520,8 +532,8 @@ ssize_t iio_scan_el_ts_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- return sprintf(buf, "%d\n", indio_dev->scan_timestamp);
+ struct iio_ring_buffer *ring = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n", ring->scan_timestamp);
}
EXPORT_SYMBOL(iio_scan_el_ts_show);
@@ -531,7 +543,8 @@ ssize_t iio_scan_el_ts_store(struct device *dev,
size_t len)
{
int ret = 0;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ 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);
@@ -539,7 +552,7 @@ ssize_t iio_scan_el_ts_store(struct device *dev,
ret = -EBUSY;
goto error_ret;
}
- indio_dev->scan_timestamp = state;
+ ring->scan_timestamp = state;
error_ret:
mutex_unlock(&indio_dev->mlock);
diff --git a/drivers/staging/iio/light/Kconfig b/drivers/staging/iio/light/Kconfig
index 3ddc478..36d8bbe 100644
--- a/drivers/staging/iio/light/Kconfig
+++ b/drivers/staging/iio/light/Kconfig
@@ -12,3 +12,15 @@ config SENSORS_TSL2563
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
+ default n
+ help
+ If you say yes here you get support for ambient light sensing and
+ proximity infrared sensing from Intersil ISL29018.
+ This driver will provide the measurements of ambient light intensity
+ in lux, proximity infrared sensing and normal infrared sensing.
+ Data from sensor is accessible via sysfs.
+
diff --git a/drivers/staging/iio/light/Makefile b/drivers/staging/iio/light/Makefile
index 30f3300..9142c0e 100644
--- a/drivers/staging/iio/light/Makefile
+++ b/drivers/staging/iio/light/Makefile
@@ -3,3 +3,4 @@
#
obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
+obj-$(CONFIG_SENSORS_ISL29018) += isl29018.o
diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
new file mode 100644
index 0000000..f919cc1
--- /dev/null
+++ b/drivers/staging/iio/light/isl29018.c
@@ -0,0 +1,563 @@
+/*
+ * A iio driver for the light sensor ISL 29018.
+ *
+ * IIO driver for monitoring ambient light intensity in luxi, proximity
+ * sensing and infrared sensing.
+ *
+ * Copyright (c) 2010, NVIDIA 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/module.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include "../iio.h"
+
+#define CONVERSION_TIME_MS 100
+
+#define ISL29018_REG_ADD_COMMAND1 0x00
+#define COMMMAND1_OPMODE_SHIFT 5
+#define COMMMAND1_OPMODE_MASK (7 << COMMMAND1_OPMODE_SHIFT)
+#define COMMMAND1_OPMODE_POWER_DOWN 0
+#define COMMMAND1_OPMODE_ALS_ONCE 1
+#define COMMMAND1_OPMODE_IR_ONCE 2
+#define COMMMAND1_OPMODE_PROX_ONCE 3
+
+#define ISL29018_REG_ADD_COMMANDII 0x01
+#define COMMANDII_RESOLUTION_SHIFT 2
+#define COMMANDII_RESOLUTION_MASK (0x3 << COMMANDII_RESOLUTION_SHIFT)
+
+#define COMMANDII_RANGE_SHIFT 0
+#define COMMANDII_RANGE_MASK (0x3 << COMMANDII_RANGE_SHIFT)
+
+#define COMMANDII_SCHEME_SHIFT 7
+#define COMMANDII_SCHEME_MASK (0x1 << COMMANDII_SCHEME_SHIFT)
+
+#define ISL29018_REG_ADD_DATA_LSB 0x02
+#define ISL29018_REG_ADD_DATA_MSB 0x03
+#define ISL29018_MAX_REGS ISL29018_REG_ADD_DATA_MSB
+
+struct isl29018_chip {
+ struct iio_dev *indio_dev;
+ struct i2c_client *client;
+ struct mutex lock;
+ unsigned int range;
+ unsigned int adc_bit;
+ int prox_scheme;
+ u8 reg_cache[ISL29018_MAX_REGS];
+};
+
+static int isl29018_write_data(struct i2c_client *client, u8 reg,
+ u8 val, u8 mask, u8 shift)
+{
+ u8 regval;
+ int ret = 0;
+ struct isl29018_chip *chip = i2c_get_clientdata(client);
+
+ regval = chip->reg_cache[reg];
+ regval &= ~mask;
+ regval |= val << shift;
+
+ ret = i2c_smbus_write_byte_data(client, reg, regval);
+ if (ret) {
+ dev_err(&client->dev, "Write to device fails status %x\n", ret);
+ return ret;
+ }
+ chip->reg_cache[reg] = regval;
+
+ return 0;
+}
+
+static int isl29018_set_range(struct i2c_client *client, unsigned long range,
+ unsigned int *new_range)
+{
+ static const unsigned long supp_ranges[] = {1000, 4000, 16000, 64000};
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(supp_ranges); ++i) {
+ if (range <= supp_ranges[i]) {
+ *new_range = (unsigned int)supp_ranges[i];
+ break;
+ }
+ }
+
+ if (i >= ARRAY_SIZE(supp_ranges))
+ return -EINVAL;
+
+ return isl29018_write_data(client, ISL29018_REG_ADD_COMMANDII,
+ i, COMMANDII_RANGE_MASK, COMMANDII_RANGE_SHIFT);
+}
+
+static int isl29018_set_resolution(struct i2c_client *client,
+ unsigned long adcbit, unsigned int *conf_adc_bit)
+{
+ static const unsigned long supp_adcbit[] = {16, 12, 8, 4};
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(supp_adcbit); ++i) {
+ if (adcbit >= supp_adcbit[i]) {
+ *conf_adc_bit = (unsigned int)supp_adcbit[i];
+ break;
+ }
+ }
+
+ if (i >= ARRAY_SIZE(supp_adcbit))
+ return -EINVAL;
+
+ return isl29018_write_data(client, ISL29018_REG_ADD_COMMANDII,
+ i, COMMANDII_RESOLUTION_MASK,
+ COMMANDII_RESOLUTION_SHIFT);
+}
+
+static int isl29018_read_sensor_input(struct i2c_client *client, int mode)
+{
+ int status;
+ int lsb;
+ int msb;
+
+ /* Set mode */
+ status = isl29018_write_data(client, ISL29018_REG_ADD_COMMAND1,
+ mode, COMMMAND1_OPMODE_MASK, COMMMAND1_OPMODE_SHIFT);
+ if (status) {
+ dev_err(&client->dev, "Error in setting operating mode\n");
+ return status;
+ }
+ msleep(CONVERSION_TIME_MS);
+ lsb = i2c_smbus_read_byte_data(client, ISL29018_REG_ADD_DATA_LSB);
+ if (lsb < 0) {
+ dev_err(&client->dev, "Error in reading LSB DATA\n");
+ return lsb;
+ }
+
+ msb = i2c_smbus_read_byte_data(client, ISL29018_REG_ADD_DATA_MSB);
+ if (msb < 0) {
+ dev_err(&client->dev, "Error in reading MSB DATA\n");
+ return msb;
+ }
+ dev_vdbg(&client->dev, "MSB 0x%x and LSB 0x%x\n", msb, lsb);
+
+ return (msb << 8) | lsb;
+}
+
+static int isl29018_read_lux(struct i2c_client *client, int *lux)
+{
+ int lux_data;
+ struct isl29018_chip *chip = i2c_get_clientdata(client);
+
+ lux_data = isl29018_read_sensor_input(client,
+ COMMMAND1_OPMODE_ALS_ONCE);
+
+ if (lux_data < 0)
+ return lux_data;
+
+ *lux = (lux_data * chip->range) >> chip->adc_bit;
+
+ return 0;
+}
+
+static int isl29018_read_ir(struct i2c_client *client, int *ir)
+{
+ int ir_data;
+
+ ir_data = isl29018_read_sensor_input(client, COMMMAND1_OPMODE_IR_ONCE);
+
+ if (ir_data < 0)
+ return ir_data;
+
+ *ir = ir_data;
+
+ return 0;
+}
+
+static int isl29018_read_proximity_ir(struct i2c_client *client, int scheme,
+ int *near_ir)
+{
+ int status;
+ int prox_data = -1;
+ int ir_data = -1;
+
+ /* Do proximity sensing with required scheme */
+ status = isl29018_write_data(client, ISL29018_REG_ADD_COMMANDII,
+ scheme, COMMANDII_SCHEME_MASK, COMMANDII_SCHEME_SHIFT);
+ if (status) {
+ dev_err(&client->dev, "Error in setting operating mode\n");
+ return status;
+ }
+
+ prox_data = isl29018_read_sensor_input(client,
+ COMMMAND1_OPMODE_PROX_ONCE);
+ if (prox_data < 0)
+ return prox_data;
+
+ if (scheme == 1) {
+ *near_ir = prox_data;
+ return 0;
+ }
+
+ ir_data = isl29018_read_sensor_input(client,
+ COMMMAND1_OPMODE_IR_ONCE);
+
+ if (ir_data < 0)
+ return ir_data;
+
+ if (prox_data >= ir_data)
+ *near_ir = prox_data - ir_data;
+ else
+ *near_ir = 0;
+
+ return 0;
+}
+
+static ssize_t get_sensor_data(struct device *dev, char *buf, int mode)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct isl29018_chip *chip = indio_dev->dev_data;
+ struct i2c_client *client = chip->client;
+ int value = 0;
+ int status;
+
+ mutex_lock(&chip->lock);
+ switch (mode) {
+ case COMMMAND1_OPMODE_PROX_ONCE:
+ status = isl29018_read_proximity_ir(client,
+ chip->prox_scheme, &value);
+ break;
+
+ case COMMMAND1_OPMODE_ALS_ONCE:
+ status = isl29018_read_lux(client, &value);
+ break;
+
+ case COMMMAND1_OPMODE_IR_ONCE:
+ status = isl29018_read_ir(client, &value);
+ break;
+
+ default:
+ dev_err(&client->dev, "Mode %d is not supported\n", mode);
+ mutex_unlock(&chip->lock);
+ return -EBUSY;
+ }
+ if (status < 0) {
+ dev_err(&client->dev, "Error in Reading data");
+ mutex_unlock(&chip->lock);
+ return status;
+ }
+
+ mutex_unlock(&chip->lock);
+
+ return sprintf(buf, "%d\n", value);
+}
+
+/* Sysfs interface */
+/* range */
+static ssize_t show_range(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, "%u\n", chip->range);
+}
+
+static ssize_t store_range(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct isl29018_chip *chip = indio_dev->dev_data;
+ struct i2c_client *client = chip->client;
+ int status;
+ unsigned long lval;
+ unsigned int new_range;
+
+ if (strict_strtoul(buf, 10, &lval))
+ return -EINVAL;
+
+ if (!(lval == 1000UL || lval == 4000UL ||
+ lval == 16000UL || lval == 64000UL)) {
+ dev_err(dev, "The range is not supported\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&chip->lock);
+ status = isl29018_set_range(client, lval, &new_range);
+ if (status < 0) {
+ mutex_unlock(&chip->lock);
+ dev_err(dev, "Error in setting max range\n");
+ return status;
+ }
+ chip->range = new_range;
+ mutex_unlock(&chip->lock);
+
+ return count;
+}
+
+/* resolution */
+static ssize_t show_resolution(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, "%u\n", chip->adc_bit);
+}
+
+static ssize_t store_resolution(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct isl29018_chip *chip = indio_dev->dev_data;
+ struct i2c_client *client = chip->client;
+ int status;
+ unsigned long lval;
+ unsigned int new_adc_bit;
+
+ if (strict_strtoul(buf, 10, &lval))
+ return -EINVAL;
+ if (!(lval == 4 || lval == 8 || lval == 12 || lval == 16)) {
+ dev_err(dev, "The resolution is not supported\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&chip->lock);
+ status = isl29018_set_resolution(client, lval, &new_adc_bit);
+ if (status < 0) {
+ mutex_unlock(&chip->lock);
+ dev_err(dev, "Error in setting resolution\n");
+ return status;
+ }
+ chip->adc_bit = new_adc_bit;
+ mutex_unlock(&chip->lock);
+
+ return count;
+}
+
+/* proximity scheme */
+static ssize_t show_prox_infrared_supression(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 the "proximity scheme" i.e. if the chip does on chip
+ infrared supression (1 means perform on chip supression) */
+ return sprintf(buf, "%d\n", chip->prox_scheme);
+}
+
+static ssize_t store_prox_infrared_supression(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct isl29018_chip *chip = indio_dev->dev_data;
+ unsigned long lval;
+
+ if (strict_strtoul(buf, 10, &lval))
+ return -EINVAL;
+ if (!(lval == 0UL || lval == 1UL)) {
+ dev_err(dev, "The mode is not supported\n");
+ return -EINVAL;
+ }
+
+ /* get the "proximity scheme" i.e. if the chip does on chip
+ infrared supression (1 means perform on chip supression) */
+ mutex_lock(&chip->lock);
+ chip->prox_scheme = (int)lval;
+ mutex_unlock(&chip->lock);
+
+ return count;
+}
+
+/* Read lux */
+static ssize_t show_lux(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ return get_sensor_data(dev, buf, COMMMAND1_OPMODE_ALS_ONCE);
+}
+
+/* Read ir */
+static ssize_t show_ir(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ return get_sensor_data(dev, buf, COMMMAND1_OPMODE_IR_ONCE);
+}
+
+/* Read nearest ir */
+static ssize_t show_proxim_ir(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ 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");
+static IIO_DEVICE_ATTR(adc_resolution, S_IRUGO | S_IWUSR,
+ show_resolution, store_resolution, 0);
+static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_supression,
+ S_IRUGO | S_IWUSR,
+ show_prox_infrared_supression,
+ store_prox_infrared_supression, 0);
+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),
+ ISL29018_CONST_ATTR(adc_resolution_available),
+ ISL29018_DEV_ATTR(proximity_on_chip_ambient_infrared_supression),
+ ISL29018_DEV_ATTR(illuminance0_input),
+ ISL29018_DEV_ATTR(intensity_infrared_raw),
+ ISL29018_DEV_ATTR(proximity_raw),
+ NULL
+};
+
+static const struct attribute_group isl29108_group = {
+ .attrs = isl29018_attributes,
+};
+
+static int isl29018_chip_init(struct i2c_client *client)
+{
+ struct isl29018_chip *chip = i2c_get_clientdata(client);
+ int status;
+ int new_adc_bit;
+ unsigned int new_range;
+
+ memset(chip->reg_cache, 0, sizeof(chip->reg_cache));
+
+ /* set defaults */
+ status = isl29018_set_range(client, chip->range, &new_range);
+ if (status < 0) {
+ dev_err(&client->dev, "Init of isl29018 fails\n");
+ return status;
+ }
+
+ status = isl29018_set_resolution(client, chip->adc_bit,
+ &new_adc_bit);
+
+ return 0;
+}
+
+static int __devinit isl29018_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct isl29018_chip *chip;
+ int err;
+
+ chip = kzalloc(sizeof(struct isl29018_chip), GFP_KERNEL);
+ if (!chip) {
+ dev_err(&client->dev, "Memory allocation fails\n");
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(client, chip);
+ chip->client = client;
+
+ mutex_init(&chip->lock);
+
+ chip->range = 1000;
+ chip->adc_bit = 16;
+
+ err = isl29018_chip_init(client);
+ if (err)
+ goto exit_free;
+
+ chip->indio_dev = iio_allocate_device();
+ if (!chip->indio_dev) {
+ dev_err(&client->dev, "iio allocation fails\n");
+ goto exit_free;
+ }
+ chip->indio_dev->attrs = &isl29108_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;
+ err = iio_device_register(chip->indio_dev);
+ if (err) {
+ dev_err(&client->dev, "iio registration fails\n");
+ goto exit_iio_free;
+ }
+
+ return 0;
+exit_iio_free:
+ iio_free_device(chip->indio_dev);
+exit_free:
+ kfree(chip);
+exit:
+ return err;
+}
+
+static int __devexit isl29018_remove(struct i2c_client *client)
+{
+ struct isl29018_chip *chip = i2c_get_clientdata(client);
+
+ dev_dbg(&client->dev, "%s()\n", __func__);
+ iio_device_unregister(chip->indio_dev);
+ kfree(chip);
+
+ return 0;
+}
+
+static const struct i2c_device_id isl29018_id[] = {
+ {"isl29018", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, isl29018_id);
+
+static struct i2c_driver isl29018_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "isl29018",
+ .owner = THIS_MODULE,
+ },
+ .probe = isl29018_probe,
+ .remove = __devexit_p(isl29018_remove),
+ .id_table = isl29018_id,
+};
+
+static int __init isl29018_init(void)
+{
+ return i2c_add_driver(&isl29018_driver);
+}
+
+static void __exit isl29018_exit(void)
+{
+ i2c_del_driver(&isl29018_driver);
+}
+
+module_init(isl29018_init);
+module_exit(isl29018_exit);
+
+MODULE_DESCRIPTION("ISL29018 Ambient Light Sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/iio/light/light.h b/drivers/staging/iio/light/light.h
deleted file mode 100644
index e4e1e2c..0000000
--- a/drivers/staging/iio/light/light.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "../sysfs.h"
-
-/* Light to digital sensor attributes */
-
-#define IIO_EVENT_CODE_LIGHT_THRESH IIO_EVENT_CODE_LIGHT_BASE
-
-
diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c
index 98f8b78..dadae75 100644
--- a/drivers/staging/iio/light/tsl2563.c
+++ b/drivers/staging/iio/light/tsl2563.c
@@ -584,14 +584,14 @@ static ssize_t tsl2563_calib_store(struct device *dev,
return len;
}
-static IIO_DEVICE_ATTR(intensity_both_raw, S_IRUGO,
+static IIO_DEVICE_ATTR(intensity0_both_raw, S_IRUGO,
tsl2563_adc_show, NULL, 0);
-static IIO_DEVICE_ATTR(intensity_ir_raw, S_IRUGO,
+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(intensity_both_calibgain, S_IRUGO | S_IWUSR,
+static IIO_DEVICE_ATTR(intensity0_both_calibgain, S_IRUGO | S_IWUSR,
tsl2563_calib_show, tsl2563_calib_store, 0);
-static IIO_DEVICE_ATTR(intensity_ir_calibgain, S_IRUGO | S_IWUSR,
+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,
@@ -606,11 +606,11 @@ static ssize_t tsl2563_show_name(struct device *dev,
static DEVICE_ATTR(name, S_IRUGO, tsl2563_show_name, NULL);
static struct attribute *tsl2563_attributes[] = {
- &iio_dev_attr_intensity_both_raw.dev_attr.attr,
- &iio_dev_attr_intensity_ir_raw.dev_attr.attr,
+ &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_intensity_both_calibgain.dev_attr.attr,
- &iio_dev_attr_intensity_ir_calibgain.dev_attr.attr,
+ &iio_dev_attr_intensity0_both_calibgain.dev_attr.attr,
+ &iio_dev_attr_intensity1_ir_calibgain.dev_attr.attr,
&dev_attr_name.attr,
NULL
};
@@ -673,13 +673,13 @@ error_ret:
return ret < 0 ? ret : len;
}
-static IIO_DEVICE_ATTR(intensity_both_thresh_high_value,
+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(intensity_both_thresh_low_value,
+static IIO_DEVICE_ATTR(intensity0_both_raw_thresh_falling_value,
S_IRUGO | S_IWUSR,
tsl2563_read_thresh,
tsl2563_write_thresh,
@@ -706,8 +706,11 @@ static void tsl2563_int_bh(struct work_struct *work_s)
u8 cmd = TSL2563_CMD | TSL2563_CLEARINT;
iio_push_event(chip->indio_dev, 0,
- IIO_EVENT_CODE_LIGHT_BASE,
- chip->event_timestamp);
+ IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_LIGHT,
+ 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_EITHER),
+ chip->event_timestamp);
/* reenable_irq */
enable_irq(chip->client->irq);
@@ -788,16 +791,16 @@ error_ret:
return (ret < 0) ? ret : len;
}
-IIO_EVENT_ATTR(intensity_both_thresh_both_en,
+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_intensity_both_thresh_both_en.dev_attr.attr,
- &iio_dev_attr_intensity_both_thresh_high_value.dev_attr.attr,
- &iio_dev_attr_intensity_both_thresh_low_value.dev_attr.attr,
+ &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,
};
diff --git a/drivers/staging/iio/magnetometer/Kconfig b/drivers/staging/iio/magnetometer/Kconfig
index d014450..81b579d 100644
--- a/drivers/staging/iio/magnetometer/Kconfig
+++ b/drivers/staging/iio/magnetometer/Kconfig
@@ -3,6 +3,16 @@
#
comment "Magnetometer sensors"
+config SENSORS_AK8975
+ tristate "Asahi Kasei AK8975 3-Axis Magnetometer"
+ depends on I2C
+ help
+ Say yes here to build support for Asahi Kasei AK8975 3-Axis
+ Magnetometer.
+
+ To compile this driver as a module, choose M here: the module
+ will be called ak8975.
+
config SENSORS_HMC5843
tristate "Honeywell HMC5843 3-Axis Magnetometer"
depends on I2C
diff --git a/drivers/staging/iio/magnetometer/Makefile b/drivers/staging/iio/magnetometer/Makefile
index f9bfb2e..f2a753f 100644
--- a/drivers/staging/iio/magnetometer/Makefile
+++ b/drivers/staging/iio/magnetometer/Makefile
@@ -2,4 +2,5 @@
# Makefile for industrial I/O Magnetometer sensors
#
+obj-$(CONFIG_SENSORS_AK8975) += ak8975.o
obj-$(CONFIG_SENSORS_HMC5843) += hmc5843.o
diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c
new file mode 100644
index 0000000..420f206
--- /dev/null
+++ b/drivers/staging/iio/magnetometer/ak8975.c
@@ -0,0 +1,558 @@
+/*
+ * A sensor driver for the magnetometer AK8975.
+ *
+ * Magnetic compass sensor driver for monitoring magnetic flux information.
+ *
+ * Copyright (c) 2010, NVIDIA 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/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#include <linux/gpio.h>
+
+#include "../iio.h"
+#include "magnet.h"
+
+/*
+ * Register definitions, as well as various shifts and masks to get at the
+ * individual fields of the registers.
+ */
+#define AK8975_REG_WIA 0x00
+#define AK8975_DEVICE_ID 0x48
+
+#define AK8975_REG_INFO 0x01
+
+#define AK8975_REG_ST1 0x02
+#define AK8975_REG_ST1_DRDY_SHIFT 0
+#define AK8975_REG_ST1_DRDY_MASK (1 << AK8975_REG_ST1_DRDY_SHIFT)
+
+#define AK8975_REG_HXL 0x03
+#define AK8975_REG_HXH 0x04
+#define AK8975_REG_HYL 0x05
+#define AK8975_REG_HYH 0x06
+#define AK8975_REG_HZL 0x07
+#define AK8975_REG_HZH 0x08
+#define AK8975_REG_ST2 0x09
+#define AK8975_REG_ST2_DERR_SHIFT 2
+#define AK8975_REG_ST2_DERR_MASK (1 << AK8975_REG_ST2_DERR_SHIFT)
+
+#define AK8975_REG_ST2_HOFL_SHIFT 3
+#define AK8975_REG_ST2_HOFL_MASK (1 << AK8975_REG_ST2_HOFL_SHIFT)
+
+#define AK8975_REG_CNTL 0x0A
+#define AK8975_REG_CNTL_MODE_SHIFT 0
+#define AK8975_REG_CNTL_MODE_MASK (0xF << AK8975_REG_CNTL_MODE_SHIFT)
+#define AK8975_REG_CNTL_MODE_POWER_DOWN 0
+#define AK8975_REG_CNTL_MODE_ONCE 1
+#define AK8975_REG_CNTL_MODE_SELF_TEST 8
+#define AK8975_REG_CNTL_MODE_FUSE_ROM 0xF
+
+#define AK8975_REG_RSVC 0x0B
+#define AK8975_REG_ASTC 0x0C
+#define AK8975_REG_TS1 0x0D
+#define AK8975_REG_TS2 0x0E
+#define AK8975_REG_I2CDIS 0x0F
+#define AK8975_REG_ASAX 0x10
+#define AK8975_REG_ASAY 0x11
+#define AK8975_REG_ASAZ 0x12
+
+#define AK8975_MAX_REGS AK8975_REG_ASAZ
+
+/*
+ * Miscellaneous values.
+ */
+#define AK8975_MAX_CONVERSION_TIMEOUT 500
+#define AK8975_CONVERSION_DONE_POLL_TIME 10
+
+/*
+ * Per-instance context data for the device.
+ */
+struct ak8975_data {
+ struct i2c_client *client;
+ struct iio_dev *indio_dev;
+ struct attribute_group attrs;
+ struct mutex lock;
+ u8 asa[3];
+ long raw_to_gauss[3];
+ unsigned long mode;
+ u8 reg_cache[AK8975_MAX_REGS];
+ int eoc_gpio;
+ int eoc_irq;
+};
+
+/*
+ * Helper function to write to the I2C device's registers.
+ */
+static int ak8975_write_data(struct i2c_client *client,
+ u8 reg, u8 val, u8 mask, u8 shift)
+{
+ u8 regval;
+ struct i2c_msg msg;
+ u8 w_data[2];
+ int ret = 0;
+
+ struct ak8975_data *data = i2c_get_clientdata(client);
+
+ regval = data->reg_cache[reg];
+ regval &= ~mask;
+ regval |= val << shift;
+
+ w_data[0] = reg;
+ w_data[1] = regval;
+
+ msg.addr = client->addr;
+ msg.flags = 0;
+ msg.len = 2;
+ msg.buf = w_data;
+
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret < 0) {
+ dev_err(&client->dev, "Write to device fails status %x\n", ret);
+ return ret;
+ }
+ data->reg_cache[reg] = regval;
+
+ return 0;
+}
+
+/*
+ * Helper function to read a contiguous set of the I2C device's registers.
+ */
+static int ak8975_read_data(struct i2c_client *client,
+ u8 reg, u8 length, u8 *buffer)
+{
+ struct i2c_msg msg[2];
+ u8 w_data[2];
+ int ret;
+
+ w_data[0] = reg;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = I2C_M_NOSTART; /* set repeated start and write */
+ msg[0].len = 1;
+ msg[0].buf = w_data;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = length;
+ msg[1].buf = buffer;
+
+ ret = i2c_transfer(client->adapter, msg, 2);
+ if (ret < 0) {
+ dev_err(&client->dev, "Read from device fails\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ * Perform some start-of-day setup, including reading the asa calibration
+ * values and caching them.
+ */
+static int ak8975_setup(struct i2c_client *client)
+{
+ struct ak8975_data *data = i2c_get_clientdata(client);
+ u8 device_id;
+ int ret;
+
+ /* Confirm that the device we're talking to is really an AK8975. */
+ ret = ak8975_read_data(client, AK8975_REG_WIA, 1, &device_id);
+ if (ret < 0) {
+ dev_err(&client->dev, "Error reading WIA\n");
+ return ret;
+ }
+ if (device_id != AK8975_DEVICE_ID) {
+ dev_err(&client->dev, "Device ak8975 not found\n");
+ return -ENODEV;
+ }
+
+ /* Write the fused rom access mode. */
+ ret = ak8975_write_data(client,
+ AK8975_REG_CNTL,
+ AK8975_REG_CNTL_MODE_FUSE_ROM,
+ AK8975_REG_CNTL_MODE_MASK,
+ AK8975_REG_CNTL_MODE_SHIFT);
+ if (ret < 0) {
+ dev_err(&client->dev, "Error in setting fuse access mode\n");
+ return ret;
+ }
+
+ /* Get asa data and store in the device data. */
+ ret = ak8975_read_data(client, AK8975_REG_ASAX, 3, data->asa);
+ if (ret < 0) {
+ dev_err(&client->dev, "Not able to read asa data\n");
+ return ret;
+ }
+
+ /* Precalculate scale factor for each axis and
+ 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;
+
+ return 0;
+}
+
+/*
+ * Shows the device's mode. 0 = off, 1 = on.
+ */
+static ssize_t show_mode(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ak8975_data *data = indio_dev->dev_data;
+
+ return sprintf(buf, "%lu\n", data->mode);
+}
+
+/*
+ * Sets the device's mode. 0 = off, 1 = on. The device's mode must be on
+ * for the magn raw attributes to be available.
+ */
+static ssize_t store_mode(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ak8975_data *data = indio_dev->dev_data;
+ struct i2c_client *client = data->client;
+ unsigned long oval;
+ int ret;
+
+ /* Convert mode string and do some basic sanity checking on it.
+ only 0 or 1 are valid. */
+ if (strict_strtoul(buf, 10, &oval))
+ return -EINVAL;
+
+ if (oval > 1) {
+ dev_err(dev, "mode value is not supported\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&data->lock);
+
+ /* Write the mode to the device. */
+ if (data->mode != oval) {
+ ret = ak8975_write_data(client,
+ AK8975_REG_CNTL,
+ (u8)oval,
+ AK8975_REG_CNTL_MODE_MASK,
+ AK8975_REG_CNTL_MODE_SHIFT);
+
+ if (ret < 0) {
+ dev_err(&client->dev, "Error in setting mode\n");
+ mutex_unlock(&data->lock);
+ return ret;
+ }
+ data->mode = oval;
+ }
+
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+/*
+ * Emits the scale factor to bring the raw value into Gauss units.
+ *
+ * This scale factor is axis-dependent, and is derived from 3 calibration
+ * factors ASA(x), ASA(y), and ASA(z).
+ *
+ * These ASA values are read from the sensor device at start of day, and
+ * cached in the device context struct.
+ *
+ * Adjusting the flux value with the sensitivity adjustment value should be
+ * done via the following formula:
+ *
+ * Hadj = H * ( ( ( (ASA-128)*0.5 ) / 128 ) + 1 )
+ *
+ * where H is the raw value, ASA is the sensitivity adjustment, and Hadj
+ * is the resultant adjusted value.
+ *
+ * We reduce the formula to:
+ *
+ * Hadj = H * (ASA + 128) / 256
+ *
+ * H is in the range of -4096 to 4095. The magnetometer has a range of
+ * +-1229uT. To go from the raw value to uT is:
+ *
+ * HuT = H * 1229/4096, or roughly, 3/10.
+ *
+ * Since 1uT = 100 gauss, our final scale factor becomes:
+ *
+ * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100
+ * Hadj = H * ((ASA + 128) * 30 / 256
+ *
+ * Since ASA doesn't change, we cache the resultant scale factor into the
+ * device context in ak8975_setup().
+ */
+static ssize_t show_scale(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ak8975_data *data = indio_dev->dev_data;
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(devattr);
+
+ return sprintf(buf, "%ld\n", data->raw_to_gauss[this_attr->address]);
+}
+
+/*
+ * Emits the raw flux value for the x, y, or z axis.
+ */
+static ssize_t show_raw(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ 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;
+ int ret;
+
+ mutex_lock(&data->lock);
+
+ if (data->mode == 0) {
+ dev_err(&client->dev, "Operating mode is in power down mode\n");
+ ret = -EBUSY;
+ goto exit;
+ }
+
+ /* Set up the device for taking a sample. */
+ ret = ak8975_write_data(client,
+ AK8975_REG_CNTL,
+ AK8975_REG_CNTL_MODE_ONCE,
+ AK8975_REG_CNTL_MODE_MASK,
+ AK8975_REG_CNTL_MODE_SHIFT);
+ if (ret < 0) {
+ dev_err(&client->dev, "Error in setting operating mode\n");
+ goto exit;
+ }
+
+ /* 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;
+ 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;
+ }
+
+ if (read_status & AK8975_REG_ST1_DRDY_MASK) {
+ ret = ak8975_read_data(client, AK8975_REG_ST2, 1, &read_status);
+ if (ret < 0) {
+ dev_err(&client->dev, "Error in reading ST2\n");
+ goto exit;
+ }
+ if (read_status & (AK8975_REG_ST2_DERR_MASK |
+ AK8975_REG_ST2_HOFL_MASK)) {
+ dev_err(&client->dev, "ST2 status error 0x%x\n",
+ read_status);
+ ret = -EINVAL;
+ goto exit;
+ }
+ }
+
+ /* Read the flux value from the appropriate register
+ (the register is specified in the iio device attributes). */
+ ret = ak8975_read_data(client, this_attr->address, 2, (u8 *)&meas_reg);
+ if (ret < 0) {
+ dev_err(&client->dev, "Read axis data fails\n");
+ goto exit;
+ }
+
+ mutex_unlock(&data->lock);
+
+ /* Endian conversion of the measured values. */
+ raw = (s16) (le16_to_cpu(meas_reg));
+
+ /* Clamp to valid range. */
+ raw = clamp_t(s16, raw, -4096, 4095);
+
+ return sprintf(buf, "%d\n", raw);
+
+exit:
+ mutex_unlock(&data->lock);
+ return ret;
+}
+
+static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, show_mode, store_mode, 0);
+static IIO_DEV_ATTR_MAGN_X_SCALE(S_IRUGO, show_scale, NULL, 0);
+static IIO_DEV_ATTR_MAGN_Y_SCALE(S_IRUGO, show_scale, NULL, 1);
+static IIO_DEV_ATTR_MAGN_Z_SCALE(S_IRUGO, show_scale, NULL, 2);
+static IIO_DEV_ATTR_MAGN_X(show_raw, AK8975_REG_HXL);
+static IIO_DEV_ATTR_MAGN_Y(show_raw, AK8975_REG_HYL);
+static IIO_DEV_ATTR_MAGN_Z(show_raw, AK8975_REG_HZL);
+
+static struct attribute *ak8975_attr[] = {
+ &iio_dev_attr_mode.dev_attr.attr,
+ &iio_dev_attr_magn_x_scale.dev_attr.attr,
+ &iio_dev_attr_magn_y_scale.dev_attr.attr,
+ &iio_dev_attr_magn_z_scale.dev_attr.attr,
+ &iio_dev_attr_magn_x_raw.dev_attr.attr,
+ &iio_dev_attr_magn_y_raw.dev_attr.attr,
+ &iio_dev_attr_magn_z_raw.dev_attr.attr,
+ NULL
+};
+
+static struct attribute_group ak8975_attr_group = {
+ .attrs = ak8975_attr,
+};
+
+static int ak8975_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct ak8975_data *data;
+ int err;
+
+ /* Allocate our device context. */
+ data = kzalloc(sizeof(struct ak8975_data), GFP_KERNEL);
+ if (!data) {
+ dev_err(&client->dev, "Memory allocation fails\n");
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(client, data);
+ data->client = client;
+
+ mutex_init(&data->lock);
+
+ /* Grab and set up the supplied GPIO. */
+ 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;
+ }
+
+ 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;
+ }
+
+ /* Perform some basic start-of-day setup of the device. */
+ err = ak8975_setup(client);
+ if (err < 0) {
+ dev_err(&client->dev, "AK8975 initialization fails\n");
+ goto exit_gpio;
+ }
+
+ /* Register with IIO */
+ data->indio_dev = iio_allocate_device();
+ 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->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 < 0)
+ goto exit_free_iio;
+
+ return 0;
+
+exit_free_iio:
+ iio_free_device(data->indio_dev);
+exit_gpio:
+ gpio_free(data->eoc_gpio);
+exit_free:
+ kfree(data);
+exit:
+ return err;
+}
+
+static int ak8975_remove(struct i2c_client *client)
+{
+ struct ak8975_data *data = i2c_get_clientdata(client);
+
+ iio_device_unregister(data->indio_dev);
+ iio_free_device(data->indio_dev);
+
+ gpio_free(data->eoc_gpio);
+
+ kfree(data);
+
+ return 0;
+}
+
+static const struct i2c_device_id ak8975_id[] = {
+ {"ak8975", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, ak8975_id);
+
+static struct i2c_driver ak8975_driver = {
+ .driver = {
+ .name = "ak8975",
+ },
+ .probe = ak8975_probe,
+ .remove = __devexit_p(ak8975_remove),
+ .id_table = ak8975_id,
+};
+
+static int __init ak8975_init(void)
+{
+ return i2c_add_driver(&ak8975_driver);
+}
+
+static void __exit ak8975_exit(void)
+{
+ i2c_del_driver(&ak8975_driver);
+}
+
+module_init(ak8975_init);
+module_exit(ak8975_exit);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("AK8975 magnetometer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
index 92f6c6f..5168917 100644
--- a/drivers/staging/iio/magnetometer/hmc5843.c
+++ b/drivers/staging/iio/magnetometer/hmc5843.c
@@ -95,15 +95,15 @@
#define CONF_NOT_USED 0x03
#define MEAS_CONF_MASK 0x03
-static const int regval_to_counts_per_mg[] = {
- 1620,
- 1300,
- 970,
- 780,
- 530,
- 460,
- 390,
- 280
+static const char *regval_to_scale[] = {
+ "0.0000006173",
+ "0.0000007692",
+ "0.0000010309",
+ "0.0000012821",
+ "0.0000018868",
+ "0.0000021739",
+ "0.0000025641",
+ "0.0000035714",
};
static const int regval_to_input_field_mg[] = {
700,
@@ -220,11 +220,15 @@ static ssize_t hmc5843_set_operating_mode(struct device *dev,
int error;
mutex_lock(&data->lock);
error = strict_strtoul(buf, 10, &operating_mode);
- if (error)
- return error;
+ if (error) {
+ count = error;
+ goto exit;
+ }
dev_dbg(dev, "set Conversion mode to %lu\n", operating_mode);
- if (operating_mode > MODE_SLEEP)
- return -EINVAL;
+ if (operating_mode > MODE_SLEEP) {
+ count = -EINVAL;
+ goto exit;
+ }
status = i2c_smbus_write_byte_data(client, this_attr->address,
operating_mode);
@@ -322,7 +326,7 @@ static IIO_DEVICE_ATTR(meas_conf,
* 6 | 50
* 7 | Not used
*/
-static IIO_CONST_ATTR_AVAIL_SAMP_FREQ("0.5 1 2 5 10 20 50");
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("0.5 1 2 5 10 20 50");
static s32 hmc5843_set_rate(struct i2c_client *client,
u8 rate)
@@ -385,11 +389,11 @@ static ssize_t show_sampling_frequency(struct device *dev,
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- u32 rate;
+ s32 rate;
rate = i2c_smbus_read_byte_data(client, this_attr->address);
if (rate < 0)
- return -EINVAL;
+ return rate;
rate = (rate & RATE_BITMASK) >> RATE_OFFSET;
return sprintf(buf, "%s\n", regval_to_samp_freq[rate]);
}
@@ -437,18 +441,23 @@ static ssize_t set_range(struct device *dev,
int error;
mutex_lock(&data->lock);
error = strict_strtoul(buf, 10, &range);
- if (error)
- return error;
+ if (error) {
+ count = error;
+ goto exit;
+ }
dev_dbg(dev, "set range to %lu\n", range);
- if (range > RANGE_6_5)
- return -EINVAL;
+ if (range > RANGE_6_5) {
+ count = -EINVAL;
+ goto exit;
+ }
data->range = range;
range = range << RANGE_GAIN_OFFSET;
if (i2c_smbus_write_byte_data(client, this_attr->address, range))
count = -EINVAL;
+exit:
mutex_unlock(&data->lock);
return count;
@@ -459,17 +468,17 @@ static IIO_DEVICE_ATTR(magn_range,
set_range,
HMC5843_CONFIG_REG_B);
-static ssize_t show_gain(struct device *dev,
+static ssize_t show_scale(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct hmc5843_data *data = indio_dev->dev_data;
- return sprintf(buf, "%d\n", regval_to_counts_per_mg[data->range]);
+ return strlen(strcpy(buf, regval_to_scale[data->range]));
}
-static IIO_DEVICE_ATTR(magn_gain,
+static IIO_DEVICE_ATTR(magn_scale,
S_IRUGO,
- show_gain,
+ show_scale,
NULL , 0);
static struct attribute *hmc5843_attributes[] = {
@@ -477,11 +486,11 @@ static struct attribute *hmc5843_attributes[] = {
&iio_dev_attr_operating_mode.dev_attr.attr,
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_dev_attr_magn_range.dev_attr.attr,
- &iio_dev_attr_magn_gain.dev_attr.attr,
+ &iio_dev_attr_magn_scale.dev_attr.attr,
&iio_dev_attr_magn_x_raw.dev_attr.attr,
&iio_dev_attr_magn_y_raw.dev_attr.attr,
&iio_dev_attr_magn_z_raw.dev_attr.attr,
- &iio_const_attr_available_sampling_frequency.dev_attr.attr,
+ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
NULL
};
diff --git a/drivers/staging/iio/magnetometer/magnet.h b/drivers/staging/iio/magnetometer/magnet.h
index 6433830..1260eb7 100644
--- a/drivers/staging/iio/magnetometer/magnet.h
+++ b/drivers/staging/iio/magnetometer/magnet.h
@@ -12,14 +12,14 @@
#define IIO_DEV_ATTR_MAGN_Z_OFFSET(_mode, _show, _store, _addr) \
IIO_DEVICE_ATTR(magn_z_offset, _mode, _show, _store, _addr)
-#define IIO_DEV_ATTR_MAGN_X_GAIN(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(magn_x_gain, _mode, _show, _store, _addr)
+#define IIO_DEV_ATTR_MAGN_X_SCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(magn_x_scale, _mode, _show, _store, _addr)
-#define IIO_DEV_ATTR_MAGN_Y_GAIN(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(magn_y_gain, _mode, _show, _store, _addr)
+#define IIO_DEV_ATTR_MAGN_Y_SCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(magn_y_scale, _mode, _show, _store, _addr)
-#define IIO_DEV_ATTR_MAGN_Z_GAIN(_mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(magn_z_gain, _mode, _show, _store, _addr)
+#define IIO_DEV_ATTR_MAGN_Z_SCALE(_mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(magn_z_scale, _mode, _show, _store, _addr)
#define IIO_DEV_ATTR_MAGN_X(_show, _addr) \
IIO_DEVICE_ATTR(magn_x_raw, S_IRUGO, _show, NULL, _addr)
diff --git a/drivers/staging/iio/ring_generic.h b/drivers/staging/iio/ring_generic.h
index a872d39..8ecb189 100644
--- a/drivers/staging/iio/ring_generic.h
+++ b/drivers/staging/iio/ring_generic.h
@@ -13,9 +13,7 @@
#ifdef CONFIG_IIO_RING_BUFFER
-struct iio_handler;
struct iio_ring_buffer;
-struct iio_dev;
/**
* iio_push_ring_event() - ring buffer specific push to event chrdev
@@ -52,8 +50,8 @@ int iio_push_or_escallate_ring_event(struct iio_ring_buffer *ring_buf,
* change.
* @request_update: if a parameter change has been marked, update underlying
* storage.
- * @get_bpd: get current bytes per datum
- * @set_bpd: set number of bytes per datum
+ * @get_bytes_per_datum:get current bytes per datum
+ * @set_bytes_per_datum:set number of bytes per datum
* @get_length: get number of datums in ring
* @set_length: set number of datums in ring
* @is_enabled: query if ring is currently being used
@@ -81,8 +79,8 @@ struct iio_ring_access_funcs {
int (*mark_param_change)(struct iio_ring_buffer *ring);
int (*request_update)(struct iio_ring_buffer *ring);
- int (*get_bpd)(struct iio_ring_buffer *ring);
- int (*set_bpd)(struct iio_ring_buffer *ring, size_t bpd);
+ int (*get_bytes_per_datum)(struct iio_ring_buffer *ring);
+ int (*set_bytes_per_datum)(struct iio_ring_buffer *ring, size_t bpd);
int (*get_length)(struct iio_ring_buffer *ring);
int (*set_length)(struct iio_ring_buffer *ring, int length);
@@ -99,9 +97,14 @@ struct iio_ring_access_funcs {
* @id: unique id number
* @access_id: device id number
* @length: [DEVICE] number of datums in ring
- * @bpd: [DEVICE] size of individual datum including timestamp
+ * @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
@@ -121,9 +124,13 @@ struct iio_ring_buffer {
int id;
int access_id;
int length;
- int bpd;
+ 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;
@@ -134,6 +141,12 @@ struct iio_ring_buffer {
int (*postdisable)(struct iio_dev *);
};
+
+/**
+ * iio_ring_buffer_init() - Initialize the buffer structure
+ * @ring: buffer to be initialized
+ * @dev_info: the iio device the buffer is assocated with
+ **/
void iio_ring_buffer_init(struct iio_ring_buffer *ring,
struct iio_dev *dev_info);
@@ -146,7 +159,7 @@ void iio_ring_buffer_init(struct iio_ring_buffer *ring,
static inline void __iio_update_ring_buffer(struct iio_ring_buffer *ring,
int bytes_per_datum, int length)
{
- ring->bpd = bytes_per_datum;
+ ring->bytes_per_datum = bytes_per_datum;
ring->length = length;
ring->loopcount = 0;
}
@@ -155,7 +168,6 @@ static inline void __iio_update_ring_buffer(struct iio_ring_buffer *ring,
* 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)
- * @bit_count: number of bits in scan element
* @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
@@ -164,7 +176,6 @@ static inline void __iio_update_ring_buffer(struct iio_ring_buffer *ring,
struct iio_scan_el {
struct device_attribute dev_attr;
unsigned int number;
- int bit_count;
unsigned int label;
int (*set_state)(struct iio_scan_el *scanel,
@@ -192,7 +203,7 @@ struct iio_scan_el {
ssize_t iio_scan_el_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t len);
/**
- * iio_scal_el_show() - sysfs interface to query whether a scan element is
+ * 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
@@ -201,9 +212,16 @@ ssize_t iio_scan_el_store(struct device *dev, struct device_attribute *attr,
ssize_t iio_scan_el_show(struct device *dev, struct device_attribute *attr,
char *buf);
+/**
+ * iio_scan_el_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);
/**
@@ -212,52 +230,189 @@ ssize_t iio_scan_el_ts_show(struct device *dev, struct device_attribute *attr,
* @_name: identifying name. Resulting struct is iio_scan_el_##_name,
* sysfs element, _name##_en.
* @_number: unique id number for the scan element.
- * @_bits: number of bits in the scan element result (used in mixed bit
* length devices).
* @_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, _bits, _label, _controlfunc) \
+#define __IIO_SCAN_EL_C(_name, _number, _label, _controlfunc) \
struct iio_scan_el iio_scan_el_##_name = { \
- .dev_attr = __ATTR(_number##_##_name##_en, \
+ .dev_attr = __ATTR(_name##_en, \
S_IRUGO | S_IWUSR, \
iio_scan_el_show, \
iio_scan_el_store), \
.number = _number, \
- .bit_count = _bits, \
.label = _label, \
.set_state = _controlfunc, \
- }
+ }; \
+ static IIO_CONST_ATTR(_name##_index, #_number)
-#define IIO_SCAN_EL_C(_name, _number, _bits, _label, _controlfunc) \
- __IIO_SCAN_EL_C(_name, _number, _bits, _label, _controlfunc)
+#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, _bits, _label, _cf) \
+#define __IIO_SCAN_NAMED_EL_C(_name, _string, _number, _label, _cf) \
struct iio_scan_el iio_scan_el_##_name = { \
- .dev_attr = __ATTR(_number##_##_string##_en, \
+ .dev_attr = __ATTR(_string##_en, \
S_IRUGO | S_IWUSR, \
iio_scan_el_show, \
iio_scan_el_store), \
.number = _number, \
- .bit_count = _bits, \
.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, _bits, _label, _cf) \
- __IIO_SCAN_NAMED_EL_C(_name, _string, _number, _bits, _label, _cf)
+
+
+#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(number##_timestamp_en, \
+ .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
+ */
+#define IIO_MAX_SCAN_LENGTH 31
+
+/* note 0 used as error indicator as it doesn't make sense. */
+static inline u32 iio_scan_mask_match(u32 *av_masks, u32 mask)
+{
+ while (*av_masks) {
+ if (!(~*av_masks & mask))
+ return *av_masks;
+ av_masks++;
+ }
+ return 0;
+}
+
+static inline int iio_scan_mask_query(struct iio_ring_buffer *ring, int bit)
+{
+ struct iio_dev *dev_info = ring->indio_dev;
+ u32 mask;
+
+ if (bit > IIO_MAX_SCAN_LENGTH)
+ return -EINVAL;
+
+ if (!ring->scan_mask)
+ return 0;
+
+ if (dev_info->available_scan_masks)
+ mask = iio_scan_mask_match(dev_info->available_scan_masks,
+ ring->scan_mask);
+ else
+ mask = ring->scan_mask;
+
+ if (!mask)
+ return -EINVAL;
+
+ return !!(mask & (1 << bit));
+};
+
+/**
+ * iio_scan_mask_set() - set particular bit in the scan mask
+ * @ring: the ring buffer whose scan mask we are interested in
+ * @bit: the bit to be set.
+ **/
+static inline int iio_scan_mask_set(struct iio_ring_buffer *ring, int bit)
+{
+ struct iio_dev *dev_info = ring->indio_dev;
+ u32 mask;
+ u32 trialmask = ring->scan_mask | (1 << bit);
+
+ if (bit > IIO_MAX_SCAN_LENGTH)
+ return -EINVAL;
+ if (dev_info->available_scan_masks) {
+ mask = iio_scan_mask_match(dev_info->available_scan_masks,
+ trialmask);
+ if (!mask)
+ return -EINVAL;
+ }
+ ring->scan_mask = trialmask;
+ ring->scan_count++;
+
+ return 0;
+};
+
+/**
+ * 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.
+ **/
static inline void iio_put_ring_buffer(struct iio_ring_buffer *ring)
{
put_device(&ring->dev);
@@ -267,32 +422,58 @@ static inline void iio_put_ring_buffer(struct iio_ring_buffer *ring)
container_of(d, struct iio_ring_buffer, dev)
#define access_dev_to_iio_ring_buffer(d) \
container_of(d, struct iio_ring_buffer, access_dev)
+
+/**
+ * iio_ring_buffer_register() - 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);
+
+/**
+ * iio_ring_buffer_unregister() - unregister the buffer from IIO core
+ * @ring: the buffer to be unregistered
+ **/
void iio_ring_buffer_unregister(struct iio_ring_buffer *ring);
+/**
+ * iio_read_ring_length() - attr func to get number of datums in the buffer
+ **/
ssize_t iio_read_ring_length(struct device *dev,
struct device_attribute *attr,
char *buf);
+/**
+ * iio_write_ring_length() - attr func to set number of datums in the buffer
+ **/
ssize_t iio_write_ring_length(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len);
-ssize_t iio_read_ring_bps(struct device *dev,
+/**
+ * iio_read_ring_bytes_per_datum() - attr for number of bytes in whole datum
+ **/
+ssize_t iio_read_ring_bytes_per_datum(struct device *dev,
struct device_attribute *attr,
char *buf);
+/**
+ * iio_store_ring_enable() - attr to turn the buffer on
+ **/
ssize_t iio_store_ring_enable(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len);
+/**
+ * iio_show_ring_enable() - attr to see if the buffer is on
+ **/
ssize_t iio_show_ring_enable(struct device *dev,
struct device_attribute *attr,
char *buf);
#define IIO_RING_LENGTH_ATTR DEVICE_ATTR(length, S_IRUGO | S_IWUSR, \
iio_read_ring_length, \
iio_write_ring_length)
-#define IIO_RING_BPS_ATTR DEVICE_ATTR(bps, S_IRUGO | S_IWUSR, \
- iio_read_ring_bps, NULL)
-#define IIO_RING_ENABLE_ATTR DEVICE_ATTR(ring_enable, S_IRUGO | S_IWUSR, \
+#define IIO_RING_BYTES_PER_DATUM_ATTR DEVICE_ATTR(bytes_per_datum, S_IRUGO | S_IWUSR, \
+ iio_read_ring_bytes_per_datum, NULL)
+#define IIO_RING_ENABLE_ATTR DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, \
iio_show_ring_enable, \
iio_store_ring_enable)
#else /* CONFIG_IIO_RING_BUFFER */
diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c
index e2f01c6..52624ac 100644
--- a/drivers/staging/iio/ring_sw.c
+++ b/drivers/staging/iio/ring_sw.c
@@ -21,7 +21,7 @@ static inline int __iio_allocate_sw_ring_buffer(struct iio_sw_ring_buffer *ring,
if ((length == 0) || (bytes_per_datum == 0))
return -EINVAL;
__iio_update_ring_buffer(&ring->buf, bytes_per_datum, length);
- ring->data = kmalloc(length*ring->buf.bpd, GFP_ATOMIC);
+ ring->data = kmalloc(length*ring->buf.bytes_per_datum, GFP_ATOMIC);
ring->read_p = NULL;
ring->write_p = NULL;
ring->last_written_p = NULL;
@@ -77,10 +77,10 @@ static int iio_store_to_sw_ring(struct iio_sw_ring_buffer *ring,
* as long as the read pointer is valid before this
* passes it - guaranteed as set later in this function.
*/
- ring->half_p = ring->data - ring->buf.length*ring->buf.bpd/2;
+ ring->half_p = ring->data - ring->buf.length*ring->buf.bytes_per_datum/2;
}
/* Copy data to where ever the current write pointer says */
- memcpy(ring->write_p, data, ring->buf.bpd);
+ memcpy(ring->write_p, data, ring->buf.bytes_per_datum);
barrier();
/* Update the pointer used to get most recent value.
* Always valid as either points to latest or second latest value.
@@ -91,9 +91,9 @@ static int iio_store_to_sw_ring(struct iio_sw_ring_buffer *ring,
/* temp_ptr used to ensure we never have an invalid pointer
* it may be slightly lagging, but never invalid
*/
- temp_ptr = ring->write_p + ring->buf.bpd;
+ temp_ptr = ring->write_p + ring->buf.bytes_per_datum;
/* End of ring, back to the beginning */
- if (temp_ptr == ring->data + ring->buf.length*ring->buf.bpd)
+ if (temp_ptr == ring->data + ring->buf.length*ring->buf.bytes_per_datum)
temp_ptr = ring->data;
/* Update the write pointer
* always valid as long as this is the only function able to write.
@@ -112,9 +112,9 @@ static int iio_store_to_sw_ring(struct iio_sw_ring_buffer *ring,
*/
else if (ring->write_p == ring->read_p) {
change_test_ptr = ring->read_p;
- temp_ptr = change_test_ptr + ring->buf.bpd;
+ temp_ptr = change_test_ptr + ring->buf.bytes_per_datum;
if (temp_ptr
- == ring->data + ring->buf.length*ring->buf.bpd) {
+ == ring->data + ring->buf.length*ring->buf.bytes_per_datum) {
temp_ptr = ring->data;
}
/* We are moving pointer on one because the ring is full. Any
@@ -135,8 +135,8 @@ static int iio_store_to_sw_ring(struct iio_sw_ring_buffer *ring,
/* There are definite 'issues' with this and chances of
* simultaneous read */
/* Also need to use loop count to ensure this only happens once */
- ring->half_p += ring->buf.bpd;
- if (ring->half_p == ring->data + ring->buf.length*ring->buf.bpd)
+ ring->half_p += ring->buf.bytes_per_datum;
+ 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);
@@ -164,15 +164,15 @@ int iio_rip_sw_rb(struct iio_ring_buffer *r,
* read something that is not a whole number of bpds.
* Return an error.
*/
- if (count % ring->buf.bpd) {
+ if (count % ring->buf.bytes_per_datum) {
ret = -EINVAL;
printk(KERN_INFO "Ring buffer read request not whole number of"
- "samples: Request bytes %zd, Current bpd %d\n",
- count, ring->buf.bpd);
+ "samples: Request bytes %zd, Current bytes per datum %d\n",
+ count, ring->buf.bytes_per_datum);
goto error_ret;
}
/* Limit size to whole of ring buffer */
- bytes_to_rip = min((size_t)(ring->buf.bpd*ring->buf.length), count);
+ bytes_to_rip = min((size_t)(ring->buf.bytes_per_datum*ring->buf.length), count);
*data = kmalloc(bytes_to_rip, GFP_KERNEL);
if (*data == NULL) {
@@ -214,7 +214,7 @@ int iio_rip_sw_rb(struct iio_ring_buffer *r,
} else {
/* going through 'end' of ring buffer */
max_copied = ring->data
- + ring->buf.length*ring->buf.bpd - initial_read_p;
+ + ring->buf.length*ring->buf.bytes_per_datum - initial_read_p;
memcpy(*data, initial_read_p, max_copied);
/* possible we are done if we align precisely with end */
if (max_copied == bytes_to_rip)
@@ -240,7 +240,7 @@ int iio_rip_sw_rb(struct iio_ring_buffer *r,
if (initial_read_p <= current_read_p)
*dead_offset = current_read_p - initial_read_p;
else
- *dead_offset = ring->buf.length*ring->buf.bpd
+ *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
@@ -293,7 +293,7 @@ again:
/* Check there is anything here */
if (last_written_p_copy == NULL)
return -EAGAIN;
- memcpy(data, last_written_p_copy, ring->buf.bpd);
+ memcpy(data, last_written_p_copy, ring->buf.bytes_per_datum);
if (unlikely(ring->last_written_p != last_written_p_copy))
goto again;
@@ -322,7 +322,7 @@ int iio_request_update_sw_rb(struct iio_ring_buffer *r)
goto error_ret;
}
__iio_free_sw_ring_buffer(ring);
- ret = __iio_allocate_sw_ring_buffer(ring, ring->buf.bpd,
+ ret = __iio_allocate_sw_ring_buffer(ring, ring->buf.bytes_per_datum,
ring->buf.length);
error_ret:
spin_unlock(&ring->use_lock);
@@ -330,23 +330,23 @@ error_ret:
}
EXPORT_SYMBOL(iio_request_update_sw_rb);
-int iio_get_bpd_sw_rb(struct iio_ring_buffer *r)
+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.bpd;
+ return ring->buf.bytes_per_datum;
}
-EXPORT_SYMBOL(iio_get_bpd_sw_rb);
+EXPORT_SYMBOL(iio_get_bytes_per_datum_sw_rb);
-int iio_set_bpd_sw_rb(struct iio_ring_buffer *r, size_t bpd)
+int iio_set_bytes_per_datum_sw_rb(struct iio_ring_buffer *r, size_t bpd)
{
- if (r->bpd != bpd) {
- r->bpd = bpd;
+ if (r->bytes_per_datum != bpd) {
+ r->bytes_per_datum = bpd;
if (r->access.mark_param_change)
r->access.mark_param_change(r);
}
return 0;
}
-EXPORT_SYMBOL(iio_set_bpd_sw_rb);
+EXPORT_SYMBOL(iio_set_bytes_per_datum_sw_rb);
int iio_get_length_sw_rb(struct iio_ring_buffer *r)
{
@@ -380,14 +380,14 @@ static void iio_sw_rb_release(struct device *dev)
}
static IIO_RING_ENABLE_ATTR;
-static IIO_RING_BPS_ATTR;
+static IIO_RING_BYTES_PER_DATUM_ATTR;
static IIO_RING_LENGTH_ATTR;
/* Standard set of ring buffer attributes */
static struct attribute *iio_ring_attributes[] = {
&dev_attr_length.attr,
- &dev_attr_bps.attr,
- &dev_attr_ring_enable.attr,
+ &dev_attr_bytes_per_datum.attr,
+ &dev_attr_enable.attr,
NULL,
};
@@ -435,23 +435,24 @@ 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 (!(indio_dev->scan_count || indio_dev->scan_timestamp))
+ if (!(ring->scan_count || ring->scan_timestamp))
return -EINVAL;
- if (indio_dev->scan_timestamp)
- if (indio_dev->scan_count)
+ if (ring->scan_timestamp)
+ if (ring->scan_count)
/* Timestamp (aligned to s64) and data */
- size = (((indio_dev->scan_count * indio_dev->ring->bpe)
+ size = (((ring->scan_count * ring->bpe)
+ sizeof(s64) - 1)
& ~(sizeof(s64) - 1))
+ sizeof(s64);
else /* Timestamp only */
size = sizeof(s64);
else /* Data only */
- size = indio_dev->scan_count * indio_dev->ring->bpe;
- indio_dev->ring->access.set_bpd(indio_dev->ring, size);
+ size = ring->scan_count * ring->bpe;
+ ring->access.set_bytes_per_datum(ring, size);
return 0;
}
@@ -462,9 +463,9 @@ 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 = st->indio_dev
- ->ring->access.get_bpd(st->indio_dev->ring);
+ size_t datasize = ring->access.get_bytes_per_datum(ring);
char *data = kmalloc(datasize, GFP_KERNEL);
if (data == NULL) {
@@ -473,16 +474,16 @@ void iio_sw_trigger_bh_to_ring(struct work_struct *work_s)
return;
}
- if (st->indio_dev->scan_count)
+ if (ring->scan_count)
len = st->get_ring_element(st, data);
/* Guaranteed to be aligned with 8 byte boundary */
- if (st->indio_dev->scan_timestamp)
+ if (ring->scan_timestamp)
*(s64 *)(((phys_addr_t)data + len
+ sizeof(s64) - 1) & ~(sizeof(s64) - 1))
= st->last_timestamp;
- st->indio_dev->ring->access.store_to(st->indio_dev->ring,
- (u8 *)data,
+ ring->access.store_to(ring,
+ (u8 *)data,
st->last_timestamp);
iio_trigger_notify_done(st->indio_dev->trig);
diff --git a/drivers/staging/iio/ring_sw.h b/drivers/staging/iio/ring_sw.h
index 61f1ed6..ad03d83 100644
--- a/drivers/staging/iio/ring_sw.h
+++ b/drivers/staging/iio/ring_sw.h
@@ -121,19 +121,19 @@ int iio_mark_update_needed_sw_rb(struct iio_ring_buffer *r);
/**
- * iio_get_bpd_sw_rb() - get the datum size in bytes
+ * 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_bpd_sw_rb(struct iio_ring_buffer *r);
+int iio_get_bytes_per_datum_sw_rb(struct iio_ring_buffer *r);
/**
- * iio_set_bpd_sw_rb() - set the datum size in bytes
+ * 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_bpd_sw_rb(struct iio_ring_buffer *r, size_t bpd);
+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
@@ -166,8 +166,8 @@ static inline void iio_ring_sw_register_funcs(struct iio_ring_access_funcs *ra)
ra->mark_param_change = &iio_mark_update_needed_sw_rb;
ra->request_update = &iio_request_update_sw_rb;
- ra->get_bpd = &iio_get_bpd_sw_rb;
- ra->set_bpd = &iio_set_bpd_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;
diff --git a/drivers/staging/iio/sysfs.h b/drivers/staging/iio/sysfs.h
index 6083416..ee91a95 100644
--- a/drivers/staging/iio/sysfs.h
+++ b/drivers/staging/iio/sysfs.h
@@ -30,27 +30,6 @@ struct iio_event_attr {
container_of(_dev_attr, struct iio_event_attr, dev_attr)
/**
- * struct iio_chrdev_minor_attr - simple attribute to allow reading of chrdev
- * minor number
- * @dev_attr: underlying device attribute
- * @minor: the minor number
- */
-struct iio_chrdev_minor_attr {
- struct device_attribute dev_attr;
- int minor;
-};
-
-void
-__init_iio_chrdev_minor_attr(struct iio_chrdev_minor_attr *minor_attr,
- const char *name,
- struct module *owner,
- int id);
-
-
-#define to_iio_chrdev_minor_attr(_dev_attr) \
- container_of(_dev_attr, struct iio_chrdev_minor_attr, dev_attr);
-
-/**
* struct iio_dev_attr - iio specific device attribute
* @dev_attr: underlying device attribute
* @address: associated register address
@@ -89,11 +68,6 @@ struct iio_const_attr {
{ .dev_attr = __ATTR(_name, _mode, _show, _store), \
.address = _addr }
-#define IIO_ATTR_2(_name, _mode, _show, _store, _addr, _val2) \
- { .dev_attr = __ATTR(_name, _mode, _show, _store), \
- .address = _addr, \
- .val2 = _val2 }
-
#define IIO_DEVICE_ATTR(_name, _mode, _show, _store, _addr) \
struct iio_dev_attr iio_dev_attr_##_name \
= IIO_ATTR(_name, _mode, _show, _store, _addr)
@@ -111,6 +85,10 @@ struct iio_const_attr {
= { .string = _string, \
.dev_attr = __ATTR(_name, S_IRUGO, iio_read_const_attr, NULL)}
+#define IIO_CONST_ATTR_NAMED(_vname, _name, _string) \
+ struct iio_const_attr iio_const_attr_##_vname \
+ = { .string = _string, \
+ .dev_attr = __ATTR(_name, S_IRUGO, iio_read_const_attr, NULL)}
/* Generic attributes of onetype or another */
/**
@@ -130,6 +108,13 @@ struct iio_const_attr {
IIO_DEVICE_ATTR(name, S_IRUGO, _show, NULL, 0)
/**
+ * IIO_CONST_ATTR_NAME - constant identifier
+ * @_string: the name
+ **/
+#define IIO_CONST_ATTR_NAME(_string) \
+ IIO_CONST_ATTR(name, _string)
+
+/**
* IIO_DEV_ATTR_SAMP_FREQ - sets any internal clock frequency
* @_mode: sysfs file mode/permissions
* @_show: output method for the attribute
@@ -156,48 +141,10 @@ struct iio_const_attr {
*
* Constant version
**/
-/* Deprecated */
-#define IIO_CONST_ATTR_AVAIL_SAMP_FREQ(_string) \
- IIO_CONST_ATTR(available_sampling_frequency, _string)
-
#define IIO_CONST_ATTR_SAMP_FREQ_AVAIL(_string) \
IIO_CONST_ATTR(sampling_frequency_available, _string)
/**
- * IIO_DEV_ATTR_SCAN_MODE - select a scan mode
- * @_mode: sysfs file mode/permissions
- * @_show: output method for the attribute
- * @_store: input method for the attribute
- *
- * This is used when only certain combinations of inputs may be read in one
- * scan.
- **/
-#define IIO_DEV_ATTR_SCAN_MODE(_mode, _show, _store) \
- IIO_DEVICE_ATTR(scan_mode, _mode, _show, _store, 0)
-
-/**
- * IIO_DEV_ATTR_AVAIL_SCAN_MODES - list available scan modes
- * @_show: output method for the attribute
- **/
-#define IIO_DEV_ATTR_AVAIL_SCAN_MODES(_show) \
- IIO_DEVICE_ATTR(available_scan_modes, S_IRUGO, _show, NULL, 0)
-
-/**
- * IIO_DEV_ATTR_SCAN - result of scan of multiple channels
- * @_show: output method for the attribute
- **/
-#define IIO_DEV_ATTR_SCAN(_show) \
- IIO_DEVICE_ATTR(scan, S_IRUGO, _show, NULL, 0);
-
-/**
- * IIO_DEV_ATTR_INPUT - direct read of a single input channel
- * @_number: input channel number
- * @_show: output method for the attribute
- **/
-#define IIO_DEV_ATTR_INPUT(_number, _show) \
- IIO_DEVICE_ATTR(in##_number, S_IRUGO, _show, NULL, _number)
-
-/**
* IIO_DEV_ATTR_SW_RING_ENABLE - enable software ring buffer
* @_show: output method for the attribute
* @_store: input method for the attribute
@@ -218,32 +165,15 @@ struct iio_const_attr {
#define IIO_DEV_ATTR_HW_RING_ENABLE(_show, _store) \
IIO_DEVICE_ATTR(hw_ring_enable, S_IRUGO | S_IWUSR, _show, _store, 0)
-/**
- * IIO_DEV_ATTR_BPSE - set number of bits per scan element
- * @_mode: sysfs file mode/permissions
- * @_show: output method for the attribute
- * @_store: input method for the attribute
- **/
-#define IIO_DEV_ATTR_BPSE(_mode, _show, _store) \
- IIO_DEVICE_ATTR(bpse, _mode, _show, _store, 0)
-
-/**
- * IIO_DEV_ATTR_BPSE_AVAILABLE - number of bits per scan element supported
- * @_show: output method for the attribute
- **/
-#define IIO_DEV_ATTR_BPSE_AVAILABLE(_show) \
- IIO_DEVICE_ATTR(bpse_available, S_IRUGO, _show, NULL, 0)
-
-/**
- * IIO_DEV_ATTR_TEMP - many sensors have auxiliary temperature sensors
- * @_show: output method for the attribute
- **/
-#define IIO_DEV_ATTR_TEMP(_show) \
- IIO_DEVICE_ATTR(temp, S_IRUGO, _show, NULL, 0)
-
#define IIO_DEV_ATTR_TEMP_RAW(_show) \
IIO_DEVICE_ATTR(temp_raw, S_IRUGO, _show, NULL, 0)
+#define IIO_CONST_ATTR_TEMP_OFFSET(_string) \
+ IIO_CONST_ATTR(temp_offset, _string)
+
+#define IIO_CONST_ATTR_TEMP_SCALE(_string) \
+ IIO_CONST_ATTR(temp_scale, _string)
+
/**
* IIO_EVENT_SH - generic shared event handler
* @_name: event name
@@ -323,15 +253,49 @@ struct iio_const_attr {
#define IIO_EVENT_ATTR_DATA_RDY(_show, _store, _mask, _handler) \
IIO_EVENT_ATTR(data_rdy, _show, _store, _mask, _handler)
-#define IIO_EVENT_CODE_DATA_RDY 100
-#define IIO_EVENT_CODE_RING_BASE 200
-#define IIO_EVENT_CODE_ACCEL_BASE 300
-#define IIO_EVENT_CODE_GYRO_BASE 400
-#define IIO_EVENT_CODE_ADC_BASE 500
-#define IIO_EVENT_CODE_MISC_BASE 600
-#define IIO_EVENT_CODE_LIGHT_BASE 700
-
-#define IIO_EVENT_CODE_DEVICE_SPECIFIC 1000
+#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
+
+#define IIO_EV_TYPE_THRESH 0
+#define IIO_EV_TYPE_MAG 1
+#define IIO_EV_TYPE_ROC 2
+
+#define IIO_EV_DIR_EITHER 0
+#define IIO_EV_DIR_RISING 1
+#define IIO_EV_DIR_FALLING 2
+
+#define IIO_EVENT_CODE(channelclass, orient_bit, number, \
+ modifier, type, direction) \
+ (channelclass | (orient_bit << 8) | ((number) << 9) | \
+ ((modifier) << 13) | ((type) << 16) | ((direction) << 24))
+
+#define IIO_MOD_EVENT_CODE(channelclass, number, modifier, \
+ type, direction) \
+ IIO_EVENT_CODE(channelclass, 1, number, modifier, type, direction)
+
+#define IIO_UNMOD_EVENT_CODE(channelclass, number, type, direction) \
+ IIO_EVENT_CODE(channelclass, 0, number, 0, type, direction)
+
+
+#define IIO_BUFFER_EVENT_CODE(code) \
+ (IIO_EV_CLASS_BUFFER | (code << 8))
/**
* IIO_EVENT_ATTR_RING_50_FULL - ring buffer event to indicate 50% full
@@ -363,8 +327,8 @@ struct iio_const_attr {
#define IIO_EVENT_ATTR_RING_75_FULL_SH(_evlist, _show, _store, _mask) \
IIO_EVENT_ATTR_SH(ring_75_full, _evlist, _show, _store, _mask)
-#define IIO_EVENT_CODE_RING_50_FULL IIO_EVENT_CODE_RING_BASE
-#define IIO_EVENT_CODE_RING_75_FULL (IIO_EVENT_CODE_RING_BASE + 1)
-#define IIO_EVENT_CODE_RING_100_FULL (IIO_EVENT_CODE_RING_BASE + 2)
+#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)
#endif /* _INDUSTRIAL_IO_SYSFS_H_ */
diff --git a/drivers/staging/iio/trigger.h b/drivers/staging/iio/trigger.h
index 4699586..469beba 100644
--- a/drivers/staging/iio/trigger.h
+++ b/drivers/staging/iio/trigger.h
@@ -152,7 +152,7 @@ int iio_alloc_pollfunc(struct iio_dev *indio_dev,
/*
* Two functions for common case where all that happens is a pollfunc
- * is attached and detached form a trigger
+ * is attached and detached from a trigger
*/
int iio_triggered_ring_postenable(struct iio_dev *indio_dev);
int iio_triggered_ring_predisable(struct iio_dev *indio_dev);
@@ -161,8 +161,4 @@ struct iio_trigger *iio_allocate_trigger(void);
void iio_free_trigger(struct iio_trigger *trig);
-
-struct iio_simple_trigger {
- struct iio_trigger trig;
-};
#endif /* _IIO_TRIGGER_H_ */
diff --git a/drivers/staging/iio/trigger/iio-trig-gpio.c b/drivers/staging/iio/trigger/iio-trig-gpio.c
index f93cc91..2ce95e9 100644
--- a/drivers/staging/iio/trigger/iio-trig-gpio.c
+++ b/drivers/staging/iio/trigger/iio-trig-gpio.c
@@ -47,7 +47,7 @@ static irqreturn_t iio_gpio_trigger_poll(int irq, void *private)
return IRQ_HANDLED;
}
-static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
+static IIO_TRIGGER_NAME_ATTR;
static struct attribute *iio_gpio_trigger_attrs[] = {
&dev_attr_name.attr,
diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
index b0b52f8..24f174e 100644
--- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
@@ -72,17 +72,7 @@ error_ret:
return ret;
}
-static ssize_t iio_trig_periodic_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_trig_periodic_read_name,
- NULL);
+static IIO_TRIGGER_NAME_ATTR;
static DEVICE_ATTR(frequency, S_IRUGO | S_IWUSR,
iio_trig_periodic_read_freq,
iio_trig_periodic_write_freq);
OpenPOWER on IntegriCloud