diff options
Diffstat (limited to 'drivers/staging/iio')
207 files changed, 9626 insertions, 32063 deletions
diff --git a/drivers/staging/iio/Documentation/device.txt b/drivers/staging/iio/Documentation/device.txt index 1abb80cb884..8be32e5a0af 100644 --- a/drivers/staging/iio/Documentation/device.txt +++ b/drivers/staging/iio/Documentation/device.txt @@ -8,11 +8,11 @@ The crucial structure for device drivers in iio is iio_dev. First allocate one using: -struct iio_dev *indio_dev = iio_allocate_device(sizeof(struct chip_state)); +struct iio_dev *indio_dev = iio_device_alloc(sizeof(struct chip_state)); where chip_state is a structure of local state data for this instance of the chip. -That data can be accessed using iio_priv(struct iio_dev *) +That data can be accessed using iio_priv(struct iio_dev *). Then fill in the following: @@ -29,8 +29,6 @@ Then fill in the following: * info->driver_module: Set to THIS_MODULE. Used to ensure correct ownership of various resources allocate by the core. - * info->num_interrupt_lines: - Number of event triggering hardware lines the device has. * info->event_attrs: Attributes used to enable / disable hardware events. * info->attrs: @@ -41,7 +39,7 @@ Then fill in the following: and for associate parameters such as offsets and scales. * info->write_raw: Raw value writing function. Used for writable device values such - as DAC values and caliboffset. + as DAC values and calibbias. * info->read_event_config: Typically only set if there are some interrupt lines. This is used to read if an on sensor event detector is enabled. @@ -58,18 +56,18 @@ Then fill in the following: - indio_dev->modes: Specify whether direct access and / or ring buffer access is supported. -- indio_dev->ring: +- indio_dev->buffer: An optional associated buffer. - indio_dev->pollfunc: Poll function related elements. This controls what occurs when a trigger - to which this device is attached sends and event. + to which this device is attached sends an event. - indio_dev->channels: - Specification of device channels. Most attributes etc are built - form this spec. + Specification of device channels. Most attributes etc. are built + from this spec. - indio_dev->num_channels: How many channels are there? -Once these are set up, a call to iio_device_register(indio_dev), +Once these are set up, a call to iio_device_register(indio_dev) will register the device with the iio core. Worth noting here is that, if a ring buffer is to be used, it can be @@ -78,4 +76,4 @@ be registered afterwards (otherwise the whole parentage of devices gets confused) On remove, iio_device_unregister(indio_dev) will remove the device from -the core, and iio_free_device will clean up. +the core, and iio_device_free(indio_dev) will clean up. diff --git a/drivers/staging/iio/Documentation/generic_buffer.c b/drivers/staging/iio/Documentation/generic_buffer.c index 69a05b9456d..40d0ecac047 100644 --- a/drivers/staging/iio/Documentation/generic_buffer.c +++ b/drivers/staging/iio/Documentation/generic_buffer.c @@ -18,6 +18,8 @@ * */ +#define _GNU_SOURCE + #include <unistd.h> #include <dirent.h> #include <fcntl.h> @@ -29,12 +31,14 @@ #include <string.h> #include <poll.h> #include <endian.h> +#include <getopt.h> +#include <inttypes.h> #include "iio_utils.h" /** * size_from_channelarray() - calculate the storage size of a scan - * @channels: the channel info array - * @num_channels: size of the channel info array + * @channels: the channel info array + * @num_channels: number of channels * * Has the side effect of filling the channels[i].location values used * in processing the buffer output. @@ -58,22 +62,22 @@ int size_from_channelarray(struct iio_channel_info *channels, int num_channels) void print2byte(int input, struct iio_channel_info *info) { /* First swap if incorrect endian */ - if (info->be) - input = be16toh((uint_16t)input); + input = be16toh((uint16_t)input); else - input = le16toh((uint_16t)input); + input = le16toh((uint16_t)input); - /* shift before conversion to avoid sign extension - of left aligned data */ + /* + * Shift before conversion to avoid sign extension + * of left aligned data + */ input = input >> info->shift; if (info->is_signed) { int16_t val = input; val &= (1 << info->bits_used) - 1; val = (int16_t)(val << (16 - info->bits_used)) >> (16 - info->bits_used); - printf("%05f ", val, - (float)(val + info->offset)*info->scale); + printf("%05f ", ((float)val + info->offset)*info->scale); } else { uint16_t val = input; val &= (1 << info->bits_used) - 1; @@ -83,39 +87,49 @@ void print2byte(int input, struct iio_channel_info *info) /** * process_scan() - print out the values in SI units * @data: pointer to the start of the scan - * @infoarray: information about the channels. Note + * @channels: 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 + * @num_channels: number of channels **/ void process_scan(char *data, - struct iio_channel_info *infoarray, + struct iio_channel_info *channels, int num_channels) { int k; for (k = 0; k < num_channels; k++) - switch (infoarray[k].bytes) { + switch (channels[k].bytes) { /* only a few cases implemented so far */ case 2: - print2byte(*(uint16_t *)(data + infoarray[k].location), - &infoarray[k]); + print2byte(*(uint16_t *)(data + channels[k].location), + &channels[k]); + break; + case 4: + if (!channels[k].is_signed) { + uint32_t val = *(uint32_t *) + (data + channels[k].location); + printf("%05f ", ((float)val + + channels[k].offset)* + channels[k].scale); + + } break; case 8: - if (infoarray[k].is_signed) { + if (channels[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; + channels[k].location); + if ((val >> channels[k].bits_used) & 1) + val = (val & channels[k].mask) | + ~channels[k].mask; /* special case for timestamp */ - if (infoarray[k].scale == 1.0f && - infoarray[k].offset == 0.0f) - printf(" %lld", val); + if (channels[k].scale == 1.0f && + channels[k].offset == 0.0f) + printf("%" PRId64 " ", val); else printf("%05f ", ((float)val + - infoarray[k].offset)* - infoarray[k].scale); + channels[k].offset)* + channels[k].scale); } break; default: @@ -130,10 +144,7 @@ int main(int argc, char **argv) unsigned long timedelay = 1000000; unsigned long buf_len = 128; - int ret, c, i, j, toread; - - FILE *fp_ev; int fp; int num_channels; @@ -149,7 +160,7 @@ int main(int argc, char **argv) int noevents = 0; char *dummy; - struct iio_channel_info *infoarray; + struct iio_channel_info *channels; while ((c = getopt(argc, argv, "l:w:c:et:n:")) != -1) { switch (c) { @@ -192,7 +203,7 @@ int main(int argc, char **argv) asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num); if (trigger_name == NULL) { /* - * Build the trigger name. If it is device associated it's + * Build the trigger name. If it is device associated its * name is <device_name>_dev[n] where n matches the device * number found above */ @@ -217,7 +228,7 @@ int main(int argc, char **argv) * Parse the files in scan_elements to identify what channels are * present */ - ret = build_channel_array(dev_dir_name, &infoarray, &num_channels); + ret = build_channel_array(dev_dir_name, &channels, &num_channels); if (ret) { printf("Problem reading scan element information\n"); printf("diag %s\n", dev_dir_name); @@ -236,7 +247,7 @@ int main(int argc, char **argv) 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 */ + /* Set the device trigger to be the data ready trigger found above */ ret = write_sysfs_string_and_verify("trigger/current_trigger", dev_dir_name, trigger_name); @@ -254,7 +265,7 @@ int main(int argc, char **argv) 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); + scan_size = size_from_channelarray(channels, num_channels); data = malloc(scan_size*buf_len); if (!data) { ret = -ENOMEM; @@ -269,7 +280,7 @@ int main(int argc, char **argv) /* 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 */ + 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_access; @@ -300,16 +311,16 @@ int main(int argc, char **argv) } for (i = 0; i < read_size/scan_size; i++) process_scan(data + scan_size*i, - infoarray, + channels, num_channels); } - /* Stop the ring buffer */ + /* Stop the buffer */ ret = write_sysfs_int("enable", buf_dir_name, 0); if (ret < 0) goto error_close_buffer_access; - /* Disconnect from the trigger - just write a dummy name.*/ + /* Disconnect the trigger - just write a dummy name. */ write_sysfs_string("trigger/current_trigger", dev_dir_name, "NULL"); diff --git a/drivers/staging/iio/Documentation/iio_event_monitor.c b/drivers/staging/iio/Documentation/iio_event_monitor.c new file mode 100644 index 00000000000..3a9b0008740 --- /dev/null +++ b/drivers/staging/iio/Documentation/iio_event_monitor.c @@ -0,0 +1,255 @@ +/* Industrialio event test code. + * + * Copyright (c) 2011-2012 Lars-Peter Clausen <lars@metafoo.de> + * + * 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. + * + * Usage: + * iio_event_monitor <device_name> + * + */ + +#define _GNU_SOURCE + +#include <unistd.h> +#include <stdbool.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <poll.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include "iio_utils.h" +#include <linux/iio/events.h> + +static const char * const iio_chan_type_name_spec[] = { + [IIO_VOLTAGE] = "voltage", + [IIO_CURRENT] = "current", + [IIO_POWER] = "power", + [IIO_ACCEL] = "accel", + [IIO_ANGL_VEL] = "anglvel", + [IIO_MAGN] = "magn", + [IIO_LIGHT] = "illuminance", + [IIO_INTENSITY] = "intensity", + [IIO_PROXIMITY] = "proximity", + [IIO_TEMP] = "temp", + [IIO_INCLI] = "incli", + [IIO_ROT] = "rot", + [IIO_ANGL] = "angl", + [IIO_TIMESTAMP] = "timestamp", + [IIO_CAPACITANCE] = "capacitance", + [IIO_ALTVOLTAGE] = "altvoltage", +}; + +static const char * const iio_ev_type_text[] = { + [IIO_EV_TYPE_THRESH] = "thresh", + [IIO_EV_TYPE_MAG] = "mag", + [IIO_EV_TYPE_ROC] = "roc", + [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", + [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", +}; + +static const char * const iio_ev_dir_text[] = { + [IIO_EV_DIR_EITHER] = "either", + [IIO_EV_DIR_RISING] = "rising", + [IIO_EV_DIR_FALLING] = "falling" +}; + +static const char * const iio_modifier_names[] = { + [IIO_MOD_X] = "x", + [IIO_MOD_Y] = "y", + [IIO_MOD_Z] = "z", + [IIO_MOD_LIGHT_BOTH] = "both", + [IIO_MOD_LIGHT_IR] = "ir", + [IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)", + [IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2", + [IIO_MOD_LIGHT_CLEAR] = "clear", + [IIO_MOD_LIGHT_RED] = "red", + [IIO_MOD_LIGHT_GREEN] = "green", + [IIO_MOD_LIGHT_BLUE] = "blue", +}; + +static bool event_is_known(struct iio_event_data *event) +{ + enum iio_chan_type type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id); + enum iio_modifier mod = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id); + enum iio_event_type ev_type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id); + enum iio_event_direction dir = IIO_EVENT_CODE_EXTRACT_DIR(event->id); + + switch (type) { + case IIO_VOLTAGE: + case IIO_CURRENT: + case IIO_POWER: + case IIO_ACCEL: + case IIO_ANGL_VEL: + case IIO_MAGN: + case IIO_LIGHT: + case IIO_INTENSITY: + case IIO_PROXIMITY: + case IIO_TEMP: + case IIO_INCLI: + case IIO_ROT: + case IIO_ANGL: + case IIO_TIMESTAMP: + case IIO_CAPACITANCE: + case IIO_ALTVOLTAGE: + break; + default: + return false; + } + + switch (mod) { + case IIO_NO_MOD: + case IIO_MOD_X: + case IIO_MOD_Y: + case IIO_MOD_Z: + case IIO_MOD_LIGHT_BOTH: + case IIO_MOD_LIGHT_IR: + case IIO_MOD_ROOT_SUM_SQUARED_X_Y: + case IIO_MOD_SUM_SQUARED_X_Y_Z: + case IIO_MOD_LIGHT_CLEAR: + case IIO_MOD_LIGHT_RED: + case IIO_MOD_LIGHT_GREEN: + case IIO_MOD_LIGHT_BLUE: + break; + default: + return false; + } + + switch (ev_type) { + case IIO_EV_TYPE_THRESH: + case IIO_EV_TYPE_MAG: + case IIO_EV_TYPE_ROC: + case IIO_EV_TYPE_THRESH_ADAPTIVE: + case IIO_EV_TYPE_MAG_ADAPTIVE: + break; + default: + return false; + } + + switch (dir) { + case IIO_EV_DIR_EITHER: + case IIO_EV_DIR_RISING: + case IIO_EV_DIR_FALLING: + break; + default: + return false; + } + + return true; +} + +static void print_event(struct iio_event_data *event) +{ + enum iio_chan_type type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id); + enum iio_modifier mod = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id); + enum iio_event_type ev_type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id); + enum iio_event_direction dir = IIO_EVENT_CODE_EXTRACT_DIR(event->id); + int chan = IIO_EVENT_CODE_EXTRACT_CHAN(event->id); + int chan2 = IIO_EVENT_CODE_EXTRACT_CHAN2(event->id); + bool diff = IIO_EVENT_CODE_EXTRACT_DIFF(event->id); + + if (!event_is_known(event)) { + printf("Unknown event: time: %lld, id: %llx\n", + event->timestamp, event->id); + return; + } + + printf("Event: time: %lld, ", event->timestamp); + + if (mod != IIO_NO_MOD) { + printf("type: %s(%s), ", + iio_chan_type_name_spec[type], + iio_modifier_names[mod]); + } else { + printf("type: %s, ", + iio_chan_type_name_spec[type]); + } + + if (diff && chan >= 0 && chan2 >= 0) + printf("channel: %d-%d, ", chan, chan2); + else if (chan >= 0) + printf("channel: %d, ", chan); + + printf("evtype: %s, direction: %s\n", + iio_ev_type_text[ev_type], + iio_ev_dir_text[dir]); +} + +int main(int argc, char **argv) +{ + struct iio_event_data event; + const char *device_name; + char *chrdev_name; + int ret; + int dev_num; + int fd, event_fd; + + if (argc <= 1) { + printf("Usage: %s <device_name>\n", argv[0]); + return -1; + } + + device_name = argv[1]; + + dev_num = find_type_by_name(device_name, "iio:device"); + if (dev_num >= 0) { + printf("Found IIO device with name %s with device number %d\n", + device_name, dev_num); + ret = asprintf(&chrdev_name, "/dev/iio:device%d", dev_num); + if (ret < 0) { + ret = -ENOMEM; + goto error_ret; + } + } else { + /* If we can't find a IIO device by name assume device_name is a + IIO chrdev */ + chrdev_name = strdup(device_name); + } + + fd = open(chrdev_name, 0); + if (fd == -1) { + fprintf(stdout, "Failed to open %s\n", chrdev_name); + ret = -errno; + goto error_free_chrdev_name; + } + + ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd); + + close(fd); + + if (ret == -1 || event_fd == -1) { + fprintf(stdout, "Failed to retrieve event fd\n"); + ret = -errno; + goto error_free_chrdev_name; + } + + while (true) { + ret = read(event_fd, &event, sizeof(event)); + if (ret == -1) { + if (errno == EAGAIN) { + printf("nothing available\n"); + continue; + } else { + perror("Failed to read event from device"); + ret = -errno; + break; + } + } + + print_event(&event); + } + + close(event_fd); +error_free_chrdev_name: + free(chrdev_name); +error_ret: + return ret; +} diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h index 6f3a392297e..a9cfc06edb0 100644 --- a/drivers/staging/iio/Documentation/iio_utils.h +++ b/drivers/staging/iio/Documentation/iio_utils.h @@ -7,14 +7,15 @@ * the Free Software Foundation. */ -/* Made up value to limit allocation sizes */ #include <string.h> #include <stdlib.h> #include <ctype.h> #include <stdio.h> #include <stdint.h> #include <dirent.h> +#include <errno.h> +/* Made up value to limit allocation sizes */ #define IIO_MAX_NAME_LENGTH 30 #define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements" @@ -27,7 +28,7 @@ const char *iio_dir = "/sys/bus/iio/devices/"; * @full_name: the full channel name * @generic_name: the output generic channel name **/ -static int iioutils_break_up_name(const char *full_name, +inline int iioutils_break_up_name(const char *full_name, char **generic_name) { char *current; @@ -76,7 +77,6 @@ struct iio_channel_info { uint64_t mask; unsigned be; unsigned is_signed; - unsigned enabled; unsigned location; }; @@ -157,7 +157,8 @@ inline int iioutils_get_type(unsigned *is_signed, &padint, shift); if (ret < 0) { printf("failed to pass scan type description\n"); - return ret; + ret = -errno; + goto error_close_sysfsfp; } *be = (endianchar == 'b'); *bytes = padint / 8; @@ -173,7 +174,11 @@ inline int iioutils_get_type(unsigned *is_signed, free(filename); filename = 0; + sysfsfp = 0; } +error_close_sysfsfp: + if (sysfsfp) + fclose(sysfsfp); error_free_filename: if (filename) free(filename); @@ -280,7 +285,7 @@ inline int build_channel_array(const char *device_dir, { DIR *dp; FILE *sysfsfp; - int count, temp, i; + int count, i; struct iio_channel_info *current; int ret; const struct dirent *ent; @@ -313,7 +318,7 @@ inline int build_channel_array(const char *device_dir, free(filename); goto error_close_dir; } - fscanf(sysfsfp, "%u", &ret); + fscanf(sysfsfp, "%i", &ret); if (ret == 1) (*counter)++; fclose(sysfsfp); @@ -329,6 +334,7 @@ inline int build_channel_array(const char *device_dir, while (ent = readdir(dp), ent != NULL) { if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"), "_en") == 0) { + int current_enabled = 0; current = &(*ci_array)[count++]; ret = asprintf(&filename, "%s/%s", scan_el_dir, ent->d_name); @@ -344,10 +350,10 @@ inline int build_channel_array(const char *device_dir, ret = -errno; goto error_cleanup_array; } - fscanf(sysfsfp, "%u", ¤t->enabled); + fscanf(sysfsfp, "%i", ¤t_enabled); fclose(sysfsfp); - if (!current->enabled) { + if (!current_enabled) { free(filename); count--; continue; @@ -447,7 +453,7 @@ inline int find_type_by_name(const char *name, const char *type) dp = opendir(iio_dir); if (dp == NULL) { - printf("No industrialio devices available"); + printf("No industrialio devices available\n"); return -ENODEV; } @@ -467,29 +473,36 @@ inline int find_type_by_name(const char *name, const char *type) + strlen(type) + numstrlen + 6); - if (filename == NULL) + if (filename == NULL) { + closedir(dp); return -ENOMEM; + } sprintf(filename, "%s%s%d/name", iio_dir, type, number); nameFile = fopen(filename, "r"); - if (!nameFile) + if (!nameFile) { + free(filename); continue; + } free(filename); fscanf(nameFile, "%s", thisname); - if (strcmp(name, thisname) == 0) - return number; fclose(nameFile); + if (strcmp(name, thisname) == 0) { + closedir(dp); + return number; + } } } } + closedir(dp); return -ENODEV; } inline int _write_sysfs_int(char *filename, char *basedir, int val, int verify) { - int ret; + int ret = 0; FILE *sysfsfp; int test; char *temp = malloc(strlen(basedir) + strlen(filename) + 2); @@ -512,6 +525,7 @@ inline int _write_sysfs_int(char *filename, char *basedir, int val, int verify) goto error_free; } fscanf(sysfsfp, "%d", &test); + fclose(sysfsfp); if (test != val) { printf("Possible failure in int write %d to %s%s\n", val, @@ -561,6 +575,7 @@ int _write_sysfs_string(char *filename, char *basedir, char *val, int verify) goto error_free; } fscanf(sysfsfp, "%s", temp); + fclose(sysfsfp); if (strcmp(temp, val) != 0) { printf("Possible failure in string write of %s " "Should be %s " @@ -637,3 +652,25 @@ error_free: free(temp); return ret; } + +read_sysfs_string(const char *filename, const char *basedir, char *str) +{ + float ret = 0; + FILE *sysfsfp; + char *temp = malloc(strlen(basedir) + strlen(filename) + 2); + if (temp == NULL) { + printf("Memory allocation failed"); + return -ENOMEM; + } + sprintf(temp, "%s/%s", basedir, filename); + sysfsfp = fopen(temp, "r"); + if (sysfsfp == NULL) { + ret = -errno; + goto error_free; + } + fscanf(sysfsfp, "%s\n", str); + fclose(sysfsfp); +error_free: + free(temp); + return ret; +} diff --git a/drivers/staging/iio/Documentation/inkernel.txt b/drivers/staging/iio/Documentation/inkernel.txt new file mode 100644 index 00000000000..ab528409bba --- /dev/null +++ b/drivers/staging/iio/Documentation/inkernel.txt @@ -0,0 +1,58 @@ +Industrial I/O Subsystem in kernel consumers. + +The IIO subsystem can act as a layer under other elements of the kernel +providing a means of obtaining ADC type readings or of driving DAC type +signals. The functionality supported will grow as use cases arise. + +Describing the channel mapping (iio/machine.h) + +Channel associations are described using: + +struct iio_map { + const char *adc_channel_label; + const char *consumer_dev_name; + const char *consumer_channel; +}; + +adc_channel_label identifies the channel on the IIO device by being +matched against the datasheet_name field of the iio_chan_spec. + +consumer_dev_name allows identification of the consumer device. +This are then used to find the channel mapping from the consumer device (see +below). + +Finally consumer_channel is a string identifying the channel to the consumer. +(Perhaps 'battery_voltage' or similar). + +An array of these structures is then passed to the IIO driver. + +Supporting in kernel interfaces in the driver (driver.h) + +The driver must provide datasheet_name values for its channels and +must pass the iio_map structures and a pointer to its own iio_dev structure + on to the core via a call to iio_map_array_register. On removal, +iio_map_array_unregister reverses this process. + +The result of this is that the IIO core now has all the information needed +to associate a given channel with the consumer requesting it. + +Acting as an IIO consumer (consumer.h) + +The consumer first has to obtain an iio_channel structure from the core +by calling iio_channel_get(). The correct channel is identified by: + +* matching dev or dev_name against consumer_dev and consumer_dev_name +* matching consumer_channel against consumer_channel in the map + +There are then a number of functions that can be used to get information +about this channel such as it's current reading. + +e.g. +iio_read_channel_raw() - get a reading +iio_get_channel_type() - get the type of channel + +There is also provision for retrieving all of the channels associated +with a given consumer. This is useful for generic drivers such as +iio_hwmon where the number and naming of channels is not known by the +consumer driver. To do this, use iio_channel_get_all. + diff --git a/drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2583 b/drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2583 new file mode 100644 index 00000000000..470f7ad9c07 --- /dev/null +++ b/drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2583 @@ -0,0 +1,6 @@ +What: /sys/bus/iio/devices/device[n]/in_illuminance0_calibrate +KernelVersion: 2.6.37 +Contact: linux-iio@vger.kernel.org +Description: + This property causes an internal calibration of the als gain trim + value which is later used in calculating illuminance in lux. diff --git a/drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2x7x b/drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2x7x new file mode 100644 index 00000000000..b2798b258bf --- /dev/null +++ b/drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2x7x @@ -0,0 +1,13 @@ +What: /sys/bus/iio/devices/device[n]/in_illuminance0_calibrate +KernelVersion: 3.3-rc1 +Contact: linux-iio@vger.kernel.org +Description: + Causes an internal calibration of the als gain trim + value which is later used in calculating illuminance in lux. + +What: /sys/bus/iio/devices/device[n]/in_proximity0_calibrate +KernelVersion: 3.3-rc1 +Contact: linux-iio@vger.kernel.org +Description: + Causes a recalculation and adjustment to the + proximity_thresh_rising_value. diff --git a/drivers/staging/iio/Documentation/lsiio.c b/drivers/staging/iio/Documentation/lsiio.c new file mode 100644 index 00000000000..24ae9694eb4 --- /dev/null +++ b/drivers/staging/iio/Documentation/lsiio.c @@ -0,0 +1,157 @@ +/* + * Industrial I/O utilities - lsiio.c + * + * Copyright (c) 2010 Manuel Stahl <manuel.stahl@iis.fraunhofer.de> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include <string.h> +#include <dirent.h> +#include <stdio.h> +#include <errno.h> +#include <stdint.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/dir.h> +#include "iio_utils.h" + + +static enum verbosity { + VERBLEVEL_DEFAULT, /* 0 gives lspci behaviour */ + VERBLEVEL_SENSORS, /* 1 lists sensors */ +} verblevel = VERBLEVEL_DEFAULT; + +const char *type_device = "iio:device"; +const char *type_trigger = "trigger"; + + +static inline int check_prefix(const char *str, const char *prefix) +{ + return strlen(str) > strlen(prefix) && + strncmp(str, prefix, strlen(prefix)) == 0; +} + +static inline int check_postfix(const char *str, const char *postfix) +{ + return strlen(str) > strlen(postfix) && + strcmp(str + strlen(str) - strlen(postfix), postfix) == 0; +} + +static int dump_channels(const char *dev_dir_name) +{ + DIR *dp; + const struct dirent *ent; + dp = opendir(dev_dir_name); + if (dp == NULL) + return -errno; + while (ent = readdir(dp), ent != NULL) + if (check_prefix(ent->d_name, "in_") && + check_postfix(ent->d_name, "_raw")) { + printf(" %-10s\n", ent->d_name); + } + + return 0; +} + +static int dump_one_device(const char *dev_dir_name) +{ + char name[IIO_MAX_NAME_LENGTH]; + int dev_idx; + + sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_device), + "%i", &dev_idx); + read_sysfs_string("name", dev_dir_name, name); + printf("Device %03d: %s\n", dev_idx, name); + + if (verblevel >= VERBLEVEL_SENSORS) { + int ret = dump_channels(dev_dir_name); + if (ret) + return ret; + } + return 0; +} + +static int dump_one_trigger(const char *dev_dir_name) +{ + char name[IIO_MAX_NAME_LENGTH]; + int dev_idx; + + sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_trigger), + "%i", &dev_idx); + read_sysfs_string("name", dev_dir_name, name); + printf("Trigger %03d: %s\n", dev_idx, name); + return 0; +} + +static void dump_devices(void) +{ + const struct dirent *ent; + int number, numstrlen; + + FILE *nameFile; + DIR *dp; + char thisname[IIO_MAX_NAME_LENGTH]; + char *filename; + + dp = opendir(iio_dir); + if (dp == NULL) { + printf("No industrial I/O devices available\n"); + return; + } + + while (ent = readdir(dp), ent != NULL) { + if (check_prefix(ent->d_name, type_device)) { + char *dev_dir_name; + asprintf(&dev_dir_name, "%s%s", iio_dir, ent->d_name); + dump_one_device(dev_dir_name); + free(dev_dir_name); + if (verblevel >= VERBLEVEL_SENSORS) + printf("\n"); + } + } + rewinddir(dp); + while (ent = readdir(dp), ent != NULL) { + if (check_prefix(ent->d_name, type_trigger)) { + char *dev_dir_name; + asprintf(&dev_dir_name, "%s%s", iio_dir, ent->d_name); + dump_one_trigger(dev_dir_name); + free(dev_dir_name); + } + } + closedir(dp); +} + +int main(int argc, char **argv) +{ + int c, err = 0; + + while ((c = getopt(argc, argv, "d:D:v")) != EOF) { + switch (c) { + case 'v': + verblevel++; + break; + + case '?': + default: + err++; + break; + } + } + if (err || argc > optind) { + fprintf(stderr, "Usage: lsiio [options]...\n" + "List industrial I/O devices\n" + " -v, --verbose\n" + " Increase verbosity (may be given multiple times)\n" + ); + exit(1); + } + + dump_devices(); + + return 0; +} diff --git a/drivers/staging/iio/Documentation/overview.txt b/drivers/staging/iio/Documentation/overview.txt index afc39ecde9c..43f92b06bc3 100644 --- a/drivers/staging/iio/Documentation/overview.txt +++ b/drivers/staging/iio/Documentation/overview.txt @@ -8,7 +8,7 @@ actual devices combine some ADCs with digital to analog converters The aim is to fill the gap between the somewhat similar hwmon and input subsystems. Hwmon is very much directed at low sample rate sensors used in applications such as fan speed control and temperature -measurement. Input is, as it's name suggests focused on input +measurement. Input is, as its name suggests focused on input devices. In some cases there is considerable overlap between these and IIO. diff --git a/drivers/staging/iio/Documentation/ring.txt b/drivers/staging/iio/Documentation/ring.txt index e33807761cd..e1da43381d0 100644 --- a/drivers/staging/iio/Documentation/ring.txt +++ b/drivers/staging/iio/Documentation/ring.txt @@ -15,8 +15,8 @@ struct iio_ring_buffer contains a struct iio_ring_setup_ops *setup_ops which in turn contains the 4 function pointers (preenable, postenable, predisable and postdisable). These are used to perform device specific steps on either side -of the core changing it's current mode to indicate that the buffer -is enabled or disabled (along with enabling triggering etc as appropriate). +of the core changing its current mode to indicate that the buffer +is enabled or disabled (along with enabling triggering etc. as appropriate). Also in struct iio_ring_buffer is a struct iio_ring_access_funcs. The function pointers within here are used to allow the core to handle diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio b/drivers/staging/iio/Documentation/sysfs-bus-iio deleted file mode 100644 index 46a995d6d26..00000000000 --- a/drivers/staging/iio/Documentation/sysfs-bus-iio +++ /dev/null @@ -1,741 +0,0 @@ -What: /sys/bus/iio/devices/iio:deviceX -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - Hardware chip or device accessed by one communication port. - Corresponds to a grouping of sensor channels. X is the IIO - index of the device. - -What: /sys/bus/iio/devices/triggerX -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. - X is the IIO index of the trigger. - -What: /sys/bus/iio/devices/iio:deviceX/buffer -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - Directory of attributes relating to the buffer for the device. - -What: /sys/bus/iio/devices/iio:deviceX/name -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - Description of the physical chip / device for device X. - Typically a part number. - -What: /sys/bus/iio/devices/iio:deviceX/sampling_frequency -What: /sys/bus/iio/devices/iio:deviceX/buffer/sampling_frequency -What: /sys/bus/iio/devices/triggerX/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. - -What: /sys/bus/iio/devices/iio:deviceX/sampling_frequency_available -What: /sys/.../iio:deviceX/buffer/sampling_frequency_available -What: /sys/bus/iio/devices/triggerX/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 available. - -What: /sys/bus/iio/devices/iio:deviceX/oversampling_ratio -KernelVersion: 2.6.38 -Contact: linux-iio@vger.kernel.org -Description: - Hardware dependent ADC oversampling. Controls the sampling ratio - of the digital filter if available. - -What: /sys/bus/iio/devices/iio:deviceX/oversampling_ratio_available -KernelVersion: 2.6.38 -Contact: linux-iio@vger.kernel.org -Description: - Hardware dependent values supported by the oversampling filter. - -What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_raw -What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_raw -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - Raw (unscaled no bias removal etc) voltage measurement from - channel Y. In special cases where the channel does not - correspond to externally available input one of the named - versions may be used. The number must always be specified and - unique to allow association with event codes. Units after - application of scale and offset are microvolts. - -What: /sys/bus/iio/devices/iio:deviceX/in_voltageY-voltageZ_raw -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - Raw (unscaled) differential voltage measurement equivalent to - channel Y - channel Z 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 labeling. Units after application - of scale and offset are microvolts. - -What: /sys/bus/iio/devices/iio:deviceX/in_capacitanceY_raw -KernelVersion: 3.2 -Contact: linux-iio@vger.kernel.org -Description: - Raw capacitance measurement from channel Y. Units after - application of scale and offset are nanofarads. - -What: /sys/.../iio:deviceX/in_capacitanceY-in_capacitanceZ_raw -KernelVersion: 3.2 -Contact: linux-iio@vger.kernel.org -Description: - Raw differential capacitance measurement equivalent to - channel Y - channel Z 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 labeling. Units after application - of scale and offset are nanofarads.. - -What: /sys/bus/iio/devices/iio:deviceX/in_temp_raw -What: /sys/bus/iio/devices/iio:deviceX/in_tempX_raw -What: /sys/bus/iio/devices/iio:deviceX/in_temp_x_raw -What: /sys/bus/iio/devices/iio:deviceX/in_temp_y_raw -What: /sys/bus/iio/devices/iio:deviceX/in_temp_z_raw -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - Raw (unscaled no bias removal etc) temperature measurement. - It an axis is specified it generally means that the temperature - sensor is associated with one part of a compound device (e.g. - a gyroscope axis). Units after application of scale and offset - are milli degrees Celsuis. - -What: /sys/bus/iio/devices/iio:deviceX/in_tempX_input -KernelVersion: 2.6.38 -Contact: linux-iio@vger.kernel.org -Description: - Scaled temperature measurement in milli degrees Celsius. - -What: /sys/bus/iio/devices/iio:deviceX/in_accel_x_raw -What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_raw -What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_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). - Has all of the equivalent parameters as per voltageY. Units - after application of scale and offset are m/s^2. - -What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_raw -What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_raw -What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_raw -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - Angular velocity about axis x, y or z (may be arbitrarily - assigned) Data converted by application of offset then scale to - radians per second. Has all the equivalent parameters as - per voltageY. Units after application of scale and offset are - radians per second. - -What: /sys/bus/iio/devices/iio:deviceX/in_incli_x_raw -What: /sys/bus/iio/devices/iio:deviceX/in_incli_y_raw -What: /sys/bus/iio/devices/iio:deviceX/in_incli_z_raw -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - Inclination raw reading about axis x, y or z (may be - arbitrarily assigned). Data converted by application of offset - and scale to Degrees. - -What: /sys/bus/iio/devices/iio:deviceX/in_magn_x_raw -What: /sys/bus/iio/devices/iio:deviceX/in_magn_y_raw -What: /sys/bus/iio/devices/iio:deviceX/in_magn_z_raw -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - Magnetic field along axis x, y or z (may be arbitrarily - assigned). Data converted by application of offset - then scale to Gauss. - -What: /sys/bus/iio/devices/iio:deviceX/in_accel_x_peak_raw -What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_peak_raw -What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_peak_raw -KernelVersion: 2.6.36 -Contact: linux-iio@vger.kernel.org -Description: - Highest value since some reset condition. These - attributes allow access to this and are otherwise - the direct equivalent of the <type>Y[_name]_raw attributes. - -What: /sys/bus/iio/devices/iio:deviceX/in_accel_xyz_squared_peak_raw -KernelVersion: 2.6.36 -Contact: linux-iio@vger.kernel.org -Description: - A computed peak value based on the sum squared magnitude of - the underlying value in the specified directions. - -What: /sys/bus/iio/devices/iio:deviceX/in_accel_offset -What: /sys/bus/iio/devices/iio:deviceX/in_accel_x_offset -What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_offset -What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_offset -What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_offset -What: /sys/bus/iio/devices/iio:deviceX/in_voltage_offset -What: /sys/bus/iio/devices/iio:deviceX/in_tempY_offset -What: /sys/bus/iio/devices/iio:deviceX/in_temp_offset -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - If known for a device, offset to be added to <type>[Y]_raw prior - to scaling by <type>[Y]_scale in order to obtain value in the - <type> units as specified in <type>[y]_raw documentation. - Not present if the offset is always 0 or unknown. If Y or - axis <x|y|z> is not present, then the offset applies to all - in channels of <type>. - May be writable if a variable offset can be applied on the - device. Note that this is different to calibbias which - is for devices (or drivers) that apply offsets to compensate - for variation between different instances of the part, typically - adjusted by using some hardware supported calibration procedure. - Calibbias is applied internally, offset is applied in userspace - to the _raw output. - -What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_scale -What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_scale -What: /sys/bus/iio/devices/iio:deviceX/in_voltage_scale -What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_scale -What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale -What: /sys/bus/iio/devices/iio:deviceX/in_accel_peak_scale -What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_scale -What: /sys/bus/iio/devices/iio:deviceX/in_magn_scale -What: /sys/bus/iio/devices/iio:deviceX/in_magn_x_scale -What: /sys/bus/iio/devices/iio:deviceX/in_magn_y_scale -What: /sys/bus/iio/devices/iio:deviceX/in_magn_z_scale -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - If known for a device, scale to be applied to <type>Y[_name]_raw - post addition of <type>[Y][_name]_offset in order to obtain the - measured value in <type> units as specified in - <type>[Y][_name]_raw documentation.. If shared across all in - channels then Y and <x|y|z> are not present and the value is - called <type>[Y][_name]_scale. The peak modifier means this - value is applied to <type>Y[_name]_peak_raw values. - -What: /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibbias -What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibbias -What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibbias -What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibbias -What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias -What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - Hardware applied calibration offset. (assumed to fix production - inaccuracies). - -What /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_voltage_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibscale -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - Hardware applied calibration scale factor. (assumed to fix - production inaccuracies). If shared across all channels, - <type>_calibscale is used. - -What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale_available -What: /sys/.../iio:deviceX/in_voltageX_scale_available -What: /sys/.../iio:deviceX/in_voltage-voltage_scale_available -What: /sys/.../iio:deviceX/out_voltageX_scale_available -What: /sys/.../iio:deviceX/in_capacitance_scale_available -KernelVersion: 2.635 -Contact: linux-iio@vger.kernel.org -Description: - If a discrete set of scale values are available, they - are listed in this attribute. - -What: /sys/.../in_accel_filter_low_pass_3db_frequency -What: /sys/.../in_magn_filter_low_pass_3db_frequency -What: /sys/.../in_anglvel_filter_low_pass_3db_frequency -KernelVersion: 3.2 -Contact: linux-iio@vger.kernel.org -Description: - If a known or controllable low pass filter is applied - to the underlying data channel, then this parameter - gives the 3dB frequency of the filter in Hz. - -What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_raw -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - Raw (unscaled, no bias etc.) output voltage for - channel Y. The number must always be specified and - unique if the output corresponds to a single channel. - -What: /sys/bus/iio/devices/iio:deviceX/out_voltageY&Z_raw -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - Raw (unscaled, no bias etc.) output voltage for an aggregate of - channel Y, channel Z, etc. This interface is available in cases - where a single output sets the value for multiple channels - simultaneously. - -What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_powerdown_mode -What: /sys/bus/iio/devices/iio:deviceX/out_voltage_powerdown_mode -KernelVersion: 2.6.38 -Contact: linux-iio@vger.kernel.org -Description: - Specifies the output powerdown mode. - DAC output stage is disconnected from the amplifier and - 1kohm_to_gnd: connected to ground via an 1kOhm resistor - 100kohm_to_gnd: connected to ground via an 100kOhm resistor - three_state: left floating - For a list of available output power down options read - outX_powerdown_mode_available. If Y is not present the - mode is shared across all outputs. - -What: /sys/.../iio:deviceX/out_votlageY_powerdown_mode_available -What: /sys/.../iio:deviceX/out_voltage_powerdown_mode_available -KernelVersion: 2.6.38 -Contact: linux-iio@vger.kernel.org -Description: - Lists all available output power down modes. - If Y is not present the mode is shared across all outputs. - -What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_powerdown -What: /sys/bus/iio/devices/iio:deviceX/out_voltage_powerdown -KernelVersion: 2.6.38 -Contact: linux-iio@vger.kernel.org -Description: - Writing 1 causes output Y to enter the power down mode specified - by the corresponding outY_powerdown_mode. Clearing returns to - normal operation. Y may be suppressed if all outputs are - controlled together. - -What: /sys/bus/iio/devices/iio:deviceX/events -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - Configuration of which hardware generated events are passed up - to user-space. - -What: /sys/.../iio:deviceX/events/in_accel_x_thresh_rising_en -What: /sys/.../iio:deviceX/events/in_accel_x_thresh_falling_en -What: /sys/.../iio:deviceX/events/in_accel_y_thresh_rising_en -What: /sys/.../iio:deviceX/events/in_accel_y_thresh_falling_en -What: /sys/.../iio:deviceX/events/in_accel_z_thresh_rising_en -What: /sys/.../iio:deviceX/events/in_accel_z_thresh_falling_en -What: /sys/.../iio:deviceX/events/in_anglvel_x_thresh_rising_en -What: /sys/.../iio:deviceX/events/in_anglvel_x_thresh_falling_en -What: /sys/.../iio:deviceX/events/in_anglvel_y_thresh_rising_en -What: /sys/.../iio:deviceX/events/in_anglvel_y_thresh_falling_en -What: /sys/.../iio:deviceX/events/in_anglvel_z_thresh_rising_en -What: /sys/.../iio:deviceX/events/in_anglvel_z_thresh_falling_en -What: /sys/.../iio:deviceX/events/in_magn_x_thresh_rising_en -What: /sys/.../iio:deviceX/events/in_magn_x_thresh_falling_en -What: /sys/.../iio:deviceX/events/in_magn_y_thresh_rising_en -What: /sys/.../iio:deviceX/events/in_magn_y_thresh_falling_en -What: /sys/.../iio:deviceX/events/in_magn_z_thresh_rising_en -What: /sys/.../iio:deviceX/events/in_magn_z_thresh_falling_en -What: /sys/.../iio:deviceX/events/in_voltageY_supply_thresh_rising_en -What: /sys/.../iio:deviceX/events/in_voltageY_supply_thresh_falling_en -What: /sys/.../iio:deviceX/events/in_voltageY_thresh_rising_en -What: /sys/.../iio:deviceX/events/in_voltageY_thresh_falling_en -What: /sys/.../iio:deviceX/events/in_tempY_thresh_rising_en -What: /sys/.../iio:deviceX/events/in_tempY_thresh_falling_en -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - Event generated when channel passes a threshold in the specified - (_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 passed in (e.g. - <type>[Y][_name]_<raw|input>_thresh_value) or - <type>[Y][_name]_<raw|input>_thresh_rising_value and - <type>[Y][_name]_<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/.../iio:deviceX/events/in_accel_x_roc_rising_en -What: /sys/.../iio:deviceX/events/in_accel_x_roc_falling_en -What: /sys/.../iio:deviceX/events/in_accel_y_roc_rising_en -What: /sys/.../iio:deviceX/events/in_accel_y_roc_falling_en -What: /sys/.../iio:deviceX/events/in_accel_z_roc_rising_en -What: /sys/.../iio:deviceX/events/in_accel_z_roc_falling_en -What: /sys/.../iio:deviceX/events/in_anglvel_x_roc_rising_en -What: /sys/.../iio:deviceX/events/in_anglvel_x_roc_falling_en -What: /sys/.../iio:deviceX/events/in_anglvel_y_roc_rising_en -What: /sys/.../iio:deviceX/events/in_anglvel_y_roc_falling_en -What: /sys/.../iio:deviceX/events/in_anglvel_z_roc_rising_en -What: /sys/.../iio:deviceX/events/in_anglvel_z_roc_falling_en -What: /sys/.../iio:deviceX/events/in_magn_x_roc_rising_en -What: /sys/.../iio:deviceX/events/in_magn_x_roc_falling_en -What: /sys/.../iio:deviceX/events/in_magn_y_roc_rising_en -What: /sys/.../iio:deviceX/events/in_magn_y_roc_falling_en -What: /sys/.../iio:deviceX/events/in_magn_z_roc_rising_en -What: /sys/.../iio:deviceX/events/in_magn_z_roc_falling_en -What: /sys/.../iio:deviceX/events/in_voltageY_supply_roc_rising_en -What: /sys/.../iio:deviceX/events/in_voltageY_supply_roc_falling_en -What: /sys/.../iio:deviceX/events/in_voltageY_roc_rising_en -What: /sys/.../iio:deviceX/events/in_voltageY_roc_falling_en -What: /sys/.../iio:deviceX/events/in_tempY_roc_rising_en -What: /sys/.../iio:deviceX/events/in_tempY_roc_falling_en -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - Event generated when channel passes a threshold on the rate of - change (1st differential) in the specified (_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 passed in (e.g. - <type>[Y][_name]_<raw|input>_roc_value) or - <type>[Y][_name]_<raw|input>_roc_rising_value and - <type>[Y][_name]_<raw|input>_roc_falling_value may take - different values, but the device can only enable both rate of - change 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/.../events/in_accel_x_raw_thresh_rising_value -What: /sys/.../events/in_accel_x_raw_thresh_falling_value -What: /sys/.../events/in_accel_y_raw_thresh_rising_value -What: /sys/.../events/in_accel_y_raw_thresh_falling_value -What: /sys/.../events/in_accel_z_raw_thresh_rising_value -What: /sys/.../events/in_accel_z_raw_thresh_falling_value -What: /sys/.../events/in_anglvel_x_raw_thresh_rising_value -What: /sys/.../events/in_anglvel_x_raw_thresh_falling_value -What: /sys/.../events/in_anglvel_y_raw_thresh_rising_value -What: /sys/.../events/in_anglvel_y_raw_thresh_falling_value -What: /sys/.../events/in_anglvel_z_raw_thresh_rising_value -What: /sys/.../events/in_anglvel_z_raw_thresh_falling_value -What: /sys/.../events/in_magn_x_raw_thresh_rising_value -What: /sys/.../events/in_magn_x_raw_thresh_falling_value -What: /sys/.../events/in_magn_y_raw_thresh_rising_value -What: /sys/.../events/in_magn_y_raw_thresh_falling_value -What: /sys/.../events/in_magn_z_raw_thresh_rising_value -What: /sys/.../events/in_magn_z_raw_thresh_falling_value -What: /sys/.../events/in_voltageY_supply_raw_thresh_rising_value -What: /sys/.../events/in_voltageY_supply_raw_thresh_falling_value -What: /sys/.../events/in_voltageY_raw_thresh_falling_value -What: /sys/.../events/in_voltageY_raw_thresh_falling_value -What: /sys/.../events/in_tempY_raw_thresh_falling_value -What: /sys/.../events/in_tempY_raw_thresh_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 - <type>Y[_name]_thresh[_rising|falling]_en. - If separate attributes 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/.../events/in_accel_x_raw_roc_rising_value -What: /sys/.../events/in_accel_x_raw_roc_falling_value -What: /sys/.../events/in_accel_y_raw_roc_rising_value -What: /sys/.../events/in_accel_y_raw_roc_falling_value -What: /sys/.../events/in_accel_z_raw_roc_rising_value -What: /sys/.../events/in_accel_z_raw_roc_falling_value -What: /sys/.../events/in_anglvel_x_raw_roc_rising_value -What: /sys/.../events/in_anglvel_x_raw_roc_falling_value -What: /sys/.../events/in_anglvel_y_raw_roc_rising_value -What: /sys/.../events/in_anglvel_y_raw_roc_falling_value -What: /sys/.../events/in_anglvel_z_raw_roc_rising_value -What: /sys/.../events/in_anglvel_z_raw_roc_falling_value -What: /sys/.../events/in_magn_x_raw_roc_rising_value -What: /sys/.../events/in_magn_x_raw_roc_falling_value -What: /sys/.../events/in_magn_y_raw_roc_rising_value -What: /sys/.../events/in_magn_y_raw_roc_falling_value -What: /sys/.../events/in_magn_z_raw_roc_rising_value -What: /sys/.../events/in_magn_z_raw_roc_falling_value -What: /sys/.../events/in_voltageY_supply_raw_roc_rising_value -What: /sys/.../events/in_voltageY_supply_raw_roc_falling_value -What: /sys/.../events/in_voltageY_raw_roc_falling_value -What: /sys/.../events/in_voltageY_raw_roc_falling_value -What: /sys/.../events/in_tempY_raw_roc_falling_value -What: /sys/.../events/in_tempY_raw_roc_falling_value -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - Specifies the value of rate of change threshold that the - device is comparing against for the events enabled by - <type>[Y][_name]_roc[_rising|falling]_en. - If separate attributes 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/.../events/in_accel_x_thresh_rising_period -What: /sys/.../events/in_accel_x_thresh_falling_period -hat: /sys/.../events/in_accel_x_roc_rising_period -What: /sys/.../events/in_accel_x_roc_falling_period -What: /sys/.../events/in_accel_y_thresh_rising_period -What: /sys/.../events/in_accel_y_thresh_falling_period -What: /sys/.../events/in_accel_y_roc_rising_period -What: /sys/.../events/in_accel_y_roc_falling_period -What: /sys/.../events/in_accel_z_thresh_rising_period -What: /sys/.../events/in_accel_z_thresh_falling_period -What: /sys/.../events/in_accel_z_roc_rising_period -What: /sys/.../events/in_accel_z_roc_falling_period -What: /sys/.../events/in_anglvel_x_thresh_rising_period -What: /sys/.../events/in_anglvel_x_thresh_falling_period -What: /sys/.../events/in_anglvel_x_roc_rising_period -What: /sys/.../events/in_anglvel_x_roc_falling_period -What: /sys/.../events/in_anglvel_y_thresh_rising_period -What: /sys/.../events/in_anglvel_y_thresh_falling_period -What: /sys/.../events/in_anglvel_y_roc_rising_period -What: /sys/.../events/in_anglvel_y_roc_falling_period -What: /sys/.../events/in_anglvel_z_thresh_rising_period -What: /sys/.../events/in_anglvel_z_thresh_falling_period -What: /sys/.../events/in_anglvel_z_roc_rising_period -What: /sys/.../events/in_anglvel_z_roc_falling_period -What: /sys/.../events/in_magn_x_thresh_rising_period -What: /sys/.../events/in_magn_x_thresh_falling_period -What: /sys/.../events/in_magn_x_roc_rising_period -What: /sys/.../events/in_magn_x_roc_falling_period -What: /sys/.../events/in_magn_y_thresh_rising_period -What: /sys/.../events/in_magn_y_thresh_falling_period -What: /sys/.../events/in_magn_y_roc_rising_period -What: /sys/.../events/in_magn_y_roc_falling_period -What: /sys/.../events/in_magn_z_thresh_rising_period -What: /sys/.../events/in_magn_z_thresh_falling_period -What: /sys/.../events/in_magn_z_roc_rising_period -What: /sys/.../events/in_magn_z_roc_falling_period -What: /sys/.../events/in_voltageY_supply_thresh_rising_period -What: /sys/.../events/in_voltageY_supply_thresh_falling_period -What: /sys/.../events/in_voltageY_supply_roc_rising_period -What: /sys/.../events/in_voltageY_supply_roc_falling_period -What: /sys/.../events/in_voltageY_thresh_rising_period -What: /sys/.../events/in_voltageY_thresh_falling_period -What: /sys/.../events/in_voltageY_roc_rising_period -What: /sys/.../events/in_voltageY_roc_falling_period -What: /sys/.../events/in_tempY_thresh_rising_period -What: /sys/.../events/in_tempY_thresh_falling_period -What: /sys/.../events/in_tempY_roc_rising_period -What: /sys/.../events/in_tempY_roc_falling_period -What: /sys/.../events/in_accel_x&y&z_mag_falling_period -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - Period of time (in seconds) for which the condition must be - met before an event is generated. If direction is not - specified then this period applies to both directions. - -What: /sys/.../iio:deviceX/events/in_accel_mag_en -What: /sys/.../iio:deviceX/events/in_accel_mag_rising_en -What: /sys/.../iio:deviceX/events/in_accel_mag_falling_en -What: /sys/.../iio:deviceX/events/in_accel_x_mag_en -What: /sys/.../iio:deviceX/events/in_accel_x_mag_rising_en -What: /sys/.../iio:deviceX/events/in_accel_x_mag_falling_en -What: /sys/.../iio:deviceX/events/in_accel_y_mag_en -What: /sys/.../iio:deviceX/events/in_accel_y_mag_rising_en -What: /sys/.../iio:deviceX/events/in_accel_y_mag_falling_en -What: /sys/.../iio:deviceX/events/in_accel_z_mag_en -What: /sys/.../iio:deviceX/events/in_accel_z_mag_rising_en -What: /sys/.../iio:deviceX/events/in_accel_z_mag_falling_en -What: /sys/.../iio:deviceX/events/in_accel_x&y&z_mag_rising_en -What: /sys/.../iio:deviceX/events/in_accel_x&y&z_mag_falling_en -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - Similar to in_accel_x_thresh[_rising|_falling]_en, but here the - magnitude of the channel is compared to the threshold, not its - signed value. - -What: /sys/.../events/in_accel_raw_mag_value -What: /sys/.../events/in_accel_x_raw_mag_rising_value -What: /sys/.../events/in_accel_y_raw_mag_rising_value -What: /sys/.../events/in_accel_z_raw_mag_rising_value -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - The value to which the magnitude of the channel is compared. If - number or direction is not specified, applies to all channels of - this type. - -What: /sys/bus/iio/devices/iio:deviceX/trigger/current_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/triggerY/name. - -What: /sys/bus/iio/devices/iio:deviceX/buffer/length -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - Number of scans contained by the buffer. - -What: /sys/bus/iio/devices/iio:deviceX/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/bus/iio/devices/iio:deviceX/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/bus/iio/devices/iio:deviceX/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/.../buffer/scan_elements/in_accel_x_en -What: /sys/.../buffer/scan_elements/in_accel_y_en -What: /sys/.../buffer/scan_elements/in_accel_z_en -What: /sys/.../buffer/scan_elements/in_anglvel_x_en -What: /sys/.../buffer/scan_elements/in_anglvel_y_en -What: /sys/.../buffer/scan_elements/in_anglvel_z_en -What: /sys/.../buffer/scan_elements/in_magn_x_en -What: /sys/.../buffer/scan_elements/in_magn_y_en -What: /sys/.../buffer/scan_elements/in_magn_z_en -What: /sys/.../buffer/scan_elements/in_timestamp_en -What: /sys/.../buffer/scan_elements/in_voltageY_supply_en -What: /sys/.../buffer/scan_elements/in_voltageY_en -What: /sys/.../buffer/scan_elements/in_voltageY-voltageZ_en -What: /sys/.../buffer/scan_elements/in_incli_x_en -What: /sys/.../buffer/scan_elements/in_incli_y_en -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - Scan element control for triggered data capture. - -What: /sys/.../buffer/scan_elements/in_accel_type -What: /sys/.../buffer/scan_elements/in_anglvel_type -What: /sys/.../buffer/scan_elements/in_magn_type -What: /sys/.../buffer/scan_elements/in_incli_type -What: /sys/.../buffer/scan_elements/in_voltageY_type -What: /sys/.../buffer/scan_elements/in_voltage-in_type -What: /sys/.../buffer/scan_elements/in_voltageY_supply_type -What: /sys/.../buffer/scan_elements/in_timestamp_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 user-space. - Form is [be|le]:[s|u]bits/storagebits[>>shift]. - be or le specifies big or little endian. 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. shift if specified, is the shift that - needs to be applied prior to masking out unused bits. Some - devices put their data in the middle of the transferred elements - with additional information on both sides. 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>>2 will be a - signed 48 bit integer stored in a 64 bit location aligned to - a a64 bit boundary. To obtain the clean value, shift right 2 - and apply a mask to zero the top 16 bits of the result. - For other storage combinations this attribute will be extended - appropriately. - -What: /sys/.../buffer/scan_elements/in_accel_type_available -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - If the type parameter can take one of a small set of values, - this attribute lists them. - -What: /sys/.../buffer/scan_elements/in_voltageY_index -What: /sys/.../buffer/scan_elements/in_voltageY_supply_index -What: /sys/.../buffer/scan_elements/in_accel_x_index -What: /sys/.../buffer/scan_elements/in_accel_y_index -What: /sys/.../buffer/scan_elements/in_accel_z_index -What: /sys/.../buffer/scan_elements/in_anglvel_x_index -What: /sys/.../buffer/scan_elements/in_anglvel_y_index -What: /sys/.../buffer/scan_elements/in_anglvel_z_index -What: /sys/.../buffer/scan_elements/in_magn_x_index -What: /sys/.../buffer/scan_elements/in_magn_y_index -What: /sys/.../buffer/scan_elements/in_magn_z_index -What: /sys/.../buffer/scan_elements/in_incli_x_index -What: /sys/.../buffer/scan_elements/in_incli_y_index -What: /sys/.../buffer/scan_elements/in_timestamp_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 dependent on - what is enabled and may not be contiguous. Thus for user-space - 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/.../iio:deviceX/in_anglvel_z_quadrature_correction_raw -KernelVersion: 2.6.38 -Contact: linux-iio@vger.kernel.org -Description: - This attribute is used to read the amount of quadrature error - present in the device at a given time. - -What: /sys/.../iio:deviceX/ac_excitation_en -KernelVersion: 3.1.0 -Contact: linux-iio@vger.kernel.org -Description: - This attribute, if available, is used to enable the AC - excitation mode found on some converters. In ac excitation mode, - the polarity of the excitation voltage is reversed on - alternate cycles, to eliminate DC errors. - -What: /sys/.../iio:deviceX/bridge_switch_en -KernelVersion: 3.1.0 -Contact: linux-iio@vger.kernel.org -Description: - This attribute, if available, is used to close or open the - bridge power down switch found on some converters. - In bridge applications, such as strain gauges and load cells, - the bridge itself consumes the majority of the current in the - system. To minimize the current consumption of the system, - the bridge can be disconnected (when it is not being used - using the bridge_switch_en attribute. diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-ad7192 b/drivers/staging/iio/Documentation/sysfs-bus-iio-ad7192 new file mode 100644 index 00000000000..1c35c507cc0 --- /dev/null +++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-ad7192 @@ -0,0 +1,20 @@ +What: /sys/.../iio:deviceX/ac_excitation_en +KernelVersion: 3.1.0 +Contact: linux-iio@vger.kernel.org +Description: + This attribute, if available, is used to enable the AC + excitation mode found on some converters. In ac excitation mode, + the polarity of the excitation voltage is reversed on + alternate cycles, to eliminate DC errors. + +What: /sys/.../iio:deviceX/bridge_switch_en +KernelVersion: 3.1.0 +Contact: linux-iio@vger.kernel.org +Description: + This attribute, if available, is used to close or open the + bridge power down switch found on some converters. + In bridge applications, such as strain gauges and load cells, + the bridge itself consumes the majority of the current in the + system. To minimize the current consumption of the system, + the bridge can be disconnected (when it is not being used + using the bridge_switch_en attribute. diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-dds b/drivers/staging/iio/Documentation/sysfs-bus-iio-dds index ffdd5478a35..ee8c509c673 100644 --- a/drivers/staging/iio/Documentation/sysfs-bus-iio-dds +++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-dds @@ -1,83 +1,86 @@ -What: /sys/bus/iio/devices/.../ddsX_freqY +What: /sys/bus/iio/devices/.../out_altvoltageX_frequencyY KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: Stores frequency into tuning word Y. - There will be more than one ddsX_freqY file, which allows for - pin controlled FSK Frequency Shift Keying - (ddsX_pincontrol_freq_en is active) or the user can control - the desired active tuning word by writing Y to the - ddsX_freqsymbol file. + There will be more than one out_altvoltageX_frequencyY file, + which allows for pin controlled FSK Frequency Shift Keying + (out_altvoltageX_pincontrol_frequency_en is active) or the user + can control the desired active tuning word by writing Y to the + out_altvoltageX_frequencysymbol file. -What: /sys/bus/iio/devices/.../ddsX_freqY_scale +What: /sys/bus/iio/devices/.../out_altvoltageX_frequencyY_scale KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: - Scale to be applied to ddsX_freqY in order to obtain the - desired value in Hz. If shared across all frequency registers - Y is not present. It is also possible X is not present if - shared across all channels. + Scale to be applied to out_altvoltageX_frequencyY in order to + obtain the desired value in Hz. If shared across all frequency + registers Y is not present. It is also possible X is not present + if shared across all channels. -What: /sys/bus/iio/devices/.../ddsX_freqsymbol +What: /sys/bus/iio/devices/.../out_altvoltageX_frequencysymbol KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: Specifies the active output frequency tuning word. The value - corresponds to the Y in ddsX_freqY. To exit this mode the user - can write ddsX_pincontrol_freq_en or ddsX_out_enable file. + corresponds to the Y in out_altvoltageX_frequencyY. + To exit this mode the user can write + out_altvoltageX_pincontrol_frequency_en or + out_altvoltageX_out_enable file. -What: /sys/bus/iio/devices/.../ddsX_phaseY +What: /sys/bus/iio/devices/.../out_altvoltageX_phaseY KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: Stores phase into Y. - There will be more than one ddsX_phaseY file, which allows for - pin controlled PSK Phase Shift Keying - (ddsX_pincontrol_phase_en is active) or the user can + There will be more than one out_altvoltageX_phaseY file, which + allows for pin controlled PSK Phase Shift Keying + (out_altvoltageX_pincontrol_phase_en is active) or the user can control the desired phase Y which is added to the phase - accumulator output by writing Y to the en_phase file. + accumulator output by writing Y to the phase_en file. -What: /sys/bus/iio/devices/.../ddsX_phaseY_scale +What: /sys/bus/iio/devices/.../out_altvoltageX_phaseY_scale KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: - Scale to be applied to ddsX_phaseY in order to obtain the - desired value in rad. If shared across all phase registers + Scale to be applied to out_altvoltageX_phaseY in order to obtain + the desired value in rad. If shared across all phase registers Y is not present. It is also possible X is not present if shared across all channels. -What: /sys/bus/iio/devices/.../ddsX_phasesymbol +What: /sys/bus/iio/devices/.../out_altvoltageX_phasesymbol KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: Specifies the active phase Y which is added to the phase accumulator output. The value corresponds to the Y in - ddsX_phaseY. To exit this mode the user can write - ddsX_pincontrol_phase_en or disable file. + out_altvoltageX_phaseY. To exit this mode the user can write + out_altvoltageX_pincontrol_phase_en or disable file. -What: /sys/bus/iio/devices/.../ddsX_pincontrol_en -What: /sys/bus/iio/devices/.../ddsX_pincontrol_freq_en -What: /sys/bus/iio/devices/.../ddsX_pincontrol_phase_en +What: /sys/bus/iio/devices/.../out_altvoltageX_pincontrol_en +What: /sys/bus/iio/devices/.../out_altvoltageX_pincontrol_frequency_en +What: /sys/bus/iio/devices/.../out_altvoltageX_pincontrol_phase_en KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: - ddsX_pincontrol_en: Both, the active frequency and phase is - controlled by the respective phase and frequency control inputs. - In case the device in question allows to independent controls, - then there are dedicated files (ddsX_pincontrol_freq_en, - ddsX_pincontrol_phase_en). + out_altvoltageX_pincontrol_en: Both, the active frequency and + phase is controlled by the respective phase and frequency + control inputs. In case the device in features independent + controls, then there are dedicated files + (out_altvoltageX_pincontrol_frequency_en, + out_altvoltageX_pincontrol_phase_en). -What: /sys/bus/iio/devices/.../ddsX_out_enable -What: /sys/bus/iio/devices/.../ddsX_outY_enable +What: /sys/bus/iio/devices/.../out_altvoltageX_out_enable +What: /sys/bus/iio/devices/.../out_altvoltageX_outY_enable KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: - ddsX_outY_enable controls signal generation on output Y of - channel X. Y may be suppressed if all channels are + out_altvoltageX_outY_enable controls signal generation on + output Y of channel X. Y may be suppressed if all channels are controlled together. -What: /sys/bus/iio/devices/.../ddsX_outY_wavetype +What: /sys/bus/iio/devices/.../out_altvoltageX_outY_wavetype KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: @@ -86,7 +89,7 @@ Description: For a list of available output waveform options read available_output_modes. -What: /sys/bus/iio/devices/.../ddsX_outY_wavetype_available +What: /sys/bus/iio/devices/.../out_altvoltageX_outY_wavetype_available KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-light b/drivers/staging/iio/Documentation/sysfs-bus-iio-light index edbf470e4e3..17e5c9c515d 100644 --- a/drivers/staging/iio/Documentation/sysfs-bus-iio-light +++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-light @@ -26,7 +26,7 @@ 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] +What: /sys/bus/iio/devices/device[n]/in_illuminance0[_input|_raw] KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: @@ -34,7 +34,7 @@ Description: 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 +What: /sys/.../device[n]/proximity_on_chip_ambient_infrared_suppression KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: @@ -45,7 +45,7 @@ Description: 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] +What: /sys/bus/iio/devices/device[n]/in_proximity[_input|_raw] KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: @@ -63,23 +63,45 @@ Description: and if expressed in SI units, should include _input. If this value is not in SI units, then it should include _raw. -What: /sys/bus/iio/devices/device[n]/illuminance0_target +What: /sys/bus/iio/devices/device[n]/in_illuminance0_target KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: This property gets/sets the last known external lux measurement used in/for calibration. -What: /sys/bus/iio/devices/device[n]/illuminance0_integration_time +What: /sys/bus/iio/devices/device[n]/in_illuminance0_integration_time KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: This property gets/sets the sensors ADC analog integration time. -What: /sys/bus/iio/devices/device[n]/illuminance0_calibscale +What: /sys/bus/iio/devices/device[n]/in_illuminance0_lux_table KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: - Hardware or software applied calibration scale factor assumed - to account for attenuation due to industrial design (glass - filters or aperture holes). + This property gets/sets the table of coefficients + used in calculating illuminance in lux. + +What: /sys/bus/iio/devices/device[n]/in_intensity_clear[_input|_raw] +What: /sys/bus/iio/devices/device[n]/in_intensity_red[_input|_raw] +What: /sys/bus/iio/devices/device[n]/in_intensity_green[_input|_raw] +What: /sys/bus/iio/devices/device[n]/in_intensity_blue[_input|_raw] +KernelVersion: 3.6.0 +Contact: linux-iio@vger.kernel.org +Description: + This property is supported by sensors that have a RGBC + 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 (irradiance, uW/mm^2), then it should + include _raw. + +What: /sys/bus/iio/devices/device[n]/in_cct0[_input|_raw] +KernelVersion: 3.6.0 +Contact: linux-iio@vger.kernel.org +Description: + This should return the correlated color temperature 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. + diff --git a/drivers/staging/iio/Documentation/trigger.txt b/drivers/staging/iio/Documentation/trigger.txt index fc2012ebc10..64e2e08fb4d 100644 --- a/drivers/staging/iio/Documentation/trigger.txt +++ b/drivers/staging/iio/Documentation/trigger.txt @@ -5,14 +5,11 @@ an IIO device. Whilst this can create device specific complexities such triggers are registered with the core in the same way as stand-alone triggers. -struct iio_trig *trig = iio_allocate_trigger("<trigger format string>", ...); +struct iio_trig *trig = iio_trigger_alloc("<trigger format string>", ...); allocates a trigger structure. The key elements to then fill in within a driver are: -trig->private_data - Device specific private data. - trig->owner Typically set to THIS_MODULE. Used to ensure correct ownership of core allocated resources. diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig index 90162aa8b2d..fa38be0982f 100644 --- a/drivers/staging/iio/Kconfig +++ b/drivers/staging/iio/Kconfig @@ -1,70 +1,16 @@ # -# Industrial I/O subsytem configuration +# Industrial I/O subsystem configuration # - -menuconfig IIO - tristate "Industrial I/O support" - depends on GENERIC_HARDIRQS - help - The industrial I/O subsystem provides a unified framework for - drivers for many different types of embedded sensors using a - number of different physical interfaces (i2c, spi, etc). See - drivers/staging/iio/Documentation for more information. -if IIO - -config IIO_BUFFER - bool "Enable buffer support within IIO" - help - Provide core support for various buffer based data - acquisition methods. - -if IIO_BUFFER - -config IIO_SW_RING - select IIO_TRIGGER - tristate "Industrial I/O lock free software ring" - help - Example software ring buffer implementation. The design aim - of this particular realization was to minimize write locking - with the intention that some devices would be able to write - in interrupt context. - -config IIO_KFIFO_BUF - select IIO_TRIGGER - tristate "Industrial I/O buffering based on kfifo" - help - A simple fifo based on kfifo. Use this if you want a fifo - rather than a ring buffer. Note that this currently provides - no buffer events so it is up to userspace to work out how - often to read from the buffer. - -endif # IIO_BUFFER - -config IIO_TRIGGER - boolean "Enable triggered sampling support" - help - Provides IIO core support for triggers. Currently these - are used to initialize capture of samples to push into - ring buffers. The triggers are effectively a 'capture - data now' interrupt. - -config IIO_CONSUMERS_PER_TRIGGER - int "Maximum number of consumers per trigger" - depends on IIO_TRIGGER - default "2" - help - This value controls the maximum number of consumers that a - given trigger may handle. Default is 2. +menu "IIO staging drivers" + depends on IIO source "drivers/staging/iio/accel/Kconfig" source "drivers/staging/iio/adc/Kconfig" source "drivers/staging/iio/addac/Kconfig" source "drivers/staging/iio/cdc/Kconfig" -source "drivers/staging/iio/dac/Kconfig" -source "drivers/staging/iio/dds/Kconfig" +source "drivers/staging/iio/frequency/Kconfig" source "drivers/staging/iio/gyro/Kconfig" source "drivers/staging/iio/impedance-analyzer/Kconfig" -source "drivers/staging/iio/imu/Kconfig" source "drivers/staging/iio/light/Kconfig" source "drivers/staging/iio/magnetometer/Kconfig" source "drivers/staging/iio/meter/Kconfig" @@ -79,7 +25,7 @@ config IIO_SIMPLE_DUMMY help Driver intended mainly as documentation for how to write a driver. May also be useful for testing userspace code - without hardward. + without hardware. if IIO_SIMPLE_DUMMY @@ -90,11 +36,12 @@ config IIO_SIMPLE_DUMMY_EVENTS Add some dummy events to the simple dummy driver. config IIO_SIMPLE_DUMMY_BUFFER - boolean "Buffered capture support" - depends on IIO_KFIFO_BUF - help - Add buffered data capture to the simple dummy driver. + boolean "Buffered capture support" + select IIO_BUFFER + select IIO_KFIFO_BUF + help + Add buffered data capture to the simple dummy driver. endif # IIO_SIMPLE_DUMMY -endif # IIO +endmenu diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile index 1340aead18b..d87106135b2 100644 --- a/drivers/staging/iio/Makefile +++ b/drivers/staging/iio/Makefile @@ -2,14 +2,6 @@ # Makefile for the industrial I/O core. # -obj-$(CONFIG_IIO) += industrialio.o -industrialio-y := industrialio-core.o -industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o -industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o - -obj-$(CONFIG_IIO_SW_RING) += ring_sw.o -obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o - obj-$(CONFIG_IIO_SIMPLE_DUMMY) += iio_dummy.o iio_dummy-y := iio_simple_dummy.o iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_EVENTS) += iio_simple_dummy_events.o @@ -21,11 +13,9 @@ obj-y += accel/ obj-y += adc/ obj-y += addac/ obj-y += cdc/ -obj-y += dac/ -obj-y += dds/ +obj-y += frequency/ obj-y += gyro/ obj-y += impedance-analyzer/ -obj-y += imu/ obj-y += light/ obj-y += magnetometer/ obj-y += meter/ diff --git a/drivers/staging/iio/TODO b/drivers/staging/iio/TODO index d1ad35e24ab..c22a0edd152 100644 --- a/drivers/staging/iio/TODO +++ b/drivers/staging/iio/TODO @@ -13,6 +13,17 @@ Would be nice 3) Expand device set. Lots of other maxim adc's have very similar interfaces. +MXS LRADC driver: +This is a classic MFD device as it combines the following subdevices + - touchscreen controller (input subsystem related device) + - general purpose ADC channels + - battery voltage monitor (power subsystem related device) + - die temperature monitor (thermal management) + +At least the battery voltage and die temperature feature is required in-kernel +by a driver of the SoC's battery charging unit to avoid any damage to the +silicon and the battery. + TSL2561 Would be nice 1) Open question of userspace vs kernel space balance when @@ -67,7 +78,7 @@ e-mailing the normal IIO list (see below). Documentation 1) Lots of cleanup and expansion. -2) Some device require indvidual docs. +2) Some device require individual docs. -Contact: Jonathan Cameron <jic23@cam.ac.uk>. +Contact: Jonathan Cameron <jic23@kernel.org>. Mailing list: linux-iio@vger.kernel.org diff --git a/drivers/staging/iio/accel/Kconfig b/drivers/staging/iio/accel/Kconfig index 5ab71670b70..ad45dfbdf41 100644 --- a/drivers/staging/iio/accel/Kconfig +++ b/drivers/staging/iio/accel/Kconfig @@ -6,8 +6,8 @@ menu "Accelerometers" config ADIS16201 tristate "Analog Devices ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer" depends on SPI - select IIO_TRIGGER if IIO_BUFFER - select IIO_SW_RING if IIO_BUFFER + select IIO_ADIS_LIB + select IIO_ADIS_LIB_BUFFER if IIO_BUFFER help Say yes here to build support for Analog Devices adis16201 dual-axis digital inclinometer and accelerometer. @@ -15,8 +15,8 @@ config ADIS16201 config ADIS16203 tristate "Analog Devices ADIS16203 Programmable 360 Degrees Inclinometer" depends on SPI - select IIO_TRIGGER if IIO_BUFFER - select IIO_SW_RING if IIO_BUFFER + select IIO_ADIS_LIB + select IIO_ADIS_LIB_BUFFER if IIO_BUFFER help Say yes here to build support for Analog Devices adis16203 Programmable 360 Degrees Inclinometer. @@ -24,8 +24,8 @@ config ADIS16203 config ADIS16204 tristate "Analog Devices ADIS16204 Programmable High-g Digital Impact Sensor and Recorder" depends on SPI - select IIO_TRIGGER if IIO_BUFFER - select IIO_SW_RING if IIO_BUFFER + select IIO_ADIS_LIB + select IIO_ADIS_LIB_BUFFER if IIO_BUFFER help Say yes here to build support for Analog Devices adis16204 Programmable High-g Digital Impact Sensor and Recorder. @@ -33,8 +33,8 @@ config ADIS16204 config ADIS16209 tristate "Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer" depends on SPI - select IIO_TRIGGER if IIO_BUFFER - select IIO_SW_RING if IIO_BUFFER + select IIO_ADIS_LIB + select IIO_ADIS_LIB_BUFFER if IIO_BUFFER help Say yes here to build support for Analog Devices adis16209 dual-axis digital inclinometer and accelerometer. @@ -42,6 +42,7 @@ config ADIS16209 config ADIS16220 tristate "Analog Devices ADIS16220 Programmable Digital Vibration Sensor" depends on SPI + select IIO_ADIS_LIB help Say yes here to build support for Analog Devices adis16220 programmable digital vibration sensor. @@ -49,51 +50,23 @@ config ADIS16220 config ADIS16240 tristate "Analog Devices ADIS16240 Programmable Impact Sensor and Recorder" depends on SPI - select IIO_TRIGGER if IIO_BUFFER - select IIO_SW_RING if IIO_BUFFER + select IIO_ADIS_LIB + select IIO_ADIS_LIB_BUFFER if IIO_BUFFER help Say yes here to build support for Analog Devices adis16240 programmable impact Sensor and recorder. -config KXSD9 - tristate "Kionix KXSD9 Accelerometer Driver" - depends on SPI - help - Say yes here to build support for the Kionix KXSD9 accelerometer. - Currently this only supports the device via an SPI interface. - config LIS3L02DQ tristate "ST Microelectronics LIS3L02DQ Accelerometer Driver" depends on SPI select IIO_TRIGGER if IIO_BUFFER - depends on !IIO_BUFFER || IIO_KFIFO_BUF || IIO_SW_RING - depends on GENERIC_GPIO + depends on !IIO_BUFFER || IIO_KFIFO_BUF + depends on GPIOLIB help Say yes here to build SPI support for the ST microelectronics accelerometer. The driver supplies direct access via sysfs files and an event interface via a character device. -choice - prompt "Buffer type" - depends on LIS3L02DQ && IIO_BUFFER - -config LIS3L02DQ_BUF_KFIFO - depends on IIO_KFIFO_BUF - bool "Simple FIFO" - help - Kfifo based FIFO. Does not provide any events so it is up - to userspace to ensure it reads often enough that data is not - lost. - -config LIS3L02DQ_BUF_RING_SW - depends on IIO_SW_RING - bool "IIO Software Ring" - help - Original IIO ring buffer implementation. Provides simple - buffer events, half full etc. - -endchoice - config SCA3000 depends on IIO_BUFFER depends on SPI diff --git a/drivers/staging/iio/accel/Makefile b/drivers/staging/iio/accel/Makefile index 95c66661e70..1ed137f1a50 100644 --- a/drivers/staging/iio/accel/Makefile +++ b/drivers/staging/iio/accel/Makefile @@ -3,30 +3,23 @@ # adis16201-y := adis16201_core.o -adis16201-$(CONFIG_IIO_BUFFER) += adis16201_ring.o adis16201_trigger.o obj-$(CONFIG_ADIS16201) += adis16201.o adis16203-y := adis16203_core.o -adis16203-$(CONFIG_IIO_BUFFER) += adis16203_ring.o adis16203_trigger.o obj-$(CONFIG_ADIS16203) += adis16203.o adis16204-y := adis16204_core.o -adis16204-$(CONFIG_IIO_BUFFER) += adis16204_ring.o adis16204_trigger.o obj-$(CONFIG_ADIS16204) += adis16204.o adis16209-y := adis16209_core.o -adis16209-$(CONFIG_IIO_BUFFER) += adis16209_ring.o adis16209_trigger.o obj-$(CONFIG_ADIS16209) += adis16209.o adis16220-y := adis16220_core.o obj-$(CONFIG_ADIS16220) += adis16220.o adis16240-y := adis16240_core.o -adis16240-$(CONFIG_IIO_BUFFER) += adis16240_ring.o adis16240_trigger.o obj-$(CONFIG_ADIS16240) += adis16240.o -obj-$(CONFIG_KXSD9) += kxsd9.o - lis3l02dq-y := lis3l02dq_core.o lis3l02dq-$(CONFIG_IIO_BUFFER) += lis3l02dq_ring.o obj-$(CONFIG_LIS3L02DQ) += lis3l02dq.o diff --git a/drivers/staging/iio/accel/adis16201.h b/drivers/staging/iio/accel/adis16201.h index 72750f7f3a8..8747de5a980 100644 --- a/drivers/staging/iio/accel/adis16201.h +++ b/drivers/staging/iio/accel/adis16201.h @@ -3,9 +3,6 @@ #define ADIS16201_STARTUP_DELAY 220 /* ms */ -#define ADIS16201_READ_REG(a) a -#define ADIS16201_WRITE_REG(a) ((a) | 0x80) - #define ADIS16201_FLASH_CNT 0x00 /* Flash memory write count */ #define ADIS16201_SUPPLY_OUT 0x02 /* Output, power supply */ #define ADIS16201_XACCL_OUT 0x04 /* Output, x-axis accelerometer */ @@ -36,8 +33,6 @@ #define ADIS16201_DIAG_STAT 0x3C /* Diagnostics, system status register */ #define ADIS16201_GLOB_CMD 0x3E /* Operation, system command register */ -#define ADIS16201_OUTPUTS 7 - /* MSC_CTRL */ #define ADIS16201_MSC_CTRL_SELF_TEST_EN (1 << 8) /* Self-test enable */ #define ADIS16201_MSC_CTRL_DATA_RDY_EN (1 << 2) /* Data-ready enable: 1 = enabled, 0 = disabled */ @@ -47,95 +42,25 @@ /* DIAG_STAT */ #define ADIS16201_DIAG_STAT_ALARM2 (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ #define ADIS16201_DIAG_STAT_ALARM1 (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ -#define ADIS16201_DIAG_STAT_SPI_FAIL (1<<3) /* SPI communications failure */ -#define ADIS16201_DIAG_STAT_FLASH_UPT (1<<2) /* Flash update failure */ -#define ADIS16201_DIAG_STAT_POWER_HIGH (1<<1) /* Power supply above 3.625 V */ -#define ADIS16201_DIAG_STAT_POWER_LOW (1<<0) /* Power supply below 3.15 V */ +#define ADIS16201_DIAG_STAT_SPI_FAIL_BIT 3 /* SPI communications failure */ +#define ADIS16201_DIAG_STAT_FLASH_UPT_BIT 2 /* Flash update failure */ +#define ADIS16201_DIAG_STAT_POWER_HIGH_BIT 1 /* Power supply above 3.625 V */ +#define ADIS16201_DIAG_STAT_POWER_LOW_BIT 0 /* Power supply below 3.15 V */ /* GLOB_CMD */ #define ADIS16201_GLOB_CMD_SW_RESET (1<<7) #define ADIS16201_GLOB_CMD_FACTORY_CAL (1<<1) -#define ADIS16201_MAX_TX 14 -#define ADIS16201_MAX_RX 14 - #define ADIS16201_ERROR_ACTIVE (1<<14) -/** - * struct adis16201_state - device instance specific data - * @us: actual spi_device - * @trig: data ready trigger registered with iio - * @tx: transmit buffer - * @rx: receive buffer - * @buf_lock: mutex to protect tx and rx - **/ -struct adis16201_state { - struct spi_device *us; - struct iio_trigger *trig; - struct mutex buf_lock; - u8 tx[14] ____cacheline_aligned; - u8 rx[14]; -}; - -int adis16201_set_irq(struct iio_dev *indio_dev, bool enable); - enum adis16201_scan { - ADIS16201_SCAN_SUPPLY, ADIS16201_SCAN_ACC_X, ADIS16201_SCAN_ACC_Y, - ADIS16201_SCAN_AUX_ADC, - ADIS16201_SCAN_TEMP, ADIS16201_SCAN_INCLI_X, ADIS16201_SCAN_INCLI_Y, + ADIS16201_SCAN_SUPPLY, + ADIS16201_SCAN_AUX_ADC, + ADIS16201_SCAN_TEMP, }; -#ifdef CONFIG_IIO_BUFFER -void adis16201_remove_trigger(struct iio_dev *indio_dev); -int adis16201_probe_trigger(struct iio_dev *indio_dev); - -ssize_t adis16201_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf); - -int adis16201_configure_ring(struct iio_dev *indio_dev); -void adis16201_unconfigure_ring(struct iio_dev *indio_dev); - -#else /* CONFIG_IIO_BUFFER */ - -static inline void adis16201_remove_trigger(struct iio_dev *indio_dev) -{ -} - -static inline int adis16201_probe_trigger(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline ssize_t -adis16201_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return 0; -} - -static int adis16201_configure_ring(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline void adis16201_unconfigure_ring(struct iio_dev *indio_dev) -{ -} - -static inline int adis16201_initialize_ring(struct iio_ring_buffer *ring) -{ - return 0; -} - -static inline void adis16201_uninitialize_ring(struct iio_ring_buffer *ring) -{ -} - -#endif /* CONFIG_IIO_BUFFER */ #endif /* SPI_ADIS16201_H_ */ diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c index d439e45d07f..2105576fa77 100644 --- a/drivers/staging/iio/accel/adis16201_core.c +++ b/drivers/staging/iio/accel/adis16201_core.c @@ -15,276 +15,18 @@ #include <linux/sysfs.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> +#include <linux/iio/imu/adis.h> #include "adis16201.h" -enum adis16201_chan { - in_supply, - temp, - accel_x, - accel_y, - incli_x, - incli_y, - in_aux, -}; - -/** - * adis16201_spi_write_reg_8() - write single byte to a register - * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @reg_address: the address of the register to be written - * @val: the value to write - **/ -static int adis16201_spi_write_reg_8(struct iio_dev *indio_dev, - u8 reg_address, - u8 val) -{ - int ret; - struct adis16201_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16201_WRITE_REG(reg_address); - st->tx[1] = val; - - ret = spi_write(st->us, st->tx, 2); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/** - * adis16201_spi_write_reg_16() - write 2 bytes to a pair of registers - * @indio_dev: iio device associated with child of actual device - * @reg_address: the address of the lower of the two registers. Second register - * is assumed to have address one greater. - * @val: value to be written - **/ -static int adis16201_spi_write_reg_16(struct iio_dev *indio_dev, - u8 lower_reg_address, - u16 value) -{ - int ret; - struct spi_message msg; - struct adis16201_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - }, { - .tx_buf = st->tx + 2, - .bits_per_word = 8, - .len = 2, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16201_WRITE_REG(lower_reg_address); - st->tx[1] = value & 0xFF; - st->tx[2] = ADIS16201_WRITE_REG(lower_reg_address + 1); - st->tx[3] = (value >> 8) & 0xFF; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/** - * adis16201_spi_read_reg_16() - read 2 bytes from a 16-bit register - * @indio_dev: iio device associated with child of actual device - * @reg_address: the address of the lower of the two registers. Second register - * is assumed to have address one greater. - * @val: somewhere to pass back the value read - **/ -static int adis16201_spi_read_reg_16(struct iio_dev *indio_dev, - u8 lower_reg_address, - u16 *val) -{ - struct spi_message msg; - struct adis16201_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 20, - }, { - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 2, - .delay_usecs = 20, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16201_READ_REG(lower_reg_address); - st->tx[1] = 0; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - if (ret) { - dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", - lower_reg_address); - goto error_ret; - } - *val = (st->rx[0] << 8) | st->rx[1]; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -static int adis16201_reset(struct iio_dev *indio_dev) -{ - int ret; - struct adis16201_state *st = iio_priv(indio_dev); - - ret = adis16201_spi_write_reg_8(indio_dev, - ADIS16201_GLOB_CMD, - ADIS16201_GLOB_CMD_SW_RESET); - if (ret) - dev_err(&st->us->dev, "problem resetting device"); - - return ret; -} - -static ssize_t adis16201_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - int ret; - bool res; - - if (len < 1) - return -EINVAL; - ret = strtobool(buf, &res); - if (ret || !res) - return ret; - return adis16201_reset(dev_get_drvdata(dev)); -} - -int adis16201_set_irq(struct iio_dev *indio_dev, bool enable) -{ - int ret = 0; - u16 msc; - - ret = adis16201_spi_read_reg_16(indio_dev, ADIS16201_MSC_CTRL, &msc); - if (ret) - goto error_ret; - - msc |= ADIS16201_MSC_CTRL_ACTIVE_HIGH; - msc &= ~ADIS16201_MSC_CTRL_DATA_RDY_DIO1; - if (enable) - msc |= ADIS16201_MSC_CTRL_DATA_RDY_EN; - else - msc &= ~ADIS16201_MSC_CTRL_DATA_RDY_EN; - - ret = adis16201_spi_write_reg_16(indio_dev, ADIS16201_MSC_CTRL, msc); - -error_ret: - return ret; -} - -static int adis16201_check_status(struct iio_dev *indio_dev) -{ - u16 status; - int ret; - - ret = adis16201_spi_read_reg_16(indio_dev, - ADIS16201_DIAG_STAT, &status); - if (ret < 0) { - dev_err(&indio_dev->dev, "Reading status failed\n"); - goto error_ret; - } - ret = status & 0xF; - if (ret) - ret = -EFAULT; - - if (status & ADIS16201_DIAG_STAT_SPI_FAIL) - dev_err(&indio_dev->dev, "SPI failure\n"); - if (status & ADIS16201_DIAG_STAT_FLASH_UPT) - dev_err(&indio_dev->dev, "Flash update failed\n"); - if (status & ADIS16201_DIAG_STAT_POWER_HIGH) - dev_err(&indio_dev->dev, "Power supply above 3.625V\n"); - if (status & ADIS16201_DIAG_STAT_POWER_LOW) - dev_err(&indio_dev->dev, "Power supply below 3.15V\n"); - -error_ret: - return ret; -} - -static int adis16201_self_test(struct iio_dev *indio_dev) -{ - int ret; - ret = adis16201_spi_write_reg_16(indio_dev, - ADIS16201_MSC_CTRL, - ADIS16201_MSC_CTRL_SELF_TEST_EN); - if (ret) { - dev_err(&indio_dev->dev, "problem starting self test"); - goto err_ret; - } - - ret = adis16201_check_status(indio_dev); - -err_ret: - return ret; -} - -static int adis16201_initial_setup(struct iio_dev *indio_dev) -{ - int ret; - struct device *dev = &indio_dev->dev; - - /* Disable IRQ */ - ret = adis16201_set_irq(indio_dev, false); - if (ret) { - dev_err(dev, "disable irq failed"); - goto err_ret; - } - - /* Do self test */ - ret = adis16201_self_test(indio_dev); - if (ret) { - dev_err(dev, "self test failure"); - goto err_ret; - } - - /* Read status register to check the result */ - ret = adis16201_check_status(indio_dev); - if (ret) { - adis16201_reset(indio_dev); - dev_err(dev, "device not playing ball -> reset"); - msleep(ADIS16201_STARTUP_DELAY); - ret = adis16201_check_status(indio_dev); - if (ret) { - dev_err(dev, "giving up"); - goto err_ret; - } - } - -err_ret: - return ret; -} - -static u8 adis16201_addresses[7][2] = { - [in_supply] = { ADIS16201_SUPPLY_OUT, }, - [temp] = { ADIS16201_TEMP_OUT }, - [accel_x] = { ADIS16201_XACCL_OUT, ADIS16201_XACCL_OFFS }, - [accel_y] = { ADIS16201_YACCL_OUT, ADIS16201_YACCL_OFFS }, - [in_aux] = { ADIS16201_AUX_ADC }, - [incli_x] = { ADIS16201_XINCL_OUT }, - [incli_y] = { ADIS16201_YINCL_OUT }, +static const u8 adis16201_addresses[] = { + [ADIS16201_SCAN_ACC_X] = ADIS16201_XACCL_OFFS, + [ADIS16201_SCAN_ACC_Y] = ADIS16201_YACCL_OFFS, + [ADIS16201_SCAN_INCLI_X] = ADIS16201_XINCL_OFFS, + [ADIS16201_SCAN_INCLI_Y] = ADIS16201_YINCL_OFFS, }; static int adis16201_read_raw(struct iio_dev *indio_dev, @@ -292,63 +34,45 @@ static int adis16201_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { + struct adis *st = iio_priv(indio_dev); int ret; int bits; u8 addr; s16 val16; switch (mask) { - case 0: - mutex_lock(&indio_dev->mlock); - addr = adis16201_addresses[chan->address][0]; - ret = adis16201_spi_read_reg_16(indio_dev, addr, &val16); - if (ret) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - - if (val16 & ADIS16201_ERROR_ACTIVE) { - ret = adis16201_check_status(indio_dev); - if (ret) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - } - val16 = val16 & ((1 << chan->scan_type.realbits) - 1); - if (chan->scan_type.sign == 's') - val16 = (s16)(val16 << - (16 - chan->scan_type.realbits)) >> - (16 - chan->scan_type.realbits); - *val = val16; - mutex_unlock(&indio_dev->mlock); - return IIO_VAL_INT; + case IIO_CHAN_INFO_RAW: + return adis_single_conversion(indio_dev, chan, + ADIS16201_ERROR_ACTIVE, val); case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: - *val = 0; - if (chan->channel == 0) - *val2 = 1220; - else - *val2 = 610; + if (chan->channel == 0) { + *val = 1; + *val2 = 220000; /* 1.22 mV */ + } else { + *val = 0; + *val2 = 610000; /* 0.610 mV */ + } return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 0; - *val2 = -470000; + *val = -470; /* 0.47 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: *val = 0; - *val2 = 462500; - return IIO_VAL_INT_PLUS_MICRO; + *val2 = IIO_G_TO_M_S_2(462400); /* 0.4624 mg */ + return IIO_VAL_INT_PLUS_NANO; case IIO_INCLI: *val = 0; - *val2 = 100000; + *val2 = 100000; /* 0.1 degree */ return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } break; case IIO_CHAN_INFO_OFFSET: - *val = 25; + *val = 25000 / -470 - 1278; /* 25 C = 1278 */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { @@ -360,10 +84,10 @@ static int adis16201_read_raw(struct iio_dev *indio_dev, break; default: return -EINVAL; - }; + } mutex_lock(&indio_dev->mlock); - addr = adis16201_addresses[chan->address][1]; - ret = adis16201_spi_read_reg_16(indio_dev, addr, &val16); + addr = adis16201_addresses[chan->scan_index]; + ret = adis_read_reg_16(st, addr, &val16); if (ret) { mutex_unlock(&indio_dev->mlock); return ret; @@ -383,6 +107,7 @@ static int adis16201_write_raw(struct iio_dev *indio_dev, int val2, long mask) { + struct adis *st = iio_priv(indio_dev); int bits; s16 val16; u8 addr; @@ -397,88 +122,74 @@ static int adis16201_write_raw(struct iio_dev *indio_dev, break; default: return -EINVAL; - }; + } val16 = val & ((1 << bits) - 1); - addr = adis16201_addresses[chan->address][1]; - return adis16201_spi_write_reg_16(indio_dev, addr, val16); + addr = adis16201_addresses[chan->scan_index]; + return adis_write_reg_16(st, addr, val16); } return -EINVAL; } -static struct iio_chan_spec adis16201_channels[] = { - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - in_supply, ADIS16201_SCAN_SUPPLY, - IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT | - IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, - temp, ADIS16201_SCAN_TEMP, - IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, - accel_x, ADIS16201_SCAN_ACC_X, - IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, - accel_y, ADIS16201_SCAN_ACC_Y, - IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - in_aux, ADIS16201_SCAN_AUX_ADC, - IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X, - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, - incli_x, ADIS16201_SCAN_INCLI_X, - IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y, - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, - incli_y, ADIS16201_SCAN_INCLI_Y, - IIO_ST('s', 14, 16, 0), 0), +static const struct iio_chan_spec adis16201_channels[] = { + ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 12), + ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 12), + ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT, ADIS16201_SCAN_ACC_X, + BIT(IIO_CHAN_INFO_CALIBBIAS), 14), + ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT, ADIS16201_SCAN_ACC_Y, + BIT(IIO_CHAN_INFO_CALIBBIAS), 14), + ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC, ADIS16201_SCAN_AUX_ADC, 12), + ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT, ADIS16201_SCAN_INCLI_X, + BIT(IIO_CHAN_INFO_CALIBBIAS), 14), + ADIS_INCLI_CHAN(X, ADIS16201_YINCL_OUT, ADIS16201_SCAN_INCLI_Y, + BIT(IIO_CHAN_INFO_CALIBBIAS), 14), IIO_CHAN_SOFT_TIMESTAMP(7) }; -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16201_write_reset, 0); - -static struct attribute *adis16201_attributes[] = { - &iio_dev_attr_reset.dev_attr.attr, - NULL -}; - -static const struct attribute_group adis16201_attribute_group = { - .attrs = adis16201_attributes, -}; - static const struct iio_info adis16201_info = { - .attrs = &adis16201_attribute_group, .read_raw = &adis16201_read_raw, .write_raw = &adis16201_write_raw, + .update_scan_mode = adis_update_scan_mode, .driver_module = THIS_MODULE, }; -static int __devinit adis16201_probe(struct spi_device *spi) +static const char * const adis16201_status_error_msgs[] = { + [ADIS16201_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure", + [ADIS16201_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed", + [ADIS16201_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V", + [ADIS16201_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V", +}; + +static const struct adis_data adis16201_data = { + .read_delay = 20, + .msc_ctrl_reg = ADIS16201_MSC_CTRL, + .glob_cmd_reg = ADIS16201_GLOB_CMD, + .diag_stat_reg = ADIS16201_DIAG_STAT, + + .self_test_mask = ADIS16201_MSC_CTRL_SELF_TEST_EN, + .startup_delay = ADIS16201_STARTUP_DELAY, + + .status_error_msgs = adis16201_status_error_msgs, + .status_error_mask = BIT(ADIS16201_DIAG_STAT_SPI_FAIL_BIT) | + BIT(ADIS16201_DIAG_STAT_FLASH_UPT_BIT) | + BIT(ADIS16201_DIAG_STAT_POWER_HIGH_BIT) | + BIT(ADIS16201_DIAG_STAT_POWER_LOW_BIT), +}; + +static int adis16201_probe(struct spi_device *spi) { int ret; - struct adis16201_state *st; + struct adis *st; struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + st = iio_priv(indio_dev); /* this is only used for removal purposes */ spi_set_drvdata(spi, indio_dev); - st->us = spi; - mutex_init(&st->buf_lock); - indio_dev->name = spi->dev.driver->name; indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16201_info; @@ -487,55 +198,35 @@ static int __devinit adis16201_probe(struct spi_device *spi) indio_dev->num_channels = ARRAY_SIZE(adis16201_channels); indio_dev->modes = INDIO_DIRECT_MODE; - ret = adis16201_configure_ring(indio_dev); + ret = adis_init(st, indio_dev, spi, &adis16201_data); if (ret) - goto error_free_dev; - - ret = iio_buffer_register(indio_dev, - adis16201_channels, - ARRAY_SIZE(adis16201_channels)); - if (ret) { - printk(KERN_ERR "failed to initialize the ring\n"); - goto error_unreg_ring_funcs; - } - - if (spi->irq) { - ret = adis16201_probe_trigger(indio_dev); - if (ret) - goto error_uninitialize_ring; - } + return ret; + ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL); + if (ret) + return ret; /* Get the device into a sane initial state */ - ret = adis16201_initial_setup(indio_dev); + ret = adis_initial_startup(st); if (ret) - goto error_remove_trigger; + goto error_cleanup_buffer_trigger; ret = iio_device_register(indio_dev); if (ret < 0) - goto error_remove_trigger; + goto error_cleanup_buffer_trigger; return 0; -error_remove_trigger: - adis16201_remove_trigger(indio_dev); -error_uninitialize_ring: - iio_buffer_unregister(indio_dev); -error_unreg_ring_funcs: - adis16201_unconfigure_ring(indio_dev); -error_free_dev: - iio_free_device(indio_dev); -error_ret: +error_cleanup_buffer_trigger: + adis_cleanup_buffer_and_trigger(st, indio_dev); return ret; } static int adis16201_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct adis *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - adis16201_remove_trigger(indio_dev); - iio_buffer_unregister(indio_dev); - adis16201_unconfigure_ring(indio_dev); - iio_free_device(indio_dev); + adis_cleanup_buffer_and_trigger(st, indio_dev); return 0; } @@ -546,7 +237,7 @@ static struct spi_driver adis16201_driver = { .owner = THIS_MODULE, }, .probe = adis16201_probe, - .remove = __devexit_p(adis16201_remove), + .remove = adis16201_remove, }; module_spi_driver(adis16201_driver); diff --git a/drivers/staging/iio/accel/adis16201_ring.c b/drivers/staging/iio/accel/adis16201_ring.c deleted file mode 100644 index 26c610faee3..00000000000 --- a/drivers/staging/iio/accel/adis16201_ring.c +++ /dev/null @@ -1,139 +0,0 @@ -#include <linux/export.h> -#include <linux/interrupt.h> -#include <linux/mutex.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> - -#include "../iio.h" -#include "../ring_sw.h" -#include "../trigger_consumer.h" -#include "adis16201.h" - - -/** - * adis16201_read_ring_data() read data registers which will be placed into ring - * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @rx: somewhere to pass back the value read - **/ -static int adis16201_read_ring_data(struct iio_dev *indio_dev, u8 *rx) -{ - struct spi_message msg; - struct adis16201_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[ADIS16201_OUTPUTS + 1]; - int ret; - int i; - - mutex_lock(&st->buf_lock); - - spi_message_init(&msg); - - memset(xfers, 0, sizeof(xfers)); - for (i = 0; i <= ADIS16201_OUTPUTS; i++) { - xfers[i].bits_per_word = 8; - xfers[i].cs_change = 1; - xfers[i].len = 2; - xfers[i].delay_usecs = 20; - if (i < ADIS16201_OUTPUTS) { - xfers[i].tx_buf = st->tx + 2 * i; - st->tx[2 * i] = ADIS16201_READ_REG(ADIS16201_SUPPLY_OUT + - 2 * i); - st->tx[2 * i + 1] = 0; - } - if (i >= 1) - xfers[i].rx_buf = rx + 2 * (i - 1); - spi_message_add_tail(&xfers[i], &msg); - } - - ret = spi_sync(st->us, &msg); - if (ret) - dev_err(&st->us->dev, "problem when burst reading"); - - mutex_unlock(&st->buf_lock); - - return ret; -} - -/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device - * specific to be rolled into the core. - */ -static irqreturn_t adis16201_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct adis16201_state *st = iio_priv(indio_dev); - struct iio_buffer *ring = indio_dev->buffer; - - int i = 0; - s16 *data; - size_t datasize = ring->access->get_bytes_per_datum(ring); - - data = kmalloc(datasize, GFP_KERNEL); - if (data == NULL) { - dev_err(&st->us->dev, "memory alloc failed in ring bh"); - return -ENOMEM; - } - - if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) - && adis16201_read_ring_data(indio_dev, st->rx) >= 0) - for (; i < bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength); i++) - data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2])); - - /* Guaranteed to be aligned with 8 byte boundary */ - if (ring->scan_timestamp) - *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - - ring->access->store_to(ring, (u8 *)data, pf->timestamp); - - iio_trigger_notify_done(indio_dev->trig); - kfree(data); - - return IRQ_HANDLED; -} - -void adis16201_unconfigure_ring(struct iio_dev *indio_dev) -{ - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->buffer); -} - -static const struct iio_buffer_setup_ops adis16201_ring_setup_ops = { - .preenable = &iio_sw_buffer_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, -}; - -int adis16201_configure_ring(struct iio_dev *indio_dev) -{ - int ret = 0; - struct iio_buffer *ring; - - ring = iio_sw_rb_allocate(indio_dev); - if (!ring) { - ret = -ENOMEM; - return ret; - } - indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ - ring->scan_timestamp = true; - ring->access = &ring_sw_access_funcs; - indio_dev->setup_ops = &adis16201_ring_setup_ops; - - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, - &adis16201_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "adis16201_consumer%d", - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_iio_sw_rb_free; - } - - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; -error_iio_sw_rb_free: - iio_sw_rb_free(indio_dev->buffer); - return ret; -} diff --git a/drivers/staging/iio/accel/adis16201_trigger.c b/drivers/staging/iio/accel/adis16201_trigger.c deleted file mode 100644 index bce505e716d..00000000000 --- a/drivers/staging/iio/accel/adis16201_trigger.c +++ /dev/null @@ -1,71 +0,0 @@ -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/export.h> - -#include "../iio.h" -#include "../trigger.h" -#include "adis16201.h" - -/** - * adis16201_data_rdy_trigger_set_state() set datardy interrupt state - **/ -static int adis16201_data_rdy_trigger_set_state(struct iio_trigger *trig, - bool state) -{ - struct iio_dev *indio_dev = trig->private_data; - - dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); - return adis16201_set_irq(indio_dev, state); -} - -static const struct iio_trigger_ops adis16201_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &adis16201_data_rdy_trigger_set_state, -}; - -int adis16201_probe_trigger(struct iio_dev *indio_dev) -{ - int ret; - struct adis16201_state *st = iio_priv(indio_dev); - - st->trig = iio_allocate_trigger("adis16201-dev%d", indio_dev->id); - if (st->trig == NULL) { - ret = -ENOMEM; - goto error_ret; - } - ret = request_irq(st->us->irq, - &iio_trigger_generic_data_rdy_poll, - IRQF_TRIGGER_RISING, - "adis16201", - st->trig); - if (ret) - goto error_free_trig; - st->trig->dev.parent = &st->us->dev; - st->trig->ops = &adis16201_trigger_ops; - st->trig->private_data = indio_dev; - ret = iio_trigger_register(st->trig); - - /* select default trigger */ - indio_dev->trig = st->trig; - if (ret) - goto error_free_irq; - - return 0; - -error_free_irq: - free_irq(st->us->irq, st->trig); -error_free_trig: - iio_free_trigger(st->trig); -error_ret: - return ret; -} - -void adis16201_remove_trigger(struct iio_dev *indio_dev) -{ - struct adis16201_state *state = iio_priv(indio_dev); - - iio_trigger_unregister(state->trig); - free_irq(state->us->irq, state->trig); - iio_free_trigger(state->trig); -} diff --git a/drivers/staging/iio/accel/adis16203.h b/drivers/staging/iio/accel/adis16203.h index 3f96ad3bbd6..acc688d7ea9 100644 --- a/drivers/staging/iio/accel/adis16203.h +++ b/drivers/staging/iio/accel/adis16203.h @@ -3,9 +3,6 @@ #define ADIS16203_STARTUP_DELAY 220 /* ms */ -#define ADIS16203_READ_REG(a) a -#define ADIS16203_WRITE_REG(a) ((a) | 0x80) - #define ADIS16203_FLASH_CNT 0x00 /* Flash memory write count */ #define ADIS16203_SUPPLY_OUT 0x02 /* Output, power supply */ #define ADIS16203_AUX_ADC 0x08 /* Output, auxiliary ADC input */ @@ -27,8 +24,6 @@ #define ADIS16203_DIAG_STAT 0x3C /* Diagnostics, system status register */ #define ADIS16203_GLOB_CMD 0x3E /* Operation, system command register */ -#define ADIS16203_OUTPUTS 5 - /* MSC_CTRL */ #define ADIS16203_MSC_CTRL_PWRUP_SELF_TEST (1 << 10) /* Self-test at power-on: 1 = disabled, 0 = enabled */ #define ADIS16203_MSC_CTRL_REVERSE_ROT_EN (1 << 9) /* Reverses rotation of both inclination outputs */ @@ -40,86 +35,25 @@ /* DIAG_STAT */ #define ADIS16203_DIAG_STAT_ALARM2 (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ #define ADIS16203_DIAG_STAT_ALARM1 (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ -#define ADIS16203_DIAG_STAT_SELFTEST_FAIL (1<<5) /* Self-test diagnostic error flag */ -#define ADIS16203_DIAG_STAT_SPI_FAIL (1<<3) /* SPI communications failure */ -#define ADIS16203_DIAG_STAT_FLASH_UPT (1<<2) /* Flash update failure */ -#define ADIS16203_DIAG_STAT_POWER_HIGH (1<<1) /* Power supply above 3.625 V */ -#define ADIS16203_DIAG_STAT_POWER_LOW (1<<0) /* Power supply below 3.15 V */ +#define ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT 5 /* Self-test diagnostic error flag */ +#define ADIS16203_DIAG_STAT_SPI_FAIL_BIT 3 /* SPI communications failure */ +#define ADIS16203_DIAG_STAT_FLASH_UPT_BIT 2 /* Flash update failure */ +#define ADIS16203_DIAG_STAT_POWER_HIGH_BIT 1 /* Power supply above 3.625 V */ +#define ADIS16203_DIAG_STAT_POWER_LOW_BIT 0 /* Power supply below 3.15 V */ /* GLOB_CMD */ #define ADIS16203_GLOB_CMD_SW_RESET (1<<7) #define ADIS16203_GLOB_CMD_CLEAR_STAT (1<<4) #define ADIS16203_GLOB_CMD_FACTORY_CAL (1<<1) -#define ADIS16203_MAX_TX 12 -#define ADIS16203_MAX_RX 10 - #define ADIS16203_ERROR_ACTIVE (1<<14) -/** - * struct adis16203_state - device instance specific data - * @us: actual spi_device - * @trig: data ready trigger registered with iio - * @tx: transmit buffer - * @rx: receive buffer - * @buf_lock: mutex to protect tx and rx - **/ -struct adis16203_state { - struct spi_device *us; - struct iio_trigger *trig; - struct mutex buf_lock; - u8 tx[ADIS16203_MAX_TX] ____cacheline_aligned; - u8 rx[ADIS16203_MAX_RX]; -}; - -int adis16203_set_irq(struct iio_dev *indio_dev, bool enable); - enum adis16203_scan { + ADIS16203_SCAN_INCLI_X, + ADIS16203_SCAN_INCLI_Y, ADIS16203_SCAN_SUPPLY, ADIS16203_SCAN_AUX_ADC, ADIS16203_SCAN_TEMP, - ADIS16203_SCAN_INCLI_X, - ADIS16203_SCAN_INCLI_Y, }; -#ifdef CONFIG_IIO_BUFFER -void adis16203_remove_trigger(struct iio_dev *indio_dev); -int adis16203_probe_trigger(struct iio_dev *indio_dev); - -ssize_t adis16203_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf); - -int adis16203_configure_ring(struct iio_dev *indio_dev); -void adis16203_unconfigure_ring(struct iio_dev *indio_dev); - -#else /* CONFIG_IIO_BUFFER */ - -static inline void adis16203_remove_trigger(struct iio_dev *indio_dev) -{ -} - -static inline int adis16203_probe_trigger(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline ssize_t -adis16203_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return 0; -} - -static int adis16203_configure_ring(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline void adis16203_unconfigure_ring(struct iio_dev *indio_dev) -{ -} - -#endif /* CONFIG_IIO_BUFFER */ #endif /* SPI_ADIS16203_H_ */ diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c index 1a5140f9e3f..409a28ed904 100644 --- a/drivers/staging/iio/accel/adis16203_core.c +++ b/drivers/staging/iio/accel/adis16203_core.c @@ -1,7 +1,7 @@ /* * ADIS16203 Programmable Digital Vibration Sensor driver * - * Copyright 2010 Analog Devices Inc. + * Copyright 2030 Analog Devices Inc. * * Licensed under the GPL-2 or later. */ @@ -15,273 +15,17 @@ #include <linux/sysfs.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> +#include <linux/iio/imu/adis.h> #include "adis16203.h" #define DRIVER_NAME "adis16203" -/** - * adis16203_spi_write_reg_8() - write single byte to a register - * @indio_dev: iio device associated with child of actual device - * @reg_address: the address of the register to be written - * @val: the value to write - **/ -static int adis16203_spi_write_reg_8(struct iio_dev *indio_dev, - u8 reg_address, - u8 val) -{ - int ret; - struct adis16203_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16203_WRITE_REG(reg_address); - st->tx[1] = val; - - ret = spi_write(st->us, st->tx, 2); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/** - * adis16203_spi_write_reg_16() - write 2 bytes to a pair of registers - * @indio_dev: iio device associated with child of actual device - * @reg_address: the address of the lower of the two registers. Second register - * is assumed to have address one greater. - * @val: value to be written - **/ -static int adis16203_spi_write_reg_16(struct iio_dev *indio_dev, - u8 lower_reg_address, - u16 value) -{ - int ret; - struct spi_message msg; - struct adis16203_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - }, { - .tx_buf = st->tx + 2, - .bits_per_word = 8, - .len = 2, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16203_WRITE_REG(lower_reg_address); - st->tx[1] = value & 0xFF; - st->tx[2] = ADIS16203_WRITE_REG(lower_reg_address + 1); - st->tx[3] = (value >> 8) & 0xFF; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/** - * adis16203_spi_read_reg_16() - read 2 bytes from a 16-bit register - * @indio_dev: iio device associated with child of actual device - * @reg_address: the address of the lower of the two registers. Second register - * is assumed to have address one greater. - * @val: somewhere to pass back the value read - **/ -static int adis16203_spi_read_reg_16(struct iio_dev *indio_dev, - u8 lower_reg_address, - u16 *val) -{ - struct spi_message msg; - struct adis16203_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 20, - }, { - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 2, - .delay_usecs = 20, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16203_READ_REG(lower_reg_address); - st->tx[1] = 0; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - if (ret) { - dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", - lower_reg_address); - goto error_ret; - } - *val = (st->rx[0] << 8) | st->rx[1]; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -static int adis16203_check_status(struct iio_dev *indio_dev) -{ - u16 status; - int ret; - - ret = adis16203_spi_read_reg_16(indio_dev, - ADIS16203_DIAG_STAT, - &status); - if (ret < 0) { - dev_err(&indio_dev->dev, "Reading status failed\n"); - goto error_ret; - } - ret = status & 0x1F; - - if (status & ADIS16203_DIAG_STAT_SELFTEST_FAIL) - dev_err(&indio_dev->dev, "Self test failure\n"); - if (status & ADIS16203_DIAG_STAT_SPI_FAIL) - dev_err(&indio_dev->dev, "SPI failure\n"); - if (status & ADIS16203_DIAG_STAT_FLASH_UPT) - dev_err(&indio_dev->dev, "Flash update failed\n"); - if (status & ADIS16203_DIAG_STAT_POWER_HIGH) - dev_err(&indio_dev->dev, "Power supply above 3.625V\n"); - if (status & ADIS16203_DIAG_STAT_POWER_LOW) - dev_err(&indio_dev->dev, "Power supply below 3.15V\n"); - -error_ret: - return ret; -} - -static int adis16203_reset(struct iio_dev *indio_dev) -{ - int ret; - ret = adis16203_spi_write_reg_8(indio_dev, - ADIS16203_GLOB_CMD, - ADIS16203_GLOB_CMD_SW_RESET); - if (ret) - dev_err(&indio_dev->dev, "problem resetting device"); - - return ret; -} - -static ssize_t adis16203_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - if (len < 1) - return -EINVAL; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return adis16203_reset(indio_dev); - } - return -EINVAL; -} - -int adis16203_set_irq(struct iio_dev *indio_dev, bool enable) -{ - int ret = 0; - u16 msc; - - ret = adis16203_spi_read_reg_16(indio_dev, ADIS16203_MSC_CTRL, &msc); - if (ret) - goto error_ret; - - msc |= ADIS16203_MSC_CTRL_ACTIVE_HIGH; - msc &= ~ADIS16203_MSC_CTRL_DATA_RDY_DIO1; - if (enable) - msc |= ADIS16203_MSC_CTRL_DATA_RDY_EN; - else - msc &= ~ADIS16203_MSC_CTRL_DATA_RDY_EN; - - ret = adis16203_spi_write_reg_16(indio_dev, ADIS16203_MSC_CTRL, msc); - -error_ret: - return ret; -} - -static int adis16203_self_test(struct iio_dev *indio_dev) -{ - int ret; - ret = adis16203_spi_write_reg_16(indio_dev, - ADIS16203_MSC_CTRL, - ADIS16203_MSC_CTRL_SELF_TEST_EN); - if (ret) { - dev_err(&indio_dev->dev, "problem starting self test"); - goto err_ret; - } - - adis16203_check_status(indio_dev); - -err_ret: - return ret; -} - -static int adis16203_initial_setup(struct iio_dev *indio_dev) -{ - int ret; - - /* Disable IRQ */ - ret = adis16203_set_irq(indio_dev, false); - if (ret) { - dev_err(&indio_dev->dev, "disable irq failed"); - goto err_ret; - } - - /* Do self test */ - ret = adis16203_self_test(indio_dev); - if (ret) { - dev_err(&indio_dev->dev, "self test failure"); - goto err_ret; - } - - /* Read status register to check the result */ - ret = adis16203_check_status(indio_dev); - if (ret) { - adis16203_reset(indio_dev); - dev_err(&indio_dev->dev, "device not playing ball -> reset"); - msleep(ADIS16203_STARTUP_DELAY); - ret = adis16203_check_status(indio_dev); - if (ret) { - dev_err(&indio_dev->dev, "giving up"); - goto err_ret; - } - } - -err_ret: - return ret; -} - -enum adis16203_chan { - in_supply, - in_aux, - incli_x, - incli_y, - temp, -}; - -static u8 adis16203_addresses[5][2] = { - [in_supply] = { ADIS16203_SUPPLY_OUT }, - [in_aux] = { ADIS16203_AUX_ADC }, - [incli_x] = { ADIS16203_XINCL_OUT, ADIS16203_INCL_NULL}, - [incli_y] = { ADIS16203_YINCL_OUT }, - [temp] = { ADIS16203_TEMP_OUT } +static const u8 adis16203_addresses[] = { + [ADIS16203_SCAN_INCLI_X] = ADIS16203_INCL_NULL, }; static int adis16203_write_raw(struct iio_dev *indio_dev, @@ -290,9 +34,10 @@ static int adis16203_write_raw(struct iio_dev *indio_dev, int val2, long mask) { + struct adis *st = iio_priv(indio_dev); /* currently only one writable parameter which keeps this simple */ - u8 addr = adis16203_addresses[chan->address][1]; - return adis16203_spi_write_reg_16(indio_dev, addr, val & 0x3FFF); + u8 addr = adis16203_addresses[chan->scan_index]; + return adis_write_reg_16(st, addr, val & 0x3FFF); } static int adis16203_read_raw(struct iio_dev *indio_dev, @@ -300,63 +45,45 @@ static int adis16203_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { + struct adis *st = iio_priv(indio_dev); int ret; int bits; u8 addr; s16 val16; switch (mask) { - case 0: - mutex_lock(&indio_dev->mlock); - addr = adis16203_addresses[chan->address][0]; - ret = adis16203_spi_read_reg_16(indio_dev, addr, &val16); - if (ret) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - - if (val16 & ADIS16203_ERROR_ACTIVE) { - ret = adis16203_check_status(indio_dev); - if (ret) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - } - val16 = val16 & ((1 << chan->scan_type.realbits) - 1); - if (chan->scan_type.sign == 's') - val16 = (s16)(val16 << - (16 - chan->scan_type.realbits)) >> - (16 - chan->scan_type.realbits); - *val = val16; - mutex_unlock(&indio_dev->mlock); - return IIO_VAL_INT; + case IIO_CHAN_INFO_RAW: + return adis_single_conversion(indio_dev, chan, + ADIS16203_ERROR_ACTIVE, val); case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: - *val = 0; - if (chan->channel == 0) - *val2 = 1220; - else - *val2 = 610; + if (chan->channel == 0) { + *val = 1; + *val2 = 220000; /* 1.22 mV */ + } else { + *val = 0; + *val2 = 610000; /* 0.61 mV */ + } return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 0; - *val2 = -470000; + *val = -470; /* -0.47 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_INCLI: *val = 0; - *val2 = 25000; + *val2 = 25000; /* 0.025 degree */ return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } case IIO_CHAN_INFO_OFFSET: - *val = 25; + *val = 25000 / -470 - 1278; /* 25 C = 1278 */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: bits = 14; mutex_lock(&indio_dev->mlock); - addr = adis16203_addresses[chan->address][1]; - ret = adis16203_spi_read_reg_16(indio_dev, addr, &val16); + addr = adis16203_addresses[chan->scan_index]; + ret = adis_read_reg_16(st, addr, &val16); if (ret) { mutex_unlock(&indio_dev->mlock); return ret; @@ -371,68 +98,62 @@ static int adis16203_read_raw(struct iio_dev *indio_dev, } } -static struct iio_chan_spec adis16203_channels[] = { - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - in_supply, ADIS16203_SCAN_SUPPLY, - IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - in_aux, ADIS16203_SCAN_AUX_ADC, - IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X, - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, - incli_x, ADIS16203_SCAN_INCLI_X, - IIO_ST('s', 14, 16, 0), 0), +static const struct iio_chan_spec adis16203_channels[] = { + ADIS_SUPPLY_CHAN(ADIS16203_SUPPLY_OUT, ADIS16203_SCAN_SUPPLY, 12), + ADIS_AUX_ADC_CHAN(ADIS16203_AUX_ADC, ADIS16203_SCAN_AUX_ADC, 12), + ADIS_INCLI_CHAN(X, ADIS16203_XINCL_OUT, ADIS16203_SCAN_INCLI_X, + BIT(IIO_CHAN_INFO_CALIBBIAS), 14), /* Fixme: Not what it appears to be - see data sheet */ - IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - incli_y, ADIS16203_SCAN_INCLI_Y, - IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT | - IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, - temp, ADIS16203_SCAN_TEMP, - IIO_ST('u', 12, 16, 0), 0), + ADIS_INCLI_CHAN(Y, ADIS16203_YINCL_OUT, ADIS16203_SCAN_INCLI_Y, 0, 14), + ADIS_TEMP_CHAN(ADIS16203_TEMP_OUT, ADIS16203_SCAN_TEMP, 12), IIO_CHAN_SOFT_TIMESTAMP(5), }; -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16203_write_reset, 0); - -static struct attribute *adis16203_attributes[] = { - &iio_dev_attr_reset.dev_attr.attr, - NULL -}; - -static const struct attribute_group adis16203_attribute_group = { - .attrs = adis16203_attributes, -}; - static const struct iio_info adis16203_info = { - .attrs = &adis16203_attribute_group, .read_raw = &adis16203_read_raw, .write_raw = &adis16203_write_raw, + .update_scan_mode = adis_update_scan_mode, .driver_module = THIS_MODULE, }; -static int __devinit adis16203_probe(struct spi_device *spi) +static const char * const adis16203_status_error_msgs[] = { + [ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT] = "Self test failure", + [ADIS16203_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure", + [ADIS16203_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed", + [ADIS16203_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V", + [ADIS16203_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V", +}; + +static const struct adis_data adis16203_data = { + .read_delay = 20, + .msc_ctrl_reg = ADIS16203_MSC_CTRL, + .glob_cmd_reg = ADIS16203_GLOB_CMD, + .diag_stat_reg = ADIS16203_DIAG_STAT, + + .self_test_mask = ADIS16203_MSC_CTRL_SELF_TEST_EN, + .startup_delay = ADIS16203_STARTUP_DELAY, + + .status_error_msgs = adis16203_status_error_msgs, + .status_error_mask = BIT(ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT) | + BIT(ADIS16203_DIAG_STAT_SPI_FAIL_BIT) | + BIT(ADIS16203_DIAG_STAT_FLASH_UPT_BIT) | + BIT(ADIS16203_DIAG_STAT_POWER_HIGH_BIT) | + BIT(ADIS16203_DIAG_STAT_POWER_LOW_BIT), +}; + +static int adis16203_probe(struct spi_device *spi) { int ret; struct iio_dev *indio_dev; - struct adis16203_state *st; + struct adis *st; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; st = iio_priv(indio_dev); /* this is only used for removal purposes */ spi_set_drvdata(spi, indio_dev); - st->us = spi; - mutex_init(&st->buf_lock); indio_dev->name = spi->dev.driver->name; indio_dev->dev.parent = &spi->dev; @@ -441,56 +162,37 @@ static int __devinit adis16203_probe(struct spi_device *spi) indio_dev->info = &adis16203_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = adis16203_configure_ring(indio_dev); + ret = adis_init(st, indio_dev, spi, &adis16203_data); if (ret) - goto error_free_dev; - - ret = iio_buffer_register(indio_dev, - adis16203_channels, - ARRAY_SIZE(adis16203_channels)); - if (ret) { - printk(KERN_ERR "failed to initialize the ring\n"); - goto error_unreg_ring_funcs; - } + return ret; - if (spi->irq) { - ret = adis16203_probe_trigger(indio_dev); - if (ret) - goto error_uninitialize_ring; - } + ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL); + if (ret) + return ret; /* Get the device into a sane initial state */ - ret = adis16203_initial_setup(indio_dev); + ret = adis_initial_startup(st); if (ret) - goto error_remove_trigger; + goto error_cleanup_buffer_trigger; ret = iio_device_register(indio_dev); if (ret) - goto error_remove_trigger; + goto error_cleanup_buffer_trigger; return 0; -error_remove_trigger: - adis16203_remove_trigger(indio_dev); -error_uninitialize_ring: - iio_buffer_unregister(indio_dev); -error_unreg_ring_funcs: - adis16203_unconfigure_ring(indio_dev); -error_free_dev: - iio_free_device(indio_dev); -error_ret: +error_cleanup_buffer_trigger: + adis_cleanup_buffer_and_trigger(st, indio_dev); return ret; } static int adis16203_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct adis *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - adis16203_remove_trigger(indio_dev); - iio_buffer_unregister(indio_dev); - adis16203_unconfigure_ring(indio_dev); - iio_free_device(indio_dev); + adis_cleanup_buffer_and_trigger(st, indio_dev); return 0; } @@ -501,7 +203,7 @@ static struct spi_driver adis16203_driver = { .owner = THIS_MODULE, }, .probe = adis16203_probe, - .remove = __devexit_p(adis16203_remove), + .remove = adis16203_remove, }; module_spi_driver(adis16203_driver); diff --git a/drivers/staging/iio/accel/adis16203_ring.c b/drivers/staging/iio/accel/adis16203_ring.c deleted file mode 100644 index 064640d15e4..00000000000 --- a/drivers/staging/iio/accel/adis16203_ring.c +++ /dev/null @@ -1,142 +0,0 @@ -#include <linux/export.h> -#include <linux/interrupt.h> -#include <linux/mutex.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> - -#include "../iio.h" -#include "../ring_sw.h" -#include "../trigger_consumer.h" -#include "adis16203.h" - -/** - * adis16203_read_ring_data() read data registers which will be placed into ring - * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @rx: somewhere to pass back the value read - **/ -static int adis16203_read_ring_data(struct device *dev, u8 *rx) -{ - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16203_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[ADIS16203_OUTPUTS + 1]; - int ret; - int i; - - mutex_lock(&st->buf_lock); - - spi_message_init(&msg); - - memset(xfers, 0, sizeof(xfers)); - for (i = 0; i <= ADIS16203_OUTPUTS; i++) { - xfers[i].bits_per_word = 8; - xfers[i].cs_change = 1; - xfers[i].len = 2; - xfers[i].delay_usecs = 20; - xfers[i].tx_buf = st->tx + 2 * i; - if (i < 1) /* SUPPLY_OUT: 0x02, AUX_ADC: 0x08 */ - st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i); - else - st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i + 6); - st->tx[2 * i + 1] = 0; - if (i >= 1) - xfers[i].rx_buf = rx + 2 * (i - 1); - spi_message_add_tail(&xfers[i], &msg); - } - - ret = spi_sync(st->us, &msg); - if (ret) - dev_err(&st->us->dev, "problem when burst reading"); - - mutex_unlock(&st->buf_lock); - - return ret; -} - -/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device - * specific to be rolled into the core. - */ -static irqreturn_t adis16203_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct adis16203_state *st = iio_priv(indio_dev); - struct iio_buffer *ring = indio_dev->buffer; - - int i = 0; - s16 *data; - size_t datasize = ring->access->get_bytes_per_datum(ring); - - data = kmalloc(datasize, GFP_KERNEL); - if (data == NULL) { - dev_err(&st->us->dev, "memory alloc failed in ring bh"); - return -ENOMEM; - } - - if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) && - adis16203_read_ring_data(&indio_dev->dev, st->rx) >= 0) - for (; i < bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength); i++) - data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2])); - - /* Guaranteed to be aligned with 8 byte boundary */ - if (ring->scan_timestamp) - *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - - ring->access->store_to(ring, - (u8 *)data, - pf->timestamp); - - iio_trigger_notify_done(indio_dev->trig); - kfree(data); - - return IRQ_HANDLED; -} - -void adis16203_unconfigure_ring(struct iio_dev *indio_dev) -{ - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->buffer); -} - -static const struct iio_buffer_setup_ops adis16203_ring_setup_ops = { - .preenable = &iio_sw_buffer_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, -}; - -int adis16203_configure_ring(struct iio_dev *indio_dev) -{ - int ret = 0; - struct iio_buffer *ring; - - ring = iio_sw_rb_allocate(indio_dev); - if (!ring) { - ret = -ENOMEM; - return ret; - } - indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ - ring->scan_timestamp = true; - ring->access = &ring_sw_access_funcs; - indio_dev->setup_ops = &adis16203_ring_setup_ops; - - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, - &adis16203_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "adis16203_consumer%d", - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_iio_sw_rb_free; - } - - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_iio_sw_rb_free: - iio_sw_rb_free(indio_dev->buffer); - return ret; -} diff --git a/drivers/staging/iio/accel/adis16203_trigger.c b/drivers/staging/iio/accel/adis16203_trigger.c deleted file mode 100644 index 24bcb8e15c5..00000000000 --- a/drivers/staging/iio/accel/adis16203_trigger.c +++ /dev/null @@ -1,73 +0,0 @@ -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/export.h> - -#include "../iio.h" -#include "../trigger.h" -#include "adis16203.h" - -/** - * adis16203_data_rdy_trigger_set_state() set datardy interrupt state - **/ -static int adis16203_data_rdy_trigger_set_state(struct iio_trigger *trig, - bool state) -{ - struct iio_dev *indio_dev = trig->private_data; - - dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); - return adis16203_set_irq(indio_dev, state); -} - -static const struct iio_trigger_ops adis16203_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &adis16203_data_rdy_trigger_set_state, -}; - -int adis16203_probe_trigger(struct iio_dev *indio_dev) -{ - int ret; - struct adis16203_state *st = iio_priv(indio_dev); - - st->trig = iio_allocate_trigger("adis16203-dev%d", indio_dev->id); - if (st->trig == NULL) { - ret = -ENOMEM; - goto error_ret; - } - - ret = request_irq(st->us->irq, - &iio_trigger_generic_data_rdy_poll, - IRQF_TRIGGER_RISING, - "adis16203", - st->trig); - if (ret) - goto error_free_trig; - - st->trig->dev.parent = &st->us->dev; - st->trig->ops = &adis16203_trigger_ops; - st->trig->private_data = indio_dev; - ret = iio_trigger_register(st->trig); - - /* select default trigger */ - indio_dev->trig = st->trig; - if (ret) - goto error_free_irq; - - return 0; - -error_free_irq: - free_irq(st->us->irq, st->trig); -error_free_trig: - iio_free_trigger(st->trig); -error_ret: - return ret; -} - -void adis16203_remove_trigger(struct iio_dev *indio_dev) -{ - struct adis16203_state *st = iio_priv(indio_dev); - - iio_trigger_unregister(st->trig); - free_irq(st->us->irq, st->trig); - iio_free_trigger(st->trig); -} diff --git a/drivers/staging/iio/accel/adis16204.h b/drivers/staging/iio/accel/adis16204.h index 7cf4e91f83a..9ff950c1e8d 100644 --- a/drivers/staging/iio/accel/adis16204.h +++ b/drivers/staging/iio/accel/adis16204.h @@ -3,9 +3,6 @@ #define ADIS16204_STARTUP_DELAY 220 /* ms */ -#define ADIS16204_READ_REG(a) a -#define ADIS16204_WRITE_REG(a) ((a) | 0x80) - #define ADIS16204_FLASH_CNT 0x00 /* Flash memory write count */ #define ADIS16204_SUPPLY_OUT 0x02 /* Output, power supply */ #define ADIS16204_XACCL_OUT 0x04 /* Output, x-axis accelerometer */ @@ -35,8 +32,6 @@ #define ADIS16204_DIAG_STAT 0x3C /* Diagnostics, system status register */ #define ADIS16204_GLOB_CMD 0x3E /* Operation, system command register */ -#define ADIS16204_OUTPUTS 5 - /* MSC_CTRL */ #define ADIS16204_MSC_CTRL_PWRUP_SELF_TEST (1 << 10) /* Self-test at power-on: 1 = disabled, 0 = enabled */ #define ADIS16204_MSC_CTRL_SELF_TEST_EN (1 << 8) /* Self-test enable */ @@ -47,87 +42,27 @@ /* DIAG_STAT */ #define ADIS16204_DIAG_STAT_ALARM2 (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ #define ADIS16204_DIAG_STAT_ALARM1 (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ -#define ADIS16204_DIAG_STAT_SELFTEST_FAIL (1<<5) /* Self-test diagnostic error flag: 1 = error condition, +#define ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT 5 /* Self-test diagnostic error flag: 1 = error condition, 0 = normal operation */ -#define ADIS16204_DIAG_STAT_SPI_FAIL (1<<3) /* SPI communications failure */ -#define ADIS16204_DIAG_STAT_FLASH_UPT (1<<2) /* Flash update failure */ -#define ADIS16204_DIAG_STAT_POWER_HIGH (1<<1) /* Power supply above 3.625 V */ -#define ADIS16204_DIAG_STAT_POWER_LOW (1<<0) /* Power supply below 2.975 V */ +#define ADIS16204_DIAG_STAT_SPI_FAIL_BIT 3 /* SPI communications failure */ +#define ADIS16204_DIAG_STAT_FLASH_UPT_BIT 2 /* Flash update failure */ +#define ADIS16204_DIAG_STAT_POWER_HIGH_BIT 1 /* Power supply above 3.625 V */ +#define ADIS16204_DIAG_STAT_POWER_LOW_BIT 0 /* Power supply below 2.975 V */ /* GLOB_CMD */ #define ADIS16204_GLOB_CMD_SW_RESET (1<<7) #define ADIS16204_GLOB_CMD_CLEAR_STAT (1<<4) #define ADIS16204_GLOB_CMD_FACTORY_CAL (1<<1) -#define ADIS16204_MAX_TX 24 -#define ADIS16204_MAX_RX 24 - #define ADIS16204_ERROR_ACTIVE (1<<14) -/** - * struct adis16204_state - device instance specific data - * @us: actual spi_device - * @trig: data ready trigger registered with iio - * @tx: transmit buffer - * @rx: receive buffer - * @buf_lock: mutex to protect tx and rx - **/ -struct adis16204_state { - struct spi_device *us; - struct iio_trigger *trig; - struct mutex buf_lock; - u8 tx[ADIS16204_MAX_TX] ____cacheline_aligned; - u8 rx[ADIS16204_MAX_RX]; -}; - -int adis16204_set_irq(struct iio_dev *indio_dev, bool enable); - enum adis16204_scan { - ADIS16204_SCAN_SUPPLY, ADIS16204_SCAN_ACC_X, ADIS16204_SCAN_ACC_Y, + ADIS16204_SCAN_ACC_XY, + ADIS16204_SCAN_SUPPLY, ADIS16204_SCAN_AUX_ADC, ADIS16204_SCAN_TEMP, }; -#ifdef CONFIG_IIO_BUFFER -void adis16204_remove_trigger(struct iio_dev *indio_dev); -int adis16204_probe_trigger(struct iio_dev *indio_dev); - -ssize_t adis16204_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf); - -int adis16204_configure_ring(struct iio_dev *indio_dev); -void adis16204_unconfigure_ring(struct iio_dev *indio_dev); - -#else /* CONFIG_IIO_BUFFER */ - -static inline void adis16204_remove_trigger(struct iio_dev *indio_dev) -{ -} - -static inline int adis16204_probe_trigger(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline ssize_t -adis16204_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return 0; -} - -static int adis16204_configure_ring(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline void adis16204_unconfigure_ring(struct iio_dev *indio_dev) -{ -} - -#endif /* CONFIG_IIO_BUFFER */ #endif /* SPI_ADIS16204_H_ */ diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c index fa89364b841..b8ea76857cd 100644 --- a/drivers/staging/iio/accel/adis16204_core.c +++ b/drivers/staging/iio/accel/adis16204_core.c @@ -18,316 +18,19 @@ #include <linux/list.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> +#include <linux/iio/imu/adis.h> #include "adis16204.h" -#define DRIVER_NAME "adis16204" - -/** - * adis16204_spi_write_reg_8() - write single byte to a register - * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @reg_address: the address of the register to be written - * @val: the value to write - **/ -static int adis16204_spi_write_reg_8(struct iio_dev *indio_dev, - u8 reg_address, - u8 val) -{ - int ret; - struct adis16204_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16204_WRITE_REG(reg_address); - st->tx[1] = val; - - ret = spi_write(st->us, st->tx, 2); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/** - * adis16204_spi_write_reg_16() - write 2 bytes to a pair of registers - * @indio_dev: iio device associated with child of actual device - * @reg_address: the address of the lower of the two registers. Second register - * is assumed to have address one greater. - * @val: value to be written - **/ -static int adis16204_spi_write_reg_16(struct iio_dev *indio_dev, - u8 lower_reg_address, - u16 value) -{ - int ret; - struct spi_message msg; - struct adis16204_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - }, { - .tx_buf = st->tx + 2, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16204_WRITE_REG(lower_reg_address); - st->tx[1] = value & 0xFF; - st->tx[2] = ADIS16204_WRITE_REG(lower_reg_address + 1); - st->tx[3] = (value >> 8) & 0xFF; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/** - * adis16204_spi_read_reg_16() - read 2 bytes from a 16-bit register - * @indio_dev: iio device associated with child of actual device - * @reg_address: the address of the lower of the two registers. Second register - * is assumed to have address one greater. - * @val: somewhere to pass back the value read - **/ -static int adis16204_spi_read_reg_16(struct iio_dev *indio_dev, - u8 lower_reg_address, - u16 *val) -{ - struct spi_message msg; - struct adis16204_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 20, - }, { - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 2, - .delay_usecs = 20, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16204_READ_REG(lower_reg_address); - st->tx[1] = 0; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - if (ret) { - dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", - lower_reg_address); - goto error_ret; - } - *val = (st->rx[0] << 8) | st->rx[1]; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -static int adis16204_check_status(struct iio_dev *indio_dev) -{ - u16 status; - int ret; - - ret = adis16204_spi_read_reg_16(indio_dev, - ADIS16204_DIAG_STAT, &status); - if (ret < 0) { - dev_err(&indio_dev->dev, "Reading status failed\n"); - goto error_ret; - } - ret = status & 0x1F; - - if (status & ADIS16204_DIAG_STAT_SELFTEST_FAIL) - dev_err(&indio_dev->dev, "Self test failure\n"); - if (status & ADIS16204_DIAG_STAT_SPI_FAIL) - dev_err(&indio_dev->dev, "SPI failure\n"); - if (status & ADIS16204_DIAG_STAT_FLASH_UPT) - dev_err(&indio_dev->dev, "Flash update failed\n"); - if (status & ADIS16204_DIAG_STAT_POWER_HIGH) - dev_err(&indio_dev->dev, "Power supply above 3.625V\n"); - if (status & ADIS16204_DIAG_STAT_POWER_LOW) - dev_err(&indio_dev->dev, "Power supply below 2.975V\n"); - -error_ret: - return ret; -} - -static ssize_t adis16204_read_14bit_signed(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - s16 val = 0; - ssize_t ret; - - mutex_lock(&indio_dev->mlock); - - ret = adis16204_spi_read_reg_16(indio_dev, - this_attr->address, (u16 *)&val); - if (!ret) { - if (val & ADIS16204_ERROR_ACTIVE) - adis16204_check_status(indio_dev); - - val = ((s16)(val << 2) >> 2); - ret = sprintf(buf, "%d\n", val); - } - - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static int adis16204_reset(struct iio_dev *indio_dev) -{ - int ret; - ret = adis16204_spi_write_reg_8(indio_dev, - ADIS16204_GLOB_CMD, - ADIS16204_GLOB_CMD_SW_RESET); - if (ret) - dev_err(&indio_dev->dev, "problem resetting device"); - - return ret; -} - -static ssize_t adis16204_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - - if (len < 1) - return -EINVAL; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return adis16204_reset(indio_dev); - } - return -EINVAL; -} - -int adis16204_set_irq(struct iio_dev *indio_dev, bool enable) -{ - int ret = 0; - u16 msc; - - ret = adis16204_spi_read_reg_16(indio_dev, ADIS16204_MSC_CTRL, &msc); - if (ret) - goto error_ret; - - msc |= ADIS16204_MSC_CTRL_ACTIVE_HIGH; - msc &= ~ADIS16204_MSC_CTRL_DATA_RDY_DIO2; - if (enable) - msc |= ADIS16204_MSC_CTRL_DATA_RDY_EN; - else - msc &= ~ADIS16204_MSC_CTRL_DATA_RDY_EN; - - ret = adis16204_spi_write_reg_16(indio_dev, ADIS16204_MSC_CTRL, msc); - -error_ret: - return ret; -} - -static int adis16204_self_test(struct iio_dev *indio_dev) -{ - int ret; - ret = adis16204_spi_write_reg_16(indio_dev, - ADIS16204_MSC_CTRL, - ADIS16204_MSC_CTRL_SELF_TEST_EN); - if (ret) { - dev_err(&indio_dev->dev, "problem starting self test"); - goto err_ret; - } - - adis16204_check_status(indio_dev); - -err_ret: - return ret; -} - -static int adis16204_initial_setup(struct iio_dev *indio_dev) -{ - int ret; - - /* Disable IRQ */ - ret = adis16204_set_irq(indio_dev, false); - if (ret) { - dev_err(&indio_dev->dev, "disable irq failed"); - goto err_ret; - } - - /* Do self test */ - ret = adis16204_self_test(indio_dev); - if (ret) { - dev_err(&indio_dev->dev, "self test failure"); - goto err_ret; - } - - /* Read status register to check the result */ - ret = adis16204_check_status(indio_dev); - if (ret) { - adis16204_reset(indio_dev); - dev_err(&indio_dev->dev, "device not playing ball -> reset"); - msleep(ADIS16204_STARTUP_DELAY); - ret = adis16204_check_status(indio_dev); - if (ret) { - dev_err(&indio_dev->dev, "giving up"); - goto err_ret; - } - } - -err_ret: - return ret; -} - /* Unique to this driver currently */ -#define IIO_DEV_ATTR_ACCEL_XY(_show, _addr) \ - IIO_DEVICE_ATTR(in_accel_xy, S_IRUGO, _show, NULL, _addr) -#define IIO_DEV_ATTR_ACCEL_XYPEAK(_show, _addr) \ - IIO_DEVICE_ATTR(in_accel_xypeak, S_IRUGO, _show, NULL, _addr) - -static IIO_DEV_ATTR_ACCEL_XY(adis16204_read_14bit_signed, - ADIS16204_XY_RSS_OUT); -static IIO_DEV_ATTR_ACCEL_XYPEAK(adis16204_read_14bit_signed, - ADIS16204_XY_PEAK_OUT); -static IIO_CONST_ATTR(in_accel_xy_scale, "0.017125"); - -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16204_write_reset, 0); - -enum adis16204_channel { - in_supply, - in_aux, - temp, - accel_x, - accel_y, -}; -static u8 adis16204_addresses[5][3] = { - [in_supply] = { ADIS16204_SUPPLY_OUT }, - [in_aux] = { ADIS16204_AUX_ADC }, - [temp] = { ADIS16204_TEMP_OUT }, - [accel_x] = { ADIS16204_XACCL_OUT, ADIS16204_XACCL_NULL, - ADIS16204_X_PEAK_OUT }, - [accel_y] = { ADIS16204_XACCL_OUT, ADIS16204_YACCL_NULL, - ADIS16204_Y_PEAK_OUT }, +static const u8 adis16204_addresses[][2] = { + [ADIS16204_SCAN_ACC_X] = { ADIS16204_XACCL_NULL, ADIS16204_X_PEAK_OUT }, + [ADIS16204_SCAN_ACC_Y] = { ADIS16204_YACCL_NULL, ADIS16204_Y_PEAK_OUT }, + [ADIS16204_SCAN_ACC_XY] = { 0, ADIS16204_XY_PEAK_OUT }, }; static int adis16204_read_raw(struct iio_dev *indio_dev, @@ -335,6 +38,7 @@ static int adis16204_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { + struct adis *st = iio_priv(indio_dev); int ret; int bits; u8 addr; @@ -342,69 +46,56 @@ static int adis16204_read_raw(struct iio_dev *indio_dev, int addrind; switch (mask) { - case 0: - mutex_lock(&indio_dev->mlock); - addr = adis16204_addresses[chan->address][0]; - ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16); - if (ret) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - - if (val16 & ADIS16204_ERROR_ACTIVE) { - ret = adis16204_check_status(indio_dev); - if (ret) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - } - val16 = val16 & ((1 << chan->scan_type.realbits) - 1); - if (chan->scan_type.sign == 's') - val16 = (s16)(val16 << - (16 - chan->scan_type.realbits)) >> - (16 - chan->scan_type.realbits); - *val = val16; - mutex_unlock(&indio_dev->mlock); - return IIO_VAL_INT; + case IIO_CHAN_INFO_RAW: + return adis_single_conversion(indio_dev, chan, + ADIS16204_ERROR_ACTIVE, val); case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: - *val = 0; - if (chan->channel == 0) - *val2 = 1220; - else - *val2 = 610; + if (chan->channel == 0) { + *val = 1; + *val2 = 220000; /* 1.22 mV */ + } else { + *val = 0; + *val2 = 610000; /* 0.61 mV */ + } return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 0; - *val2 = -470000; + *val = -470; /* 0.47 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: *val = 0; - if (chan->channel == 'x') - *val2 = 17125; - else - *val2 = 8407; + switch (chan->channel2) { + case IIO_MOD_X: + case IIO_MOD_ROOT_SUM_SQUARED_X_Y: + *val2 = IIO_G_TO_M_S_2(17125); /* 17.125 mg */ + break; + case IIO_MOD_Y: + case IIO_MOD_Z: + *val2 = IIO_G_TO_M_S_2(8407); /* 8.407 mg */ + break; + } return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } break; case IIO_CHAN_INFO_OFFSET: - *val = 25; + *val = 25000 / -470 - 1278; /* 25 C = 1278 */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_PEAK: if (mask == IIO_CHAN_INFO_CALIBBIAS) { bits = 12; - addrind = 1; + addrind = 0; } else { /* PEAK_SEPARATE */ bits = 14; - addrind = 2; + addrind = 1; } mutex_lock(&indio_dev->mlock); - addr = adis16204_addresses[chan->address][addrind]; - ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16); + addr = adis16204_addresses[chan->scan_index][addrind]; + ret = adis_read_reg_16(st, addr, &val16); if (ret) { mutex_unlock(&indio_dev->mlock); return ret; @@ -424,6 +115,7 @@ static int adis16204_write_raw(struct iio_dev *indio_dev, int val2, long mask) { + struct adis *st = iio_priv(indio_dev); int bits; s16 val16; u8 addr; @@ -435,79 +127,72 @@ static int adis16204_write_raw(struct iio_dev *indio_dev, break; default: return -EINVAL; - }; + } val16 = val & ((1 << bits) - 1); - addr = adis16204_addresses[chan->address][1]; - return adis16204_spi_write_reg_16(indio_dev, addr, val16); + addr = adis16204_addresses[chan->scan_index][1]; + return adis_write_reg_16(st, addr, val16); } return -EINVAL; } -static struct iio_chan_spec adis16204_channels[] = { - IIO_CHAN(IIO_VOLTAGE, 0, 0, 0, "supply", 0, 0, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - in_supply, ADIS16204_SCAN_SUPPLY, - IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - in_aux, ADIS16204_SCAN_AUX_ADC, - IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT | - IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, - temp, ADIS16204_SCAN_TEMP, - IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_PEAK_SEPARATE_BIT, - accel_x, ADIS16204_SCAN_ACC_X, - IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_PEAK_SEPARATE_BIT, - accel_y, ADIS16204_SCAN_ACC_Y, - IIO_ST('s', 14, 16, 0), 0), +static const struct iio_chan_spec adis16204_channels[] = { + ADIS_SUPPLY_CHAN(ADIS16204_SUPPLY_OUT, ADIS16204_SCAN_SUPPLY, 12), + ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 12), + ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 12), + ADIS_ACCEL_CHAN(X, ADIS16204_XACCL_OUT, ADIS16204_SCAN_ACC_X, + BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 14), + ADIS_ACCEL_CHAN(Y, ADIS16204_YACCL_OUT, ADIS16204_SCAN_ACC_Y, + BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 14), + ADIS_ACCEL_CHAN(ROOT_SUM_SQUARED_X_Y, ADIS16204_XY_RSS_OUT, + ADIS16204_SCAN_ACC_XY, BIT(IIO_CHAN_INFO_PEAK), 14), IIO_CHAN_SOFT_TIMESTAMP(5), }; -static struct attribute *adis16204_attributes[] = { - &iio_dev_attr_reset.dev_attr.attr, - &iio_dev_attr_in_accel_xy.dev_attr.attr, - &iio_dev_attr_in_accel_xypeak.dev_attr.attr, - &iio_const_attr_in_accel_xy_scale.dev_attr.attr, - NULL -}; - -static const struct attribute_group adis16204_attribute_group = { - .attrs = adis16204_attributes, -}; - static const struct iio_info adis16204_info = { - .attrs = &adis16204_attribute_group, .read_raw = &adis16204_read_raw, .write_raw = &adis16204_write_raw, + .update_scan_mode = adis_update_scan_mode, .driver_module = THIS_MODULE, }; -static int __devinit adis16204_probe(struct spi_device *spi) +static const char * const adis16204_status_error_msgs[] = { + [ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT] = "Self test failure", + [ADIS16204_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure", + [ADIS16204_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed", + [ADIS16204_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V", + [ADIS16204_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.975V", +}; + +static const struct adis_data adis16204_data = { + .read_delay = 20, + .msc_ctrl_reg = ADIS16204_MSC_CTRL, + .glob_cmd_reg = ADIS16204_GLOB_CMD, + .diag_stat_reg = ADIS16204_DIAG_STAT, + + .self_test_mask = ADIS16204_MSC_CTRL_SELF_TEST_EN, + .startup_delay = ADIS16204_STARTUP_DELAY, + + .status_error_msgs = adis16204_status_error_msgs, + .status_error_mask = BIT(ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT) | + BIT(ADIS16204_DIAG_STAT_SPI_FAIL_BIT) | + BIT(ADIS16204_DIAG_STAT_FLASH_UPT_BIT) | + BIT(ADIS16204_DIAG_STAT_POWER_HIGH_BIT) | + BIT(ADIS16204_DIAG_STAT_POWER_LOW_BIT), +}; + +static int adis16204_probe(struct spi_device *spi) { int ret; - struct adis16204_state *st; + struct adis *st; struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; st = iio_priv(indio_dev); /* this is only used for removal purposes */ spi_set_drvdata(spi, indio_dev); - st->us = spi; - mutex_init(&st->buf_lock); indio_dev->name = spi->dev.driver->name; indio_dev->dev.parent = &spi->dev; @@ -516,55 +201,36 @@ static int __devinit adis16204_probe(struct spi_device *spi) indio_dev->num_channels = ARRAY_SIZE(adis16204_channels); indio_dev->modes = INDIO_DIRECT_MODE; - ret = adis16204_configure_ring(indio_dev); + ret = adis_init(st, indio_dev, spi, &adis16204_data); if (ret) - goto error_free_dev; + return ret; - ret = iio_buffer_register(indio_dev, - adis16204_channels, - ARRAY_SIZE(adis16204_channels)); - if (ret) { - printk(KERN_ERR "failed to initialize the ring\n"); - goto error_unreg_ring_funcs; - } - - if (spi->irq) { - ret = adis16204_probe_trigger(indio_dev); - if (ret) - goto error_uninitialize_ring; - } + ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL); + if (ret) + return ret; /* Get the device into a sane initial state */ - ret = adis16204_initial_setup(indio_dev); + ret = adis_initial_startup(st); if (ret) - goto error_remove_trigger; + goto error_cleanup_buffer_trigger; ret = iio_device_register(indio_dev); if (ret) - goto error_remove_trigger; + goto error_cleanup_buffer_trigger; return 0; -error_remove_trigger: - adis16204_remove_trigger(indio_dev); -error_uninitialize_ring: - iio_buffer_unregister(indio_dev); -error_unreg_ring_funcs: - adis16204_unconfigure_ring(indio_dev); -error_free_dev: - iio_free_device(indio_dev); -error_ret: +error_cleanup_buffer_trigger: + adis_cleanup_buffer_and_trigger(st, indio_dev); return ret; } static int adis16204_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct adis *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - adis16204_remove_trigger(indio_dev); - iio_buffer_unregister(indio_dev); - adis16204_unconfigure_ring(indio_dev); - iio_free_device(indio_dev); + adis_cleanup_buffer_and_trigger(st, indio_dev); return 0; } @@ -575,7 +241,7 @@ static struct spi_driver adis16204_driver = { .owner = THIS_MODULE, }, .probe = adis16204_probe, - .remove = __devexit_p(adis16204_remove), + .remove = adis16204_remove, }; module_spi_driver(adis16204_driver); diff --git a/drivers/staging/iio/accel/adis16204_ring.c b/drivers/staging/iio/accel/adis16204_ring.c deleted file mode 100644 index 4081179dfa5..00000000000 --- a/drivers/staging/iio/accel/adis16204_ring.c +++ /dev/null @@ -1,138 +0,0 @@ -#include <linux/export.h> -#include <linux/interrupt.h> -#include <linux/mutex.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> - -#include "../iio.h" -#include "../ring_sw.h" -#include "../trigger_consumer.h" -#include "adis16204.h" - -/** - * adis16204_read_ring_data() read data registers which will be placed into ring - * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @rx: somewhere to pass back the value read - **/ -static int adis16204_read_ring_data(struct device *dev, u8 *rx) -{ - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16204_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[ADIS16204_OUTPUTS + 1]; - int ret; - int i; - - mutex_lock(&st->buf_lock); - - spi_message_init(&msg); - - memset(xfers, 0, sizeof(xfers)); - for (i = 0; i <= ADIS16204_OUTPUTS; i++) { - xfers[i].bits_per_word = 8; - xfers[i].cs_change = 1; - xfers[i].len = 2; - xfers[i].delay_usecs = 20; - xfers[i].tx_buf = st->tx + 2 * i; - st->tx[2 * i] - = ADIS16204_READ_REG(ADIS16204_SUPPLY_OUT + 2 * i); - st->tx[2 * i + 1] = 0; - if (i >= 1) - xfers[i].rx_buf = rx + 2 * (i - 1); - spi_message_add_tail(&xfers[i], &msg); - } - - ret = spi_sync(st->us, &msg); - if (ret) - dev_err(&st->us->dev, "problem when burst reading"); - - mutex_unlock(&st->buf_lock); - - return ret; -} - -/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device - * specific to be rolled into the core. - */ -static irqreturn_t adis16204_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct adis16204_state *st = iio_priv(indio_dev); - struct iio_buffer *ring = indio_dev->buffer; - int i = 0; - s16 *data; - size_t datasize = ring->access->get_bytes_per_datum(ring); - - data = kmalloc(datasize, GFP_KERNEL); - if (data == NULL) { - dev_err(&st->us->dev, "memory alloc failed in ring bh"); - return -ENOMEM; - } - - if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) && - adis16204_read_ring_data(&indio_dev->dev, st->rx) >= 0) - for (; i < bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength); i++) - data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2])); - - /* Guaranteed to be aligned with 8 byte boundary */ - if (ring->scan_timestamp) - *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - - ring->access->store_to(ring, (u8 *)data, pf->timestamp); - - iio_trigger_notify_done(indio_dev->trig); - kfree(data); - - return IRQ_HANDLED; -} - -void adis16204_unconfigure_ring(struct iio_dev *indio_dev) -{ - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->buffer); -} - -static const struct iio_buffer_setup_ops adis16204_ring_setup_ops = { - .preenable = &iio_sw_buffer_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, -}; - -int adis16204_configure_ring(struct iio_dev *indio_dev) -{ - int ret = 0; - struct iio_buffer *ring; - - ring = iio_sw_rb_allocate(indio_dev); - if (!ring) { - ret = -ENOMEM; - return ret; - } - indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ - ring->access = &ring_sw_access_funcs; - ring->scan_timestamp = true; - indio_dev->setup_ops = &adis16204_ring_setup_ops; - - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, - &adis16204_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "%s_consumer%d", - indio_dev->name, - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_iio_sw_rb_free; - } - - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_iio_sw_rb_free: - iio_sw_rb_free(indio_dev->buffer); - return ret; -} diff --git a/drivers/staging/iio/accel/adis16204_trigger.c b/drivers/staging/iio/accel/adis16204_trigger.c deleted file mode 100644 index 6e542af02c0..00000000000 --- a/drivers/staging/iio/accel/adis16204_trigger.c +++ /dev/null @@ -1,73 +0,0 @@ -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/export.h> - -#include "../iio.h" -#include "../trigger.h" -#include "adis16204.h" - -/** - * adis16204_data_rdy_trigger_set_state() set datardy interrupt state - **/ -static int adis16204_data_rdy_trigger_set_state(struct iio_trigger *trig, - bool state) -{ - struct iio_dev *indio_dev = trig->private_data; - - dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); - return adis16204_set_irq(indio_dev, state); -} - -static const struct iio_trigger_ops adis16204_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &adis16204_data_rdy_trigger_set_state, -}; - -int adis16204_probe_trigger(struct iio_dev *indio_dev) -{ - int ret; - struct adis16204_state *st = iio_priv(indio_dev); - - st->trig = iio_allocate_trigger("adis16204-dev%d", indio_dev->id); - if (st->trig == NULL) { - ret = -ENOMEM; - goto error_ret; - } - - ret = request_irq(st->us->irq, - &iio_trigger_generic_data_rdy_poll, - IRQF_TRIGGER_RISING, - "adis16204", - st->trig); - if (ret) - goto error_free_trig; - - st->trig->dev.parent = &st->us->dev; - st->trig->ops = &adis16204_trigger_ops; - st->trig->private_data = indio_dev; - ret = iio_trigger_register(st->trig); - - /* select default trigger */ - indio_dev->trig = st->trig; - if (ret) - goto error_free_irq; - - return 0; - -error_free_irq: - free_irq(st->us->irq, st->trig); -error_free_trig: - iio_free_trigger(st->trig); -error_ret: - return ret; -} - -void adis16204_remove_trigger(struct iio_dev *indio_dev) -{ - struct adis16204_state *state = iio_priv(indio_dev); - - iio_trigger_unregister(state->trig); - free_irq(state->us->irq, state->trig); - iio_free_trigger(state->trig); -} diff --git a/drivers/staging/iio/accel/adis16209.h b/drivers/staging/iio/accel/adis16209.h index 3c88b86e7b8..ad3945a0629 100644 --- a/drivers/staging/iio/accel/adis16209.h +++ b/drivers/staging/iio/accel/adis16209.h @@ -3,9 +3,6 @@ #define ADIS16209_STARTUP_DELAY 220 /* ms */ -#define ADIS16209_READ_REG(a) a -#define ADIS16209_WRITE_REG(a) ((a) | 0x80) - /* Flash memory write count */ #define ADIS16209_FLASH_CNT 0x00 /* Output, power supply */ @@ -61,8 +58,6 @@ /* Operation, system command register */ #define ADIS16209_GLOB_CMD 0x3E -#define ADIS16209_OUTPUTS 8 - /* MSC_CTRL */ /* Self-test at power-on: 1 = disabled, 0 = enabled */ #define ADIS16209_MSC_CTRL_PWRUP_SELF_TEST (1 << 10) @@ -81,44 +76,23 @@ /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ #define ADIS16209_DIAG_STAT_ALARM1 (1<<8) /* Self-test diagnostic error flag: 1 = error condition, 0 = normal operation */ -#define ADIS16209_DIAG_STAT_SELFTEST_FAIL (1<<5) +#define ADIS16209_DIAG_STAT_SELFTEST_FAIL_BIT 5 /* SPI communications failure */ -#define ADIS16209_DIAG_STAT_SPI_FAIL (1<<3) +#define ADIS16209_DIAG_STAT_SPI_FAIL_BIT 3 /* Flash update failure */ -#define ADIS16209_DIAG_STAT_FLASH_UPT (1<<2) +#define ADIS16209_DIAG_STAT_FLASH_UPT_BIT 2 /* Power supply above 3.625 V */ -#define ADIS16209_DIAG_STAT_POWER_HIGH (1<<1) +#define ADIS16209_DIAG_STAT_POWER_HIGH_BIT 1 /* Power supply below 3.15 V */ -#define ADIS16209_DIAG_STAT_POWER_LOW (1<<0) +#define ADIS16209_DIAG_STAT_POWER_LOW_BIT 0 /* GLOB_CMD */ #define ADIS16209_GLOB_CMD_SW_RESET (1<<7) #define ADIS16209_GLOB_CMD_CLEAR_STAT (1<<4) #define ADIS16209_GLOB_CMD_FACTORY_CAL (1<<1) -#define ADIS16209_MAX_TX 24 -#define ADIS16209_MAX_RX 24 - #define ADIS16209_ERROR_ACTIVE (1<<14) -/** - * struct adis16209_state - device instance specific data - * @us: actual spi_device - * @trig: data ready trigger registered with iio - * @tx: transmit buffer - * @rx: receive buffer - * @buf_lock: mutex to protect tx and rx - **/ -struct adis16209_state { - struct spi_device *us; - struct iio_trigger *trig; - struct mutex buf_lock; - u8 tx[ADIS16209_MAX_TX] ____cacheline_aligned; - u8 rx[ADIS16209_MAX_RX]; -}; - -int adis16209_set_irq(struct iio_dev *indio_dev, bool enable); - #define ADIS16209_SCAN_SUPPLY 0 #define ADIS16209_SCAN_ACC_X 1 #define ADIS16209_SCAN_ACC_Y 2 @@ -128,45 +102,4 @@ int adis16209_set_irq(struct iio_dev *indio_dev, bool enable); #define ADIS16209_SCAN_INCLI_Y 6 #define ADIS16209_SCAN_ROT 7 -#ifdef CONFIG_IIO_BUFFER - -void adis16209_remove_trigger(struct iio_dev *indio_dev); -int adis16209_probe_trigger(struct iio_dev *indio_dev); - -ssize_t adis16209_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf); - -int adis16209_configure_ring(struct iio_dev *indio_dev); -void adis16209_unconfigure_ring(struct iio_dev *indio_dev); - -#else /* CONFIG_IIO_BUFFER */ - -static inline void adis16209_remove_trigger(struct iio_dev *indio_dev) -{ -} - -static inline int adis16209_probe_trigger(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline ssize_t -adis16209_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return 0; -} - -static int adis16209_configure_ring(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline void adis16209_unconfigure_ring(struct iio_dev *indio_dev) -{ -} - -#endif /* CONFIG_IIO_BUFFER */ #endif /* SPI_ADIS16209_H_ */ diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index a98715f6bd6..4492e51d888 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -16,282 +16,22 @@ #include <linux/list.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> +#include <linux/iio/imu/adis.h> #include "adis16209.h" -#define DRIVER_NAME "adis16209" - -/** - * adis16209_spi_write_reg_8() - write single byte to a register - * @indio_dev: iio device associated with actual device - * @reg_address: the address of the register to be written - * @val: the value to write - **/ -static int adis16209_spi_write_reg_8(struct iio_dev *indio_dev, - u8 reg_address, - u8 val) -{ - int ret; - struct adis16209_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16209_WRITE_REG(reg_address); - st->tx[1] = val; - - ret = spi_write(st->us, st->tx, 2); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/** - * adis16209_spi_write_reg_16() - write 2 bytes to a pair of registers - * @indio_dev: iio device associated actual device - * @reg_address: the address of the lower of the two registers. Second register - * is assumed to have address one greater. - * @val: value to be written - **/ -static int adis16209_spi_write_reg_16(struct iio_dev *indio_dev, - u8 lower_reg_address, - u16 value) -{ - int ret; - struct spi_message msg; - struct adis16209_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 30, - }, { - .tx_buf = st->tx + 2, - .bits_per_word = 8, - .len = 2, - .delay_usecs = 30, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16209_WRITE_REG(lower_reg_address); - st->tx[1] = value & 0xFF; - st->tx[2] = ADIS16209_WRITE_REG(lower_reg_address + 1); - st->tx[3] = (value >> 8) & 0xFF; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/** - * adis16209_spi_read_reg_16() - read 2 bytes from a 16-bit register - * @indio_dev: iio device associated with device - * @reg_address: the address of the lower of the two registers. Second register - * is assumed to have address one greater. - * @val: somewhere to pass back the value read - **/ -static int adis16209_spi_read_reg_16(struct iio_dev *indio_dev, - u8 lower_reg_address, - u16 *val) -{ - struct spi_message msg; - struct adis16209_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 30, - }, { - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 2, - .delay_usecs = 30, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16209_READ_REG(lower_reg_address); - st->tx[1] = 0; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - if (ret) { - dev_err(&st->us->dev, - "problem when reading 16 bit register 0x%02X", - lower_reg_address); - goto error_ret; - } - *val = (st->rx[0] << 8) | st->rx[1]; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -static int adis16209_reset(struct iio_dev *indio_dev) -{ - int ret; - ret = adis16209_spi_write_reg_8(indio_dev, - ADIS16209_GLOB_CMD, - ADIS16209_GLOB_CMD_SW_RESET); - if (ret) - dev_err(&indio_dev->dev, "problem resetting device"); - - return ret; -} - -static ssize_t adis16209_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - - if (len < 1) - return -EINVAL; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return adis16209_reset(indio_dev); - } - return -EINVAL; -} - -int adis16209_set_irq(struct iio_dev *indio_dev, bool enable) -{ - int ret = 0; - u16 msc; - - ret = adis16209_spi_read_reg_16(indio_dev, ADIS16209_MSC_CTRL, &msc); - if (ret) - goto error_ret; - - msc |= ADIS16209_MSC_CTRL_ACTIVE_HIGH; - msc &= ~ADIS16209_MSC_CTRL_DATA_RDY_DIO2; - if (enable) - msc |= ADIS16209_MSC_CTRL_DATA_RDY_EN; - else - msc &= ~ADIS16209_MSC_CTRL_DATA_RDY_EN; - - ret = adis16209_spi_write_reg_16(indio_dev, ADIS16209_MSC_CTRL, msc); - -error_ret: - return ret; -} - -static int adis16209_check_status(struct iio_dev *indio_dev) -{ - u16 status; - int ret; - - ret = adis16209_spi_read_reg_16(indio_dev, - ADIS16209_DIAG_STAT, &status); - if (ret < 0) { - dev_err(&indio_dev->dev, "Reading status failed\n"); - goto error_ret; - } - ret = status & 0x1F; - - if (status & ADIS16209_DIAG_STAT_SELFTEST_FAIL) - dev_err(&indio_dev->dev, "Self test failure\n"); - if (status & ADIS16209_DIAG_STAT_SPI_FAIL) - dev_err(&indio_dev->dev, "SPI failure\n"); - if (status & ADIS16209_DIAG_STAT_FLASH_UPT) - dev_err(&indio_dev->dev, "Flash update failed\n"); - if (status & ADIS16209_DIAG_STAT_POWER_HIGH) - dev_err(&indio_dev->dev, "Power supply above 3.625V\n"); - if (status & ADIS16209_DIAG_STAT_POWER_LOW) - dev_err(&indio_dev->dev, "Power supply below 3.15V\n"); - -error_ret: - return ret; -} - -static int adis16209_self_test(struct iio_dev *indio_dev) -{ - int ret; - ret = adis16209_spi_write_reg_16(indio_dev, - ADIS16209_MSC_CTRL, - ADIS16209_MSC_CTRL_SELF_TEST_EN); - if (ret) { - dev_err(&indio_dev->dev, "problem starting self test"); - goto err_ret; - } - - adis16209_check_status(indio_dev); - -err_ret: - return ret; -} - -static int adis16209_initial_setup(struct iio_dev *indio_dev) -{ - int ret; - - /* Disable IRQ */ - ret = adis16209_set_irq(indio_dev, false); - if (ret) { - dev_err(&indio_dev->dev, "disable irq failed"); - goto err_ret; - } - - /* Do self test */ - ret = adis16209_self_test(indio_dev); - if (ret) { - dev_err(&indio_dev->dev, "self test failure"); - goto err_ret; - } - - /* Read status register to check the result */ - ret = adis16209_check_status(indio_dev); - if (ret) { - adis16209_reset(indio_dev); - dev_err(&indio_dev->dev, "device not playing ball -> reset"); - msleep(ADIS16209_STARTUP_DELAY); - ret = adis16209_check_status(indio_dev); - if (ret) { - dev_err(&indio_dev->dev, "giving up"); - goto err_ret; - } - } - -err_ret: - return ret; -} - -enum adis16209_chan { - in_supply, - temp, - accel_x, - accel_y, - incli_x, - incli_y, - in_aux, - rot, -}; - -static const u8 adis16209_addresses[8][2] = { - [in_supply] = { ADIS16209_SUPPLY_OUT }, - [in_aux] = { ADIS16209_AUX_ADC }, - [accel_x] = { ADIS16209_XACCL_OUT, ADIS16209_XACCL_NULL }, - [accel_y] = { ADIS16209_YACCL_OUT, ADIS16209_YACCL_NULL }, - [incli_x] = { ADIS16209_XINCL_OUT, ADIS16209_XINCL_NULL }, - [incli_y] = { ADIS16209_YINCL_OUT, ADIS16209_YINCL_NULL }, - [rot] = { ADIS16209_ROT_OUT }, - [temp] = { ADIS16209_TEMP_OUT }, +static const u8 adis16209_addresses[8][1] = { + [ADIS16209_SCAN_SUPPLY] = { }, + [ADIS16209_SCAN_AUX_ADC] = { }, + [ADIS16209_SCAN_ACC_X] = { ADIS16209_XACCL_NULL }, + [ADIS16209_SCAN_ACC_Y] = { ADIS16209_YACCL_NULL }, + [ADIS16209_SCAN_INCLI_X] = { ADIS16209_XINCL_NULL }, + [ADIS16209_SCAN_INCLI_Y] = { ADIS16209_YINCL_NULL }, + [ADIS16209_SCAN_ROT] = { }, + [ADIS16209_SCAN_TEMP] = { }, }; static int adis16209_write_raw(struct iio_dev *indio_dev, @@ -300,6 +40,7 @@ static int adis16209_write_raw(struct iio_dev *indio_dev, int val2, long mask) { + struct adis *st = iio_priv(indio_dev); int bits; s16 val16; u8 addr; @@ -312,10 +53,10 @@ static int adis16209_write_raw(struct iio_dev *indio_dev, break; default: return -EINVAL; - }; + } val16 = val & ((1 << bits) - 1); - addr = adis16209_addresses[chan->address][1]; - return adis16209_spi_write_reg_16(indio_dev, addr, val16); + addr = adis16209_addresses[chan->scan_index][0]; + return adis_write_reg_16(st, addr, val16); } return -EINVAL; } @@ -325,63 +66,44 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { + struct adis *st = iio_priv(indio_dev); int ret; int bits; u8 addr; s16 val16; switch (mask) { - case 0: - mutex_lock(&indio_dev->mlock); - addr = adis16209_addresses[chan->address][0]; - ret = adis16209_spi_read_reg_16(indio_dev, addr, &val16); - if (ret) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - - if (val16 & ADIS16209_ERROR_ACTIVE) { - ret = adis16209_check_status(indio_dev); - if (ret) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - } - val16 = val16 & ((1 << chan->scan_type.realbits) - 1); - if (chan->scan_type.sign == 's') - val16 = (s16)(val16 << - (16 - chan->scan_type.realbits)) >> - (16 - chan->scan_type.realbits); - *val = val16; - mutex_unlock(&indio_dev->mlock); - return IIO_VAL_INT; + case IIO_CHAN_INFO_RAW: + return adis_single_conversion(indio_dev, chan, + ADIS16209_ERROR_ACTIVE, val); case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: *val = 0; if (chan->channel == 0) - *val2 = 305180; + *val2 = 305180; /* 0.30518 mV */ else - *val2 = 610500; + *val2 = 610500; /* 0.6105 mV */ return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 0; - *val2 = -470000; + *val = -470; /* -0.47 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: *val = 0; - *val2 = 2394; - return IIO_VAL_INT_PLUS_MICRO; + *val2 = IIO_G_TO_M_S_2(244140); /* 0.244140 mg */ + return IIO_VAL_INT_PLUS_NANO; case IIO_INCLI: + case IIO_ROT: *val = 0; - *val2 = 436; + *val2 = 25000; /* 0.025 degree */ return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } break; case IIO_CHAN_INFO_OFFSET: - *val = 25; + *val = 25000 / -470 - 0x4FE; /* 25 C = 0x4FE */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { @@ -390,10 +112,10 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, break; default: return -EINVAL; - }; + } mutex_lock(&indio_dev->mlock); - addr = adis16209_addresses[chan->address][1]; - ret = adis16209_spi_read_reg_16(indio_dev, addr, &val16); + addr = adis16209_addresses[chan->scan_index][0]; + ret = adis_read_reg_16(st, addr, &val16); if (ret) { mutex_unlock(&indio_dev->mlock); return ret; @@ -407,80 +129,66 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, return -EINVAL; } -static struct iio_chan_spec adis16209_channels[] = { - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - in_supply, ADIS16209_SCAN_SUPPLY, - IIO_ST('u', 14, 16, 0), 0), - IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT | - IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, - temp, ADIS16209_SCAN_TEMP, - IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, - accel_x, ADIS16209_SCAN_ACC_X, - IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, - accel_y, ADIS16209_SCAN_ACC_Y, - IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - in_aux, ADIS16209_SCAN_AUX_ADC, - IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - incli_x, ADIS16209_SCAN_INCLI_X, - IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - incli_y, ADIS16209_SCAN_INCLI_Y, - IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_ROT, 0, 1, 0, NULL, 0, IIO_MOD_X, - 0, - rot, ADIS16209_SCAN_ROT, - IIO_ST('s', 14, 16, 0), 0), +static const struct iio_chan_spec adis16209_channels[] = { + ADIS_SUPPLY_CHAN(ADIS16209_SUPPLY_OUT, ADIS16209_SCAN_SUPPLY, 14), + ADIS_TEMP_CHAN(ADIS16209_TEMP_OUT, ADIS16209_SCAN_TEMP, 12), + ADIS_ACCEL_CHAN(X, ADIS16209_XACCL_OUT, ADIS16209_SCAN_ACC_X, + BIT(IIO_CHAN_INFO_CALIBBIAS), 14), + ADIS_ACCEL_CHAN(Y, ADIS16209_YACCL_OUT, ADIS16209_SCAN_ACC_Y, + BIT(IIO_CHAN_INFO_CALIBBIAS), 14), + ADIS_AUX_ADC_CHAN(ADIS16209_AUX_ADC, ADIS16209_SCAN_AUX_ADC, 12), + ADIS_INCLI_CHAN(X, ADIS16209_XINCL_OUT, ADIS16209_SCAN_INCLI_X, 0, 14), + ADIS_INCLI_CHAN(Y, ADIS16209_YINCL_OUT, ADIS16209_SCAN_INCLI_Y, 0, 14), + ADIS_ROT_CHAN(X, ADIS16209_ROT_OUT, ADIS16209_SCAN_ROT, 0, 14), IIO_CHAN_SOFT_TIMESTAMP(8) }; -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16209_write_reset, 0); - -static struct attribute *adis16209_attributes[] = { - &iio_dev_attr_reset.dev_attr.attr, - NULL -}; - -static const struct attribute_group adis16209_attribute_group = { - .attrs = adis16209_attributes, -}; - static const struct iio_info adis16209_info = { - .attrs = &adis16209_attribute_group, .read_raw = &adis16209_read_raw, .write_raw = &adis16209_write_raw, + .update_scan_mode = adis_update_scan_mode, .driver_module = THIS_MODULE, }; -static int __devinit adis16209_probe(struct spi_device *spi) +static const char * const adis16209_status_error_msgs[] = { + [ADIS16209_DIAG_STAT_SELFTEST_FAIL_BIT] = "Self test failure", + [ADIS16209_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure", + [ADIS16209_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed", + [ADIS16209_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V", + [ADIS16209_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V", +}; + +static const struct adis_data adis16209_data = { + .read_delay = 30, + .msc_ctrl_reg = ADIS16209_MSC_CTRL, + .glob_cmd_reg = ADIS16209_GLOB_CMD, + .diag_stat_reg = ADIS16209_DIAG_STAT, + + .self_test_mask = ADIS16209_MSC_CTRL_SELF_TEST_EN, + .startup_delay = ADIS16209_STARTUP_DELAY, + + .status_error_msgs = adis16209_status_error_msgs, + .status_error_mask = BIT(ADIS16209_DIAG_STAT_SELFTEST_FAIL_BIT) | + BIT(ADIS16209_DIAG_STAT_SPI_FAIL_BIT) | + BIT(ADIS16209_DIAG_STAT_FLASH_UPT_BIT) | + BIT(ADIS16209_DIAG_STAT_POWER_HIGH_BIT) | + BIT(ADIS16209_DIAG_STAT_POWER_LOW_BIT), +}; + + +static int adis16209_probe(struct spi_device *spi) { int ret; - struct adis16209_state *st; + struct adis *st; struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; st = iio_priv(indio_dev); /* this is only used for removal purposes */ spi_set_drvdata(spi, indio_dev); - st->us = spi; - mutex_init(&st->buf_lock); indio_dev->name = spi->dev.driver->name; indio_dev->dev.parent = &spi->dev; @@ -489,57 +197,35 @@ static int __devinit adis16209_probe(struct spi_device *spi) indio_dev->num_channels = ARRAY_SIZE(adis16209_channels); indio_dev->modes = INDIO_DIRECT_MODE; - ret = adis16209_configure_ring(indio_dev); + ret = adis_init(st, indio_dev, spi, &adis16209_data); if (ret) - goto error_free_dev; - - ret = iio_buffer_register(indio_dev, - adis16209_channels, - ARRAY_SIZE(adis16209_channels)); - if (ret) { - printk(KERN_ERR "failed to initialize the ring\n"); - goto error_unreg_ring_funcs; - } - - if (spi->irq) { - ret = adis16209_probe_trigger(indio_dev); - if (ret) - goto error_uninitialize_ring; - } + return ret; + ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL); + if (ret) + return ret; /* Get the device into a sane initial state */ - ret = adis16209_initial_setup(indio_dev); + ret = adis_initial_startup(st); if (ret) - goto error_remove_trigger; + goto error_cleanup_buffer_trigger; ret = iio_device_register(indio_dev); if (ret) - goto error_remove_trigger; + goto error_cleanup_buffer_trigger; return 0; -error_remove_trigger: - adis16209_remove_trigger(indio_dev); -error_uninitialize_ring: - iio_buffer_unregister(indio_dev); -error_unreg_ring_funcs: - adis16209_unconfigure_ring(indio_dev); -error_free_dev: - iio_free_device(indio_dev); -error_ret: +error_cleanup_buffer_trigger: + adis_cleanup_buffer_and_trigger(st, indio_dev); return ret; } static int adis16209_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); - - flush_scheduled_work(); + struct adis *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - adis16209_remove_trigger(indio_dev); - iio_buffer_unregister(indio_dev); - adis16209_unconfigure_ring(indio_dev); - iio_free_device(indio_dev); + adis_cleanup_buffer_and_trigger(st, indio_dev); return 0; } @@ -550,7 +236,7 @@ static struct spi_driver adis16209_driver = { .owner = THIS_MODULE, }, .probe = adis16209_probe, - .remove = __devexit_p(adis16209_remove), + .remove = adis16209_remove, }; module_spi_driver(adis16209_driver); diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c deleted file mode 100644 index 2a6fd334f5f..00000000000 --- a/drivers/staging/iio/accel/adis16209_ring.c +++ /dev/null @@ -1,139 +0,0 @@ -#include <linux/export.h> -#include <linux/interrupt.h> -#include <linux/mutex.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> - -#include "../iio.h" -#include "../ring_sw.h" -#include "../trigger_consumer.h" -#include "adis16209.h" - -/** - * adis16209_read_ring_data() read data registers which will be placed into ring - * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @rx: somewhere to pass back the value read - **/ -static int adis16209_read_ring_data(struct device *dev, u8 *rx) -{ - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16209_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[ADIS16209_OUTPUTS + 1]; - int ret; - int i; - - mutex_lock(&st->buf_lock); - - spi_message_init(&msg); - - memset(xfers, 0, sizeof(xfers)); - for (i = 0; i <= ADIS16209_OUTPUTS; i++) { - xfers[i].bits_per_word = 8; - xfers[i].cs_change = 1; - xfers[i].len = 2; - xfers[i].delay_usecs = 30; - xfers[i].tx_buf = st->tx + 2 * i; - st->tx[2 * i] - = ADIS16209_READ_REG(ADIS16209_SUPPLY_OUT + 2 * i); - st->tx[2 * i + 1] = 0; - if (i >= 1) - xfers[i].rx_buf = rx + 2 * (i - 1); - spi_message_add_tail(&xfers[i], &msg); - } - - ret = spi_sync(st->us, &msg); - if (ret) - dev_err(&st->us->dev, "problem when burst reading"); - - mutex_unlock(&st->buf_lock); - - return ret; -} - -/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device - * specific to be rolled into the core. - */ -static irqreturn_t adis16209_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct adis16209_state *st = iio_priv(indio_dev); - struct iio_buffer *ring = indio_dev->buffer; - - int i = 0; - s16 *data; - size_t datasize = ring->access->get_bytes_per_datum(ring); - - data = kmalloc(datasize , GFP_KERNEL); - if (data == NULL) { - dev_err(&st->us->dev, "memory alloc failed in ring bh"); - return -ENOMEM; - } - - if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) && - adis16209_read_ring_data(&indio_dev->dev, st->rx) >= 0) - for (; i < bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength); i++) - data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2])); - - /* Guaranteed to be aligned with 8 byte boundary */ - if (ring->scan_timestamp) - *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - - ring->access->store_to(ring, (u8 *)data, pf->timestamp); - - iio_trigger_notify_done(indio_dev->trig); - kfree(data); - - return IRQ_HANDLED; -} - -void adis16209_unconfigure_ring(struct iio_dev *indio_dev) -{ - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->buffer); -} - -static const struct iio_buffer_setup_ops adis16209_ring_setup_ops = { - .preenable = &iio_sw_buffer_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, -}; - -int adis16209_configure_ring(struct iio_dev *indio_dev) -{ - int ret = 0; - struct iio_buffer *ring; - - ring = iio_sw_rb_allocate(indio_dev); - if (!ring) { - ret = -ENOMEM; - return ret; - } - indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ - ring->access = &ring_sw_access_funcs; - ring->scan_timestamp = true; - indio_dev->setup_ops = &adis16209_ring_setup_ops; - - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, - &adis16209_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "%s_consumer%d", - indio_dev->name, - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_iio_sw_rb_free; - } - - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_iio_sw_rb_free: - iio_sw_rb_free(indio_dev->buffer); - return ret; -} diff --git a/drivers/staging/iio/accel/adis16209_trigger.c b/drivers/staging/iio/accel/adis16209_trigger.c deleted file mode 100644 index c5d82c1a55d..00000000000 --- a/drivers/staging/iio/accel/adis16209_trigger.c +++ /dev/null @@ -1,81 +0,0 @@ -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/export.h> - -#include "../iio.h" -#include "../trigger.h" -#include "adis16209.h" - -/** - * adis16209_data_rdy_trig_poll() the event handler for the data rdy trig - **/ -static irqreturn_t adis16209_data_rdy_trig_poll(int irq, void *trig) -{ - iio_trigger_poll(trig, iio_get_time_ns()); - return IRQ_HANDLED; -} - -/** - * adis16209_data_rdy_trigger_set_state() set datardy interrupt state - **/ -static int adis16209_data_rdy_trigger_set_state(struct iio_trigger *trig, - bool state) -{ - struct iio_dev *indio_dev = trig->private_data; - - dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); - return adis16209_set_irq(indio_dev, state); -} - -static const struct iio_trigger_ops adis16209_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &adis16209_data_rdy_trigger_set_state, -}; - -int adis16209_probe_trigger(struct iio_dev *indio_dev) -{ - int ret; - struct adis16209_state *st = iio_priv(indio_dev); - - st->trig = iio_allocate_trigger("adis16209-dev%d", indio_dev->id); - if (st->trig == NULL) { - ret = -ENOMEM; - goto error_ret; - } - - ret = request_irq(st->us->irq, - adis16209_data_rdy_trig_poll, - IRQF_TRIGGER_RISING, - "adis16209", - st->trig); - if (ret) - goto error_free_trig; - st->trig->dev.parent = &st->us->dev; - st->trig->ops = &adis16209_trigger_ops; - st->trig->private_data = indio_dev; - ret = iio_trigger_register(st->trig); - - /* select default trigger */ - indio_dev->trig = st->trig; - if (ret) - goto error_free_irq; - - return 0; - -error_free_irq: - free_irq(st->us->irq, st->trig); -error_free_trig: - iio_free_trigger(st->trig); -error_ret: - return ret; -} - -void adis16209_remove_trigger(struct iio_dev *indio_dev) -{ - struct adis16209_state *st = iio_priv(indio_dev); - - iio_trigger_unregister(st->trig); - free_irq(st->us->irq, st->trig); - iio_free_trigger(st->trig); -} diff --git a/drivers/staging/iio/accel/adis16220.h b/drivers/staging/iio/accel/adis16220.h index 024313cf5cf..a894ad7fb26 100644 --- a/drivers/staging/iio/accel/adis16220.h +++ b/drivers/staging/iio/accel/adis16220.h @@ -1,10 +1,9 @@ #ifndef SPI_ADIS16220_H_ #define SPI_ADIS16220_H_ -#define ADIS16220_STARTUP_DELAY 220 /* ms */ +#include <linux/iio/imu/adis.h> -#define ADIS16220_READ_REG(a) a -#define ADIS16220_WRITE_REG(a) ((a) | 0x80) +#define ADIS16220_STARTUP_DELAY 220 /* ms */ /* Flash memory write count */ #define ADIS16220_FLASH_CNT 0x00 @@ -102,15 +101,15 @@ #define ADIS16220_DIAG_STAT_FLASH_CHK (1<<6) #define ADIS16220_DIAG_STAT_SELF_TEST (1<<5) /* Capture period violation/interruption */ -#define ADIS16220_DIAG_STAT_VIOLATION (1<<4) +#define ADIS16220_DIAG_STAT_VIOLATION_BIT 4 /* SPI communications failure */ -#define ADIS16220_DIAG_STAT_SPI_FAIL (1<<3) +#define ADIS16220_DIAG_STAT_SPI_FAIL_BIT 3 /* Flash update failure */ -#define ADIS16220_DIAG_STAT_FLASH_UPT (1<<2) +#define ADIS16220_DIAG_STAT_FLASH_UPT_BIT 2 /* Power supply above 3.625 V */ -#define ADIS16220_DIAG_STAT_POWER_HIGH (1<<1) +#define ADIS16220_DIAG_STAT_POWER_HIGH_BIT 1 /* Power supply below 3.15 V */ -#define ADIS16220_DIAG_STAT_POWER_LOW (1<<0) +#define ADIS16220_DIAG_STAT_POWER_LOW_BIT 0 /* GLOB_CMD */ #define ADIS16220_GLOB_CMD_SW_RESET (1<<7) @@ -125,13 +124,14 @@ /** * struct adis16220_state - device instance specific data - * @us: actual spi_device + * @adis: adis device * @tx: transmit buffer * @rx: receive buffer * @buf_lock: mutex to protect tx and rx **/ struct adis16220_state { - struct spi_device *us; + struct adis adis; + struct mutex buf_lock; u8 tx[ADIS16220_MAX_TX] ____cacheline_aligned; u8 rx[ADIS16220_MAX_RX]; diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index 51a852d4548..6f38ca95f9b 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -15,143 +15,24 @@ #include <linux/sysfs.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #include "adis16220.h" -#define DRIVER_NAME "adis16220" - -/** - * adis16220_spi_write_reg_8() - write single byte to a register - * @indio_dev: iio device associated with child of actual device - * @reg_address: the address of the register to be written - * @val: the value to write - **/ -static int adis16220_spi_write_reg_8(struct iio_dev *indio_dev, - u8 reg_address, - u8 val) -{ - int ret; - struct adis16220_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16220_WRITE_REG(reg_address); - st->tx[1] = val; - - ret = spi_write(st->us, st->tx, 2); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/** - * adis16220_spi_write_reg_16() - write 2 bytes to a pair of registers - * @indio_dev: iio device associated with child of actual device - * @reg_address: the address of the lower of the two registers. Second register - * is assumed to have address one greater. - * @val: value to be written - **/ -static int adis16220_spi_write_reg_16(struct iio_dev *indio_dev, - u8 lower_reg_address, - u16 value) -{ - int ret; - struct spi_message msg; - struct adis16220_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 35, - }, { - .tx_buf = st->tx + 2, - .bits_per_word = 8, - .len = 2, - .delay_usecs = 35, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16220_WRITE_REG(lower_reg_address); - st->tx[1] = value & 0xFF; - st->tx[2] = ADIS16220_WRITE_REG(lower_reg_address + 1); - st->tx[3] = (value >> 8) & 0xFF; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/** - * adis16220_spi_read_reg_16() - read 2 bytes from a 16-bit register - * @indio_dev: iio device associated with child of actual device - * @reg_address: the address of the lower of the two registers. Second register - * is assumed to have address one greater. - * @val: somewhere to pass back the value read - **/ -static int adis16220_spi_read_reg_16(struct iio_dev *indio_dev, - u8 lower_reg_address, - u16 *val) -{ - struct spi_message msg; - struct adis16220_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 35, - }, { - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 35, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16220_READ_REG(lower_reg_address); - st->tx[1] = 0; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - if (ret) { - dev_err(&st->us->dev, - "problem when reading 16 bit register 0x%02X", - lower_reg_address); - goto error_ret; - } - *val = (st->rx[0] << 8) | st->rx[1]; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - static ssize_t adis16220_read_16bit(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct adis16220_state *st = iio_priv(indio_dev); ssize_t ret; s16 val = 0; /* Take the iio_dev status lock */ mutex_lock(&indio_dev->mlock); - ret = adis16220_spi_read_reg_16(indio_dev, this_attr->address, + ret = adis_read_reg_16(&st->adis, this_attr->address, (u16 *)&val); mutex_unlock(&indio_dev->mlock); if (ret) @@ -164,15 +45,16 @@ static ssize_t adis16220_write_16bit(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + struct adis16220_state *st = iio_priv(indio_dev); int ret; u16 val; ret = kstrtou16(buf, 10, &val); if (ret) goto error_ret; - ret = adis16220_spi_write_reg_16(indio_dev, this_attr->address, val); + ret = adis_write_reg_16(&st->adis, this_attr->address, val); error_ret: return ret ? ret : len; @@ -180,10 +62,11 @@ error_ret: static int adis16220_capture(struct iio_dev *indio_dev) { + struct adis16220_state *st = iio_priv(indio_dev); int ret; - ret = adis16220_spi_write_reg_16(indio_dev, - ADIS16220_GLOB_CMD, - 0xBF08); /* initiates a manual data capture */ + + /* initiates a manual data capture */ + ret = adis_write_reg_16(&st->adis, ADIS16220_GLOB_CMD, 0xBF08); if (ret) dev_err(&indio_dev->dev, "problem beginning capture"); @@ -192,43 +75,11 @@ static int adis16220_capture(struct iio_dev *indio_dev) return ret; } -static int adis16220_reset(struct iio_dev *indio_dev) -{ - int ret; - ret = adis16220_spi_write_reg_8(indio_dev, - ADIS16220_GLOB_CMD, - ADIS16220_GLOB_CMD_SW_RESET); - if (ret) - dev_err(&indio_dev->dev, "problem resetting device"); - - return ret; -} - -static ssize_t adis16220_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - bool val; - int ret; - - ret = strtobool(buf, &val); - if (ret) - return ret; - if (!val) - return -EINVAL; - - ret = adis16220_reset(indio_dev); - if (ret) - return ret; - return len; -} - static ssize_t adis16220_write_capture(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); bool val; int ret; @@ -244,81 +95,6 @@ static ssize_t adis16220_write_capture(struct device *dev, return len; } -static int adis16220_check_status(struct iio_dev *indio_dev) -{ - u16 status; - int ret; - - ret = adis16220_spi_read_reg_16(indio_dev, ADIS16220_DIAG_STAT, - &status); - - if (ret < 0) { - dev_err(&indio_dev->dev, "Reading status failed\n"); - goto error_ret; - } - ret = status & 0x7F; - - if (status & ADIS16220_DIAG_STAT_VIOLATION) - dev_err(&indio_dev->dev, - "Capture period violation/interruption\n"); - if (status & ADIS16220_DIAG_STAT_SPI_FAIL) - dev_err(&indio_dev->dev, "SPI failure\n"); - if (status & ADIS16220_DIAG_STAT_FLASH_UPT) - dev_err(&indio_dev->dev, "Flash update failed\n"); - if (status & ADIS16220_DIAG_STAT_POWER_HIGH) - dev_err(&indio_dev->dev, "Power supply above 3.625V\n"); - if (status & ADIS16220_DIAG_STAT_POWER_LOW) - dev_err(&indio_dev->dev, "Power supply below 3.15V\n"); - -error_ret: - return ret; -} - -static int adis16220_self_test(struct iio_dev *indio_dev) -{ - int ret; - ret = adis16220_spi_write_reg_16(indio_dev, - ADIS16220_MSC_CTRL, - ADIS16220_MSC_CTRL_SELF_TEST_EN); - if (ret) { - dev_err(&indio_dev->dev, "problem starting self test"); - goto err_ret; - } - - adis16220_check_status(indio_dev); - -err_ret: - return ret; -} - -static int adis16220_initial_setup(struct iio_dev *indio_dev) -{ - int ret; - - /* Do self test */ - ret = adis16220_self_test(indio_dev); - if (ret) { - dev_err(&indio_dev->dev, "self test failure"); - goto err_ret; - } - - /* Read status register to check the result */ - ret = adis16220_check_status(indio_dev); - if (ret) { - adis16220_reset(indio_dev); - dev_err(&indio_dev->dev, "device not playing ball -> reset"); - msleep(ADIS16220_STARTUP_DELAY); - ret = adis16220_check_status(indio_dev); - if (ret) { - dev_err(&indio_dev->dev, "giving up"); - goto err_ret; - } - } - -err_ret: - return ret; -} - static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev, char *buf, loff_t off, @@ -326,7 +102,6 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev, int addr) { struct adis16220_state *st = iio_priv(indio_dev); - struct spi_message msg; struct spi_transfer xfers[] = { { .tx_buf = st->tx, @@ -355,7 +130,7 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev, count = ADIS16220_CAPTURE_SIZE - off; /* write the begin position of capture buffer */ - ret = adis16220_spi_write_reg_16(indio_dev, + ret = adis_write_reg_16(&st->adis, ADIS16220_CAPT_PNTR, off > 1); if (ret) @@ -364,16 +139,14 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev, /* read count/2 values from capture buffer */ mutex_lock(&st->buf_lock); + for (i = 0; i < count; i += 2) { - st->tx[i] = ADIS16220_READ_REG(addr); + st->tx[i] = ADIS_READ_REG(addr); st->tx[i + 1] = 0; } xfers[1].len = count; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->adis.spi, xfers, ARRAY_SIZE(xfers)); if (ret) { mutex_unlock(&st->buf_lock); @@ -392,8 +165,7 @@ static ssize_t adis16220_accel_bin_read(struct file *filp, struct kobject *kobj, loff_t off, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj)); return adis16220_capture_buffer_read(indio_dev, buf, off, count, @@ -414,8 +186,7 @@ static ssize_t adis16220_adc1_bin_read(struct file *filp, struct kobject *kobj, char *buf, loff_t off, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj)); return adis16220_capture_buffer_read(indio_dev, buf, off, count, @@ -436,8 +207,7 @@ static ssize_t adis16220_adc2_bin_read(struct file *filp, struct kobject *kobj, char *buf, loff_t off, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj)); return adis16220_capture_buffer_read(indio_dev, buf, off, count, @@ -454,9 +224,6 @@ static struct bin_attribute adc2_bin = { .size = ADIS16220_CAPTURE_SIZE, }; -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, - adis16220_write_reset, 0); - #define IIO_DEV_ATTR_CAPTURE(_store) \ IIO_DEVICE_ATTR(capture, S_IWUSR, NULL, _store, 0) @@ -500,6 +267,8 @@ static int adis16220_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { + struct adis16220_state *st = iio_priv(indio_dev); + const struct adis16220_address_spec *addr; int ret = -EINVAL; int addrind = 0; u16 uval; @@ -507,12 +276,12 @@ static int adis16220_read_raw(struct iio_dev *indio_dev, u8 bits; switch (mask) { - case 0: + case IIO_CHAN_INFO_RAW: addrind = 0; break; case IIO_CHAN_INFO_OFFSET: if (chan->type == IIO_TEMP) { - *val = 25; + *val = 25000 / -470 - 1278; /* 25 C = 1278 */ return IIO_VAL_INT; } addrind = 1; @@ -521,19 +290,22 @@ static int adis16220_read_raw(struct iio_dev *indio_dev, addrind = 2; break; case IIO_CHAN_INFO_SCALE: - *val = 0; switch (chan->type) { case IIO_TEMP: - *val2 = -470000; + *val = -470; /* -0.47 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: - *val2 = 1887042; + *val2 = IIO_G_TO_M_S_2(19073); /* 19.073 g */ return IIO_VAL_INT_PLUS_MICRO; case IIO_VOLTAGE: - if (chan->channel == 0) - *val2 = 0012221; - else /* Should really be dependent on VDD */ - *val2 = 305; + if (chan->channel == 0) { + *val = 1; + *val2 = 220700; /* 1.2207 mV */ + } else { + /* Should really be dependent on VDD */ + *val2 = 305180; /* 305.18 uV */ + } return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; @@ -541,28 +313,21 @@ static int adis16220_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } - if (adis16220_addresses[chan->address][addrind].sign) { - ret = adis16220_spi_read_reg_16(indio_dev, - adis16220_addresses[chan - ->address] - [addrind].addr, - &sval); + addr = &adis16220_addresses[chan->address][addrind]; + if (addr->sign) { + ret = adis_read_reg_16(&st->adis, addr->addr, &sval); if (ret) return ret; - bits = adis16220_addresses[chan->address][addrind].bits; + bits = addr->bits; sval &= (1 << bits) - 1; sval = (s16)(sval << (16 - bits)) >> (16 - bits); *val = sval; return IIO_VAL_INT; } else { - ret = adis16220_spi_read_reg_16(indio_dev, - adis16220_addresses[chan - ->address] - [addrind].addr, - &uval); + ret = adis_read_reg_16(&st->adis, addr->addr, &uval); if (ret) return ret; - bits = adis16220_addresses[chan->address][addrind].bits; + bits = addr->bits; uval &= (1 << bits) - 1; *val = uval; return IIO_VAL_INT; @@ -575,38 +340,42 @@ static const struct iio_chan_spec adis16220_channels[] = { .indexed = 1, .channel = 0, .extend_name = "supply", - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), .address = in_supply, }, { .type = IIO_ACCEL, - .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT | - IIO_CHAN_INFO_PEAK_SEPARATE_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_OFFSET) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_PEAK), .address = accel, }, { .type = IIO_TEMP, .indexed = 1, .channel = 0, - .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_OFFSET) | + BIT(IIO_CHAN_INFO_SCALE), .address = temp, }, { .type = IIO_VOLTAGE, .indexed = 1, .channel = 1, - .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_OFFSET) | + BIT(IIO_CHAN_INFO_SCALE), .address = in_1, }, { .type = IIO_VOLTAGE, .indexed = 1, .channel = 2, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .address = in_2, } }; static struct attribute *adis16220_attributes[] = { - &iio_dev_attr_reset.dev_attr.attr, &iio_dev_attr_capture.dev_attr.attr, &iio_dev_attr_capture_count.dev_attr.attr, NULL @@ -622,26 +391,47 @@ static const struct iio_info adis16220_info = { .read_raw = &adis16220_read_raw, }; -static int __devinit adis16220_probe(struct spi_device *spi) +static const char * const adis16220_status_error_msgs[] = { + [ADIS16220_DIAG_STAT_VIOLATION_BIT] = "Capture period violation/interruption", + [ADIS16220_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure", + [ADIS16220_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed", + [ADIS16220_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V", + [ADIS16220_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V", +}; + +static const struct adis_data adis16220_data = { + .read_delay = 35, + .write_delay = 35, + .msc_ctrl_reg = ADIS16220_MSC_CTRL, + .glob_cmd_reg = ADIS16220_GLOB_CMD, + .diag_stat_reg = ADIS16220_DIAG_STAT, + + .self_test_mask = ADIS16220_MSC_CTRL_SELF_TEST_EN, + .startup_delay = ADIS16220_STARTUP_DELAY, + + .status_error_msgs = adis16220_status_error_msgs, + .status_error_mask = BIT(ADIS16220_DIAG_STAT_VIOLATION_BIT) | + BIT(ADIS16220_DIAG_STAT_SPI_FAIL_BIT) | + BIT(ADIS16220_DIAG_STAT_FLASH_UPT_BIT) | + BIT(ADIS16220_DIAG_STAT_POWER_HIGH_BIT) | + BIT(ADIS16220_DIAG_STAT_POWER_LOW_BIT), +}; + +static int adis16220_probe(struct spi_device *spi) { int ret; struct adis16220_state *st; struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; st = iio_priv(indio_dev); /* this is only used for removal purposes */ spi_set_drvdata(spi, indio_dev); - st->us = spi; - mutex_init(&st->buf_lock); - indio_dev->name = spi->dev.driver->name; indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16220_info; @@ -649,13 +439,13 @@ static int __devinit adis16220_probe(struct spi_device *spi) indio_dev->channels = adis16220_channels; indio_dev->num_channels = ARRAY_SIZE(adis16220_channels); - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(&spi->dev, indio_dev); if (ret) - goto error_free_dev; + return ret; ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &accel_bin); if (ret) - goto error_unregister_dev; + return ret; ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &adc1_bin); if (ret) @@ -665,8 +455,11 @@ static int __devinit adis16220_probe(struct spi_device *spi) if (ret) goto error_rm_adc1_bin; + ret = adis_init(&st->adis, indio_dev, spi, &adis16220_data); + if (ret) + goto error_rm_adc2_bin; /* Get the device into a sane initial state */ - ret = adis16220_initial_setup(indio_dev); + ret = adis_initial_startup(&st->adis); if (ret) goto error_rm_adc2_bin; return 0; @@ -677,11 +470,6 @@ error_rm_adc1_bin: sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin); error_rm_accel_bin: sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin); -error_unregister_dev: - iio_device_unregister(indio_dev); -error_free_dev: - iio_free_device(indio_dev); -error_ret: return ret; } @@ -689,13 +477,9 @@ static int adis16220_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); - flush_scheduled_work(); - sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc2_bin); sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin); sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin); - iio_device_unregister(indio_dev); - iio_free_device(indio_dev); return 0; } @@ -706,7 +490,7 @@ static struct spi_driver adis16220_driver = { .owner = THIS_MODULE, }, .probe = adis16220_probe, - .remove = __devexit_p(adis16220_remove), + .remove = adis16220_remove, }; module_spi_driver(adis16220_driver); diff --git a/drivers/staging/iio/accel/adis16240.h b/drivers/staging/iio/accel/adis16240.h index 3fabcc0b347..d442d49f51f 100644 --- a/drivers/staging/iio/accel/adis16240.h +++ b/drivers/staging/iio/accel/adis16240.h @@ -3,9 +3,6 @@ #define ADIS16240_STARTUP_DELAY 220 /* ms */ -#define ADIS16240_READ_REG(a) a -#define ADIS16240_WRITE_REG(a) ((a) | 0x80) - /* Flash memory write count */ #define ADIS16240_FLASH_CNT 0x00 /* Output, power supply */ @@ -75,8 +72,6 @@ /* System command */ #define ADIS16240_GLOB_CMD 0x4A -#define ADIS16240_OUTPUTS 6 - /* MSC_CTRL */ /* Enables sum-of-squares output (XYZPEAK_OUT) */ #define ADIS16240_MSC_CTRL_XYZPEAK_OUT_EN (1 << 15) @@ -101,17 +96,17 @@ /* Flash test, checksum flag: 1 = mismatch, 0 = match */ #define ADIS16240_DIAG_STAT_CHKSUM (1<<6) /* Power-on, self-test flag: 1 = failure, 0 = pass */ -#define ADIS16240_DIAG_STAT_PWRON_FAIL (1<<5) +#define ADIS16240_DIAG_STAT_PWRON_FAIL_BIT 5 /* Power-on self-test: 1 = in-progress, 0 = complete */ #define ADIS16240_DIAG_STAT_PWRON_BUSY (1<<4) /* SPI communications failure */ -#define ADIS16240_DIAG_STAT_SPI_FAIL (1<<3) +#define ADIS16240_DIAG_STAT_SPI_FAIL_BIT 3 /* Flash update failure */ -#define ADIS16240_DIAG_STAT_FLASH_UPT (1<<2) +#define ADIS16240_DIAG_STAT_FLASH_UPT_BIT 2 /* Power supply above 3.625 V */ -#define ADIS16240_DIAG_STAT_POWER_HIGH (1<<1) +#define ADIS16240_DIAG_STAT_POWER_HIGH_BIT 1 /* Power supply below 3.15 V */ -#define ADIS16240_DIAG_STAT_POWER_LOW (1<<0) +#define ADIS16240_DIAG_STAT_POWER_LOW_BIT 0 /* GLOB_CMD */ #define ADIS16240_GLOB_CMD_RESUME (1<<8) @@ -120,77 +115,15 @@ #define ADIS16240_ERROR_ACTIVE (1<<14) -#define ADIS16240_MAX_TX 24 -#define ADIS16240_MAX_RX 24 - -/** - * struct adis16240_state - device instance specific data - * @us: actual spi_device - * @trig: data ready trigger registered with iio - * @tx: transmit buffer - * @rx: receive buffer - * @buf_lock: mutex to protect tx and rx - **/ -struct adis16240_state { - struct spi_device *us; - struct iio_trigger *trig; - struct mutex buf_lock; - u8 tx[ADIS16240_MAX_TX] ____cacheline_aligned; - u8 rx[ADIS16240_MAX_RX]; -}; - -int adis16240_set_irq(struct iio_dev *indio_dev, bool enable); - /* At the moment triggers are only used for ring buffer * filling. This may change! */ -#define ADIS16240_SCAN_SUPPLY 0 -#define ADIS16240_SCAN_ACC_X 1 -#define ADIS16240_SCAN_ACC_Y 2 -#define ADIS16240_SCAN_ACC_Z 3 +#define ADIS16240_SCAN_ACC_X 0 +#define ADIS16240_SCAN_ACC_Y 1 +#define ADIS16240_SCAN_ACC_Z 2 +#define ADIS16240_SCAN_SUPPLY 3 #define ADIS16240_SCAN_AUX_ADC 4 #define ADIS16240_SCAN_TEMP 5 -#ifdef CONFIG_IIO_BUFFER -void adis16240_remove_trigger(struct iio_dev *indio_dev); -int adis16240_probe_trigger(struct iio_dev *indio_dev); - -ssize_t adis16240_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf); - - -int adis16240_configure_ring(struct iio_dev *indio_dev); -void adis16240_unconfigure_ring(struct iio_dev *indio_dev); - -#else /* CONFIG_IIO_BUFFER */ - -static inline void adis16240_remove_trigger(struct iio_dev *indio_dev) -{ -} - -static inline int adis16240_probe_trigger(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline ssize_t -adis16240_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return 0; -} - -static int adis16240_configure_ring(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline void adis16240_unconfigure_ring(struct iio_dev *indio_dev) -{ -} - -#endif /* CONFIG_IIO_BUFFER */ #endif /* SPI_ADIS16240_H_ */ diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index 17f77fef7f2..3a303a03d02 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -19,154 +19,32 @@ #include <linux/list.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> +#include <linux/iio/imu/adis.h> #include "adis16240.h" -#define DRIVER_NAME "adis16240" - -static int adis16240_check_status(struct iio_dev *indio_dev); - -/** - * adis16240_spi_write_reg_8() - write single byte to a register - * @indio_dev: iio_dev associated with device - * @reg_address: the address of the register to be written - * @val: the value to write - **/ -static int adis16240_spi_write_reg_8(struct iio_dev *indio_dev, - u8 reg_address, - u8 val) -{ - int ret; - struct adis16240_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16240_WRITE_REG(reg_address); - st->tx[1] = val; - - ret = spi_write(st->us, st->tx, 2); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/** - * adis16240_spi_write_reg_16() - write 2 bytes to a pair of registers - * @indio_dev: iio_dev for this device - * @reg_address: the address of the lower of the two registers. Second register - * is assumed to have address one greater. - * @val: value to be written - **/ -static int adis16240_spi_write_reg_16(struct iio_dev *indio_dev, - u8 lower_reg_address, - u16 value) -{ - int ret; - struct spi_message msg; - struct adis16240_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 35, - }, { - .tx_buf = st->tx + 2, - .bits_per_word = 8, - .len = 2, - .delay_usecs = 35, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16240_WRITE_REG(lower_reg_address); - st->tx[1] = value & 0xFF; - st->tx[2] = ADIS16240_WRITE_REG(lower_reg_address + 1); - st->tx[3] = (value >> 8) & 0xFF; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/** - * adis16240_spi_read_reg_16() - read 2 bytes from a 16-bit register - * @indio_dev: iio_dev for this device - * @reg_address: the address of the lower of the two registers. Second register - * is assumed to have address one greater. - * @val: somewhere to pass back the value read - **/ -static int adis16240_spi_read_reg_16(struct iio_dev *indio_dev, - u8 lower_reg_address, - u16 *val) -{ - struct spi_message msg; - struct adis16240_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 35, - }, { - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 35, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16240_READ_REG(lower_reg_address); - st->tx[1] = 0; - st->tx[2] = 0; - st->tx[3] = 0; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - if (ret) { - dev_err(&st->us->dev, - "problem when reading 16 bit register 0x%02X", - lower_reg_address); - goto error_ret; - } - *val = (st->rx[0] << 8) | st->rx[1]; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - static ssize_t adis16240_spi_read_signed(struct device *dev, struct device_attribute *attr, char *buf, unsigned bits) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct adis *st = iio_priv(indio_dev); int ret; s16 val = 0; unsigned shift = 16 - bits; struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - ret = adis16240_spi_read_reg_16(indio_dev, + ret = adis_read_reg_16(st, this_attr->address, (u16 *)&val); if (ret) return ret; if (val & ADIS16240_ERROR_ACTIVE) - adis16240_check_status(indio_dev); + adis_check_status(st); val = ((s16)(val << shift) >> shift); return sprintf(buf, "%d\n", val); @@ -177,7 +55,7 @@ static ssize_t adis16240_read_12bit_signed(struct device *dev, char *buf) { ssize_t ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); /* Take the iio_dev status lock */ mutex_lock(&indio_dev->mlock); @@ -187,171 +65,16 @@ static ssize_t adis16240_read_12bit_signed(struct device *dev, return ret; } -static int adis16240_reset(struct iio_dev *indio_dev) -{ - int ret; - ret = adis16240_spi_write_reg_8(indio_dev, - ADIS16240_GLOB_CMD, - ADIS16240_GLOB_CMD_SW_RESET); - if (ret) - dev_err(&indio_dev->dev, "problem resetting device"); - - return ret; -} - -static ssize_t adis16240_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - - if (len < 1) - return -EINVAL; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return adis16240_reset(indio_dev); - } - return -EINVAL; -} - -int adis16240_set_irq(struct iio_dev *indio_dev, bool enable) -{ - int ret = 0; - u16 msc; - - ret = adis16240_spi_read_reg_16(indio_dev, - ADIS16240_MSC_CTRL, &msc); - if (ret) - goto error_ret; - - msc |= ADIS16240_MSC_CTRL_ACTIVE_HIGH; - msc &= ~ADIS16240_MSC_CTRL_DATA_RDY_DIO2; - if (enable) - msc |= ADIS16240_MSC_CTRL_DATA_RDY_EN; - else - msc &= ~ADIS16240_MSC_CTRL_DATA_RDY_EN; - - ret = adis16240_spi_write_reg_16(indio_dev, - ADIS16240_MSC_CTRL, msc); - -error_ret: - return ret; -} - -static int adis16240_self_test(struct iio_dev *indio_dev) -{ - int ret; - ret = adis16240_spi_write_reg_16(indio_dev, - ADIS16240_MSC_CTRL, - ADIS16240_MSC_CTRL_SELF_TEST_EN); - if (ret) { - dev_err(&indio_dev->dev, "problem starting self test"); - goto err_ret; - } - - msleep(ADIS16240_STARTUP_DELAY); - - adis16240_check_status(indio_dev); - -err_ret: - return ret; -} - -static int adis16240_check_status(struct iio_dev *indio_dev) -{ - u16 status; - int ret; - struct device *dev = &indio_dev->dev; - - ret = adis16240_spi_read_reg_16(indio_dev, - ADIS16240_DIAG_STAT, &status); - - if (ret < 0) { - dev_err(dev, "Reading status failed\n"); - goto error_ret; - } - - ret = status & 0x2F; - if (status & ADIS16240_DIAG_STAT_PWRON_FAIL) - dev_err(dev, "Power-on, self-test fail\n"); - if (status & ADIS16240_DIAG_STAT_SPI_FAIL) - dev_err(dev, "SPI failure\n"); - if (status & ADIS16240_DIAG_STAT_FLASH_UPT) - dev_err(dev, "Flash update failed\n"); - if (status & ADIS16240_DIAG_STAT_POWER_HIGH) - dev_err(dev, "Power supply above 3.625V\n"); - if (status & ADIS16240_DIAG_STAT_POWER_LOW) - dev_err(dev, "Power supply below 2.225V\n"); - -error_ret: - return ret; -} - -static int adis16240_initial_setup(struct iio_dev *indio_dev) -{ - int ret; - struct device *dev = &indio_dev->dev; - - /* Disable IRQ */ - ret = adis16240_set_irq(indio_dev, false); - if (ret) { - dev_err(dev, "disable irq failed"); - goto err_ret; - } - - /* Do self test */ - ret = adis16240_self_test(indio_dev); - if (ret) { - dev_err(dev, "self test failure"); - goto err_ret; - } - - /* Read status register to check the result */ - ret = adis16240_check_status(indio_dev); - if (ret) { - adis16240_reset(indio_dev); - dev_err(dev, "device not playing ball -> reset"); - msleep(ADIS16240_STARTUP_DELAY); - ret = adis16240_check_status(indio_dev); - if (ret) { - dev_err(dev, "giving up"); - goto err_ret; - } - } - -err_ret: - return ret; -} - static IIO_DEVICE_ATTR(in_accel_xyz_squared_peak_raw, S_IRUGO, adis16240_read_12bit_signed, NULL, ADIS16240_XYZPEAK_OUT); -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16240_write_reset, 0); - static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("4096"); -enum adis16240_chan { - in_supply, - in_aux, - accel_x, - accel_y, - accel_z, - temp, -}; - -static const u8 adis16240_addresses[6][3] = { - [in_supply] = { ADIS16240_SUPPLY_OUT }, - [in_aux] = { ADIS16240_AUX_ADC }, - [accel_x] = { ADIS16240_XACCL_OUT, ADIS16240_XACCL_OFF, - ADIS16240_XPEAK_OUT }, - [accel_y] = { ADIS16240_YACCL_OUT, ADIS16240_YACCL_OFF, - ADIS16240_YPEAK_OUT }, - [accel_z] = { ADIS16240_ZACCL_OUT, ADIS16240_ZACCL_OFF, - ADIS16240_ZPEAK_OUT }, - [temp] = { ADIS16240_TEMP_OUT }, +static const u8 adis16240_addresses[][2] = { + [ADIS16240_SCAN_ACC_X] = { ADIS16240_XACCL_OFF, ADIS16240_XPEAK_OUT }, + [ADIS16240_SCAN_ACC_Y] = { ADIS16240_YACCL_OFF, ADIS16240_YPEAK_OUT }, + [ADIS16240_SCAN_ACC_Z] = { ADIS16240_ZACCL_OFF, ADIS16240_ZPEAK_OUT }, }; static int adis16240_read_raw(struct iio_dev *indio_dev, @@ -359,69 +82,50 @@ static int adis16240_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { + struct adis *st = iio_priv(indio_dev); int ret; int bits; u8 addr; s16 val16; switch (mask) { - case 0: - mutex_lock(&indio_dev->mlock); - addr = adis16240_addresses[chan->address][0]; - ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16); - if (ret) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - - if (val16 & ADIS16240_ERROR_ACTIVE) { - ret = adis16240_check_status(indio_dev); - if (ret) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - } - val16 = val16 & ((1 << chan->scan_type.realbits) - 1); - if (chan->scan_type.sign == 's') - val16 = (s16)(val16 << - (16 - chan->scan_type.realbits)) >> - (16 - chan->scan_type.realbits); - *val = val16; - mutex_unlock(&indio_dev->mlock); - return IIO_VAL_INT; + case IIO_CHAN_INFO_RAW: + return adis_single_conversion(indio_dev, chan, + ADIS16240_ERROR_ACTIVE, val); case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: - *val = 0; - if (chan->channel == 0) - *val2 = 4880; - else + if (chan->channel == 0) { + *val = 4; + *val2 = 880000; /* 4.88 mV */ + return IIO_VAL_INT_PLUS_MICRO; + } else { return -EINVAL; - return IIO_VAL_INT_PLUS_MICRO; + } case IIO_TEMP: - *val = 0; - *val2 = 244000; + *val = 244; /* 0.244 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: *val = 0; - *val2 = 504062; + *val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */ return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } break; case IIO_CHAN_INFO_PEAK_SCALE: - *val = 6; - *val2 = 629295; + *val = 0; + *val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */ return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_OFFSET: - *val = 25; + *val = 25000 / 244 - 0x133; /* 25 C = 0x133 */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: bits = 10; mutex_lock(&indio_dev->mlock); - addr = adis16240_addresses[chan->address][1]; - ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16); + addr = adis16240_addresses[chan->scan_index][0]; + ret = adis_read_reg_16(st, addr, &val16); if (ret) { mutex_unlock(&indio_dev->mlock); return ret; @@ -434,8 +138,8 @@ static int adis16240_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_PEAK: bits = 10; mutex_lock(&indio_dev->mlock); - addr = adis16240_addresses[chan->address][2]; - ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16); + addr = adis16240_addresses[chan->scan_index][1]; + ret = adis_read_reg_16(st, addr, &val16); if (ret) { mutex_unlock(&indio_dev->mlock); return ret; @@ -455,53 +159,35 @@ static int adis16240_write_raw(struct iio_dev *indio_dev, int val2, long mask) { + struct adis *st = iio_priv(indio_dev); int bits = 10; s16 val16; u8 addr; switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: val16 = val & ((1 << bits) - 1); - addr = adis16240_addresses[chan->address][1]; - return adis16240_spi_write_reg_16(indio_dev, addr, val16); + addr = adis16240_addresses[chan->scan_index][0]; + return adis_write_reg_16(st, addr, val16); } return -EINVAL; } -static struct iio_chan_spec adis16240_channels[] = { - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - in_supply, ADIS16240_SCAN_SUPPLY, - IIO_ST('u', 10, 16, 0), 0), - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, - 0, - in_aux, ADIS16240_SCAN_AUX_ADC, - IIO_ST('u', 10, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, - accel_x, ADIS16240_SCAN_ACC_X, - IIO_ST('s', 10, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, - accel_y, ADIS16240_SCAN_ACC_Y, - IIO_ST('s', 10, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z, - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, - accel_z, ADIS16240_SCAN_ACC_Z, - IIO_ST('s', 10, 16, 0), 0), - IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - temp, ADIS16240_SCAN_TEMP, - IIO_ST('u', 10, 16, 0), 0), +static const struct iio_chan_spec adis16240_channels[] = { + ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 10), + ADIS_AUX_ADC_CHAN(ADIS16240_AUX_ADC, ADIS16240_SCAN_AUX_ADC, 10), + ADIS_ACCEL_CHAN(X, ADIS16240_XACCL_OUT, ADIS16240_SCAN_ACC_X, + BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10), + ADIS_ACCEL_CHAN(Y, ADIS16240_YACCL_OUT, ADIS16240_SCAN_ACC_Y, + BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10), + ADIS_ACCEL_CHAN(Z, ADIS16240_ZACCL_OUT, ADIS16240_SCAN_ACC_Z, + BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10), + ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 10), IIO_CHAN_SOFT_TIMESTAMP(6) }; static struct attribute *adis16240_attributes[] = { &iio_dev_attr_in_accel_xyz_squared_peak_raw.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_reset.dev_attr.attr, NULL }; @@ -513,28 +199,50 @@ static const struct iio_info adis16240_info = { .attrs = &adis16240_attribute_group, .read_raw = &adis16240_read_raw, .write_raw = &adis16240_write_raw, + .update_scan_mode = adis_update_scan_mode, .driver_module = THIS_MODULE, }; -static int __devinit adis16240_probe(struct spi_device *spi) +static const char * const adis16240_status_error_msgs[] = { + [ADIS16240_DIAG_STAT_PWRON_FAIL_BIT] = "Power on, self-test failed", + [ADIS16240_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure", + [ADIS16240_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed", + [ADIS16240_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V", + [ADIS16240_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.225V", +}; + +static const struct adis_data adis16240_data = { + .write_delay = 35, + .read_delay = 35, + .msc_ctrl_reg = ADIS16240_MSC_CTRL, + .glob_cmd_reg = ADIS16240_GLOB_CMD, + .diag_stat_reg = ADIS16240_DIAG_STAT, + + .self_test_mask = ADIS16240_MSC_CTRL_SELF_TEST_EN, + .startup_delay = ADIS16240_STARTUP_DELAY, + + .status_error_msgs = adis16240_status_error_msgs, + .status_error_mask = BIT(ADIS16240_DIAG_STAT_PWRON_FAIL_BIT) | + BIT(ADIS16240_DIAG_STAT_SPI_FAIL_BIT) | + BIT(ADIS16240_DIAG_STAT_FLASH_UPT_BIT) | + BIT(ADIS16240_DIAG_STAT_POWER_HIGH_BIT) | + BIT(ADIS16240_DIAG_STAT_POWER_LOW_BIT), +}; + +static int adis16240_probe(struct spi_device *spi) { int ret; - struct adis16240_state *st; + struct adis *st; struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; st = iio_priv(indio_dev); /* this is only used for removal purposes */ spi_set_drvdata(spi, indio_dev); - st->us = spi; - mutex_init(&st->buf_lock); - indio_dev->name = spi->dev.driver->name; indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16240_info; @@ -542,57 +250,34 @@ static int __devinit adis16240_probe(struct spi_device *spi) indio_dev->num_channels = ARRAY_SIZE(adis16240_channels); indio_dev->modes = INDIO_DIRECT_MODE; - ret = adis16240_configure_ring(indio_dev); + ret = adis_init(st, indio_dev, spi, &adis16240_data); if (ret) - goto error_free_dev; - - ret = iio_buffer_register(indio_dev, - adis16240_channels, - ARRAY_SIZE(adis16240_channels)); - if (ret) { - printk(KERN_ERR "failed to initialize the ring\n"); - goto error_unreg_ring_funcs; - } - - if (spi->irq) { - ret = adis16240_probe_trigger(indio_dev); - if (ret) - goto error_uninitialize_ring; - } + return ret; + ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL); + if (ret) + return ret; /* Get the device into a sane initial state */ - ret = adis16240_initial_setup(indio_dev); + ret = adis_initial_startup(st); if (ret) - goto error_remove_trigger; + goto error_cleanup_buffer_trigger; ret = iio_device_register(indio_dev); if (ret) - goto error_remove_trigger; + goto error_cleanup_buffer_trigger; return 0; -error_remove_trigger: - adis16240_remove_trigger(indio_dev); -error_uninitialize_ring: - iio_buffer_unregister(indio_dev); -error_unreg_ring_funcs: - adis16240_unconfigure_ring(indio_dev); -error_free_dev: - iio_free_device(indio_dev); -error_ret: +error_cleanup_buffer_trigger: + adis_cleanup_buffer_and_trigger(st, indio_dev); return ret; } static int adis16240_remove(struct spi_device *spi) { - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - flush_scheduled_work(); + struct adis *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - adis16240_remove_trigger(indio_dev); - iio_buffer_unregister(indio_dev); - adis16240_unconfigure_ring(indio_dev); - iio_free_device(indio_dev); + adis_cleanup_buffer_and_trigger(st, indio_dev); return 0; } @@ -603,7 +288,7 @@ static struct spi_driver adis16240_driver = { .owner = THIS_MODULE, }, .probe = adis16240_probe, - .remove = __devexit_p(adis16240_remove), + .remove = adis16240_remove, }; module_spi_driver(adis16240_driver); diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c deleted file mode 100644 index e23622d96f9..00000000000 --- a/drivers/staging/iio/accel/adis16240_ring.c +++ /dev/null @@ -1,136 +0,0 @@ -#include <linux/export.h> -#include <linux/interrupt.h> -#include <linux/mutex.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> - -#include "../iio.h" -#include "../ring_sw.h" -#include "../trigger_consumer.h" -#include "adis16240.h" - -/** - * adis16240_read_ring_data() read data registers which will be placed into ring - * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @rx: somewhere to pass back the value read - **/ -static int adis16240_read_ring_data(struct device *dev, u8 *rx) -{ - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16240_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[ADIS16240_OUTPUTS + 1]; - int ret; - int i; - - mutex_lock(&st->buf_lock); - - spi_message_init(&msg); - - memset(xfers, 0, sizeof(xfers)); - for (i = 0; i <= ADIS16240_OUTPUTS; i++) { - xfers[i].bits_per_word = 8; - xfers[i].cs_change = 1; - xfers[i].len = 2; - xfers[i].delay_usecs = 30; - xfers[i].tx_buf = st->tx + 2 * i; - st->tx[2 * i] - = ADIS16240_READ_REG(ADIS16240_SUPPLY_OUT + 2 * i); - st->tx[2 * i + 1] = 0; - if (i >= 1) - xfers[i].rx_buf = rx + 2 * (i - 1); - spi_message_add_tail(&xfers[i], &msg); - } - - ret = spi_sync(st->us, &msg); - if (ret) - dev_err(&st->us->dev, "problem when burst reading"); - - mutex_unlock(&st->buf_lock); - - return ret; -} - -static irqreturn_t adis16240_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct adis16240_state *st = iio_priv(indio_dev); - struct iio_buffer *ring = indio_dev->buffer; - - int i = 0; - s16 *data; - size_t datasize = ring->access->get_bytes_per_datum(ring); - - data = kmalloc(datasize, GFP_KERNEL); - if (data == NULL) { - dev_err(&st->us->dev, "memory alloc failed in ring bh"); - return -ENOMEM; - } - - if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) && - adis16240_read_ring_data(&indio_dev->dev, st->rx) >= 0) - for (; i < bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength); i++) - data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2])); - - /* Guaranteed to be aligned with 8 byte boundary */ - if (ring->scan_timestamp) - *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - - ring->access->store_to(ring, (u8 *)data, pf->timestamp); - - iio_trigger_notify_done(indio_dev->trig); - kfree(data); - - return IRQ_HANDLED; -} - -void adis16240_unconfigure_ring(struct iio_dev *indio_dev) -{ - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->buffer); -} - -static const struct iio_buffer_setup_ops adis16240_ring_setup_ops = { - .preenable = &iio_sw_buffer_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, -}; - -int adis16240_configure_ring(struct iio_dev *indio_dev) -{ - int ret = 0; - struct iio_buffer *ring; - - ring = iio_sw_rb_allocate(indio_dev); - if (!ring) { - ret = -ENOMEM; - return ret; - } - indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ - ring->access = &ring_sw_access_funcs; - ring->scan_timestamp = true; - indio_dev->setup_ops = &adis16240_ring_setup_ops; - - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, - &adis16240_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "%s_consumer%d", - indio_dev->name, - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_iio_sw_rb_free; - } - - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_iio_sw_rb_free: - iio_sw_rb_free(indio_dev->buffer); - return ret; -} diff --git a/drivers/staging/iio/accel/adis16240_trigger.c b/drivers/staging/iio/accel/adis16240_trigger.c deleted file mode 100644 index 8e0ce568e64..00000000000 --- a/drivers/staging/iio/accel/adis16240_trigger.c +++ /dev/null @@ -1,82 +0,0 @@ -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/export.h> - -#include "../iio.h" -#include "../trigger.h" -#include "adis16240.h" - -/** - * adis16240_data_rdy_trig_poll() the event handler for the data rdy trig - **/ -static irqreturn_t adis16240_data_rdy_trig_poll(int irq, void *trig) -{ - iio_trigger_poll(trig, iio_get_time_ns()); - return IRQ_HANDLED; -} - -/** - * adis16240_data_rdy_trigger_set_state() set datardy interrupt state - **/ -static int adis16240_data_rdy_trigger_set_state(struct iio_trigger *trig, - bool state) -{ - struct iio_dev *indio_dev = trig->private_data; - - dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); - return adis16240_set_irq(indio_dev, state); -} - -static const struct iio_trigger_ops adis16240_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &adis16240_data_rdy_trigger_set_state, -}; - -int adis16240_probe_trigger(struct iio_dev *indio_dev) -{ - int ret; - struct adis16240_state *st = iio_priv(indio_dev); - - st->trig = iio_allocate_trigger("adis16240-dev%d", indio_dev->id); - if (st->trig == NULL) { - ret = -ENOMEM; - goto error_ret; - } - - ret = request_irq(st->us->irq, - adis16240_data_rdy_trig_poll, - IRQF_TRIGGER_RISING, - "adis16240", - st->trig); - if (ret) - goto error_free_trig; - - st->trig->dev.parent = &st->us->dev; - st->trig->ops = &adis16240_trigger_ops; - st->trig->private_data = indio_dev; - ret = iio_trigger_register(st->trig); - - /* select default trigger */ - indio_dev->trig = st->trig; - if (ret) - goto error_free_irq; - - return 0; - -error_free_irq: - free_irq(st->us->irq, st->trig); -error_free_trig: - iio_free_trigger(st->trig); -error_ret: - return ret; -} - -void adis16240_remove_trigger(struct iio_dev *indio_dev) -{ - struct adis16240_state *st = iio_priv(indio_dev); - - iio_trigger_unregister(st->trig); - free_irq(st->us->irq, st->trig); - iio_free_trigger(st->trig); -} diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c deleted file mode 100644 index d13d7215ff6..00000000000 --- a/drivers/staging/iio/accel/kxsd9.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * kxsd9.c simple support for the Kionix KXSD9 3D - * accelerometer. - * - * Copyright (c) 2008-2009 Jonathan Cameron <jic23@cam.ac.uk> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * The i2c interface is very similar, so shouldn't be a problem once - * I have a suitable wire made up. - * - * TODO: Support the motion detector - * Uses register address incrementing so could have a - * heavily optimized ring buffer access function. - */ - -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/sysfs.h> -#include <linux/slab.h> -#include <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" - -#define KXSD9_REG_X 0x00 -#define KXSD9_REG_Y 0x02 -#define KXSD9_REG_Z 0x04 -#define KXSD9_REG_AUX 0x06 -#define KXSD9_REG_RESET 0x0a -#define KXSD9_REG_CTRL_C 0x0c - -#define KXSD9_FS_MASK 0x03 - -#define KXSD9_REG_CTRL_B 0x0d -#define KXSD9_REG_CTRL_A 0x0e - -#define KXSD9_READ(a) (0x80 | (a)) -#define KXSD9_WRITE(a) (a) - -#define KXSD9_STATE_RX_SIZE 2 -#define KXSD9_STATE_TX_SIZE 2 -/** - * struct kxsd9_state - device related storage - * @buf_lock: protect the rx and tx buffers. - * @us: spi device - * @rx: single rx buffer storage - * @tx: single tx buffer storage - **/ -struct kxsd9_state { - struct mutex buf_lock; - struct spi_device *us; - u8 rx[KXSD9_STATE_RX_SIZE] ____cacheline_aligned; - u8 tx[KXSD9_STATE_TX_SIZE]; -}; - -#define KXSD9_SCALE_2G "0.011978" -#define KXSD9_SCALE_4G "0.023927" -#define KXSD9_SCALE_6G "0.035934" -#define KXSD9_SCALE_8G "0.047853" - -/* reverse order */ -static const int kxsd9_micro_scales[4] = { 47853, 35934, 23927, 11978 }; - -static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro) -{ - int ret, i; - struct kxsd9_state *st = iio_priv(indio_dev); - bool foundit = false; - - for (i = 0; i < 4; i++) - if (micro == kxsd9_micro_scales[i]) { - foundit = true; - break; - } - if (!foundit) - return -EINVAL; - - mutex_lock(&st->buf_lock); - ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C)); - if (ret) - goto error_ret; - st->tx[0] = KXSD9_WRITE(KXSD9_REG_CTRL_C); - st->tx[1] = (ret & ~KXSD9_FS_MASK) | i; - - ret = spi_write(st->us, st->tx, 2); -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -static int kxsd9_read(struct iio_dev *indio_dev, u8 address) -{ - struct spi_message msg; - int ret; - struct kxsd9_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[] = { - { - .bits_per_word = 8, - .len = 1, - .delay_usecs = 200, - .tx_buf = st->tx, - }, { - .bits_per_word = 8, - .len = 2, - .rx_buf = st->rx, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = KXSD9_READ(address); - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - if (ret) - return ret; - return (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0); -} - -static IIO_CONST_ATTR(accel_scale_available, - KXSD9_SCALE_2G " " - KXSD9_SCALE_4G " " - KXSD9_SCALE_6G " " - KXSD9_SCALE_8G); - -static struct attribute *kxsd9_attributes[] = { - &iio_const_attr_accel_scale_available.dev_attr.attr, - NULL, -}; - -static int kxsd9_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - int ret = -EINVAL; - - if (mask == IIO_CHAN_INFO_SCALE) { - /* Check no integer component */ - if (val) - return -EINVAL; - ret = kxsd9_write_scale(indio_dev, val2); - } - - return ret; -} - -static int kxsd9_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, long mask) -{ - int ret = -EINVAL; - struct kxsd9_state *st = iio_priv(indio_dev); - - switch (mask) { - case 0: - ret = kxsd9_read(indio_dev, chan->address); - if (ret < 0) - goto error_ret; - *val = ret; - break; - case IIO_CHAN_INFO_SCALE: - ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C)); - if (ret) - goto error_ret; - *val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK]; - ret = IIO_VAL_INT_PLUS_MICRO; - break; - }; - -error_ret: - return ret; -}; -#define KXSD9_ACCEL_CHAN(axis) \ - { \ - .type = IIO_ACCEL, \ - .modified = 1, \ - .channel2 = IIO_MOD_##axis, \ - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ - .address = KXSD9_REG_##axis, \ - } - -static struct iio_chan_spec kxsd9_channels[] = { - KXSD9_ACCEL_CHAN(X), KXSD9_ACCEL_CHAN(Y), KXSD9_ACCEL_CHAN(Z), - { - .type = IIO_VOLTAGE, - .indexed = 1, - .address = KXSD9_REG_AUX, - } -}; - -static const struct attribute_group kxsd9_attribute_group = { - .attrs = kxsd9_attributes, -}; - -static int __devinit kxsd9_power_up(struct kxsd9_state *st) -{ - int ret; - - st->tx[0] = 0x0d; - st->tx[1] = 0x40; - ret = spi_write(st->us, st->tx, 2); - if (ret) - return ret; - - st->tx[0] = 0x0c; - st->tx[1] = 0x9b; - return spi_write(st->us, st->tx, 2); -}; - -static const struct iio_info kxsd9_info = { - .read_raw = &kxsd9_read_raw, - .write_raw = &kxsd9_write_raw, - .attrs = &kxsd9_attribute_group, - .driver_module = THIS_MODULE, -}; - -static int __devinit kxsd9_probe(struct spi_device *spi) -{ - struct iio_dev *indio_dev; - struct kxsd9_state *st; - int ret = 0; - - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - st = iio_priv(indio_dev); - spi_set_drvdata(spi, indio_dev); - - st->us = spi; - mutex_init(&st->buf_lock); - indio_dev->channels = kxsd9_channels; - indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels); - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &kxsd9_info; - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - - spi->mode = SPI_MODE_0; - spi_setup(spi); - kxsd9_power_up(st); - - return 0; - -error_free_dev: - iio_free_device(indio_dev); -error_ret: - return ret; -} - -static int __devexit kxsd9_remove(struct spi_device *spi) -{ - iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); - - return 0; -} - -static const struct spi_device_id kxsd9_id[] = { - {"kxsd9", 0}, - { }, -}; -MODULE_DEVICE_TABLE(spi, kxsd9_id); - -static struct spi_driver kxsd9_driver = { - .driver = { - .name = "kxsd9", - .owner = THIS_MODULE, - }, - .probe = kxsd9_probe, - .remove = __devexit_p(kxsd9_remove), - .id_table = kxsd9_id, -}; -module_spi_driver(kxsd9_driver); - -MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); -MODULE_DESCRIPTION("Kionix KXSD9 SPI driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/accel/lis3l02dq.h b/drivers/staging/iio/accel/lis3l02dq.h index 2db383fc274..0a8ea827086 100644 --- a/drivers/staging/iio/accel/lis3l02dq.h +++ b/drivers/staging/iio/accel/lis3l02dq.h @@ -2,7 +2,7 @@ * LISL02DQ.h -- support STMicroelectronics LISD02DQ * 3d 2g Linear Accelerometers via SPI * - * Copyright (c) 2007 Jonathan Cameron <jic23@cam.ac.uk> + * Copyright (c) 2007 Jonathan Cameron <jic23@kernel.org> * * Loosely based upon tle62x0.c * @@ -28,7 +28,7 @@ /* Control Register (1 of 2) */ #define LIS3L02DQ_REG_CTRL_1_ADDR 0x20 /* Power ctrl - either bit set corresponds to on*/ -#define LIS3L02DQ_REG_CTRL_1_PD_ON 0xC0 +#define LIS3L02DQ_REG_CTRL_1_PD_ON 0xC0 /* Decimation Factor */ #define LIS3L02DQ_DEC_MASK 0x30 @@ -73,14 +73,14 @@ /* Interrupt related stuff */ #define LIS3L02DQ_REG_WAKE_UP_CFG_ADDR 0x23 -/* Switch from or combination fo conditions to and */ +/* Switch from or combination of conditions to and */ #define LIS3L02DQ_REG_WAKE_UP_CFG_BOOLEAN_AND 0x80 /* Latch interrupt request, * if on ack must be given by reading the ack register */ #define LIS3L02DQ_REG_WAKE_UP_CFG_LATCH_SRC 0x40 -/* Z Interrupt on High (above threshold)*/ +/* Z Interrupt on High (above threshold) */ #define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_HIGH 0x20 /* Z Interrupt on Low */ #define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_LOW 0x10 @@ -117,13 +117,13 @@ #define LIS3L02DQ_REG_STATUS_Y_OVERRUN 0x20 #define LIS3L02DQ_REG_STATUS_X_OVERRUN 0x10 /* XYZ new data available - first is all 3 available? */ -#define LIS3L02DQ_REG_STATUS_XYZ_NEW_DATA 0x08 +#define LIS3L02DQ_REG_STATUS_XYZ_NEW_DATA 0x08 #define LIS3L02DQ_REG_STATUS_Z_NEW_DATA 0x04 #define LIS3L02DQ_REG_STATUS_Y_NEW_DATA 0x02 #define LIS3L02DQ_REG_STATUS_X_NEW_DATA 0x01 /* The accelerometer readings - low and high bytes. -Form of high byte dependent on justification set in ctrl reg */ + * Form of high byte dependent on justification set in ctrl reg */ #define LIS3L02DQ_REG_OUT_X_L_ADDR 0x28 #define LIS3L02DQ_REG_OUT_X_H_ADDR 0x29 #define LIS3L02DQ_REG_OUT_Y_L_ADDR 0x2A @@ -150,14 +150,15 @@ Form of high byte dependent on justification set in ctrl reg */ * struct lis3l02dq_state - device instance specific data * @us: actual spi_device * @trig: data ready trigger registered with iio + * @buf_lock: mutex to protect tx and rx * @tx: transmit buffer * @rx: receive buffer - * @buf_lock: mutex to protect tx and rx **/ struct lis3l02dq_state { struct spi_device *us; struct iio_trigger *trig; struct mutex buf_lock; + int gpio; bool trigger_on; u8 tx[LIS3L02DQ_MAX_RX] ____cacheline_aligned; @@ -184,16 +185,6 @@ int lis3l02dq_probe_trigger(struct iio_dev *indio_dev); int lis3l02dq_configure_buffer(struct iio_dev *indio_dev); void lis3l02dq_unconfigure_buffer(struct iio_dev *indio_dev); -#ifdef CONFIG_LIS3L02DQ_BUF_RING_SW -#define lis3l02dq_free_buf iio_sw_rb_free -#define lis3l02dq_alloc_buf iio_sw_rb_allocate -#define lis3l02dq_access_funcs ring_sw_access_funcs -#endif -#ifdef CONFIG_LIS3L02DQ_BUF_KFIFO -#define lis3l02dq_free_buf iio_kfifo_free -#define lis3l02dq_alloc_buf iio_kfifo_allocate -#define lis3l02dq_access_funcs kfifo_access_funcs -#endif irqreturn_t lis3l02dq_data_rdy_trig_poll(int irq, void *private); #define lis3l02dq_th lis3l02dq_data_rdy_trig_poll diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index 376da513796..898653c0927 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -2,7 +2,7 @@ * lis3l02dq.c support STMicroelectronics LISD02DQ * 3d 2g Linear Accelerometers via SPI * - * Copyright (c) 2007 Jonathan Cameron <jic23@cam.ac.uk> + * Copyright (c) 2007 Jonathan Cameron <jic23@kernel.org> * * 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 @@ -15,6 +15,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/gpio.h> +#include <linux/of_gpio.h> #include <linux/mutex.h> #include <linux/device.h> #include <linux/kernel.h> @@ -23,10 +24,10 @@ #include <linux/sysfs.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" -#include "../buffer.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/events.h> +#include <linux/iio/buffer.h> #include "lis3l02dq.h" @@ -52,7 +53,6 @@ int lis3l02dq_spi_read_reg_8(struct iio_dev *indio_dev, u8 reg_address, u8 *val) { struct lis3l02dq_state *st = iio_priv(indio_dev); - struct spi_message msg; int ret; struct spi_transfer xfer = { .tx_buf = st->tx, @@ -65,9 +65,7 @@ int lis3l02dq_spi_read_reg_8(struct iio_dev *indio_dev, st->tx[0] = LIS3L02DQ_READ_REG(reg_address); st->tx[1] = 0; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, &xfer, 1); *val = st->rx[1]; mutex_unlock(&st->buf_lock); @@ -108,7 +106,6 @@ static int lis3l02dq_spi_write_reg_s16(struct iio_dev *indio_dev, s16 value) { int ret; - struct spi_message msg; struct lis3l02dq_state *st = iio_priv(indio_dev); struct spi_transfer xfers[] = { { .tx_buf = st->tx, @@ -128,10 +125,7 @@ static int lis3l02dq_spi_write_reg_s16(struct iio_dev *indio_dev, st->tx[2] = LIS3L02DQ_WRITE_REG(lower_reg_address + 1); st->tx[3] = (value >> 8) & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); mutex_unlock(&st->buf_lock); return ret; @@ -142,8 +136,6 @@ static int lis3l02dq_read_reg_s16(struct iio_dev *indio_dev, int *val) { struct lis3l02dq_state *st = iio_priv(indio_dev); - - struct spi_message msg; int ret; s16 tempval; struct spi_transfer xfers[] = { { @@ -166,10 +158,7 @@ static int lis3l02dq_read_reg_s16(struct iio_dev *indio_dev, st->tx[2] = LIS3L02DQ_READ_REG(lower_reg_address + 1); st->tx[3] = 0; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 16 bit register"); goto error_ret; @@ -201,15 +190,26 @@ static u8 lis3l02dq_axis_map[3][3] = { }; static int lis3l02dq_read_thresh(struct iio_dev *indio_dev, - u64 e, - int *val) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) { - return lis3l02dq_read_reg_s16(indio_dev, LIS3L02DQ_REG_THS_L_ADDR, val); + int ret; + + ret = lis3l02dq_read_reg_s16(indio_dev, LIS3L02DQ_REG_THS_L_ADDR, val); + if (ret) + return ret; + return IIO_VAL_INT; } static int lis3l02dq_write_thresh(struct iio_dev *indio_dev, - u64 event_code, - int val) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) { u16 value = val; return lis3l02dq_spi_write_reg_s16(indio_dev, @@ -257,7 +257,7 @@ static int lis3l02dq_read_raw(struct iio_dev *indio_dev, u8 reg; switch (mask) { - case 0: + case IIO_CHAN_INFO_RAW: /* Take the iio_dev status lock */ mutex_lock(&indio_dev->mlock); if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { @@ -268,6 +268,8 @@ static int lis3l02dq_read_raw(struct iio_dev *indio_dev, ret = lis3l02dq_read_reg_s16(indio_dev, reg, val); } mutex_unlock(&indio_dev->mlock); + if (ret < 0) + goto error_ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: *val = 0; @@ -297,7 +299,7 @@ static ssize_t lis3l02dq_read_frequency(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); int ret, len = 0; s8 t; ret = lis3l02dq_spi_read_reg_8(indio_dev, @@ -328,7 +330,7 @@ static ssize_t lis3l02dq_write_frequency(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); unsigned long val; int ret; u8 t; @@ -392,7 +394,7 @@ static int lis3l02dq_initial_setup(struct iio_dev *indio_dev) dev_err(&st->us->dev, "problem with setup control register 1"); goto err_ret; } - /* Repeat as sometimes doesn't work first time?*/ + /* Repeat as sometimes doesn't work first time? */ ret = lis3l02dq_spi_write_reg_8(indio_dev, LIS3L02DQ_REG_CTRL_1_ADDR, val); @@ -512,35 +514,57 @@ static irqreturn_t lis3l02dq_event_handler(int irq, void *private) return IRQ_HANDLED; } -#define LIS3L02DQ_INFO_MASK \ - (IIO_CHAN_INFO_SCALE_SHARED_BIT | \ - IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT) - -#define LIS3L02DQ_EVENT_MASK \ - (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | \ - IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)) - -static struct iio_chan_spec lis3l02dq_channels[] = { - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, LIS3L02DQ_INFO_MASK, - 0, 0, IIO_ST('s', 12, 16, 0), LIS3L02DQ_EVENT_MASK), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, LIS3L02DQ_INFO_MASK, - 1, 1, IIO_ST('s', 12, 16, 0), LIS3L02DQ_EVENT_MASK), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z, LIS3L02DQ_INFO_MASK, - 2, 2, IIO_ST('s', 12, 16, 0), LIS3L02DQ_EVENT_MASK), +static const struct iio_event_spec lis3l02dq_event[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE), + } +}; + +#define LIS3L02DQ_CHAN(index, mod) \ + { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = mod, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_CALIBSCALE) | \ + BIT(IIO_CHAN_INFO_CALIBBIAS), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .address = index, \ + .scan_index = index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 12, \ + .storagebits = 16, \ + }, \ + .event_spec = lis3l02dq_event, \ + .num_event_specs = ARRAY_SIZE(lis3l02dq_event), \ + } + +static const struct iio_chan_spec lis3l02dq_channels[] = { + LIS3L02DQ_CHAN(0, IIO_MOD_X), + LIS3L02DQ_CHAN(1, IIO_MOD_Y), + LIS3L02DQ_CHAN(2, IIO_MOD_Z), IIO_CHAN_SOFT_TIMESTAMP(3) }; static int lis3l02dq_read_event_config(struct iio_dev *indio_dev, - u64 event_code) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) { u8 val; int ret; - u8 mask = (1 << (IIO_EVENT_CODE_EXTRACT_MODIFIER(event_code)*2 + - (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_RISING))); + u8 mask = (1 << (chan->channel2*2 + (dir == IIO_EV_DIR_RISING))); ret = lis3l02dq_spi_read_reg_8(indio_dev, LIS3L02DQ_REG_WAKE_UP_CFG_ADDR, &val); @@ -585,16 +609,16 @@ error_ret: } static int lis3l02dq_write_event_config(struct iio_dev *indio_dev, - u64 event_code, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, int state) { int ret = 0; u8 val, control; u8 currentlyset; bool changed = false; - u8 mask = (1 << (IIO_EVENT_CODE_EXTRACT_MODIFIER(event_code)*2 + - (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_RISING))); + u8 mask = (1 << (chan->channel2*2 + (dir == IIO_EV_DIR_RISING))); mutex_lock(&indio_dev->mlock); /* read current control */ @@ -660,22 +684,21 @@ static const struct iio_info lis3l02dq_info = { .attrs = &lis3l02dq_attribute_group, }; -static int __devinit lis3l02dq_probe(struct spi_device *spi) +static int lis3l02dq_probe(struct spi_device *spi) { int ret; struct lis3l02dq_state *st; struct iio_dev *indio_dev; - indio_dev = iio_allocate_device(sizeof *st); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; st = iio_priv(indio_dev); - /* this is only used tor removal purposes */ + /* this is only used for removal purposes */ spi_set_drvdata(spi, indio_dev); st->us = spi; + st->gpio = of_get_gpio(spi->dev.of_node, 0); mutex_init(&st->buf_lock); indio_dev->name = spi->dev.driver->name; indio_dev->dev.parent = &spi->dev; @@ -687,17 +710,17 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi) ret = lis3l02dq_configure_buffer(indio_dev); if (ret) - goto error_free_dev; + return ret; ret = iio_buffer_register(indio_dev, lis3l02dq_channels, ARRAY_SIZE(lis3l02dq_channels)); if (ret) { - printk(KERN_ERR "failed to initialize the buffer\n"); + dev_err(&spi->dev, "failed to initialize the buffer\n"); goto error_unreg_buffer_funcs; } - if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) { + if (spi->irq) { ret = request_threaded_irq(st->us->irq, &lis3l02dq_th, &lis3l02dq_event_handler, @@ -724,18 +747,15 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi) return 0; error_remove_trigger: - if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) + if (spi->irq) lis3l02dq_remove_trigger(indio_dev); error_free_interrupt: - if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) + if (spi->irq) free_irq(st->us->irq, indio_dev); error_uninitialize_buffer: iio_buffer_unregister(indio_dev); error_unreg_buffer_funcs: lis3l02dq_unconfigure_buffer(indio_dev); -error_free_dev: - iio_free_device(indio_dev); -error_ret: return ret; } @@ -768,30 +788,22 @@ err_ret: /* fixme, confirm ordering in this function */ static int lis3l02dq_remove(struct spi_device *spi) { - int ret; struct iio_dev *indio_dev = spi_get_drvdata(spi); struct lis3l02dq_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - ret = lis3l02dq_disable_all_events(indio_dev); - if (ret) - goto err_ret; + lis3l02dq_disable_all_events(indio_dev); + lis3l02dq_stop_device(indio_dev); - ret = lis3l02dq_stop_device(indio_dev); - if (ret) - goto err_ret; - - if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) + if (spi->irq) free_irq(st->us->irq, indio_dev); lis3l02dq_remove_trigger(indio_dev); iio_buffer_unregister(indio_dev); lis3l02dq_unconfigure_buffer(indio_dev); - iio_free_device(indio_dev); -err_ret: - return ret; + return 0; } static struct spi_driver lis3l02dq_driver = { @@ -800,11 +812,11 @@ static struct spi_driver lis3l02dq_driver = { .owner = THIS_MODULE, }, .probe = lis3l02dq_probe, - .remove = __devexit_p(lis3l02dq_remove), + .remove = lis3l02dq_remove, }; module_spi_driver(lis3l02dq_driver); -MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); +MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); MODULE_DESCRIPTION("ST LIS3L02DQ Accelerometer SPI driver"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("spi:lis3l02dq"); diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index 98c5c92d345..79cefe0a516 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -6,15 +6,14 @@ #include <linux/slab.h> #include <linux/export.h> -#include "../iio.h" -#include "../ring_sw.h" -#include "../kfifo_buf.h" -#include "../trigger.h" -#include "../trigger_consumer.h" +#include <linux/iio/iio.h> +#include <linux/iio/kfifo_buf.h> +#include <linux/iio/trigger.h> +#include <linux/iio/trigger_consumer.h> #include "lis3l02dq.h" /** - * combine_8_to_16() utility function to munge to u8s into u16 + * combine_8_to_16() utility function to munge two u8s into u16 **/ static inline u16 combine_8_to_16(u8 lower, u8 upper) { @@ -49,7 +48,7 @@ static const u8 read_all_tx_array[] = { /** * lis3l02dq_read_all() Reads all channels currently selected - * @st: device specific state + * @indio_dev: IIO device state * @rx_array: (dma capable) receive array, must be at least * 4*number of channels **/ @@ -112,7 +111,7 @@ static int lis3l02dq_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) { int ret, i; - u8 *rx_array ; + u8 *rx_array; s16 *data = (s16 *)buf; int scan_count = bitmap_weight(indio_dev->active_scan_mask, indio_dev->masklength); @@ -121,8 +120,10 @@ static int lis3l02dq_get_buffer_element(struct iio_dev *indio_dev, if (rx_array == NULL) return -ENOMEM; ret = lis3l02dq_read_all(indio_dev, rx_array); - if (ret < 0) + if (ret < 0) { + kfree(rx_array); return ret; + } for (i = 0; i < scan_count; i++) data[i] = combine_8_to_16(rx_array[i*4+1], rx_array[i*4+3]); @@ -135,58 +136,49 @@ static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; - struct iio_buffer *buffer = indio_dev->buffer; int len = 0; - size_t datasize = buffer->access->get_bytes_per_datum(buffer); - char *data = kmalloc(datasize, GFP_KERNEL); + char *data; - if (data == NULL) { - dev_err(indio_dev->dev.parent, - "memory alloc failed in buffer bh"); - return -ENOMEM; - } + data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); + if (data == NULL) + goto done; if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) len = lis3l02dq_get_buffer_element(indio_dev, data); - /* Guaranteed to be aligned with 8 byte boundary */ - if (buffer->scan_timestamp) - *(s64 *)(((phys_addr_t)data + len - + sizeof(s64) - 1) & ~(sizeof(s64) - 1)) - = pf->timestamp; - buffer->access->store_to(buffer, (u8 *)data, pf->timestamp); + iio_push_to_buffers_with_timestamp(indio_dev, data, pf->timestamp); - iio_trigger_notify_done(indio_dev->trig); kfree(data); +done: + iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; } /* Caller responsible for locking as necessary. */ static int -__lis3l02dq_write_data_ready_config(struct device *dev, bool state) +__lis3l02dq_write_data_ready_config(struct iio_dev *indio_dev, bool state) { int ret; u8 valold; bool currentlyset; - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct lis3l02dq_state *st = iio_priv(indio_dev); -/* Get the current event mask register */ + /* Get the current event mask register */ ret = lis3l02dq_spi_read_reg_8(indio_dev, LIS3L02DQ_REG_CTRL_2_ADDR, &valold); if (ret) goto error_ret; -/* Find out if data ready is already on */ + /* Find out if data ready is already on */ currentlyset = valold & LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION; -/* Disable requested */ + /* Disable requested */ if (!state && currentlyset) { - /* disable the data ready signal */ + /* Disable the data ready signal */ valold &= ~LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION; - /* The double write is to overcome a hardware bug?*/ + /* The double write is to overcome a hardware bug? */ ret = lis3l02dq_spi_write_reg_8(indio_dev, LIS3L02DQ_REG_CTRL_2_ADDR, valold); @@ -198,10 +190,10 @@ __lis3l02dq_write_data_ready_config(struct device *dev, bool state) if (ret) goto error_ret; st->trigger_on = false; -/* Enable requested */ + /* Enable requested */ } else if (state && !currentlyset) { - /* if not set, enable requested */ - /* first disable all events */ + /* If not set, enable requested + * first disable all events */ ret = lis3l02dq_disable_all_events(indio_dev); if (ret < 0) goto error_ret; @@ -232,15 +224,15 @@ error_ret: static int lis3l02dq_data_rdy_trigger_set_state(struct iio_trigger *trig, bool state) { - struct iio_dev *indio_dev = trig->private_data; + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); int ret = 0; u8 t; - __lis3l02dq_write_data_ready_config(&indio_dev->dev, state); - if (state == false) { + __lis3l02dq_write_data_ready_config(indio_dev, state); + if (!state) { /* - * A possible quirk with teh handler is currently worked around - * by ensuring outstanding read events are cleared. + * A possible quirk with the handler is currently worked around + * by ensuring outstanding read events are cleared. */ ret = lis3l02dq_read_all(indio_dev, NULL); } @@ -251,25 +243,24 @@ static int lis3l02dq_data_rdy_trigger_set_state(struct iio_trigger *trig, } /** - * lis3l02dq_trig_try_reen() try renabling irq for data rdy trigger + * lis3l02dq_trig_try_reen() try reenabling irq for data rdy trigger * @trig: the datardy trigger */ static int lis3l02dq_trig_try_reen(struct iio_trigger *trig) { - struct iio_dev *indio_dev = trig->private_data; + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); struct lis3l02dq_state *st = iio_priv(indio_dev); int i; - /* If gpio still high (or high again) */ - /* In theory possible we will need to do this several times */ + /* If gpio still high (or high again) + * In theory possible we will need to do this several times */ for (i = 0; i < 5; i++) - if (gpio_get_value(irq_to_gpio(st->us->irq))) + if (gpio_get_value(st->gpio)) lis3l02dq_read_all(indio_dev, NULL); else break; if (i == 5) - printk(KERN_INFO - "Failed to clear the interrupt for lis3l02dq\n"); + pr_info("Failed to clear the interrupt for lis3l02dq\n"); /* irq reenabled so success! */ return 0; @@ -286,7 +277,7 @@ int lis3l02dq_probe_trigger(struct iio_dev *indio_dev) int ret; struct lis3l02dq_state *st = iio_priv(indio_dev); - st->trig = iio_allocate_trigger("lis3l02dq-dev%d", indio_dev->id); + st->trig = iio_trigger_alloc("lis3l02dq-dev%d", indio_dev->id); if (!st->trig) { ret = -ENOMEM; goto error_ret; @@ -294,7 +285,7 @@ int lis3l02dq_probe_trigger(struct iio_dev *indio_dev) st->trig->dev.parent = &st->us->dev; st->trig->ops = &lis3l02dq_trigger_ops; - st->trig->private_data = indio_dev; + iio_trigger_set_drvdata(st->trig, indio_dev); ret = iio_trigger_register(st->trig); if (ret) goto error_free_trig; @@ -302,7 +293,7 @@ int lis3l02dq_probe_trigger(struct iio_dev *indio_dev) return 0; error_free_trig: - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); error_ret: return ret; } @@ -312,13 +303,13 @@ void lis3l02dq_remove_trigger(struct iio_dev *indio_dev) struct lis3l02dq_state *st = iio_priv(indio_dev); iio_trigger_unregister(st->trig); - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); } void lis3l02dq_unconfigure_buffer(struct iio_dev *indio_dev) { iio_dealloc_pollfunc(indio_dev->pollfunc); - lis3l02dq_free_buf(indio_dev->buffer); + iio_kfifo_free(indio_dev->buffer); } static int lis3l02dq_buffer_postenable(struct iio_dev *indio_dev) @@ -391,7 +382,6 @@ error_ret: } static const struct iio_buffer_setup_ops lis3l02dq_buffer_setup_ops = { - .preenable = &iio_sw_buffer_preenable, .postenable = &lis3l02dq_buffer_postenable, .predisable = &lis3l02dq_buffer_predisable, }; @@ -401,13 +391,11 @@ int lis3l02dq_configure_buffer(struct iio_dev *indio_dev) int ret; struct iio_buffer *buffer; - buffer = lis3l02dq_alloc_buf(indio_dev); + buffer = iio_kfifo_allocate(indio_dev); if (!buffer) return -ENOMEM; - indio_dev->buffer = buffer; - /* Effectively select the buffer implementation */ - indio_dev->buffer->access = &lis3l02dq_access_funcs; + iio_device_attach_buffer(indio_dev, buffer); buffer->scan_timestamp = true; indio_dev->setup_ops = &lis3l02dq_buffer_setup_ops; @@ -429,6 +417,6 @@ int lis3l02dq_configure_buffer(struct iio_dev *indio_dev) return 0; error_iio_sw_rb_free: - lis3l02dq_free_buf(indio_dev->buffer); + iio_kfifo_free(indio_dev->buffer); return ret; } diff --git a/drivers/staging/iio/accel/sca3000.h b/drivers/staging/iio/accel/sca3000.h index ad38dd955cd..b284e5a6cac 100644 --- a/drivers/staging/iio/accel/sca3000.h +++ b/drivers/staging/iio/accel/sca3000.h @@ -2,7 +2,7 @@ * sca3000.c -- support VTI sca3000 series accelerometers * via SPI * - * Copyright (c) 2007 Jonathan Cameron <jic23@cam.ac.uk> + * Copyright (c) 2007 Jonathan Cameron <jic23@kernel.org> * * Partly based upon tle62x0.c * @@ -65,7 +65,8 @@ #define SCA3000_RING_BUF_ENABLE 0x80 #define SCA3000_RING_BUF_8BIT 0x40 -/* Free fall detection triggers an interrupt if the acceleration +/* + * Free fall detection triggers an interrupt if the acceleration * is below a threshold for equivalent of 25cm drop */ #define SCA3000_FREE_FALL_DETECT 0x10 @@ -73,8 +74,9 @@ #define SCA3000_MEAS_MODE_OP_1 0x01 #define SCA3000_MEAS_MODE_OP_2 0x02 -/* In motion detection mode the accelerations are band pass filtered - * (aprox 1 - 25Hz) and then a programmable threshold used to trigger +/* + * In motion detection mode the accelerations are band pass filtered + * (approx 1 - 25Hz) and then a programmable threshold used to trigger * and interrupt. */ #define SCA3000_MEAS_MODE_MOT_DET 0x03 @@ -99,8 +101,10 @@ #define SCA3000_REG_CTRL_SEL_MD_Y_TH 0x03 #define SCA3000_REG_CTRL_SEL_MD_X_TH 0x04 #define SCA3000_REG_CTRL_SEL_MD_Z_TH 0x05 -/* BE VERY CAREFUL WITH THIS, IF 3 BITS ARE NOT SET the device - will not function */ +/* + * BE VERY CAREFUL WITH THIS, IF 3 BITS ARE NOT SET the device + * will not function + */ #define SCA3000_REG_CTRL_SEL_OUT_CTRL 0x0B #define SCA3000_OUT_CTRL_PROT_MASK 0xE0 #define SCA3000_OUT_CTRL_BUF_X_EN 0x10 @@ -109,8 +113,9 @@ #define SCA3000_OUT_CTRL_BUF_DIV_4 0x02 #define SCA3000_OUT_CTRL_BUF_DIV_2 0x01 -/* Control which motion detector interrupts are on. - * For now only OR combinations are supported.x +/* + * Control which motion detector interrupts are on. + * For now only OR combinations are supported. */ #define SCA3000_MD_CTRL_PROT_MASK 0xC0 #define SCA3000_MD_CTRL_OR_Y 0x01 @@ -121,7 +126,8 @@ #define SCA3000_MD_CTRL_AND_X 0x10 #define SAC3000_MD_CTRL_AND_Z 0x20 -/* Some control registers of complex access methods requiring this register to +/* + * Some control registers of complex access methods requiring this register to * be used to remove a lock. */ #define SCA3000_REG_ADDR_UNLOCK 0x1e @@ -136,10 +142,11 @@ #define SCA3000_INT_MASK_ACTIVE_HIGH 0x01 #define SCA3000_INT_MASK_ACTIVE_LOW 0x00 -/* Values of mulipexed registers (write to ctrl_data after select) */ +/* Values of multiplexed registers (write to ctrl_data after select) */ #define SCA3000_REG_ADDR_CTRL_DATA 0x22 -/* Measurement modes available on some sca3000 series chips. Code assumes others +/* + * Measurement modes available on some sca3000 series chips. Code assumes others * may become available in the future. * * Bypass - Bypass the low-pass filter in the signal channel so as to increase @@ -160,7 +167,6 @@ * struct sca3000_state - device instance state information * @us: the associated spi device * @info: chip variant information - * @indio_dev: device information used by the IIO core * @interrupt_handler_ws: event interrupt handler for all events * @last_timestamp: the timestamp of the last event * @mo_det_use_count: reference counter for the motion detection unit diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index 49764fb7181..ed30e32e60d 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -5,7 +5,7 @@ * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * - * Copyright (c) 2009 Jonathan Cameron <jic23@cam.ac.uk> + * Copyright (c) 2009 Jonathan Cameron <jic23@kernel.org> * * See industrialio/accels/sca3000.h for comments. */ @@ -18,10 +18,10 @@ #include <linux/spi/spi.h> #include <linux/sysfs.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" -#include "../buffer.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/events.h> +#include <linux/iio/buffer.h> #include "sca3000.h" @@ -32,7 +32,8 @@ enum sca3000_variant { e05, }; -/* Note where option modes are not defined, the chip simply does not +/* + * Note where option modes are not defined, the chip simply does not * support any. * Other chips in the sca3000 series use i2c and are not included here. * @@ -90,7 +91,6 @@ int sca3000_read_data_short(struct sca3000_state *st, uint8_t reg_address_high, int len) { - struct spi_message msg; struct spi_transfer xfer[2] = { { .len = 1, @@ -101,11 +101,8 @@ int sca3000_read_data_short(struct sca3000_state *st, } }; st->tx[0] = SCA3000_READ_REG(reg_address_high); - spi_message_init(&msg); - spi_message_add_tail(&xfer[0], &msg); - spi_message_add_tail(&xfer[1], &msg); - return spi_sync(st->us, &msg); + return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); } /** @@ -133,7 +130,6 @@ static int sca3000_reg_lock_on(struct sca3000_state *st) **/ static int __sca3000_unlock_reg_lock(struct sca3000_state *st) { - struct spi_message msg; struct spi_transfer xfer[3] = { { .len = 2, @@ -154,12 +150,8 @@ static int __sca3000_unlock_reg_lock(struct sca3000_state *st) st->tx[3] = 0x50; st->tx[4] = SCA3000_WRITE_REG(SCA3000_REG_ADDR_UNLOCK); st->tx[5] = 0xA0; - spi_message_init(&msg); - spi_message_add_tail(&xfer[0], &msg); - spi_message_add_tail(&xfer[1], &msg); - spi_message_add_tail(&xfer[2], &msg); - return spi_sync(st->us, &msg); + return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); } /** @@ -200,7 +192,6 @@ error_ret: return ret; } -/* Crucial that lock is called before calling this */ /** * sca3000_read_ctrl_reg() read from lock protected control register. * @@ -241,7 +232,7 @@ error_ret: static int sca3000_check_status(struct device *dev) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct sca3000_state *st = iio_priv(indio_dev); mutex_lock(&st->lock); @@ -259,16 +250,15 @@ error_ret: } #endif /* SCA3000_DEBUG */ - /** - * sca3000_show_reg() - sysfs interface to read the chip revision number + * sca3000_show_rev() - sysfs interface to read the chip revision number **/ static ssize_t sca3000_show_rev(struct device *dev, struct device_attribute *attr, char *buf) { int len = 0, ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct sca3000_state *st = iio_priv(indio_dev); mutex_lock(&st->lock); @@ -296,7 +286,7 @@ sca3000_show_available_measurement_modes(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct sca3000_state *st = iio_priv(indio_dev); int len = 0; @@ -321,14 +311,14 @@ sca3000_show_available_measurement_modes(struct device *dev, } /** - * sca3000_show_measurmenet_mode() sysfs read of current mode + * sca3000_show_measurement_mode() sysfs read of current mode **/ static ssize_t sca3000_show_measurement_mode(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct sca3000_state *st = iio_priv(indio_dev); int len = 0, ret; @@ -379,7 +369,7 @@ sca3000_store_measurement_mode(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct sca3000_state *st = iio_priv(indio_dev); int ret; u8 mask = 0x03; @@ -412,7 +402,8 @@ error_ret: } -/* Not even vaguely standard attributes so defined here rather than +/* + * Not even vaguely standard attributes so defined here rather than * in the relevant IIO core headers */ static IIO_DEVICE_ATTR(measurement_mode_available, S_IRUGO, @@ -428,18 +419,47 @@ static IIO_DEVICE_ATTR(measurement_mode, S_IRUGO | S_IWUSR, static IIO_DEVICE_ATTR(revision, S_IRUGO, sca3000_show_rev, NULL, 0); -#define SCA3000_INFO_MASK \ - IIO_CHAN_INFO_SCALE_SHARED_BIT -#define SCA3000_EVENT_MASK \ - (IIO_EV_BIT(IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING)) - -static struct iio_chan_spec sca3000_channels[] = { - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, SCA3000_INFO_MASK, - 0, 0, IIO_ST('s', 11, 16, 5), SCA3000_EVENT_MASK), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, SCA3000_INFO_MASK, - 1, 1, IIO_ST('s', 11, 16, 5), SCA3000_EVENT_MASK), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z, SCA3000_INFO_MASK, - 2, 2, IIO_ST('s', 11, 16, 5), SCA3000_EVENT_MASK), +static const struct iio_event_spec sca3000_event = { + .type = IIO_EV_TYPE_MAG, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), +}; + +#define SCA3000_CHAN(index, mod) \ + { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = mod, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ + .address = index, \ + .scan_index = index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 11, \ + .storagebits = 16, \ + .shift = 5, \ + }, \ + .event_spec = &sca3000_event, \ + .num_event_specs = 1, \ + } + +static const struct iio_chan_spec sca3000_channels[] = { + SCA3000_CHAN(0, IIO_MOD_X), + SCA3000_CHAN(1, IIO_MOD_Y), + SCA3000_CHAN(2, IIO_MOD_Z), +}; + +static const struct iio_chan_spec sca3000_channels_with_temp[] = { + SCA3000_CHAN(0, IIO_MOD_X), + SCA3000_CHAN(1, IIO_MOD_Y), + SCA3000_CHAN(2, IIO_MOD_Z), + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + }, }; static u8 sca3000_addresses[3][3] = { @@ -462,21 +482,32 @@ static int sca3000_read_raw(struct iio_dev *indio_dev, u8 address; switch (mask) { - case 0: + case IIO_CHAN_INFO_RAW: mutex_lock(&st->lock); - if (st->mo_det_use_count) { - mutex_unlock(&st->lock); - return -EBUSY; - } - address = sca3000_addresses[chan->address][0]; - ret = sca3000_read_data_short(st, address, 2); - if (ret < 0) { - mutex_unlock(&st->lock); - return ret; + if (chan->type == IIO_ACCEL) { + if (st->mo_det_use_count) { + mutex_unlock(&st->lock); + return -EBUSY; + } + address = sca3000_addresses[chan->address][0]; + ret = sca3000_read_data_short(st, address, 2); + if (ret < 0) { + mutex_unlock(&st->lock); + return ret; + } + *val = (be16_to_cpup((__be16 *)st->rx) >> 3) & 0x1FFF; + *val = ((*val) << (sizeof(*val)*8 - 13)) >> + (sizeof(*val)*8 - 13); + } else { + /* get the temperature when available */ + ret = sca3000_read_data_short(st, + SCA3000_REG_ADDR_TEMP_MSB, 2); + if (ret < 0) { + mutex_unlock(&st->lock); + return ret; + } + *val = ((st->rx[0] & 0x3F) << 3) | ((st->rx[1] & 0xE0) >> 5); } - *val = (be16_to_cpup((__be16 *)st->rx) >> 3) & 0x1FFF; - *val = ((*val) << (sizeof(*val)*8 - 13)) >> - (sizeof(*val)*8 - 13); mutex_unlock(&st->lock); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: @@ -486,6 +517,10 @@ static int sca3000_read_raw(struct iio_dev *indio_dev, else /* temperature */ *val2 = 555556; return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_OFFSET: + *val = -214; + *val2 = 600000; + return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } @@ -503,7 +538,7 @@ static ssize_t sca3000_read_av_freq(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct sca3000_state *st = iio_priv(indio_dev); int len = 0, ret, val; @@ -539,7 +574,7 @@ error_ret: return ret; } /** - * __sca3000_get_base_frequency() obtain mode specific base frequency + * __sca3000_get_base_freq() obtain mode specific base frequency * * lock must be held **/ @@ -574,7 +609,7 @@ static ssize_t sca3000_read_frequency(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct sca3000_state *st = iio_priv(indio_dev); int ret, len = 0, base_freq = 0, val; @@ -616,13 +651,13 @@ static ssize_t sca3000_set_frequency(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct sca3000_state *st = iio_priv(indio_dev); int ret, base_freq = 0; int ctrlval; - long val; + int val; - ret = strict_strtol(buf, 10, &val); + ret = kstrtoint(buf, 10, &val); if (ret) return ret; @@ -655,7 +690,8 @@ error_free_lock: return ret ? ret : len; } -/* Should only really be registered if ring buffer support is compiled in. +/* + * Should only really be registered if ring buffer support is compiled in. * Does no harm however and doing it right would add a fair bit of complexity */ static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq); @@ -664,47 +700,19 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, sca3000_read_frequency, sca3000_set_frequency); - -/** - * sca3000_read_temp() sysfs interface to get the temperature when available - * -* The alignment of data in here is downright odd. See data sheet. -* Converting this into a meaningful value is left to inline functions in -* userspace part of header. -**/ -static ssize_t sca3000_read_temp(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct sca3000_state *st = iio_priv(indio_dev); - int ret; - int val; - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_TEMP_MSB, 2); - if (ret < 0) - goto error_ret; - val = ((st->rx[0] & 0x3F) << 3) | ((st->rx[1] & 0xE0) >> 5); - - return sprintf(buf, "%d\n", val); - -error_ret: - return 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"); - /** * sca3000_read_thresh() - query of a threshold **/ static int sca3000_read_thresh(struct iio_dev *indio_dev, - u64 e, - int *val) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) { int ret, i; struct sca3000_state *st = iio_priv(indio_dev); - int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e); + int num = chan->channel2; mutex_lock(&st->lock); ret = sca3000_read_ctrl_reg(st, sca3000_addresses[num][1]); mutex_unlock(&st->lock); @@ -720,18 +728,21 @@ static int sca3000_read_thresh(struct iio_dev *indio_dev, ARRAY_SIZE(st->info->mot_det_mult_xz)) *val += st->info->mot_det_mult_xz[i]; - return 0; + return IIO_VAL_INT; } /** * sca3000_write_thresh() control of threshold **/ static int sca3000_write_thresh(struct iio_dev *indio_dev, - u64 e, - int val) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) { struct sca3000_state *st = iio_priv(indio_dev); - int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e); + int num = chan->channel2; int ret; int i; u8 nonlinear = 0; @@ -768,33 +779,16 @@ static struct attribute *sca3000_attributes[] = { NULL, }; -static struct attribute *sca3000_attributes_with_temp[] = { - &iio_dev_attr_revision.dev_attr.attr, - &iio_dev_attr_measurement_mode_available.dev_attr.attr, - &iio_dev_attr_measurement_mode.dev_attr.attr, - &iio_dev_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_sampling_frequency.dev_attr.attr, - /* Only present if temp sensor is */ - &iio_dev_attr_in_temp_raw.dev_attr.attr, - &iio_const_attr_in_temp_offset.dev_attr.attr, - &iio_const_attr_in_temp_scale.dev_attr.attr, - NULL, -}; - static const struct attribute_group sca3000_attribute_group = { .attrs = sca3000_attributes, }; -static const struct attribute_group sca3000_attribute_group_with_temp = { - .attrs = sca3000_attributes_with_temp, -}; - -/* RING RELATED interrupt handler */ -/* depending on event, push to the ring buffer event chrdev or the event one */ - /** * sca3000_event_handler() - handling ring and non ring events * + * Ring related interrupt handler. Depending on event, push to + * the ring buffer event chrdev or the event one. + * * This function is complicated by the fact that the devices can signify ring * and non ring events via the same interrupt line and they can only * be distinguished via a read of the relevant status register. @@ -806,7 +800,8 @@ static irqreturn_t sca3000_event_handler(int irq, void *private) int ret, val; s64 last_timestamp = iio_get_time_ns(); - /* Could lead if badly timed to an extra read of status reg, + /* + * Could lead if badly timed to an extra read of status reg, * but ensures no interrupt is missed. */ mutex_lock(&st->lock); @@ -862,12 +857,14 @@ done: * sca3000_read_event_config() what events are enabled **/ static int sca3000_read_event_config(struct iio_dev *indio_dev, - u64 e) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) { struct sca3000_state *st = iio_priv(indio_dev); int ret; u8 protect_mask = 0x03; - int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e); + int num = chan->channel2; /* read current value of mode register */ mutex_lock(&st->lock); @@ -897,7 +894,7 @@ static ssize_t sca3000_query_free_fall_mode(struct device *dev, char *buf) { int ret, len; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct sca3000_state *st = iio_priv(indio_dev); int val; @@ -919,20 +916,19 @@ static ssize_t sca3000_query_free_fall_mode(struct device *dev, * the device falls more than 25cm. This has not been tested due * to fragile wiring. **/ - static ssize_t sca3000_set_free_fall_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct sca3000_state *st = iio_priv(indio_dev); - long val; + u8 val; int ret; u8 protect_mask = SCA3000_FREE_FALL_DETECT; mutex_lock(&st->lock); - ret = strict_strtol(buf, 10, &val); + ret = kstrtou8(buf, 10, &val); if (ret) goto error_ret; @@ -941,7 +937,7 @@ static ssize_t sca3000_set_free_fall_mode(struct device *dev, if (ret) goto error_ret; - /*if off and should be on*/ + /* if off and should be on */ if (val && !(st->rx[0] & protect_mask)) ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, (st->rx[0] | SCA3000_FREE_FALL_DETECT)); @@ -956,7 +952,7 @@ error_ret: } /** - * sca3000_set_mo_det() simple on off control for motion detector + * sca3000_write_event_config() simple on off control for motion detector * * This is a per axis control, but enabling any will result in the * motion detector unit being enabled. @@ -965,22 +961,26 @@ error_ret: * this mode is disabled. Currently normal mode is assumed. **/ static int sca3000_write_event_config(struct iio_dev *indio_dev, - u64 e, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, int state) { struct sca3000_state *st = iio_priv(indio_dev); int ret, ctrlval; u8 protect_mask = 0x03; - int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e); + int num = chan->channel2; mutex_lock(&st->lock); - /* First read the motion detector config to find out if - * this axis is on*/ + /* + * First read the motion detector config to find out if + * this axis is on + */ ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL); if (ret < 0) goto exit_point; ctrlval = ret; - /* Off and should be on */ + /* if off and should be on */ if (state && !(ctrlval & sca3000_addresses[num][2])) { ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL, @@ -1003,7 +1003,7 @@ static int sca3000_write_event_config(struct iio_dev *indio_dev, ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); if (ret) goto exit_point; - /*if off and should be on*/ + /* if off and should be on */ if ((st->mo_det_use_count) && ((st->rx[0] & protect_mask) != SCA3000_MEAS_MODE_MOT_DET)) ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, @@ -1049,7 +1049,7 @@ static struct attribute_group sca3000_event_attribute_group = { * Devices use flash memory to store many of the register values * and hence can come up in somewhat unpredictable states. * Hence reset everything on driver load. - **/ + **/ static int sca3000_clean_setup(struct sca3000_state *st) { int ret; @@ -1089,9 +1089,11 @@ static int sca3000_clean_setup(struct sca3000_state *st) | SCA3000_INT_MASK_ACTIVE_LOW); if (ret) goto error_ret; - /* Select normal measurement mode, free fall off, ring off */ - /* Ring in 12 bit mode - it is fine to overwrite reserved bits 3,5 - * as that occurs in one of the example on the datasheet */ + /* + * Select normal measurement mode, free fall off, ring off + * Ring in 12 bit mode - it is fine to overwrite reserved bits 3,5 + * as that occurs in one of the example on the datasheet + */ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); if (ret) goto error_ret; @@ -1115,27 +1117,15 @@ static const struct iio_info sca3000_info = { .driver_module = THIS_MODULE, }; -static const struct iio_info sca3000_info_with_temp = { - .attrs = &sca3000_attribute_group_with_temp, - .read_raw = &sca3000_read_raw, - .read_event_value = &sca3000_read_thresh, - .write_event_value = &sca3000_write_thresh, - .read_event_config = &sca3000_read_event_config, - .write_event_config = &sca3000_write_event_config, - .driver_module = THIS_MODULE, -}; - -static int __devinit sca3000_probe(struct spi_device *spi) +static int sca3000_probe(struct spi_device *spi) { int ret; struct sca3000_state *st; struct iio_dev *indio_dev; - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; st = iio_priv(indio_dev); spi_set_drvdata(spi, indio_dev); @@ -1146,10 +1136,12 @@ static int __devinit sca3000_probe(struct spi_device *spi) indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; - if (st->info->temp_output) - indio_dev->info = &sca3000_info_with_temp; - else { - indio_dev->info = &sca3000_info; + indio_dev->info = &sca3000_info; + if (st->info->temp_output) { + indio_dev->channels = sca3000_channels_with_temp; + indio_dev->num_channels = + ARRAY_SIZE(sca3000_channels_with_temp); + } else { indio_dev->channels = sca3000_channels; indio_dev->num_channels = ARRAY_SIZE(sca3000_channels); } @@ -1158,7 +1150,7 @@ static int __devinit sca3000_probe(struct spi_device *spi) sca3000_configure_ring(indio_dev); ret = iio_device_register(indio_dev); if (ret < 0) - goto error_free_dev; + return ret; ret = iio_buffer_register(indio_dev, sca3000_channels, @@ -1175,7 +1167,7 @@ static int __devinit sca3000_probe(struct spi_device *spi) ret = request_threaded_irq(spi->irq, NULL, &sca3000_event_handler, - IRQF_TRIGGER_FALLING, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "sca3000", indio_dev); if (ret) @@ -1194,10 +1186,6 @@ error_unregister_ring: iio_buffer_unregister(indio_dev); error_unregister_dev: iio_device_unregister(indio_dev); -error_free_dev: - iio_free_device(indio_dev); - -error_ret: return ret; } @@ -1223,17 +1211,14 @@ static int sca3000_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct sca3000_state *st = iio_priv(indio_dev); - int ret; - /* Must ensure no interrupts can be generated after this!*/ - ret = sca3000_stop_all_interrupts(st); - if (ret) - return ret; + + /* Must ensure no interrupts can be generated after this! */ + sca3000_stop_all_interrupts(st); if (spi->irq) free_irq(spi->irq, indio_dev); iio_device_unregister(indio_dev); iio_buffer_unregister(indio_dev); sca3000_unconfigure_ring(indio_dev); - iio_free_device(indio_dev); return 0; } @@ -1253,11 +1238,11 @@ static struct spi_driver sca3000_driver = { .owner = THIS_MODULE, }, .probe = sca3000_probe, - .remove = __devexit_p(sca3000_remove), + .remove = sca3000_remove, .id_table = sca3000_id, }; module_spi_driver(sca3000_driver); -MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); +MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); MODULE_DESCRIPTION("VTI SCA3000 Series Accelerometers SPI driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index 6b824a11f7f..198710651e0 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -5,7 +5,7 @@ * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * - * Copyright (c) 2009 Jonathan Cameron <jic23@cam.ac.uk> + * Copyright (c) 2009 Jonathan Cameron <jic23@kernel.org> * */ @@ -18,9 +18,9 @@ #include <linux/sched.h> #include <linux/poll.h> -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> #include "../ring_hw.h" #include "sca3000.h" @@ -39,7 +39,6 @@ static int sca3000_read_data(struct sca3000_state *st, int len) { int ret; - struct spi_message msg; struct spi_transfer xfer[2] = { { .len = 1, @@ -55,10 +54,7 @@ static int sca3000_read_data(struct sca3000_state *st, } xfer[1].rx_buf = *rx_p; st->tx[0] = SCA3000_READ_REG(reg_address_high); - spi_message_init(&msg); - spi_message_add_tail(&xfer[0], &msg); - spi_message_add_tail(&xfer[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); if (ret) { dev_err(get_device(&st->us->dev), "problem reading register"); goto error_free_rx; @@ -157,7 +153,7 @@ static ssize_t sca3000_query_ring_int(struct device *dev, { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret, val; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct sca3000_state *st = iio_priv(indio_dev); mutex_lock(&st->lock); @@ -178,14 +174,14 @@ static ssize_t sca3000_set_ring_int(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct sca3000_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - long val; + u8 val; int ret; mutex_lock(&st->lock); - ret = strict_strtol(buf, 10, &val); + ret = kstrtou8(buf, 10, &val); if (ret) goto error_ret; ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1); @@ -219,7 +215,7 @@ static ssize_t sca3000_show_buffer_scale(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct sca3000_state *st = iio_priv(indio_dev); return sprintf(buf, "0.%06d\n", 4*st->info->scale); @@ -256,7 +252,7 @@ static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) struct iio_buffer *buf; struct iio_hw_buffer *ring; - ring = kzalloc(sizeof *ring, GFP_KERNEL); + ring = kzalloc(sizeof(*ring), GFP_KERNEL); if (!ring) return NULL; @@ -269,7 +265,7 @@ static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) return buf; } -static inline void sca3000_rb_free(struct iio_buffer *r) +static void sca3000_ring_release(struct iio_buffer *r) { kfree(iio_to_hw_buf(r)); } @@ -278,23 +274,28 @@ static const struct iio_buffer_access_funcs sca3000_ring_access_funcs = { .read_first_n = &sca3000_read_first_n_hw_rb, .get_length = &sca3000_ring_get_length, .get_bytes_per_datum = &sca3000_ring_get_bytes_per_datum, + .release = sca3000_ring_release, }; int sca3000_configure_ring(struct iio_dev *indio_dev) { - indio_dev->buffer = sca3000_rb_allocate(indio_dev); - if (indio_dev->buffer == NULL) + struct iio_buffer *buffer; + + buffer = sca3000_rb_allocate(indio_dev); + if (buffer == NULL) return -ENOMEM; indio_dev->modes |= INDIO_BUFFER_HARDWARE; indio_dev->buffer->access = &sca3000_ring_access_funcs; + iio_device_attach_buffer(indio_dev, buffer); + return 0; } void sca3000_unconfigure_ring(struct iio_dev *indio_dev) { - sca3000_rb_free(indio_dev->buffer); + iio_buffer_put(indio_dev->buffer); } static inline @@ -308,7 +309,7 @@ int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state) if (ret) goto error_ret; if (state) { - printk(KERN_INFO "supposedly enabling ring buffer\n"); + dev_info(&indio_dev->dev, "supposedly enabling ring buffer\n"); ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, (st->rx[0] | SCA3000_RING_BUF_ENABLE)); diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index d9decea4fa6..b87e382ad76 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -10,22 +10,11 @@ config AD7291 Say yes here to build support for Analog Devices AD7291 8 Channel ADC with temperature sensor. -config AD7298 - tristate "Analog Devices AD7298 ADC driver" - depends on SPI - help - Say yes here to build support for Analog Devices AD7298 - 8 Channel ADC with temperature sensor. - - To compile this driver as a module, choose M here: the - module will be called ad7298. - config AD7606 tristate "Analog Devices AD7606 ADC driver" depends on GPIOLIB select IIO_BUFFER - select IIO_TRIGGER - select IIO_SW_RING + select IIO_TRIGGERED_BUFFER help Say yes here to build support for Analog Devices: ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC). @@ -48,85 +37,23 @@ config AD7606_IFACE_SPI Say yes here to include parallel interface support on the AD7606 ADC driver. -config AD799X - tristate "Analog Devices AD799x ADC driver" - depends on I2C - select IIO_TRIGGER if IIO_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 converters (ADC). Provides direct access - via sysfs. - -config AD799X_RING_BUFFER - bool "Analog Devices AD799x: use ring buffer" - depends on AD799X - select IIO_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_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 converters (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. - -config AD7887 - tristate "Analog Devices AD7887 ADC driver" - depends on SPI - select IIO_BUFFER - select IIO_SW_RING - select IIO_TRIGGER - help - Say yes here to build support for Analog Devices - AD7887 SPI analog to digital converter (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 ad7887. - config AD7780 - tristate "Analog Devices AD7780 AD7781 ADC driver" + tristate "Analog Devices AD7780 and similar ADCs driver" depends on SPI depends on GPIOLIB + select AD_SIGMA_DELTA help - Say yes here to build support for Analog Devices + Say yes here to build support for Analog Devices AD7170, AD7171, AD7780 and AD7781 SPI analog to digital converters (ADC). If unsure, say N (but it's safe to say "Y"). To compile this driver as a module, choose M here: the module will be called ad7780. -config AD7793 - tristate "Analog Devices AD7792 AD7793 ADC driver" - depends on SPI - select IIO_BUFFER - select IIO_SW_RING - select IIO_TRIGGER - help - Say yes here to build support for Analog Devices - AD7792 and AD7793 SPI analog to digital converters (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 AD7793. - config AD7816 tristate "Analog Devices AD7816/7/8 temperature sensor and ADC driver" depends on SPI - depends on GENERIC_GPIO + depends on GPIOLIB help Say yes here to build support for Analog Devices AD7816/7/8 temperature sensors and ADC. @@ -134,9 +61,7 @@ config AD7816 config AD7192 tristate "Analog Devices AD7190 AD7192 AD7195 ADC driver" depends on SPI - select IIO_BUFFER - select IIO_SW_RING - select IIO_TRIGGER + select AD_SIGMA_DELTA help Say yes here to build support for Analog Devices AD7190, AD7192 or AD7195 SPI analog to digital converters (ADC). @@ -145,20 +70,6 @@ config AD7192 To compile this driver as a module, choose M here: the module will be called ad7192. -config ADT7310 - tristate "Analog Devices ADT7310 temperature sensor driver" - depends on SPI - help - Say yes here to build support for Analog Devices ADT7310 - temperature sensors. - -config ADT7410 - tristate "Analog Devices ADT7410 temperature sensor driver" - depends on I2C - help - Say yes here to build support for Analog Devices ADT7410 - temperature sensors. - config AD7280 tristate "Analog Devices AD7280A Lithium Ion Battery Monitoring System" depends on SPI @@ -169,28 +80,38 @@ config AD7280 To compile this driver as a module, choose M here: the module will be called ad7280a -config MAX1363 - tristate "Maxim max1363 ADC driver" - depends on I2C - select IIO_TRIGGER if IIO_BUFFER - select MAX1363_RING_BUFFER +config LPC32XX_ADC + tristate "NXP LPC32XX ADC" + depends on ARCH_LPC32XX || COMPILE_TEST + depends on HAS_IOMEM help - Say yes here to build support for many Maxim i2c analog to digital - converters (ADC). (max1361, max1362, max1363, max1364, max1036, - max1037, max1038, max1039, max1136, max1136, max1137, max1138, - max1139, max1236, max1237, max11238, max1239, max11600, max11601, - max11602, max11603, max11604, max11605, max11606, max11607, - max11608, max11609, max11610, max11611, max11612, max11613, - max11614, max11615, max11616, max11617, max11644, max11645, - max11646, max11647) Provides direct access via sysfs. - -config MAX1363_RING_BUFFER - bool "Maxim max1363: use ring buffer" - depends on MAX1363 + Say yes here to build support for the integrated ADC inside the + LPC32XX SoC. Note that this feature uses the same hardware as the + touchscreen driver, so you should either select only one of the two + drivers (lpc32xx_adc or lpc32xx_ts) or, in the OpenFirmware case, + activate only one via device tree selection. Provides direct access + via sysfs. + +config MXS_LRADC + tristate "Freescale i.MX23/i.MX28 LRADC" + depends on ARCH_MXS || COMPILE_TEST + depends on INPUT + select STMP_DEVICE select IIO_BUFFER - select IIO_SW_RING + select IIO_TRIGGERED_BUFFER help - Say yes here to include ring buffer support in the MAX1363 - ADC driver. + Say yes here to build support for i.MX23/i.MX28 LRADC convertor + built into these chips. + + To compile this driver as a module, choose M here: the + module will be called mxs-lradc. + +config SPEAR_ADC + tristate "ST SPEAr ADC" + depends on PLAT_SPEAR || COMPILE_TEST + depends on HAS_IOMEM + help + Say yes here to build support for the integrated ADC inside the + ST SPEAr SoC. Provides direct access via sysfs. endmenu diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile index ceee7f3c306..afdcd1ff08f 100644 --- a/drivers/staging/iio/adc/Makefile +++ b/drivers/staging/iio/adc/Makefile @@ -2,38 +2,17 @@ # Makefile for industrial I/O ADC drivers # -max1363-y := max1363_core.o -max1363-y += max1363_ring.o - -obj-$(CONFIG_MAX1363) += max1363.o - ad7606-y := ad7606_core.o ad7606-$(CONFIG_IIO_BUFFER) += ad7606_ring.o ad7606-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o ad7606-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o obj-$(CONFIG_AD7606) += ad7606.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_BUFFER) += ad7476_ring.o -obj-$(CONFIG_AD7476) += ad7476.o - -ad7887-y := ad7887_core.o -ad7887-$(CONFIG_IIO_BUFFER) += ad7887_ring.o -obj-$(CONFIG_AD7887) += ad7887.o - -ad7298-y := ad7298_core.o -ad7298-$(CONFIG_IIO_BUFFER) += ad7298_ring.o -obj-$(CONFIG_AD7298) += ad7298.o - obj-$(CONFIG_AD7291) += ad7291.o obj-$(CONFIG_AD7780) += ad7780.o -obj-$(CONFIG_AD7793) += ad7793.o obj-$(CONFIG_AD7816) += ad7816.o obj-$(CONFIG_AD7192) += ad7192.o -obj-$(CONFIG_ADT7310) += adt7310.o -obj-$(CONFIG_ADT7410) += adt7410.o obj-$(CONFIG_AD7280) += ad7280a.o +obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o +obj-$(CONFIG_MXS_LRADC) += mxs-lradc.o +obj-$(CONFIG_SPEAR_ADC) += spear_adc.o diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 45f4504ed92..83bb44b3815 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -1,7 +1,7 @@ /* * AD7190 AD7192 AD7195 SPI ADC driver * - * Copyright 2011 Analog Devices Inc. + * Copyright 2011-2012 Analog Devices Inc. * * Licensed under the GPL-2. */ @@ -17,12 +17,13 @@ #include <linux/sched.h> #include <linux/delay.h> -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" -#include "../ring_sw.h" -#include "../trigger.h" -#include "../trigger_consumer.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> +#include <linux/iio/trigger.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/iio/adc/ad_sigma_delta.h> #include "ad7192.h" @@ -57,6 +58,7 @@ /* Mode Register Bit Designations (AD7192_REG_MODE) */ #define AD7192_MODE_SEL(x) (((x) & 0x7) << 21) /* Operation Mode Select */ +#define AD7192_MODE_SEL_MASK (0x7 << 21) /* Operation Mode Select Mask */ #define AD7192_MODE_DAT_STA (1 << 20) /* Status Register transmission */ #define AD7192_MODE_CLKSRC(x) (((x) & 0x3) << 18) /* Clock Source Select */ #define AD7192_MODE_SINC3 (1 << 15) /* SINC3 Filter Select */ @@ -91,7 +93,8 @@ #define AD7192_CONF_CHOP (1 << 23) /* CHOP enable */ #define AD7192_CONF_REFSEL (1 << 20) /* REFIN1/REFIN2 Reference Select */ -#define AD7192_CONF_CHAN(x) (((x) & 0xFF) << 8) /* Channel select */ +#define AD7192_CONF_CHAN(x) (((1 << (x)) & 0xFF) << 8) /* Channel select */ +#define AD7192_CONF_CHAN_MASK (0xFF << 8) /* Channel select mask */ #define AD7192_CONF_BURN (1 << 7) /* Burnout current enable */ #define AD7192_CONF_REFDET (1 << 6) /* Reference detect enable */ #define AD7192_CONF_BUF (1 << 4) /* Buffered Mode Enable */ @@ -133,194 +136,54 @@ */ struct ad7192_state { - struct spi_device *spi; - struct iio_trigger *trig; struct regulator *reg; - struct ad7192_platform_data *pdata; - wait_queue_head_t wq_data_avail; - bool done; - bool irq_dis; u16 int_vref_mv; u32 mclk; u32 f_order; u32 mode; u32 conf; u32 scale_avail[8][2]; - long available_scan_masks[9]; u8 gpocon; u8 devid; - /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - */ - u8 data[4] ____cacheline_aligned; + + struct ad_sigma_delta sd; }; -static int __ad7192_write_reg(struct ad7192_state *st, bool locked, - bool cs_change, unsigned char reg, - unsigned size, unsigned val) +static struct ad7192_state *ad_sigma_delta_to_ad7192(struct ad_sigma_delta *sd) { - u8 *data = st->data; - struct spi_transfer t = { - .tx_buf = data, - .len = size + 1, - .cs_change = cs_change, - }; - struct spi_message m; - - data[0] = AD7192_COMM_WRITE | AD7192_COMM_ADDR(reg); - - switch (size) { - case 3: - data[1] = val >> 16; - data[2] = val >> 8; - data[3] = val; - break; - case 2: - data[1] = val >> 8; - data[2] = val; - break; - case 1: - data[1] = val; - break; - default: - return -EINVAL; - } - - spi_message_init(&m); - spi_message_add_tail(&t, &m); - - if (locked) - return spi_sync_locked(st->spi, &m); - else - return spi_sync(st->spi, &m); + return container_of(sd, struct ad7192_state, sd); } -static int ad7192_write_reg(struct ad7192_state *st, - unsigned reg, unsigned size, unsigned val) +static int ad7192_set_channel(struct ad_sigma_delta *sd, unsigned int channel) { - return __ad7192_write_reg(st, false, false, reg, size, val); -} + struct ad7192_state *st = ad_sigma_delta_to_ad7192(sd); -static int __ad7192_read_reg(struct ad7192_state *st, bool locked, - bool cs_change, unsigned char reg, - int *val, unsigned size) -{ - u8 *data = st->data; - int ret; - struct spi_transfer t[] = { - { - .tx_buf = data, - .len = 1, - }, { - .rx_buf = data, - .len = size, - .cs_change = cs_change, - }, - }; - struct spi_message m; - - data[0] = AD7192_COMM_READ | AD7192_COMM_ADDR(reg); - - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - spi_message_add_tail(&t[1], &m); - - if (locked) - ret = spi_sync_locked(st->spi, &m); - else - ret = spi_sync(st->spi, &m); + st->conf &= ~AD7192_CONF_CHAN_MASK; + st->conf |= AD7192_CONF_CHAN(channel); - if (ret < 0) - return ret; - - switch (size) { - case 3: - *val = data[0] << 16 | data[1] << 8 | data[2]; - break; - case 2: - *val = data[0] << 8 | data[1]; - break; - case 1: - *val = data[0]; - break; - default: - return -EINVAL; - } - - return 0; + return ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf); } -static int ad7192_read_reg(struct ad7192_state *st, - unsigned reg, int *val, unsigned size) +static int ad7192_set_mode(struct ad_sigma_delta *sd, + enum ad_sigma_delta_mode mode) { - return __ad7192_read_reg(st, 0, 0, reg, val, size); -} + struct ad7192_state *st = ad_sigma_delta_to_ad7192(sd); -static int ad7192_read(struct ad7192_state *st, unsigned ch, - unsigned len, int *val) -{ - int ret; - st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) | - AD7192_CONF_CHAN(1 << ch); - st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | - AD7192_MODE_SEL(AD7192_MODE_SINGLE); - - ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf); - - spi_bus_lock(st->spi->master); - st->done = false; - - ret = __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, st->mode); - if (ret < 0) - goto out; - - st->irq_dis = false; - enable_irq(st->spi->irq); - wait_event_interruptible(st->wq_data_avail, st->done); + st->mode &= ~AD7192_MODE_SEL_MASK; + st->mode |= AD7192_MODE_SEL(mode); - ret = __ad7192_read_reg(st, 1, 0, AD7192_REG_DATA, val, len); -out: - spi_bus_unlock(st->spi->master); - - return ret; + return ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); } -static int ad7192_calibrate(struct ad7192_state *st, unsigned mode, unsigned ch) -{ - int ret; - - st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) | - AD7192_CONF_CHAN(1 << ch); - st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | AD7192_MODE_SEL(mode); - - ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf); - - spi_bus_lock(st->spi->master); - st->done = false; - - ret = __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, - (st->devid != ID_AD7195) ? - st->mode | AD7192_MODE_CLKDIV : - st->mode); - if (ret < 0) - goto out; - - st->irq_dis = false; - enable_irq(st->spi->irq); - wait_event_interruptible(st->wq_data_avail, st->done); - - st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | - AD7192_MODE_SEL(AD7192_MODE_IDLE); - - ret = __ad7192_write_reg(st, 1, 0, AD7192_REG_MODE, 3, st->mode); -out: - spi_bus_unlock(st->spi->master); - - return ret; -} +static const struct ad_sigma_delta_info ad7192_sigma_delta_info = { + .set_channel = ad7192_set_channel, + .set_mode = ad7192_set_mode, + .has_registers = true, + .addr_shift = 3, + .read_mask = BIT(6), +}; -static const u8 ad7192_calib_arr[8][2] = { +static const struct ad_sd_calib_data ad7192_calib_arr[8] = { {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN1}, {AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN1}, {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN2}, @@ -333,45 +196,34 @@ static const u8 ad7192_calib_arr[8][2] = { static int ad7192_calibrate_all(struct ad7192_state *st) { - int i, ret; - - for (i = 0; i < ARRAY_SIZE(ad7192_calib_arr); i++) { - ret = ad7192_calibrate(st, ad7192_calib_arr[i][0], - ad7192_calib_arr[i][1]); - if (ret) - goto out; - } - - return 0; -out: - dev_err(&st->spi->dev, "Calibration failed\n"); - return ret; + return ad_sd_calibrate_all(&st->sd, ad7192_calib_arr, + ARRAY_SIZE(ad7192_calib_arr)); } -static int ad7192_setup(struct ad7192_state *st) +static int ad7192_setup(struct ad7192_state *st, + const struct ad7192_platform_data *pdata) { - struct iio_dev *indio_dev = spi_get_drvdata(st->spi); - struct ad7192_platform_data *pdata = st->pdata; + struct iio_dev *indio_dev = spi_get_drvdata(st->sd.spi); unsigned long long scale_uv; int i, ret, id; u8 ones[6]; /* reset the serial interface */ memset(&ones, 0xFF, 6); - ret = spi_write(st->spi, &ones, 6); + ret = spi_write(st->sd.spi, &ones, 6); if (ret < 0) goto out; msleep(1); /* Wait for at least 500us */ /* write/read test for device presence */ - ret = ad7192_read_reg(st, AD7192_REG_ID, &id, 1); + ret = ad_sd_read_reg(&st->sd, AD7192_REG_ID, 1, &id); if (ret) goto out; id &= AD7192_ID_MASK; if (id != st->devid) - dev_warn(&st->spi->dev, "device ID query failed (0x%X)\n", id); + dev_warn(&st->sd.spi->dev, "device ID query failed (0x%X)\n", id); switch (pdata->clock_source_sel) { case AD7192_CLK_EXT_MCLK1_2: @@ -424,11 +276,11 @@ static int ad7192_setup(struct ad7192_state *st) if (pdata->burnout_curr_en) st->conf |= AD7192_CONF_BURN; - ret = ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode); + ret = ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); if (ret) goto out; - ret = ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf); + ret = ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf); if (ret) goto out; @@ -449,227 +301,15 @@ static int ad7192_setup(struct ad7192_state *st) return 0; out: - dev_err(&st->spi->dev, "setup failed\n"); - return ret; -} - -static int ad7192_ring_preenable(struct iio_dev *indio_dev) -{ - struct ad7192_state *st = iio_priv(indio_dev); - struct iio_buffer *ring = indio_dev->buffer; - size_t d_size; - unsigned channel; - - if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) - return -EINVAL; - - channel = find_first_bit(indio_dev->active_scan_mask, - indio_dev->masklength); - - d_size = bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength) * - indio_dev->channels[0].scan_type.storagebits / 8; - - if (ring->scan_timestamp) { - d_size += sizeof(s64); - - if (d_size % sizeof(s64)) - d_size += sizeof(s64) - (d_size % sizeof(s64)); - } - - if (indio_dev->buffer->access->set_bytes_per_datum) - indio_dev->buffer->access-> - set_bytes_per_datum(indio_dev->buffer, d_size); - - st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | - AD7192_MODE_SEL(AD7192_MODE_CONT); - st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) | - AD7192_CONF_CHAN(1 << indio_dev->channels[channel].address); - - ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf); - - spi_bus_lock(st->spi->master); - __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, st->mode); - - st->irq_dis = false; - enable_irq(st->spi->irq); - - return 0; -} - -static int ad7192_ring_postdisable(struct iio_dev *indio_dev) -{ - struct ad7192_state *st = iio_priv(indio_dev); - - st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | - AD7192_MODE_SEL(AD7192_MODE_IDLE); - - st->done = false; - wait_event_interruptible(st->wq_data_avail, st->done); - - if (!st->irq_dis) - disable_irq_nosync(st->spi->irq); - - __ad7192_write_reg(st, 1, 0, AD7192_REG_MODE, 3, st->mode); - - return spi_bus_unlock(st->spi->master); -} - -/** - * ad7192_trigger_handler() bh of trigger launched polling to ring buffer - **/ -static irqreturn_t ad7192_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct iio_buffer *ring = indio_dev->buffer; - struct ad7192_state *st = iio_priv(indio_dev); - s64 dat64[2]; - s32 *dat32 = (s32 *)dat64; - - if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) - __ad7192_read_reg(st, 1, 1, AD7192_REG_DATA, - dat32, - indio_dev->channels[0].scan_type.realbits/8); - - /* Guaranteed to be aligned with 8 byte boundary */ - if (ring->scan_timestamp) - dat64[1] = pf->timestamp; - - ring->access->store_to(ring, (u8 *)dat64, pf->timestamp); - - iio_trigger_notify_done(indio_dev->trig); - st->irq_dis = false; - enable_irq(st->spi->irq); - - return IRQ_HANDLED; -} - -static const struct iio_buffer_setup_ops ad7192_ring_setup_ops = { - .preenable = &ad7192_ring_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, - .postdisable = &ad7192_ring_postdisable, -}; - -static int ad7192_register_ring_funcs_and_init(struct iio_dev *indio_dev) -{ - int ret; - - indio_dev->buffer = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->buffer) { - ret = -ENOMEM; - goto error_ret; - } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, - &ad7192_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "ad7192_consumer%d", - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_deallocate_sw_rb; - } - - /* Ring buffer functions - here trigger setup related */ - indio_dev->setup_ops = &ad7192_ring_setup_ops; - - /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_deallocate_sw_rb: - iio_sw_rb_free(indio_dev->buffer); -error_ret: + dev_err(&st->sd.spi->dev, "setup failed\n"); return ret; } -static void ad7192_ring_cleanup(struct iio_dev *indio_dev) -{ - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->buffer); -} - -/** - * ad7192_data_rdy_trig_poll() the event handler for the data rdy trig - **/ -static irqreturn_t ad7192_data_rdy_trig_poll(int irq, void *private) -{ - struct ad7192_state *st = iio_priv(private); - - st->done = true; - wake_up_interruptible(&st->wq_data_avail); - disable_irq_nosync(irq); - st->irq_dis = true; - iio_trigger_poll(st->trig, iio_get_time_ns()); - - return IRQ_HANDLED; -} - -static struct iio_trigger_ops ad7192_trigger_ops = { - .owner = THIS_MODULE, -}; - -static int ad7192_probe_trigger(struct iio_dev *indio_dev) -{ - struct ad7192_state *st = iio_priv(indio_dev); - int ret; - - st->trig = iio_allocate_trigger("%s-dev%d", - spi_get_device_id(st->spi)->name, - indio_dev->id); - if (st->trig == NULL) { - ret = -ENOMEM; - goto error_ret; - } - st->trig->ops = &ad7192_trigger_ops; - ret = request_irq(st->spi->irq, - ad7192_data_rdy_trig_poll, - IRQF_TRIGGER_LOW, - spi_get_device_id(st->spi)->name, - indio_dev); - if (ret) - goto error_free_trig; - - disable_irq_nosync(st->spi->irq); - st->irq_dis = true; - st->trig->dev.parent = &st->spi->dev; - st->trig->private_data = indio_dev; - - ret = iio_trigger_register(st->trig); - - /* select default trigger */ - indio_dev->trig = st->trig; - if (ret) - goto error_free_irq; - - return 0; - -error_free_irq: - free_irq(st->spi->irq, indio_dev); -error_free_trig: - iio_free_trigger(st->trig); -error_ret: - return ret; -} - -static void ad7192_remove_trigger(struct iio_dev *indio_dev) -{ - struct ad7192_state *st = iio_priv(indio_dev); - - iio_trigger_unregister(st->trig); - free_irq(st->spi->irq, indio_dev); - iio_free_trigger(st->trig); -} - static ssize_t ad7192_read_frequency(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7192_state *st = iio_priv(indio_dev); return sprintf(buf, "%d\n", st->mclk / @@ -681,14 +321,16 @@ static ssize_t ad7192_write_frequency(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7192_state *st = iio_priv(indio_dev); unsigned long lval; int div, ret; - ret = strict_strtoul(buf, 10, &lval); + ret = kstrtoul(buf, 10, &lval); if (ret) return ret; + if (lval == 0) + return -EINVAL; mutex_lock(&indio_dev->mlock); if (iio_buffer_enabled(indio_dev)) { @@ -704,7 +346,7 @@ static ssize_t ad7192_write_frequency(struct device *dev, st->mode &= ~AD7192_MODE_RATE(-1); st->mode |= AD7192_MODE_RATE(div); - ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode); + ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); out: mutex_unlock(&indio_dev->mlock); @@ -716,11 +358,10 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, ad7192_read_frequency, ad7192_write_frequency); - static ssize_t ad7192_show_scale_available(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7192_state *st = iio_priv(indio_dev); int i, len = 0; @@ -744,7 +385,7 @@ static ssize_t ad7192_show_ac_excitation(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7192_state *st = iio_priv(indio_dev); return sprintf(buf, "%d\n", !!(st->mode & AD7192_MODE_ACX)); @@ -754,7 +395,7 @@ static ssize_t ad7192_show_bridge_switch(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7192_state *st = iio_priv(indio_dev); return sprintf(buf, "%d\n", !!(st->gpocon & AD7192_GPOCON_BPDSW)); @@ -765,7 +406,7 @@ static ssize_t ad7192_set(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7192_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; @@ -788,7 +429,7 @@ static ssize_t ad7192_set(struct device *dev, else st->gpocon &= ~AD7192_GPOCON_BPDSW; - ad7192_write_reg(st, AD7192_REG_GPOCON, 1, st->gpocon); + ad_sd_write_reg(&st->sd, AD7192_REG_GPOCON, 1, st->gpocon); break; case AD7192_REG_MODE: if (val) @@ -796,7 +437,7 @@ static ssize_t ad7192_set(struct device *dev, else st->mode &= ~AD7192_MODE_ACX; - ad7192_write_reg(st, AD7192_REG_GPOCON, 3, st->mode); + ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); break; default: ret = -EINVAL; @@ -824,27 +465,27 @@ static struct attribute *ad7192_attributes[] = { NULL }; -static umode_t ad7192_attr_is_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7192_state *st = iio_priv(indio_dev); +static const struct attribute_group ad7192_attribute_group = { + .attrs = ad7192_attributes, +}; - umode_t mode = attr->mode; +static struct attribute *ad7195_attributes[] = { + &iio_dev_attr_sampling_frequency.dev_attr.attr, + &iio_dev_attr_in_v_m_v_scale_available.dev_attr.attr, + &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, + &iio_dev_attr_bridge_switch_en.dev_attr.attr, + NULL +}; - if ((st->devid != ID_AD7195) && - (attr == &iio_dev_attr_ac_excitation_en.dev_attr.attr)) - mode = 0; +static const struct attribute_group ad7195_attribute_group = { + .attrs = ad7195_attributes, +}; - return mode; +static unsigned int ad7192_get_temp_scale(bool unipolar) +{ + return unipolar ? 2815 * 2 : 2815; } -static const struct attribute_group ad7192_attribute_group = { - .attrs = ad7192_attributes, - .is_visible = ad7192_attr_is_visible, -}; - static int ad7192_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, @@ -852,40 +493,11 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, long m) { struct ad7192_state *st = iio_priv(indio_dev); - int ret, smpl = 0; bool unipolar = !!(st->conf & AD7192_CONF_UNIPOLAR); switch (m) { - case 0: - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) - ret = -EBUSY; - else - ret = ad7192_read(st, chan->address, - chan->scan_type.realbits / 8, &smpl); - mutex_unlock(&indio_dev->mlock); - - if (ret < 0) - return ret; - - *val = (smpl >> chan->scan_type.shift) & - ((1 << (chan->scan_type.realbits)) - 1); - - switch (chan->type) { - case IIO_VOLTAGE: - if (!unipolar) - *val -= (1 << (chan->scan_type.realbits - 1)); - break; - case IIO_TEMP: - *val -= 0x800000; - *val /= 2815; /* temp Kelvin */ - *val -= 273; /* temp Celsius */ - break; - default: - return -EINVAL; - } - return IIO_VAL_INT; - + case IIO_CHAN_INFO_RAW: + return ad_sigma_delta_single_conversion(indio_dev, chan, val); case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: @@ -895,11 +507,21 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT_PLUS_NANO; case IIO_TEMP: - *val = 1000; - return IIO_VAL_INT; + *val = 0; + *val2 = 1000000000 / ad7192_get_temp_scale(unipolar); + return IIO_VAL_INT_PLUS_NANO; default: return -EINVAL; } + case IIO_CHAN_INFO_OFFSET: + if (!unipolar) + *val = -(1 << (chan->scan_type.realbits - 1)); + else + *val = 0; + /* Kelvin to Celsius */ + if (chan->type == IIO_TEMP) + *val -= 273 * ad7192_get_temp_scale(unipolar); + return IIO_VAL_INT; } return -EINVAL; @@ -926,18 +548,18 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, ret = -EINVAL; for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) if (val2 == st->scale_avail[i][1]) { + ret = 0; tmp = st->conf; st->conf &= ~AD7192_CONF_GAIN(-1); st->conf |= AD7192_CONF_GAIN(i); - - if (tmp != st->conf) { - ad7192_write_reg(st, AD7192_REG_CONF, - 3, st->conf); - ad7192_calibrate_all(st); - } - ret = 0; + if (tmp == st->conf) + break; + ad_sd_write_reg(&st->sd, AD7192_REG_CONF, + 3, st->conf); + ad7192_calibrate_all(st); + break; } - + break; default: ret = -EINVAL; } @@ -947,15 +569,6 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, return ret; } -static int ad7192_validate_trigger(struct iio_dev *indio_dev, - struct iio_trigger *trig) -{ - if (indio_dev->trig != trig) - return -EINVAL; - - return 0; -} - static int ad7192_write_raw_get_fmt(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, long mask) @@ -968,58 +581,37 @@ static const struct iio_info ad7192_info = { .write_raw = &ad7192_write_raw, .write_raw_get_fmt = &ad7192_write_raw_get_fmt, .attrs = &ad7192_attribute_group, - .validate_trigger = ad7192_validate_trigger, + .validate_trigger = ad_sd_validate_trigger, .driver_module = THIS_MODULE, }; -#define AD7192_CHAN_DIFF(_chan, _chan2, _name, _address, _si) \ - { .type = IIO_VOLTAGE, \ - .differential = 1, \ - .indexed = 1, \ - .extend_name = _name, \ - .channel = _chan, \ - .channel2 = _chan2, \ - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ - .address = _address, \ - .scan_index = _si, \ - .scan_type = IIO_ST('s', 24, 32, 0)} - -#define AD7192_CHAN(_chan, _address, _si) \ - { .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .channel = _chan, \ - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ - .address = _address, \ - .scan_index = _si, \ - .scan_type = IIO_ST('s', 24, 32, 0)} - -#define AD7192_CHAN_TEMP(_chan, _address, _si) \ - { .type = IIO_TEMP, \ - .indexed = 1, \ - .channel = _chan, \ - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ - .address = _address, \ - .scan_index = _si, \ - .scan_type = IIO_ST('s', 24, 32, 0)} - -static struct iio_chan_spec ad7192_channels[] = { - AD7192_CHAN_DIFF(1, 2, NULL, AD7192_CH_AIN1P_AIN2M, 0), - AD7192_CHAN_DIFF(3, 4, NULL, AD7192_CH_AIN3P_AIN4M, 1), - AD7192_CHAN_TEMP(0, AD7192_CH_TEMP, 2), - AD7192_CHAN_DIFF(2, 2, "shorted", AD7192_CH_AIN2P_AIN2M, 3), - AD7192_CHAN(1, AD7192_CH_AIN1, 4), - AD7192_CHAN(2, AD7192_CH_AIN2, 5), - AD7192_CHAN(3, AD7192_CH_AIN3, 6), - AD7192_CHAN(4, AD7192_CH_AIN4, 7), +static const struct iio_info ad7195_info = { + .read_raw = &ad7192_read_raw, + .write_raw = &ad7192_write_raw, + .write_raw_get_fmt = &ad7192_write_raw_get_fmt, + .attrs = &ad7195_attribute_group, + .validate_trigger = ad_sd_validate_trigger, + .driver_module = THIS_MODULE, +}; + +static const struct iio_chan_spec ad7192_channels[] = { + AD_SD_DIFF_CHANNEL(0, 1, 2, AD7192_CH_AIN1P_AIN2M, 24, 32, 0), + AD_SD_DIFF_CHANNEL(1, 3, 4, AD7192_CH_AIN3P_AIN4M, 24, 32, 0), + AD_SD_TEMP_CHANNEL(2, AD7192_CH_TEMP, 24, 32, 0), + AD_SD_SHORTED_CHANNEL(3, 2, AD7192_CH_AIN2P_AIN2M, 24, 32, 0), + AD_SD_CHANNEL(4, 1, AD7192_CH_AIN1, 24, 32, 0), + AD_SD_CHANNEL(5, 2, AD7192_CH_AIN2, 24, 32, 0), + AD_SD_CHANNEL(6, 3, AD7192_CH_AIN3, 24, 32, 0), + AD_SD_CHANNEL(7, 4, AD7192_CH_AIN4, 24, 32, 0), IIO_CHAN_SOFT_TIMESTAMP(8), }; -static int __devinit ad7192_probe(struct spi_device *spi) +static int ad7192_probe(struct spi_device *spi) { - struct ad7192_platform_data *pdata = spi->dev.platform_data; + const struct ad7192_platform_data *pdata = spi->dev.platform_data; struct ad7192_state *st; struct iio_dev *indio_dev; - int ret, i , voltage_uv = 0; + int ret , voltage_uv = 0; if (!pdata) { dev_err(&spi->dev, "no platform data?\n"); @@ -1031,23 +623,21 @@ static int __devinit ad7192_probe(struct spi_device *spi) return -ENODEV; } - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; st = iio_priv(indio_dev); - st->reg = regulator_get(&spi->dev, "vcc"); + st->reg = devm_regulator_get(&spi->dev, "vcc"); if (!IS_ERR(st->reg)) { ret = regulator_enable(st->reg); if (ret) - goto error_put_reg; + return ret; voltage_uv = regulator_get_voltage(st->reg); } - st->pdata = pdata; - if (pdata && pdata->vref_mv) st->int_vref_mv = pdata->vref_mv; else if (voltage_uv) @@ -1056,60 +646,37 @@ static int __devinit ad7192_probe(struct spi_device *spi) dev_warn(&spi->dev, "reference voltage undefined\n"); spi_set_drvdata(spi, indio_dev); - st->spi = spi; st->devid = spi_get_device_id(spi)->driver_data; indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ad7192_channels; indio_dev->num_channels = ARRAY_SIZE(ad7192_channels); - indio_dev->available_scan_masks = st->available_scan_masks; - indio_dev->info = &ad7192_info; - - for (i = 0; i < indio_dev->num_channels; i++) - st->available_scan_masks[i] = (1 << i) | (1 << - indio_dev->channels[indio_dev->num_channels - 1]. - scan_index); + if (st->devid == ID_AD7195) + indio_dev->info = &ad7195_info; + else + indio_dev->info = &ad7192_info; - init_waitqueue_head(&st->wq_data_avail); + ad_sd_init(&st->sd, indio_dev, spi, &ad7192_sigma_delta_info); - ret = ad7192_register_ring_funcs_and_init(indio_dev); + ret = ad_sd_setup_buffer_and_trigger(indio_dev); if (ret) goto error_disable_reg; - ret = ad7192_probe_trigger(indio_dev); - if (ret) - goto error_ring_cleanup; - - ret = iio_buffer_register(indio_dev, - indio_dev->channels, - indio_dev->num_channels); + ret = ad7192_setup(st, pdata); if (ret) goto error_remove_trigger; - ret = ad7192_setup(st); - if (ret) - goto error_unreg_ring; - ret = iio_device_register(indio_dev); if (ret < 0) - goto error_unreg_ring; + goto error_remove_trigger; return 0; -error_unreg_ring: - iio_buffer_unregister(indio_dev); error_remove_trigger: - ad7192_remove_trigger(indio_dev); -error_ring_cleanup: - ad7192_ring_cleanup(indio_dev); + ad_sd_cleanup_buffer_and_trigger(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); - - iio_free_device(indio_dev); return ret; } @@ -1120,14 +687,10 @@ static int ad7192_remove(struct spi_device *spi) struct ad7192_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); - ad7192_remove_trigger(indio_dev); - ad7192_ring_cleanup(indio_dev); + ad_sd_cleanup_buffer_and_trigger(indio_dev); - if (!IS_ERR(st->reg)) { + if (!IS_ERR(st->reg)) regulator_disable(st->reg); - regulator_put(st->reg); - } return 0; } @@ -1146,7 +709,7 @@ static struct spi_driver ad7192_driver = { .owner = THIS_MODULE, }, .probe = ad7192_probe, - .remove = __devexit_p(ad7192_remove), + .remove = ad7192_remove, .id_table = ad7192_id, }; module_spi_driver(ad7192_driver); diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index 7dbd6812c24..d215edf66af 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -16,9 +16,9 @@ #include <linux/interrupt.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/events.h> #include "ad7280a.h" @@ -117,7 +117,7 @@ */ #define POLYNOM 0x2F #define POLYNOM_ORDER 8 -#define HIGHBIT 1 << (POLYNOM_ORDER - 1); +#define HIGHBIT (1 << (POLYNOM_ORDER - 1)) struct ad7280_state { struct spi_device *spi; @@ -134,6 +134,8 @@ struct ad7280_state { unsigned char aux_threshhigh; unsigned char aux_threshlow; unsigned char cb_mask[AD7280A_MAX_CHAIN]; + + __be32 buf[2] ____cacheline_aligned; }; static void ad7280_crc8_build_table(unsigned char *crc_tab) @@ -189,26 +191,22 @@ static void ad7280_delay(struct ad7280_state *st) msleep(1); } -static int __ad7280_read32(struct spi_device *spi, unsigned *val) +static int __ad7280_read32(struct ad7280_state *st, unsigned *val) { - unsigned rx_buf, tx_buf = cpu_to_be32(AD7280A_READ_TXVAL); int ret; - struct spi_transfer t = { - .tx_buf = &tx_buf, - .rx_buf = &rx_buf, + .tx_buf = &st->buf[0], + .rx_buf = &st->buf[1], .len = 4, }; - struct spi_message m; - spi_message_init(&m); - spi_message_add_tail(&t, &m); + st->buf[0] = cpu_to_be32(AD7280A_READ_TXVAL); - ret = spi_sync(spi, &m); + ret = spi_sync_transfer(st->spi, &t, 1); if (ret) return ret; - *val = be32_to_cpu(rx_buf); + *val = be32_to_cpu(st->buf[1]); return 0; } @@ -220,9 +218,9 @@ static int ad7280_write(struct ad7280_state *st, unsigned devaddr, (val & 0xFF) << 13 | all << 12); reg |= ad7280_calc_crc8(st->crc_tab, reg >> 11) << 3 | 0x2; - reg = cpu_to_be32(reg); + st->buf[0] = cpu_to_be32(reg); - return spi_write(st->spi, ®, 4); + return spi_write(st->spi, &st->buf[0], 4); } static int ad7280_read(struct ad7280_state *st, unsigned devaddr, @@ -252,7 +250,7 @@ static int ad7280_read(struct ad7280_state *st, unsigned devaddr, if (ret) return ret; - __ad7280_read32(st->spi, &tmp); + __ad7280_read32(st, &tmp); if (ad7280_check_crc(st, tmp)) return -EIO; @@ -290,7 +288,7 @@ static int ad7280_read_channel(struct ad7280_state *st, unsigned devaddr, ad7280_delay(st); - __ad7280_read32(st->spi, &tmp); + __ad7280_read32(st, &tmp); if (ad7280_check_crc(st, tmp)) return -EIO; @@ -323,7 +321,7 @@ static int ad7280_read_all_channels(struct ad7280_state *st, unsigned cnt, ad7280_delay(st); for (i = 0; i < cnt; i++) { - __ad7280_read32(st->spi, &tmp); + __ad7280_read32(st, &tmp); if (ad7280_check_crc(st, tmp)) return -EIO; @@ -366,7 +364,7 @@ static int ad7280_chain_setup(struct ad7280_state *st) return ret; for (n = 0; n <= AD7280A_MAX_CHAIN; n++) { - __ad7280_read32(st->spi, &val); + __ad7280_read32(st, &val); if (val == 0) return n - 1; @@ -384,7 +382,7 @@ static ssize_t ad7280_show_balance_sw(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7280_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); @@ -398,7 +396,7 @@ static ssize_t ad7280_store_balance_sw(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7280_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); bool readin; @@ -429,7 +427,7 @@ static ssize_t ad7280_show_balance_timer(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7280_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; @@ -445,7 +443,7 @@ static ssize_t ad7280_show_balance_timer(struct device *dev, msecs = (ret >> 3) * 71500; - return sprintf(buf, "%d\n", msecs); + return sprintf(buf, "%u\n", msecs); } static ssize_t ad7280_store_balance_timer(struct device *dev, @@ -453,7 +451,7 @@ static ssize_t ad7280_store_balance_timer(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7280_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); unsigned long val; @@ -507,8 +505,10 @@ static int ad7280_channel_init(struct ad7280_state *st) st->channels[cnt].channel = (dev * 6) + ch - 6; } st->channels[cnt].indexed = 1; - st->channels[cnt].info_mask = - IIO_CHAN_INFO_SCALE_SHARED_BIT; + st->channels[cnt].info_mask_separate = + BIT(IIO_CHAN_INFO_RAW); + st->channels[cnt].info_mask_shared_by_type = + BIT(IIO_CHAN_INFO_SCALE); st->channels[cnt].address = AD7280A_DEVADDR(dev) << 8 | ch; st->channels[cnt].scan_index = cnt; @@ -524,7 +524,8 @@ static int ad7280_channel_init(struct ad7280_state *st) st->channels[cnt].channel2 = dev * 6; st->channels[cnt].address = AD7280A_ALL_CELLS; st->channels[cnt].indexed = 1; - st->channels[cnt].info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT; + st->channels[cnt].info_mask_separate = BIT(IIO_CHAN_INFO_RAW); + st->channels[cnt].info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); st->channels[cnt].scan_index = cnt; st->channels[cnt].scan_type.sign = 'u'; st->channels[cnt].scan_type.realbits = 32; @@ -596,7 +597,7 @@ static ssize_t ad7280_read_channel_config(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7280_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); unsigned val; @@ -618,7 +619,7 @@ static ssize_t ad7280_read_channel_config(struct device *dev, return -EINVAL; } - return sprintf(buf, "%d\n", val); + return sprintf(buf, "%u\n", val); } static ssize_t ad7280_write_channel_config(struct device *dev, @@ -626,14 +627,14 @@ static ssize_t ad7280_write_channel_config(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7280_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); long val; int ret; - ret = strict_strtol(buf, 10, &val); + ret = kstrtol(buf, 10, &val); if (ret) return ret; @@ -784,11 +785,10 @@ static int ad7280_read_raw(struct iio_dev *indio_dev, long m) { struct ad7280_state *st = iio_priv(indio_dev); - unsigned int scale_uv; int ret; switch (m) { - case 0: + case IIO_CHAN_INFO_RAW: mutex_lock(&indio_dev->mlock); if (chan->address == AD7280A_ALL_CELLS) ret = ad7280_read_all_channels(st, st->scan_cnt, NULL); @@ -805,13 +805,12 @@ static int ad7280_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: if ((chan->address & 0xFF) <= AD7280A_CELL_VOLTAGE_6) - scale_uv = (4000 * 1000) >> AD7280A_BITS; + *val = 4000; else - scale_uv = (5000 * 1000) >> AD7280A_BITS; + *val = 5000; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; + *val2 = AD7280A_BITS; + return IIO_VAL_FRACTIONAL_LOG2; } return -EINVAL; } @@ -829,15 +828,16 @@ static const struct ad7280_platform_data ad7793_default_pdata = { .thermistor_term_en = true, }; -static int __devinit ad7280_probe(struct spi_device *spi) +static int ad7280_probe(struct spi_device *spi) { const struct ad7280_platform_data *pdata = spi->dev.platform_data; struct ad7280_state *st; int ret; const unsigned short tACQ_ns[4] = {465, 1010, 1460, 1890}; const unsigned short nAVG[4] = {1, 2, 4, 8}; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); + struct iio_dev *indio_dev; + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; @@ -861,7 +861,7 @@ static int __devinit ad7280_probe(struct spi_device *spi) ret = ad7280_chain_setup(st); if (ret < 0) - goto error_free_device; + return ret; st->slave_num = ret; st->scan_cnt = (st->slave_num + 1) * AD7280A_NUM_CH; @@ -892,7 +892,7 @@ static int __devinit ad7280_probe(struct spi_device *spi) ret = ad7280_channel_init(st); if (ret < 0) - goto error_free_device; + return ret; indio_dev->num_channels = ret; indio_dev->channels = st->channels; @@ -941,13 +941,10 @@ error_free_attr: error_free_channels: kfree(st->channels); -error_free_device: - iio_free_device(indio_dev); - return ret; } -static int __devexit ad7280_remove(struct spi_device *spi) +static int ad7280_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad7280_state *st = iio_priv(indio_dev); @@ -961,7 +958,6 @@ static int __devexit ad7280_remove(struct spi_device *spi) kfree(st->channels); kfree(st->iio_attr); - iio_free_device(indio_dev); return 0; } @@ -978,7 +974,7 @@ static struct spi_driver ad7280_driver = { .owner = THIS_MODULE, }, .probe = ad7280_probe, - .remove = __devexit_p(ad7280_remove), + .remove = ad7280_remove, .id_table = ad7280_id, }; module_spi_driver(ad7280_driver); diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c index 0a13616e3db..7194bd13876 100644 --- a/drivers/staging/iio/adc/ad7291.c +++ b/drivers/staging/iio/adc/ad7291.c @@ -17,9 +17,11 @@ #include <linux/regulator/consumer.h> #include <linux/err.h> -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/events.h> + +#include "ad7291.h" /* * Simplified handling @@ -39,33 +41,9 @@ #define AD7291_VOLTAGE 0x01 #define AD7291_T_SENSE 0x02 #define AD7291_T_AVERAGE 0x03 -#define AD7291_CH0_DATA_HIGH 0x04 -#define AD7291_CH0_DATA_LOW 0x05 -#define AD7291_CH0_HYST 0x06 -#define AD7291_CH1_DATA_HIGH 0x07 -#define AD7291_CH1_DATA_LOW 0x08 -#define AD7291_CH1_HYST 0x09 -#define AD7291_CH2_DATA_HIGH 0x0A -#define AD7291_CH2_DATA_LOW 0x0B -#define AD7291_CH2_HYST 0x0C -#define AD7291_CH3_DATA_HIGH 0x0D -#define AD7291_CH3_DATA_LOW 0x0E -#define AD7291_CH3_HYST 0x0F -#define AD7291_CH4_DATA_HIGH 0x10 -#define AD7291_CH4_DATA_LOW 0x11 -#define AD7291_CH4_HYST 0x12 -#define AD7291_CH5_DATA_HIGH 0x13 -#define AD7291_CH5_DATA_LOW 0x14 -#define AD7291_CH5_HYST 0x15 -#define AD7291_CH6_DATA_HIGH 0x16 -#define AD7291_CH6_DATA_LOW 0x17 -#define AD7291_CH6_HYST 0x18 -#define AD7291_CH7_DATA_HIGH 0x19 -#define AD7291_CH7_DATA_LOW 0x1A -#define AD7291_CH7_HYST 0x2B -#define AD7291_T_SENSE_HIGH 0x1C -#define AD7291_T_SENSE_LOW 0x1D -#define AD7291_T_SENSE_HYST 0x1E +#define AD7291_DATA_HIGH(x) ((x) * 3 + 0x4) +#define AD7291_DATA_LOW(x) ((x) * 3 + 0x5) +#define AD7291_HYST(x) ((x) * 3 + 0x6) #define AD7291_VOLTAGE_ALERT_STATUS 0x1F #define AD7291_T_ALERT_STATUS 0x20 @@ -100,7 +78,6 @@ struct ad7291_chip_info { struct i2c_client *client; struct regulator *reg; - u16 int_vref_mv; u16 command; u16 c_mask; /* Active voltage channels for events */ struct mutex state_lock; @@ -111,45 +88,22 @@ static int ad7291_i2c_read(struct ad7291_chip_info *chip, u8 reg, u16 *data) struct i2c_client *client = chip->client; int ret = 0; - ret = i2c_smbus_read_word_data(client, reg); + ret = i2c_smbus_read_word_swapped(client, reg); if (ret < 0) { dev_err(&client->dev, "I2C read error\n"); return ret; } - *data = swab16((u16)ret); + *data = ret; return 0; } static int ad7291_i2c_write(struct ad7291_chip_info *chip, u8 reg, u16 data) { - return i2c_smbus_write_word_data(chip->client, reg, swab16(data)); -} - -static ssize_t ad7291_store_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7291_chip_info *chip = iio_priv(indio_dev); - - return ad7291_i2c_write(chip, AD7291_COMMAND, - chip->command | AD7291_RESET); + return i2c_smbus_write_word_swapped(chip->client, reg, data); } -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, ad7291_store_reset, 0); - -static struct attribute *ad7291_attributes[] = { - &iio_dev_attr_reset.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad7291_attribute_group = { - .attrs = ad7291_attributes, -}; - static irqreturn_t ad7291_event_handler(int irq, void *private) { struct iio_dev *indio_dev = private; @@ -210,183 +164,94 @@ static irqreturn_t ad7291_event_handler(int irq, void *private) return IRQ_HANDLED; } -static inline ssize_t ad7291_show_hyst(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7291_chip_info *chip = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - u16 data; - int ret; - - ret = ad7291_i2c_read(chip, this_attr->address, &data); - if (ret < 0) - return ret; - - return sprintf(buf, "%d\n", data & AD7291_VALUE_MASK); -} - -static inline ssize_t ad7291_set_hyst(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) +static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan, + enum iio_event_direction dir, enum iio_event_info info) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7291_chip_info *chip = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - u16 data; - int ret; - - ret = kstrtou16(buf, 10, &data); - - if (ret < 0) - return ret; - if (data > AD7291_VALUE_MASK) - return -EINVAL; + unsigned int offset; - ret = ad7291_i2c_write(chip, this_attr->address, data); - if (ret < 0) - return ret; + switch (chan->type) { + case IIO_VOLTAGE: + offset = chan->channel; + break; + case IIO_TEMP: + offset = 8; + break; + default: + return 0; + } - return len; + switch (info) { + case IIO_EV_INFO_VALUE: + if (dir == IIO_EV_DIR_FALLING) + return AD7291_DATA_HIGH(offset); + else + return AD7291_DATA_LOW(offset); + case IIO_EV_INFO_HYSTERESIS: + return AD7291_HYST(offset); + default: + break; + } + return 0; } -static IIO_DEVICE_ATTR(in_temp0_thresh_both_hyst_raw, - S_IRUGO | S_IWUSR, - ad7291_show_hyst, ad7291_set_hyst, - AD7291_T_SENSE_HYST); -static IIO_DEVICE_ATTR(in_voltage0_thresh_both_hyst_raw, - S_IRUGO | S_IWUSR, - ad7291_show_hyst, ad7291_set_hyst, AD7291_CH0_HYST); -static IIO_DEVICE_ATTR(in_voltage1_thresh_both_hyst_raw, - S_IRUGO | S_IWUSR, - ad7291_show_hyst, ad7291_set_hyst, AD7291_CH1_HYST); -static IIO_DEVICE_ATTR(in_voltage2_thresh_both_hyst_raw, - S_IRUGO | S_IWUSR, - ad7291_show_hyst, ad7291_set_hyst, AD7291_CH2_HYST); -static IIO_DEVICE_ATTR(in_voltage3_thresh_both_hyst_raw, - S_IRUGO | S_IWUSR, - ad7291_show_hyst, ad7291_set_hyst, AD7291_CH3_HYST); -static IIO_DEVICE_ATTR(in_voltage4_thresh_both_hyst_raw, - S_IRUGO | S_IWUSR, - ad7291_show_hyst, ad7291_set_hyst, AD7291_CH4_HYST); -static IIO_DEVICE_ATTR(in_voltage5_thresh_both_hyst_raw, - S_IRUGO | S_IWUSR, - ad7291_show_hyst, ad7291_set_hyst, AD7291_CH5_HYST); -static IIO_DEVICE_ATTR(in_voltage6_thresh_both_hyst_raw, - S_IRUGO | S_IWUSR, - ad7291_show_hyst, ad7291_set_hyst, AD7291_CH6_HYST); -static IIO_DEVICE_ATTR(in_voltage7_thresh_both_hyst_raw, - S_IRUGO | S_IWUSR, - ad7291_show_hyst, ad7291_set_hyst, AD7291_CH7_HYST); - -static struct attribute *ad7291_event_attributes[] = { - &iio_dev_attr_in_temp0_thresh_both_hyst_raw.dev_attr.attr, - &iio_dev_attr_in_voltage0_thresh_both_hyst_raw.dev_attr.attr, - &iio_dev_attr_in_voltage1_thresh_both_hyst_raw.dev_attr.attr, - &iio_dev_attr_in_voltage2_thresh_both_hyst_raw.dev_attr.attr, - &iio_dev_attr_in_voltage3_thresh_both_hyst_raw.dev_attr.attr, - &iio_dev_attr_in_voltage4_thresh_both_hyst_raw.dev_attr.attr, - &iio_dev_attr_in_voltage5_thresh_both_hyst_raw.dev_attr.attr, - &iio_dev_attr_in_voltage6_thresh_both_hyst_raw.dev_attr.attr, - &iio_dev_attr_in_voltage7_thresh_both_hyst_raw.dev_attr.attr, - NULL, -}; - -/* high / low */ -static u8 ad7291_limit_regs[9][2] = { - { AD7291_CH0_DATA_HIGH, AD7291_CH0_DATA_LOW }, - { AD7291_CH1_DATA_HIGH, AD7291_CH1_DATA_LOW }, - { AD7291_CH2_DATA_HIGH, AD7291_CH2_DATA_LOW }, - { AD7291_CH3_DATA_HIGH, AD7291_CH3_DATA_LOW }, /* FIXME: ? */ - { AD7291_CH4_DATA_HIGH, AD7291_CH4_DATA_LOW }, - { AD7291_CH5_DATA_HIGH, AD7291_CH5_DATA_LOW }, - { AD7291_CH6_DATA_HIGH, AD7291_CH6_DATA_LOW }, - { AD7291_CH7_DATA_HIGH, AD7291_CH7_DATA_LOW }, - /* temp */ - { AD7291_T_SENSE_HIGH, AD7291_T_SENSE_LOW }, -}; - static int ad7291_read_event_value(struct iio_dev *indio_dev, - u64 event_code, - int *val) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) { struct ad7291_chip_info *chip = iio_priv(indio_dev); - int ret; - u8 reg; u16 uval; - s16 signval; - switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { - case IIO_VOLTAGE: - reg = ad7291_limit_regs[IIO_EVENT_CODE_EXTRACT_NUM(event_code)] - [!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_RISING)]; + ret = ad7291_i2c_read(chip, ad7291_threshold_reg(chan, dir, info), + &uval); + if (ret < 0) + return ret; - ret = ad7291_i2c_read(chip, reg, &uval); - if (ret < 0) - return ret; + if (info == IIO_EV_INFO_HYSTERESIS || chan->type == IIO_VOLTAGE) *val = uval & AD7291_VALUE_MASK; - return 0; - case IIO_TEMP: - reg = ad7291_limit_regs[8] - [!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_RISING)]; + else + *val = sign_extend32(uval, 11); - ret = ad7291_i2c_read(chip, reg, &signval); - if (ret < 0) - return ret; - signval = (s16)((signval & AD7291_VALUE_MASK) << 4) >> 4; - *val = signval; - return 0; - default: - return -EINVAL; - }; + return IIO_VAL_INT; } static int ad7291_write_event_value(struct iio_dev *indio_dev, - u64 event_code, - int val) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) { struct ad7291_chip_info *chip = iio_priv(indio_dev); - u8 reg; - s16 signval; - switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { - case IIO_VOLTAGE: + if (info == IIO_EV_INFO_HYSTERESIS || chan->type == IIO_VOLTAGE) { if (val > AD7291_VALUE_MASK || val < 0) return -EINVAL; - reg = ad7291_limit_regs[IIO_EVENT_CODE_EXTRACT_NUM(event_code)] - [!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_RISING)]; - return ad7291_i2c_write(chip, reg, val); - case IIO_TEMP: + } else { if (val > 2047 || val < -2048) return -EINVAL; - reg = ad7291_limit_regs[8] - [!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_RISING)]; - signval = val; - return ad7291_i2c_write(chip, reg, *(u16 *)&signval); - default: - return -EINVAL; - }; + } + + return ad7291_i2c_write(chip, ad7291_threshold_reg(chan, dir, info), + val); } static int ad7291_read_event_config(struct iio_dev *indio_dev, - u64 event_code) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) { struct ad7291_chip_info *chip = iio_priv(indio_dev); /* To be enabled the channel must simply be on. If any are enabled we are in continuous sampling mode */ - switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { + switch (chan->type) { case IIO_VOLTAGE: - if (chip->c_mask & - (1 << (15 - IIO_EVENT_CODE_EXTRACT_NUM(event_code)))) + if (chip->c_mask & (1 << (15 - chan->channel))) return 1; else return 0; @@ -400,11 +265,14 @@ static int ad7291_read_event_config(struct iio_dev *indio_dev, } static int ad7291_write_event_config(struct iio_dev *indio_dev, - u64 event_code, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, int state) { int ret = 0; struct ad7291_chip_info *chip = iio_priv(indio_dev); + unsigned int mask; u16 regval; mutex_lock(&chip->state_lock); @@ -415,16 +283,14 @@ static int ad7291_write_event_config(struct iio_dev *indio_dev, * Possible to disable temp as well but that makes single read tricky. */ - switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) { + mask = BIT(15 - chan->channel); + + switch (chan->type) { case IIO_VOLTAGE: - if ((!state) && (chip->c_mask & (1 << (15 - - IIO_EVENT_CODE_EXTRACT_NUM(event_code))))) - chip->c_mask &= ~(1 << (15 - IIO_EVENT_CODE_EXTRACT_NUM - (event_code))); - else if (state && (!(chip->c_mask & (1 << (15 - - IIO_EVENT_CODE_EXTRACT_NUM(event_code)))))) - chip->c_mask |= (1 << (15 - IIO_EVENT_CODE_EXTRACT_NUM - (event_code))); + if ((!state) && (chip->c_mask & mask)) + chip->c_mask &= ~mask; + else if (state && (!(chip->c_mask & mask))) + chip->c_mask |= mask; else break; @@ -456,12 +322,10 @@ static int ad7291_read_raw(struct iio_dev *indio_dev, { int ret; struct ad7291_chip_info *chip = iio_priv(indio_dev); - unsigned int scale_uv; u16 regval; - s16 signval; switch (mask) { - case 0: + case IIO_CHAN_INFO_RAW: switch (chan->type) { case IIO_VOLTAGE: mutex_lock(&chip->state_lock); @@ -479,44 +343,47 @@ static int ad7291_read_raw(struct iio_dev *indio_dev, return ret; } /* Read voltage */ - ret = i2c_smbus_read_word_data(chip->client, + ret = i2c_smbus_read_word_swapped(chip->client, AD7291_VOLTAGE); if (ret < 0) { mutex_unlock(&chip->state_lock); return ret; } - *val = swab16((u16)ret) & AD7291_VALUE_MASK; + *val = ret & AD7291_VALUE_MASK; mutex_unlock(&chip->state_lock); return IIO_VAL_INT; case IIO_TEMP: /* Assumes tsense bit of command register always set */ - ret = i2c_smbus_read_word_data(chip->client, + ret = i2c_smbus_read_word_swapped(chip->client, AD7291_T_SENSE); if (ret < 0) return ret; - signval = (s16)((swab16((u16)ret) & - AD7291_VALUE_MASK) << 4) >> 4; - *val = signval; + *val = sign_extend32(ret, 11); return IIO_VAL_INT; default: return -EINVAL; } case IIO_CHAN_INFO_AVERAGE_RAW: - ret = i2c_smbus_read_word_data(chip->client, + ret = i2c_smbus_read_word_swapped(chip->client, AD7291_T_AVERAGE); if (ret < 0) return ret; - signval = (s16)((swab16((u16)ret) & - AD7291_VALUE_MASK) << 4) >> 4; - *val = signval; + *val = sign_extend32(ret, 11); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: - scale_uv = (chip->int_vref_mv * 1000) >> AD7291_BITS; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; + if (chip->reg) { + int vref; + vref = regulator_get_voltage(chip->reg); + if (vref < 0) + return vref; + *val = vref / 1000; + } else { + *val = 2500; + } + *val2 = AD7291_BITS; + return IIO_VAL_FRACTIONAL_LOG2; case IIO_TEMP: /* * One LSB of the ADC corresponds to 0.25 deg C. @@ -533,14 +400,33 @@ static int ad7291_read_raw(struct iio_dev *indio_dev, } } +static const struct iio_event_spec ad7291_events[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_HYSTERESIS), + }, +}; + #define AD7291_VOLTAGE_CHAN(_chan) \ { \ .type = IIO_VOLTAGE, \ - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ .indexed = 1, \ .channel = _chan, \ - .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING)|\ - IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING) \ + .event_spec = ad7291_events, \ + .num_event_specs = ARRAY_SIZE(ad7291_events), \ } static const struct iio_chan_spec ad7291_channels[] = { @@ -554,50 +440,46 @@ static const struct iio_chan_spec ad7291_channels[] = { AD7291_VOLTAGE_CHAN(7), { .type = IIO_TEMP, - .info_mask = IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_AVERAGE_RAW) | + BIT(IIO_CHAN_INFO_SCALE), .indexed = 1, .channel = 0, - .event_mask = - IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING)| - IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING) + .event_spec = ad7291_events, + .num_event_specs = ARRAY_SIZE(ad7291_events), } }; -static struct attribute_group ad7291_event_attribute_group = { - .attrs = ad7291_event_attributes, -}; - static const struct iio_info ad7291_info = { - .attrs = &ad7291_attribute_group, .read_raw = &ad7291_read_raw, .read_event_config = &ad7291_read_event_config, .write_event_config = &ad7291_write_event_config, .read_event_value = &ad7291_read_event_value, .write_event_value = &ad7291_write_event_value, - .event_attrs = &ad7291_event_attribute_group, + .driver_module = THIS_MODULE, }; -static int __devinit ad7291_probe(struct i2c_client *client, +static int ad7291_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct ad7291_platform_data *pdata = client->dev.platform_data; struct ad7291_chip_info *chip; struct iio_dev *indio_dev; - int ret = 0, voltage_uv = 0; + int ret; - indio_dev = iio_allocate_device(sizeof(*chip)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); + if (!indio_dev) + return -ENOMEM; chip = iio_priv(indio_dev); - chip->reg = regulator_get(&client->dev, "vcc"); - if (!IS_ERR(chip->reg)) { + if (pdata && pdata->use_external_ref) { + chip->reg = devm_regulator_get(&client->dev, "vref"); + if (IS_ERR(chip->reg)) + return PTR_ERR(chip->reg); + ret = regulator_enable(chip->reg); if (ret) - goto error_put_reg; - voltage_uv = regulator_get_voltage(chip->reg); + return ret; } mutex_init(&chip->state_lock); @@ -610,12 +492,8 @@ static int __devinit ad7291_probe(struct i2c_client *client, AD7291_T_SENSE_MASK | /* Tsense always enabled */ AD7291_ALERT_POLARITY; /* set irq polarity low level */ - if (voltage_uv) { - chip->int_vref_mv = voltage_uv / 1000; + if (pdata && pdata->use_external_ref) chip->command |= AD7291_EXT_REF; - } else { - chip->int_vref_mv = 2500; /* Build-in ref */ - } indio_dev->name = id->name; indio_dev->channels = ad7291_channels; @@ -652,27 +530,19 @@ static int __devinit ad7291_probe(struct i2c_client *client, if (ret) goto error_unreg_irq; - dev_info(&client->dev, "%s ADC registered.\n", - id->name); - return 0; error_unreg_irq: if (client->irq) free_irq(client->irq, indio_dev); error_disable_reg: - if (!IS_ERR(chip->reg)) + if (chip->reg) regulator_disable(chip->reg); -error_put_reg: - if (!IS_ERR(chip->reg)) - regulator_put(chip->reg); - iio_free_device(indio_dev); -error_ret: return ret; } -static int __devexit ad7291_remove(struct i2c_client *client) +static int ad7291_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); struct ad7291_chip_info *chip = iio_priv(indio_dev); @@ -682,12 +552,8 @@ static int __devexit ad7291_remove(struct i2c_client *client) if (client->irq) free_irq(client->irq, indio_dev); - if (!IS_ERR(chip->reg)) { + if (chip->reg) regulator_disable(chip->reg); - regulator_put(chip->reg); - } - - iio_free_device(indio_dev); return 0; } @@ -704,7 +570,7 @@ static struct i2c_driver ad7291_driver = { .name = KBUILD_MODNAME, }, .probe = ad7291_probe, - .remove = __devexit_p(ad7291_remove), + .remove = ad7291_remove, .id_table = ad7291_id, }; module_i2c_driver(ad7291_driver); diff --git a/drivers/staging/iio/adc/ad7291.h b/drivers/staging/iio/adc/ad7291.h new file mode 100644 index 00000000000..bbd89fa5118 --- /dev/null +++ b/drivers/staging/iio/adc/ad7291.h @@ -0,0 +1,12 @@ +#ifndef __IIO_AD7291_H__ +#define __IIO_AD7291_H__ + +/** + * struct ad7291_platform_data - AD7291 platform data + * @use_external_ref: Whether to use an external or internal reference voltage + */ +struct ad7291_platform_data { + bool use_external_ref; +}; + +#endif diff --git a/drivers/staging/iio/adc/ad7298.h b/drivers/staging/iio/adc/ad7298.h deleted file mode 100644 index a0e5dea415e..00000000000 --- a/drivers/staging/iio/adc/ad7298.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * AD7298 SPI ADC driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#ifndef IIO_ADC_AD7298_H_ -#define IIO_ADC_AD7298_H_ - -#define AD7298_WRITE (1 << 15) /* write to the control register */ -#define AD7298_REPEAT (1 << 14) /* repeated conversion enable */ -#define AD7298_CH(x) (1 << (13 - (x))) /* channel select */ -#define AD7298_TSENSE (1 << 5) /* temperature conversion enable */ -#define AD7298_EXTREF (1 << 2) /* external reference enable */ -#define AD7298_TAVG (1 << 1) /* temperature sensor averaging enable */ -#define AD7298_PDD (1 << 0) /* partial power down enable */ - -#define AD7298_MAX_CHAN 8 -#define AD7298_BITS 12 -#define AD7298_STORAGE_BITS 16 -#define AD7298_INTREF_mV 2500 - -#define AD7298_CH_TEMP 9 - -#define RES_MASK(bits) ((1 << (bits)) - 1) - -/* - * TODO: struct ad7298_platform_data needs to go into include/linux/iio - */ - -struct ad7298_platform_data { - /* External Vref voltage applied */ - u16 vref_mv; -}; - -struct ad7298_state { - struct spi_device *spi; - struct regulator *reg; - size_t d_size; - u16 int_vref_mv; - unsigned ext_ref; - struct spi_transfer ring_xfer[10]; - struct spi_transfer scan_single_xfer[3]; - struct spi_message ring_msg; - struct spi_message scan_single_msg; - /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - */ - unsigned short rx_buf[8] ____cacheline_aligned; - unsigned short tx_buf[2]; -}; - -#ifdef CONFIG_IIO_BUFFER -int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev); -void ad7298_ring_cleanup(struct iio_dev *indio_dev); -#else /* CONFIG_IIO_BUFFER */ - -static inline int -ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline void ad7298_ring_cleanup(struct iio_dev *indio_dev) -{ -} -#endif /* CONFIG_IIO_BUFFER */ -#endif /* IIO_ADC_AD7298_H_ */ diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/staging/iio/adc/ad7298_core.c deleted file mode 100644 index 8dd6aa9cf92..00000000000 --- a/drivers/staging/iio/adc/ad7298_core.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * AD7298 SPI ADC driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/spi/spi.h> -#include <linux/regulator/consumer.h> -#include <linux/err.h> -#include <linux/delay.h> -#include <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" - -#include "ad7298.h" - -static struct iio_chan_spec ad7298_channels[] = { - IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - 9, AD7298_CH_TEMP, IIO_ST('s', 32, 32, 0), 0), - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 0, 0, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 1, 1, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 2, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 2, 2, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 3, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 3, 3, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 4, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 4, 4, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 5, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 5, 5, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 6, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 6, 6, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 7, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 7, 7, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN_SOFT_TIMESTAMP(8), -}; - -static int ad7298_scan_direct(struct ad7298_state *st, unsigned ch) -{ - int ret; - st->tx_buf[0] = cpu_to_be16(AD7298_WRITE | st->ext_ref | - (AD7298_CH(0) >> ch)); - - ret = spi_sync(st->spi, &st->scan_single_msg); - if (ret) - return ret; - - return be16_to_cpu(st->rx_buf[0]); -} - -static int ad7298_scan_temp(struct ad7298_state *st, int *val) -{ - int tmp, ret; - __be16 buf; - - buf = cpu_to_be16(AD7298_WRITE | AD7298_TSENSE | - AD7298_TAVG | st->ext_ref); - - ret = spi_write(st->spi, (u8 *)&buf, 2); - if (ret) - return ret; - - buf = cpu_to_be16(0); - - ret = spi_write(st->spi, (u8 *)&buf, 2); - if (ret) - return ret; - - usleep_range(101, 1000); /* sleep > 100us */ - - ret = spi_read(st->spi, (u8 *)&buf, 2); - if (ret) - return ret; - - tmp = be16_to_cpu(buf) & RES_MASK(AD7298_BITS); - - /* - * One LSB of the ADC corresponds to 0.25 deg C. - * The temperature reading is in 12-bit twos complement format - */ - - if (tmp & (1 << (AD7298_BITS - 1))) { - tmp = (4096 - tmp) * 250; - tmp -= (2 * tmp); - - } else { - tmp *= 250; /* temperature in milli degrees Celsius */ - } - - *val = tmp; - - return 0; -} - -static int ad7298_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - int ret; - struct ad7298_state *st = iio_priv(indio_dev); - unsigned int scale_uv; - - switch (m) { - case 0: - mutex_lock(&indio_dev->mlock); - if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { - ret = -EBUSY; - } else { - if (chan->address == AD7298_CH_TEMP) - ret = ad7298_scan_temp(st, val); - else - ret = ad7298_scan_direct(st, chan->address); - } - mutex_unlock(&indio_dev->mlock); - - if (ret < 0) - return ret; - - if (chan->address != AD7298_CH_TEMP) - *val = ret & RES_MASK(AD7298_BITS); - - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_VOLTAGE: - scale_uv = (st->int_vref_mv * 1000) >> AD7298_BITS; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_TEMP: - *val = 1; - *val2 = 0; - return IIO_VAL_INT_PLUS_MICRO; - default: - return -EINVAL; - } - } - return -EINVAL; -} - -static const struct iio_info ad7298_info = { - .read_raw = &ad7298_read_raw, - .driver_module = THIS_MODULE, -}; - -static int __devinit ad7298_probe(struct spi_device *spi) -{ - struct ad7298_platform_data *pdata = spi->dev.platform_data; - struct ad7298_state *st; - int ret; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); - - if (indio_dev == NULL) - return -ENOMEM; - - st = iio_priv(indio_dev); - - st->reg = regulator_get(&spi->dev, "vcc"); - if (!IS_ERR(st->reg)) { - ret = regulator_enable(st->reg); - if (ret) - goto error_put_reg; - } - - spi_set_drvdata(spi, indio_dev); - - st->spi = spi; - - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = ad7298_channels; - indio_dev->num_channels = ARRAY_SIZE(ad7298_channels); - indio_dev->info = &ad7298_info; - - /* Setup default message */ - - st->scan_single_xfer[0].tx_buf = &st->tx_buf[0]; - st->scan_single_xfer[0].len = 2; - st->scan_single_xfer[0].cs_change = 1; - st->scan_single_xfer[1].tx_buf = &st->tx_buf[1]; - st->scan_single_xfer[1].len = 2; - st->scan_single_xfer[1].cs_change = 1; - st->scan_single_xfer[2].rx_buf = &st->rx_buf[0]; - st->scan_single_xfer[2].len = 2; - - spi_message_init(&st->scan_single_msg); - spi_message_add_tail(&st->scan_single_xfer[0], &st->scan_single_msg); - spi_message_add_tail(&st->scan_single_xfer[1], &st->scan_single_msg); - spi_message_add_tail(&st->scan_single_xfer[2], &st->scan_single_msg); - - if (pdata && pdata->vref_mv) { - st->int_vref_mv = pdata->vref_mv; - st->ext_ref = AD7298_EXTREF; - } else { - st->int_vref_mv = AD7298_INTREF_mV; - } - - ret = ad7298_register_ring_funcs_and_init(indio_dev); - if (ret) - goto error_disable_reg; - - ret = iio_buffer_register(indio_dev, - &ad7298_channels[1], /* skip temp0 */ - ARRAY_SIZE(ad7298_channels) - 1); - if (ret) - goto error_cleanup_ring; - ret = iio_device_register(indio_dev); - if (ret) - goto error_unregister_ring; - - return 0; - -error_unregister_ring: - iio_buffer_unregister(indio_dev); -error_cleanup_ring: - ad7298_ring_cleanup(indio_dev); -error_disable_reg: - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); -error_put_reg: - if (!IS_ERR(st->reg)) - regulator_put(st->reg); - iio_free_device(indio_dev); - - return ret; -} - -static int __devexit ad7298_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad7298_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); - ad7298_ring_cleanup(indio_dev); - if (!IS_ERR(st->reg)) { - regulator_disable(st->reg); - regulator_put(st->reg); - } - iio_free_device(indio_dev); - - return 0; -} - -static const struct spi_device_id ad7298_id[] = { - {"ad7298", 0}, - {} -}; -MODULE_DEVICE_TABLE(spi, ad7298_id); - -static struct spi_driver ad7298_driver = { - .driver = { - .name = "ad7298", - .owner = THIS_MODULE, - }, - .probe = ad7298_probe, - .remove = __devexit_p(ad7298_remove), - .id_table = ad7298_id, -}; -module_spi_driver(ad7298_driver); - -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("Analog Devices AD7298 ADC"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c deleted file mode 100644 index d1a12dd015e..00000000000 --- a/drivers/staging/iio/adc/ad7298_ring.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * AD7298 SPI ADC driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/spi/spi.h> - -#include "../iio.h" -#include "../buffer.h" -#include "../ring_sw.h" -#include "../trigger_consumer.h" - -#include "ad7298.h" - -/** - * ad7298_ring_preenable() setup the parameters of the ring before enabling - * - * The complex nature of the setting of the number of bytes per datum is due - * to this driver currently ensuring that the timestamp is stored at an 8 - * byte boundary. - **/ -static int ad7298_ring_preenable(struct iio_dev *indio_dev) -{ - struct ad7298_state *st = iio_priv(indio_dev); - struct iio_buffer *ring = indio_dev->buffer; - size_t d_size; - int i, m; - unsigned short command; - int scan_count = bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength); - d_size = scan_count * (AD7298_STORAGE_BITS / 8); - - if (ring->scan_timestamp) { - d_size += sizeof(s64); - - if (d_size % sizeof(s64)) - d_size += sizeof(s64) - (d_size % sizeof(s64)); - } - - if (ring->access->set_bytes_per_datum) - ring->access->set_bytes_per_datum(ring, d_size); - - st->d_size = d_size; - - command = AD7298_WRITE | st->ext_ref; - - for (i = 0, m = AD7298_CH(0); i < AD7298_MAX_CHAN; i++, m >>= 1) - if (test_bit(i, indio_dev->active_scan_mask)) - command |= m; - - st->tx_buf[0] = cpu_to_be16(command); - - /* build spi ring message */ - st->ring_xfer[0].tx_buf = &st->tx_buf[0]; - st->ring_xfer[0].len = 2; - st->ring_xfer[0].cs_change = 1; - st->ring_xfer[1].tx_buf = &st->tx_buf[1]; - st->ring_xfer[1].len = 2; - st->ring_xfer[1].cs_change = 1; - - spi_message_init(&st->ring_msg); - spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg); - spi_message_add_tail(&st->ring_xfer[1], &st->ring_msg); - - for (i = 0; i < scan_count; i++) { - st->ring_xfer[i + 2].rx_buf = &st->rx_buf[i]; - st->ring_xfer[i + 2].len = 2; - st->ring_xfer[i + 2].cs_change = 1; - spi_message_add_tail(&st->ring_xfer[i + 2], &st->ring_msg); - } - /* make sure last transfer cs_change is not set */ - st->ring_xfer[i + 1].cs_change = 0; - - return 0; -} - -/** - * ad7298_trigger_handler() bh of trigger launched polling to ring buffer - * - * Currently there is no option in this driver to disable the saving of - * timestamps within the ring. - **/ -static irqreturn_t ad7298_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct ad7298_state *st = iio_priv(indio_dev); - struct iio_buffer *ring = indio_dev->buffer; - s64 time_ns; - __u16 buf[16]; - int b_sent, i; - - b_sent = spi_sync(st->spi, &st->ring_msg); - if (b_sent) - return b_sent; - - if (ring->scan_timestamp) { - time_ns = iio_get_time_ns(); - memcpy((u8 *)buf + st->d_size - sizeof(s64), - &time_ns, sizeof(time_ns)); - } - - for (i = 0; i < bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength); i++) - buf[i] = be16_to_cpu(st->rx_buf[i]); - - indio_dev->buffer->access->store_to(ring, (u8 *)buf, time_ns); - iio_trigger_notify_done(indio_dev->trig); - - return IRQ_HANDLED; -} - -static const struct iio_buffer_setup_ops ad7298_ring_setup_ops = { - .preenable = &ad7298_ring_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, -}; - -int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev) -{ - int ret; - - indio_dev->buffer = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->buffer) { - ret = -ENOMEM; - goto error_ret; - } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; - - indio_dev->pollfunc = iio_alloc_pollfunc(NULL, - &ad7298_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "ad7298_consumer%d", - indio_dev->id); - - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_deallocate_sw_rb; - } - - /* Ring buffer functions - here trigger setup related */ - indio_dev->setup_ops = &ad7298_ring_setup_ops; - indio_dev->buffer->scan_timestamp = true; - - /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_deallocate_sw_rb: - iio_sw_rb_free(indio_dev->buffer); -error_ret: - return ret; -} - -void ad7298_ring_cleanup(struct iio_dev *indio_dev) -{ - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->buffer); -} diff --git a/drivers/staging/iio/adc/ad7476.h b/drivers/staging/iio/adc/ad7476.h deleted file mode 100644 index 27f696c75cc..00000000000 --- a/drivers/staging/iio/adc/ad7476.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 { - u16 int_vref_mv; - struct iio_chan_spec channel[2]; -}; - -struct ad7476_state { - struct spi_device *spi; - const struct ad7476_chip_info *chip_info; - struct regulator *reg; - size_t d_size; - 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_BUFFER -int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev); -void ad7476_ring_cleanup(struct iio_dev *indio_dev); -#else /* CONFIG_IIO_BUFFER */ - -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_BUFFER */ -#endif /* IIO_ADC_AD7476_H_ */ diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c deleted file mode 100644 index 0c064d1c392..00000000000 --- a/drivers/staging/iio/adc/ad7476_core.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * 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/device.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/spi/spi.h> -#include <linux/regulator/consumer.h> -#include <linux/err.h> -#include <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.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 int ad7476_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - int ret; - struct ad7476_state *st = iio_priv(indio_dev); - unsigned int scale_uv; - - switch (m) { - case 0: - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) - ret = -EBUSY; - else - ret = ad7476_scan_direct(st); - mutex_unlock(&indio_dev->mlock); - - if (ret < 0) - return ret; - *val = (ret >> st->chip_info->channel[0].scan_type.shift) & - RES_MASK(st->chip_info->channel[0].scan_type.realbits); - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - scale_uv = (st->int_vref_mv * 1000) - >> st->chip_info->channel[0].scan_type.realbits; - *val = scale_uv/1000; - *val2 = (scale_uv%1000)*1000; - return IIO_VAL_INT_PLUS_MICRO; - } - return -EINVAL; -} - -static const struct ad7476_chip_info ad7476_chip_info_tbl[] = { - [ID_AD7466] = { - .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 0, 0, IIO_ST('u', 12, 16, 0), 0), - .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), - }, - [ID_AD7467] = { - .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 0, 0, IIO_ST('u', 10, 16, 2), 0), - .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), - }, - [ID_AD7468] = { - .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1 , 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 0, 0, IIO_ST('u', 8, 16, 4), 0), - .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), - }, - [ID_AD7475] = { - .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 0, 0, IIO_ST('u', 12, 16, 0), 0), - .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), - }, - [ID_AD7476] = { - .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 0, 0, IIO_ST('u', 12, 16, 0), 0), - .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), - }, - [ID_AD7477] = { - .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 0, 0, IIO_ST('u', 10, 16, 2), 0), - .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), - }, - [ID_AD7478] = { - .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 0, 0, IIO_ST('u', 8, 16, 4), 0), - .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), - }, - [ID_AD7495] = { - .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 0, 0, IIO_ST('u', 12, 16, 0), 0), - .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), - .int_vref_mv = 2500, - }, -}; - -static const struct iio_info ad7476_info = { - .driver_module = THIS_MODULE, - .read_raw = &ad7476_read_raw, -}; - -static int __devinit ad7476_probe(struct spi_device *spi) -{ - struct ad7476_platform_data *pdata = spi->dev.platform_data; - struct ad7476_state *st; - struct iio_dev *indio_dev; - int ret, voltage_uv = 0; - - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - st = iio_priv(indio_dev); - st->reg = regulator_get(&spi->dev, "vcc"); - if (!IS_ERR(st->reg)) { - ret = regulator_enable(st->reg); - if (ret) - goto error_put_reg; - - voltage_uv = regulator_get_voltage(st->reg); - } - st->chip_info = - &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, indio_dev); - - st->spi = spi; - - /* Establish that the iio_dev is a child of the spi device */ - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = st->chip_info->channel; - indio_dev->num_channels = 2; - indio_dev->info = &ad7476_info; - /* Setup default message */ - - st->xfer.rx_buf = &st->data; - st->xfer.len = st->chip_info->channel[0].scan_type.storagebits / 8; - - spi_message_init(&st->msg); - spi_message_add_tail(&st->xfer, &st->msg); - - ret = ad7476_register_ring_funcs_and_init(indio_dev); - if (ret) - goto error_disable_reg; - - ret = iio_buffer_register(indio_dev, - st->chip_info->channel, - ARRAY_SIZE(st->chip_info->channel)); - if (ret) - goto error_cleanup_ring; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_ring_unregister; - return 0; - -error_ring_unregister: - iio_buffer_unregister(indio_dev); -error_cleanup_ring: - ad7476_ring_cleanup(indio_dev); -error_disable_reg: - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); -error_put_reg: - if (!IS_ERR(st->reg)) - regulator_put(st->reg); - iio_free_device(indio_dev); - -error_ret: - return ret; -} - -static int ad7476_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad7476_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); - ad7476_ring_cleanup(indio_dev); - if (!IS_ERR(st->reg)) { - regulator_disable(st->reg); - regulator_put(st->reg); - } - iio_free_device(indio_dev); - - 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}, - {} -}; -MODULE_DEVICE_TABLE(spi, ad7476_id); - -static struct spi_driver ad7476_driver = { - .driver = { - .name = "ad7476", - .owner = THIS_MODULE, - }, - .probe = ad7476_probe, - .remove = __devexit_p(ad7476_remove), - .id_table = ad7476_id, -}; -module_spi_driver(ad7476_driver); - -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"); diff --git a/drivers/staging/iio/adc/ad7476_ring.c b/drivers/staging/iio/adc/ad7476_ring.c deleted file mode 100644 index 4e298b2a05b..00000000000 --- a/drivers/staging/iio/adc/ad7476_ring.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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/device.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/spi/spi.h> - -#include "../iio.h" -#include "../buffer.h" -#include "../ring_sw.h" -#include "../trigger_consumer.h" - -#include "ad7476.h" - -/** - * 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 = iio_priv(indio_dev); - struct iio_buffer *ring = indio_dev->buffer; - - st->d_size = bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength) * - st->chip_info->channel[0].scan_type.storagebits / 8; - - if (ring->scan_timestamp) { - st->d_size += sizeof(s64); - - if (st->d_size % sizeof(s64)) - st->d_size += sizeof(s64) - (st->d_size % sizeof(s64)); - } - - if (indio_dev->buffer->access->set_bytes_per_datum) - indio_dev->buffer->access-> - set_bytes_per_datum(indio_dev->buffer, st->d_size); - - return 0; -} - -static irqreturn_t ad7476_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct ad7476_state *st = iio_priv(indio_dev); - s64 time_ns; - __u8 *rxbuf; - int b_sent; - - rxbuf = kzalloc(st->d_size, GFP_KERNEL); - if (rxbuf == NULL) - return -ENOMEM; - - b_sent = spi_read(st->spi, rxbuf, - st->chip_info->channel[0].scan_type.storagebits / 8); - if (b_sent < 0) - goto done; - - time_ns = iio_get_time_ns(); - - if (indio_dev->buffer->scan_timestamp) - memcpy(rxbuf + st->d_size - sizeof(s64), - &time_ns, sizeof(time_ns)); - - indio_dev->buffer->access->store_to(indio_dev->buffer, rxbuf, time_ns); -done: - iio_trigger_notify_done(indio_dev->trig); - kfree(rxbuf); - - return IRQ_HANDLED; -} - -static const struct iio_buffer_setup_ops ad7476_ring_setup_ops = { - .preenable = &ad7476_ring_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, -}; - -int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev) -{ - struct ad7476_state *st = iio_priv(indio_dev); - int ret = 0; - - indio_dev->buffer = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->buffer) { - ret = -ENOMEM; - goto error_ret; - } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; - indio_dev->pollfunc - = iio_alloc_pollfunc(NULL, - &ad7476_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "%s_consumer%d", - spi_get_device_id(st->spi)->name, - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_deallocate_sw_rb; - } - - /* Ring buffer functions - here trigger setup related */ - indio_dev->setup_ops = &ad7476_ring_setup_ops; - indio_dev->buffer->scan_timestamp = true; - - /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_deallocate_sw_rb: - iio_sw_rb_free(indio_dev->buffer); -error_ret: - return ret; -} - -void ad7476_ring_cleanup(struct iio_dev *indio_dev) -{ - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->buffer); -} diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h index 10f59896597..ec89d055cf5 100644 --- a/drivers/staging/iio/adc/ad7606.h +++ b/drivers/staging/iio/adc/ad7606.h @@ -14,7 +14,7 @@ */ /** - * struct ad7606_platform_data - platform/board specifc information + * struct ad7606_platform_data - platform/board specific information * @default_os: default oversampling value {0, 2, 4, 8, 16, 32, 64} * @default_range: default range +/-{5000, 10000} mVolt * @gpio_convst: number of gpio connected to the CONVST pin @@ -41,8 +41,8 @@ struct ad7606_platform_data { }; /** - * struct ad7606_chip_info - chip specifc information - * @name: indentification string for chip + * struct ad7606_chip_info - chip specific information + * @name: identification string for chip * @int_vref_mv: the internal reference voltage * @channels: channel specification * @num_channels: number of channels @@ -51,7 +51,7 @@ struct ad7606_platform_data { struct ad7606_chip_info { const char *name; u16 int_vref_mv; - struct iio_chan_spec *channels; + const struct iio_chan_spec *channels; unsigned num_channels; }; diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index ddb7ef92f5c..f0f05f195d2 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -18,9 +18,9 @@ #include <linux/sched.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> #include "ad7606.h" @@ -85,10 +85,9 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, { int ret; struct ad7606_state *st = iio_priv(indio_dev); - unsigned int scale_uv; switch (m) { - case 0: + case IIO_CHAN_INFO_RAW: mutex_lock(&indio_dev->mlock); if (iio_buffer_enabled(indio_dev)) ret = -EBUSY; @@ -101,11 +100,9 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, *val = (short) ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - scale_uv = (st->range * 1000 * 2) - >> st->chip_info->channels[0].scan_type.realbits; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; + *val = st->range * 2; + *val2 = st->chip_info->channels[0].scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; } return -EINVAL; } @@ -113,7 +110,7 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, static ssize_t ad7606_show_range(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7606_state *st = iio_priv(indio_dev); return sprintf(buf, "%u\n", st->range); @@ -122,12 +119,15 @@ static ssize_t ad7606_show_range(struct device *dev, static ssize_t ad7606_store_range(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7606_state *st = iio_priv(indio_dev); unsigned long lval; + int ret; + + ret = kstrtoul(buf, 10, &lval); + if (ret) + return ret; - if (strict_strtoul(buf, 10, &lval)) - return -EINVAL; if (!(lval == 5000 || lval == 10000)) { dev_err(dev, "range is not supported\n"); return -EINVAL; @@ -147,7 +147,7 @@ static IIO_CONST_ATTR(in_voltage_range_available, "5000 10000"); static ssize_t ad7606_show_oversampling_ratio(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7606_state *st = iio_priv(indio_dev); return sprintf(buf, "%u\n", st->oversampling); @@ -168,13 +168,14 @@ static int ad7606_oversampling_get_index(unsigned val) static ssize_t ad7606_store_oversampling_ratio(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7606_state *st = iio_priv(indio_dev); unsigned long lval; int ret; - if (strict_strtoul(buf, 10, &lval)) - return -EINVAL; + ret = kstrtoul(buf, 10, &lval); + if (ret) + return ret; ret = ad7606_oversampling_get_index(lval); if (ret < 0) { @@ -197,7 +198,7 @@ static IIO_DEVICE_ATTR(oversampling_ratio, S_IRUGO | S_IWUSR, ad7606_store_oversampling_ratio, 0); static IIO_CONST_ATTR(oversampling_ratio_available, "0 2 4 8 16 32 64"); -static struct attribute *ad7606_attributes[] = { +static struct attribute *ad7606_attributes_os_and_range[] = { &iio_dev_attr_in_voltage_range.dev_attr.attr, &iio_const_attr_in_voltage_range_available.dev_attr.attr, &iio_dev_attr_oversampling_ratio.dev_attr.attr, @@ -205,47 +206,48 @@ static struct attribute *ad7606_attributes[] = { NULL, }; -static umode_t ad7606_attr_is_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7606_state *st = iio_priv(indio_dev); +static const struct attribute_group ad7606_attribute_group_os_and_range = { + .attrs = ad7606_attributes_os_and_range, +}; - umode_t mode = attr->mode; - - if (!(gpio_is_valid(st->pdata->gpio_os0) && - gpio_is_valid(st->pdata->gpio_os1) && - gpio_is_valid(st->pdata->gpio_os2)) && - (attr == &iio_dev_attr_oversampling_ratio.dev_attr.attr || - attr == - &iio_const_attr_oversampling_ratio_available.dev_attr.attr)) - mode = 0; - else if (!gpio_is_valid(st->pdata->gpio_range) && - (attr == &iio_dev_attr_in_voltage_range.dev_attr.attr || - attr == - &iio_const_attr_in_voltage_range_available.dev_attr.attr)) - mode = 0; - - return mode; -} +static struct attribute *ad7606_attributes_os[] = { + &iio_dev_attr_oversampling_ratio.dev_attr.attr, + &iio_const_attr_oversampling_ratio_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7606_attribute_group_os = { + .attrs = ad7606_attributes_os, +}; -static const struct attribute_group ad7606_attribute_group = { - .attrs = ad7606_attributes, - .is_visible = ad7606_attr_is_visible, +static struct attribute *ad7606_attributes_range[] = { + &iio_dev_attr_in_voltage_range.dev_attr.attr, + &iio_const_attr_in_voltage_range_available.dev_attr.attr, + NULL, }; -#define AD7606_CHANNEL(num) \ - { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .channel = num, \ - .address = num, \ - .scan_index = num, \ - .scan_type = IIO_ST('s', 16, 16, 0), \ +static const struct attribute_group ad7606_attribute_group_range = { + .attrs = ad7606_attributes_range, +}; + +#define AD7606_CHANNEL(num) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = num, \ + .address = num, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ + .scan_index = num, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + }, \ } -static struct iio_chan_spec ad7606_8_channels[] = { +static const struct iio_chan_spec ad7606_8_channels[] = { AD7606_CHANNEL(0), AD7606_CHANNEL(1), AD7606_CHANNEL(2), @@ -257,7 +259,7 @@ static struct iio_chan_spec ad7606_8_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(8), }; -static struct iio_chan_spec ad7606_6_channels[] = { +static const struct iio_chan_spec ad7606_6_channels[] = { AD7606_CHANNEL(0), AD7606_CHANNEL(1), AD7606_CHANNEL(2), @@ -267,7 +269,7 @@ static struct iio_chan_spec ad7606_6_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(6), }; -static struct iio_chan_spec ad7606_4_channels[] = { +static const struct iio_chan_spec ad7606_4_channels[] = { AD7606_CHANNEL(0), AD7606_CHANNEL(1), AD7606_CHANNEL(2), @@ -425,8 +427,7 @@ static irqreturn_t ad7606_interrupt(int irq, void *dev_id) struct ad7606_state *st = iio_priv(indio_dev); if (iio_buffer_enabled(indio_dev)) { - if (!work_pending(&st->poll_work)) - schedule_work(&st->poll_work); + schedule_work(&st->poll_work); } else { st->done = true; wake_up_interruptible(&st->wq_data_avail); @@ -435,10 +436,27 @@ static irqreturn_t ad7606_interrupt(int irq, void *dev_id) return IRQ_HANDLED; }; -static const struct iio_info ad7606_info = { +static const struct iio_info ad7606_info_no_os_or_range = { + .driver_module = THIS_MODULE, + .read_raw = &ad7606_read_raw, +}; + +static const struct iio_info ad7606_info_os_and_range = { .driver_module = THIS_MODULE, .read_raw = &ad7606_read_raw, - .attrs = &ad7606_attribute_group, + .attrs = &ad7606_attribute_group_os_and_range, +}; + +static const struct iio_info ad7606_info_os = { + .driver_module = THIS_MODULE, + .read_raw = &ad7606_read_raw, + .attrs = &ad7606_attribute_group_os, +}; + +static const struct iio_info ad7606_info_range = { + .driver_module = THIS_MODULE, + .read_raw = &ad7606_read_raw, + .attrs = &ad7606_attribute_group_range, }; struct iio_dev *ad7606_probe(struct device *dev, int irq, @@ -449,12 +467,11 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, struct ad7606_platform_data *pdata = dev->platform_data; struct ad7606_state *st; int ret; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); + struct iio_dev *indio_dev; - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); + if (!indio_dev) + return ERR_PTR(-ENOMEM); st = iio_priv(indio_dev); @@ -472,18 +489,30 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, st->oversampling = pdata->default_os; } - st->reg = regulator_get(dev, "vcc"); + st->reg = devm_regulator_get(dev, "vcc"); if (!IS_ERR(st->reg)) { ret = regulator_enable(st->reg); if (ret) - goto error_put_reg; + return ERR_PTR(ret); } st->pdata = pdata; st->chip_info = &ad7606_chip_info_tbl[id]; indio_dev->dev.parent = dev; - indio_dev->info = &ad7606_info; + if (gpio_is_valid(st->pdata->gpio_os0) && + gpio_is_valid(st->pdata->gpio_os1) && + gpio_is_valid(st->pdata->gpio_os2)) { + if (gpio_is_valid(st->pdata->gpio_range)) + indio_dev->info = &ad7606_info_os_and_range; + else + indio_dev->info = &ad7606_info_os; + } else { + if (gpio_is_valid(st->pdata->gpio_range)) + indio_dev->info = &ad7606_info_range; + else + indio_dev->info = &ad7606_info_no_os_or_range; + } indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->name = st->chip_info->name; indio_dev->channels = st->chip_info->channels; @@ -508,20 +537,12 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, if (ret) goto error_free_irq; - ret = iio_buffer_register(indio_dev, - indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_cleanup_ring; ret = iio_device_register(indio_dev); if (ret) goto error_unregister_ring; return indio_dev; error_unregister_ring: - iio_buffer_unregister(indio_dev); - -error_cleanup_ring: ad7606_ring_cleanup(indio_dev); error_free_irq: @@ -533,11 +554,6 @@ error_free_gpios: error_disable_reg: if (!IS_ERR(st->reg)) regulator_disable(st->reg); -error_put_reg: - if (!IS_ERR(st->reg)) - regulator_put(st->reg); - iio_free_device(indio_dev); -error_ret: return ERR_PTR(ret); } @@ -546,17 +562,13 @@ int ad7606_remove(struct iio_dev *indio_dev, int irq) struct ad7606_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); ad7606_ring_cleanup(indio_dev); free_irq(irq, indio_dev); - if (!IS_ERR(st->reg)) { + if (!IS_ERR(st->reg)) regulator_disable(st->reg); - regulator_put(st->reg); - } ad7606_free_gpios(st); - iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c index cff97568189..8a48d18de78 100644 --- a/drivers/staging/iio/adc/ad7606_par.c +++ b/drivers/staging/iio/adc/ad7606_par.c @@ -12,7 +12,7 @@ #include <linux/err.h> #include <linux/io.h> -#include "../iio.h" +#include <linux/iio/iio.h> #include "ad7606.h" static int ad7606_par16_read_block(struct device *dev, @@ -47,7 +47,7 @@ static const struct ad7606_bus_ops ad7606_par8_bops = { .read_block = ad7606_par8_read_block, }; -static int __devinit ad7606_par_probe(struct platform_device *pdev) +static int ad7606_par_probe(struct platform_device *pdev) { struct resource *res; struct iio_dev *indio_dev; @@ -100,7 +100,7 @@ out1: return ret; } -static int __devexit ad7606_par_remove(struct platform_device *pdev) +static int ad7606_par_remove(struct platform_device *pdev) { struct iio_dev *indio_dev = platform_get_drvdata(pdev); struct resource *res; @@ -112,8 +112,6 @@ static int __devexit ad7606_par_remove(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, resource_size(res)); - platform_set_drvdata(pdev, NULL); - return 0; } @@ -164,7 +162,7 @@ MODULE_DEVICE_TABLE(platform, ad7606_driver_ids); static struct platform_driver ad7606_driver = { .probe = ad7606_par_probe, - .remove = __devexit_p(ad7606_par_remove), + .remove = ad7606_par_remove, .id_table = ad7606_driver_ids, .driver = { .name = "ad7606", @@ -173,18 +171,7 @@ static struct platform_driver ad7606_driver = { }, }; -static int __init ad7606_init(void) -{ - return platform_driver_register(&ad7606_driver); -} - -static void __exit ad7606_cleanup(void) -{ - platform_driver_unregister(&ad7606_driver); -} - -module_init(ad7606_init); -module_exit(ad7606_cleanup); +module_platform_driver(ad7606_driver); MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c index e8f94a18a94..3bf174cb19b 100644 --- a/drivers/staging/iio/adc/ad7606_ring.c +++ b/drivers/staging/iio/adc/ad7606_ring.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Analog Devices Inc. + * Copyright 2011-2012 Analog Devices Inc. * * Licensed under the GPL-2. * @@ -11,10 +11,10 @@ #include <linux/kernel.h> #include <linux/slab.h> -#include "../iio.h" -#include "../buffer.h" -#include "../ring_sw.h" -#include "../trigger_consumer.h" +#include <linux/iio/iio.h> +#include <linux/iio/buffer.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> #include "ad7606.h" @@ -46,13 +46,10 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s) struct ad7606_state *st = container_of(work_s, struct ad7606_state, poll_work); struct iio_dev *indio_dev = iio_priv_to_dev(st); - struct iio_buffer *ring = indio_dev->buffer; - s64 time_ns; __u8 *buf; int ret; - buf = kzalloc(ring->access->get_bytes_per_datum(ring), - GFP_KERNEL); + buf = kzalloc(indio_dev->scan_bytes, GFP_KERNEL); if (buf == NULL) return; @@ -80,69 +77,25 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s) goto done; } - time_ns = iio_get_time_ns(); - - if (ring->scan_timestamp) - *((s64 *)(buf + ring->access->get_bytes_per_datum(ring) - - sizeof(s64))) = time_ns; - - ring->access->store_to(indio_dev->buffer, buf, time_ns); + iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); done: gpio_set_value(st->pdata->gpio_convst, 0); iio_trigger_notify_done(indio_dev->trig); kfree(buf); } -static const struct iio_buffer_setup_ops ad7606_ring_setup_ops = { - .preenable = &iio_sw_buffer_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, -}; - int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev) { struct ad7606_state *st = iio_priv(indio_dev); - int ret; - - indio_dev->buffer = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->buffer) { - ret = -ENOMEM; - goto error_ret; - } - - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; - indio_dev->pollfunc = iio_alloc_pollfunc(&ad7606_trigger_handler_th_bh, - &ad7606_trigger_handler_th_bh, - 0, - indio_dev, - "%s_consumer%d", - indio_dev->name, - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_deallocate_sw_rb; - } - - /* Ring buffer functions - here trigger setup related */ - - indio_dev->setup_ops = &ad7606_ring_setup_ops; - indio_dev->buffer->scan_timestamp = true ; INIT_WORK(&st->poll_work, &ad7606_poll_bh_to_ring); - /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_deallocate_sw_rb: - iio_sw_rb_free(indio_dev->buffer); -error_ret: - return ret; + return iio_triggered_buffer_setup(indio_dev, + &ad7606_trigger_handler_th_bh, &ad7606_trigger_handler_th_bh, + NULL); } void ad7606_ring_cleanup(struct iio_dev *indio_dev) { - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->buffer); + iio_triggered_buffer_cleanup(indio_dev); } diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c index 237f1c44d29..6a8ecd73a1a 100644 --- a/drivers/staging/iio/adc/ad7606_spi.c +++ b/drivers/staging/iio/adc/ad7606_spi.c @@ -11,7 +11,7 @@ #include <linux/types.h> #include <linux/err.h> -#include "../iio.h" +#include <linux/iio/iio.h> #include "ad7606.h" #define MAX_SPI_FREQ_HZ 23500000 /* VDRIVE above 4.75 V */ @@ -39,7 +39,7 @@ static const struct ad7606_bus_ops ad7606_spi_bops = { .read_block = ad7606_spi_read_block, }; -static int __devinit ad7606_spi_probe(struct spi_device *spi) +static int ad7606_spi_probe(struct spi_device *spi) { struct iio_dev *indio_dev; @@ -55,7 +55,7 @@ static int __devinit ad7606_spi_probe(struct spi_device *spi) return 0; } -static int __devexit ad7606_spi_remove(struct spi_device *spi) +static int ad7606_spi_remove(struct spi_device *spi) { struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev); @@ -106,7 +106,7 @@ static struct spi_driver ad7606_driver = { .pm = AD7606_SPI_PM_OPS, }, .probe = ad7606_spi_probe, - .remove = __devexit_p(ad7606_spi_remove), + .remove = ad7606_spi_remove, .id_table = ad7606_id, }; module_spi_driver(ad7606_driver); diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c index a13e58c814e..273add3ed63 100644 --- a/drivers/staging/iio/adc/ad7780.c +++ b/drivers/staging/iio/adc/ad7780.c @@ -1,5 +1,5 @@ /* - * AD7780/AD7781 SPI ADC driver + * AD7170/AD7171 and AD7780/AD7781 SPI ADC driver * * Copyright 2011 Analog Devices Inc. * @@ -18,8 +18,9 @@ #include <linux/gpio.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/adc/ad_sigma_delta.h> #include "ad7780.h" @@ -33,53 +34,53 @@ #define AD7780_PAT0 (1 << 0) struct ad7780_chip_info { - struct iio_chan_spec channel; + struct iio_chan_spec channel; + unsigned int pattern_mask; + unsigned int pattern; }; struct ad7780_state { - struct spi_device *spi; const struct ad7780_chip_info *chip_info; struct regulator *reg; - struct ad7780_platform_data *pdata; - wait_queue_head_t wq_data_avail; - bool done; + int powerdown_gpio; + unsigned int gain; u16 int_vref_mv; - struct spi_transfer xfer; - struct spi_message msg; - /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - */ - unsigned int data ____cacheline_aligned; + + struct ad_sigma_delta sd; }; enum ad7780_supported_device_ids { + ID_AD7170, + ID_AD7171, ID_AD7780, ID_AD7781, }; -static int ad7780_read(struct ad7780_state *st, int *val) +static struct ad7780_state *ad_sigma_delta_to_ad7780(struct ad_sigma_delta *sd) { - int ret; - - spi_bus_lock(st->spi->master); - - enable_irq(st->spi->irq); - st->done = false; - gpio_set_value(st->pdata->gpio_pdrst, 1); + return container_of(sd, struct ad7780_state, sd); +} - ret = wait_event_interruptible(st->wq_data_avail, st->done); - disable_irq_nosync(st->spi->irq); - if (ret) - goto out; +static int ad7780_set_mode(struct ad_sigma_delta *sigma_delta, + enum ad_sigma_delta_mode mode) +{ + struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta); + unsigned val; + + switch (mode) { + case AD_SD_MODE_SINGLE: + case AD_SD_MODE_CONTINUOUS: + val = 1; + break; + default: + val = 0; + break; + } - ret = spi_sync_locked(st->spi, &st->msg); - *val = be32_to_cpu(st->data); -out: - gpio_set_value(st->pdata->gpio_pdrst, 0); - spi_bus_unlock(st->spi->master); + if (gpio_is_valid(st->powerdown_gpio)) + gpio_set_value(st->powerdown_gpio, val); - return ret; + return 0; } static int ad7780_read_raw(struct iio_dev *indio_dev, @@ -89,95 +90,98 @@ static int ad7780_read_raw(struct iio_dev *indio_dev, long m) { struct ad7780_state *st = iio_priv(indio_dev); - struct iio_chan_spec channel = st->chip_info->channel; - int ret, smpl = 0; - unsigned long scale_uv; switch (m) { - case 0: - mutex_lock(&indio_dev->mlock); - ret = ad7780_read(st, &smpl); - mutex_unlock(&indio_dev->mlock); + case IIO_CHAN_INFO_RAW: + return ad_sigma_delta_single_conversion(indio_dev, chan, val); + case IIO_CHAN_INFO_SCALE: + *val = st->int_vref_mv * st->gain; + *val2 = chan->scan_type.realbits - 1; + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_OFFSET: + *val -= (1 << (chan->scan_type.realbits - 1)); + return IIO_VAL_INT; + } - if (ret < 0) - return ret; + return -EINVAL; +} - if ((smpl & AD7780_ERR) || - !((smpl & AD7780_PAT0) && !(smpl & AD7780_PAT1))) - return -EIO; +static int ad7780_postprocess_sample(struct ad_sigma_delta *sigma_delta, + unsigned int raw_sample) +{ + struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta); + const struct ad7780_chip_info *chip_info = st->chip_info; - *val = (smpl >> channel.scan_type.shift) & - ((1 << (channel.scan_type.realbits)) - 1); - *val -= (1 << (channel.scan_type.realbits - 1)); + if ((raw_sample & AD7780_ERR) || + ((raw_sample & chip_info->pattern_mask) != chip_info->pattern)) + return -EIO; - if (!(smpl & AD7780_GAIN)) - *val *= 128; + if (raw_sample & AD7780_GAIN) + st->gain = 1; + else + st->gain = 128; - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - scale_uv = (st->int_vref_mv * 100000) - >> (channel.scan_type.realbits - 1); - *val = scale_uv / 100000; - *val2 = (scale_uv % 100000) * 10; - return IIO_VAL_INT_PLUS_MICRO; - } - return -EINVAL; + return 0; } +static const struct ad_sigma_delta_info ad7780_sigma_delta_info = { + .set_mode = ad7780_set_mode, + .postprocess_sample = ad7780_postprocess_sample, + .has_registers = false, +}; + +#define AD7780_CHANNEL(bits, wordsize) \ + AD_SD_CHANNEL(1, 0, 0, bits, 32, wordsize - bits) + static const struct ad7780_chip_info ad7780_chip_info_tbl[] = { + [ID_AD7170] = { + .channel = AD7780_CHANNEL(12, 24), + .pattern = 0x5, + .pattern_mask = 0x7, + }, + [ID_AD7171] = { + .channel = AD7780_CHANNEL(16, 24), + .pattern = 0x5, + .pattern_mask = 0x7, + }, [ID_AD7780] = { - .channel = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 0, 0, IIO_ST('s', 24, 32, 8), 0), + .channel = AD7780_CHANNEL(24, 32), + .pattern = 0x1, + .pattern_mask = 0x3, }, [ID_AD7781] = { - .channel = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - 0, 0, IIO_ST('s', 20, 32, 12), 0), + .channel = AD7780_CHANNEL(20, 32), + .pattern = 0x1, + .pattern_mask = 0x3, }, }; -/** - * Interrupt handler - */ -static irqreturn_t ad7780_interrupt(int irq, void *dev_id) -{ - struct ad7780_state *st = dev_id; - - st->done = true; - wake_up_interruptible(&st->wq_data_avail); - - return IRQ_HANDLED; -}; - static const struct iio_info ad7780_info = { .read_raw = &ad7780_read_raw, .driver_module = THIS_MODULE, }; -static int __devinit ad7780_probe(struct spi_device *spi) +static int ad7780_probe(struct spi_device *spi) { struct ad7780_platform_data *pdata = spi->dev.platform_data; struct ad7780_state *st; struct iio_dev *indio_dev; int ret, voltage_uv = 0; - if (!pdata) { - dev_dbg(&spi->dev, "no platform data?\n"); - return -ENODEV; - } - - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; st = iio_priv(indio_dev); + st->gain = 1; + + ad_sd_init(&st->sd, indio_dev, spi, &ad7780_sigma_delta_info); - st->reg = regulator_get(&spi->dev, "vcc"); + st->reg = devm_regulator_get(&spi->dev, "vcc"); if (!IS_ERR(st->reg)) { ret = regulator_enable(st->reg); if (ret) - goto error_put_reg; + return ret; voltage_uv = regulator_get_voltage(st->reg); } @@ -185,8 +189,6 @@ static int __devinit ad7780_probe(struct spi_device *spi) st->chip_info = &ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data]; - st->pdata = pdata; - if (pdata && pdata->vref_mv) st->int_vref_mv = pdata->vref_mv; else if (voltage_uv) @@ -195,7 +197,6 @@ static int __devinit ad7780_probe(struct spi_device *spi) dev_warn(&spi->dev, "reference voltage unspecified\n"); spi_set_drvdata(spi, indio_dev); - st->spi = spi; indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; @@ -204,48 +205,34 @@ static int __devinit ad7780_probe(struct spi_device *spi) indio_dev->num_channels = 1; indio_dev->info = &ad7780_info; - init_waitqueue_head(&st->wq_data_avail); - - /* Setup default message */ - - st->xfer.rx_buf = &st->data; - st->xfer.len = st->chip_info->channel.scan_type.storagebits / 8; - - spi_message_init(&st->msg); - spi_message_add_tail(&st->xfer, &st->msg); - - ret = gpio_request_one(st->pdata->gpio_pdrst, GPIOF_OUT_INIT_LOW, - "AD7780 /PDRST"); - if (ret) { - dev_err(&spi->dev, "failed to request GPIO PDRST\n"); - goto error_disable_reg; + if (pdata && gpio_is_valid(pdata->gpio_pdrst)) { + + ret = devm_gpio_request_one(&spi->dev, pdata->gpio_pdrst, + GPIOF_OUT_INIT_LOW, "AD7780 /PDRST"); + if (ret) { + dev_err(&spi->dev, "failed to request GPIO PDRST\n"); + goto error_disable_reg; + } + st->powerdown_gpio = pdata->gpio_pdrst; + } else { + st->powerdown_gpio = -1; } - ret = request_irq(spi->irq, ad7780_interrupt, - IRQF_TRIGGER_FALLING, spi_get_device_id(spi)->name, st); + ret = ad_sd_setup_buffer_and_trigger(indio_dev); if (ret) - goto error_free_gpio; - - disable_irq(spi->irq); + goto error_disable_reg; ret = iio_device_register(indio_dev); if (ret) - goto error_free_irq; + goto error_cleanup_buffer_and_trigger; return 0; -error_free_irq: - free_irq(spi->irq, st); -error_free_gpio: - gpio_free(st->pdata->gpio_pdrst); +error_cleanup_buffer_and_trigger: + ad_sd_cleanup_buffer_and_trigger(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); - - iio_free_device(indio_dev); return ret; } @@ -256,18 +243,17 @@ static int ad7780_remove(struct spi_device *spi) struct ad7780_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - free_irq(spi->irq, st); - gpio_free(st->pdata->gpio_pdrst); - if (!IS_ERR(st->reg)) { + ad_sd_cleanup_buffer_and_trigger(indio_dev); + + if (!IS_ERR(st->reg)) regulator_disable(st->reg); - regulator_put(st->reg); - } - iio_free_device(indio_dev); return 0; } static const struct spi_device_id ad7780_id[] = { + {"ad7170", ID_AD7170}, + {"ad7171", ID_AD7171}, {"ad7780", ID_AD7780}, {"ad7781", ID_AD7781}, {} @@ -280,11 +266,11 @@ static struct spi_driver ad7780_driver = { .owner = THIS_MODULE, }, .probe = ad7780_probe, - .remove = __devexit_p(ad7780_remove), + .remove = ad7780_remove, .id_table = ad7780_id, }; module_spi_driver(ad7780_driver); MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("Analog Devices AD7780/1 ADC"); +MODULE_DESCRIPTION("Analog Devices AD7780 and similar ADCs"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c deleted file mode 100644 index 6a058b19c49..00000000000 --- a/drivers/staging/iio/adc/ad7793.c +++ /dev/null @@ -1,1039 +0,0 @@ -/* - * AD7792/AD7793 SPI ADC driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include <linux/interrupt.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/spi/spi.h> -#include <linux/regulator/consumer.h> -#include <linux/err.h> -#include <linux/sched.h> -#include <linux/delay.h> -#include <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" -#include "../ring_sw.h" -#include "../trigger.h" -#include "../trigger_consumer.h" - -#include "ad7793.h" - -/* NOTE: - * The AD7792/AD7793 features a dual use data out ready DOUT/RDY output. - * In order to avoid contentions on the SPI bus, it's therefore necessary - * to use spi bus locking. - * - * The DOUT/RDY output must also be wired to an interrupt capable GPIO. - */ - -struct ad7793_chip_info { - struct iio_chan_spec channel[7]; -}; - -struct ad7793_state { - struct spi_device *spi; - struct iio_trigger *trig; - const struct ad7793_chip_info *chip_info; - struct regulator *reg; - struct ad7793_platform_data *pdata; - wait_queue_head_t wq_data_avail; - bool done; - bool irq_dis; - u16 int_vref_mv; - u16 mode; - u16 conf; - u32 scale_avail[8][2]; - /* Note this uses fact that 8 the mask always fits in a long */ - unsigned long available_scan_masks[7]; - /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - */ - u8 data[4] ____cacheline_aligned; -}; - -enum ad7793_supported_device_ids { - ID_AD7792, - ID_AD7793, -}; - -static int __ad7793_write_reg(struct ad7793_state *st, bool locked, - bool cs_change, unsigned char reg, - unsigned size, unsigned val) -{ - u8 *data = st->data; - struct spi_transfer t = { - .tx_buf = data, - .len = size + 1, - .cs_change = cs_change, - }; - struct spi_message m; - - data[0] = AD7793_COMM_WRITE | AD7793_COMM_ADDR(reg); - - switch (size) { - case 3: - data[1] = val >> 16; - data[2] = val >> 8; - data[3] = val; - break; - case 2: - data[1] = val >> 8; - data[2] = val; - break; - case 1: - data[1] = val; - break; - default: - return -EINVAL; - } - - spi_message_init(&m); - spi_message_add_tail(&t, &m); - - if (locked) - return spi_sync_locked(st->spi, &m); - else - return spi_sync(st->spi, &m); -} - -static int ad7793_write_reg(struct ad7793_state *st, - unsigned reg, unsigned size, unsigned val) -{ - return __ad7793_write_reg(st, false, false, reg, size, val); -} - -static int __ad7793_read_reg(struct ad7793_state *st, bool locked, - bool cs_change, unsigned char reg, - int *val, unsigned size) -{ - u8 *data = st->data; - int ret; - struct spi_transfer t[] = { - { - .tx_buf = data, - .len = 1, - }, { - .rx_buf = data, - .len = size, - .cs_change = cs_change, - }, - }; - struct spi_message m; - - data[0] = AD7793_COMM_READ | AD7793_COMM_ADDR(reg); - - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - spi_message_add_tail(&t[1], &m); - - if (locked) - ret = spi_sync_locked(st->spi, &m); - else - ret = spi_sync(st->spi, &m); - - if (ret < 0) - return ret; - - switch (size) { - case 3: - *val = data[0] << 16 | data[1] << 8 | data[2]; - break; - case 2: - *val = data[0] << 8 | data[1]; - break; - case 1: - *val = data[0]; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int ad7793_read_reg(struct ad7793_state *st, - unsigned reg, int *val, unsigned size) -{ - return __ad7793_read_reg(st, 0, 0, reg, val, size); -} - -static int ad7793_read(struct ad7793_state *st, unsigned ch, - unsigned len, int *val) -{ - int ret; - st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | AD7793_CONF_CHAN(ch); - st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | - AD7793_MODE_SEL(AD7793_MODE_SINGLE); - - ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf); - - spi_bus_lock(st->spi->master); - st->done = false; - - ret = __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE, - sizeof(st->mode), st->mode); - if (ret < 0) - goto out; - - st->irq_dis = false; - enable_irq(st->spi->irq); - wait_event_interruptible(st->wq_data_avail, st->done); - - ret = __ad7793_read_reg(st, 1, 0, AD7793_REG_DATA, val, len); -out: - spi_bus_unlock(st->spi->master); - - return ret; -} - -static int ad7793_calibrate(struct ad7793_state *st, unsigned mode, unsigned ch) -{ - int ret; - - st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | AD7793_CONF_CHAN(ch); - st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | AD7793_MODE_SEL(mode); - - ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf); - - spi_bus_lock(st->spi->master); - st->done = false; - - ret = __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE, - sizeof(st->mode), st->mode); - if (ret < 0) - goto out; - - st->irq_dis = false; - enable_irq(st->spi->irq); - wait_event_interruptible(st->wq_data_avail, st->done); - - st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | - AD7793_MODE_SEL(AD7793_MODE_IDLE); - - ret = __ad7793_write_reg(st, 1, 0, AD7793_REG_MODE, - sizeof(st->mode), st->mode); -out: - spi_bus_unlock(st->spi->master); - - return ret; -} - -static const u8 ad7793_calib_arr[6][2] = { - {AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN1P_AIN1M}, - {AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN1P_AIN1M}, - {AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN2P_AIN2M}, - {AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN2P_AIN2M}, - {AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN3P_AIN3M}, - {AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN3P_AIN3M} -}; - -static int ad7793_calibrate_all(struct ad7793_state *st) -{ - int i, ret; - - for (i = 0; i < ARRAY_SIZE(ad7793_calib_arr); i++) { - ret = ad7793_calibrate(st, ad7793_calib_arr[i][0], - ad7793_calib_arr[i][1]); - if (ret) - goto out; - } - - return 0; -out: - dev_err(&st->spi->dev, "Calibration failed\n"); - return ret; -} - -static int ad7793_setup(struct ad7793_state *st) -{ - int i, ret = -1; - unsigned long long scale_uv; - u32 id; - - /* reset the serial interface */ - ret = spi_write(st->spi, (u8 *)&ret, sizeof(ret)); - if (ret < 0) - goto out; - msleep(1); /* Wait for at least 500us */ - - /* write/read test for device presence */ - ret = ad7793_read_reg(st, AD7793_REG_ID, &id, 1); - if (ret) - goto out; - - id &= AD7793_ID_MASK; - - if (!((id == AD7792_ID) || (id == AD7793_ID))) { - dev_err(&st->spi->dev, "device ID query failed\n"); - goto out; - } - - st->mode = (st->pdata->mode & ~AD7793_MODE_SEL(-1)) | - AD7793_MODE_SEL(AD7793_MODE_IDLE); - st->conf = st->pdata->conf & ~AD7793_CONF_CHAN(-1); - - ret = ad7793_write_reg(st, AD7793_REG_MODE, sizeof(st->mode), st->mode); - if (ret) - goto out; - - ret = ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf); - if (ret) - goto out; - - ret = ad7793_write_reg(st, AD7793_REG_IO, - sizeof(st->pdata->io), st->pdata->io); - if (ret) - goto out; - - ret = ad7793_calibrate_all(st); - if (ret) - goto out; - - /* Populate available ADC input ranges */ - for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) { - scale_uv = ((u64)st->int_vref_mv * 100000000) - >> (st->chip_info->channel[0].scan_type.realbits - - (!!(st->conf & AD7793_CONF_UNIPOLAR) ? 0 : 1)); - scale_uv >>= i; - - st->scale_avail[i][1] = do_div(scale_uv, 100000000) * 10; - st->scale_avail[i][0] = scale_uv; - } - - return 0; -out: - dev_err(&st->spi->dev, "setup failed\n"); - return ret; -} - -static int ad7793_ring_preenable(struct iio_dev *indio_dev) -{ - struct ad7793_state *st = iio_priv(indio_dev); - struct iio_buffer *ring = indio_dev->buffer; - size_t d_size; - unsigned channel; - - if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) - return -EINVAL; - - channel = find_first_bit(indio_dev->active_scan_mask, - indio_dev->masklength); - - d_size = bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength) * - indio_dev->channels[0].scan_type.storagebits / 8; - - if (ring->scan_timestamp) { - d_size += sizeof(s64); - - if (d_size % sizeof(s64)) - d_size += sizeof(s64) - (d_size % sizeof(s64)); - } - - if (indio_dev->buffer->access->set_bytes_per_datum) - indio_dev->buffer->access-> - set_bytes_per_datum(indio_dev->buffer, d_size); - - st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | - AD7793_MODE_SEL(AD7793_MODE_CONT); - st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | - AD7793_CONF_CHAN(indio_dev->channels[channel].address); - - ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf); - - spi_bus_lock(st->spi->master); - __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE, - sizeof(st->mode), st->mode); - - st->irq_dis = false; - enable_irq(st->spi->irq); - - return 0; -} - -static int ad7793_ring_postdisable(struct iio_dev *indio_dev) -{ - struct ad7793_state *st = iio_priv(indio_dev); - - st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | - AD7793_MODE_SEL(AD7793_MODE_IDLE); - - st->done = false; - wait_event_interruptible(st->wq_data_avail, st->done); - - if (!st->irq_dis) - disable_irq_nosync(st->spi->irq); - - __ad7793_write_reg(st, 1, 0, AD7793_REG_MODE, - sizeof(st->mode), st->mode); - - return spi_bus_unlock(st->spi->master); -} - -/** - * ad7793_trigger_handler() bh of trigger launched polling to ring buffer - **/ - -static irqreturn_t ad7793_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct iio_buffer *ring = indio_dev->buffer; - struct ad7793_state *st = iio_priv(indio_dev); - s64 dat64[2]; - s32 *dat32 = (s32 *)dat64; - - if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) - __ad7793_read_reg(st, 1, 1, AD7793_REG_DATA, - dat32, - indio_dev->channels[0].scan_type.realbits/8); - - /* Guaranteed to be aligned with 8 byte boundary */ - if (ring->scan_timestamp) - dat64[1] = pf->timestamp; - - ring->access->store_to(ring, (u8 *)dat64, pf->timestamp); - - iio_trigger_notify_done(indio_dev->trig); - st->irq_dis = false; - enable_irq(st->spi->irq); - - return IRQ_HANDLED; -} - -static const struct iio_buffer_setup_ops ad7793_ring_setup_ops = { - .preenable = &ad7793_ring_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, - .postdisable = &ad7793_ring_postdisable, -}; - -static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev) -{ - int ret; - - indio_dev->buffer = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->buffer) { - ret = -ENOMEM; - goto error_ret; - } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, - &ad7793_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "ad7793_consumer%d", - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_deallocate_sw_rb; - } - - /* Ring buffer functions - here trigger setup related */ - indio_dev->setup_ops = &ad7793_ring_setup_ops; - - /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_deallocate_sw_rb: - iio_sw_rb_free(indio_dev->buffer); -error_ret: - return ret; -} - -static void ad7793_ring_cleanup(struct iio_dev *indio_dev) -{ - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->buffer); -} - -/** - * ad7793_data_rdy_trig_poll() the event handler for the data rdy trig - **/ -static irqreturn_t ad7793_data_rdy_trig_poll(int irq, void *private) -{ - struct ad7793_state *st = iio_priv(private); - - st->done = true; - wake_up_interruptible(&st->wq_data_avail); - disable_irq_nosync(irq); - st->irq_dis = true; - iio_trigger_poll(st->trig, iio_get_time_ns()); - - return IRQ_HANDLED; -} - -static struct iio_trigger_ops ad7793_trigger_ops = { - .owner = THIS_MODULE, -}; - -static int ad7793_probe_trigger(struct iio_dev *indio_dev) -{ - struct ad7793_state *st = iio_priv(indio_dev); - int ret; - - st->trig = iio_allocate_trigger("%s-dev%d", - spi_get_device_id(st->spi)->name, - indio_dev->id); - if (st->trig == NULL) { - ret = -ENOMEM; - goto error_ret; - } - st->trig->ops = &ad7793_trigger_ops; - - ret = request_irq(st->spi->irq, - ad7793_data_rdy_trig_poll, - IRQF_TRIGGER_LOW, - spi_get_device_id(st->spi)->name, - indio_dev); - if (ret) - goto error_free_trig; - - disable_irq_nosync(st->spi->irq); - st->irq_dis = true; - st->trig->dev.parent = &st->spi->dev; - st->trig->private_data = indio_dev; - - ret = iio_trigger_register(st->trig); - - /* select default trigger */ - indio_dev->trig = st->trig; - if (ret) - goto error_free_irq; - - return 0; - -error_free_irq: - free_irq(st->spi->irq, indio_dev); -error_free_trig: - iio_free_trigger(st->trig); -error_ret: - return ret; -} - -static void ad7793_remove_trigger(struct iio_dev *indio_dev) -{ - struct ad7793_state *st = iio_priv(indio_dev); - - iio_trigger_unregister(st->trig); - free_irq(st->spi->irq, indio_dev); - iio_free_trigger(st->trig); -} - -static const u16 sample_freq_avail[16] = {0, 470, 242, 123, 62, 50, 39, 33, 19, - 17, 16, 12, 10, 8, 6, 4}; - -static ssize_t ad7793_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7793_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", - sample_freq_avail[AD7793_MODE_RATE(st->mode)]); -} - -static ssize_t ad7793_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7793_state *st = iio_priv(indio_dev); - long lval; - int i, ret; - - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { - mutex_unlock(&indio_dev->mlock); - return -EBUSY; - } - mutex_unlock(&indio_dev->mlock); - - ret = strict_strtol(buf, 10, &lval); - if (ret) - return ret; - - ret = -EINVAL; - - for (i = 0; i < ARRAY_SIZE(sample_freq_avail); i++) - if (lval == sample_freq_avail[i]) { - mutex_lock(&indio_dev->mlock); - st->mode &= ~AD7793_MODE_RATE(-1); - st->mode |= AD7793_MODE_RATE(i); - ad7793_write_reg(st, AD7793_REG_MODE, - sizeof(st->mode), st->mode); - mutex_unlock(&indio_dev->mlock); - ret = 0; - } - - return ret ? ret : len; -} - -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - ad7793_read_frequency, - ad7793_write_frequency); - -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( - "470 242 123 62 50 39 33 19 17 16 12 10 8 6 4"); - -static ssize_t ad7793_show_scale_available(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7793_state *st = iio_priv(indio_dev); - int i, len = 0; - - for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) - len += sprintf(buf + len, "%d.%09u ", st->scale_avail[i][0], - st->scale_avail[i][1]); - - len += sprintf(buf + len, "\n"); - - return len; -} - -static IIO_DEVICE_ATTR_NAMED(in_m_in_scale_available, in-in_scale_available, - S_IRUGO, ad7793_show_scale_available, NULL, 0); - -static struct attribute *ad7793_attributes[] = { - &iio_dev_attr_sampling_frequency.dev_attr.attr, - &iio_const_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_in_m_in_scale_available.dev_attr.attr, - NULL -}; - -static const struct attribute_group ad7793_attribute_group = { - .attrs = ad7793_attributes, -}; - -static int ad7793_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - struct ad7793_state *st = iio_priv(indio_dev); - int ret, smpl = 0; - unsigned long long scale_uv; - bool unipolar = !!(st->conf & AD7793_CONF_UNIPOLAR); - - switch (m) { - case 0: - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) - ret = -EBUSY; - else - ret = ad7793_read(st, chan->address, - chan->scan_type.realbits / 8, &smpl); - mutex_unlock(&indio_dev->mlock); - - if (ret < 0) - return ret; - - *val = (smpl >> chan->scan_type.shift) & - ((1 << (chan->scan_type.realbits)) - 1); - - if (!unipolar) - *val -= (1 << (chan->scan_type.realbits - 1)); - - return IIO_VAL_INT; - - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_VOLTAGE: - if (chan->differential) { - *val = st-> - scale_avail[(st->conf >> 8) & 0x7][0]; - *val2 = st-> - scale_avail[(st->conf >> 8) & 0x7][1]; - return IIO_VAL_INT_PLUS_NANO; - } else { - /* 1170mV / 2^23 * 6 */ - scale_uv = (1170ULL * 100000000ULL * 6ULL) - >> (chan->scan_type.realbits - - (unipolar ? 0 : 1)); - } - break; - case IIO_TEMP: - /* Always uses unity gain and internal ref */ - scale_uv = (2500ULL * 100000000ULL) - >> (chan->scan_type.realbits - - (unipolar ? 0 : 1)); - break; - default: - return -EINVAL; - } - - *val2 = do_div(scale_uv, 100000000) * 10; - *val = scale_uv; - - return IIO_VAL_INT_PLUS_NANO; - } - return -EINVAL; -} - -static int ad7793_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct ad7793_state *st = iio_priv(indio_dev); - int ret, i; - unsigned int tmp; - - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { - mutex_unlock(&indio_dev->mlock); - return -EBUSY; - } - - switch (mask) { - case IIO_CHAN_INFO_SCALE: - ret = -EINVAL; - for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) - if (val2 == st->scale_avail[i][1]) { - tmp = st->conf; - st->conf &= ~AD7793_CONF_GAIN(-1); - st->conf |= AD7793_CONF_GAIN(i); - - if (tmp != st->conf) { - ad7793_write_reg(st, AD7793_REG_CONF, - sizeof(st->conf), - st->conf); - ad7793_calibrate_all(st); - } - ret = 0; - } - - default: - ret = -EINVAL; - } - - mutex_unlock(&indio_dev->mlock); - return ret; -} - -static int ad7793_validate_trigger(struct iio_dev *indio_dev, - struct iio_trigger *trig) -{ - if (indio_dev->trig != trig) - return -EINVAL; - - return 0; -} - -static int ad7793_write_raw_get_fmt(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - long mask) -{ - return IIO_VAL_INT_PLUS_NANO; -} - -static const struct iio_info ad7793_info = { - .read_raw = &ad7793_read_raw, - .write_raw = &ad7793_write_raw, - .write_raw_get_fmt = &ad7793_write_raw_get_fmt, - .attrs = &ad7793_attribute_group, - .validate_trigger = ad7793_validate_trigger, - .driver_module = THIS_MODULE, -}; - -static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { - [ID_AD7793] = { - .channel[0] = { - .type = IIO_VOLTAGE, - .differential = 1, - .indexed = 1, - .channel = 0, - .channel2 = 0, - .address = AD7793_CH_AIN1P_AIN1M, - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, - .scan_index = 0, - .scan_type = IIO_ST('s', 24, 32, 0) - }, - .channel[1] = { - .type = IIO_VOLTAGE, - .differential = 1, - .indexed = 1, - .channel = 1, - .channel2 = 1, - .address = AD7793_CH_AIN2P_AIN2M, - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, - .scan_index = 1, - .scan_type = IIO_ST('s', 24, 32, 0) - }, - .channel[2] = { - .type = IIO_VOLTAGE, - .differential = 1, - .indexed = 1, - .channel = 2, - .channel2 = 2, - .address = AD7793_CH_AIN3P_AIN3M, - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, - .scan_index = 2, - .scan_type = IIO_ST('s', 24, 32, 0) - }, - .channel[3] = { - .type = IIO_VOLTAGE, - .differential = 1, - .extend_name = "shorted", - .indexed = 1, - .channel = 2, - .channel2 = 2, - .address = AD7793_CH_AIN1M_AIN1M, - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, - .scan_index = 2, - .scan_type = IIO_ST('s', 24, 32, 0) - }, - .channel[4] = { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .address = AD7793_CH_TEMP, - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - .scan_index = 4, - .scan_type = IIO_ST('s', 24, 32, 0), - }, - .channel[5] = { - .type = IIO_VOLTAGE, - .extend_name = "supply", - .indexed = 1, - .channel = 4, - .address = AD7793_CH_AVDD_MONITOR, - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - .scan_index = 5, - .scan_type = IIO_ST('s', 24, 32, 0), - }, - .channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6), - }, - [ID_AD7792] = { - .channel[0] = { - .type = IIO_VOLTAGE, - .differential = 1, - .indexed = 1, - .channel = 0, - .channel2 = 0, - .address = AD7793_CH_AIN1P_AIN1M, - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, - .scan_index = 0, - .scan_type = IIO_ST('s', 16, 32, 0) - }, - .channel[1] = { - .type = IIO_VOLTAGE, - .differential = 1, - .indexed = 1, - .channel = 1, - .channel2 = 1, - .address = AD7793_CH_AIN2P_AIN2M, - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, - .scan_index = 1, - .scan_type = IIO_ST('s', 16, 32, 0) - }, - .channel[2] = { - .type = IIO_VOLTAGE, - .differential = 1, - .indexed = 1, - .channel = 2, - .channel2 = 2, - .address = AD7793_CH_AIN3P_AIN3M, - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, - .scan_index = 2, - .scan_type = IIO_ST('s', 16, 32, 0) - }, - .channel[3] = { - .type = IIO_VOLTAGE, - .differential = 1, - .extend_name = "shorted", - .indexed = 1, - .channel = 2, - .channel2 = 2, - .address = AD7793_CH_AIN1M_AIN1M, - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, - .scan_index = 2, - .scan_type = IIO_ST('s', 16, 32, 0) - }, - .channel[4] = { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .address = AD7793_CH_TEMP, - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - .scan_index = 4, - .scan_type = IIO_ST('s', 16, 32, 0), - }, - .channel[5] = { - .type = IIO_VOLTAGE, - .extend_name = "supply", - .indexed = 1, - .channel = 4, - .address = AD7793_CH_AVDD_MONITOR, - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - .scan_index = 5, - .scan_type = IIO_ST('s', 16, 32, 0), - }, - .channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6), - }, -}; - -static int __devinit ad7793_probe(struct spi_device *spi) -{ - struct ad7793_platform_data *pdata = spi->dev.platform_data; - struct ad7793_state *st; - struct iio_dev *indio_dev; - int ret, i, voltage_uv = 0; - - if (!pdata) { - dev_err(&spi->dev, "no platform data?\n"); - return -ENODEV; - } - - if (!spi->irq) { - dev_err(&spi->dev, "no IRQ?\n"); - return -ENODEV; - } - - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) - return -ENOMEM; - - st = iio_priv(indio_dev); - - st->reg = regulator_get(&spi->dev, "vcc"); - if (!IS_ERR(st->reg)) { - ret = regulator_enable(st->reg); - if (ret) - goto error_put_reg; - - voltage_uv = regulator_get_voltage(st->reg); - } - - st->chip_info = - &ad7793_chip_info_tbl[spi_get_device_id(spi)->driver_data]; - - st->pdata = pdata; - - if (pdata && pdata->vref_mv) - st->int_vref_mv = pdata->vref_mv; - else if (voltage_uv) - st->int_vref_mv = voltage_uv / 1000; - else - st->int_vref_mv = 2500; /* Build-in ref */ - - spi_set_drvdata(spi, indio_dev); - st->spi = spi; - - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = st->chip_info->channel; - indio_dev->available_scan_masks = st->available_scan_masks; - indio_dev->num_channels = 7; - indio_dev->info = &ad7793_info; - - for (i = 0; i < indio_dev->num_channels; i++) { - set_bit(i, &st->available_scan_masks[i]); - set_bit(indio_dev-> - channels[indio_dev->num_channels - 1].scan_index, - &st->available_scan_masks[i]); - } - - init_waitqueue_head(&st->wq_data_avail); - - ret = ad7793_register_ring_funcs_and_init(indio_dev); - if (ret) - goto error_disable_reg; - - ret = ad7793_probe_trigger(indio_dev); - if (ret) - goto error_unreg_ring; - - ret = iio_buffer_register(indio_dev, - indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_remove_trigger; - - ret = ad7793_setup(st); - if (ret) - goto error_uninitialize_ring; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_uninitialize_ring; - - return 0; - -error_uninitialize_ring: - iio_buffer_unregister(indio_dev); -error_remove_trigger: - ad7793_remove_trigger(indio_dev); -error_unreg_ring: - ad7793_ring_cleanup(indio_dev); -error_disable_reg: - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); -error_put_reg: - if (!IS_ERR(st->reg)) - regulator_put(st->reg); - - iio_free_device(indio_dev); - - return ret; -} - -static int ad7793_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad7793_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); - ad7793_remove_trigger(indio_dev); - ad7793_ring_cleanup(indio_dev); - - if (!IS_ERR(st->reg)) { - regulator_disable(st->reg); - regulator_put(st->reg); - } - - iio_free_device(indio_dev); - - return 0; -} - -static const struct spi_device_id ad7793_id[] = { - {"ad7792", ID_AD7792}, - {"ad7793", ID_AD7793}, - {} -}; -MODULE_DEVICE_TABLE(spi, ad7793_id); - -static struct spi_driver ad7793_driver = { - .driver = { - .name = "ad7793", - .owner = THIS_MODULE, - }, - .probe = ad7793_probe, - .remove = __devexit_p(ad7793_remove), - .id_table = ad7793_id, -}; -module_spi_driver(ad7793_driver); - -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("Analog Devices AD7792/3 ADC"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/ad7793.h b/drivers/staging/iio/adc/ad7793.h deleted file mode 100644 index 64f7d41dc45..00000000000 --- a/drivers/staging/iio/adc/ad7793.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * AD7792/AD7793 SPI ADC driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ -#ifndef IIO_ADC_AD7793_H_ -#define IIO_ADC_AD7793_H_ - -/* - * TODO: struct ad7793_platform_data needs to go into include/linux/iio - */ - -/* Registers */ -#define AD7793_REG_COMM 0 /* Communications Register (WO, 8-bit) */ -#define AD7793_REG_STAT 0 /* Status Register (RO, 8-bit) */ -#define AD7793_REG_MODE 1 /* Mode Register (RW, 16-bit */ -#define AD7793_REG_CONF 2 /* Configuration Register (RW, 16-bit) */ -#define AD7793_REG_DATA 3 /* Data Register (RO, 16-/24-bit) */ -#define AD7793_REG_ID 4 /* ID Register (RO, 8-bit) */ -#define AD7793_REG_IO 5 /* IO Register (RO, 8-bit) */ -#define AD7793_REG_OFFSET 6 /* Offset Register (RW, 16-bit - * (AD7792)/24-bit (AD7793)) */ -#define AD7793_REG_FULLSALE 7 /* Full-Scale Register - * (RW, 16-bit (AD7792)/24-bit (AD7793)) */ - -/* Communications Register Bit Designations (AD7793_REG_COMM) */ -#define AD7793_COMM_WEN (1 << 7) /* Write Enable */ -#define AD7793_COMM_WRITE (0 << 6) /* Write Operation */ -#define AD7793_COMM_READ (1 << 6) /* Read Operation */ -#define AD7793_COMM_ADDR(x) (((x) & 0x7) << 3) /* Register Address */ -#define AD7793_COMM_CREAD (1 << 2) /* Continuous Read of Data Register */ - -/* Status Register Bit Designations (AD7793_REG_STAT) */ -#define AD7793_STAT_RDY (1 << 7) /* Ready */ -#define AD7793_STAT_ERR (1 << 6) /* Error (Overrange, Underrange) */ -#define AD7793_STAT_CH3 (1 << 2) /* Channel 3 */ -#define AD7793_STAT_CH2 (1 << 1) /* Channel 2 */ -#define AD7793_STAT_CH1 (1 << 0) /* Channel 1 */ - -/* Mode Register Bit Designations (AD7793_REG_MODE) */ -#define AD7793_MODE_SEL(x) (((x) & 0x7) << 13) /* Operation Mode Select */ -#define AD7793_MODE_CLKSRC(x) (((x) & 0x3) << 6) /* ADC Clock Source Select */ -#define AD7793_MODE_RATE(x) ((x) & 0xF) /* Filter Update Rate Select */ - -#define AD7793_MODE_CONT 0 /* Continuous Conversion Mode */ -#define AD7793_MODE_SINGLE 1 /* Single Conversion Mode */ -#define AD7793_MODE_IDLE 2 /* Idle Mode */ -#define AD7793_MODE_PWRDN 3 /* Power-Down Mode */ -#define AD7793_MODE_CAL_INT_ZERO 4 /* Internal Zero-Scale Calibration */ -#define AD7793_MODE_CAL_INT_FULL 5 /* Internal Full-Scale Calibration */ -#define AD7793_MODE_CAL_SYS_ZERO 6 /* System Zero-Scale Calibration */ -#define AD7793_MODE_CAL_SYS_FULL 7 /* System Full-Scale Calibration */ - -#define AD7793_CLK_INT 0 /* Internal 64 kHz Clock not - * available at the CLK pin */ -#define AD7793_CLK_INT_CO 1 /* Internal 64 kHz Clock available - * at the CLK pin */ -#define AD7793_CLK_EXT 2 /* External 64 kHz Clock */ -#define AD7793_CLK_EXT_DIV2 3 /* External Clock divided by 2 */ - -/* Configuration Register Bit Designations (AD7793_REG_CONF) */ -#define AD7793_CONF_VBIAS(x) (((x) & 0x3) << 14) /* Bias Voltage - * Generator Enable */ -#define AD7793_CONF_BO_EN (1 << 13) /* Burnout Current Enable */ -#define AD7793_CONF_UNIPOLAR (1 << 12) /* Unipolar/Bipolar Enable */ -#define AD7793_CONF_BOOST (1 << 11) /* Boost Enable */ -#define AD7793_CONF_GAIN(x) (((x) & 0x7) << 8) /* Gain Select */ -#define AD7793_CONF_REFSEL (1 << 7) /* INT/EXT Reference Select */ -#define AD7793_CONF_BUF (1 << 4) /* Buffered Mode Enable */ -#define AD7793_CONF_CHAN(x) ((x) & 0x7) /* Channel select */ - -#define AD7793_CH_AIN1P_AIN1M 0 /* AIN1(+) - AIN1(-) */ -#define AD7793_CH_AIN2P_AIN2M 1 /* AIN2(+) - AIN2(-) */ -#define AD7793_CH_AIN3P_AIN3M 2 /* AIN3(+) - AIN3(-) */ -#define AD7793_CH_AIN1M_AIN1M 3 /* AIN1(-) - AIN1(-) */ -#define AD7793_CH_TEMP 6 /* Temp Sensor */ -#define AD7793_CH_AVDD_MONITOR 7 /* AVDD Monitor */ - -/* ID Register Bit Designations (AD7793_REG_ID) */ -#define AD7792_ID 0xA -#define AD7793_ID 0xB -#define AD7793_ID_MASK 0xF - -/* IO (Excitation Current Sources) Register Bit Designations (AD7793_REG_IO) */ -#define AD7793_IO_IEXC1_IOUT1_IEXC2_IOUT2 0 /* IEXC1 connect to IOUT1, - * IEXC2 connect to IOUT2 */ -#define AD7793_IO_IEXC1_IOUT2_IEXC2_IOUT1 1 /* IEXC1 connect to IOUT2, - * IEXC2 connect to IOUT1 */ -#define AD7793_IO_IEXC1_IEXC2_IOUT1 2 /* Both current sources - * IEXC1,2 connect to IOUT1 */ -#define AD7793_IO_IEXC1_IEXC2_IOUT2 3 /* Both current sources - * IEXC1,2 connect to IOUT2 */ - -#define AD7793_IO_IXCEN_10uA (1 << 0) /* Excitation Current 10uA */ -#define AD7793_IO_IXCEN_210uA (2 << 0) /* Excitation Current 210uA */ -#define AD7793_IO_IXCEN_1mA (3 << 0) /* Excitation Current 1mA */ - -struct ad7793_platform_data { - u16 vref_mv; - u16 mode; - u16 conf; - u8 io; -}; - -#endif /* IIO_ADC_AD7793_H_ */ diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c index 52b720e2b03..158d770f961 100644 --- a/drivers/staging/iio/adc/ad7816.c +++ b/drivers/staging/iio/adc/ad7816.c @@ -16,9 +16,9 @@ #include <linux/spi/spi.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/events.h> /* * AD7816 config masks @@ -40,7 +40,7 @@ /* - * struct ad7816_chip_info - chip specifc information + * struct ad7816_chip_info - chip specific information */ struct ad7816_chip_info { @@ -113,7 +113,7 @@ static ssize_t ad7816_show_mode(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7816_chip_info *chip = iio_priv(indio_dev); if (chip->mode) @@ -127,7 +127,7 @@ static ssize_t ad7816_store_mode(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7816_chip_info *chip = iio_priv(indio_dev); if (strcmp(buf, "full")) { @@ -159,7 +159,7 @@ static ssize_t ad7816_show_channel(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7816_chip_info *chip = iio_priv(indio_dev); return sprintf(buf, "%d\n", chip->channel_id); @@ -170,14 +170,14 @@ static ssize_t ad7816_store_channel(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7816_chip_info *chip = iio_priv(indio_dev); unsigned long data; int ret; - ret = strict_strtoul(buf, 10, &data); + ret = kstrtoul(buf, 10, &data); if (ret) - return -EINVAL; + return ret; if (data > AD7816_CS_MAX && data != AD7816_CS_MASK) { dev_err(&chip->spi_dev->dev, "Invalid channel id %lu for %s.\n", @@ -208,7 +208,7 @@ static ssize_t ad7816_show_value(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7816_chip_info *chip = iio_priv(indio_dev); u16 data; s8 value; @@ -263,7 +263,7 @@ static ssize_t ad7816_show_oti(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7816_chip_info *chip = iio_priv(indio_dev); int value; @@ -284,13 +284,15 @@ static inline ssize_t ad7816_set_oti(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7816_chip_info *chip = iio_priv(indio_dev); long value; u8 data; int ret; - ret = strict_strtol(buf, 10, &value); + ret = kstrtol(buf, 10, &value); + if (ret) + return ret; if (chip->channel_id > AD7816_CS_MAX) { dev_err(dev, "Invalid oti channel id %d.\n", chip->channel_id); @@ -341,7 +343,7 @@ static const struct iio_info ad7816_info = { * device probe and remove */ -static int __devinit ad7816_probe(struct spi_device *spi_dev) +static int ad7816_probe(struct spi_device *spi_dev) { struct ad7816_chip_info *chip; struct iio_dev *indio_dev; @@ -354,11 +356,9 @@ static int __devinit ad7816_probe(struct spi_device *spi_dev) return -EINVAL; } - indio_dev = iio_allocate_device(sizeof(*chip)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&spi_dev->dev, sizeof(*chip)); + if (!indio_dev) + return -ENOMEM; chip = iio_priv(indio_dev); /* this is only used for device removal purposes */ dev_set_drvdata(&spi_dev->dev, indio_dev); @@ -370,25 +370,28 @@ static int __devinit ad7816_probe(struct spi_device *spi_dev) chip->convert_pin = pins[1]; chip->busy_pin = pins[2]; - ret = gpio_request(chip->rdwr_pin, spi_get_device_id(spi_dev)->name); + ret = devm_gpio_request(&spi_dev->dev, chip->rdwr_pin, + spi_get_device_id(spi_dev)->name); if (ret) { dev_err(&spi_dev->dev, "Fail to request rdwr gpio PIN %d.\n", chip->rdwr_pin); - goto error_free_device; + return ret; } gpio_direction_input(chip->rdwr_pin); - ret = gpio_request(chip->convert_pin, spi_get_device_id(spi_dev)->name); + ret = devm_gpio_request(&spi_dev->dev, chip->convert_pin, + spi_get_device_id(spi_dev)->name); if (ret) { dev_err(&spi_dev->dev, "Fail to request convert gpio PIN %d.\n", chip->convert_pin); - goto error_free_gpio_rdwr; + return ret; } gpio_direction_input(chip->convert_pin); - ret = gpio_request(chip->busy_pin, spi_get_device_id(spi_dev)->name); + ret = devm_gpio_request(&spi_dev->dev, chip->busy_pin, + spi_get_device_id(spi_dev)->name); if (ret) { dev_err(&spi_dev->dev, "Fail to request busy gpio PIN %d.\n", chip->busy_pin); - goto error_free_gpio_convert; + return ret; } gpio_direction_input(chip->busy_pin); @@ -399,53 +402,24 @@ static int __devinit ad7816_probe(struct spi_device *spi_dev) if (spi_dev->irq) { /* Only low trigger is supported in ad7816/7/8 */ - ret = request_threaded_irq(spi_dev->irq, - NULL, - &ad7816_event_handler, - IRQF_TRIGGER_LOW, - indio_dev->name, - indio_dev); + ret = devm_request_threaded_irq(&spi_dev->dev, spi_dev->irq, + NULL, + &ad7816_event_handler, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + indio_dev->name, + indio_dev); if (ret) - goto error_free_gpio; + return ret; } - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(&spi_dev->dev, indio_dev); if (ret) - goto error_free_irq; + return ret; dev_info(&spi_dev->dev, "%s temperature sensor and ADC registered.\n", indio_dev->name); return 0; -error_free_irq: - free_irq(spi_dev->irq, indio_dev); -error_free_gpio: - gpio_free(chip->busy_pin); -error_free_gpio_convert: - gpio_free(chip->convert_pin); -error_free_gpio_rdwr: - gpio_free(chip->rdwr_pin); -error_free_device: - iio_free_device(indio_dev); -error_ret: - return ret; -} - -static int __devexit ad7816_remove(struct spi_device *spi_dev) -{ - struct iio_dev *indio_dev = dev_get_drvdata(&spi_dev->dev); - struct ad7816_chip_info *chip = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - dev_set_drvdata(&spi_dev->dev, NULL); - if (spi_dev->irq) - free_irq(spi_dev->irq, indio_dev); - gpio_free(chip->busy_pin); - gpio_free(chip->convert_pin); - gpio_free(chip->rdwr_pin); - iio_free_device(indio_dev); - - return 0; } static const struct spi_device_id ad7816_id[] = { @@ -463,7 +437,6 @@ static struct spi_driver ad7816_driver = { .owner = THIS_MODULE, }, .probe = ad7816_probe, - .remove = __devexit_p(ad7816_remove), .id_table = ad7816_id, }; module_spi_driver(ad7816_driver); diff --git a/drivers/staging/iio/adc/ad7887.h b/drivers/staging/iio/adc/ad7887.h deleted file mode 100644 index bc53b653212..00000000000 --- a/drivers/staging/iio/adc/ad7887.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * AD7887 SPI ADC driver - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ -#ifndef IIO_ADC_AD7887_H_ -#define IIO_ADC_AD7887_H_ - -#define AD7887_REF_DIS (1 << 5) /* on-chip reference disable */ -#define AD7887_DUAL (1 << 4) /* dual-channel mode */ -#define AD7887_CH_AIN1 (1 << 3) /* convert on channel 1, DUAL=1 */ -#define AD7887_CH_AIN0 (0 << 3) /* convert on channel 0, DUAL=0,1 */ -#define AD7887_PM_MODE1 (0) /* CS based shutdown */ -#define AD7887_PM_MODE2 (1) /* full on */ -#define AD7887_PM_MODE3 (2) /* auto shutdown after conversion */ -#define AD7887_PM_MODE4 (3) /* standby mode */ - -enum ad7887_channels { - AD7887_CH0, - AD7887_CH0_CH1, - AD7887_CH1, -}; - -#define RES_MASK(bits) ((1 << (bits)) - 1) /* TODO: move this into a common header */ - -/* - * TODO: struct ad7887_platform_data needs to go into include/linux/iio - */ - -struct ad7887_platform_data { - /* External Vref voltage applied */ - u16 vref_mv; - /* - * AD7887: - * In single channel mode en_dual = flase, AIN1/Vref pins assumes its - * Vref function. In dual channel mode en_dual = true, AIN1 becomes the - * second input channel, and Vref is internally connected to Vdd. - */ - bool en_dual; - /* - * AD7887: - * use_onchip_ref = true, the Vref is internally connected to the 2.500V - * Voltage reference. If use_onchip_ref = false, the reference voltage - * is supplied by AIN1/Vref - */ - bool use_onchip_ref; -}; - -/** - * struct ad7887_chip_info - chip specifc information - * @int_vref_mv: the internal reference voltage - * @channel: channel specification - */ - -struct ad7887_chip_info { - u16 int_vref_mv; - struct iio_chan_spec channel[3]; -}; - -struct ad7887_state { - struct spi_device *spi; - const struct ad7887_chip_info *chip_info; - struct regulator *reg; - size_t d_size; - u16 int_vref_mv; - struct spi_transfer xfer[4]; - struct spi_message msg[3]; - struct spi_message *ring_msg; - unsigned char tx_cmd_buf[8]; - - /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - */ - - unsigned char data[4] ____cacheline_aligned; -}; - -enum ad7887_supported_device_ids { - ID_AD7887 -}; - -#ifdef CONFIG_IIO_BUFFER -int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev); -void ad7887_ring_cleanup(struct iio_dev *indio_dev); -#else /* CONFIG_IIO_BUFFER */ - -static inline int -ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline void ad7887_ring_cleanup(struct iio_dev *indio_dev) -{ -} -#endif /* CONFIG_IIO_BUFFER */ -#endif /* IIO_ADC_AD7887_H_ */ diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c deleted file mode 100644 index e9bbc3eed15..00000000000 --- a/drivers/staging/iio/adc/ad7887_core.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * AD7887 SPI ADC driver - * - * Copyright 2010-2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/spi/spi.h> -#include <linux/regulator/consumer.h> -#include <linux/err.h> -#include <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" - - -#include "ad7887.h" - -static int ad7887_scan_direct(struct ad7887_state *st, unsigned ch) -{ - int ret = spi_sync(st->spi, &st->msg[ch]); - if (ret) - return ret; - - return (st->data[(ch * 2)] << 8) | st->data[(ch * 2) + 1]; -} - -static int ad7887_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - int ret; - struct ad7887_state *st = iio_priv(indio_dev); - unsigned int scale_uv; - - switch (m) { - case 0: - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) - ret = -EBUSY; - else - ret = ad7887_scan_direct(st, chan->address); - mutex_unlock(&indio_dev->mlock); - - if (ret < 0) - return ret; - *val = (ret >> st->chip_info->channel[0].scan_type.shift) & - RES_MASK(st->chip_info->channel[0].scan_type.realbits); - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - scale_uv = (st->int_vref_mv * 1000) - >> st->chip_info->channel[0].scan_type.realbits; - *val = scale_uv/1000; - *val2 = (scale_uv%1000)*1000; - return IIO_VAL_INT_PLUS_MICRO; - } - return -EINVAL; -} - - -static const struct ad7887_chip_info ad7887_chip_info_tbl[] = { - /* - * More devices added in future - */ - [ID_AD7887] = { - .channel[0] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, - .address = 1, - .scan_index = 1, - .scan_type = IIO_ST('u', 12, 16, 0), - }, - .channel[1] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, - .address = 0, - .scan_index = 0, - .scan_type = IIO_ST('u', 12, 16, 0), - }, - .channel[2] = IIO_CHAN_SOFT_TIMESTAMP(2), - .int_vref_mv = 2500, - }, -}; - -static const struct iio_info ad7887_info = { - .read_raw = &ad7887_read_raw, - .driver_module = THIS_MODULE, -}; - -static int __devinit ad7887_probe(struct spi_device *spi) -{ - struct ad7887_platform_data *pdata = spi->dev.platform_data; - struct ad7887_state *st; - int ret, voltage_uv = 0; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); - - if (indio_dev == NULL) - return -ENOMEM; - - st = iio_priv(indio_dev); - - st->reg = regulator_get(&spi->dev, "vcc"); - if (!IS_ERR(st->reg)) { - ret = regulator_enable(st->reg); - if (ret) - goto error_put_reg; - - voltage_uv = regulator_get_voltage(st->reg); - } - - st->chip_info = - &ad7887_chip_info_tbl[spi_get_device_id(spi)->driver_data]; - - spi_set_drvdata(spi, indio_dev); - st->spi = spi; - - /* Estabilish that the iio_dev is a child of the spi device */ - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->info = &ad7887_info; - indio_dev->modes = INDIO_DIRECT_MODE; - - /* Setup default message */ - - st->tx_cmd_buf[0] = AD7887_CH_AIN0 | AD7887_PM_MODE4 | - ((pdata && pdata->use_onchip_ref) ? - 0 : AD7887_REF_DIS); - - st->xfer[0].rx_buf = &st->data[0]; - st->xfer[0].tx_buf = &st->tx_cmd_buf[0]; - st->xfer[0].len = 2; - - spi_message_init(&st->msg[AD7887_CH0]); - spi_message_add_tail(&st->xfer[0], &st->msg[AD7887_CH0]); - - if (pdata && pdata->en_dual) { - st->tx_cmd_buf[0] |= AD7887_DUAL | AD7887_REF_DIS; - - st->tx_cmd_buf[2] = AD7887_CH_AIN1 | AD7887_DUAL | - AD7887_REF_DIS | AD7887_PM_MODE4; - st->tx_cmd_buf[4] = AD7887_CH_AIN0 | AD7887_DUAL | - AD7887_REF_DIS | AD7887_PM_MODE4; - st->tx_cmd_buf[6] = AD7887_CH_AIN1 | AD7887_DUAL | - AD7887_REF_DIS | AD7887_PM_MODE4; - - st->xfer[1].rx_buf = &st->data[0]; - st->xfer[1].tx_buf = &st->tx_cmd_buf[2]; - st->xfer[1].len = 2; - - st->xfer[2].rx_buf = &st->data[2]; - st->xfer[2].tx_buf = &st->tx_cmd_buf[4]; - st->xfer[2].len = 2; - - spi_message_init(&st->msg[AD7887_CH0_CH1]); - spi_message_add_tail(&st->xfer[1], &st->msg[AD7887_CH0_CH1]); - spi_message_add_tail(&st->xfer[2], &st->msg[AD7887_CH0_CH1]); - - st->xfer[3].rx_buf = &st->data[0]; - st->xfer[3].tx_buf = &st->tx_cmd_buf[6]; - st->xfer[3].len = 2; - - spi_message_init(&st->msg[AD7887_CH1]); - spi_message_add_tail(&st->xfer[3], &st->msg[AD7887_CH1]); - - 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"); - - indio_dev->channels = st->chip_info->channel; - indio_dev->num_channels = 3; - } else { - if (pdata && pdata->vref_mv) - st->int_vref_mv = pdata->vref_mv; - else if (pdata && pdata->use_onchip_ref) - st->int_vref_mv = st->chip_info->int_vref_mv; - else - dev_warn(&spi->dev, "reference voltage unspecified\n"); - - indio_dev->channels = &st->chip_info->channel[1]; - indio_dev->num_channels = 2; - } - - ret = ad7887_register_ring_funcs_and_init(indio_dev); - if (ret) - goto error_disable_reg; - - ret = iio_buffer_register(indio_dev, - indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_cleanup_ring; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_unregister_ring; - - return 0; -error_unregister_ring: - iio_buffer_unregister(indio_dev); -error_cleanup_ring: - ad7887_ring_cleanup(indio_dev); -error_disable_reg: - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); -error_put_reg: - if (!IS_ERR(st->reg)) - regulator_put(st->reg); - iio_free_device(indio_dev); - - return ret; -} - -static int ad7887_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad7887_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); - ad7887_ring_cleanup(indio_dev); - if (!IS_ERR(st->reg)) { - regulator_disable(st->reg); - regulator_put(st->reg); - } - iio_free_device(indio_dev); - - return 0; -} - -static const struct spi_device_id ad7887_id[] = { - {"ad7887", ID_AD7887}, - {} -}; -MODULE_DEVICE_TABLE(spi, ad7887_id); - -static struct spi_driver ad7887_driver = { - .driver = { - .name = "ad7887", - .owner = THIS_MODULE, - }, - .probe = ad7887_probe, - .remove = __devexit_p(ad7887_remove), - .id_table = ad7887_id, -}; -module_spi_driver(ad7887_driver); - -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("Analog Devices AD7887 ADC"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c deleted file mode 100644 index 85076cd962e..00000000000 --- a/drivers/staging/iio/adc/ad7887_ring.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2010-2011 Analog Devices Inc. - * Copyright (C) 2008 Jonathan Cameron - * - * Licensed under the GPL-2. - * - * ad7887_ring.c - */ - -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/spi/spi.h> - -#include "../iio.h" -#include "../buffer.h" -#include "../ring_sw.h" -#include "../trigger_consumer.h" - -#include "ad7887.h" - -/** - * ad7887_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 ad7887_ring_preenable(struct iio_dev *indio_dev) -{ - struct ad7887_state *st = iio_priv(indio_dev); - struct iio_buffer *ring = indio_dev->buffer; - - st->d_size = bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength) * - st->chip_info->channel[0].scan_type.storagebits / 8; - - if (ring->scan_timestamp) { - st->d_size += sizeof(s64); - - if (st->d_size % sizeof(s64)) - st->d_size += sizeof(s64) - (st->d_size % sizeof(s64)); - } - - if (indio_dev->buffer->access->set_bytes_per_datum) - indio_dev->buffer->access-> - set_bytes_per_datum(indio_dev->buffer, st->d_size); - - /* We know this is a single long so can 'cheat' */ - switch (*indio_dev->active_scan_mask) { - case (1 << 0): - st->ring_msg = &st->msg[AD7887_CH0]; - break; - case (1 << 1): - st->ring_msg = &st->msg[AD7887_CH1]; - /* Dummy read: push CH1 setting down to hardware */ - spi_sync(st->spi, st->ring_msg); - break; - case ((1 << 1) | (1 << 0)): - st->ring_msg = &st->msg[AD7887_CH0_CH1]; - break; - } - - return 0; -} - -static int ad7887_ring_postdisable(struct iio_dev *indio_dev) -{ - struct ad7887_state *st = iio_priv(indio_dev); - - /* dummy read: restore default CH0 settin */ - return spi_sync(st->spi, &st->msg[AD7887_CH0]); -} - -/** - * ad7887_trigger_handler() bh of trigger launched polling to ring buffer - * - * Currently there is no option in this driver to disable the saving of - * timestamps within the ring. - **/ -static irqreturn_t ad7887_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct ad7887_state *st = iio_priv(indio_dev); - struct iio_buffer *ring = indio_dev->buffer; - s64 time_ns; - __u8 *buf; - int b_sent; - - unsigned int bytes = bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength) * - st->chip_info->channel[0].scan_type.storagebits / 8; - - buf = kzalloc(st->d_size, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - b_sent = spi_sync(st->spi, st->ring_msg); - if (b_sent) - goto done; - - time_ns = iio_get_time_ns(); - - memcpy(buf, st->data, bytes); - if (ring->scan_timestamp) - memcpy(buf + st->d_size - sizeof(s64), - &time_ns, sizeof(time_ns)); - - indio_dev->buffer->access->store_to(indio_dev->buffer, buf, time_ns); -done: - kfree(buf); - iio_trigger_notify_done(indio_dev->trig); - - return IRQ_HANDLED; -} - -static const struct iio_buffer_setup_ops ad7887_ring_setup_ops = { - .preenable = &ad7887_ring_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, - .postdisable = &ad7887_ring_postdisable, -}; - -int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev) -{ - int ret; - - indio_dev->buffer = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->buffer) { - ret = -ENOMEM; - goto error_ret; - } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, - &ad7887_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "ad7887_consumer%d", - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_deallocate_sw_rb; - } - /* Ring buffer functions - here trigger setup related */ - indio_dev->setup_ops = &ad7887_ring_setup_ops; - - /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_deallocate_sw_rb: - iio_sw_rb_free(indio_dev->buffer); -error_ret: - return ret; -} - -void ad7887_ring_cleanup(struct iio_dev *indio_dev) -{ - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->buffer); -} diff --git a/drivers/staging/iio/adc/ad799x.h b/drivers/staging/iio/adc/ad799x.h deleted file mode 100644 index 356f690a76f..00000000000 --- a/drivers/staging/iio/adc/ad799x.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2010-2011 Michael Hennerich, Analog Devices Inc. - * Copyright (C) 2008-2010 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify - * 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 -/* TODO: move this into a common header */ -#define RES_MASK(bits) ((1 << (bits)) - 1) - -enum { - ad7991, - ad7995, - ad7999, - ad7992, - ad7993, - ad7994, - ad7997, - ad7998 -}; - -struct ad799x_state; - -/** - * struct ad799x_chip_info - chip specifc information - * @channel: channel specification - * @num_channels: number of channels - * @int_vref_mv: the internal reference voltage - * @monitor_mode: whether the chip supports monitor interrupts - * @default_config: device default configuration - * @event_attrs: pointer to the monitor event attribute group - */ - -struct ad799x_chip_info { - struct iio_chan_spec channel[9]; - int num_channels; - u16 int_vref_mv; - u16 default_config; - const struct iio_info *info; -}; - -struct ad799x_state { - struct i2c_client *client; - const struct ad799x_chip_info *chip_info; - size_t d_size; - struct iio_trigger *trig; - struct regulator *reg; - 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 ad7997_8_set_scan_mode(struct ad799x_state *st, unsigned mask); - -#ifdef CONFIG_AD799X_RING_BUFFER -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 */ - -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 deleted file mode 100644 index d5b581d8bc2..00000000000 --- a/drivers/staging/iio/adc/ad799x_core.c +++ /dev/null @@ -1,936 +0,0 @@ -/* - * iio/adc/ad799x.c - * Copyright (C) 2010-1011 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/device.h> -#include <linux/kernel.h> -#include <linux/sysfs.h> -#include <linux/i2c.h> -#include <linux/regulator/consumer.h> -#include <linux/slab.h> -#include <linux/types.h> -#include <linux/err.h> -#include <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" -#include "../buffer.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; -} - -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)); -} - -static int ad799x_scan_direct(struct ad799x_state *st, unsigned ch) -{ - u16 rxbuf; - u8 cmd; - int ret; - - switch (st->id) { - case ad7991: - case ad7995: - case ad7999: - cmd = st->config | ((1 << ch) << AD799X_CHANNEL_SHIFT); - break; - case ad7992: - case ad7993: - case ad7994: - cmd = (1 << ch) << AD799X_CHANNEL_SHIFT; - break; - case ad7997: - case ad7998: - cmd = (ch << AD799X_CHANNEL_SHIFT) | AD7997_8_READ_SINGLE; - break; - default: - return -EINVAL; - } - - ret = ad799x_i2c_read16(st, cmd, &rxbuf); - if (ret < 0) - return ret; - - return rxbuf; -} - -static int ad799x_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - int ret; - struct ad799x_state *st = iio_priv(indio_dev); - unsigned int scale_uv; - - switch (m) { - case 0: - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) - ret = -EBUSY; - else - ret = ad799x_scan_direct(st, chan->scan_index); - mutex_unlock(&indio_dev->mlock); - - if (ret < 0) - return ret; - *val = (ret >> chan->scan_type.shift) & - RES_MASK(chan->scan_type.realbits); - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - scale_uv = (st->int_vref_mv * 1000) >> chan->scan_type.realbits; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; - } - return -EINVAL; -} -static const unsigned int ad7998_frequencies[] = { - [AD7998_CYC_DIS] = 0, - [AD7998_CYC_TCONF_32] = 15625, - [AD7998_CYC_TCONF_64] = 7812, - [AD7998_CYC_TCONF_128] = 3906, - [AD7998_CYC_TCONF_512] = 976, - [AD7998_CYC_TCONF_1024] = 488, - [AD7998_CYC_TCONF_2048] = 244, -}; -static ssize_t ad799x_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad799x_state *st = iio_priv(indio_dev); - - int ret; - u8 val; - ret = ad799x_i2c_read8(st, AD7998_CYCLE_TMR_REG, &val); - if (ret) - return ret; - - val &= AD7998_CYC_MASK; - - return sprintf(buf, "%u\n", ad7998_frequencies[val]); -} - -static ssize_t ad799x_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad799x_state *st = iio_priv(indio_dev); - - long val; - int ret, i; - u8 t; - - ret = strict_strtol(buf, 10, &val); - if (ret) - return ret; - - mutex_lock(&indio_dev->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; - - for (i = 0; i < ARRAY_SIZE(ad7998_frequencies); i++) - if (val == ad7998_frequencies[i]) - break; - if (i == ARRAY_SIZE(ad7998_frequencies)) { - ret = -EINVAL; - goto error_ret_mutex; - } - t |= i; - ret = ad799x_i2c_write8(st, AD7998_CYCLE_TMR_REG, t); - -error_ret_mutex: - mutex_unlock(&indio_dev->mlock); - - return ret ? ret : len; -} - -static int ad799x_read_event_config(struct iio_dev *indio_dev, - u64 event_code) -{ - return 1; -} - -static const u8 ad799x_threshold_addresses[][2] = { - { AD7998_DATALOW_CH1_REG, AD7998_DATAHIGH_CH1_REG }, - { AD7998_DATALOW_CH2_REG, AD7998_DATAHIGH_CH2_REG }, - { AD7998_DATALOW_CH3_REG, AD7998_DATAHIGH_CH3_REG }, - { AD7998_DATALOW_CH4_REG, AD7998_DATAHIGH_CH4_REG }, -}; - -static int ad799x_write_event_value(struct iio_dev *indio_dev, - u64 event_code, - int val) -{ - int ret; - struct ad799x_state *st = iio_priv(indio_dev); - int direction = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_FALLING); - int number = IIO_EVENT_CODE_EXTRACT_NUM(event_code); - - mutex_lock(&indio_dev->mlock); - ret = ad799x_i2c_write16(st, - ad799x_threshold_addresses[number][direction], - val); - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static int ad799x_read_event_value(struct iio_dev *indio_dev, - u64 event_code, - int *val) -{ - int ret; - struct ad799x_state *st = iio_priv(indio_dev); - int direction = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_FALLING); - int number = IIO_EVENT_CODE_EXTRACT_NUM(event_code); - u16 valin; - - mutex_lock(&indio_dev->mlock); - ret = ad799x_i2c_read16(st, - ad799x_threshold_addresses[number][direction], - &valin); - mutex_unlock(&indio_dev->mlock); - if (ret < 0) - return ret; - *val = valin; - - return 0; -} - -static ssize_t ad799x_read_channel_config(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad799x_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - int ret; - u16 val; - ret = ad799x_i2c_read16(st, this_attr->address, &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 *indio_dev = dev_get_drvdata(dev); - struct ad799x_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - long val; - int ret; - - ret = strict_strtol(buf, 10, &val); - if (ret) - return ret; - - mutex_lock(&indio_dev->mlock); - ret = ad799x_i2c_write16(st, this_attr->address, val); - mutex_unlock(&indio_dev->mlock); - - return ret ? ret : len; -} - -static irqreturn_t ad799x_event_handler(int irq, void *private) -{ - struct iio_dev *indio_dev = private; - struct ad799x_state *st = iio_priv(private); - u8 status; - int i, ret; - - ret = ad799x_i2c_read8(st, AD7998_ALERT_STAT_REG, &status); - if (ret) - return ret; - - if (!status) - return -EIO; - - ad799x_i2c_write8(st, AD7998_ALERT_STAT_REG, AD7998_ALERT_STAT_CLEAR); - - for (i = 0; i < 8; i++) { - if (status & (1 << i)) - iio_push_event(indio_dev, - i & 0x1 ? - IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, - (i >> 1), - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING) : - IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, - (i >> 1), - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING), - iio_get_time_ns()); - } - - return IRQ_HANDLED; -} - -static IIO_DEVICE_ATTR(in_voltage0_thresh_both_hyst_raw, - S_IRUGO | S_IWUSR, - ad799x_read_channel_config, - ad799x_write_channel_config, - AD7998_HYST_CH1_REG); - -static IIO_DEVICE_ATTR(in_voltage1_thresh_both_hyst_raw, - S_IRUGO | S_IWUSR, - ad799x_read_channel_config, - ad799x_write_channel_config, - AD7998_HYST_CH2_REG); - -static IIO_DEVICE_ATTR(in_voltage2_thresh_both_hyst_raw, - S_IRUGO | S_IWUSR, - ad799x_read_channel_config, - ad799x_write_channel_config, - AD7998_HYST_CH3_REG); - -static IIO_DEVICE_ATTR(in_voltage3_thresh_both_hyst_raw, - S_IRUGO | S_IWUSR, - ad799x_read_channel_config, - ad799x_write_channel_config, - AD7998_HYST_CH4_REG); - -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - ad799x_read_frequency, - 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_dev_attr_in_voltage0_thresh_both_hyst_raw.dev_attr.attr, - &iio_dev_attr_in_voltage1_thresh_both_hyst_raw.dev_attr.attr, - &iio_dev_attr_in_voltage2_thresh_both_hyst_raw.dev_attr.attr, - &iio_dev_attr_in_voltage3_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, - .name = "events", -}; - -static struct attribute *ad7992_event_attributes[] = { - &iio_dev_attr_in_voltage0_thresh_both_hyst_raw.dev_attr.attr, - &iio_dev_attr_in_voltage1_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, - .name = "events", -}; - -static const struct iio_info ad7991_info = { - .read_raw = &ad799x_read_raw, - .driver_module = THIS_MODULE, -}; - -static const struct iio_info ad7992_info = { - .read_raw = &ad799x_read_raw, - .event_attrs = &ad7992_event_attrs_group, - .read_event_config = &ad799x_read_event_config, - .read_event_value = &ad799x_read_event_value, - .write_event_value = &ad799x_write_event_value, - .driver_module = THIS_MODULE, -}; - -static const struct iio_info ad7993_4_7_8_info = { - .read_raw = &ad799x_read_raw, - .event_attrs = &ad7993_4_7_8_event_attrs_group, - .read_event_config = &ad799x_read_event_config, - .read_event_value = &ad799x_read_event_value, - .write_event_value = &ad799x_write_event_value, - .driver_module = THIS_MODULE, -}; - -#define AD799X_EV_MASK (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | \ - IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)) - -static const struct ad799x_chip_info ad799x_chip_info_tbl[] = { - [ad7991] = { - .channel = { - [0] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .scan_index = 0, - .scan_type = IIO_ST('u', 12, 16, 0), - }, - [1] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .scan_index = 1, - .scan_type = IIO_ST('u', 12, 16, 0), - }, - [2] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 2, - .scan_index = 2, - .scan_type = IIO_ST('u', 12, 16, 0), - }, - [3] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 3, - .scan_index = 3, - .scan_type = IIO_ST('u', 12, 16, 0), - }, - [4] = IIO_CHAN_SOFT_TIMESTAMP(4), - }, - .num_channels = 5, - .int_vref_mv = 4096, - .info = &ad7991_info, - }, - [ad7995] = { - .channel = { - [0] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .scan_index = 0, - .scan_type = IIO_ST('u', 10, 16, 2), - }, - [1] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .scan_index = 1, - .scan_type = IIO_ST('u', 10, 16, 2), - }, - [2] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 2, - .scan_index = 2, - .scan_type = IIO_ST('u', 10, 16, 2), - }, - [3] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 3, - .scan_index = 3, - .scan_type = IIO_ST('u', 10, 16, 2), - }, - [4] = IIO_CHAN_SOFT_TIMESTAMP(4), - }, - .num_channels = 5, - .int_vref_mv = 1024, - .info = &ad7991_info, - }, - [ad7999] = { - .channel = { - [0] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .scan_index = 0, - .scan_type = IIO_ST('u', 8, 16, 4), - }, - [1] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .scan_index = 1, - .scan_type = IIO_ST('u', 8, 16, 4), - }, - [2] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 2, - .scan_index = 2, - .scan_type = IIO_ST('u', 8, 16, 4), - }, - [3] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 3, - .scan_index = 3, - .scan_type = IIO_ST('u', 8, 16, 4), - }, - [4] = IIO_CHAN_SOFT_TIMESTAMP(4), - }, - .num_channels = 5, - .int_vref_mv = 1024, - .info = &ad7991_info, - }, - [ad7992] = { - .channel = { - [0] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .scan_index = 0, - .scan_type = IIO_ST('u', 12, 16, 0), - .event_mask = AD799X_EV_MASK, - }, - [1] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .scan_index = 1, - .scan_type = IIO_ST('u', 12, 16, 0), - .event_mask = AD799X_EV_MASK, - }, - [2] = IIO_CHAN_SOFT_TIMESTAMP(2), - }, - .num_channels = 3, - .int_vref_mv = 4096, - .default_config = AD7998_ALERT_EN, - .info = &ad7992_info, - }, - [ad7993] = { - .channel = { - [0] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .scan_index = 0, - .scan_type = IIO_ST('u', 10, 16, 2), - .event_mask = AD799X_EV_MASK, - }, - [1] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .scan_index = 1, - .scan_type = IIO_ST('u', 10, 16, 2), - .event_mask = AD799X_EV_MASK, - }, - [2] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 2, - .scan_index = 2, - .scan_type = IIO_ST('u', 10, 16, 2), - .event_mask = AD799X_EV_MASK, - }, - [3] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 3, - .scan_index = 3, - .scan_type = IIO_ST('u', 10, 16, 2), - .event_mask = AD799X_EV_MASK, - }, - [4] = IIO_CHAN_SOFT_TIMESTAMP(4), - }, - .num_channels = 5, - .int_vref_mv = 1024, - .default_config = AD7998_ALERT_EN, - .info = &ad7993_4_7_8_info, - }, - [ad7994] = { - .channel = { - [0] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .scan_index = 0, - .scan_type = IIO_ST('u', 12, 16, 0), - .event_mask = AD799X_EV_MASK, - }, - [1] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .scan_index = 1, - .scan_type = IIO_ST('u', 12, 16, 0), - .event_mask = AD799X_EV_MASK, - }, - [2] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 2, - .scan_index = 2, - .scan_type = IIO_ST('u', 12, 16, 0), - .event_mask = AD799X_EV_MASK, - }, - [3] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 3, - .scan_index = 3, - .scan_type = IIO_ST('u', 12, 16, 0), - .event_mask = AD799X_EV_MASK, - }, - [4] = IIO_CHAN_SOFT_TIMESTAMP(4), - }, - .num_channels = 5, - .int_vref_mv = 4096, - .default_config = AD7998_ALERT_EN, - .info = &ad7993_4_7_8_info, - }, - [ad7997] = { - .channel = { - [0] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .scan_index = 0, - .scan_type = IIO_ST('u', 10, 16, 2), - .event_mask = AD799X_EV_MASK, - }, - [1] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .scan_index = 1, - .scan_type = IIO_ST('u', 10, 16, 2), - .event_mask = AD799X_EV_MASK, - }, - [2] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 2, - .scan_index = 2, - .scan_type = IIO_ST('u', 10, 16, 2), - .event_mask = AD799X_EV_MASK, - }, - [3] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 3, - .scan_index = 3, - .scan_type = IIO_ST('u', 10, 16, 2), - .event_mask = AD799X_EV_MASK, - }, - [4] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 4, - .scan_index = 4, - .scan_type = IIO_ST('u', 10, 16, 2), - }, - [5] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 5, - .scan_index = 5, - .scan_type = IIO_ST('u', 10, 16, 2), - }, - [6] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 6, - .scan_index = 6, - .scan_type = IIO_ST('u', 10, 16, 2), - }, - [7] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 7, - .scan_index = 7, - .scan_type = IIO_ST('u', 10, 16, 2), - }, - [8] = IIO_CHAN_SOFT_TIMESTAMP(8), - }, - .num_channels = 9, - .int_vref_mv = 1024, - .default_config = AD7998_ALERT_EN, - .info = &ad7993_4_7_8_info, - }, - [ad7998] = { - .channel = { - [0] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .scan_index = 0, - .scan_type = IIO_ST('u', 12, 16, 0), - .event_mask = AD799X_EV_MASK, - }, - [1] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .scan_index = 1, - .scan_type = IIO_ST('u', 12, 16, 0), - .event_mask = AD799X_EV_MASK, - }, - [2] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 2, - .scan_index = 2, - .scan_type = IIO_ST('u', 12, 16, 0), - .event_mask = AD799X_EV_MASK, - }, - [3] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 3, - .scan_index = 3, - .scan_type = IIO_ST('u', 12, 16, 0), - .event_mask = AD799X_EV_MASK, - }, - [4] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 4, - .scan_index = 4, - .scan_type = IIO_ST('u', 12, 16, 0), - }, - [5] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 5, - .scan_index = 5, - .scan_type = IIO_ST('u', 12, 16, 0), - }, - [6] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 6, - .scan_index = 6, - .scan_type = IIO_ST('u', 12, 16, 0), - }, - [7] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 7, - .scan_index = 7, - .scan_type = IIO_ST('u', 12, 16, 0), - }, - [8] = IIO_CHAN_SOFT_TIMESTAMP(8), - }, - .num_channels = 9, - .int_vref_mv = 4096, - .default_config = AD7998_ALERT_EN, - .info = &ad7993_4_7_8_info, - }, -}; - -static int __devinit ad799x_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int ret; - struct ad799x_platform_data *pdata = client->dev.platform_data; - struct ad799x_state *st; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); - - if (indio_dev == NULL) - return -ENOMEM; - - st = iio_priv(indio_dev); - /* this is only used for device removal purposes */ - i2c_set_clientdata(client, indio_dev); - - 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; - - indio_dev->dev.parent = &client->dev; - indio_dev->name = id->name; - indio_dev->info = st->chip_info->info; - - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = st->chip_info->channel; - indio_dev->num_channels = st->chip_info->num_channels; - - ret = ad799x_register_ring_funcs_and_init(indio_dev); - if (ret) - goto error_disable_reg; - - ret = iio_buffer_register(indio_dev, - indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_cleanup_ring; - - if (client->irq > 0) { - ret = request_threaded_irq(client->irq, - NULL, - ad799x_event_handler, - IRQF_TRIGGER_FALLING | - IRQF_ONESHOT, - client->name, - indio_dev); - if (ret) - goto error_cleanup_ring; - } - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_irq; - - return 0; - -error_free_irq: - free_irq(client->irq, indio_dev); -error_cleanup_ring: - ad799x_ring_cleanup(indio_dev); -error_disable_reg: - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); -error_put_reg: - if (!IS_ERR(st->reg)) - regulator_put(st->reg); - iio_free_device(indio_dev); - - return ret; -} - -static __devexit int ad799x_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct ad799x_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - if (client->irq > 0) - free_irq(client->irq, indio_dev); - - iio_buffer_unregister(indio_dev); - ad799x_ring_cleanup(indio_dev); - if (!IS_ERR(st->reg)) { - regulator_disable(st->reg); - regulator_put(st->reg); - } - iio_free_device(indio_dev); - - 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, -}; -module_i2c_driver(ad799x_driver); - -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("Analog Devices AD799x ADC"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c deleted file mode 100644 index 5dded9e7820..00000000000 --- a/drivers/staging/iio/adc/ad799x_ring.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * 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/slab.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/i2c.h> -#include <linux/bitops.h> - -#include "../iio.h" -#include "../buffer.h" -#include "../ring_sw.h" -#include "../trigger_consumer.h" - -#include "ad799x.h" - -/** - * 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_buffer *ring = indio_dev->buffer; - struct ad799x_state *st = iio_priv(indio_dev); - - /* - * Need to figure out the current mode based upon the requested - * scan mask in iio_dev - */ - - if (st->id == ad7997 || st->id == ad7998) - ad7997_8_set_scan_mode(st, *indio_dev->active_scan_mask); - - st->d_size = bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength) * 2; - - if (ring->scan_timestamp) { - st->d_size += sizeof(s64); - - if (st->d_size % sizeof(s64)) - st->d_size += sizeof(s64) - (st->d_size % sizeof(s64)); - } - - if (indio_dev->buffer->access->set_bytes_per_datum) - indio_dev->buffer->access-> - set_bytes_per_datum(indio_dev->buffer, st->d_size); - - return 0; -} - -/** - * ad799x_trigger_handler() bh of trigger launched polling to ring buffer - * - * Currently there is no option in this driver to disable the saving of - * timestamps within the ring. - **/ - -static irqreturn_t ad799x_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct ad799x_state *st = iio_priv(indio_dev); - struct iio_buffer *ring = indio_dev->buffer; - s64 time_ns; - __u8 *rxbuf; - int b_sent; - u8 cmd; - - rxbuf = kmalloc(st->d_size, GFP_KERNEL); - if (rxbuf == NULL) - goto out; - - switch (st->id) { - case ad7991: - case ad7995: - case ad7999: - cmd = st->config | - (*indio_dev->active_scan_mask << AD799X_CHANNEL_SHIFT); - break; - case ad7992: - case ad7993: - case ad7994: - cmd = (*indio_dev->active_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, bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength) * 2, rxbuf); - if (b_sent < 0) - goto done; - - time_ns = iio_get_time_ns(); - - if (ring->scan_timestamp) - memcpy(rxbuf + st->d_size - sizeof(s64), - &time_ns, sizeof(time_ns)); - - ring->access->store_to(indio_dev->buffer, rxbuf, time_ns); -done: - kfree(rxbuf); - if (b_sent < 0) - return b_sent; -out: - iio_trigger_notify_done(indio_dev->trig); - - return IRQ_HANDLED; -} - -static const struct iio_buffer_setup_ops ad799x_buf_setup_ops = { - .preenable = &ad799x_ring_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, -}; - -int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev) -{ - int ret = 0; - - indio_dev->buffer = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->buffer) { - ret = -ENOMEM; - goto error_ret; - } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; - indio_dev->pollfunc = iio_alloc_pollfunc(NULL, - &ad799x_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "%s_consumer%d", - indio_dev->name, - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_deallocate_sw_rb; - } - - /* Ring buffer functions - here trigger setup related */ - indio_dev->setup_ops = &ad799x_buf_setup_ops; - indio_dev->buffer->scan_timestamp = true; - - /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_deallocate_sw_rb: - iio_sw_rb_free(indio_dev->buffer); -error_ret: - return ret; -} - -void ad799x_ring_cleanup(struct iio_dev *indio_dev) -{ - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->buffer); -} diff --git a/drivers/staging/iio/adc/adt7310.c b/drivers/staging/iio/adc/adt7310.c deleted file mode 100644 index eec2f325d54..00000000000 --- a/drivers/staging/iio/adc/adt7310.c +++ /dev/null @@ -1,891 +0,0 @@ -/* - * ADT7310 digital temperature sensor driver supporting ADT7310 - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/interrupt.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/module.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" -/* - * ADT7310 registers definition - */ - -#define ADT7310_STATUS 0 -#define ADT7310_CONFIG 1 -#define ADT7310_TEMPERATURE 2 -#define ADT7310_ID 3 -#define ADT7310_T_CRIT 4 -#define ADT7310_T_HYST 5 -#define ADT7310_T_ALARM_HIGH 6 -#define ADT7310_T_ALARM_LOW 7 - -/* - * ADT7310 status - */ -#define ADT7310_STAT_T_LOW 0x10 -#define ADT7310_STAT_T_HIGH 0x20 -#define ADT7310_STAT_T_CRIT 0x40 -#define ADT7310_STAT_NOT_RDY 0x80 - -/* - * ADT7310 config - */ -#define ADT7310_FAULT_QUEUE_MASK 0x3 -#define ADT7310_CT_POLARITY 0x4 -#define ADT7310_INT_POLARITY 0x8 -#define ADT7310_EVENT_MODE 0x10 -#define ADT7310_MODE_MASK 0x60 -#define ADT7310_ONESHOT 0x20 -#define ADT7310_SPS 0x40 -#define ADT7310_PD 0x60 -#define ADT7310_RESOLUTION 0x80 - -/* - * ADT7310 masks - */ -#define ADT7310_T16_VALUE_SIGN 0x8000 -#define ADT7310_T16_VALUE_FLOAT_OFFSET 7 -#define ADT7310_T16_VALUE_FLOAT_MASK 0x7F -#define ADT7310_T13_VALUE_SIGN 0x1000 -#define ADT7310_T13_VALUE_OFFSET 3 -#define ADT7310_T13_VALUE_FLOAT_OFFSET 4 -#define ADT7310_T13_VALUE_FLOAT_MASK 0xF -#define ADT7310_T_HYST_MASK 0xF -#define ADT7310_DEVICE_ID_MASK 0x7 -#define ADT7310_MANUFACTORY_ID_MASK 0xF8 -#define ADT7310_MANUFACTORY_ID_OFFSET 3 - - -#define ADT7310_CMD_REG_MASK 0x28 -#define ADT7310_CMD_REG_OFFSET 3 -#define ADT7310_CMD_READ 0x40 -#define ADT7310_CMD_CON_READ 0x4 - -#define ADT7310_IRQS 2 - -/* - * struct adt7310_chip_info - chip specifc information - */ - -struct adt7310_chip_info { - struct spi_device *spi_dev; - u8 config; -}; - -/* - * adt7310 register access by SPI - */ - -static int adt7310_spi_read_word(struct adt7310_chip_info *chip, u8 reg, u16 *data) -{ - struct spi_device *spi_dev = chip->spi_dev; - u8 command = (reg << ADT7310_CMD_REG_OFFSET) & ADT7310_CMD_REG_MASK; - int ret = 0; - - command |= ADT7310_CMD_READ; - ret = spi_write(spi_dev, &command, sizeof(command)); - if (ret < 0) { - dev_err(&spi_dev->dev, "SPI write command error\n"); - return ret; - } - - ret = spi_read(spi_dev, (u8 *)data, sizeof(*data)); - if (ret < 0) { - dev_err(&spi_dev->dev, "SPI read word error\n"); - return ret; - } - - *data = be16_to_cpu(*data); - - return 0; -} - -static int adt7310_spi_write_word(struct adt7310_chip_info *chip, u8 reg, u16 data) -{ - struct spi_device *spi_dev = chip->spi_dev; - u8 buf[3]; - int ret = 0; - - buf[0] = (reg << ADT7310_CMD_REG_OFFSET) & ADT7310_CMD_REG_MASK; - buf[1] = (u8)(data >> 8); - buf[2] = (u8)(data & 0xFF); - - ret = spi_write(spi_dev, buf, 3); - if (ret < 0) { - dev_err(&spi_dev->dev, "SPI write word error\n"); - return ret; - } - - return ret; -} - -static int adt7310_spi_read_byte(struct adt7310_chip_info *chip, u8 reg, u8 *data) -{ - struct spi_device *spi_dev = chip->spi_dev; - u8 command = (reg << ADT7310_CMD_REG_OFFSET) & ADT7310_CMD_REG_MASK; - int ret = 0; - - command |= ADT7310_CMD_READ; - ret = spi_write(spi_dev, &command, sizeof(command)); - if (ret < 0) { - dev_err(&spi_dev->dev, "SPI write command error\n"); - return ret; - } - - ret = spi_read(spi_dev, data, sizeof(*data)); - if (ret < 0) { - dev_err(&spi_dev->dev, "SPI read byte error\n"); - return ret; - } - - return 0; -} - -static int adt7310_spi_write_byte(struct adt7310_chip_info *chip, u8 reg, u8 data) -{ - struct spi_device *spi_dev = chip->spi_dev; - u8 buf[2]; - int ret = 0; - - buf[0] = (reg << ADT7310_CMD_REG_OFFSET) & ADT7310_CMD_REG_MASK; - buf[1] = data; - - ret = spi_write(spi_dev, buf, 2); - if (ret < 0) { - dev_err(&spi_dev->dev, "SPI write byte error\n"); - return ret; - } - - return ret; -} - -static ssize_t adt7310_show_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7310_chip_info *chip = iio_priv(dev_info); - u8 config; - - config = chip->config & ADT7310_MODE_MASK; - - switch (config) { - case ADT7310_PD: - return sprintf(buf, "power-down\n"); - case ADT7310_ONESHOT: - return sprintf(buf, "one-shot\n"); - case ADT7310_SPS: - return sprintf(buf, "sps\n"); - default: - return sprintf(buf, "full\n"); - } -} - -static ssize_t adt7310_store_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7310_chip_info *chip = iio_priv(dev_info); - u16 config; - int ret; - - ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); - if (ret) - return -EIO; - - config = chip->config & (~ADT7310_MODE_MASK); - if (strcmp(buf, "power-down")) - config |= ADT7310_PD; - else if (strcmp(buf, "one-shot")) - config |= ADT7310_ONESHOT; - else if (strcmp(buf, "sps")) - config |= ADT7310_SPS; - - ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, config); - if (ret) - return -EIO; - - chip->config = config; - - return len; -} - -static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, - adt7310_show_mode, - adt7310_store_mode, - 0); - -static ssize_t adt7310_show_available_modes(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "full\none-shot\nsps\npower-down\n"); -} - -static IIO_DEVICE_ATTR(available_modes, S_IRUGO, adt7310_show_available_modes, NULL, 0); - -static ssize_t adt7310_show_resolution(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7310_chip_info *chip = iio_priv(dev_info); - int ret; - int bits; - - ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); - if (ret) - return -EIO; - - if (chip->config & ADT7310_RESOLUTION) - bits = 16; - else - bits = 13; - - return sprintf(buf, "%d bits\n", bits); -} - -static ssize_t adt7310_store_resolution(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7310_chip_info *chip = iio_priv(dev_info); - unsigned long data; - u16 config; - int ret; - - ret = strict_strtoul(buf, 10, &data); - if (ret) - return -EINVAL; - - ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); - if (ret) - return -EIO; - - config = chip->config & (~ADT7310_RESOLUTION); - if (data) - config |= ADT7310_RESOLUTION; - - ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, config); - if (ret) - return -EIO; - - chip->config = config; - - return len; -} - -static IIO_DEVICE_ATTR(resolution, S_IRUGO | S_IWUSR, - adt7310_show_resolution, - adt7310_store_resolution, - 0); - -static ssize_t adt7310_show_id(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7310_chip_info *chip = iio_priv(dev_info); - u8 id; - int ret; - - ret = adt7310_spi_read_byte(chip, ADT7310_ID, &id); - if (ret) - return -EIO; - - return sprintf(buf, "device id: 0x%x\nmanufactory id: 0x%x\n", - id & ADT7310_DEVICE_ID_MASK, - (id & ADT7310_MANUFACTORY_ID_MASK) >> ADT7310_MANUFACTORY_ID_OFFSET); -} - -static IIO_DEVICE_ATTR(id, S_IRUGO | S_IWUSR, - adt7310_show_id, - NULL, - 0); - -static ssize_t adt7310_convert_temperature(struct adt7310_chip_info *chip, - u16 data, char *buf) -{ - char sign = ' '; - - if (chip->config & ADT7310_RESOLUTION) { - if (data & ADT7310_T16_VALUE_SIGN) { - /* convert supplement to positive value */ - data = (u16)((ADT7310_T16_VALUE_SIGN << 1) - (u32)data); - sign = '-'; - } - return sprintf(buf, "%c%d.%.7d\n", sign, - (data >> ADT7310_T16_VALUE_FLOAT_OFFSET), - (data & ADT7310_T16_VALUE_FLOAT_MASK) * 78125); - } else { - if (data & ADT7310_T13_VALUE_SIGN) { - /* convert supplement to positive value */ - data >>= ADT7310_T13_VALUE_OFFSET; - data = (ADT7310_T13_VALUE_SIGN << 1) - data; - sign = '-'; - } - return sprintf(buf, "%c%d.%.4d\n", sign, - (data >> ADT7310_T13_VALUE_FLOAT_OFFSET), - (data & ADT7310_T13_VALUE_FLOAT_MASK) * 625); - } -} - -static ssize_t adt7310_show_value(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7310_chip_info *chip = iio_priv(dev_info); - u8 status; - u16 data; - int ret, i = 0; - - do { - ret = adt7310_spi_read_byte(chip, ADT7310_STATUS, &status); - if (ret) - return -EIO; - i++; - if (i == 10000) - return -EIO; - } while (status & ADT7310_STAT_NOT_RDY); - - ret = adt7310_spi_read_word(chip, ADT7310_TEMPERATURE, &data); - if (ret) - return -EIO; - - return adt7310_convert_temperature(chip, data, buf); -} - -static IIO_DEVICE_ATTR(value, S_IRUGO, adt7310_show_value, NULL, 0); - -static struct attribute *adt7310_attributes[] = { - &iio_dev_attr_available_modes.dev_attr.attr, - &iio_dev_attr_mode.dev_attr.attr, - &iio_dev_attr_resolution.dev_attr.attr, - &iio_dev_attr_id.dev_attr.attr, - &iio_dev_attr_value.dev_attr.attr, - NULL, -}; - -static const struct attribute_group adt7310_attribute_group = { - .attrs = adt7310_attributes, -}; - -static irqreturn_t adt7310_event_handler(int irq, void *private) -{ - struct iio_dev *indio_dev = private; - struct adt7310_chip_info *chip = iio_priv(indio_dev); - s64 timestamp = iio_get_time_ns(); - u8 status; - int ret; - - ret = adt7310_spi_read_byte(chip, ADT7310_STATUS, &status); - if (ret) - return ret; - - if (status & ADT7310_STAT_T_HIGH) - iio_push_event(indio_dev, - IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - timestamp); - if (status & ADT7310_STAT_T_LOW) - iio_push_event(indio_dev, - IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING), - timestamp); - if (status & ADT7310_STAT_T_CRIT) - iio_push_event(indio_dev, - IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - timestamp); - return IRQ_HANDLED; -} - -static ssize_t adt7310_show_event_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7310_chip_info *chip = iio_priv(dev_info); - int ret; - - ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); - if (ret) - return -EIO; - - if (chip->config & ADT7310_EVENT_MODE) - return sprintf(buf, "interrupt\n"); - else - return sprintf(buf, "comparator\n"); -} - -static ssize_t adt7310_set_event_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7310_chip_info *chip = iio_priv(dev_info); - u16 config; - int ret; - - ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); - if (ret) - return -EIO; - - config = chip->config &= ~ADT7310_EVENT_MODE; - if (strcmp(buf, "comparator") != 0) - config |= ADT7310_EVENT_MODE; - - ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, config); - if (ret) - return -EIO; - - chip->config = config; - - return len; -} - -static ssize_t adt7310_show_available_event_modes(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "comparator\ninterrupt\n"); -} - -static ssize_t adt7310_show_fault_queue(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7310_chip_info *chip = iio_priv(dev_info); - int ret; - - ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); - if (ret) - return -EIO; - - return sprintf(buf, "%d\n", chip->config & ADT7310_FAULT_QUEUE_MASK); -} - -static ssize_t adt7310_set_fault_queue(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7310_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - u8 config; - - ret = strict_strtoul(buf, 10, &data); - if (ret || data > 3) - return -EINVAL; - - ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); - if (ret) - return -EIO; - - config = chip->config & ~ADT7310_FAULT_QUEUE_MASK; - config |= data; - ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, config); - if (ret) - return -EIO; - - chip->config = config; - - return len; -} - -static inline ssize_t adt7310_show_t_bound(struct device *dev, - struct device_attribute *attr, - u8 bound_reg, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7310_chip_info *chip = iio_priv(dev_info); - u16 data; - int ret; - - ret = adt7310_spi_read_word(chip, bound_reg, &data); - if (ret) - return -EIO; - - return adt7310_convert_temperature(chip, data, buf); -} - -static inline ssize_t adt7310_set_t_bound(struct device *dev, - struct device_attribute *attr, - u8 bound_reg, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7310_chip_info *chip = iio_priv(dev_info); - long tmp1, tmp2; - u16 data; - char *pos; - int ret; - - pos = strchr(buf, '.'); - - ret = strict_strtol(buf, 10, &tmp1); - - if (ret || tmp1 > 127 || tmp1 < -128) - return -EINVAL; - - if (pos) { - len = strlen(pos); - - if (chip->config & ADT7310_RESOLUTION) { - if (len > ADT7310_T16_VALUE_FLOAT_OFFSET) - len = ADT7310_T16_VALUE_FLOAT_OFFSET; - pos[len] = 0; - ret = strict_strtol(pos, 10, &tmp2); - - if (!ret) - tmp2 = (tmp2 / 78125) * 78125; - } else { - if (len > ADT7310_T13_VALUE_FLOAT_OFFSET) - len = ADT7310_T13_VALUE_FLOAT_OFFSET; - pos[len] = 0; - ret = strict_strtol(pos, 10, &tmp2); - - if (!ret) - tmp2 = (tmp2 / 625) * 625; - } - } - - if (tmp1 < 0) - data = (u16)(-tmp1); - else - data = (u16)tmp1; - - if (chip->config & ADT7310_RESOLUTION) { - data = (data << ADT7310_T16_VALUE_FLOAT_OFFSET) | - (tmp2 & ADT7310_T16_VALUE_FLOAT_MASK); - - if (tmp1 < 0) - /* convert positive value to supplyment */ - data = (u16)((ADT7310_T16_VALUE_SIGN << 1) - (u32)data); - } else { - data = (data << ADT7310_T13_VALUE_FLOAT_OFFSET) | - (tmp2 & ADT7310_T13_VALUE_FLOAT_MASK); - - if (tmp1 < 0) - /* convert positive value to supplyment */ - data = (ADT7310_T13_VALUE_SIGN << 1) - data; - data <<= ADT7310_T13_VALUE_OFFSET; - } - - ret = adt7310_spi_write_word(chip, bound_reg, data); - if (ret) - return -EIO; - - return len; -} - -static ssize_t adt7310_show_t_alarm_high(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return adt7310_show_t_bound(dev, attr, - ADT7310_T_ALARM_HIGH, buf); -} - -static inline ssize_t adt7310_set_t_alarm_high(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - return adt7310_set_t_bound(dev, attr, - ADT7310_T_ALARM_HIGH, buf, len); -} - -static ssize_t adt7310_show_t_alarm_low(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return adt7310_show_t_bound(dev, attr, - ADT7310_T_ALARM_LOW, buf); -} - -static inline ssize_t adt7310_set_t_alarm_low(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - return adt7310_set_t_bound(dev, attr, - ADT7310_T_ALARM_LOW, buf, len); -} - -static ssize_t adt7310_show_t_crit(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return adt7310_show_t_bound(dev, attr, - ADT7310_T_CRIT, buf); -} - -static inline ssize_t adt7310_set_t_crit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - return adt7310_set_t_bound(dev, attr, - ADT7310_T_CRIT, buf, len); -} - -static ssize_t adt7310_show_t_hyst(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7310_chip_info *chip = iio_priv(dev_info); - int ret; - u8 t_hyst; - - ret = adt7310_spi_read_byte(chip, ADT7310_T_HYST, &t_hyst); - if (ret) - return -EIO; - - return sprintf(buf, "%d\n", t_hyst & ADT7310_T_HYST_MASK); -} - -static inline ssize_t adt7310_set_t_hyst(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7310_chip_info *chip = iio_priv(dev_info); - int ret; - unsigned long data; - u8 t_hyst; - - ret = strict_strtol(buf, 10, &data); - - if (ret || data > ADT7310_T_HYST_MASK) - return -EINVAL; - - t_hyst = (u8)data; - - ret = adt7310_spi_write_byte(chip, ADT7310_T_HYST, t_hyst); - if (ret) - return -EIO; - - return len; -} - -static IIO_DEVICE_ATTR(event_mode, - S_IRUGO | S_IWUSR, - adt7310_show_event_mode, adt7310_set_event_mode, 0); -static IIO_DEVICE_ATTR(available_event_modes, - S_IRUGO | S_IWUSR, - adt7310_show_available_event_modes, NULL, 0); -static IIO_DEVICE_ATTR(fault_queue, - S_IRUGO | S_IWUSR, - adt7310_show_fault_queue, adt7310_set_fault_queue, 0); -static IIO_DEVICE_ATTR(t_alarm_high, - S_IRUGO | S_IWUSR, - adt7310_show_t_alarm_high, adt7310_set_t_alarm_high, 0); -static IIO_DEVICE_ATTR(t_alarm_low, - S_IRUGO | S_IWUSR, - adt7310_show_t_alarm_low, adt7310_set_t_alarm_low, 0); -static IIO_DEVICE_ATTR(t_crit, - S_IRUGO | S_IWUSR, - adt7310_show_t_crit, adt7310_set_t_crit, 0); -static IIO_DEVICE_ATTR(t_hyst, - S_IRUGO | S_IWUSR, - adt7310_show_t_hyst, adt7310_set_t_hyst, 0); - -static struct attribute *adt7310_event_int_attributes[] = { - &iio_dev_attr_event_mode.dev_attr.attr, - &iio_dev_attr_available_event_modes.dev_attr.attr, - &iio_dev_attr_fault_queue.dev_attr.attr, - &iio_dev_attr_t_alarm_high.dev_attr.attr, - &iio_dev_attr_t_alarm_low.dev_attr.attr, - &iio_dev_attr_t_hyst.dev_attr.attr, - NULL, -}; - -static struct attribute *adt7310_event_ct_attributes[] = { - &iio_dev_attr_event_mode.dev_attr.attr, - &iio_dev_attr_available_event_modes.dev_attr.attr, - &iio_dev_attr_fault_queue.dev_attr.attr, - &iio_dev_attr_t_crit.dev_attr.attr, - &iio_dev_attr_t_hyst.dev_attr.attr, - NULL, -}; - -static struct attribute_group adt7310_event_attribute_group[ADT7310_IRQS] = { - { - .attrs = adt7310_event_int_attributes, - .name = "events", - }, { - .attrs = adt7310_event_ct_attributes, - .name = "events", - } -}; - -static const struct iio_info adt7310_info = { - .attrs = &adt7310_attribute_group, - .event_attrs = adt7310_event_attribute_group, - .driver_module = THIS_MODULE, -}; - -/* - * device probe and remove - */ - -static int __devinit adt7310_probe(struct spi_device *spi_dev) -{ - struct adt7310_chip_info *chip; - struct iio_dev *indio_dev; - int ret = 0; - unsigned long *adt7310_platform_data = spi_dev->dev.platform_data; - unsigned long irq_flags; - - indio_dev = iio_allocate_device(sizeof(*chip)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - chip = iio_priv(indio_dev); - /* this is only used for device removal purposes */ - dev_set_drvdata(&spi_dev->dev, indio_dev); - - chip->spi_dev = spi_dev; - - indio_dev->dev.parent = &spi_dev->dev; - indio_dev->name = spi_get_device_id(spi_dev)->name; - indio_dev->info = &adt7310_info; - indio_dev->modes = INDIO_DIRECT_MODE; - - /* CT critcal temperature event. line 0 */ - if (spi_dev->irq) { - if (adt7310_platform_data[2]) - irq_flags = adt7310_platform_data[2]; - else - irq_flags = IRQF_TRIGGER_LOW; - ret = request_threaded_irq(spi_dev->irq, - NULL, - &adt7310_event_handler, - irq_flags, - indio_dev->name, - indio_dev); - if (ret) - goto error_free_dev; - } - - /* INT bound temperature alarm event. line 1 */ - if (adt7310_platform_data[0]) { - ret = request_threaded_irq(adt7310_platform_data[0], - NULL, - &adt7310_event_handler, - adt7310_platform_data[1], - indio_dev->name, - indio_dev); - if (ret) - goto error_unreg_ct_irq; - } - - if (spi_dev->irq && adt7310_platform_data[0]) { - ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); - if (ret) { - ret = -EIO; - goto error_unreg_int_irq; - } - - /* set irq polarity low level */ - chip->config &= ~ADT7310_CT_POLARITY; - - if (adt7310_platform_data[1] & IRQF_TRIGGER_HIGH) - chip->config |= ADT7310_INT_POLARITY; - else - chip->config &= ~ADT7310_INT_POLARITY; - - ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, chip->config); - if (ret) { - ret = -EIO; - goto error_unreg_int_irq; - } - } - - ret = iio_device_register(indio_dev); - if (ret) - goto error_unreg_int_irq; - - dev_info(&spi_dev->dev, "%s temperature sensor registered.\n", - indio_dev->name); - - return 0; - -error_unreg_int_irq: - free_irq(adt7310_platform_data[0], indio_dev); -error_unreg_ct_irq: - free_irq(spi_dev->irq, indio_dev); -error_free_dev: - iio_free_device(indio_dev); -error_ret: - return ret; -} - -static int __devexit adt7310_remove(struct spi_device *spi_dev) -{ - struct iio_dev *indio_dev = dev_get_drvdata(&spi_dev->dev); - unsigned long *adt7310_platform_data = spi_dev->dev.platform_data; - - iio_device_unregister(indio_dev); - dev_set_drvdata(&spi_dev->dev, NULL); - if (adt7310_platform_data[0]) - free_irq(adt7310_platform_data[0], indio_dev); - if (spi_dev->irq) - free_irq(spi_dev->irq, indio_dev); - iio_free_device(indio_dev); - - return 0; -} - -static const struct spi_device_id adt7310_id[] = { - { "adt7310", 0 }, - {} -}; - -MODULE_DEVICE_TABLE(spi, adt7310_id); - -static struct spi_driver adt7310_driver = { - .driver = { - .name = "adt7310", - .owner = THIS_MODULE, - }, - .probe = adt7310_probe, - .remove = __devexit_p(adt7310_remove), - .id_table = adt7310_id, -}; -module_spi_driver(adt7310_driver); - -MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>"); -MODULE_DESCRIPTION("Analog Devices ADT7310 digital" - " temperature sensor driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c deleted file mode 100644 index c62248ceb37..00000000000 --- a/drivers/staging/iio/adc/adt7410.c +++ /dev/null @@ -1,853 +0,0 @@ -/* - * ADT7410 digital temperature sensor driver supporting ADT7410 - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/interrupt.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/list.h> -#include <linux/i2c.h> -#include <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" - -/* - * ADT7410 registers definition - */ - -#define ADT7410_TEMPERATURE 0 -#define ADT7410_STATUS 2 -#define ADT7410_CONFIG 3 -#define ADT7410_T_ALARM_HIGH 4 -#define ADT7410_T_ALARM_LOW 6 -#define ADT7410_T_CRIT 8 -#define ADT7410_T_HYST 0xA -#define ADT7410_ID 0xB -#define ADT7410_RESET 0x2F - -/* - * ADT7410 status - */ -#define ADT7410_STAT_T_LOW 0x10 -#define ADT7410_STAT_T_HIGH 0x20 -#define ADT7410_STAT_T_CRIT 0x40 -#define ADT7410_STAT_NOT_RDY 0x80 - -/* - * ADT7410 config - */ -#define ADT7410_FAULT_QUEUE_MASK 0x3 -#define ADT7410_CT_POLARITY 0x4 -#define ADT7410_INT_POLARITY 0x8 -#define ADT7410_EVENT_MODE 0x10 -#define ADT7410_MODE_MASK 0x60 -#define ADT7410_ONESHOT 0x20 -#define ADT7410_SPS 0x40 -#define ADT7410_PD 0x60 -#define ADT7410_RESOLUTION 0x80 - -/* - * ADT7410 masks - */ -#define ADT7410_T16_VALUE_SIGN 0x8000 -#define ADT7410_T16_VALUE_FLOAT_OFFSET 7 -#define ADT7410_T16_VALUE_FLOAT_MASK 0x7F -#define ADT7410_T13_VALUE_SIGN 0x1000 -#define ADT7410_T13_VALUE_OFFSET 3 -#define ADT7410_T13_VALUE_FLOAT_OFFSET 4 -#define ADT7410_T13_VALUE_FLOAT_MASK 0xF -#define ADT7410_T_HYST_MASK 0xF -#define ADT7410_DEVICE_ID_MASK 0xF -#define ADT7410_MANUFACTORY_ID_MASK 0xF0 -#define ADT7410_MANUFACTORY_ID_OFFSET 4 - -#define ADT7410_IRQS 2 - -/* - * struct adt7410_chip_info - chip specifc information - */ - -struct adt7410_chip_info { - struct i2c_client *client; - u8 config; -}; - -/* - * adt7410 register access by I2C - */ - -static int adt7410_i2c_read_word(struct adt7410_chip_info *chip, u8 reg, u16 *data) -{ - struct i2c_client *client = chip->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 adt7410_i2c_write_word(struct adt7410_chip_info *chip, u8 reg, u16 data) -{ - struct i2c_client *client = chip->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 adt7410_i2c_read_byte(struct adt7410_chip_info *chip, u8 reg, u8 *data) -{ - struct i2c_client *client = chip->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 adt7410_i2c_write_byte(struct adt7410_chip_info *chip, u8 reg, u8 data) -{ - struct i2c_client *client = chip->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 ssize_t adt7410_show_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7410_chip_info *chip = iio_priv(dev_info); - u8 config; - - config = chip->config & ADT7410_MODE_MASK; - - switch (config) { - case ADT7410_PD: - return sprintf(buf, "power-down\n"); - case ADT7410_ONESHOT: - return sprintf(buf, "one-shot\n"); - case ADT7410_SPS: - return sprintf(buf, "sps\n"); - default: - return sprintf(buf, "full\n"); - } -} - -static ssize_t adt7410_store_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7410_chip_info *chip = iio_priv(dev_info); - u16 config; - int ret; - - ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); - if (ret) - return -EIO; - - config = chip->config & (~ADT7410_MODE_MASK); - if (strcmp(buf, "power-down")) - config |= ADT7410_PD; - else if (strcmp(buf, "one-shot")) - config |= ADT7410_ONESHOT; - else if (strcmp(buf, "sps")) - config |= ADT7410_SPS; - - ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, config); - if (ret) - return -EIO; - - chip->config = config; - - return ret; -} - -static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, - adt7410_show_mode, - adt7410_store_mode, - 0); - -static ssize_t adt7410_show_available_modes(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "full\none-shot\nsps\npower-down\n"); -} - -static IIO_DEVICE_ATTR(available_modes, S_IRUGO, adt7410_show_available_modes, NULL, 0); - -static ssize_t adt7410_show_resolution(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7410_chip_info *chip = iio_priv(dev_info); - int ret; - int bits; - - ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); - if (ret) - return -EIO; - - if (chip->config & ADT7410_RESOLUTION) - bits = 16; - else - bits = 13; - - return sprintf(buf, "%d bits\n", bits); -} - -static ssize_t adt7410_store_resolution(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7410_chip_info *chip = iio_priv(dev_info); - unsigned long data; - u16 config; - int ret; - - ret = strict_strtoul(buf, 10, &data); - if (ret) - return -EINVAL; - - ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); - if (ret) - return -EIO; - - config = chip->config & (~ADT7410_RESOLUTION); - if (data) - config |= ADT7410_RESOLUTION; - - ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, config); - if (ret) - return -EIO; - - chip->config = config; - - return ret; -} - -static IIO_DEVICE_ATTR(resolution, S_IRUGO | S_IWUSR, - adt7410_show_resolution, - adt7410_store_resolution, - 0); - -static ssize_t adt7410_show_id(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7410_chip_info *chip = iio_priv(dev_info); - u8 id; - int ret; - - ret = adt7410_i2c_read_byte(chip, ADT7410_ID, &id); - if (ret) - return -EIO; - - return sprintf(buf, "device id: 0x%x\nmanufactory id: 0x%x\n", - id & ADT7410_DEVICE_ID_MASK, - (id & ADT7410_MANUFACTORY_ID_MASK) >> ADT7410_MANUFACTORY_ID_OFFSET); -} - -static IIO_DEVICE_ATTR(id, S_IRUGO | S_IWUSR, - adt7410_show_id, - NULL, - 0); - -static ssize_t adt7410_convert_temperature(struct adt7410_chip_info *chip, - u16 data, char *buf) -{ - char sign = ' '; - - if (chip->config & ADT7410_RESOLUTION) { - if (data & ADT7410_T16_VALUE_SIGN) { - /* convert supplement to positive value */ - data = (u16)((ADT7410_T16_VALUE_SIGN << 1) - (u32)data); - sign = '-'; - } - return sprintf(buf, "%c%d.%.7d\n", sign, - (data >> ADT7410_T16_VALUE_FLOAT_OFFSET), - (data & ADT7410_T16_VALUE_FLOAT_MASK) * 78125); - } else { - if (data & ADT7410_T13_VALUE_SIGN) { - /* convert supplement to positive value */ - data >>= ADT7410_T13_VALUE_OFFSET; - data = (ADT7410_T13_VALUE_SIGN << 1) - data; - sign = '-'; - } - return sprintf(buf, "%c%d.%.4d\n", sign, - (data >> ADT7410_T13_VALUE_FLOAT_OFFSET), - (data & ADT7410_T13_VALUE_FLOAT_MASK) * 625); - } -} - -static ssize_t adt7410_show_value(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7410_chip_info *chip = iio_priv(dev_info); - u8 status; - u16 data; - int ret, i = 0; - - do { - ret = adt7410_i2c_read_byte(chip, ADT7410_STATUS, &status); - if (ret) - return -EIO; - i++; - if (i == 10000) - return -EIO; - } while (status & ADT7410_STAT_NOT_RDY); - - ret = adt7410_i2c_read_word(chip, ADT7410_TEMPERATURE, &data); - if (ret) - return -EIO; - - return adt7410_convert_temperature(chip, data, buf); -} - -static IIO_DEVICE_ATTR(value, S_IRUGO, adt7410_show_value, NULL, 0); - -static struct attribute *adt7410_attributes[] = { - &iio_dev_attr_available_modes.dev_attr.attr, - &iio_dev_attr_mode.dev_attr.attr, - &iio_dev_attr_resolution.dev_attr.attr, - &iio_dev_attr_id.dev_attr.attr, - &iio_dev_attr_value.dev_attr.attr, - NULL, -}; - -static const struct attribute_group adt7410_attribute_group = { - .attrs = adt7410_attributes, -}; - -static irqreturn_t adt7410_event_handler(int irq, void *private) -{ - struct iio_dev *indio_dev = private; - struct adt7410_chip_info *chip = iio_priv(indio_dev); - s64 timestamp = iio_get_time_ns(); - u8 status; - - if (adt7410_i2c_read_byte(chip, ADT7410_STATUS, &status)) - return IRQ_HANDLED; - - if (status & ADT7410_STAT_T_HIGH) - iio_push_event(indio_dev, - IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - timestamp); - if (status & ADT7410_STAT_T_LOW) - iio_push_event(indio_dev, - IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING), - timestamp); - if (status & ADT7410_STAT_T_CRIT) - iio_push_event(indio_dev, - IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - timestamp); - - return IRQ_HANDLED; -} - -static ssize_t adt7410_show_event_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7410_chip_info *chip = iio_priv(dev_info); - int ret; - - ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); - if (ret) - return -EIO; - - if (chip->config & ADT7410_EVENT_MODE) - return sprintf(buf, "interrupt\n"); - else - return sprintf(buf, "comparator\n"); -} - -static ssize_t adt7410_set_event_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7410_chip_info *chip = iio_priv(dev_info); - u16 config; - int ret; - - ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); - if (ret) - return -EIO; - - config = chip->config &= ~ADT7410_EVENT_MODE; - if (strcmp(buf, "comparator") != 0) - config |= ADT7410_EVENT_MODE; - - ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, config); - if (ret) - return -EIO; - - chip->config = config; - - return ret; -} - -static ssize_t adt7410_show_available_event_modes(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "comparator\ninterrupt\n"); -} - -static ssize_t adt7410_show_fault_queue(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7410_chip_info *chip = iio_priv(dev_info); - int ret; - - ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); - if (ret) - return -EIO; - - return sprintf(buf, "%d\n", chip->config & ADT7410_FAULT_QUEUE_MASK); -} - -static ssize_t adt7410_set_fault_queue(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7410_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - u8 config; - - ret = strict_strtoul(buf, 10, &data); - if (ret || data > 3) - return -EINVAL; - - ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); - if (ret) - return -EIO; - - config = chip->config & ~ADT7410_FAULT_QUEUE_MASK; - config |= data; - ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, config); - if (ret) - return -EIO; - - chip->config = config; - - return ret; -} - -static inline ssize_t adt7410_show_t_bound(struct device *dev, - struct device_attribute *attr, - u8 bound_reg, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7410_chip_info *chip = iio_priv(dev_info); - u16 data; - int ret; - - ret = adt7410_i2c_read_word(chip, bound_reg, &data); - if (ret) - return -EIO; - - return adt7410_convert_temperature(chip, data, buf); -} - -static inline ssize_t adt7410_set_t_bound(struct device *dev, - struct device_attribute *attr, - u8 bound_reg, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7410_chip_info *chip = iio_priv(dev_info); - long tmp1, tmp2; - u16 data; - char *pos; - int ret; - - pos = strchr(buf, '.'); - - ret = strict_strtol(buf, 10, &tmp1); - - if (ret || tmp1 > 127 || tmp1 < -128) - return -EINVAL; - - if (pos) { - len = strlen(pos); - - if (chip->config & ADT7410_RESOLUTION) { - if (len > ADT7410_T16_VALUE_FLOAT_OFFSET) - len = ADT7410_T16_VALUE_FLOAT_OFFSET; - pos[len] = 0; - ret = strict_strtol(pos, 10, &tmp2); - - if (!ret) - tmp2 = (tmp2 / 78125) * 78125; - } else { - if (len > ADT7410_T13_VALUE_FLOAT_OFFSET) - len = ADT7410_T13_VALUE_FLOAT_OFFSET; - pos[len] = 0; - ret = strict_strtol(pos, 10, &tmp2); - - if (!ret) - tmp2 = (tmp2 / 625) * 625; - } - } - - if (tmp1 < 0) - data = (u16)(-tmp1); - else - data = (u16)tmp1; - - if (chip->config & ADT7410_RESOLUTION) { - data = (data << ADT7410_T16_VALUE_FLOAT_OFFSET) | - (tmp2 & ADT7410_T16_VALUE_FLOAT_MASK); - - if (tmp1 < 0) - /* convert positive value to supplyment */ - data = (u16)((ADT7410_T16_VALUE_SIGN << 1) - (u32)data); - } else { - data = (data << ADT7410_T13_VALUE_FLOAT_OFFSET) | - (tmp2 & ADT7410_T13_VALUE_FLOAT_MASK); - - if (tmp1 < 0) - /* convert positive value to supplyment */ - data = (ADT7410_T13_VALUE_SIGN << 1) - data; - data <<= ADT7410_T13_VALUE_OFFSET; - } - - ret = adt7410_i2c_write_word(chip, bound_reg, data); - if (ret) - return -EIO; - - return ret; -} - -static ssize_t adt7410_show_t_alarm_high(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return adt7410_show_t_bound(dev, attr, - ADT7410_T_ALARM_HIGH, buf); -} - -static inline ssize_t adt7410_set_t_alarm_high(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - return adt7410_set_t_bound(dev, attr, - ADT7410_T_ALARM_HIGH, buf, len); -} - -static ssize_t adt7410_show_t_alarm_low(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return adt7410_show_t_bound(dev, attr, - ADT7410_T_ALARM_LOW, buf); -} - -static inline ssize_t adt7410_set_t_alarm_low(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - return adt7410_set_t_bound(dev, attr, - ADT7410_T_ALARM_LOW, buf, len); -} - -static ssize_t adt7410_show_t_crit(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return adt7410_show_t_bound(dev, attr, - ADT7410_T_CRIT, buf); -} - -static inline ssize_t adt7410_set_t_crit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - return adt7410_set_t_bound(dev, attr, - ADT7410_T_CRIT, buf, len); -} - -static ssize_t adt7410_show_t_hyst(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7410_chip_info *chip = iio_priv(dev_info); - int ret; - u8 t_hyst; - - ret = adt7410_i2c_read_byte(chip, ADT7410_T_HYST, &t_hyst); - if (ret) - return -EIO; - - return sprintf(buf, "%d\n", t_hyst & ADT7410_T_HYST_MASK); -} - -static inline ssize_t adt7410_set_t_hyst(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7410_chip_info *chip = iio_priv(dev_info); - int ret; - unsigned long data; - u8 t_hyst; - - ret = strict_strtol(buf, 10, &data); - - if (ret || data > ADT7410_T_HYST_MASK) - return -EINVAL; - - t_hyst = (u8)data; - - ret = adt7410_i2c_write_byte(chip, ADT7410_T_HYST, t_hyst); - if (ret) - return -EIO; - - return ret; -} - -static IIO_DEVICE_ATTR(event_mode, - S_IRUGO | S_IWUSR, - adt7410_show_event_mode, adt7410_set_event_mode, 0); -static IIO_DEVICE_ATTR(available_event_modes, - S_IRUGO, - adt7410_show_available_event_modes, NULL, 0); -static IIO_DEVICE_ATTR(fault_queue, - S_IRUGO | S_IWUSR, - adt7410_show_fault_queue, adt7410_set_fault_queue, 0); -static IIO_DEVICE_ATTR(t_alarm_high, - S_IRUGO | S_IWUSR, - adt7410_show_t_alarm_high, adt7410_set_t_alarm_high, 0); -static IIO_DEVICE_ATTR(t_alarm_low, - S_IRUGO | S_IWUSR, - adt7410_show_t_alarm_low, adt7410_set_t_alarm_low, 0); -static IIO_DEVICE_ATTR(t_crit, - S_IRUGO | S_IWUSR, - adt7410_show_t_crit, adt7410_set_t_crit, 0); -static IIO_DEVICE_ATTR(t_hyst, - S_IRUGO | S_IWUSR, - adt7410_show_t_hyst, adt7410_set_t_hyst, 0); - -static struct attribute *adt7410_event_int_attributes[] = { - &iio_dev_attr_event_mode.dev_attr.attr, - &iio_dev_attr_available_event_modes.dev_attr.attr, - &iio_dev_attr_fault_queue.dev_attr.attr, - &iio_dev_attr_t_alarm_high.dev_attr.attr, - &iio_dev_attr_t_alarm_low.dev_attr.attr, - &iio_dev_attr_t_hyst.dev_attr.attr, - NULL, -}; - -static struct attribute *adt7410_event_ct_attributes[] = { - &iio_dev_attr_event_mode.dev_attr.attr, - &iio_dev_attr_available_event_modes.dev_attr.attr, - &iio_dev_attr_fault_queue.dev_attr.attr, - &iio_dev_attr_t_crit.dev_attr.attr, - &iio_dev_attr_t_hyst.dev_attr.attr, - NULL, -}; - -static struct attribute_group adt7410_event_attribute_group[ADT7410_IRQS] = { - { - .attrs = adt7410_event_int_attributes, - .name = "events", - }, { - .attrs = adt7410_event_ct_attributes, - .name = "events", - } -}; - -static const struct iio_info adt7410_info = { - .attrs = &adt7410_attribute_group, - .event_attrs = adt7410_event_attribute_group, - .driver_module = THIS_MODULE, -}; - -/* - * device probe and remove - */ - -static int __devinit adt7410_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adt7410_chip_info *chip; - struct iio_dev *indio_dev; - int ret = 0; - unsigned long *adt7410_platform_data = client->dev.platform_data; - - indio_dev = iio_allocate_device(sizeof(*chip)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - chip = iio_priv(indio_dev); - /* this is only used for device removal purposes */ - i2c_set_clientdata(client, indio_dev); - - chip->client = client; - - indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; - indio_dev->info = &adt7410_info; - indio_dev->modes = INDIO_DIRECT_MODE; - - /* CT critcal temperature event. line 0 */ - if (client->irq) { - ret = request_threaded_irq(client->irq, - NULL, - &adt7410_event_handler, - IRQF_TRIGGER_LOW, - id->name, - indio_dev); - if (ret) - goto error_free_dev; - } - - /* INT bound temperature alarm event. line 1 */ - if (adt7410_platform_data[0]) { - ret = request_threaded_irq(adt7410_platform_data[0], - NULL, - &adt7410_event_handler, - adt7410_platform_data[1], - id->name, - indio_dev); - if (ret) - goto error_unreg_ct_irq; - } - - if (client->irq && adt7410_platform_data[0]) { - - ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); - if (ret) { - ret = -EIO; - goto error_unreg_int_irq; - } - - /* set irq polarity low level */ - chip->config &= ~ADT7410_CT_POLARITY; - - if (adt7410_platform_data[1] & IRQF_TRIGGER_HIGH) - chip->config |= ADT7410_INT_POLARITY; - else - chip->config &= ~ADT7410_INT_POLARITY; - - ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, chip->config); - if (ret) { - ret = -EIO; - goto error_unreg_int_irq; - } - } - ret = iio_device_register(indio_dev); - if (ret) - goto error_unreg_int_irq; - - dev_info(&client->dev, "%s temperature sensor registered.\n", - id->name); - - return 0; - -error_unreg_int_irq: - free_irq(adt7410_platform_data[0], indio_dev); -error_unreg_ct_irq: - free_irq(client->irq, indio_dev); -error_free_dev: - iio_free_device(indio_dev); -error_ret: - return ret; -} - -static int __devexit adt7410_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - unsigned long *adt7410_platform_data = client->dev.platform_data; - - iio_device_unregister(indio_dev); - if (adt7410_platform_data[0]) - free_irq(adt7410_platform_data[0], indio_dev); - if (client->irq) - free_irq(client->irq, indio_dev); - iio_free_device(indio_dev); - - return 0; -} - -static const struct i2c_device_id adt7410_id[] = { - { "adt7410", 0 }, - {} -}; - -MODULE_DEVICE_TABLE(i2c, adt7410_id); - -static struct i2c_driver adt7410_driver = { - .driver = { - .name = "adt7410", - }, - .probe = adt7410_probe, - .remove = __devexit_p(adt7410_remove), - .id_table = adt7410_id, -}; -module_i2c_driver(adt7410_driver); - -MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>"); -MODULE_DESCRIPTION("Analog Devices ADT7410 digital" - " temperature sensor driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c new file mode 100644 index 00000000000..a876ce75535 --- /dev/null +++ b/drivers/staging/iio/adc/lpc32xx_adc.c @@ -0,0 +1,216 @@ +/* + * lpc32xx_adc.c - Support for ADC in LPC32XX + * + * 3-channel, 10-bit ADC + * + * Copyright (C) 2011, 2012 Roland Stigge <stigge@antcom.de> + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/completion.h> +#include <linux/of.h> + +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> + +/* + * LPC32XX registers definitions + */ +#define LPC32XX_ADC_SELECT(x) ((x) + 0x04) +#define LPC32XX_ADC_CTRL(x) ((x) + 0x08) +#define LPC32XX_ADC_VALUE(x) ((x) + 0x48) + +/* Bit definitions for LPC32XX_ADC_SELECT: */ +#define AD_REFm 0x00000200 /* constant, always write this value! */ +#define AD_REFp 0x00000080 /* constant, always write this value! */ +#define AD_IN 0x00000010 /* multiple of this is the */ + /* channel number: 0, 1, 2 */ +#define AD_INTERNAL 0x00000004 /* constant, always write this value! */ + +/* Bit definitions for LPC32XX_ADC_CTRL: */ +#define AD_STROBE 0x00000002 +#define AD_PDN_CTRL 0x00000004 + +/* Bit definitions for LPC32XX_ADC_VALUE: */ +#define ADC_VALUE_MASK 0x000003FF + +#define MOD_NAME "lpc32xx-adc" + +struct lpc32xx_adc_info { + void __iomem *adc_base; + struct clk *clk; + struct completion completion; + + u32 value; +}; + +static int lpc32xx_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + struct lpc32xx_adc_info *info = iio_priv(indio_dev); + + if (mask == IIO_CHAN_INFO_RAW) { + mutex_lock(&indio_dev->mlock); + clk_enable(info->clk); + /* Measurement setup */ + __raw_writel(AD_INTERNAL | (chan->address) | AD_REFp | AD_REFm, + LPC32XX_ADC_SELECT(info->adc_base)); + /* Trigger conversion */ + __raw_writel(AD_PDN_CTRL | AD_STROBE, + LPC32XX_ADC_CTRL(info->adc_base)); + wait_for_completion(&info->completion); /* set by ISR */ + clk_disable(info->clk); + *val = info->value; + mutex_unlock(&indio_dev->mlock); + + return IIO_VAL_INT; + } + + return -EINVAL; +} + +static const struct iio_info lpc32xx_adc_iio_info = { + .read_raw = &lpc32xx_read_raw, + .driver_module = THIS_MODULE, +}; + +#define LPC32XX_ADC_CHANNEL(_index) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = _index, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .address = AD_IN * _index, \ + .scan_index = _index, \ +} + +static const struct iio_chan_spec lpc32xx_adc_iio_channels[] = { + LPC32XX_ADC_CHANNEL(0), + LPC32XX_ADC_CHANNEL(1), + LPC32XX_ADC_CHANNEL(2), +}; + +static irqreturn_t lpc32xx_adc_isr(int irq, void *dev_id) +{ + struct lpc32xx_adc_info *info = (struct lpc32xx_adc_info *) dev_id; + + /* Read value and clear irq */ + info->value = __raw_readl(LPC32XX_ADC_VALUE(info->adc_base)) & + ADC_VALUE_MASK; + complete(&info->completion); + + return IRQ_HANDLED; +} + +static int lpc32xx_adc_probe(struct platform_device *pdev) +{ + struct lpc32xx_adc_info *info = NULL; + struct resource *res; + int retval = -ENODEV; + struct iio_dev *iodev = NULL; + int irq; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "failed to get platform I/O memory\n"); + return -EBUSY; + } + + iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); + if (!iodev) + return -ENOMEM; + + info = iio_priv(iodev); + + info->adc_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!info->adc_base) { + dev_err(&pdev->dev, "failed mapping memory\n"); + return -EBUSY; + } + + info->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(info->clk)) { + dev_err(&pdev->dev, "failed getting clock\n"); + return PTR_ERR(info->clk); + } + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) { + dev_err(&pdev->dev, "failed getting interrupt resource\n"); + return -EINVAL; + } + + retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0, + MOD_NAME, info); + if (retval < 0) { + dev_err(&pdev->dev, "failed requesting interrupt\n"); + return retval; + } + + platform_set_drvdata(pdev, iodev); + + init_completion(&info->completion); + + iodev->name = MOD_NAME; + iodev->dev.parent = &pdev->dev; + iodev->info = &lpc32xx_adc_iio_info; + iodev->modes = INDIO_DIRECT_MODE; + iodev->channels = lpc32xx_adc_iio_channels; + iodev->num_channels = ARRAY_SIZE(lpc32xx_adc_iio_channels); + + retval = devm_iio_device_register(&pdev->dev, iodev); + if (retval) + return retval; + + dev_info(&pdev->dev, "LPC32XX ADC driver loaded, IRQ %d\n", irq); + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id lpc32xx_adc_match[] = { + { .compatible = "nxp,lpc3220-adc" }, + {}, +}; +MODULE_DEVICE_TABLE(of, lpc32xx_adc_match); +#endif + +static struct platform_driver lpc32xx_adc_driver = { + .probe = lpc32xx_adc_probe, + .driver = { + .name = MOD_NAME, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(lpc32xx_adc_match), + }, +}; + +module_platform_driver(lpc32xx_adc_driver); + +MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>"); +MODULE_DESCRIPTION("LPC32XX ADC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/adc/max1363.h b/drivers/staging/iio/adc/max1363.h deleted file mode 100644 index 2cd0112067b..00000000000 --- a/drivers/staging/iio/adc/max1363.h +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef _MAX1363_H_ -#define _MAX1363_H_ - -#define MAX1363_SETUP_BYTE(a) ((a) | 0x80) - -/* There is a fair bit more defined here than currently - * used, but the intention is to support everything these - * chips do in the long run */ - -/* see data sheets */ -/* max1363 and max1236, max1237, max1238, max1239 */ -#define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD 0x00 -#define MAX1363_SETUP_AIN3_IS_REF_EXT_TO_REF 0x20 -#define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_INT 0x40 -#define MAX1363_SETUP_AIN3_IS_REF_REF_IS_INT 0x60 -#define MAX1363_SETUP_POWER_UP_INT_REF 0x10 -#define MAX1363_SETUP_POWER_DOWN_INT_REF 0x00 - -/* think about includeing max11600 etc - more settings */ -#define MAX1363_SETUP_EXT_CLOCK 0x08 -#define MAX1363_SETUP_INT_CLOCK 0x00 -#define MAX1363_SETUP_UNIPOLAR 0x00 -#define MAX1363_SETUP_BIPOLAR 0x04 -#define MAX1363_SETUP_RESET 0x00 -#define MAX1363_SETUP_NORESET 0x02 -/* max1363 only - though don't care on others. - * For now monitor modes are not implemented as the relevant - * line is not connected on my test board. - * The definitions are here as I intend to add this soon. - */ -#define MAX1363_SETUP_MONITOR_SETUP 0x01 - -/* Specific to the max1363 */ -#define MAX1363_MON_RESET_CHAN(a) (1 << ((a) + 4)) -#define MAX1363_MON_INT_ENABLE 0x01 - -/* defined for readability reasons */ -/* All chips */ -#define MAX1363_CONFIG_BYTE(a) ((a)) - -#define MAX1363_CONFIG_SE 0x01 -#define MAX1363_CONFIG_DE 0x00 -#define MAX1363_CONFIG_SCAN_TO_CS 0x00 -#define MAX1363_CONFIG_SCAN_SINGLE_8 0x20 -#define MAX1363_CONFIG_SCAN_MONITOR_MODE 0x40 -#define MAX1363_CONFIG_SCAN_SINGLE_1 0x60 -/* max123{6-9} only */ -#define MAX1236_SCAN_MID_TO_CHANNEL 0x40 - -/* max1363 only - merely part of channel selects or don't care for others*/ -#define MAX1363_CONFIG_EN_MON_MODE_READ 0x18 - -#define MAX1363_CHANNEL_SEL(a) ((a) << 1) - -/* max1363 strictly 0x06 - but doesn't matter */ -#define MAX1363_CHANNEL_SEL_MASK 0x1E -#define MAX1363_SCAN_MASK 0x60 -#define MAX1363_SE_DE_MASK 0x01 - -#define MAX1363_MAX_CHANNELS 25 -/** - * struct max1363_mode - scan mode information - * @conf: The corresponding value of the configuration register - * @modemask: Bit mask corresponding to channels enabled in this mode - */ -struct max1363_mode { - int8_t conf; - DECLARE_BITMAP(modemask, MAX1363_MAX_CHANNELS); -}; - -/* This must be maintained along side the max1363_mode_table in max1363_core */ -enum max1363_modes { - /* Single read of a single channel */ - _s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11, - /* Differential single read */ - d0m1, d2m3, d4m5, d6m7, d8m9, d10m11, - d1m0, d3m2, d5m4, d7m6, d9m8, d11m10, - /* Scan to channel and mid to channel where overlapping */ - s0to1, s0to2, s2to3, s0to3, s0to4, s0to5, s0to6, - s6to7, s0to7, s6to8, s0to8, s6to9, - s0to9, s6to10, s0to10, s6to11, s0to11, - /* Differential scan to channel and mid to channel where overlapping */ - d0m1to2m3, d0m1to4m5, d0m1to6m7, d6m7to8m9, - d0m1to8m9, d6m7to10m11, d0m1to10m11, d1m0to3m2, - d1m0to5m4, d1m0to7m6, d7m6to9m8, d1m0to9m8, - d7m6to11m10, d1m0to11m10, -}; - -/** - * struct max1363_chip_info - chip specifc information - * @name: indentification string for chip - * @bits: accuracy of the adc in bits - * @int_vref_mv: the internal reference voltage - * @info: iio core function callbacks structure - * @mode_list: array of available scan modes - * @num_modes: the number of scan modes available - * @default_mode: the scan mode in which the chip starts up - * @channel: channel specification - * @num_channels: number of channels - */ -struct max1363_chip_info { - const struct iio_info *info; - struct iio_chan_spec *channels; - int num_channels; - const enum max1363_modes *mode_list; - enum max1363_modes default_mode; - u16 int_vref_mv; - u8 num_modes; - u8 bits; -}; - -/** - * struct max1363_state - driver instance specific data - * @client: i2c_client - * @setupbyte: cache of current device setup byte - * @configbyte: cache of current device config byte - * @chip_info: chip model specific constants, available modes etc - * @current_mode: the scan mode of this chip - * @requestedmask: a valid requested set of channels - * @reg: supply regulator - * @monitor_on: whether monitor mode is enabled - * @monitor_speed: parameter corresponding to device monitor speed setting - * @mask_high: bitmask for enabled high thresholds - * @mask_low: bitmask for enabled low thresholds - * @thresh_high: high threshold values - * @thresh_low: low threshold values - */ -struct max1363_state { - struct i2c_client *client; - u8 setupbyte; - u8 configbyte; - const struct max1363_chip_info *chip_info; - const struct max1363_mode *current_mode; - u32 requestedmask; - struct regulator *reg; - - /* Using monitor modes and buffer at the same time is - currently not supported */ - bool monitor_on; - unsigned int monitor_speed:3; - u8 mask_high; - u8 mask_low; - /* 4x unipolar first then the fours bipolar ones */ - s16 thresh_high[8]; - s16 thresh_low[8]; -}; - -const struct max1363_mode -*max1363_match_mode(const unsigned long *mask, - const struct max1363_chip_info *ci); - -int max1363_set_scan_mode(struct max1363_state *st); - -#ifdef CONFIG_MAX1363_RING_BUFFER -int max1363_update_scan_mode(struct iio_dev *indio_dev, - const unsigned long *scan_mask); -int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev); -void max1363_ring_cleanup(struct iio_dev *indio_dev); - -#else /* CONFIG_MAX1363_RING_BUFFER */ -int max1363_update_scan_mode(struct iio_dev *indio_dev, - const long *scan_mask) -{ - return 0; -} - -static inline int -max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline void max1363_ring_cleanup(struct iio_dev *indio_dev) -{ -} -#endif /* CONFIG_MAX1363_RING_BUFFER */ -#endif /* _MAX1363_H_ */ diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c deleted file mode 100644 index b92cb4af18c..00000000000 --- a/drivers/staging/iio/adc/max1363_core.c +++ /dev/null @@ -1,1423 +0,0 @@ - /* - * iio/adc/max1363.c - * Copyright (C) 2008-2010 Jonathan Cameron - * - * based on linux/drivers/i2c/chips/max123x - * Copyright (C) 2002-2004 Stefan Eletzhofer - * - * based on linux/drivers/acron/char/pcf8583.c - * Copyright (C) 2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * max1363.c - * - * Partial support for max1363 and similar chips. - * - * Not currently implemented. - * - * - Control of internal reference. - */ - -#include <linux/interrupt.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/err.h> -#include <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" -#include "../buffer.h" - -#include "max1363.h" - -#define MAX1363_MODE_SINGLE(_num, _mask) { \ - .conf = MAX1363_CHANNEL_SEL(_num) \ - | MAX1363_CONFIG_SCAN_SINGLE_1 \ - | MAX1363_CONFIG_SE, \ - .modemask[0] = _mask, \ - } - -#define MAX1363_MODE_SCAN_TO_CHANNEL(_num, _mask) { \ - .conf = MAX1363_CHANNEL_SEL(_num) \ - | MAX1363_CONFIG_SCAN_TO_CS \ - | MAX1363_CONFIG_SE, \ - .modemask[0] = _mask, \ - } - -/* note not available for max1363 hence naming */ -#define MAX1236_MODE_SCAN_MID_TO_CHANNEL(_mid, _num, _mask) { \ - .conf = MAX1363_CHANNEL_SEL(_num) \ - | MAX1236_SCAN_MID_TO_CHANNEL \ - | MAX1363_CONFIG_SE, \ - .modemask[0] = _mask \ -} - -#define MAX1363_MODE_DIFF_SINGLE(_nump, _numm, _mask) { \ - .conf = MAX1363_CHANNEL_SEL(_nump) \ - | MAX1363_CONFIG_SCAN_SINGLE_1 \ - | MAX1363_CONFIG_DE, \ - .modemask[0] = _mask \ - } - -/* Can't think how to automate naming so specify for now */ -#define MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(_num, _numvals, _mask) { \ - .conf = MAX1363_CHANNEL_SEL(_num) \ - | MAX1363_CONFIG_SCAN_TO_CS \ - | MAX1363_CONFIG_DE, \ - .modemask[0] = _mask \ - } - -/* note only available for max1363 hence naming */ -#define MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(_num, _numvals, _mask) { \ - .conf = MAX1363_CHANNEL_SEL(_num) \ - | MAX1236_SCAN_MID_TO_CHANNEL \ - | MAX1363_CONFIG_SE, \ - .modemask[0] = _mask \ -} - -static const struct max1363_mode max1363_mode_table[] = { - /* All of the single channel options first */ - MAX1363_MODE_SINGLE(0, 1 << 0), - MAX1363_MODE_SINGLE(1, 1 << 1), - MAX1363_MODE_SINGLE(2, 1 << 2), - MAX1363_MODE_SINGLE(3, 1 << 3), - MAX1363_MODE_SINGLE(4, 1 << 4), - MAX1363_MODE_SINGLE(5, 1 << 5), - MAX1363_MODE_SINGLE(6, 1 << 6), - MAX1363_MODE_SINGLE(7, 1 << 7), - MAX1363_MODE_SINGLE(8, 1 << 8), - MAX1363_MODE_SINGLE(9, 1 << 9), - MAX1363_MODE_SINGLE(10, 1 << 10), - MAX1363_MODE_SINGLE(11, 1 << 11), - - MAX1363_MODE_DIFF_SINGLE(0, 1, 1 << 12), - MAX1363_MODE_DIFF_SINGLE(2, 3, 1 << 13), - MAX1363_MODE_DIFF_SINGLE(4, 5, 1 << 14), - MAX1363_MODE_DIFF_SINGLE(6, 7, 1 << 15), - MAX1363_MODE_DIFF_SINGLE(8, 9, 1 << 16), - MAX1363_MODE_DIFF_SINGLE(10, 11, 1 << 17), - MAX1363_MODE_DIFF_SINGLE(1, 0, 1 << 18), - MAX1363_MODE_DIFF_SINGLE(3, 2, 1 << 19), - MAX1363_MODE_DIFF_SINGLE(5, 4, 1 << 20), - MAX1363_MODE_DIFF_SINGLE(7, 6, 1 << 21), - MAX1363_MODE_DIFF_SINGLE(9, 8, 1 << 22), - MAX1363_MODE_DIFF_SINGLE(11, 10, 1 << 23), - - /* The multichannel scans next */ - MAX1363_MODE_SCAN_TO_CHANNEL(1, 0x003), - MAX1363_MODE_SCAN_TO_CHANNEL(2, 0x007), - MAX1236_MODE_SCAN_MID_TO_CHANNEL(2, 3, 0x00C), - MAX1363_MODE_SCAN_TO_CHANNEL(3, 0x00F), - MAX1363_MODE_SCAN_TO_CHANNEL(4, 0x01F), - MAX1363_MODE_SCAN_TO_CHANNEL(5, 0x03F), - MAX1363_MODE_SCAN_TO_CHANNEL(6, 0x07F), - MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 7, 0x0C0), - MAX1363_MODE_SCAN_TO_CHANNEL(7, 0x0FF), - MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 8, 0x1C0), - MAX1363_MODE_SCAN_TO_CHANNEL(8, 0x1FF), - MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 9, 0x3C0), - MAX1363_MODE_SCAN_TO_CHANNEL(9, 0x3FF), - MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 10, 0x7C0), - MAX1363_MODE_SCAN_TO_CHANNEL(10, 0x7FF), - MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 11, 0xFC0), - MAX1363_MODE_SCAN_TO_CHANNEL(11, 0xFFF), - - MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(2, 2, 0x003000), - MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(4, 3, 0x007000), - MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(6, 4, 0x00F000), - MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(8, 2, 0x018000), - MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(8, 5, 0x01F000), - MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(10, 3, 0x038000), - MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(10, 6, 0x3F000), - MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(3, 2, 0x0C0000), - MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(5, 3, 0x1C0000), - MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(7, 4, 0x3C0000), - MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(9, 2, 0x600000), - MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(9, 5, 0x7C0000), - MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(11, 3, 0xE00000), - MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(11, 6, 0xFC0000), -}; - -const struct max1363_mode -*max1363_match_mode(const unsigned long *mask, -const struct max1363_chip_info *ci) -{ - int i; - if (mask) - for (i = 0; i < ci->num_modes; i++) - if (bitmap_subset(mask, - max1363_mode_table[ci->mode_list[i]]. - modemask, - MAX1363_MAX_CHANNELS)) - return &max1363_mode_table[ci->mode_list[i]]; - return NULL; -} - -static int max1363_write_basic_config(struct i2c_client *client, - unsigned char d1, - unsigned char d2) -{ - u8 tx_buf[2] = {d1, d2}; - - return i2c_master_send(client, tx_buf, 2); -} - -int max1363_set_scan_mode(struct max1363_state *st) -{ - st->configbyte &= ~(MAX1363_CHANNEL_SEL_MASK - | MAX1363_SCAN_MASK - | MAX1363_SE_DE_MASK); - st->configbyte |= st->current_mode->conf; - - return max1363_write_basic_config(st->client, - st->setupbyte, - st->configbyte); -} - -static int max1363_read_single_chan(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - long m) -{ - int ret = 0; - s32 data; - char rxbuf[2]; - struct max1363_state *st = iio_priv(indio_dev); - struct i2c_client *client = st->client; - - mutex_lock(&indio_dev->mlock); - /* - * If monitor mode is enabled, the method for reading a single - * channel will have to be rather different and has not yet - * been implemented. - * - * Also, cannot read directly if buffered capture enabled. - */ - if (st->monitor_on || iio_buffer_enabled(indio_dev)) { - ret = -EBUSY; - goto error_ret; - } - - /* Check to see if current scan mode is correct */ - if (st->current_mode != &max1363_mode_table[chan->address]) { - /* Update scan mode if needed */ - st->current_mode = &max1363_mode_table[chan->address]; - ret = max1363_set_scan_mode(st); - if (ret < 0) - goto error_ret; - } - if (st->chip_info->bits != 8) { - /* Get reading */ - data = i2c_master_recv(client, rxbuf, 2); - if (data < 0) { - ret = data; - goto error_ret; - } - data = (s32)(rxbuf[1]) | ((s32)(rxbuf[0] & 0x0F)) << 8; - } else { - /* Get reading */ - data = i2c_master_recv(client, rxbuf, 1); - if (data < 0) { - ret = data; - goto error_ret; - } - data = rxbuf[0]; - } - *val = data; -error_ret: - mutex_unlock(&indio_dev->mlock); - return ret; - -} - -static int max1363_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - struct max1363_state *st = iio_priv(indio_dev); - int ret; - switch (m) { - case 0: - ret = max1363_read_single_chan(indio_dev, chan, val, m); - if (ret < 0) - return ret; - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - if ((1 << (st->chip_info->bits + 1)) > - st->chip_info->int_vref_mv) { - *val = 0; - *val2 = 500000; - return IIO_VAL_INT_PLUS_MICRO; - } else { - *val = (st->chip_info->int_vref_mv) - >> st->chip_info->bits; - return IIO_VAL_INT; - } - default: - return -EINVAL; - } - return 0; -} - -/* Applies to max1363 */ -static const enum max1363_modes max1363_mode_list[] = { - _s0, _s1, _s2, _s3, - s0to1, s0to2, s0to3, - d0m1, d2m3, d1m0, d3m2, - d0m1to2m3, d1m0to3m2, -}; - -#define MAX1363_EV_M \ - (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) \ - | IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)) -#define MAX1363_INFO_MASK IIO_CHAN_INFO_SCALE_SHARED_BIT -#define MAX1363_CHAN_U(num, addr, si, bits, evmask) \ - { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .channel = num, \ - .address = addr, \ - .info_mask = MAX1363_INFO_MASK, \ - .datasheet_name = "AIN"#num, \ - .scan_type = { \ - .sign = 'u', \ - .realbits = bits, \ - .storagebits = (bits > 8) ? 16 : 8, \ - .endianness = IIO_BE, \ - }, \ - .scan_index = si, \ - .event_mask = evmask, \ - } - -/* bipolar channel */ -#define MAX1363_CHAN_B(num, num2, addr, si, bits, evmask) \ - { \ - .type = IIO_VOLTAGE, \ - .differential = 1, \ - .indexed = 1, \ - .channel = num, \ - .channel2 = num2, \ - .address = addr, \ - .info_mask = MAX1363_INFO_MASK, \ - .datasheet_name = "AIN"#num"-AIN"#num2, \ - .scan_type = { \ - .sign = 's', \ - .realbits = bits, \ - .storagebits = (bits > 8) ? 16 : 8, \ - .endianness = IIO_BE, \ - }, \ - .scan_index = si, \ - .event_mask = evmask, \ - } - -#define MAX1363_4X_CHANS(bits, em) { \ - MAX1363_CHAN_U(0, _s0, 0, bits, em), \ - MAX1363_CHAN_U(1, _s1, 1, bits, em), \ - MAX1363_CHAN_U(2, _s2, 2, bits, em), \ - MAX1363_CHAN_U(3, _s3, 3, bits, em), \ - MAX1363_CHAN_B(0, 1, d0m1, 4, bits, em), \ - MAX1363_CHAN_B(2, 3, d2m3, 5, bits, em), \ - MAX1363_CHAN_B(1, 0, d1m0, 6, bits, em), \ - MAX1363_CHAN_B(3, 2, d3m2, 7, bits, em), \ - IIO_CHAN_SOFT_TIMESTAMP(8) \ - } - -static struct iio_chan_spec max1036_channels[] = MAX1363_4X_CHANS(8, 0); -static struct iio_chan_spec max1136_channels[] = MAX1363_4X_CHANS(10, 0); -static struct iio_chan_spec max1236_channels[] = MAX1363_4X_CHANS(12, 0); -static struct iio_chan_spec max1361_channels[] = - MAX1363_4X_CHANS(10, MAX1363_EV_M); -static struct iio_chan_spec max1363_channels[] = - MAX1363_4X_CHANS(12, MAX1363_EV_M); - -/* Appies to max1236, max1237 */ -static const enum max1363_modes max1236_mode_list[] = { - _s0, _s1, _s2, _s3, - s0to1, s0to2, s0to3, - d0m1, d2m3, d1m0, d3m2, - d0m1to2m3, d1m0to3m2, - s2to3, -}; - -/* Applies to max1238, max1239 */ -static const enum max1363_modes max1238_mode_list[] = { - _s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11, - s0to1, s0to2, s0to3, s0to4, s0to5, s0to6, - s0to7, s0to8, s0to9, s0to10, s0to11, - d0m1, d2m3, d4m5, d6m7, d8m9, d10m11, - d1m0, d3m2, d5m4, d7m6, d9m8, d11m10, - d0m1to2m3, d0m1to4m5, d0m1to6m7, d0m1to8m9, d0m1to10m11, - d1m0to3m2, d1m0to5m4, d1m0to7m6, d1m0to9m8, d1m0to11m10, - s6to7, s6to8, s6to9, s6to10, s6to11, - d6m7to8m9, d6m7to10m11, d7m6to9m8, d7m6to11m10, -}; - -#define MAX1363_12X_CHANS(bits) { \ - MAX1363_CHAN_U(0, _s0, 0, bits, 0), \ - MAX1363_CHAN_U(1, _s1, 1, bits, 0), \ - MAX1363_CHAN_U(2, _s2, 2, bits, 0), \ - MAX1363_CHAN_U(3, _s3, 3, bits, 0), \ - MAX1363_CHAN_U(4, _s4, 4, bits, 0), \ - MAX1363_CHAN_U(5, _s5, 5, bits, 0), \ - MAX1363_CHAN_U(6, _s6, 6, bits, 0), \ - MAX1363_CHAN_U(7, _s7, 7, bits, 0), \ - MAX1363_CHAN_U(8, _s8, 8, bits, 0), \ - MAX1363_CHAN_U(9, _s9, 9, bits, 0), \ - MAX1363_CHAN_U(10, _s10, 10, bits, 0), \ - MAX1363_CHAN_U(11, _s11, 11, bits, 0), \ - MAX1363_CHAN_B(0, 1, d0m1, 12, bits, 0), \ - MAX1363_CHAN_B(2, 3, d2m3, 13, bits, 0), \ - MAX1363_CHAN_B(4, 5, d4m5, 14, bits, 0), \ - MAX1363_CHAN_B(6, 7, d6m7, 15, bits, 0), \ - MAX1363_CHAN_B(8, 9, d8m9, 16, bits, 0), \ - MAX1363_CHAN_B(10, 11, d10m11, 17, bits, 0), \ - MAX1363_CHAN_B(1, 0, d1m0, 18, bits, 0), \ - MAX1363_CHAN_B(3, 2, d3m2, 19, bits, 0), \ - MAX1363_CHAN_B(5, 4, d5m4, 20, bits, 0), \ - MAX1363_CHAN_B(7, 6, d7m6, 21, bits, 0), \ - MAX1363_CHAN_B(9, 8, d9m8, 22, bits, 0), \ - MAX1363_CHAN_B(11, 10, d11m10, 23, bits, 0), \ - IIO_CHAN_SOFT_TIMESTAMP(24) \ - } -static struct iio_chan_spec max1038_channels[] = MAX1363_12X_CHANS(8); -static struct iio_chan_spec max1138_channels[] = MAX1363_12X_CHANS(10); -static struct iio_chan_spec max1238_channels[] = MAX1363_12X_CHANS(12); - -static const enum max1363_modes max11607_mode_list[] = { - _s0, _s1, _s2, _s3, - s0to1, s0to2, s0to3, - s2to3, - d0m1, d2m3, d1m0, d3m2, - d0m1to2m3, d1m0to3m2, -}; - -static const enum max1363_modes max11608_mode_list[] = { - _s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, - s0to1, s0to2, s0to3, s0to4, s0to5, s0to6, s0to7, - s6to7, - d0m1, d2m3, d4m5, d6m7, - d1m0, d3m2, d5m4, d7m6, - d0m1to2m3, d0m1to4m5, d0m1to6m7, - d1m0to3m2, d1m0to5m4, d1m0to7m6, -}; - -#define MAX1363_8X_CHANS(bits) { \ - MAX1363_CHAN_U(0, _s0, 0, bits, 0), \ - MAX1363_CHAN_U(1, _s1, 1, bits, 0), \ - MAX1363_CHAN_U(2, _s2, 2, bits, 0), \ - MAX1363_CHAN_U(3, _s3, 3, bits, 0), \ - MAX1363_CHAN_U(4, _s4, 4, bits, 0), \ - MAX1363_CHAN_U(5, _s5, 5, bits, 0), \ - MAX1363_CHAN_U(6, _s6, 6, bits, 0), \ - MAX1363_CHAN_U(7, _s7, 7, bits, 0), \ - MAX1363_CHAN_B(0, 1, d0m1, 8, bits, 0), \ - MAX1363_CHAN_B(2, 3, d2m3, 9, bits, 0), \ - MAX1363_CHAN_B(4, 5, d4m5, 10, bits, 0), \ - MAX1363_CHAN_B(6, 7, d6m7, 11, bits, 0), \ - MAX1363_CHAN_B(1, 0, d1m0, 12, bits, 0), \ - MAX1363_CHAN_B(3, 2, d3m2, 13, bits, 0), \ - MAX1363_CHAN_B(5, 4, d5m4, 14, bits, 0), \ - MAX1363_CHAN_B(7, 6, d7m6, 15, bits, 0), \ - IIO_CHAN_SOFT_TIMESTAMP(16) \ -} -static struct iio_chan_spec max11602_channels[] = MAX1363_8X_CHANS(8); -static struct iio_chan_spec max11608_channels[] = MAX1363_8X_CHANS(10); -static struct iio_chan_spec max11614_channels[] = MAX1363_8X_CHANS(12); - -static const enum max1363_modes max11644_mode_list[] = { - _s0, _s1, s0to1, d0m1, d1m0, -}; - -#define MAX1363_2X_CHANS(bits) { \ - MAX1363_CHAN_U(0, _s0, 0, bits, 0), \ - MAX1363_CHAN_U(1, _s1, 1, bits, 0), \ - MAX1363_CHAN_B(0, 1, d0m1, 2, bits, 0), \ - MAX1363_CHAN_B(1, 0, d1m0, 3, bits, 0), \ - IIO_CHAN_SOFT_TIMESTAMP(4) \ - } - -static struct iio_chan_spec max11646_channels[] = MAX1363_2X_CHANS(10); -static struct iio_chan_spec max11644_channels[] = MAX1363_2X_CHANS(12); - -enum { max1361, - max1362, - max1363, - max1364, - max1036, - max1037, - max1038, - max1039, - max1136, - max1137, - max1138, - max1139, - max1236, - max1237, - max1238, - max1239, - max11600, - max11601, - max11602, - max11603, - max11604, - max11605, - max11606, - max11607, - max11608, - max11609, - max11610, - max11611, - max11612, - max11613, - max11614, - max11615, - max11616, - max11617, - max11644, - max11645, - max11646, - max11647 -}; - -static const int max1363_monitor_speeds[] = { 133000, 665000, 33300, 16600, - 8300, 4200, 2000, 1000 }; - -static ssize_t max1363_monitor_show_freq(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct max1363_state *st = iio_priv(dev_get_drvdata(dev)); - return sprintf(buf, "%d\n", max1363_monitor_speeds[st->monitor_speed]); -} - -static ssize_t max1363_monitor_store_freq(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct max1363_state *st = iio_priv(indio_dev); - int i, ret; - unsigned long val; - bool found = false; - - ret = strict_strtoul(buf, 10, &val); - if (ret) - return -EINVAL; - for (i = 0; i < ARRAY_SIZE(max1363_monitor_speeds); i++) - if (val == max1363_monitor_speeds[i]) { - found = true; - break; - } - if (!found) - return -EINVAL; - - mutex_lock(&indio_dev->mlock); - st->monitor_speed = i; - mutex_unlock(&indio_dev->mlock); - - return 0; -} - -static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR, - max1363_monitor_show_freq, - max1363_monitor_store_freq); - -static IIO_CONST_ATTR(sampling_frequency_available, - "133000 665000 33300 16600 8300 4200 2000 1000"); - -static int max1363_read_thresh(struct iio_dev *indio_dev, - u64 event_code, - int *val) -{ - struct max1363_state *st = iio_priv(indio_dev); - if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING) - *val = st->thresh_low[IIO_EVENT_CODE_EXTRACT_NUM(event_code)]; - else - *val = st->thresh_high[IIO_EVENT_CODE_EXTRACT_NUM(event_code)]; - return 0; -} - -static int max1363_write_thresh(struct iio_dev *indio_dev, - u64 event_code, - int val) -{ - struct max1363_state *st = iio_priv(indio_dev); - /* make it handle signed correctly as well */ - switch (st->chip_info->bits) { - case 10: - if (val > 0x3FF) - return -EINVAL; - break; - case 12: - if (val > 0xFFF) - return -EINVAL; - break; - } - - switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) { - case IIO_EV_DIR_FALLING: - st->thresh_low[IIO_EVENT_CODE_EXTRACT_NUM(event_code)] = val; - break; - case IIO_EV_DIR_RISING: - st->thresh_high[IIO_EVENT_CODE_EXTRACT_NUM(event_code)] = val; - break; - } - - return 0; -} - -static const u64 max1363_event_codes[] = { - IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0, - IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), - IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 1, - IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), - IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 2, - IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), - IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 3, - IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), - IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0, - IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), - IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 1, - IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), - IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 2, - IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), - IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 3, - IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), -}; - -static irqreturn_t max1363_event_handler(int irq, void *private) -{ - struct iio_dev *indio_dev = private; - struct max1363_state *st = iio_priv(indio_dev); - s64 timestamp = iio_get_time_ns(); - unsigned long mask, loc; - u8 rx; - u8 tx[2] = { st->setupbyte, - MAX1363_MON_INT_ENABLE | (st->monitor_speed << 1) | 0xF0 }; - - i2c_master_recv(st->client, &rx, 1); - mask = rx; - for_each_set_bit(loc, &mask, 8) - iio_push_event(indio_dev, max1363_event_codes[loc], timestamp); - i2c_master_send(st->client, tx, 2); - - return IRQ_HANDLED; -} - -static int max1363_read_event_config(struct iio_dev *indio_dev, - u64 event_code) -{ - struct max1363_state *st = iio_priv(indio_dev); - - int val; - int number = IIO_EVENT_CODE_EXTRACT_NUM(event_code); - mutex_lock(&indio_dev->mlock); - if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING) - val = (1 << number) & st->mask_low; - else - val = (1 << number) & st->mask_high; - mutex_unlock(&indio_dev->mlock); - - return val; -} - -static int max1363_monitor_mode_update(struct max1363_state *st, int enabled) -{ - u8 *tx_buf; - int ret, i = 3, j; - unsigned long numelements; - int len; - const long *modemask; - - if (!enabled) { - /* transition to ring capture is not currently supported */ - st->setupbyte &= ~MAX1363_SETUP_MONITOR_SETUP; - st->configbyte &= ~MAX1363_SCAN_MASK; - st->monitor_on = false; - return max1363_write_basic_config(st->client, - st->setupbyte, - st->configbyte); - } - - /* Ensure we are in the relevant mode */ - st->setupbyte |= MAX1363_SETUP_MONITOR_SETUP; - st->configbyte &= ~(MAX1363_CHANNEL_SEL_MASK - | MAX1363_SCAN_MASK - | MAX1363_SE_DE_MASK); - st->configbyte |= MAX1363_CONFIG_SCAN_MONITOR_MODE; - if ((st->mask_low | st->mask_high) & 0x0F) { - st->configbyte |= max1363_mode_table[s0to3].conf; - modemask = max1363_mode_table[s0to3].modemask; - } else if ((st->mask_low | st->mask_high) & 0x30) { - st->configbyte |= max1363_mode_table[d0m1to2m3].conf; - modemask = max1363_mode_table[d0m1to2m3].modemask; - } else { - st->configbyte |= max1363_mode_table[d1m0to3m2].conf; - modemask = max1363_mode_table[d1m0to3m2].modemask; - } - numelements = bitmap_weight(modemask, MAX1363_MAX_CHANNELS); - len = 3 * numelements + 3; - tx_buf = kmalloc(len, GFP_KERNEL); - if (!tx_buf) { - ret = -ENOMEM; - goto error_ret; - } - tx_buf[0] = st->configbyte; - tx_buf[1] = st->setupbyte; - tx_buf[2] = (st->monitor_speed << 1); - - /* - * So we need to do yet another bit of nefarious scan mode - * setup to match what we need. - */ - for (j = 0; j < 8; j++) - if (test_bit(j, modemask)) { - /* Establish the mode is in the scan */ - if (st->mask_low & (1 << j)) { - tx_buf[i] = (st->thresh_low[j] >> 4) & 0xFF; - tx_buf[i + 1] = (st->thresh_low[j] << 4) & 0xF0; - } else if (j < 4) { - tx_buf[i] = 0; - tx_buf[i + 1] = 0; - } else { - tx_buf[i] = 0x80; - tx_buf[i + 1] = 0; - } - if (st->mask_high & (1 << j)) { - tx_buf[i + 1] |= - (st->thresh_high[j] >> 8) & 0x0F; - tx_buf[i + 2] = st->thresh_high[j] & 0xFF; - } else if (j < 4) { - tx_buf[i + 1] |= 0x0F; - tx_buf[i + 2] = 0xFF; - } else { - tx_buf[i + 1] |= 0x07; - tx_buf[i + 2] = 0xFF; - } - i += 3; - } - - - ret = i2c_master_send(st->client, tx_buf, len); - if (ret < 0) - goto error_ret; - if (ret != len) { - ret = -EIO; - goto error_ret; - } - - /* - * Now that we hopefully have sensible thresholds in place it is - * time to turn the interrupts on. - * It is unclear from the data sheet if this should be necessary - * (i.e. whether monitor mode setup is atomic) but it appears to - * be in practice. - */ - tx_buf[0] = st->setupbyte; - tx_buf[1] = MAX1363_MON_INT_ENABLE | (st->monitor_speed << 1) | 0xF0; - ret = i2c_master_send(st->client, tx_buf, 2); - if (ret < 0) - goto error_ret; - if (ret != 2) { - ret = -EIO; - goto error_ret; - } - ret = 0; - st->monitor_on = true; -error_ret: - - kfree(tx_buf); - - return ret; -} - -/* - * To keep this manageable we always use one of 3 scan modes. - * Scan 0...3, 0-1,2-3 and 1-0,3-2 - */ - -static inline int __max1363_check_event_mask(int thismask, int checkmask) -{ - int ret = 0; - /* Is it unipolar */ - if (thismask < 4) { - if (checkmask & ~0x0F) { - ret = -EBUSY; - goto error_ret; - } - } else if (thismask < 6) { - if (checkmask & ~0x30) { - ret = -EBUSY; - goto error_ret; - } - } else if (checkmask & ~0xC0) - ret = -EBUSY; -error_ret: - return ret; -} - -static int max1363_write_event_config(struct iio_dev *indio_dev, - u64 event_code, - int state) -{ - int ret = 0; - struct max1363_state *st = iio_priv(indio_dev); - u16 unifiedmask; - int number = IIO_EVENT_CODE_EXTRACT_NUM(event_code); - - mutex_lock(&indio_dev->mlock); - unifiedmask = st->mask_low | st->mask_high; - if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING) { - - if (state == 0) - st->mask_low &= ~(1 << number); - else { - ret = __max1363_check_event_mask((1 << number), - unifiedmask); - if (ret) - goto error_ret; - st->mask_low |= (1 << number); - } - } else { - if (state == 0) - st->mask_high &= ~(1 << number); - else { - ret = __max1363_check_event_mask((1 << number), - unifiedmask); - if (ret) - goto error_ret; - st->mask_high |= (1 << number); - } - } - - max1363_monitor_mode_update(st, !!(st->mask_high | st->mask_low)); -error_ret: - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -/* - * As with scan_elements, only certain sets of these can - * be combined. - */ -static struct attribute *max1363_event_attributes[] = { - &iio_dev_attr_sampling_frequency.dev_attr.attr, - &iio_const_attr_sampling_frequency_available.dev_attr.attr, - NULL, -}; - -static struct attribute_group max1363_event_attribute_group = { - .attrs = max1363_event_attributes, - .name = "events", -}; - -#define MAX1363_EVENT_FUNCS \ - - -static const struct iio_info max1238_info = { - .read_raw = &max1363_read_raw, - .driver_module = THIS_MODULE, -}; - -static const struct iio_info max1363_info = { - .read_event_value = &max1363_read_thresh, - .write_event_value = &max1363_write_thresh, - .read_event_config = &max1363_read_event_config, - .write_event_config = &max1363_write_event_config, - .read_raw = &max1363_read_raw, - .update_scan_mode = &max1363_update_scan_mode, - .driver_module = THIS_MODULE, - .event_attrs = &max1363_event_attribute_group, -}; - -/* max1363 and max1368 tested - rest from data sheet */ -static const struct max1363_chip_info max1363_chip_info_tbl[] = { - [max1361] = { - .bits = 10, - .int_vref_mv = 2048, - .mode_list = max1363_mode_list, - .num_modes = ARRAY_SIZE(max1363_mode_list), - .default_mode = s0to3, - .channels = max1361_channels, - .num_channels = ARRAY_SIZE(max1361_channels), - .info = &max1363_info, - }, - [max1362] = { - .bits = 10, - .int_vref_mv = 4096, - .mode_list = max1363_mode_list, - .num_modes = ARRAY_SIZE(max1363_mode_list), - .default_mode = s0to3, - .channels = max1361_channels, - .num_channels = ARRAY_SIZE(max1361_channels), - .info = &max1363_info, - }, - [max1363] = { - .bits = 12, - .int_vref_mv = 2048, - .mode_list = max1363_mode_list, - .num_modes = ARRAY_SIZE(max1363_mode_list), - .default_mode = s0to3, - .channels = max1363_channels, - .num_channels = ARRAY_SIZE(max1363_channels), - .info = &max1363_info, - }, - [max1364] = { - .bits = 12, - .int_vref_mv = 4096, - .mode_list = max1363_mode_list, - .num_modes = ARRAY_SIZE(max1363_mode_list), - .default_mode = s0to3, - .channels = max1363_channels, - .num_channels = ARRAY_SIZE(max1363_channels), - .info = &max1363_info, - }, - [max1036] = { - .bits = 8, - .int_vref_mv = 4096, - .mode_list = max1236_mode_list, - .num_modes = ARRAY_SIZE(max1236_mode_list), - .default_mode = s0to3, - .info = &max1238_info, - .channels = max1036_channels, - .num_channels = ARRAY_SIZE(max1036_channels), - }, - [max1037] = { - .bits = 8, - .int_vref_mv = 2048, - .mode_list = max1236_mode_list, - .num_modes = ARRAY_SIZE(max1236_mode_list), - .default_mode = s0to3, - .info = &max1238_info, - .channels = max1036_channels, - .num_channels = ARRAY_SIZE(max1036_channels), - }, - [max1038] = { - .bits = 8, - .int_vref_mv = 4096, - .mode_list = max1238_mode_list, - .num_modes = ARRAY_SIZE(max1238_mode_list), - .default_mode = s0to11, - .info = &max1238_info, - .channels = max1038_channels, - .num_channels = ARRAY_SIZE(max1038_channels), - }, - [max1039] = { - .bits = 8, - .int_vref_mv = 2048, - .mode_list = max1238_mode_list, - .num_modes = ARRAY_SIZE(max1238_mode_list), - .default_mode = s0to11, - .info = &max1238_info, - .channels = max1038_channels, - .num_channels = ARRAY_SIZE(max1038_channels), - }, - [max1136] = { - .bits = 10, - .int_vref_mv = 4096, - .mode_list = max1236_mode_list, - .num_modes = ARRAY_SIZE(max1236_mode_list), - .default_mode = s0to3, - .info = &max1238_info, - .channels = max1136_channels, - .num_channels = ARRAY_SIZE(max1136_channels), - }, - [max1137] = { - .bits = 10, - .int_vref_mv = 2048, - .mode_list = max1236_mode_list, - .num_modes = ARRAY_SIZE(max1236_mode_list), - .default_mode = s0to3, - .info = &max1238_info, - .channels = max1136_channels, - .num_channels = ARRAY_SIZE(max1136_channels), - }, - [max1138] = { - .bits = 10, - .int_vref_mv = 4096, - .mode_list = max1238_mode_list, - .num_modes = ARRAY_SIZE(max1238_mode_list), - .default_mode = s0to11, - .info = &max1238_info, - .channels = max1138_channels, - .num_channels = ARRAY_SIZE(max1138_channels), - }, - [max1139] = { - .bits = 10, - .int_vref_mv = 2048, - .mode_list = max1238_mode_list, - .num_modes = ARRAY_SIZE(max1238_mode_list), - .default_mode = s0to11, - .info = &max1238_info, - .channels = max1138_channels, - .num_channels = ARRAY_SIZE(max1138_channels), - }, - [max1236] = { - .bits = 12, - .int_vref_mv = 4096, - .mode_list = max1236_mode_list, - .num_modes = ARRAY_SIZE(max1236_mode_list), - .default_mode = s0to3, - .info = &max1238_info, - .channels = max1236_channels, - .num_channels = ARRAY_SIZE(max1236_channels), - }, - [max1237] = { - .bits = 12, - .int_vref_mv = 2048, - .mode_list = max1236_mode_list, - .num_modes = ARRAY_SIZE(max1236_mode_list), - .default_mode = s0to3, - .info = &max1238_info, - .channels = max1236_channels, - .num_channels = ARRAY_SIZE(max1236_channels), - }, - [max1238] = { - .bits = 12, - .int_vref_mv = 4096, - .mode_list = max1238_mode_list, - .num_modes = ARRAY_SIZE(max1238_mode_list), - .default_mode = s0to11, - .info = &max1238_info, - .channels = max1238_channels, - .num_channels = ARRAY_SIZE(max1238_channels), - }, - [max1239] = { - .bits = 12, - .int_vref_mv = 2048, - .mode_list = max1238_mode_list, - .num_modes = ARRAY_SIZE(max1238_mode_list), - .default_mode = s0to11, - .info = &max1238_info, - .channels = max1238_channels, - .num_channels = ARRAY_SIZE(max1238_channels), - }, - [max11600] = { - .bits = 8, - .int_vref_mv = 4096, - .mode_list = max11607_mode_list, - .num_modes = ARRAY_SIZE(max11607_mode_list), - .default_mode = s0to3, - .info = &max1238_info, - .channels = max1036_channels, - .num_channels = ARRAY_SIZE(max1036_channels), - }, - [max11601] = { - .bits = 8, - .int_vref_mv = 2048, - .mode_list = max11607_mode_list, - .num_modes = ARRAY_SIZE(max11607_mode_list), - .default_mode = s0to3, - .info = &max1238_info, - .channels = max1036_channels, - .num_channels = ARRAY_SIZE(max1036_channels), - }, - [max11602] = { - .bits = 8, - .int_vref_mv = 4096, - .mode_list = max11608_mode_list, - .num_modes = ARRAY_SIZE(max11608_mode_list), - .default_mode = s0to7, - .info = &max1238_info, - .channels = max11602_channels, - .num_channels = ARRAY_SIZE(max11602_channels), - }, - [max11603] = { - .bits = 8, - .int_vref_mv = 2048, - .mode_list = max11608_mode_list, - .num_modes = ARRAY_SIZE(max11608_mode_list), - .default_mode = s0to7, - .info = &max1238_info, - .channels = max11602_channels, - .num_channels = ARRAY_SIZE(max11602_channels), - }, - [max11604] = { - .bits = 8, - .int_vref_mv = 4098, - .mode_list = max1238_mode_list, - .num_modes = ARRAY_SIZE(max1238_mode_list), - .default_mode = s0to11, - .info = &max1238_info, - .channels = max1238_channels, - .num_channels = ARRAY_SIZE(max1238_channels), - }, - [max11605] = { - .bits = 8, - .int_vref_mv = 2048, - .mode_list = max1238_mode_list, - .num_modes = ARRAY_SIZE(max1238_mode_list), - .default_mode = s0to11, - .info = &max1238_info, - .channels = max1238_channels, - .num_channels = ARRAY_SIZE(max1238_channels), - }, - [max11606] = { - .bits = 10, - .int_vref_mv = 4096, - .mode_list = max11607_mode_list, - .num_modes = ARRAY_SIZE(max11607_mode_list), - .default_mode = s0to3, - .info = &max1238_info, - .channels = max1136_channels, - .num_channels = ARRAY_SIZE(max1136_channels), - }, - [max11607] = { - .bits = 10, - .int_vref_mv = 2048, - .mode_list = max11607_mode_list, - .num_modes = ARRAY_SIZE(max11607_mode_list), - .default_mode = s0to3, - .info = &max1238_info, - .channels = max1136_channels, - .num_channels = ARRAY_SIZE(max1136_channels), - }, - [max11608] = { - .bits = 10, - .int_vref_mv = 4096, - .mode_list = max11608_mode_list, - .num_modes = ARRAY_SIZE(max11608_mode_list), - .default_mode = s0to7, - .info = &max1238_info, - .channels = max11608_channels, - .num_channels = ARRAY_SIZE(max11608_channels), - }, - [max11609] = { - .bits = 10, - .int_vref_mv = 2048, - .mode_list = max11608_mode_list, - .num_modes = ARRAY_SIZE(max11608_mode_list), - .default_mode = s0to7, - .info = &max1238_info, - .channels = max11608_channels, - .num_channels = ARRAY_SIZE(max11608_channels), - }, - [max11610] = { - .bits = 10, - .int_vref_mv = 4098, - .mode_list = max1238_mode_list, - .num_modes = ARRAY_SIZE(max1238_mode_list), - .default_mode = s0to11, - .info = &max1238_info, - .channels = max1238_channels, - .num_channels = ARRAY_SIZE(max1238_channels), - }, - [max11611] = { - .bits = 10, - .int_vref_mv = 2048, - .mode_list = max1238_mode_list, - .num_modes = ARRAY_SIZE(max1238_mode_list), - .default_mode = s0to11, - .info = &max1238_info, - .channels = max1238_channels, - .num_channels = ARRAY_SIZE(max1238_channels), - }, - [max11612] = { - .bits = 12, - .int_vref_mv = 4096, - .mode_list = max11607_mode_list, - .num_modes = ARRAY_SIZE(max11607_mode_list), - .default_mode = s0to3, - .info = &max1238_info, - .channels = max1363_channels, - .num_channels = ARRAY_SIZE(max1363_channels), - }, - [max11613] = { - .bits = 12, - .int_vref_mv = 2048, - .mode_list = max11607_mode_list, - .num_modes = ARRAY_SIZE(max11607_mode_list), - .default_mode = s0to3, - .info = &max1238_info, - .channels = max1363_channels, - .num_channels = ARRAY_SIZE(max1363_channels), - }, - [max11614] = { - .bits = 12, - .int_vref_mv = 4096, - .mode_list = max11608_mode_list, - .num_modes = ARRAY_SIZE(max11608_mode_list), - .default_mode = s0to7, - .info = &max1238_info, - .channels = max11614_channels, - .num_channels = ARRAY_SIZE(max11614_channels), - }, - [max11615] = { - .bits = 12, - .int_vref_mv = 2048, - .mode_list = max11608_mode_list, - .num_modes = ARRAY_SIZE(max11608_mode_list), - .default_mode = s0to7, - .info = &max1238_info, - .channels = max11614_channels, - .num_channels = ARRAY_SIZE(max11614_channels), - }, - [max11616] = { - .bits = 12, - .int_vref_mv = 4098, - .mode_list = max1238_mode_list, - .num_modes = ARRAY_SIZE(max1238_mode_list), - .default_mode = s0to11, - .info = &max1238_info, - .channels = max1238_channels, - .num_channels = ARRAY_SIZE(max1238_channels), - }, - [max11617] = { - .bits = 12, - .int_vref_mv = 2048, - .mode_list = max1238_mode_list, - .num_modes = ARRAY_SIZE(max1238_mode_list), - .default_mode = s0to11, - .info = &max1238_info, - .channels = max1238_channels, - .num_channels = ARRAY_SIZE(max1238_channels), - }, - [max11644] = { - .bits = 12, - .int_vref_mv = 2048, - .mode_list = max11644_mode_list, - .num_modes = ARRAY_SIZE(max11644_mode_list), - .default_mode = s0to1, - .info = &max1238_info, - .channels = max11644_channels, - .num_channels = ARRAY_SIZE(max11644_channels), - }, - [max11645] = { - .bits = 12, - .int_vref_mv = 4096, - .mode_list = max11644_mode_list, - .num_modes = ARRAY_SIZE(max11644_mode_list), - .default_mode = s0to1, - .info = &max1238_info, - .channels = max11644_channels, - .num_channels = ARRAY_SIZE(max11644_channels), - }, - [max11646] = { - .bits = 10, - .int_vref_mv = 2048, - .mode_list = max11644_mode_list, - .num_modes = ARRAY_SIZE(max11644_mode_list), - .default_mode = s0to1, - .info = &max1238_info, - .channels = max11646_channels, - .num_channels = ARRAY_SIZE(max11646_channels), - }, - [max11647] = { - .bits = 10, - .int_vref_mv = 4096, - .mode_list = max11644_mode_list, - .num_modes = ARRAY_SIZE(max11644_mode_list), - .default_mode = s0to1, - .info = &max1238_info, - .channels = max11646_channels, - .num_channels = ARRAY_SIZE(max11646_channels), - }, -}; - - - -static int max1363_initial_setup(struct max1363_state *st) -{ - st->setupbyte = MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD - | MAX1363_SETUP_POWER_UP_INT_REF - | MAX1363_SETUP_INT_CLOCK - | MAX1363_SETUP_UNIPOLAR - | MAX1363_SETUP_NORESET; - - /* Set scan mode writes the config anyway so wait until then*/ - st->setupbyte = MAX1363_SETUP_BYTE(st->setupbyte); - st->current_mode = &max1363_mode_table[st->chip_info->default_mode]; - st->configbyte = MAX1363_CONFIG_BYTE(st->configbyte); - - return max1363_set_scan_mode(st); -} - -static int __devinit max1363_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int ret, i; - struct max1363_state *st; - struct iio_dev *indio_dev; - struct regulator *reg; - - reg = regulator_get(&client->dev, "vcc"); - if (IS_ERR(reg)) { - ret = PTR_ERR(reg); - goto error_out; - } - - ret = regulator_enable(reg); - if (ret) - goto error_put_reg; - - indio_dev = iio_allocate_device(sizeof(struct max1363_state)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_disable_reg; - } - st = iio_priv(indio_dev); - st->reg = reg; - /* this is only used for device removal purposes */ - i2c_set_clientdata(client, indio_dev); - - st->chip_info = &max1363_chip_info_tbl[id->driver_data]; - st->client = client; - - indio_dev->available_scan_masks - = kzalloc(BITS_TO_LONGS(MAX1363_MAX_CHANNELS)*sizeof(long)* - (st->chip_info->num_modes + 1), GFP_KERNEL); - if (!indio_dev->available_scan_masks) { - ret = -ENOMEM; - goto error_free_device; - } - - for (i = 0; i < st->chip_info->num_modes; i++) - bitmap_copy(indio_dev->available_scan_masks + - BITS_TO_LONGS(MAX1363_MAX_CHANNELS)*i, - max1363_mode_table[st->chip_info->mode_list[i]] - .modemask, MAX1363_MAX_CHANNELS); - /* Estabilish that the iio_dev is a child of the i2c device */ - indio_dev->dev.parent = &client->dev; - indio_dev->name = id->name; - indio_dev->channels = st->chip_info->channels; - indio_dev->num_channels = st->chip_info->num_channels; - indio_dev->info = st->chip_info->info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = st->chip_info->channels; - indio_dev->num_channels = st->chip_info->num_channels; - ret = max1363_initial_setup(st); - if (ret < 0) - goto error_free_available_scan_masks; - - ret = max1363_register_ring_funcs_and_init(indio_dev); - if (ret) - goto error_free_available_scan_masks; - - ret = iio_buffer_register(indio_dev, - st->chip_info->channels, - st->chip_info->num_channels); - if (ret) - goto error_cleanup_ring; - - if (client->irq) { - ret = request_threaded_irq(st->client->irq, - NULL, - &max1363_event_handler, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - "max1363_event", - indio_dev); - - if (ret) - goto error_uninit_ring; - } - - ret = iio_device_register(indio_dev); - if (ret < 0) - goto error_free_irq; - - return 0; -error_free_irq: - free_irq(st->client->irq, indio_dev); -error_uninit_ring: - iio_buffer_unregister(indio_dev); -error_cleanup_ring: - max1363_ring_cleanup(indio_dev); -error_free_available_scan_masks: - kfree(indio_dev->available_scan_masks); -error_free_device: - iio_free_device(indio_dev); -error_disable_reg: - regulator_disable(reg); -error_put_reg: - regulator_put(reg); -error_out: - return ret; -} - -static int max1363_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct max1363_state *st = iio_priv(indio_dev); - struct regulator *reg = st->reg; - - iio_device_unregister(indio_dev); - if (client->irq) - free_irq(st->client->irq, indio_dev); - iio_buffer_unregister(indio_dev); - max1363_ring_cleanup(indio_dev); - kfree(indio_dev->available_scan_masks); - if (!IS_ERR(reg)) { - regulator_disable(reg); - regulator_put(reg); - } - iio_free_device(indio_dev); - - return 0; -} - -static const struct i2c_device_id max1363_id[] = { - { "max1361", max1361 }, - { "max1362", max1362 }, - { "max1363", max1363 }, - { "max1364", max1364 }, - { "max1036", max1036 }, - { "max1037", max1037 }, - { "max1038", max1038 }, - { "max1039", max1039 }, - { "max1136", max1136 }, - { "max1137", max1137 }, - { "max1138", max1138 }, - { "max1139", max1139 }, - { "max1236", max1236 }, - { "max1237", max1237 }, - { "max1238", max1238 }, - { "max1239", max1239 }, - { "max11600", max11600 }, - { "max11601", max11601 }, - { "max11602", max11602 }, - { "max11603", max11603 }, - { "max11604", max11604 }, - { "max11605", max11605 }, - { "max11606", max11606 }, - { "max11607", max11607 }, - { "max11608", max11608 }, - { "max11609", max11609 }, - { "max11610", max11610 }, - { "max11611", max11611 }, - { "max11612", max11612 }, - { "max11613", max11613 }, - { "max11614", max11614 }, - { "max11615", max11615 }, - { "max11616", max11616 }, - { "max11617", max11617 }, - {} -}; - -MODULE_DEVICE_TABLE(i2c, max1363_id); - -static struct i2c_driver max1363_driver = { - .driver = { - .name = "max1363", - }, - .probe = max1363_probe, - .remove = max1363_remove, - .id_table = max1363_id, -}; -module_i2c_driver(max1363_driver); - -MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); -MODULE_DESCRIPTION("Maxim 1363 ADC"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c deleted file mode 100644 index f730b3fb971..00000000000 --- a/drivers/staging/iio/adc/max1363_ring.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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. - * - * max1363_ring.c - */ - -#include <linux/interrupt.h> -#include <linux/slab.h> -#include <linux/kernel.h> -#include <linux/i2c.h> -#include <linux/bitops.h> - -#include "../iio.h" -#include "../buffer.h" -#include "../ring_sw.h" -#include "../trigger_consumer.h" - -#include "max1363.h" - -int max1363_update_scan_mode(struct iio_dev *indio_dev, - const unsigned long *scan_mask) -{ - struct max1363_state *st = iio_priv(indio_dev); - - /* - * Need to figure out the current mode based upon the requested - * scan mask in iio_dev - */ - st->current_mode = max1363_match_mode(scan_mask, st->chip_info); - if (!st->current_mode) - return -EINVAL; - max1363_set_scan_mode(st); - return 0; -} - -static irqreturn_t max1363_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct max1363_state *st = iio_priv(indio_dev); - s64 time_ns; - __u8 *rxbuf; - int b_sent; - size_t d_size; - unsigned long numvals = bitmap_weight(st->current_mode->modemask, - MAX1363_MAX_CHANNELS); - - /* Ensure the timestamp is 8 byte aligned */ - if (st->chip_info->bits != 8) - d_size = numvals*2; - else - d_size = numvals; - if (indio_dev->buffer->scan_timestamp) { - d_size += sizeof(s64); - if (d_size % sizeof(s64)) - d_size += sizeof(s64) - (d_size % sizeof(s64)); - } - /* 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 IRQ_HANDLED; - - rxbuf = kmalloc(d_size, GFP_KERNEL); - if (rxbuf == NULL) - return -ENOMEM; - if (st->chip_info->bits != 8) - b_sent = i2c_master_recv(st->client, rxbuf, numvals*2); - else - b_sent = i2c_master_recv(st->client, rxbuf, numvals); - if (b_sent < 0) - goto done; - - time_ns = iio_get_time_ns(); - - if (indio_dev->buffer->scan_timestamp) - memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns)); - iio_push_to_buffer(indio_dev->buffer, rxbuf, time_ns); - -done: - iio_trigger_notify_done(indio_dev->trig); - kfree(rxbuf); - - return IRQ_HANDLED; -} - -static const struct iio_buffer_setup_ops max1363_ring_setup_ops = { - .postenable = &iio_triggered_buffer_postenable, - .preenable = &iio_sw_buffer_preenable, - .predisable = &iio_triggered_buffer_predisable, -}; - -int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) -{ - struct max1363_state *st = iio_priv(indio_dev); - int ret = 0; - - indio_dev->buffer = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->buffer) { - ret = -ENOMEM; - goto error_ret; - } - indio_dev->pollfunc = iio_alloc_pollfunc(NULL, - &max1363_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "%s_consumer%d", - st->client->name, - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_deallocate_sw_rb; - } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; - /* Ring buffer functions - here trigger setup related */ - indio_dev->setup_ops = &max1363_ring_setup_ops; - - /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - - return 0; - -error_deallocate_sw_rb: - iio_sw_rb_free(indio_dev->buffer); -error_ret: - return ret; -} - -void max1363_ring_cleanup(struct iio_dev *indio_dev) -{ - /* ensure that the trigger has been detached */ - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->buffer); -} diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c new file mode 100644 index 00000000000..52d7517b342 --- /dev/null +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -0,0 +1,1685 @@ +/* + * Freescale i.MX28 LRADC driver + * + * Copyright (c) 2012 DENX Software Engineering, GmbH. + * Marek Vasut <marex@denx.de> + * + * 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. + */ + +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/sysfs.h> +#include <linux/list.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> +#include <linux/wait.h> +#include <linux/sched.h> +#include <linux/stmp_device.h> +#include <linux/bitops.h> +#include <linux/completion.h> +#include <linux/delay.h> +#include <linux/input.h> +#include <linux/clk.h> + +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> +#include <linux/iio/trigger.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> + +#define DRIVER_NAME "mxs-lradc" + +#define LRADC_MAX_DELAY_CHANS 4 +#define LRADC_MAX_MAPPED_CHANS 8 +#define LRADC_MAX_TOTAL_CHANS 16 + +#define LRADC_DELAY_TIMER_HZ 2000 + +/* + * Make this runtime configurable if necessary. Currently, if the buffered mode + * is enabled, the LRADC takes LRADC_DELAY_TIMER_LOOP samples of data before + * triggering IRQ. The sampling happens every (LRADC_DELAY_TIMER_PER / 2000) + * seconds. The result is that the samples arrive every 500mS. + */ +#define LRADC_DELAY_TIMER_PER 200 +#define LRADC_DELAY_TIMER_LOOP 5 + +/* + * Once the pen touches the touchscreen, the touchscreen switches from + * IRQ-driven mode to polling mode to prevent interrupt storm. The polling + * is realized by worker thread, which is called every 20 or so milliseconds. + * This gives the touchscreen enough fluence and does not strain the system + * too much. + */ +#define LRADC_TS_SAMPLE_DELAY_MS 5 + +/* + * The LRADC reads the following amount of samples from each touchscreen + * channel and the driver then computes avarage of these. + */ +#define LRADC_TS_SAMPLE_AMOUNT 4 + +enum mxs_lradc_id { + IMX23_LRADC, + IMX28_LRADC, +}; + +static const char * const mx23_lradc_irq_names[] = { + "mxs-lradc-touchscreen", + "mxs-lradc-channel0", + "mxs-lradc-channel1", + "mxs-lradc-channel2", + "mxs-lradc-channel3", + "mxs-lradc-channel4", + "mxs-lradc-channel5", + "mxs-lradc-channel6", + "mxs-lradc-channel7", +}; + +static const char * const mx28_lradc_irq_names[] = { + "mxs-lradc-touchscreen", + "mxs-lradc-thresh0", + "mxs-lradc-thresh1", + "mxs-lradc-channel0", + "mxs-lradc-channel1", + "mxs-lradc-channel2", + "mxs-lradc-channel3", + "mxs-lradc-channel4", + "mxs-lradc-channel5", + "mxs-lradc-channel6", + "mxs-lradc-channel7", + "mxs-lradc-button0", + "mxs-lradc-button1", +}; + +struct mxs_lradc_of_config { + const int irq_count; + const char * const *irq_name; + const uint32_t *vref_mv; +}; + +#define VREF_MV_BASE 1850 + +static const uint32_t mx23_vref_mv[LRADC_MAX_TOTAL_CHANS] = { + VREF_MV_BASE, /* CH0 */ + VREF_MV_BASE, /* CH1 */ + VREF_MV_BASE, /* CH2 */ + VREF_MV_BASE, /* CH3 */ + VREF_MV_BASE, /* CH4 */ + VREF_MV_BASE, /* CH5 */ + VREF_MV_BASE * 2, /* CH6 VDDIO */ + VREF_MV_BASE * 4, /* CH7 VBATT */ + VREF_MV_BASE, /* CH8 Temp sense 0 */ + VREF_MV_BASE, /* CH9 Temp sense 1 */ + VREF_MV_BASE, /* CH10 */ + VREF_MV_BASE, /* CH11 */ + VREF_MV_BASE, /* CH12 USB_DP */ + VREF_MV_BASE, /* CH13 USB_DN */ + VREF_MV_BASE, /* CH14 VBG */ + VREF_MV_BASE * 4, /* CH15 VDD5V */ +}; + +static const uint32_t mx28_vref_mv[LRADC_MAX_TOTAL_CHANS] = { + VREF_MV_BASE, /* CH0 */ + VREF_MV_BASE, /* CH1 */ + VREF_MV_BASE, /* CH2 */ + VREF_MV_BASE, /* CH3 */ + VREF_MV_BASE, /* CH4 */ + VREF_MV_BASE, /* CH5 */ + VREF_MV_BASE, /* CH6 */ + VREF_MV_BASE * 4, /* CH7 VBATT */ + VREF_MV_BASE, /* CH8 Temp sense 0 */ + VREF_MV_BASE, /* CH9 Temp sense 1 */ + VREF_MV_BASE * 2, /* CH10 VDDIO */ + VREF_MV_BASE, /* CH11 VTH */ + VREF_MV_BASE * 2, /* CH12 VDDA */ + VREF_MV_BASE, /* CH13 VDDD */ + VREF_MV_BASE, /* CH14 VBG */ + VREF_MV_BASE * 4, /* CH15 VDD5V */ +}; + +static const struct mxs_lradc_of_config mxs_lradc_of_config[] = { + [IMX23_LRADC] = { + .irq_count = ARRAY_SIZE(mx23_lradc_irq_names), + .irq_name = mx23_lradc_irq_names, + .vref_mv = mx23_vref_mv, + }, + [IMX28_LRADC] = { + .irq_count = ARRAY_SIZE(mx28_lradc_irq_names), + .irq_name = mx28_lradc_irq_names, + .vref_mv = mx28_vref_mv, + }, +}; + +enum mxs_lradc_ts { + MXS_LRADC_TOUCHSCREEN_NONE = 0, + MXS_LRADC_TOUCHSCREEN_4WIRE, + MXS_LRADC_TOUCHSCREEN_5WIRE, +}; + +/* + * Touchscreen handling + */ +enum lradc_ts_plate { + LRADC_TOUCH = 0, + LRADC_SAMPLE_X, + LRADC_SAMPLE_Y, + LRADC_SAMPLE_PRESSURE, + LRADC_SAMPLE_VALID, +}; + +enum mxs_lradc_divbytwo { + MXS_LRADC_DIV_DISABLED = 0, + MXS_LRADC_DIV_ENABLED, +}; + +struct mxs_lradc_scale { + unsigned int integer; + unsigned int nano; +}; + +struct mxs_lradc { + struct device *dev; + void __iomem *base; + int irq[13]; + + struct clk *clk; + + uint32_t *buffer; + struct iio_trigger *trig; + + struct mutex lock; + + struct completion completion; + + const uint32_t *vref_mv; + struct mxs_lradc_scale scale_avail[LRADC_MAX_TOTAL_CHANS][2]; + unsigned long is_divided; + + /* + * Touchscreen LRADC channels receives a private slot in the CTRL4 + * register, the slot #7. Therefore only 7 slots instead of 8 in the + * CTRL4 register can be mapped to LRADC channels when using the + * touchscreen. + * + * Furthermore, certain LRADC channels are shared between touchscreen + * and/or touch-buttons and generic LRADC block. Therefore when using + * either of these, these channels are not available for the regular + * sampling. The shared channels are as follows: + * + * CH0 -- Touch button #0 + * CH1 -- Touch button #1 + * CH2 -- Touch screen XPUL + * CH3 -- Touch screen YPLL + * CH4 -- Touch screen XNUL + * CH5 -- Touch screen YNLR + * CH6 -- Touch screen WIPER (5-wire only) + * + * The bitfields below represents which parts of the LRADC block are + * switched into special mode of operation. These channels can not + * be sampled as regular LRADC channels. The driver will refuse any + * attempt to sample these channels. + */ +#define CHAN_MASK_TOUCHBUTTON (0x3 << 0) +#define CHAN_MASK_TOUCHSCREEN_4WIRE (0xf << 2) +#define CHAN_MASK_TOUCHSCREEN_5WIRE (0x1f << 2) + enum mxs_lradc_ts use_touchscreen; + bool use_touchbutton; + + struct input_dev *ts_input; + + enum mxs_lradc_id soc; + enum lradc_ts_plate cur_plate; /* statemachine */ + bool ts_valid; + unsigned ts_x_pos; + unsigned ts_y_pos; + unsigned ts_pressure; + + /* handle touchscreen's physical behaviour */ + /* samples per coordinate */ + unsigned over_sample_cnt; + /* time clocks between samples */ + unsigned over_sample_delay; + /* time in clocks to wait after the plates where switched */ + unsigned settling_delay; +}; + +#define LRADC_CTRL0 0x00 +# define LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE (1 << 23) +# define LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE (1 << 22) +# define LRADC_CTRL0_MX28_YNNSW /* YM */ (1 << 21) +# define LRADC_CTRL0_MX28_YPNSW /* YP */ (1 << 20) +# define LRADC_CTRL0_MX28_YPPSW /* YP */ (1 << 19) +# define LRADC_CTRL0_MX28_XNNSW /* XM */ (1 << 18) +# define LRADC_CTRL0_MX28_XNPSW /* XM */ (1 << 17) +# define LRADC_CTRL0_MX28_XPPSW /* XP */ (1 << 16) + +# define LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE (1 << 20) +# define LRADC_CTRL0_MX23_YM (1 << 19) +# define LRADC_CTRL0_MX23_XM (1 << 18) +# define LRADC_CTRL0_MX23_YP (1 << 17) +# define LRADC_CTRL0_MX23_XP (1 << 16) + +# define LRADC_CTRL0_MX28_PLATE_MASK \ + (LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE | \ + LRADC_CTRL0_MX28_YNNSW | LRADC_CTRL0_MX28_YPNSW | \ + LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW | \ + LRADC_CTRL0_MX28_XNPSW | LRADC_CTRL0_MX28_XPPSW) + +# define LRADC_CTRL0_MX23_PLATE_MASK \ + (LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE | \ + LRADC_CTRL0_MX23_YM | LRADC_CTRL0_MX23_XM | \ + LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_XP) + +#define LRADC_CTRL1 0x10 +#define LRADC_CTRL1_TOUCH_DETECT_IRQ_EN (1 << 24) +#define LRADC_CTRL1_LRADC_IRQ_EN(n) (1 << ((n) + 16)) +#define LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK (0x1fff << 16) +#define LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK (0x01ff << 16) +#define LRADC_CTRL1_LRADC_IRQ_EN_OFFSET 16 +#define LRADC_CTRL1_TOUCH_DETECT_IRQ (1 << 8) +#define LRADC_CTRL1_LRADC_IRQ(n) (1 << (n)) +#define LRADC_CTRL1_MX28_LRADC_IRQ_MASK 0x1fff +#define LRADC_CTRL1_MX23_LRADC_IRQ_MASK 0x01ff +#define LRADC_CTRL1_LRADC_IRQ_OFFSET 0 + +#define LRADC_CTRL2 0x20 +#define LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET 24 +#define LRADC_CTRL2_TEMPSENSE_PWD (1 << 15) + +#define LRADC_STATUS 0x40 +#define LRADC_STATUS_TOUCH_DETECT_RAW (1 << 0) + +#define LRADC_CH(n) (0x50 + (0x10 * (n))) +#define LRADC_CH_ACCUMULATE (1 << 29) +#define LRADC_CH_NUM_SAMPLES_MASK (0x1f << 24) +#define LRADC_CH_NUM_SAMPLES_OFFSET 24 +#define LRADC_CH_NUM_SAMPLES(x) \ + ((x) << LRADC_CH_NUM_SAMPLES_OFFSET) +#define LRADC_CH_VALUE_MASK 0x3ffff +#define LRADC_CH_VALUE_OFFSET 0 + +#define LRADC_DELAY(n) (0xd0 + (0x10 * (n))) +#define LRADC_DELAY_TRIGGER_LRADCS_MASK (0xff << 24) +#define LRADC_DELAY_TRIGGER_LRADCS_OFFSET 24 +#define LRADC_DELAY_TRIGGER(x) \ + (((x) << LRADC_DELAY_TRIGGER_LRADCS_OFFSET) & \ + LRADC_DELAY_TRIGGER_LRADCS_MASK) +#define LRADC_DELAY_KICK (1 << 20) +#define LRADC_DELAY_TRIGGER_DELAYS_MASK (0xf << 16) +#define LRADC_DELAY_TRIGGER_DELAYS_OFFSET 16 +#define LRADC_DELAY_TRIGGER_DELAYS(x) \ + (((x) << LRADC_DELAY_TRIGGER_DELAYS_OFFSET) & \ + LRADC_DELAY_TRIGGER_DELAYS_MASK) +#define LRADC_DELAY_LOOP_COUNT_MASK (0x1f << 11) +#define LRADC_DELAY_LOOP_COUNT_OFFSET 11 +#define LRADC_DELAY_LOOP(x) \ + (((x) << LRADC_DELAY_LOOP_COUNT_OFFSET) & \ + LRADC_DELAY_LOOP_COUNT_MASK) +#define LRADC_DELAY_DELAY_MASK 0x7ff +#define LRADC_DELAY_DELAY_OFFSET 0 +#define LRADC_DELAY_DELAY(x) \ + (((x) << LRADC_DELAY_DELAY_OFFSET) & \ + LRADC_DELAY_DELAY_MASK) + +#define LRADC_CTRL4 0x140 +#define LRADC_CTRL4_LRADCSELECT_MASK(n) (0xf << ((n) * 4)) +#define LRADC_CTRL4_LRADCSELECT_OFFSET(n) ((n) * 4) + +#define LRADC_RESOLUTION 12 +#define LRADC_SINGLE_SAMPLE_MASK ((1 << LRADC_RESOLUTION) - 1) + +static void mxs_lradc_reg_set(struct mxs_lradc *lradc, u32 val, u32 reg) +{ + writel(val, lradc->base + reg + STMP_OFFSET_REG_SET); +} + +static void mxs_lradc_reg_clear(struct mxs_lradc *lradc, u32 val, u32 reg) +{ + writel(val, lradc->base + reg + STMP_OFFSET_REG_CLR); +} + +static void mxs_lradc_reg_wrt(struct mxs_lradc *lradc, u32 val, u32 reg) +{ + writel(val, lradc->base + reg); +} + +static u32 mxs_lradc_plate_mask(struct mxs_lradc *lradc) +{ + if (lradc->soc == IMX23_LRADC) + return LRADC_CTRL0_MX23_PLATE_MASK; + else + return LRADC_CTRL0_MX28_PLATE_MASK; +} + +static u32 mxs_lradc_irq_en_mask(struct mxs_lradc *lradc) +{ + if (lradc->soc == IMX23_LRADC) + return LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK; + else + return LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK; +} + +static u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc) +{ + if (lradc->soc == IMX23_LRADC) + return LRADC_CTRL1_MX23_LRADC_IRQ_MASK; + else + return LRADC_CTRL1_MX28_LRADC_IRQ_MASK; +} + +static u32 mxs_lradc_touch_detect_bit(struct mxs_lradc *lradc) +{ + if (lradc->soc == IMX23_LRADC) + return LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE; + else + return LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE; +} + +static u32 mxs_lradc_drive_x_plate(struct mxs_lradc *lradc) +{ + if (lradc->soc == IMX23_LRADC) + return LRADC_CTRL0_MX23_XP | LRADC_CTRL0_MX23_XM; + else + return LRADC_CTRL0_MX28_XPPSW | LRADC_CTRL0_MX28_XNNSW; +} + +static u32 mxs_lradc_drive_y_plate(struct mxs_lradc *lradc) +{ + if (lradc->soc == IMX23_LRADC) + return LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_YM; + else + return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_YNNSW; +} + +static u32 mxs_lradc_drive_pressure(struct mxs_lradc *lradc) +{ + if (lradc->soc == IMX23_LRADC) + return LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_XM; + else + return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW; +} + +static bool mxs_lradc_check_touch_event(struct mxs_lradc *lradc) +{ + return !!(readl(lradc->base + LRADC_STATUS) & + LRADC_STATUS_TOUCH_DETECT_RAW); +} + +static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch) +{ + /* + * prepare for oversampling conversion + * + * from the datasheet: + * "The ACCUMULATE bit in the appropriate channel register + * HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0; + * otherwise, the IRQs will not fire." + */ + mxs_lradc_reg_wrt(lradc, LRADC_CH_ACCUMULATE | + LRADC_CH_NUM_SAMPLES(lradc->over_sample_cnt - 1), + LRADC_CH(ch)); + + /* from the datasheet: + * "Software must clear this register in preparation for a + * multi-cycle accumulation. + */ + mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch)); + + /* prepare the delay/loop unit according to the oversampling count */ + mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch) | + LRADC_DELAY_TRIGGER_DELAYS(0) | + LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) | + LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), + LRADC_DELAY(3)); + + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) | + LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) | + LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); + + /* wake us again, when the complete conversion is done */ + mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch), LRADC_CTRL1); + /* + * after changing the touchscreen plates setting + * the signals need some initial time to settle. Start the + * SoC's delay unit and start the conversion later + * and automatically. + */ + mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */ + LRADC_DELAY_TRIGGER_DELAYS(1 << 3) | /* trigger DELAY unit#3 */ + LRADC_DELAY_KICK | + LRADC_DELAY_DELAY(lradc->settling_delay), + LRADC_DELAY(2)); +} + +/* + * Pressure detection is special: + * We want to do both required measurements for the pressure detection in + * one turn. Use the hardware features to chain both conversions and let the + * hardware report one interrupt if both conversions are done + */ +static void mxs_lradc_setup_ts_pressure(struct mxs_lradc *lradc, unsigned ch1, + unsigned ch2) +{ + u32 reg; + + /* + * prepare for oversampling conversion + * + * from the datasheet: + * "The ACCUMULATE bit in the appropriate channel register + * HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0; + * otherwise, the IRQs will not fire." + */ + reg = LRADC_CH_ACCUMULATE | + LRADC_CH_NUM_SAMPLES(lradc->over_sample_cnt - 1); + mxs_lradc_reg_wrt(lradc, reg, LRADC_CH(ch1)); + mxs_lradc_reg_wrt(lradc, reg, LRADC_CH(ch2)); + + /* from the datasheet: + * "Software must clear this register in preparation for a + * multi-cycle accumulation. + */ + mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch1)); + mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch2)); + + /* prepare the delay/loop unit according to the oversampling count */ + mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch1) | + LRADC_DELAY_TRIGGER(1 << ch2) | /* start both channels */ + LRADC_DELAY_TRIGGER_DELAYS(0) | + LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) | + LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), + LRADC_DELAY(3)); + + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) | + LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) | + LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); + + /* wake us again, when the conversions are done */ + mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch2), LRADC_CTRL1); + /* + * after changing the touchscreen plates setting + * the signals need some initial time to settle. Start the + * SoC's delay unit and start the conversion later + * and automatically. + */ + mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */ + LRADC_DELAY_TRIGGER_DELAYS(1 << 3) | /* trigger DELAY unit#3 */ + LRADC_DELAY_KICK | + LRADC_DELAY_DELAY(lradc->settling_delay), LRADC_DELAY(2)); +} + +static unsigned mxs_lradc_read_raw_channel(struct mxs_lradc *lradc, + unsigned channel) +{ + u32 reg; + unsigned num_samples, val; + + reg = readl(lradc->base + LRADC_CH(channel)); + if (reg & LRADC_CH_ACCUMULATE) + num_samples = lradc->over_sample_cnt; + else + num_samples = 1; + + val = (reg & LRADC_CH_VALUE_MASK) >> LRADC_CH_VALUE_OFFSET; + return val / num_samples; +} + +static unsigned mxs_lradc_read_ts_pressure(struct mxs_lradc *lradc, + unsigned ch1, unsigned ch2) +{ + u32 reg, mask; + unsigned pressure, m1, m2; + + mask = LRADC_CTRL1_LRADC_IRQ(ch1) | LRADC_CTRL1_LRADC_IRQ(ch2); + reg = readl(lradc->base + LRADC_CTRL1) & mask; + + while (reg != mask) { + reg = readl(lradc->base + LRADC_CTRL1) & mask; + dev_dbg(lradc->dev, "One channel is still busy: %X\n", reg); + } + + m1 = mxs_lradc_read_raw_channel(lradc, ch1); + m2 = mxs_lradc_read_raw_channel(lradc, ch2); + + if (m2 == 0) { + dev_warn(lradc->dev, "Cannot calculate pressure\n"); + return 1 << (LRADC_RESOLUTION - 1); + } + + /* simply scale the value from 0 ... max ADC resolution */ + pressure = m1; + pressure *= (1 << LRADC_RESOLUTION); + pressure /= m2; + + dev_dbg(lradc->dev, "Pressure = %u\n", pressure); + return pressure; +} + +#define TS_CH_XP 2 +#define TS_CH_YP 3 +#define TS_CH_XM 4 +#define TS_CH_YM 5 + +static int mxs_lradc_read_ts_channel(struct mxs_lradc *lradc) +{ + u32 reg; + int val; + + reg = readl(lradc->base + LRADC_CTRL1); + + /* only channels 3 to 5 are of interest here */ + if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YP)) { + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YP) | + LRADC_CTRL1_LRADC_IRQ(TS_CH_YP), LRADC_CTRL1); + val = mxs_lradc_read_raw_channel(lradc, TS_CH_YP); + } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_XM)) { + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_XM) | + LRADC_CTRL1_LRADC_IRQ(TS_CH_XM), LRADC_CTRL1); + val = mxs_lradc_read_raw_channel(lradc, TS_CH_XM); + } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YM)) { + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YM) | + LRADC_CTRL1_LRADC_IRQ(TS_CH_YM), LRADC_CTRL1); + val = mxs_lradc_read_raw_channel(lradc, TS_CH_YM); + } else { + return -EIO; + } + + mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); + mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); + + return val; +} + +/* + * YP(open)--+-------------+ + * | |--+ + * | | | + * YM(-)--+-------------+ | + * +--------------+ + * | | + * XP(weak+) XM(open) + * + * "weak+" means 200k Ohm VDDIO + * (-) means GND + */ +static void mxs_lradc_setup_touch_detection(struct mxs_lradc *lradc) +{ + /* + * In order to detect a touch event the 'touch detect enable' bit + * enables: + * - a weak pullup to the X+ connector + * - a strong ground at the Y- connector + */ + mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); + mxs_lradc_reg_set(lradc, mxs_lradc_touch_detect_bit(lradc), + LRADC_CTRL0); +} + +/* + * YP(meas)--+-------------+ + * | |--+ + * | | | + * YM(open)--+-------------+ | + * +--------------+ + * | | + * XP(+) XM(-) + * + * (+) means here 1.85 V + * (-) means here GND + */ +static void mxs_lradc_prepare_x_pos(struct mxs_lradc *lradc) +{ + mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); + mxs_lradc_reg_set(lradc, mxs_lradc_drive_x_plate(lradc), LRADC_CTRL0); + + lradc->cur_plate = LRADC_SAMPLE_X; + mxs_lradc_setup_ts_channel(lradc, TS_CH_YP); +} + +/* + * YP(+)--+-------------+ + * | |--+ + * | | | + * YM(-)--+-------------+ | + * +--------------+ + * | | + * XP(open) XM(meas) + * + * (+) means here 1.85 V + * (-) means here GND + */ +static void mxs_lradc_prepare_y_pos(struct mxs_lradc *lradc) +{ + mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); + mxs_lradc_reg_set(lradc, mxs_lradc_drive_y_plate(lradc), LRADC_CTRL0); + + lradc->cur_plate = LRADC_SAMPLE_Y; + mxs_lradc_setup_ts_channel(lradc, TS_CH_XM); +} + +/* + * YP(+)--+-------------+ + * | |--+ + * | | | + * YM(meas)--+-------------+ | + * +--------------+ + * | | + * XP(meas) XM(-) + * + * (+) means here 1.85 V + * (-) means here GND + */ +static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc) +{ + mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); + mxs_lradc_reg_set(lradc, mxs_lradc_drive_pressure(lradc), LRADC_CTRL0); + + lradc->cur_plate = LRADC_SAMPLE_PRESSURE; + mxs_lradc_setup_ts_pressure(lradc, TS_CH_XP, TS_CH_YM); +} + +static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc) +{ + mxs_lradc_setup_touch_detection(lradc); + + lradc->cur_plate = LRADC_TOUCH; + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ | + LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); + mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); +} + +static void mxs_lradc_report_ts_event(struct mxs_lradc *lradc) +{ + input_report_abs(lradc->ts_input, ABS_X, lradc->ts_x_pos); + input_report_abs(lradc->ts_input, ABS_Y, lradc->ts_y_pos); + input_report_abs(lradc->ts_input, ABS_PRESSURE, lradc->ts_pressure); + input_report_key(lradc->ts_input, BTN_TOUCH, 1); + input_sync(lradc->ts_input); +} + +static void mxs_lradc_complete_touch_event(struct mxs_lradc *lradc) +{ + mxs_lradc_setup_touch_detection(lradc); + lradc->cur_plate = LRADC_SAMPLE_VALID; + /* + * start a dummy conversion to burn time to settle the signals + * note: we are not interested in the conversion's value + */ + mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(5)); + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); + mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(5), LRADC_CTRL1); + mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << 5) | + LRADC_DELAY_KICK | LRADC_DELAY_DELAY(10), /* waste 5 ms */ + LRADC_DELAY(2)); +} + +/* + * in order to avoid false measurements, report only samples where + * the surface is still touched after the position measurement + */ +static void mxs_lradc_finish_touch_event(struct mxs_lradc *lradc, bool valid) +{ + /* if it is still touched, report the sample */ + if (valid && mxs_lradc_check_touch_event(lradc)) { + lradc->ts_valid = true; + mxs_lradc_report_ts_event(lradc); + } + + /* if it is even still touched, continue with the next measurement */ + if (mxs_lradc_check_touch_event(lradc)) { + mxs_lradc_prepare_y_pos(lradc); + return; + } + + if (lradc->ts_valid) { + /* signal the release */ + lradc->ts_valid = false; + input_report_key(lradc->ts_input, BTN_TOUCH, 0); + input_sync(lradc->ts_input); + } + + /* if it is released, wait for the next touch via IRQ */ + lradc->cur_plate = LRADC_TOUCH; + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1); + mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); +} + +/* touchscreen's state machine */ +static void mxs_lradc_handle_touch(struct mxs_lradc *lradc) +{ + int val; + + switch (lradc->cur_plate) { + case LRADC_TOUCH: + /* + * start with the Y-pos, because it uses nearly the same plate + * settings like the touch detection + */ + if (mxs_lradc_check_touch_event(lradc)) { + mxs_lradc_reg_clear(lradc, + LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, + LRADC_CTRL1); + mxs_lradc_prepare_y_pos(lradc); + } + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, + LRADC_CTRL1); + return; + + case LRADC_SAMPLE_Y: + val = mxs_lradc_read_ts_channel(lradc); + if (val < 0) { + mxs_lradc_enable_touch_detection(lradc); /* re-start */ + return; + } + lradc->ts_y_pos = val; + mxs_lradc_prepare_x_pos(lradc); + return; + + case LRADC_SAMPLE_X: + val = mxs_lradc_read_ts_channel(lradc); + if (val < 0) { + mxs_lradc_enable_touch_detection(lradc); /* re-start */ + return; + } + lradc->ts_x_pos = val; + mxs_lradc_prepare_pressure(lradc); + return; + + case LRADC_SAMPLE_PRESSURE: + lradc->ts_pressure = + mxs_lradc_read_ts_pressure(lradc, TS_CH_XP, TS_CH_YM); + mxs_lradc_complete_touch_event(lradc); + return; + + case LRADC_SAMPLE_VALID: + val = mxs_lradc_read_ts_channel(lradc); /* ignore the value */ + mxs_lradc_finish_touch_event(lradc, 1); + break; + } +} + +/* + * Raw I/O operations + */ +static int mxs_lradc_read_single(struct iio_dev *iio_dev, int chan, int *val) +{ + struct mxs_lradc *lradc = iio_priv(iio_dev); + int ret; + + /* + * See if there is no buffered operation in progess. If there is, simply + * bail out. This can be improved to support both buffered and raw IO at + * the same time, yet the code becomes horribly complicated. Therefore I + * applied KISS principle here. + */ + ret = mutex_trylock(&lradc->lock); + if (!ret) + return -EBUSY; + + reinit_completion(&lradc->completion); + + /* + * No buffered operation in progress, map the channel and trigger it. + * Virtual channel 0 is always used here as the others are always not + * used if doing raw sampling. + */ + if (lradc->soc == IMX28_LRADC) + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, + LRADC_CTRL1); + mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); + + /* Enable / disable the divider per requirement */ + if (test_bit(chan, &lradc->is_divided)) + mxs_lradc_reg_set(lradc, 1 << LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET, + LRADC_CTRL2); + else + mxs_lradc_reg_clear(lradc, + 1 << LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET, LRADC_CTRL2); + + /* Clean the slot's previous content, then set new one. */ + mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(0), + LRADC_CTRL4); + mxs_lradc_reg_set(lradc, chan, LRADC_CTRL4); + + mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(0)); + + /* Enable the IRQ and start sampling the channel. */ + mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), LRADC_CTRL1); + mxs_lradc_reg_set(lradc, 1 << 0, LRADC_CTRL0); + + /* Wait for completion on the channel, 1 second max. */ + ret = wait_for_completion_killable_timeout(&lradc->completion, HZ); + if (!ret) + ret = -ETIMEDOUT; + if (ret < 0) + goto err; + + /* Read the data. */ + *val = readl(lradc->base + LRADC_CH(0)) & LRADC_CH_VALUE_MASK; + ret = IIO_VAL_INT; + +err: + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), LRADC_CTRL1); + + mutex_unlock(&lradc->lock); + + return ret; +} + +static int mxs_lradc_read_temp(struct iio_dev *iio_dev, int *val) +{ + int ret, min, max; + + ret = mxs_lradc_read_single(iio_dev, 8, &min); + if (ret != IIO_VAL_INT) + return ret; + + ret = mxs_lradc_read_single(iio_dev, 9, &max); + if (ret != IIO_VAL_INT) + return ret; + + *val = max - min; + + return IIO_VAL_INT; +} + +static int mxs_lradc_read_raw(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long m) +{ + struct mxs_lradc *lradc = iio_priv(iio_dev); + + switch (m) { + case IIO_CHAN_INFO_RAW: + if (chan->type == IIO_TEMP) + return mxs_lradc_read_temp(iio_dev, val); + + return mxs_lradc_read_single(iio_dev, chan->channel, val); + + case IIO_CHAN_INFO_SCALE: + if (chan->type == IIO_TEMP) { + /* From the datasheet, we have to multiply by 1.012 and + * divide by 4 + */ + *val = 0; + *val2 = 253000; + return IIO_VAL_INT_PLUS_MICRO; + } + + *val = lradc->vref_mv[chan->channel]; + *val2 = chan->scan_type.realbits - + test_bit(chan->channel, &lradc->is_divided); + return IIO_VAL_FRACTIONAL_LOG2; + + case IIO_CHAN_INFO_OFFSET: + if (chan->type == IIO_TEMP) { + /* The calculated value from the ADC is in Kelvin, we + * want Celsius for hwmon so the offset is + * -272.15 * scale + */ + *val = -1075; + *val2 = 691699; + + return IIO_VAL_INT_PLUS_MICRO; + } + + return -EINVAL; + + default: + break; + } + + return -EINVAL; +} + +static int mxs_lradc_write_raw(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, + int val, int val2, long m) +{ + struct mxs_lradc *lradc = iio_priv(iio_dev); + struct mxs_lradc_scale *scale_avail = + lradc->scale_avail[chan->channel]; + int ret; + + ret = mutex_trylock(&lradc->lock); + if (!ret) + return -EBUSY; + + switch (m) { + case IIO_CHAN_INFO_SCALE: + ret = -EINVAL; + if (val == scale_avail[MXS_LRADC_DIV_DISABLED].integer && + val2 == scale_avail[MXS_LRADC_DIV_DISABLED].nano) { + /* divider by two disabled */ + clear_bit(chan->channel, &lradc->is_divided); + ret = 0; + } else if (val == scale_avail[MXS_LRADC_DIV_ENABLED].integer && + val2 == scale_avail[MXS_LRADC_DIV_ENABLED].nano) { + /* divider by two enabled */ + set_bit(chan->channel, &lradc->is_divided); + ret = 0; + } + + break; + default: + ret = -EINVAL; + break; + } + + mutex_unlock(&lradc->lock); + + return ret; +} + +static int mxs_lradc_write_raw_get_fmt(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, + long m) +{ + return IIO_VAL_INT_PLUS_NANO; +} + +static ssize_t mxs_lradc_show_scale_available_ch(struct device *dev, + struct device_attribute *attr, + char *buf, + int ch) +{ + struct iio_dev *iio = dev_to_iio_dev(dev); + struct mxs_lradc *lradc = iio_priv(iio); + int i, len = 0; + + for (i = 0; i < ARRAY_SIZE(lradc->scale_avail[ch]); i++) + len += sprintf(buf + len, "%d.%09u ", + lradc->scale_avail[ch][i].integer, + lradc->scale_avail[ch][i].nano); + + len += sprintf(buf + len, "\n"); + + return len; +} + +static ssize_t mxs_lradc_show_scale_available(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev_attr *iio_attr = to_iio_dev_attr(attr); + + return mxs_lradc_show_scale_available_ch(dev, attr, buf, + iio_attr->address); +} + +#define SHOW_SCALE_AVAILABLE_ATTR(ch) \ +static IIO_DEVICE_ATTR(in_voltage##ch##_scale_available, S_IRUGO, \ + mxs_lradc_show_scale_available, NULL, ch) + +SHOW_SCALE_AVAILABLE_ATTR(0); +SHOW_SCALE_AVAILABLE_ATTR(1); +SHOW_SCALE_AVAILABLE_ATTR(2); +SHOW_SCALE_AVAILABLE_ATTR(3); +SHOW_SCALE_AVAILABLE_ATTR(4); +SHOW_SCALE_AVAILABLE_ATTR(5); +SHOW_SCALE_AVAILABLE_ATTR(6); +SHOW_SCALE_AVAILABLE_ATTR(7); +SHOW_SCALE_AVAILABLE_ATTR(10); +SHOW_SCALE_AVAILABLE_ATTR(11); +SHOW_SCALE_AVAILABLE_ATTR(12); +SHOW_SCALE_AVAILABLE_ATTR(13); +SHOW_SCALE_AVAILABLE_ATTR(14); +SHOW_SCALE_AVAILABLE_ATTR(15); + +static struct attribute *mxs_lradc_attributes[] = { + &iio_dev_attr_in_voltage0_scale_available.dev_attr.attr, + &iio_dev_attr_in_voltage1_scale_available.dev_attr.attr, + &iio_dev_attr_in_voltage2_scale_available.dev_attr.attr, + &iio_dev_attr_in_voltage3_scale_available.dev_attr.attr, + &iio_dev_attr_in_voltage4_scale_available.dev_attr.attr, + &iio_dev_attr_in_voltage5_scale_available.dev_attr.attr, + &iio_dev_attr_in_voltage6_scale_available.dev_attr.attr, + &iio_dev_attr_in_voltage7_scale_available.dev_attr.attr, + &iio_dev_attr_in_voltage10_scale_available.dev_attr.attr, + &iio_dev_attr_in_voltage11_scale_available.dev_attr.attr, + &iio_dev_attr_in_voltage12_scale_available.dev_attr.attr, + &iio_dev_attr_in_voltage13_scale_available.dev_attr.attr, + &iio_dev_attr_in_voltage14_scale_available.dev_attr.attr, + &iio_dev_attr_in_voltage15_scale_available.dev_attr.attr, + NULL +}; + +static const struct attribute_group mxs_lradc_attribute_group = { + .attrs = mxs_lradc_attributes, +}; + +static const struct iio_info mxs_lradc_iio_info = { + .driver_module = THIS_MODULE, + .read_raw = mxs_lradc_read_raw, + .write_raw = mxs_lradc_write_raw, + .write_raw_get_fmt = mxs_lradc_write_raw_get_fmt, + .attrs = &mxs_lradc_attribute_group, +}; + +static int mxs_lradc_ts_open(struct input_dev *dev) +{ + struct mxs_lradc *lradc = input_get_drvdata(dev); + + /* Enable the touch-detect circuitry. */ + mxs_lradc_enable_touch_detection(lradc); + + return 0; +} + +static void mxs_lradc_disable_ts(struct mxs_lradc *lradc) +{ + /* stop all interrupts from firing */ + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN | + LRADC_CTRL1_LRADC_IRQ_EN(2) | LRADC_CTRL1_LRADC_IRQ_EN(3) | + LRADC_CTRL1_LRADC_IRQ_EN(4) | LRADC_CTRL1_LRADC_IRQ_EN(5), + LRADC_CTRL1); + + /* Power-down touchscreen touch-detect circuitry. */ + mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); +} + +static void mxs_lradc_ts_close(struct input_dev *dev) +{ + struct mxs_lradc *lradc = input_get_drvdata(dev); + + mxs_lradc_disable_ts(lradc); +} + +static int mxs_lradc_ts_register(struct mxs_lradc *lradc) +{ + struct input_dev *input; + struct device *dev = lradc->dev; + int ret; + + if (!lradc->use_touchscreen) + return 0; + + input = input_allocate_device(); + if (!input) + return -ENOMEM; + + input->name = DRIVER_NAME; + input->id.bustype = BUS_HOST; + input->dev.parent = dev; + input->open = mxs_lradc_ts_open; + input->close = mxs_lradc_ts_close; + + __set_bit(EV_ABS, input->evbit); + __set_bit(EV_KEY, input->evbit); + __set_bit(BTN_TOUCH, input->keybit); + input_set_abs_params(input, ABS_X, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0); + input_set_abs_params(input, ABS_Y, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0); + input_set_abs_params(input, ABS_PRESSURE, 0, LRADC_SINGLE_SAMPLE_MASK, + 0, 0); + + lradc->ts_input = input; + input_set_drvdata(input, lradc); + ret = input_register_device(input); + if (ret) + input_free_device(lradc->ts_input); + + return ret; +} + +static void mxs_lradc_ts_unregister(struct mxs_lradc *lradc) +{ + if (!lradc->use_touchscreen) + return; + + mxs_lradc_disable_ts(lradc); + input_unregister_device(lradc->ts_input); +} + +/* + * IRQ Handling + */ +static irqreturn_t mxs_lradc_handle_irq(int irq, void *data) +{ + struct iio_dev *iio = data; + struct mxs_lradc *lradc = iio_priv(iio); + unsigned long reg = readl(lradc->base + LRADC_CTRL1); + const uint32_t ts_irq_mask = + LRADC_CTRL1_TOUCH_DETECT_IRQ | + LRADC_CTRL1_LRADC_IRQ(2) | + LRADC_CTRL1_LRADC_IRQ(3) | + LRADC_CTRL1_LRADC_IRQ(4) | + LRADC_CTRL1_LRADC_IRQ(5); + + if (!(reg & mxs_lradc_irq_mask(lradc))) + return IRQ_NONE; + + if (lradc->use_touchscreen && (reg & ts_irq_mask)) + mxs_lradc_handle_touch(lradc); + + if (iio_buffer_enabled(iio)) + iio_trigger_poll(iio->trig, iio_get_time_ns()); + else if (reg & LRADC_CTRL1_LRADC_IRQ(0)) + complete(&lradc->completion); + + mxs_lradc_reg_clear(lradc, reg & mxs_lradc_irq_mask(lradc), + LRADC_CTRL1); + + return IRQ_HANDLED; +} + +/* + * Trigger handling + */ +static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *iio = pf->indio_dev; + struct mxs_lradc *lradc = iio_priv(iio); + const uint32_t chan_value = LRADC_CH_ACCUMULATE | + ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); + unsigned int i, j = 0; + + for_each_set_bit(i, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) { + lradc->buffer[j] = readl(lradc->base + LRADC_CH(j)); + mxs_lradc_reg_wrt(lradc, chan_value, LRADC_CH(j)); + lradc->buffer[j] &= LRADC_CH_VALUE_MASK; + lradc->buffer[j] /= LRADC_DELAY_TIMER_LOOP; + j++; + } + + iio_push_to_buffers_with_timestamp(iio, lradc->buffer, pf->timestamp); + + iio_trigger_notify_done(iio->trig); + + return IRQ_HANDLED; +} + +static int mxs_lradc_configure_trigger(struct iio_trigger *trig, bool state) +{ + struct iio_dev *iio = iio_trigger_get_drvdata(trig); + struct mxs_lradc *lradc = iio_priv(iio); + const uint32_t st = state ? STMP_OFFSET_REG_SET : STMP_OFFSET_REG_CLR; + + mxs_lradc_reg_wrt(lradc, LRADC_DELAY_KICK, LRADC_DELAY(0) + st); + + return 0; +} + +static const struct iio_trigger_ops mxs_lradc_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = &mxs_lradc_configure_trigger, +}; + +static int mxs_lradc_trigger_init(struct iio_dev *iio) +{ + int ret; + struct iio_trigger *trig; + struct mxs_lradc *lradc = iio_priv(iio); + + trig = iio_trigger_alloc("%s-dev%i", iio->name, iio->id); + if (trig == NULL) + return -ENOMEM; + + trig->dev.parent = lradc->dev; + iio_trigger_set_drvdata(trig, iio); + trig->ops = &mxs_lradc_trigger_ops; + + ret = iio_trigger_register(trig); + if (ret) { + iio_trigger_free(trig); + return ret; + } + + lradc->trig = trig; + + return 0; +} + +static void mxs_lradc_trigger_remove(struct iio_dev *iio) +{ + struct mxs_lradc *lradc = iio_priv(iio); + + iio_trigger_unregister(lradc->trig); + iio_trigger_free(lradc->trig); +} + +static int mxs_lradc_buffer_preenable(struct iio_dev *iio) +{ + struct mxs_lradc *lradc = iio_priv(iio); + int ret = 0, chan, ofs = 0; + unsigned long enable = 0; + uint32_t ctrl4_set = 0; + uint32_t ctrl4_clr = 0; + uint32_t ctrl1_irq = 0; + const uint32_t chan_value = LRADC_CH_ACCUMULATE | + ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); + const int len = bitmap_weight(iio->active_scan_mask, + LRADC_MAX_TOTAL_CHANS); + + if (!len) + return -EINVAL; + + /* + * Lock the driver so raw access can not be done during buffered + * operation. This simplifies the code a lot. + */ + ret = mutex_trylock(&lradc->lock); + if (!ret) + return -EBUSY; + + lradc->buffer = kmalloc(len * sizeof(*lradc->buffer), GFP_KERNEL); + if (!lradc->buffer) { + ret = -ENOMEM; + goto err_mem; + } + + if (lradc->soc == IMX28_LRADC) + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, + LRADC_CTRL1); + mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); + + for_each_set_bit(chan, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) { + ctrl4_set |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs); + ctrl4_clr |= LRADC_CTRL4_LRADCSELECT_MASK(ofs); + ctrl1_irq |= LRADC_CTRL1_LRADC_IRQ_EN(ofs); + mxs_lradc_reg_wrt(lradc, chan_value, LRADC_CH(ofs)); + bitmap_set(&enable, ofs, 1); + ofs++; + } + + mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK | + LRADC_DELAY_KICK, LRADC_DELAY(0)); + mxs_lradc_reg_clear(lradc, ctrl4_clr, LRADC_CTRL4); + mxs_lradc_reg_set(lradc, ctrl4_set, LRADC_CTRL4); + mxs_lradc_reg_set(lradc, ctrl1_irq, LRADC_CTRL1); + mxs_lradc_reg_set(lradc, enable << LRADC_DELAY_TRIGGER_LRADCS_OFFSET, + LRADC_DELAY(0)); + + return 0; + +err_mem: + mutex_unlock(&lradc->lock); + return ret; +} + +static int mxs_lradc_buffer_postdisable(struct iio_dev *iio) +{ + struct mxs_lradc *lradc = iio_priv(iio); + + mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK | + LRADC_DELAY_KICK, LRADC_DELAY(0)); + + mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); + if (lradc->soc == IMX28_LRADC) + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, + LRADC_CTRL1); + + kfree(lradc->buffer); + mutex_unlock(&lradc->lock); + + return 0; +} + +static bool mxs_lradc_validate_scan_mask(struct iio_dev *iio, + const unsigned long *mask) +{ + struct mxs_lradc *lradc = iio_priv(iio); + const int map_chans = bitmap_weight(mask, LRADC_MAX_TOTAL_CHANS); + int rsvd_chans = 0; + unsigned long rsvd_mask = 0; + + if (lradc->use_touchbutton) + rsvd_mask |= CHAN_MASK_TOUCHBUTTON; + if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_4WIRE) + rsvd_mask |= CHAN_MASK_TOUCHSCREEN_4WIRE; + if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) + rsvd_mask |= CHAN_MASK_TOUCHSCREEN_5WIRE; + + if (lradc->use_touchbutton) + rsvd_chans++; + if (lradc->use_touchscreen) + rsvd_chans++; + + /* Test for attempts to map channels with special mode of operation. */ + if (bitmap_intersects(mask, &rsvd_mask, LRADC_MAX_TOTAL_CHANS)) + return false; + + /* Test for attempts to map more channels then available slots. */ + if (map_chans + rsvd_chans > LRADC_MAX_MAPPED_CHANS) + return false; + + return true; +} + +static const struct iio_buffer_setup_ops mxs_lradc_buffer_ops = { + .preenable = &mxs_lradc_buffer_preenable, + .postenable = &iio_triggered_buffer_postenable, + .predisable = &iio_triggered_buffer_predisable, + .postdisable = &mxs_lradc_buffer_postdisable, + .validate_scan_mask = &mxs_lradc_validate_scan_mask, +}; + +/* + * Driver initialization + */ + +#define MXS_ADC_CHAN(idx, chan_type) { \ + .type = (chan_type), \ + .indexed = 1, \ + .scan_index = (idx), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .channel = (idx), \ + .address = (idx), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = LRADC_RESOLUTION, \ + .storagebits = 32, \ + }, \ +} + +static const struct iio_chan_spec mxs_lradc_chan_spec[] = { + MXS_ADC_CHAN(0, IIO_VOLTAGE), + MXS_ADC_CHAN(1, IIO_VOLTAGE), + MXS_ADC_CHAN(2, IIO_VOLTAGE), + MXS_ADC_CHAN(3, IIO_VOLTAGE), + MXS_ADC_CHAN(4, IIO_VOLTAGE), + MXS_ADC_CHAN(5, IIO_VOLTAGE), + MXS_ADC_CHAN(6, IIO_VOLTAGE), + MXS_ADC_CHAN(7, IIO_VOLTAGE), /* VBATT */ + /* Combined Temperature sensors */ + { + .type = IIO_TEMP, + .indexed = 1, + .scan_index = 8, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_OFFSET) | + BIT(IIO_CHAN_INFO_SCALE), + .channel = 8, + .scan_type = {.sign = 'u', .realbits = 18, .storagebits = 32,}, + }, + MXS_ADC_CHAN(10, IIO_VOLTAGE), /* VDDIO */ + MXS_ADC_CHAN(11, IIO_VOLTAGE), /* VTH */ + MXS_ADC_CHAN(12, IIO_VOLTAGE), /* VDDA */ + MXS_ADC_CHAN(13, IIO_VOLTAGE), /* VDDD */ + MXS_ADC_CHAN(14, IIO_VOLTAGE), /* VBG */ + MXS_ADC_CHAN(15, IIO_VOLTAGE), /* VDD5V */ +}; + +static int mxs_lradc_hw_init(struct mxs_lradc *lradc) +{ + /* The ADC always uses DELAY CHANNEL 0. */ + const uint32_t adc_cfg = + (1 << (LRADC_DELAY_TRIGGER_DELAYS_OFFSET + 0)) | + (LRADC_DELAY_TIMER_PER << LRADC_DELAY_DELAY_OFFSET); + + int ret = stmp_reset_block(lradc->base); + if (ret) + return ret; + + /* Configure DELAY CHANNEL 0 for generic ADC sampling. */ + mxs_lradc_reg_wrt(lradc, adc_cfg, LRADC_DELAY(0)); + + /* Disable remaining DELAY CHANNELs */ + mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(1)); + mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); + mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); + + /* Configure the touchscreen type */ + if (lradc->soc == IMX28_LRADC) { + mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, + LRADC_CTRL0); + + if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) + mxs_lradc_reg_set(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, + LRADC_CTRL0); + } + + /* Start internal temperature sensing. */ + mxs_lradc_reg_wrt(lradc, 0, LRADC_CTRL2); + + return 0; +} + +static void mxs_lradc_hw_stop(struct mxs_lradc *lradc) +{ + int i; + + mxs_lradc_reg_clear(lradc, mxs_lradc_irq_en_mask(lradc), LRADC_CTRL1); + + for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++) + mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(i)); +} + +static const struct of_device_id mxs_lradc_dt_ids[] = { + { .compatible = "fsl,imx23-lradc", .data = (void *)IMX23_LRADC, }, + { .compatible = "fsl,imx28-lradc", .data = (void *)IMX28_LRADC, }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mxs_lradc_dt_ids); + +static int mxs_lradc_probe_touchscreen(struct mxs_lradc *lradc, + struct device_node *lradc_node) +{ + int ret; + u32 ts_wires = 0, adapt; + + ret = of_property_read_u32(lradc_node, "fsl,lradc-touchscreen-wires", + &ts_wires); + if (ret) + return -ENODEV; /* touchscreen feature disabled */ + + switch (ts_wires) { + case 4: + lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_4WIRE; + break; + case 5: + if (lradc->soc == IMX28_LRADC) { + lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_5WIRE; + break; + } + /* fall through an error message for i.MX23 */ + default: + dev_err(lradc->dev, + "Unsupported number of touchscreen wires (%d)\n", + ts_wires); + return -EINVAL; + } + + lradc->over_sample_cnt = 4; + ret = of_property_read_u32(lradc_node, "fsl,ave-ctrl", &adapt); + if (ret == 0) + lradc->over_sample_cnt = adapt; + + lradc->over_sample_delay = 2; + ret = of_property_read_u32(lradc_node, "fsl,ave-delay", &adapt); + if (ret == 0) + lradc->over_sample_delay = adapt; + + lradc->settling_delay = 10; + ret = of_property_read_u32(lradc_node, "fsl,settling", &adapt); + if (ret == 0) + lradc->settling_delay = adapt; + + return 0; +} + +static int mxs_lradc_probe(struct platform_device *pdev) +{ + const struct of_device_id *of_id = + of_match_device(mxs_lradc_dt_ids, &pdev->dev); + const struct mxs_lradc_of_config *of_cfg = + &mxs_lradc_of_config[(enum mxs_lradc_id)of_id->data]; + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + struct mxs_lradc *lradc; + struct iio_dev *iio; + struct resource *iores; + int ret = 0, touch_ret; + int i, s; + uint64_t scale_uv; + + /* Allocate the IIO device. */ + iio = devm_iio_device_alloc(dev, sizeof(*lradc)); + if (!iio) { + dev_err(dev, "Failed to allocate IIO device\n"); + return -ENOMEM; + } + + lradc = iio_priv(iio); + lradc->soc = (enum mxs_lradc_id)of_id->data; + + /* Grab the memory area */ + iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); + lradc->dev = &pdev->dev; + lradc->base = devm_ioremap_resource(dev, iores); + if (IS_ERR(lradc->base)) + return PTR_ERR(lradc->base); + + lradc->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(lradc->clk)) { + dev_err(dev, "Failed to get the delay unit clock\n"); + return PTR_ERR(lradc->clk); + } + ret = clk_prepare_enable(lradc->clk); + if (ret != 0) { + dev_err(dev, "Failed to enable the delay unit clock\n"); + return ret; + } + + touch_ret = mxs_lradc_probe_touchscreen(lradc, node); + + /* Grab all IRQ sources */ + for (i = 0; i < of_cfg->irq_count; i++) { + lradc->irq[i] = platform_get_irq(pdev, i); + if (lradc->irq[i] < 0) + return lradc->irq[i]; + + ret = devm_request_irq(dev, lradc->irq[i], + mxs_lradc_handle_irq, 0, + of_cfg->irq_name[i], iio); + if (ret) + return ret; + } + + lradc->vref_mv = of_cfg->vref_mv; + + platform_set_drvdata(pdev, iio); + + init_completion(&lradc->completion); + mutex_init(&lradc->lock); + + iio->name = pdev->name; + iio->dev.parent = &pdev->dev; + iio->info = &mxs_lradc_iio_info; + iio->modes = INDIO_DIRECT_MODE; + iio->channels = mxs_lradc_chan_spec; + iio->num_channels = ARRAY_SIZE(mxs_lradc_chan_spec); + iio->masklength = LRADC_MAX_TOTAL_CHANS; + + ret = iio_triggered_buffer_setup(iio, &iio_pollfunc_store_time, + &mxs_lradc_trigger_handler, + &mxs_lradc_buffer_ops); + if (ret) + return ret; + + ret = mxs_lradc_trigger_init(iio); + if (ret) + goto err_trig; + + /* Populate available ADC input ranges */ + for (i = 0; i < LRADC_MAX_TOTAL_CHANS; i++) { + for (s = 0; s < ARRAY_SIZE(lradc->scale_avail[i]); s++) { + /* + * [s=0] = optional divider by two disabled (default) + * [s=1] = optional divider by two enabled + * + * The scale is calculated by doing: + * Vref >> (realbits - s) + * which multiplies by two on the second component + * of the array. + */ + scale_uv = ((u64)lradc->vref_mv[i] * 100000000) >> + (LRADC_RESOLUTION - s); + lradc->scale_avail[i][s].nano = + do_div(scale_uv, 100000000) * 10; + lradc->scale_avail[i][s].integer = scale_uv; + } + } + + /* Configure the hardware. */ + ret = mxs_lradc_hw_init(lradc); + if (ret) + goto err_dev; + + /* Register the touchscreen input device. */ + if (touch_ret == 0) { + ret = mxs_lradc_ts_register(lradc); + if (ret) + goto err_ts_register; + } + + /* Register IIO device. */ + ret = iio_device_register(iio); + if (ret) { + dev_err(dev, "Failed to register IIO device\n"); + goto err_ts; + } + + return 0; + +err_ts: + mxs_lradc_ts_unregister(lradc); +err_ts_register: + mxs_lradc_hw_stop(lradc); +err_dev: + mxs_lradc_trigger_remove(iio); +err_trig: + iio_triggered_buffer_cleanup(iio); + return ret; +} + +static int mxs_lradc_remove(struct platform_device *pdev) +{ + struct iio_dev *iio = platform_get_drvdata(pdev); + struct mxs_lradc *lradc = iio_priv(iio); + + iio_device_unregister(iio); + mxs_lradc_ts_unregister(lradc); + mxs_lradc_hw_stop(lradc); + mxs_lradc_trigger_remove(iio); + iio_triggered_buffer_cleanup(iio); + + clk_disable_unprepare(lradc->clk); + return 0; +} + +static struct platform_driver mxs_lradc_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = mxs_lradc_dt_ids, + }, + .probe = mxs_lradc_probe, + .remove = mxs_lradc_remove, +}; + +module_platform_driver(mxs_lradc_driver); + +MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); +MODULE_DESCRIPTION("Freescale i.MX28 LRADC driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c new file mode 100644 index 00000000000..c5492ba5075 --- /dev/null +++ b/drivers/staging/iio/adc/spear_adc.c @@ -0,0 +1,401 @@ +/* + * ST SPEAr ADC driver + * + * Copyright 2012 Stefan Roese <sr@denx.de> + * + * Licensed under the GPL-2. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/completion.h> +#include <linux/of.h> +#include <linux/of_address.h> + +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> + +/* SPEAR registers definitions */ +#define SPEAR600_ADC_SCAN_RATE_LO(x) ((x) & 0xFFFF) +#define SPEAR600_ADC_SCAN_RATE_HI(x) (((x) >> 0x10) & 0xFFFF) +#define SPEAR_ADC_CLK_LOW(x) (((x) & 0xf) << 0) +#define SPEAR_ADC_CLK_HIGH(x) (((x) & 0xf) << 4) + +/* Bit definitions for SPEAR_ADC_STATUS */ +#define SPEAR_ADC_STATUS_START_CONVERSION (1 << 0) +#define SPEAR_ADC_STATUS_CHANNEL_NUM(x) ((x) << 1) +#define SPEAR_ADC_STATUS_ADC_ENABLE (1 << 4) +#define SPEAR_ADC_STATUS_AVG_SAMPLE(x) ((x) << 5) +#define SPEAR_ADC_STATUS_VREF_INTERNAL (1 << 9) + +#define SPEAR_ADC_DATA_MASK 0x03ff +#define SPEAR_ADC_DATA_BITS 10 + +#define SPEAR_ADC_MOD_NAME "spear-adc" + +#define SPEAR_ADC_CHANNEL_NUM 8 + +#define SPEAR_ADC_CLK_MIN 2500000 +#define SPEAR_ADC_CLK_MAX 20000000 + +struct adc_regs_spear3xx { + u32 status; + u32 average; + u32 scan_rate; + u32 clk; /* Not avail for 1340 & 1310 */ + u32 ch_ctrl[SPEAR_ADC_CHANNEL_NUM]; + u32 ch_data[SPEAR_ADC_CHANNEL_NUM]; +}; + +struct chan_data { + u32 lsb; + u32 msb; +}; + +struct adc_regs_spear6xx { + u32 status; + u32 pad[2]; + u32 clk; + u32 ch_ctrl[SPEAR_ADC_CHANNEL_NUM]; + struct chan_data ch_data[SPEAR_ADC_CHANNEL_NUM]; + u32 scan_rate_lo; + u32 scan_rate_hi; + struct chan_data average; +}; + +struct spear_adc_state { + struct device_node *np; + struct adc_regs_spear3xx __iomem *adc_base_spear3xx; + struct adc_regs_spear6xx __iomem *adc_base_spear6xx; + struct clk *clk; + struct completion completion; + u32 current_clk; + u32 sampling_freq; + u32 avg_samples; + u32 vref_external; + u32 value; +}; + +/* + * Functions to access some SPEAr ADC register. Abstracted into + * static inline functions, because of different register offsets + * on different SoC variants (SPEAr300 vs SPEAr600 etc). + */ +static void spear_adc_set_status(struct spear_adc_state *st, u32 val) +{ + __raw_writel(val, &st->adc_base_spear6xx->status); +} + +static void spear_adc_set_clk(struct spear_adc_state *st, u32 val) +{ + u32 clk_high, clk_low, count; + u32 apb_clk = clk_get_rate(st->clk); + + count = (apb_clk + val - 1) / val; + clk_low = count / 2; + clk_high = count - clk_low; + st->current_clk = apb_clk / count; + + __raw_writel(SPEAR_ADC_CLK_LOW(clk_low) | SPEAR_ADC_CLK_HIGH(clk_high), + &st->adc_base_spear6xx->clk); +} + +static void spear_adc_set_ctrl(struct spear_adc_state *st, int n, + u32 val) +{ + __raw_writel(val, &st->adc_base_spear6xx->ch_ctrl[n]); +} + +static u32 spear_adc_get_average(struct spear_adc_state *st) +{ + if (of_device_is_compatible(st->np, "st,spear600-adc")) { + return __raw_readl(&st->adc_base_spear6xx->average.msb) & + SPEAR_ADC_DATA_MASK; + } else { + return __raw_readl(&st->adc_base_spear3xx->average) & + SPEAR_ADC_DATA_MASK; + } +} + +static void spear_adc_set_scanrate(struct spear_adc_state *st, u32 rate) +{ + if (of_device_is_compatible(st->np, "st,spear600-adc")) { + __raw_writel(SPEAR600_ADC_SCAN_RATE_LO(rate), + &st->adc_base_spear6xx->scan_rate_lo); + __raw_writel(SPEAR600_ADC_SCAN_RATE_HI(rate), + &st->adc_base_spear6xx->scan_rate_hi); + } else { + __raw_writel(rate, &st->adc_base_spear3xx->scan_rate); + } +} + +static int spear_adc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + struct spear_adc_state *st = iio_priv(indio_dev); + u32 status; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&indio_dev->mlock); + + status = SPEAR_ADC_STATUS_CHANNEL_NUM(chan->channel) | + SPEAR_ADC_STATUS_AVG_SAMPLE(st->avg_samples) | + SPEAR_ADC_STATUS_START_CONVERSION | + SPEAR_ADC_STATUS_ADC_ENABLE; + if (st->vref_external == 0) + status |= SPEAR_ADC_STATUS_VREF_INTERNAL; + + spear_adc_set_status(st, status); + wait_for_completion(&st->completion); /* set by ISR */ + *val = st->value; + + mutex_unlock(&indio_dev->mlock); + + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + *val = st->vref_external; + *val2 = SPEAR_ADC_DATA_BITS; + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_SAMP_FREQ: + *val = st->current_clk; + return IIO_VAL_INT; + } + + return -EINVAL; +} + +static int spear_adc_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct spear_adc_state *st = iio_priv(indio_dev); + int ret = 0; + + if (mask != IIO_CHAN_INFO_SAMP_FREQ) + return -EINVAL; + + mutex_lock(&indio_dev->mlock); + + if ((val < SPEAR_ADC_CLK_MIN) || + (val > SPEAR_ADC_CLK_MAX) || + (val2 != 0)) { + ret = -EINVAL; + goto out; + } + + spear_adc_set_clk(st, val); + +out: + mutex_unlock(&indio_dev->mlock); + return ret; +} + +#define SPEAR_ADC_CHAN(idx) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ + .channel = idx, \ +} + +static const struct iio_chan_spec spear_adc_iio_channels[] = { + SPEAR_ADC_CHAN(0), + SPEAR_ADC_CHAN(1), + SPEAR_ADC_CHAN(2), + SPEAR_ADC_CHAN(3), + SPEAR_ADC_CHAN(4), + SPEAR_ADC_CHAN(5), + SPEAR_ADC_CHAN(6), + SPEAR_ADC_CHAN(7), +}; + +static irqreturn_t spear_adc_isr(int irq, void *dev_id) +{ + struct spear_adc_state *st = (struct spear_adc_state *)dev_id; + + /* Read value to clear IRQ */ + st->value = spear_adc_get_average(st); + complete(&st->completion); + + return IRQ_HANDLED; +} + +static int spear_adc_configure(struct spear_adc_state *st) +{ + int i; + + /* Reset ADC core */ + spear_adc_set_status(st, 0); + __raw_writel(0, &st->adc_base_spear6xx->clk); + for (i = 0; i < 8; i++) + spear_adc_set_ctrl(st, i, 0); + spear_adc_set_scanrate(st, 0); + + spear_adc_set_clk(st, st->sampling_freq); + + return 0; +} + +static const struct iio_info spear_adc_info = { + .read_raw = &spear_adc_read_raw, + .write_raw = &spear_adc_write_raw, + .driver_module = THIS_MODULE, +}; + +static int spear_adc_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct spear_adc_state *st; + struct iio_dev *indio_dev = NULL; + int ret = -ENODEV; + int irq; + + indio_dev = devm_iio_device_alloc(dev, sizeof(struct spear_adc_state)); + if (!indio_dev) { + dev_err(dev, "failed allocating iio device\n"); + return -ENOMEM; + } + + st = iio_priv(indio_dev); + st->np = np; + + /* + * SPEAr600 has a different register layout than other SPEAr SoC's + * (e.g. SPEAr3xx). Let's provide two register base addresses + * to support multi-arch kernels. + */ + st->adc_base_spear6xx = of_iomap(np, 0); + if (!st->adc_base_spear6xx) { + dev_err(dev, "failed mapping memory\n"); + return -ENOMEM; + } + st->adc_base_spear3xx = + (struct adc_regs_spear3xx __iomem *)st->adc_base_spear6xx; + + st->clk = clk_get(dev, NULL); + if (IS_ERR(st->clk)) { + dev_err(dev, "failed getting clock\n"); + goto errout1; + } + + ret = clk_prepare_enable(st->clk); + if (ret) { + dev_err(dev, "failed enabling clock\n"); + goto errout2; + } + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) { + dev_err(dev, "failed getting interrupt resource\n"); + ret = -EINVAL; + goto errout3; + } + + ret = devm_request_irq(dev, irq, spear_adc_isr, 0, SPEAR_ADC_MOD_NAME, + st); + if (ret < 0) { + dev_err(dev, "failed requesting interrupt\n"); + goto errout3; + } + + if (of_property_read_u32(np, "sampling-frequency", + &st->sampling_freq)) { + dev_err(dev, "sampling-frequency missing in DT\n"); + ret = -EINVAL; + goto errout3; + } + + /* + * Optional avg_samples defaults to 0, resulting in single data + * conversion + */ + of_property_read_u32(np, "average-samples", &st->avg_samples); + + /* + * Optional vref_external defaults to 0, resulting in internal vref + * selection + */ + of_property_read_u32(np, "vref-external", &st->vref_external); + + spear_adc_configure(st); + + platform_set_drvdata(pdev, indio_dev); + + init_completion(&st->completion); + + indio_dev->name = SPEAR_ADC_MOD_NAME; + indio_dev->dev.parent = dev; + indio_dev->info = &spear_adc_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = spear_adc_iio_channels; + indio_dev->num_channels = ARRAY_SIZE(spear_adc_iio_channels); + + ret = iio_device_register(indio_dev); + if (ret) + goto errout3; + + dev_info(dev, "SPEAR ADC driver loaded, IRQ %d\n", irq); + + return 0; + +errout3: + clk_disable_unprepare(st->clk); +errout2: + clk_put(st->clk); +errout1: + iounmap(st->adc_base_spear6xx); + return ret; +} + +static int spear_adc_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct spear_adc_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + clk_disable_unprepare(st->clk); + clk_put(st->clk); + iounmap(st->adc_base_spear6xx); + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id spear_adc_dt_ids[] = { + { .compatible = "st,spear600-adc", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, spear_adc_dt_ids); +#endif + +static struct platform_driver spear_adc_driver = { + .probe = spear_adc_probe, + .remove = spear_adc_remove, + .driver = { + .name = SPEAR_ADC_MOD_NAME, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(spear_adc_dt_ids), + }, +}; + +module_platform_driver(spear_adc_driver); + +MODULE_AUTHOR("Stefan Roese <sr@denx.de>"); +MODULE_DESCRIPTION("SPEAr ADC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/addac/Kconfig b/drivers/staging/iio/addac/Kconfig index 698a8970b37..e6795e0bed1 100644 --- a/drivers/staging/iio/addac/Kconfig +++ b/drivers/staging/iio/addac/Kconfig @@ -5,7 +5,7 @@ menu "Analog digital bi-direction converters" config ADT7316 tristate "Analog Devices ADT7316/7/8 ADT7516/7/9 temperature sensor, ADC and DAC driver" - depends on GENERIC_GPIO + depends on GPIOLIB help Say yes here to build support for Analog Devices ADT7316, ADT7317, ADT7318 and ADT7516, ADT7517, ADT7519 temperature sensors, ADC and DAC. diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c index 2c03a39220e..75ddd4f801a 100644 --- a/drivers/staging/iio/addac/adt7316-i2c.c +++ b/drivers/staging/iio/addac/adt7316-i2c.c @@ -92,7 +92,7 @@ static int adt7316_i2c_multi_write(void *client, u8 reg, u8 count, u8 *data) * device probe and remove */ -static int __devinit adt7316_i2c_probe(struct i2c_client *client, +static int adt7316_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct adt7316_bus bus = { @@ -108,11 +108,6 @@ static int __devinit adt7316_i2c_probe(struct i2c_client *client, return adt7316_probe(&client->dev, &bus, id->name); } -static int __devexit adt7316_i2c_remove(struct i2c_client *client) -{ - return adt7316_remove(&client->dev); -} - static const struct i2c_device_id adt7316_i2c_id[] = { { "adt7316", 0 }, { "adt7317", 0 }, @@ -125,35 +120,17 @@ static const struct i2c_device_id adt7316_i2c_id[] = { MODULE_DEVICE_TABLE(i2c, adt7316_i2c_id); -#ifdef CONFIG_PM -static int adt7316_i2c_suspend(struct i2c_client *client, pm_message_t message) -{ - return adt7316_disable(&client->dev); -} - -static int adt7316_i2c_resume(struct i2c_client *client) -{ - return adt7316_enable(&client->dev); -} -#else -# define adt7316_i2c_suspend NULL -# define adt7316_i2c_resume NULL -#endif - static struct i2c_driver adt7316_driver = { .driver = { .name = "adt7316", + .pm = ADT7316_PM_OPS, .owner = THIS_MODULE, }, .probe = adt7316_i2c_probe, - .remove = __devexit_p(adt7316_i2c_remove), - .suspend = adt7316_i2c_suspend, - .resume = adt7316_i2c_resume, .id_table = adt7316_i2c_id, }; module_i2c_driver(adt7316_driver); MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>"); -MODULE_DESCRIPTION("I2C bus driver for Analog Devices ADT7316/7/9 and" - "ADT7516/7/8 digital temperature sensor, ADC and DAC"); +MODULE_DESCRIPTION("I2C bus driver for Analog Devices ADT7316/7/9 and ADT7516/7/8 digital temperature sensor, ADC and DAC"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/addac/adt7316-spi.c b/drivers/staging/iio/addac/adt7316-spi.c index 1ea3cd06299..e480abb72e4 100644 --- a/drivers/staging/iio/addac/adt7316-spi.c +++ b/drivers/staging/iio/addac/adt7316-spi.c @@ -89,7 +89,7 @@ static int adt7316_spi_write(void *client, u8 reg, u8 val) * device probe and remove */ -static int __devinit adt7316_spi_probe(struct spi_device *spi_dev) +static int adt7316_spi_probe(struct spi_device *spi_dev) { struct adt7316_bus bus = { .client = spi_dev, @@ -116,11 +116,6 @@ static int __devinit adt7316_spi_probe(struct spi_device *spi_dev) return adt7316_probe(&spi_dev->dev, &bus, spi_dev->modalias); } -static int __devexit adt7316_spi_remove(struct spi_device *spi_dev) -{ - return adt7316_remove(&spi_dev->dev); -} - static const struct spi_device_id adt7316_spi_id[] = { { "adt7316", 0 }, { "adt7317", 0 }, @@ -133,35 +128,17 @@ static const struct spi_device_id adt7316_spi_id[] = { MODULE_DEVICE_TABLE(spi, adt7316_spi_id); -#ifdef CONFIG_PM -static int adt7316_spi_suspend(struct spi_device *spi_dev, pm_message_t message) -{ - return adt7316_disable(&spi_dev->dev); -} - -static int adt7316_spi_resume(struct spi_device *spi_dev) -{ - return adt7316_enable(&spi_dev->dev); -} -#else -# define adt7316_spi_suspend NULL -# define adt7316_spi_resume NULL -#endif - static struct spi_driver adt7316_driver = { .driver = { .name = "adt7316", + .pm = ADT7316_PM_OPS, .owner = THIS_MODULE, }, .probe = adt7316_spi_probe, - .remove = __devexit_p(adt7316_spi_remove), - .suspend = adt7316_spi_suspend, - .resume = adt7316_spi_resume, .id_table = adt7316_spi_id, }; module_spi_driver(adt7316_driver); MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>"); -MODULE_DESCRIPTION("SPI bus driver for Analog Devices ADT7316/7/8 and" - "ADT7516/7/9 digital temperature sensor, ADC and DAC"); +MODULE_DESCRIPTION("SPI bus driver for Analog Devices ADT7316/7/8 and ADT7516/7/9 digital temperature sensor, ADC and DAC"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index 13c39292d3f..5f1770e6f6c 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -19,9 +19,9 @@ #include <linux/rtc.h> #include <linux/module.h> -#include "../iio.h" -#include "../events.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/events.h> +#include <linux/iio/sysfs.h> #include "adt7316.h" /* @@ -172,7 +172,7 @@ #define ID_ADT75XX 0x10 /* - * struct adt7316_chip_info - chip specifc information + * struct adt7316_chip_info - chip specific information */ struct adt7316_chip_info { @@ -208,7 +208,7 @@ struct adt7316_chip_info { (ADT7316_TEMP_INT_MASK) /* - * struct adt7316_chip_info - chip specifc information + * struct adt7316_chip_info - chip specific information */ struct adt7316_limit_regs { @@ -220,7 +220,7 @@ static ssize_t adt7316_show_enabled(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_EN)); @@ -252,11 +252,11 @@ static ssize_t adt7316_store_enabled(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); int enable; - if (!memcmp(buf, "1", 1)) + if (buf[0] == '1') enable = 1; else enable = 0; @@ -276,7 +276,7 @@ static ssize_t adt7316_show_select_ex_temp(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX) @@ -290,7 +290,7 @@ static ssize_t adt7316_store_select_ex_temp(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 config1; int ret; @@ -299,7 +299,7 @@ static ssize_t adt7316_store_select_ex_temp(struct device *dev, return -EPERM; config1 = chip->config1 & (~ADT7516_SEL_EX_TEMP); - if (!memcmp(buf, "1", 1)) + if (buf[0] == '1') config1 |= ADT7516_SEL_EX_TEMP; ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, config1); @@ -320,7 +320,7 @@ static ssize_t adt7316_show_mode(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); if (chip->config2 & ADT7316_AD_SINGLE_CH_MODE) @@ -334,7 +334,7 @@ static ssize_t adt7316_store_mode(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 config2; int ret; @@ -370,7 +370,7 @@ static ssize_t adt7316_show_ad_channel(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); if (!(chip->config2 & ADT7316_AD_SINGLE_CH_MODE)) @@ -409,16 +409,16 @@ static ssize_t adt7316_store_ad_channel(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 config2; - unsigned long data = 0; + u8 data; int ret; if (!(chip->config2 & ADT7316_AD_SINGLE_CH_MODE)) return -EPERM; - ret = strict_strtoul(buf, 10, &data); + ret = kstrtou8(buf, 10, &data); if (ret) return -EINVAL; @@ -455,7 +455,7 @@ static ssize_t adt7316_show_all_ad_channels(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); if (!(chip->config2 & ADT7316_AD_SINGLE_CH_MODE)) @@ -477,7 +477,7 @@ static ssize_t adt7316_show_disable_averaging(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return sprintf(buf, "%d\n", @@ -489,13 +489,13 @@ static ssize_t adt7316_store_disable_averaging(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 config2; int ret; config2 = chip->config2 & (~ADT7316_DISABLE_AVERAGING); - if (!memcmp(buf, "1", 1)) + if (buf[0] == '1') config2 |= ADT7316_DISABLE_AVERAGING; ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG2, config2); @@ -516,7 +516,7 @@ static ssize_t adt7316_show_enable_smbus_timeout(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return sprintf(buf, "%d\n", @@ -528,13 +528,13 @@ static ssize_t adt7316_store_enable_smbus_timeout(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 config2; int ret; config2 = chip->config2 & (~ADT7316_EN_SMBUS_TIMEOUT); - if (!memcmp(buf, "1", 1)) + if (buf[0] == '1') config2 |= ADT7316_EN_SMBUS_TIMEOUT; ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG2, config2); @@ -551,36 +551,11 @@ static IIO_DEVICE_ATTR(enable_smbus_timeout, S_IRUGO | S_IWUSR, adt7316_store_enable_smbus_timeout, 0); - -static ssize_t adt7316_store_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt7316_chip_info *chip = iio_priv(dev_info); - u8 config2; - int ret; - - config2 = chip->config2 | ADT7316_RESET; - - ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG2, config2); - if (ret) - return -EIO; - - return len; -} - -static IIO_DEVICE_ATTR(reset, S_IWUSR, - NULL, - adt7316_store_reset, - 0); - static ssize_t adt7316_show_powerdown(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_PD)); @@ -591,13 +566,13 @@ static ssize_t adt7316_store_powerdown(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 config1; int ret; config1 = chip->config1 & (~ADT7316_PD); - if (!memcmp(buf, "1", 1)) + if (buf[0] == '1') config1 |= ADT7316_PD; ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, config1); @@ -618,7 +593,7 @@ static ssize_t adt7316_show_fast_ad_clock(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return sprintf(buf, "%d\n", !!(chip->config3 & ADT7316_ADCLK_22_5)); @@ -629,13 +604,13 @@ static ssize_t adt7316_store_fast_ad_clock(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 config3; int ret; config3 = chip->config3 & (~ADT7316_ADCLK_22_5); - if (!memcmp(buf, "1", 1)) + if (buf[0] == '1') config3 |= ADT7316_ADCLK_22_5; ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, config3); @@ -656,7 +631,7 @@ static ssize_t adt7316_show_da_high_resolution(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); if (chip->config3 & ADT7316_DA_HIGH_RESOLUTION) { @@ -674,14 +649,14 @@ static ssize_t adt7316_store_da_high_resolution(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 config3; int ret; chip->dac_bits = 8; - if (!memcmp(buf, "1", 1)) { + if (buf[0] == '1') { config3 = chip->config3 | ADT7316_DA_HIGH_RESOLUTION; if (chip->id == ID_ADT7316 || chip->id == ID_ADT7516) chip->dac_bits = 12; @@ -708,7 +683,7 @@ static ssize_t adt7316_show_AIN_internal_Vref(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX) @@ -723,7 +698,7 @@ static ssize_t adt7316_store_AIN_internal_Vref(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 config3; int ret; @@ -731,7 +706,7 @@ static ssize_t adt7316_store_AIN_internal_Vref(struct device *dev, if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX) return -EPERM; - if (memcmp(buf, "1", 1)) + if (buf[0] != '1') config3 = chip->config3 & (~ADT7516_AIN_IN_VREF); else config3 = chip->config3 | ADT7516_AIN_IN_VREF; @@ -755,7 +730,7 @@ static ssize_t adt7316_show_enable_prop_DACA(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return sprintf(buf, "%d\n", @@ -767,13 +742,13 @@ static ssize_t adt7316_store_enable_prop_DACA(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 config3; int ret; config3 = chip->config3 & (~ADT7316_EN_IN_TEMP_PROP_DACA); - if (!memcmp(buf, "1", 1)) + if (buf[0] == '1') config3 |= ADT7316_EN_IN_TEMP_PROP_DACA; ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, config3); @@ -794,7 +769,7 @@ static ssize_t adt7316_show_enable_prop_DACB(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return sprintf(buf, "%d\n", @@ -806,13 +781,13 @@ static ssize_t adt7316_store_enable_prop_DACB(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 config3; int ret; config3 = chip->config3 & (~ADT7316_EN_EX_TEMP_PROP_DACB); - if (!memcmp(buf, "1", 1)) + if (buf[0] == '1') config3 |= ADT7316_EN_EX_TEMP_PROP_DACB; ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, config3); @@ -833,7 +808,7 @@ static ssize_t adt7316_show_DAC_2Vref_ch_mask(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return sprintf(buf, "0x%x\n", @@ -845,13 +820,13 @@ static ssize_t adt7316_store_DAC_2Vref_ch_mask(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 dac_config; - unsigned long data = 0; + u8 data; int ret; - ret = strict_strtoul(buf, 16, &data); + ret = kstrtou8(buf, 16, &data); if (ret || data > ADT7316_DA_2VREF_CH_MASK) return -EINVAL; @@ -876,7 +851,7 @@ static ssize_t adt7316_show_DAC_update_mode(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA)) @@ -884,11 +859,14 @@ static ssize_t adt7316_show_DAC_update_mode(struct device *dev, else { switch (chip->dac_config & ADT7316_DA_EN_MODE_MASK) { case ADT7316_DA_EN_MODE_SINGLE: - return sprintf(buf, "0 - auto at any MSB DAC writing\n"); + return sprintf(buf, + "0 - auto at any MSB DAC writing\n"); case ADT7316_DA_EN_MODE_AB_CD: - return sprintf(buf, "1 - auto at MSB DAC AB and CD writing\n"); + return sprintf(buf, + "1 - auto at MSB DAC AB and CD writing\n"); case ADT7316_DA_EN_MODE_ABCD: - return sprintf(buf, "2 - auto at MSB DAC ABCD writing\n"); + return sprintf(buf, + "2 - auto at MSB DAC ABCD writing\n"); default: /* ADT7316_DA_EN_MODE_LDAC */ return sprintf(buf, "3 - manual\n"); } @@ -900,16 +878,16 @@ static ssize_t adt7316_store_DAC_update_mode(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 dac_config; - unsigned long data; + u8 data; int ret; if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA)) return -EPERM; - ret = strict_strtoul(buf, 10, &data); + ret = kstrtou8(buf, 10, &data); if (ret || data > ADT7316_DA_EN_MODE_MASK) return -EINVAL; @@ -934,7 +912,7 @@ static ssize_t adt7316_show_all_DAC_update_modes(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA) @@ -955,10 +933,10 @@ static ssize_t adt7316_store_update_DAC(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 ldac_config; - unsigned long data; + u8 data; int ret; if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA) { @@ -966,7 +944,7 @@ static ssize_t adt7316_store_update_DAC(struct device *dev, ADT7316_DA_EN_MODE_LDAC) return -EPERM; - ret = strict_strtoul(buf, 16, &data); + ret = kstrtou8(buf, 16, &data); if (ret || data > ADT7316_LDAC_EN_DA_MASK) return -EINVAL; @@ -994,7 +972,7 @@ static ssize_t adt7316_show_DA_AB_Vref_bypass(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) @@ -1009,7 +987,7 @@ static ssize_t adt7316_store_DA_AB_Vref_bypass(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 dac_config; int ret; @@ -1018,7 +996,7 @@ static ssize_t adt7316_store_DA_AB_Vref_bypass(struct device *dev, return -EPERM; dac_config = chip->dac_config & (~ADT7316_VREF_BYPASS_DAC_AB); - if (!memcmp(buf, "1", 1)) + if (buf[0] == '1') dac_config |= ADT7316_VREF_BYPASS_DAC_AB; ret = chip->bus.write(chip->bus.client, ADT7316_DAC_CONFIG, dac_config); @@ -1039,7 +1017,7 @@ static ssize_t adt7316_show_DA_CD_Vref_bypass(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) @@ -1054,7 +1032,7 @@ static ssize_t adt7316_store_DA_CD_Vref_bypass(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 dac_config; int ret; @@ -1063,7 +1041,7 @@ static ssize_t adt7316_store_DA_CD_Vref_bypass(struct device *dev, return -EPERM; dac_config = chip->dac_config & (~ADT7316_VREF_BYPASS_DAC_CD); - if (!memcmp(buf, "1", 1)) + if (buf[0] == '1') dac_config |= ADT7316_VREF_BYPASS_DAC_CD; ret = chip->bus.write(chip->bus.client, ADT7316_DAC_CONFIG, dac_config); @@ -1084,7 +1062,7 @@ static ssize_t adt7316_show_DAC_internal_Vref(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) @@ -1101,14 +1079,14 @@ static ssize_t adt7316_store_DAC_internal_Vref(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 ldac_config; - unsigned long data; + u8 data; int ret; if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) { - ret = strict_strtoul(buf, 16, &data); + ret = kstrtou8(buf, 16, &data); if (ret || data > 3) return -EINVAL; @@ -1118,7 +1096,7 @@ static ssize_t adt7316_store_DAC_internal_Vref(struct device *dev, else if (data & 0x2) ldac_config |= ADT7516_DAC_CD_IN_VREF; } else { - ret = strict_strtoul(buf, 16, &data); + ret = kstrtou8(buf, 16, &data); if (ret) return -EINVAL; @@ -1127,7 +1105,8 @@ static ssize_t adt7316_store_DAC_internal_Vref(struct device *dev, ldac_config = chip->ldac_config | ADT7316_DAC_IN_VREF; } - ret = chip->bus.write(chip->bus.client, ADT7316_LDAC_CONFIG, ldac_config); + ret = chip->bus.write(chip->bus.client, ADT7316_LDAC_CONFIG, + ldac_config); if (ret) return -EIO; @@ -1220,7 +1199,7 @@ static ssize_t adt7316_show_VDD(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_VDD, buf); @@ -1231,7 +1210,7 @@ static ssize_t adt7316_show_in_temp(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_IN, buf); @@ -1243,20 +1222,21 @@ static ssize_t adt7316_show_ex_temp_AIN1(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_EX, buf); } -static IIO_DEVICE_ATTR(ex_temp_AIN1, S_IRUGO, adt7316_show_ex_temp_AIN1, NULL, 0); +static IIO_DEVICE_ATTR(ex_temp_AIN1, S_IRUGO, adt7316_show_ex_temp_AIN1, + NULL, 0); static IIO_DEVICE_ATTR(ex_temp, S_IRUGO, adt7316_show_ex_temp_AIN1, NULL, 0); static ssize_t adt7316_show_AIN2(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN2, buf); @@ -1267,7 +1247,7 @@ static ssize_t adt7316_show_AIN3(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN3, buf); @@ -1278,7 +1258,7 @@ static ssize_t adt7316_show_AIN4(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN4, buf); @@ -1306,11 +1286,11 @@ static ssize_t adt7316_show_temp_offset(struct adt7316_chip_info *chip, static ssize_t adt7316_store_temp_offset(struct adt7316_chip_info *chip, int offset_addr, const char *buf, size_t len) { - long data; + int data; u8 val; int ret; - ret = strict_strtol(buf, 10, &data); + ret = kstrtoint(buf, 10, &data); if (ret || data > 127 || data < -128) return -EINVAL; @@ -1330,7 +1310,7 @@ static ssize_t adt7316_show_in_temp_offset(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_show_temp_offset(chip, ADT7316_IN_TEMP_OFFSET, buf); @@ -1341,10 +1321,11 @@ static ssize_t adt7316_store_in_temp_offset(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - return adt7316_store_temp_offset(chip, ADT7316_IN_TEMP_OFFSET, buf, len); + return adt7316_store_temp_offset(chip, ADT7316_IN_TEMP_OFFSET, buf, + len); } static IIO_DEVICE_ATTR(in_temp_offset, S_IRUGO | S_IWUSR, @@ -1355,7 +1336,7 @@ static ssize_t adt7316_show_ex_temp_offset(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_show_temp_offset(chip, ADT7316_EX_TEMP_OFFSET, buf); @@ -1366,10 +1347,11 @@ static ssize_t adt7316_store_ex_temp_offset(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - return adt7316_store_temp_offset(chip, ADT7316_EX_TEMP_OFFSET, buf, len); + return adt7316_store_temp_offset(chip, ADT7316_EX_TEMP_OFFSET, buf, + len); } static IIO_DEVICE_ATTR(ex_temp_offset, S_IRUGO | S_IWUSR, @@ -1380,7 +1362,7 @@ static ssize_t adt7316_show_in_analog_temp_offset(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_show_temp_offset(chip, @@ -1392,7 +1374,7 @@ static ssize_t adt7316_store_in_analog_temp_offset(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_store_temp_offset(chip, @@ -1407,7 +1389,7 @@ static ssize_t adt7316_show_ex_analog_temp_offset(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_show_temp_offset(chip, @@ -1419,7 +1401,7 @@ static ssize_t adt7316_store_ex_analog_temp_offset(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_store_temp_offset(chip, @@ -1467,7 +1449,7 @@ static ssize_t adt7316_store_DAC(struct adt7316_chip_info *chip, int channel, const char *buf, size_t len) { u8 msb, lsb, offset; - unsigned long data; + u16 data; int ret; if (channel >= ADT7316_DA_MSB_DATA_REGS || @@ -1479,7 +1461,7 @@ static ssize_t adt7316_store_DAC(struct adt7316_chip_info *chip, offset = chip->dac_bits - 8; - ret = strict_strtoul(buf, 10, &data); + ret = kstrtou16(buf, 10, &data); if (ret || data >= (1 << chip->dac_bits)) return -EINVAL; @@ -1504,7 +1486,7 @@ static ssize_t adt7316_show_DAC_A(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_show_DAC(chip, 0, buf); @@ -1515,7 +1497,7 @@ static ssize_t adt7316_store_DAC_A(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_store_DAC(chip, 0, buf, len); @@ -1528,7 +1510,7 @@ static ssize_t adt7316_show_DAC_B(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_show_DAC(chip, 1, buf); @@ -1539,7 +1521,7 @@ static ssize_t adt7316_store_DAC_B(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_store_DAC(chip, 1, buf, len); @@ -1552,7 +1534,7 @@ static ssize_t adt7316_show_DAC_C(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_show_DAC(chip, 2, buf); @@ -1563,7 +1545,7 @@ static ssize_t adt7316_store_DAC_C(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_store_DAC(chip, 2, buf, len); @@ -1576,7 +1558,7 @@ static ssize_t adt7316_show_DAC_D(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_show_DAC(chip, 3, buf); @@ -1587,7 +1569,7 @@ static ssize_t adt7316_store_DAC_D(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return adt7316_store_DAC(chip, 3, buf, len); @@ -1600,7 +1582,7 @@ static ssize_t adt7316_show_device_id(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 id; int ret; @@ -1618,7 +1600,7 @@ static ssize_t adt7316_show_manufactorer_id(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 id; int ret; @@ -1637,7 +1619,7 @@ static ssize_t adt7316_show_device_rev(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 rev; int ret; @@ -1655,7 +1637,7 @@ static ssize_t adt7316_show_bus_type(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 stat; int ret; @@ -1675,7 +1657,6 @@ static IIO_DEVICE_ATTR(bus_type, S_IRUGO, adt7316_show_bus_type, NULL, 0); static struct attribute *adt7316_attributes[] = { &iio_dev_attr_all_modes.dev_attr.attr, &iio_dev_attr_mode.dev_attr.attr, - &iio_dev_attr_reset.dev_attr.attr, &iio_dev_attr_enabled.dev_attr.attr, &iio_dev_attr_ad_channel.dev_attr.attr, &iio_dev_attr_all_ad_channels.dev_attr.attr, @@ -1719,7 +1700,6 @@ static struct attribute *adt7516_attributes[] = { &iio_dev_attr_all_modes.dev_attr.attr, &iio_dev_attr_mode.dev_attr.attr, &iio_dev_attr_select_ex_temp.dev_attr.attr, - &iio_dev_attr_reset.dev_attr.attr, &iio_dev_attr_enabled.dev_attr.attr, &iio_dev_attr_ad_channel.dev_attr.attr, &iio_dev_attr_all_ad_channels.dev_attr.attr, @@ -1841,7 +1821,7 @@ static ssize_t adt7316_show_int_mask(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return sprintf(buf, "0x%x\n", chip->int_mask); @@ -1855,13 +1835,13 @@ static ssize_t adt7316_set_int_mask(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - unsigned long data; + u16 data; int ret; u8 mask; - ret = strict_strtoul(buf, 16, &data); + ret = kstrtou16(buf, 16, &data); if (ret || data >= ADT7316_VDD_INT_MASK + 1) return -EINVAL; @@ -1895,7 +1875,7 @@ static inline ssize_t adt7316_show_ad_bound(struct device *dev, char *buf) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 val; int data; @@ -1926,9 +1906,9 @@ static inline ssize_t adt7316_set_ad_bound(struct device *dev, size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - long data; + int data; u8 val; int ret; @@ -1936,7 +1916,7 @@ static inline ssize_t adt7316_set_ad_bound(struct device *dev, this_attr->address > ADT7316_EX_TEMP_LOW) return -EPERM; - ret = strict_strtol(buf, 10, &data); + ret = kstrtoint(buf, 10, &data); if (ret) return -EINVAL; @@ -1965,7 +1945,7 @@ static ssize_t adt7316_show_int_enabled(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_INT_EN)); @@ -1976,13 +1956,13 @@ static ssize_t adt7316_set_int_enabled(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); + struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); u8 config1; int ret; config1 = chip->config1 & (~ADT7316_INT_EN); - if (!memcmp(buf, "1", 1)) + if (buf[0] == '1') config1 |= ADT7316_INT_EN; ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, config1); @@ -2089,24 +2069,25 @@ static struct attribute_group adt7516_event_attribute_group = { .name = "events", }; -#ifdef CONFIG_PM -int adt7316_disable(struct device *dev) +#ifdef CONFIG_PM_SLEEP +static int adt7316_disable(struct device *dev) { struct iio_dev *dev_info = dev_get_drvdata(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return _adt7316_store_enabled(chip, 0); } -EXPORT_SYMBOL(adt7316_disable); -int adt7316_enable(struct device *dev) +static int adt7316_enable(struct device *dev) { struct iio_dev *dev_info = dev_get_drvdata(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return _adt7316_store_enabled(chip, 1); } -EXPORT_SYMBOL(adt7316_enable); + +SIMPLE_DEV_PM_OPS(adt7316_pm_ops, adt7316_disable, adt7316_enable); +EXPORT_SYMBOL_GPL(adt7316_pm_ops); #endif static const struct iio_info adt7316_info = { @@ -2124,7 +2105,7 @@ static const struct iio_info adt7516_info = { /* * device probe and remove */ -int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus, +int adt7316_probe(struct device *dev, struct adt7316_bus *bus, const char *name) { struct adt7316_chip_info *chip; @@ -2132,11 +2113,9 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus, unsigned short *adt7316_platform_data = dev->platform_data; int ret = 0; - indio_dev = iio_allocate_device(sizeof(*chip)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(dev, sizeof(*chip)); + if (!indio_dev) + return -ENOMEM; chip = iio_priv(indio_dev); /* this is only used for device removal purposes */ dev_set_drvdata(dev, indio_dev); @@ -2172,63 +2151,39 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus, if (adt7316_platform_data[0]) chip->bus.irq_flags = adt7316_platform_data[0]; - ret = request_threaded_irq(chip->bus.irq, - NULL, - &adt7316_event_handler, - chip->bus.irq_flags | IRQF_ONESHOT, - indio_dev->name, - indio_dev); + ret = devm_request_threaded_irq(dev, chip->bus.irq, + NULL, + &adt7316_event_handler, + chip->bus.irq_flags | + IRQF_ONESHOT, + indio_dev->name, + indio_dev); if (ret) - goto error_free_dev; + return ret; if (chip->bus.irq_flags & IRQF_TRIGGER_HIGH) chip->config1 |= ADT7316_INT_POLARITY; } ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, chip->config1); - if (ret) { - ret = -EIO; - goto error_unreg_irq; - } + if (ret) + return -EIO; ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, chip->config3); - if (ret) { - ret = -EIO; - goto error_unreg_irq; - } + if (ret) + return -EIO; - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(dev, indio_dev); if (ret) - goto error_unreg_irq; + return ret; dev_info(dev, "%s temperature sensor, ADC and DAC registered.\n", indio_dev->name); return 0; - -error_unreg_irq: - free_irq(chip->bus.irq, indio_dev); -error_free_dev: - iio_free_device(indio_dev); -error_ret: - return ret; } EXPORT_SYMBOL(adt7316_probe); -int __devexit adt7316_remove(struct device *dev) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adt7316_chip_info *chip = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - if (chip->bus.irq) - free_irq(chip->bus.irq, indio_dev); - iio_free_device(indio_dev); - - return 0; -} -EXPORT_SYMBOL(adt7316_remove); - MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>"); MODULE_DESCRIPTION("Analog Devices ADT7316/7/8 and ADT7516/7/9 digital" " temperature sensor, ADC and DAC driver"); diff --git a/drivers/staging/iio/addac/adt7316.h b/drivers/staging/iio/addac/adt7316.h index d34bd679bb4..ec50bf34628 100644 --- a/drivers/staging/iio/addac/adt7316.h +++ b/drivers/staging/iio/addac/adt7316.h @@ -10,6 +10,7 @@ #define _ADT7316_H_ #include <linux/types.h> +#include <linux/pm.h> #define ADT7316_REG_MAX_ADDR 0x3F @@ -17,17 +18,18 @@ struct adt7316_bus { void *client; int irq; int irq_flags; - int (*read) (void *client, u8 reg, u8 *data); - int (*write) (void *client, u8 reg, u8 val); - int (*multi_read) (void *client, u8 first_reg, u8 count, u8 *data); - int (*multi_write) (void *client, u8 first_reg, u8 count, u8 *data); + int (*read)(void *client, u8 reg, u8 *data); + int (*write)(void *client, u8 reg, u8 val); + int (*multi_read)(void *client, u8 first_reg, u8 count, u8 *data); + int (*multi_write)(void *client, u8 first_reg, u8 count, u8 *data); }; -#ifdef CONFIG_PM -int adt7316_disable(struct device *dev); -int adt7316_enable(struct device *dev); +#ifdef CONFIG_PM_SLEEP +extern const struct dev_pm_ops adt7316_pm_ops; +#define ADT7316_PM_OPS (&adt7316_pm_ops) +#else +#define ADT7316_PM_OPS NULL #endif int adt7316_probe(struct device *dev, struct adt7316_bus *bus, const char *name); -int adt7316_remove(struct device *dev); #endif diff --git a/drivers/staging/iio/buffer.h b/drivers/staging/iio/buffer.h deleted file mode 100644 index 6fb6e64181a..00000000000 --- a/drivers/staging/iio/buffer.h +++ /dev/null @@ -1,195 +0,0 @@ -/* The industrial I/O core - generic buffer interfaces. - * - * 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. - */ - -#ifndef _IIO_BUFFER_GENERIC_H_ -#define _IIO_BUFFER_GENERIC_H_ -#include <linux/sysfs.h> -#include "iio.h" - -#ifdef CONFIG_IIO_BUFFER - -struct iio_buffer; - -/** - * struct iio_buffer_access_funcs - access functions for buffers. - * @store_to: actually store stuff to the buffer - * @read_first_n: try to get a specified number of bytes (must exist) - * @request_update: if a parameter change has been marked, update underlying - * storage. - * @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 buffer - * @set_length: set number of datums in buffer - * - * The purpose of this structure is to make the buffer element - * modular as event for a given driver, different usecases may require - * different buffer designs (space efficiency vs speed for example). - * - * It is worth noting that a given buffer implementation may only support a - * small proportion of these functions. The core code 'should' cope fine with - * any of them not existing. - **/ -struct iio_buffer_access_funcs { - int (*store_to)(struct iio_buffer *buffer, u8 *data, s64 timestamp); - int (*read_first_n)(struct iio_buffer *buffer, - size_t n, - char __user *buf); - - int (*request_update)(struct iio_buffer *buffer); - - int (*get_bytes_per_datum)(struct iio_buffer *buffer); - int (*set_bytes_per_datum)(struct iio_buffer *buffer, size_t bpd); - int (*get_length)(struct iio_buffer *buffer); - int (*set_length)(struct iio_buffer *buffer, int length); -}; - -/** - * struct iio_buffer - general buffer structure - * @length: [DEVICE] number of datums in buffer - * @bytes_per_datum: [DEVICE] size of individual datum including timestamp - * @scan_el_attrs: [DRIVER] control of scan elements if that scan mode - * control method is used - * @scan_mask: [INTERN] bitmask used in masking scan mode elements - * @scan_index_timestamp:[INTERN] cache of the index to the timestamp - * @scan_timestamp: [INTERN] does the scan mode include a timestamp - * @access: [DRIVER] buffer access functions associated with the - * implementation. - * @scan_el_dev_attr_list:[INTERN] list of scan element related attributes. - * @scan_el_group: [DRIVER] attribute group for those attributes not - * created from the iio_chan_info array. - * @pollq: [INTERN] wait queue to allow for polling on the buffer. - * @stufftoread: [INTERN] flag to indicate new data. - * @demux_list: [INTERN] list of operations required to demux the scan. - * @demux_bounce: [INTERN] buffer for doing gather from incoming scan. - **/ -struct iio_buffer { - int length; - int bytes_per_datum; - struct attribute_group *scan_el_attrs; - long *scan_mask; - bool scan_timestamp; - unsigned scan_index_timestamp; - const struct iio_buffer_access_funcs *access; - struct list_head scan_el_dev_attr_list; - struct attribute_group scan_el_group; - wait_queue_head_t pollq; - bool stufftoread; - const struct attribute_group *attrs; - struct list_head demux_list; - unsigned char *demux_bounce; -}; - -/** - * iio_buffer_init() - Initialize the buffer structure - * @buffer: buffer to be initialized - **/ -void iio_buffer_init(struct iio_buffer *buffer); - -void iio_buffer_deinit(struct iio_buffer *buffer); - -/** - * __iio_update_buffer() - update common elements of buffers - * @buffer: buffer that is the event source - * @bytes_per_datum: size of individual datum including timestamp - * @length: number of datums in buffer - **/ -static inline void __iio_update_buffer(struct iio_buffer *buffer, - int bytes_per_datum, int length) -{ - buffer->bytes_per_datum = bytes_per_datum; - buffer->length = length; -} - -int iio_scan_mask_query(struct iio_dev *indio_dev, - struct iio_buffer *buffer, int bit); - -/** - * iio_scan_mask_set() - set particular bit in the scan mask - * @buffer: the buffer whose scan mask we are interested in - * @bit: the bit to be set. - **/ -int iio_scan_mask_set(struct iio_dev *indio_dev, - struct iio_buffer *buffer, int bit); - -/** - * iio_push_to_buffer() - push to a registered buffer. - * @buffer: IIO buffer structure for device - * @scan: Full scan. - * @timestamp: - */ -int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data, - s64 timestamp); - -int iio_update_demux(struct iio_dev *indio_dev); - -/** - * iio_buffer_register() - register the buffer with IIO core - * @indio_dev: device with the buffer to be registered - **/ -int iio_buffer_register(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, - int num_channels); - -/** - * iio_buffer_unregister() - unregister the buffer from IIO core - * @indio_dev: the device with the buffer to be unregistered - **/ -void iio_buffer_unregister(struct iio_dev *indio_dev); - -/** - * iio_buffer_read_length() - attr func to get number of datums in the buffer - **/ -ssize_t iio_buffer_read_length(struct device *dev, - struct device_attribute *attr, - char *buf); -/** - * iio_buffer_write_length() - attr func to set number of datums in the buffer - **/ -ssize_t iio_buffer_write_length(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len); -/** - * iio_buffer_store_enable() - attr to turn the buffer on - **/ -ssize_t iio_buffer_store_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len); -/** - * iio_buffer_show_enable() - attr to see if the buffer is on - **/ -ssize_t iio_buffer_show_enable(struct device *dev, - struct device_attribute *attr, - char *buf); -#define IIO_BUFFER_LENGTH_ATTR DEVICE_ATTR(length, S_IRUGO | S_IWUSR, \ - iio_buffer_read_length, \ - iio_buffer_write_length) - -#define IIO_BUFFER_ENABLE_ATTR DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, \ - iio_buffer_show_enable, \ - iio_buffer_store_enable) - -int iio_sw_buffer_preenable(struct iio_dev *indio_dev); - -#else /* CONFIG_IIO_BUFFER */ - -static inline int iio_buffer_register(struct iio_dev *indio_dev, - struct iio_chan_spec *channels, - int num_channels) -{ - return 0; -} - -static inline void iio_buffer_unregister(struct iio_dev *indio_dev) -{}; - -#endif /* CONFIG_IIO_BUFFER */ - -#endif /* _IIO_BUFFER_GENERIC_H_ */ diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index b73007dcf4b..047af237630 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -13,9 +13,9 @@ #include <linux/i2c.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/events.h> /* * AD7150 registers definition */ @@ -104,7 +104,7 @@ static int ad7150_read_raw(struct iio_dev *indio_dev, struct ad7150_chip_info *chip = iio_priv(indio_dev); switch (mask) { - case 0: + case IIO_CHAN_INFO_RAW: ret = i2c_smbus_read_word_data(chip->client, ad7150_addresses[chan->channel][0]); if (ret < 0) @@ -123,14 +123,14 @@ static int ad7150_read_raw(struct iio_dev *indio_dev, } } -static int ad7150_read_event_config(struct iio_dev *indio_dev, u64 event_code) +static int ad7150_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, enum iio_event_type type, + enum iio_event_direction dir) { int ret; u8 threshtype; bool adaptive; struct ad7150_chip_info *chip = iio_priv(indio_dev); - int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_RISING); ret = i2c_smbus_read_byte_data(chip->client, AD7150_CFG); if (ret < 0) @@ -139,42 +139,47 @@ static int ad7150_read_event_config(struct iio_dev *indio_dev, u64 event_code) threshtype = (ret >> 5) & 0x03; adaptive = !!(ret & 0x80); - switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) { + switch (type) { case IIO_EV_TYPE_MAG_ADAPTIVE: - if (rising) + if (dir == IIO_EV_DIR_RISING) return adaptive && (threshtype == 0x1); else return adaptive && (threshtype == 0x0); case IIO_EV_TYPE_THRESH_ADAPTIVE: - if (rising) + if (dir == IIO_EV_DIR_RISING) return adaptive && (threshtype == 0x3); else return adaptive && (threshtype == 0x2); case IIO_EV_TYPE_THRESH: - if (rising) + if (dir == IIO_EV_DIR_RISING) return !adaptive && (threshtype == 0x1); else return !adaptive && (threshtype == 0x0); - }; + default: + break; + } return -EINVAL; } /* lock should be held */ -static int ad7150_write_event_params(struct iio_dev *indio_dev, u64 event_code) +static int ad7150_write_event_params(struct iio_dev *indio_dev, + unsigned int chan, enum iio_event_type type, + enum iio_event_direction dir) { int ret; u16 value; u8 sens, timeout; struct ad7150_chip_info *chip = iio_priv(indio_dev); - int chan = IIO_EVENT_CODE_EXTRACT_NUM(event_code); - int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_RISING); + int rising = (dir == IIO_EV_DIR_RISING); + u64 event_code; + + event_code = IIO_UNMOD_EVENT_CODE(IIO_CAPACITANCE, chan, type, dir); if (event_code != chip->current_event) return 0; - switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) { + switch (type) { /* Note completely different from the adaptive versions */ case IIO_EV_TYPE_THRESH: value = chip->threshold[rising][chan]; @@ -194,7 +199,7 @@ static int ad7150_write_event_params(struct iio_dev *indio_dev, u64 event_code) break; default: return -EINVAL; - }; + } ret = i2c_smbus_write_byte_data(chip->client, ad7150_addresses[chan][4], sens); @@ -211,18 +216,20 @@ static int ad7150_write_event_params(struct iio_dev *indio_dev, u64 event_code) } static int ad7150_write_event_config(struct iio_dev *indio_dev, - u64 event_code, int state) + const struct iio_chan_spec *chan, enum iio_event_type type, + enum iio_event_direction dir, int state) { u8 thresh_type, cfg, adaptive; int ret; struct ad7150_chip_info *chip = iio_priv(indio_dev); - int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_RISING); + int rising = (dir == IIO_EV_DIR_RISING); + u64 event_code; /* Something must always be turned on */ if (state == 0) return -EINVAL; + event_code = IIO_UNMOD_EVENT_CODE(chan->type, chan->channel, type, dir); if (event_code == chip->current_event) return 0; mutex_lock(&chip->state_lock); @@ -232,7 +239,7 @@ static int ad7150_write_event_config(struct iio_dev *indio_dev, cfg = ret & ~((0x03 << 5) | (0x1 << 7)); - switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) { + switch (type) { case IIO_EV_TYPE_MAG_ADAPTIVE: adaptive = 1; if (rising) @@ -257,7 +264,7 @@ static int ad7150_write_event_config(struct iio_dev *indio_dev, default: ret = -EINVAL; goto error_ret; - }; + } cfg |= (!adaptive << 7) | (thresh_type << 5); @@ -268,7 +275,7 @@ static int ad7150_write_event_config(struct iio_dev *indio_dev, chip->current_event = event_code; /* update control attributes */ - ret = ad7150_write_event_params(indio_dev, event_code); + ret = ad7150_write_event_params(indio_dev, chan->channel, type, dir); error_ret: mutex_unlock(&chip->state_lock); @@ -276,61 +283,60 @@ error_ret: } static int ad7150_read_event_value(struct iio_dev *indio_dev, - u64 event_code, - int *val) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) { - int chan = IIO_EVENT_CODE_EXTRACT_NUM(event_code); struct ad7150_chip_info *chip = iio_priv(indio_dev); - int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_RISING); + int rising = (dir == IIO_EV_DIR_RISING); /* Complex register sharing going on here */ - switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) { + switch (type) { case IIO_EV_TYPE_MAG_ADAPTIVE: - *val = chip->mag_sensitivity[rising][chan]; - return 0; - + *val = chip->mag_sensitivity[rising][chan->channel]; + return IIO_VAL_INT; case IIO_EV_TYPE_THRESH_ADAPTIVE: - *val = chip->thresh_sensitivity[rising][chan]; - return 0; - + *val = chip->thresh_sensitivity[rising][chan->channel]; + return IIO_VAL_INT; case IIO_EV_TYPE_THRESH: - *val = chip->threshold[rising][chan]; - return 0; - + *val = chip->threshold[rising][chan->channel]; + return IIO_VAL_INT; default: return -EINVAL; - }; + } } static int ad7150_write_event_value(struct iio_dev *indio_dev, - u64 event_code, - int val) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) { int ret; struct ad7150_chip_info *chip = iio_priv(indio_dev); - int chan = IIO_EVENT_CODE_EXTRACT_NUM(event_code); - int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_RISING); + int rising = (dir == IIO_EV_DIR_RISING); mutex_lock(&chip->state_lock); - switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) { + switch (type) { case IIO_EV_TYPE_MAG_ADAPTIVE: - chip->mag_sensitivity[rising][chan] = val; + chip->mag_sensitivity[rising][chan->channel] = val; break; case IIO_EV_TYPE_THRESH_ADAPTIVE: - chip->thresh_sensitivity[rising][chan] = val; + chip->thresh_sensitivity[rising][chan->channel] = val; break; case IIO_EV_TYPE_THRESH: - chip->threshold[rising][chan] = val; + chip->threshold[rising][chan->channel] = val; break; default: ret = -EINVAL; goto error_ret; - }; + } /* write back if active */ - ret = ad7150_write_event_params(indio_dev, event_code); + ret = ad7150_write_event_params(indio_dev, chan->channel, type, dir); error_ret: mutex_unlock(&chip->state_lock); @@ -341,13 +347,13 @@ static ssize_t ad7150_show_timeout(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7150_chip_info *chip = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); u8 value; /* use the event code for consistency reasons */ - int chan = IIO_EVENT_CODE_EXTRACT_NUM(this_attr->address); + int chan = IIO_EVENT_CODE_EXTRACT_CHAN(this_attr->address); int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(this_attr->address) == IIO_EV_DIR_RISING); @@ -360,7 +366,7 @@ static ssize_t ad7150_show_timeout(struct device *dev, break; default: return -EINVAL; - }; + } return sprintf(buf, "%d\n", value); } @@ -370,21 +376,26 @@ static ssize_t ad7150_store_timeout(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7150_chip_info *chip = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int chan = IIO_EVENT_CODE_EXTRACT_NUM(this_attr->address); - int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(this_attr->address) == - IIO_EV_DIR_RISING); + int chan = IIO_EVENT_CODE_EXTRACT_CHAN(this_attr->address); + enum iio_event_direction dir; + enum iio_event_type type; + int rising; u8 data; int ret; + type = IIO_EVENT_CODE_EXTRACT_TYPE(this_attr->address); + dir = IIO_EVENT_CODE_EXTRACT_DIR(this_attr->address); + rising = (dir == IIO_EV_DIR_RISING); + ret = kstrtou8(buf, 10, &data); if (ret < 0) return ret; mutex_lock(&chip->state_lock); - switch (IIO_EVENT_CODE_EXTRACT_TYPE(this_attr->address)) { + switch (type) { case IIO_EV_TYPE_MAG_ADAPTIVE: chip->mag_timeout[rising][chan] = data; break; @@ -394,9 +405,9 @@ static ssize_t ad7150_store_timeout(struct device *dev, default: ret = -EINVAL; goto error_ret; - }; + } - ret = ad7150_write_event_params(indio_dev, this_attr->address); + ret = ad7150_write_event_params(indio_dev, chan, type, dir); error_ret: mutex_unlock(&chip->state_lock); @@ -424,31 +435,57 @@ static AD7150_TIMEOUT(0, thresh_adaptive, falling, THRESH_ADAPTIVE, FALLING); static AD7150_TIMEOUT(1, thresh_adaptive, rising, THRESH_ADAPTIVE, RISING); static AD7150_TIMEOUT(1, thresh_adaptive, falling, THRESH_ADAPTIVE, FALLING); +static const struct iio_event_spec ad7150_events[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, { + .type = IIO_EV_TYPE_THRESH_ADAPTIVE, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, { + .type = IIO_EV_TYPE_THRESH_ADAPTIVE, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, { + .type = IIO_EV_TYPE_MAG_ADAPTIVE, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, { + .type = IIO_EV_TYPE_MAG_ADAPTIVE, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, +}; + static const struct iio_chan_spec ad7150_channels[] = { { .type = IIO_CAPACITANCE, .indexed = 1, .channel = 0, - .info_mask = IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT, - .event_mask = - IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | - IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING) | - IIO_EV_BIT(IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_DIR_RISING) | - IIO_EV_BIT(IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_DIR_FALLING) | - IIO_EV_BIT(IIO_EV_TYPE_MAG_ADAPTIVE, IIO_EV_DIR_RISING) | - IIO_EV_BIT(IIO_EV_TYPE_MAG_ADAPTIVE, IIO_EV_DIR_FALLING) + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_AVERAGE_RAW), + .event_spec = ad7150_events, + .num_event_specs = ARRAY_SIZE(ad7150_events), }, { .type = IIO_CAPACITANCE, .indexed = 1, .channel = 1, - .info_mask = IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT, - .event_mask = - IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | - IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING) | - IIO_EV_BIT(IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_DIR_RISING) | - IIO_EV_BIT(IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_DIR_FALLING) | - IIO_EV_BIT(IIO_EV_TYPE_MAG_ADAPTIVE, IIO_EV_DIR_RISING) | - IIO_EV_BIT(IIO_EV_TYPE_MAG_ADAPTIVE, IIO_EV_DIR_FALLING) + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_AVERAGE_RAW), + .event_spec = ad7150_events, + .num_event_specs = ARRAY_SIZE(ad7150_events), }, }; @@ -549,18 +586,16 @@ static const struct iio_info ad7150_info = { * device probe and remove */ -static int __devinit ad7150_probe(struct i2c_client *client, +static int ad7150_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret; struct ad7150_chip_info *chip; struct iio_dev *indio_dev; - indio_dev = iio_allocate_device(sizeof(*chip)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); + if (!indio_dev) + return -ENOMEM; chip = iio_priv(indio_dev); mutex_init(&chip->state_lock); /* this is only used for device removal purposes */ @@ -579,63 +614,47 @@ static int __devinit ad7150_probe(struct i2c_client *client, indio_dev->modes = INDIO_DIRECT_MODE; if (client->irq) { - ret = request_threaded_irq(client->irq, + ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, &ad7150_event_handler, IRQF_TRIGGER_RISING | - IRQF_TRIGGER_FALLING, + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, "ad7150_irq1", indio_dev); if (ret) - goto error_free_dev; + return ret; } if (client->dev.platform_data) { - ret = request_threaded_irq(*(unsigned int *) + ret = devm_request_threaded_irq(&client->dev, *(unsigned int *) client->dev.platform_data, NULL, &ad7150_event_handler, IRQF_TRIGGER_RISING | - IRQF_TRIGGER_FALLING, + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, "ad7150_irq2", indio_dev); if (ret) - goto error_free_irq; + return ret; } ret = iio_device_register(indio_dev); if (ret) - goto error_free_irq2; + return ret; dev_info(&client->dev, "%s capacitive sensor registered,irq: %d\n", id->name, client->irq); return 0; -error_free_irq2: - if (client->dev.platform_data) - free_irq(*(unsigned int *)client->dev.platform_data, - indio_dev); -error_free_irq: - if (client->irq) - free_irq(client->irq, indio_dev); -error_free_dev: - iio_free_device(indio_dev); -error_ret: - return ret; } -static int __devexit ad7150_remove(struct i2c_client *client) +static int ad7150_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); iio_device_unregister(indio_dev); - if (client->irq) - free_irq(client->irq, indio_dev); - - if (client->dev.platform_data) - free_irq(*(unsigned int *)client->dev.platform_data, indio_dev); - - iio_free_device(indio_dev); return 0; } @@ -654,7 +673,7 @@ static struct i2c_driver ad7150_driver = { .name = "ad7150", }, .probe = ad7150_probe, - .remove = __devexit_p(ad7150_remove), + .remove = ad7150_remove, .id_table = ad7150_id, }; module_i2c_driver(ad7150_driver); diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c index fdb83c35e6d..87110d940e9 100644 --- a/drivers/staging/iio/cdc/ad7152.c +++ b/drivers/staging/iio/cdc/ad7152.c @@ -15,8 +15,8 @@ #include <linux/module.h> #include <linux/delay.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> /* * TODO: Check compliance of calibbias with abi (units) @@ -78,7 +78,7 @@ enum { }; /* - * struct ad7152_chip_info - chip specifc information + * struct ad7152_chip_info - chip specific information */ struct ad7152_chip_info { @@ -97,7 +97,7 @@ static inline ssize_t ad7152_start_calib(struct device *dev, size_t len, u8 regval) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7152_chip_info *chip = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); bool doit; @@ -169,7 +169,7 @@ static ssize_t ad7152_show_filter_rate_setup(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7152_chip_info *chip = iio_priv(indio_dev); return sprintf(buf, "%d\n", @@ -181,7 +181,7 @@ static ssize_t ad7152_store_filter_rate_setup(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7152_chip_info *chip = iio_priv(indio_dev); u8 data; int ret, i; @@ -329,7 +329,7 @@ static int ad7152_read_raw(struct iio_dev *indio_dev, mutex_lock(&indio_dev->mlock); switch (mask) { - case 0: + case IIO_CHAN_INFO_RAW: /* First set whether in differential mode */ regval = chip->setup[chan->channel]; @@ -405,7 +405,7 @@ static int ad7152_read_raw(struct iio_dev *indio_dev, break; default: ret = -EINVAL; - }; + } out: mutex_unlock(&indio_dev->mlock); return ret; @@ -436,52 +436,54 @@ static const struct iio_chan_spec ad7152_channels[] = { .type = IIO_CAPACITANCE, .indexed = 1, .channel = 0, - .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | + BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_SCALE), }, { .type = IIO_CAPACITANCE, .differential = 1, .indexed = 1, .channel = 0, .channel2 = 2, - .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | + BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_SCALE), }, { .type = IIO_CAPACITANCE, .indexed = 1, .channel = 1, - .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | + BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_SCALE), }, { .type = IIO_CAPACITANCE, .differential = 1, .indexed = 1, .channel = 1, .channel2 = 3, - .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | + BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_SCALE), } }; /* * device probe and remove */ -static int __devinit ad7152_probe(struct i2c_client *client, +static int ad7152_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret = 0; struct ad7152_chip_info *chip; struct iio_dev *indio_dev; - indio_dev = iio_allocate_device(sizeof(*chip)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); + if (!indio_dev) + return -ENOMEM; chip = iio_priv(indio_dev); /* this is only used for device removal purposes */ i2c_set_clientdata(client, indio_dev); @@ -502,24 +504,18 @@ static int __devinit ad7152_probe(struct i2c_client *client, ret = iio_device_register(indio_dev); if (ret) - goto error_free_dev; + return ret; dev_err(&client->dev, "%s capacitive sensor registered\n", id->name); return 0; - -error_free_dev: - iio_free_device(indio_dev); -error_ret: - return ret; } -static int __devexit ad7152_remove(struct i2c_client *client) +static int ad7152_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); iio_device_unregister(indio_dev); - iio_free_device(indio_dev); return 0; } @@ -537,7 +533,7 @@ static struct i2c_driver ad7152_driver = { .name = KBUILD_MODNAME, }, .probe = ad7152_probe, - .remove = __devexit_p(ad7152_remove), + .remove = ad7152_remove, .id_table = ad7152_id, }; module_i2c_driver(ad7152_driver); diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 40b8512cbc3..e6e9eaa9eab 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -16,8 +16,8 @@ #include <linux/module.h> #include <linux/stat.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #include "ad7746.h" @@ -91,7 +91,7 @@ #define AD7746_CAPDAC_DACP(x) ((x) & 0x7F) /* - * struct ad7746_chip_info - chip specifc information + * struct ad7746_chip_info - chip specific information */ struct ad7746_chip_info { @@ -105,6 +105,11 @@ struct ad7746_chip_info { u8 vt_setup; u8 capdac[2][2]; s8 capdac_set; + + union { + __be32 d32; + u8 d8[4]; + } data ____cacheline_aligned; }; enum ad7746_chan { @@ -123,7 +128,8 @@ static const struct iio_chan_spec ad7746_channels[] = { .type = IIO_VOLTAGE, .indexed = 1, .channel = 0, - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), .address = AD7746_REG_VT_DATA_HIGH << 8 | AD7746_VTSETUP_VTMD_EXT_VIN, }, @@ -132,7 +138,8 @@ static const struct iio_chan_spec ad7746_channels[] = { .indexed = 1, .channel = 1, .extend_name = "supply", - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), .address = AD7746_REG_VT_DATA_HIGH << 8 | AD7746_VTSETUP_VTMD_VDD_MON, }, @@ -140,7 +147,7 @@ static const struct iio_chan_spec ad7746_channels[] = { .type = IIO_TEMP, .indexed = 1, .channel = 0, - .processed_val = IIO_PROCESSED, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), .address = AD7746_REG_VT_DATA_HIGH << 8 | AD7746_VTSETUP_VTMD_INT_TEMP, }, @@ -148,7 +155,7 @@ static const struct iio_chan_spec ad7746_channels[] = { .type = IIO_TEMP, .indexed = 1, .channel = 1, - .processed_val = IIO_PROCESSED, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), .address = AD7746_REG_VT_DATA_HIGH << 8 | AD7746_VTSETUP_VTMD_EXT_TEMP, }, @@ -156,10 +163,10 @@ static const struct iio_chan_spec ad7746_channels[] = { .type = IIO_CAPACITANCE, .indexed = 1, .channel = 0, - .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | - IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT | - IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_SCALE), .address = AD7746_REG_CAP_DATA_HIGH << 8, }, [CIN1_DIFF] = { @@ -168,10 +175,10 @@ static const struct iio_chan_spec ad7746_channels[] = { .indexed = 1, .channel = 0, .channel2 = 2, - .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | - IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT | - IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_SCALE), .address = AD7746_REG_CAP_DATA_HIGH << 8 | AD7746_CAPSETUP_CAPDIFF }, @@ -179,10 +186,10 @@ static const struct iio_chan_spec ad7746_channels[] = { .type = IIO_CAPACITANCE, .indexed = 1, .channel = 1, - .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | - IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT | - IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_SCALE), .address = AD7746_REG_CAP_DATA_HIGH << 8 | AD7746_CAPSETUP_CIN2, }, @@ -192,10 +199,10 @@ static const struct iio_chan_spec ad7746_channels[] = { .indexed = 1, .channel = 1, .channel2 = 3, - .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | - IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT | - IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_SCALE), .address = AD7746_REG_CAP_DATA_HIGH << 8 | AD7746_CAPSETUP_CAPDIFF | AD7746_CAPSETUP_CIN2, } @@ -280,7 +287,7 @@ static inline ssize_t ad7746_start_calib(struct device *dev, size_t len, u8 regval) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7746_chip_info *chip = iio_priv(indio_dev); bool doit; int ret, timeout = 10; @@ -319,7 +326,7 @@ static ssize_t ad7746_start_offset_calib(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); int ret = ad7746_select_channel(indio_dev, &ad7746_channels[to_iio_dev_attr(attr)->address]); if (ret < 0) @@ -334,7 +341,7 @@ static ssize_t ad7746_start_gain_calib(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); int ret = ad7746_select_channel(indio_dev, &ad7746_channels[to_iio_dev_attr(attr)->address]); if (ret < 0) @@ -359,7 +366,7 @@ static ssize_t ad7746_show_cap_filter_rate_setup(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7746_chip_info *chip = iio_priv(indio_dev); return sprintf(buf, "%d\n", ad7746_cap_filter_rate_table[ @@ -371,7 +378,7 @@ static ssize_t ad7746_store_cap_filter_rate_setup(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7746_chip_info *chip = iio_priv(indio_dev); u8 data; int ret, i; @@ -399,7 +406,7 @@ static ssize_t ad7746_show_vt_filter_rate_setup(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7746_chip_info *chip = iio_priv(indio_dev); return sprintf(buf, "%d\n", ad7746_vt_filter_rate_table[ @@ -411,7 +418,7 @@ static ssize_t ad7746_store_vt_filter_rate_setup(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7746_chip_info *chip = iio_priv(indio_dev); u8 data; int ret, i; @@ -564,15 +571,11 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, int ret, delay; u8 regval, reg; - union { - u32 d32; - u8 d8[4]; - } data; - mutex_lock(&indio_dev->mlock); switch (mask) { - case 0: + case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_PROCESSED: ret = ad7746_select_channel(indio_dev, chan); if (ret < 0) goto out; @@ -588,12 +591,12 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, /* Now read the actual register */ ret = i2c_smbus_read_i2c_block_data(chip->client, - chan->address >> 8, 3, &data.d8[1]); + chan->address >> 8, 3, &chip->data.d8[1]); if (ret < 0) goto out; - *val = (be32_to_cpu(data.d32) & 0xFFFFFF) - 0x800000; + *val = (be32_to_cpu(chip->data.d32) & 0xFFFFFF) - 0x800000; switch (chan->type) { case IIO_TEMP: @@ -653,24 +656,25 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, switch (chan->type) { case IIO_CAPACITANCE: /* 8.192pf / 2^24 */ - *val2 = 488; *val = 0; + *val2 = 488; + ret = IIO_VAL_INT_PLUS_NANO; break; case IIO_VOLTAGE: /* 1170mV / 2^23 */ - *val2 = 139475; - *val = 0; + *val = 1170; + *val2 = 23; + ret = IIO_VAL_FRACTIONAL_LOG2; break; default: - ret = -EINVAL; - goto out; + ret = -EINVAL; + break; } - ret = IIO_VAL_INT_PLUS_NANO; break; default: ret = -EINVAL; - }; + } out: mutex_unlock(&indio_dev->mlock); return ret; @@ -687,7 +691,7 @@ static const struct iio_info ad7746_info = { * device probe and remove */ -static int __devinit ad7746_probe(struct i2c_client *client, +static int ad7746_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct ad7746_platform_data *pdata = client->dev.platform_data; @@ -696,11 +700,9 @@ static int __devinit ad7746_probe(struct i2c_client *client, int ret = 0; unsigned char regval = 0; - indio_dev = iio_allocate_device(sizeof(*chip)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); + if (!indio_dev) + return -ENOMEM; chip = iio_priv(indio_dev); /* this is only used for device removal purposes */ i2c_set_clientdata(client, indio_dev); @@ -745,28 +747,22 @@ static int __devinit ad7746_probe(struct i2c_client *client, ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_EXC_SETUP, regval); if (ret < 0) - goto error_free_dev; + return ret; ret = iio_device_register(indio_dev); if (ret) - goto error_free_dev; + return ret; dev_info(&client->dev, "%s capacitive sensor registered\n", id->name); return 0; - -error_free_dev: - iio_free_device(indio_dev); -error_ret: - return ret; } -static int __devexit ad7746_remove(struct i2c_client *client) +static int ad7746_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); iio_device_unregister(indio_dev); - iio_free_device(indio_dev); return 0; } @@ -785,7 +781,7 @@ static struct i2c_driver ad7746_driver = { .name = KBUILD_MODNAME, }, .probe = ad7746_probe, - .remove = __devexit_p(ad7746_remove), + .remove = ad7746_remove, .id_table = ad7746_id, }; module_i2c_driver(ad7746_driver); diff --git a/drivers/staging/iio/dac/Kconfig b/drivers/staging/iio/dac/Kconfig deleted file mode 100644 index 13e27979df2..00000000000 --- a/drivers/staging/iio/dac/Kconfig +++ /dev/null @@ -1,120 +0,0 @@ -# -# DAC drivers -# -menu "Digital to analog converters" - -config AD5064 - tristate "Analog Devices AD5064/64-1/44/24 DAC driver" - depends on SPI - help - Say yes here to build support for Analog Devices AD5064, AD5064-1, - AD5044, AD5024 Digital to Analog Converter. - - To compile this driver as a module, choose M here: the - module will be called ad5064. - -config AD5360 - tristate "Analog Devices Analog Devices AD5360/61/62/63/70/71/73 DAC driver" - depends on SPI - help - Say yes here to build support for Analog Devices AD5360, AD5361, - AD5362, AD5363, AD5370, AD5371, AD5373 multi-channel - Digital to Analog Converters (DAC). - - To compile this driver as module choose M here: the module will be called - ad5360. - -config AD5380 - tristate "Analog Devices AD5380/81/82/83/84/90/91/92 DAC driver" - depends on (SPI_MASTER || I2C) - select REGMAP_I2C if I2C - select REGMAP_SPI if SPI_MASTER - help - Say yes here to build support for Analog Devices AD5380, AD5381, - AD5382, AD5383, AD5384, AD5390, AD5391, AD5392 multi-channel - Digital to Analog Converters (DAC). - - To compile this driver as module choose M here: the module will be called - ad5380. - -config AD5421 - tristate "Analog Devices AD5421 DAC driver" - depends on SPI - help - Say yes here to build support for Analog Devices AD5421 loop-powered - digital-to-analog convertors (DAC). - - To compile this driver as module choose M here: the module will be called - ad5421. - -config AD5624R_SPI - tristate "Analog Devices AD5624/44/64R DAC spi driver" - depends on SPI - help - Say yes here to build support for Analog Devices AD5624R, AD5644R and - AD5664R converters (DAC). This driver uses the common SPI interface. - -config AD5446 - tristate "Analog Devices AD5444/6, AD5620/40/60 and AD5542A/12A DAC SPI driver" - depends on SPI - help - Say yes here to build support for Analog Devices AD5444, AD5446, - AD5512A, AD5542A, AD5543, AD5553, AD5601, AD5611, AD5620, AD5621, - AD5640, AD5660, AD5662 DACs. - - To compile this driver as a module, choose M here: the - module will be called ad5446. - -config AD5504 - tristate "Analog Devices AD5504/AD5501 DAC SPI driver" - depends on SPI - help - Say yes here to build support for Analog Devices AD5504, AD5501, - High Voltage Digital to Analog Converter. - - To compile this driver as a module, choose M here: the - module will be called ad5504. - -config AD5764 - tristate "Analog Devices AD5764/64R/44/44R DAC driver" - depends on SPI_MASTER - help - Say yes here to build support for Analog Devices AD5764, AD5764R, AD5744, - AD5744R Digital to Analog Converter. - - To compile this driver as a module, choose M here: the - module will be called ad5764. - -config AD5791 - tristate "Analog Devices AD5760/AD5780/AD5781/AD5790/AD5791 DAC SPI driver" - depends on SPI - help - Say yes here to build support for Analog Devices AD5760, AD5780, - AD5781, AD5790, AD5791 High Resolution Voltage Output Digital to - Analog Converter. - - To compile this driver as a module, choose M here: the - module will be called ad5791. - -config AD5686 - tristate "Analog Devices AD5686R/AD5685R/AD5684R DAC SPI driver" - depends on SPI - help - Say yes here to build support for Analog Devices AD5686R, AD5685R, - AD5684R, AD5791 Voltage Output Digital to - Analog Converter. - - To compile this driver as a module, choose M here: the - module will be called ad5686. - -config MAX517 - tristate "Maxim MAX517/518/519 DAC driver" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for the Maxim chips MAX517, - MAX518 and MAX519 (I2C 8-Bit DACs with rail-to-rail outputs). - - This driver can also be built as a module. If so, the module - will be called max517. - -endmenu diff --git a/drivers/staging/iio/dac/Makefile b/drivers/staging/iio/dac/Makefile deleted file mode 100644 index 8ab1d264aab..00000000000 --- a/drivers/staging/iio/dac/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Makefile for industrial I/O DAC drivers -# - -obj-$(CONFIG_AD5360) += ad5360.o -obj-$(CONFIG_AD5380) += ad5380.o -obj-$(CONFIG_AD5421) += ad5421.o -obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o -obj-$(CONFIG_AD5064) += ad5064.o -obj-$(CONFIG_AD5504) += ad5504.o -obj-$(CONFIG_AD5446) += ad5446.o -obj-$(CONFIG_AD5764) += ad5764.o -obj-$(CONFIG_AD5791) += ad5791.o -obj-$(CONFIG_AD5686) += ad5686.o -obj-$(CONFIG_MAX517) += max517.o diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c deleted file mode 100644 index 049a855039c..00000000000 --- a/drivers/staging/iio/dac/ad5064.c +++ /dev/null @@ -1,452 +0,0 @@ -/* - * AD5064, AD5064-1, AD5044, AD5024 Digital to analog converters driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include <linux/device.h> -#include <linux/err.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/regulator/consumer.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "dac.h" - -#define AD5064_DAC_CHANNELS 4 - -#define AD5064_ADDR(x) ((x) << 20) -#define AD5064_CMD(x) ((x) << 24) - -#define AD5064_ADDR_DAC(chan) (chan) -#define AD5064_ADDR_ALL_DAC 0xF - -#define AD5064_CMD_WRITE_INPUT_N 0x0 -#define AD5064_CMD_UPDATE_DAC_N 0x1 -#define AD5064_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2 -#define AD5064_CMD_WRITE_INPUT_N_UPDATE_N 0x3 -#define AD5064_CMD_POWERDOWN_DAC 0x4 -#define AD5064_CMD_CLEAR 0x5 -#define AD5064_CMD_LDAC_MASK 0x6 -#define AD5064_CMD_RESET 0x7 -#define AD5064_CMD_DAISY_CHAIN_ENABLE 0x8 - -#define AD5064_LDAC_PWRDN_NONE 0x0 -#define AD5064_LDAC_PWRDN_1K 0x1 -#define AD5064_LDAC_PWRDN_100K 0x2 -#define AD5064_LDAC_PWRDN_3STATE 0x3 - -/** - * struct ad5064_chip_info - chip specific information - * @shared_vref: whether the vref supply is shared between channels - * @channel: channel specification -*/ - -struct ad5064_chip_info { - bool shared_vref; - struct iio_chan_spec channel[AD5064_DAC_CHANNELS]; -}; - -/** - * struct ad5064_state - driver instance specific data - * @spi: spi_device - * @chip_info: chip model specific constants, available modes etc - * @vref_reg: vref supply regulators - * @pwr_down: whether channel is powered down - * @pwr_down_mode: channel's current power down mode - * @dac_cache: current DAC raw value (chip does not support readback) - * @data: spi transfer buffers - */ - -struct ad5064_state { - struct spi_device *spi; - const struct ad5064_chip_info *chip_info; - struct regulator_bulk_data vref_reg[AD5064_DAC_CHANNELS]; - bool pwr_down[AD5064_DAC_CHANNELS]; - u8 pwr_down_mode[AD5064_DAC_CHANNELS]; - unsigned int dac_cache[AD5064_DAC_CHANNELS]; - - /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - */ - __be32 data ____cacheline_aligned; -}; - -enum ad5064_type { - ID_AD5024, - ID_AD5044, - ID_AD5064, - ID_AD5064_1, -}; - -#define AD5064_CHANNEL(chan, bits) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .output = 1, \ - .channel = (chan), \ - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ - .address = AD5064_ADDR_DAC(chan), \ - .scan_type = IIO_ST('u', (bits), 16, 20 - (bits)) \ -} - -static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { - [ID_AD5024] = { - .shared_vref = false, - .channel[0] = AD5064_CHANNEL(0, 12), - .channel[1] = AD5064_CHANNEL(1, 12), - .channel[2] = AD5064_CHANNEL(2, 12), - .channel[3] = AD5064_CHANNEL(3, 12), - }, - [ID_AD5044] = { - .shared_vref = false, - .channel[0] = AD5064_CHANNEL(0, 14), - .channel[1] = AD5064_CHANNEL(1, 14), - .channel[2] = AD5064_CHANNEL(2, 14), - .channel[3] = AD5064_CHANNEL(3, 14), - }, - [ID_AD5064] = { - .shared_vref = false, - .channel[0] = AD5064_CHANNEL(0, 16), - .channel[1] = AD5064_CHANNEL(1, 16), - .channel[2] = AD5064_CHANNEL(2, 16), - .channel[3] = AD5064_CHANNEL(3, 16), - }, - [ID_AD5064_1] = { - .shared_vref = true, - .channel[0] = AD5064_CHANNEL(0, 16), - .channel[1] = AD5064_CHANNEL(1, 16), - .channel[2] = AD5064_CHANNEL(2, 16), - .channel[3] = AD5064_CHANNEL(3, 16), - }, -}; - -static int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd, - unsigned int addr, unsigned int val, unsigned int shift) -{ - val <<= shift; - - st->data = cpu_to_be32(AD5064_CMD(cmd) | AD5064_ADDR(addr) | val); - - return spi_write(st->spi, &st->data, sizeof(st->data)); -} - -static int ad5064_sync_powerdown_mode(struct ad5064_state *st, - unsigned int channel) -{ - unsigned int val; - int ret; - - val = (0x1 << channel); - - if (st->pwr_down[channel]) - val |= st->pwr_down_mode[channel] << 8; - - ret = ad5064_spi_write(st, AD5064_CMD_POWERDOWN_DAC, 0, val, 0); - - return ret; -} - -static const char ad5064_powerdown_modes[][15] = { - [AD5064_LDAC_PWRDN_NONE] = "", - [AD5064_LDAC_PWRDN_1K] = "1kohm_to_gnd", - [AD5064_LDAC_PWRDN_100K] = "100kohm_to_gnd", - [AD5064_LDAC_PWRDN_3STATE] = "three_state", -}; - -static ssize_t ad5064_read_powerdown_mode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5064_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%s\n", - ad5064_powerdown_modes[st->pwr_down_mode[this_attr->address]]); -} - -static ssize_t ad5064_write_powerdown_mode(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) -{ - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5064_state *st = iio_priv(indio_dev); - unsigned int mode, i; - int ret; - - mode = 0; - - for (i = 1; i < ARRAY_SIZE(ad5064_powerdown_modes); ++i) { - if (sysfs_streq(buf, ad5064_powerdown_modes[i])) { - mode = i; - break; - } - } - if (mode == 0) - return -EINVAL; - - mutex_lock(&indio_dev->mlock); - st->pwr_down_mode[this_attr->address] = mode; - - ret = ad5064_sync_powerdown_mode(st, this_attr->address); - mutex_unlock(&indio_dev->mlock); - - return ret ? ret : len; -} - -static ssize_t ad5064_read_dac_powerdown(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5064_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - return sprintf(buf, "%d\n", st->pwr_down[this_attr->address]); -} - -static ssize_t ad5064_write_dac_powerdown(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5064_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - bool pwr_down; - int ret; - - ret = strtobool(buf, &pwr_down); - if (ret) - return ret; - - mutex_lock(&indio_dev->mlock); - st->pwr_down[this_attr->address] = pwr_down; - - ret = ad5064_sync_powerdown_mode(st, this_attr->address); - mutex_unlock(&indio_dev->mlock); - return ret ? ret : len; -} - -static IIO_CONST_ATTR(out_voltage_powerdown_mode_available, - "1kohm_to_gnd 100kohm_to_gnd three_state"); - -#define IIO_DEV_ATTR_DAC_POWERDOWN_MODE(_chan) \ - IIO_DEVICE_ATTR(out_voltage##_chan##_powerdown_mode, \ - S_IRUGO | S_IWUSR, \ - ad5064_read_powerdown_mode, \ - ad5064_write_powerdown_mode, _chan); - -#define IIO_DEV_ATTR_DAC_POWERDOWN(_chan) \ - IIO_DEVICE_ATTR(out_voltage##_chan##_powerdown, \ - S_IRUGO | S_IWUSR, \ - ad5064_read_dac_powerdown, \ - ad5064_write_dac_powerdown, _chan) - -static IIO_DEV_ATTR_DAC_POWERDOWN(0); -static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(0); -static IIO_DEV_ATTR_DAC_POWERDOWN(1); -static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(1); -static IIO_DEV_ATTR_DAC_POWERDOWN(2); -static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(2); -static IIO_DEV_ATTR_DAC_POWERDOWN(3); -static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(3); - -static struct attribute *ad5064_attributes[] = { - &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage1_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage2_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage3_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage0_powerdown_mode.dev_attr.attr, - &iio_dev_attr_out_voltage1_powerdown_mode.dev_attr.attr, - &iio_dev_attr_out_voltage2_powerdown_mode.dev_attr.attr, - &iio_dev_attr_out_voltage3_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad5064_attribute_group = { - .attrs = ad5064_attributes, -}; - -static int ad5064_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - struct ad5064_state *st = iio_priv(indio_dev); - unsigned int vref; - int scale_uv; - - switch (m) { - case 0: - *val = st->dac_cache[chan->channel]; - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - vref = st->chip_info->shared_vref ? 0 : chan->channel; - scale_uv = regulator_get_voltage(st->vref_reg[vref].consumer); - if (scale_uv < 0) - return scale_uv; - - scale_uv = (scale_uv * 100) >> chan->scan_type.realbits; - *val = scale_uv / 100000; - *val2 = (scale_uv % 100000) * 10; - return IIO_VAL_INT_PLUS_MICRO; - default: - break; - } - return -EINVAL; -} - -static int ad5064_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int val, int val2, long mask) -{ - struct ad5064_state *st = iio_priv(indio_dev); - int ret; - - switch (mask) { - case 0: - if (val > (1 << chan->scan_type.realbits) || val < 0) - return -EINVAL; - - mutex_lock(&indio_dev->mlock); - ret = ad5064_spi_write(st, AD5064_CMD_WRITE_INPUT_N_UPDATE_N, - chan->address, val, chan->scan_type.shift); - if (ret == 0) - st->dac_cache[chan->channel] = val; - mutex_unlock(&indio_dev->mlock); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static const struct iio_info ad5064_info = { - .read_raw = ad5064_read_raw, - .write_raw = ad5064_write_raw, - .attrs = &ad5064_attribute_group, - .driver_module = THIS_MODULE, -}; - -static inline unsigned int ad5064_num_vref(struct ad5064_state *st) -{ - return st->chip_info->shared_vref ? 1 : AD5064_DAC_CHANNELS; -} - -static const char * const ad5064_vref_names[] = { - "vrefA", - "vrefB", - "vrefC", - "vrefD", -}; - -static const char * const ad5064_vref_name(struct ad5064_state *st, - unsigned int vref) -{ - return st->chip_info->shared_vref ? "vref" : ad5064_vref_names[vref]; -} - -static int __devinit ad5064_probe(struct spi_device *spi) -{ - enum ad5064_type type = spi_get_device_id(spi)->driver_data; - struct iio_dev *indio_dev; - struct ad5064_state *st; - unsigned int i; - int ret; - - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) - return -ENOMEM; - - st = iio_priv(indio_dev); - spi_set_drvdata(spi, indio_dev); - - st->chip_info = &ad5064_chip_info_tbl[type]; - st->spi = spi; - - for (i = 0; i < ad5064_num_vref(st); ++i) - st->vref_reg[i].supply = ad5064_vref_name(st, i); - - ret = regulator_bulk_get(&st->spi->dev, ad5064_num_vref(st), - st->vref_reg); - if (ret) - goto error_free; - - ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg); - if (ret) - goto error_free_reg; - - for (i = 0; i < AD5064_DAC_CHANNELS; ++i) { - st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K; - st->dac_cache[i] = 0x8000; - } - - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->info = &ad5064_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = st->chip_info->channel; - indio_dev->num_channels = AD5064_DAC_CHANNELS; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_disable_reg; - - return 0; - -error_disable_reg: - regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); -error_free_reg: - regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); -error_free: - iio_free_device(indio_dev); - - return ret; -} - - -static int __devexit ad5064_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad5064_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); - regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); - - iio_free_device(indio_dev); - - return 0; -} - -static const struct spi_device_id ad5064_id[] = { - {"ad5024", ID_AD5024}, - {"ad5044", ID_AD5044}, - {"ad5064", ID_AD5064}, - {"ad5064-1", ID_AD5064_1}, - {} -}; -MODULE_DEVICE_TABLE(spi, ad5064_id); - -static struct spi_driver ad5064_driver = { - .driver = { - .name = "ad5064", - .owner = THIS_MODULE, - }, - .probe = ad5064_probe, - .remove = __devexit_p(ad5064_remove), - .id_table = ad5064_id, -}; -module_spi_driver(ad5064_driver); - -MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); -MODULE_DESCRIPTION("Analog Devices AD5064/64-1/44/24 DAC"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/dac/ad5360.c b/drivers/staging/iio/dac/ad5360.c deleted file mode 100644 index 710b256affc..00000000000 --- a/drivers/staging/iio/dac/ad5360.c +++ /dev/null @@ -1,570 +0,0 @@ -/* - * Analog devices AD5360, AD5361, AD5362, AD5363, AD5370, AD5371, AD5373 - * multi-channel Digital to Analog Converters driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include <linux/device.h> -#include <linux/err.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/regulator/consumer.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "dac.h" - -#define AD5360_CMD(x) ((x) << 22) -#define AD5360_ADDR(x) ((x) << 16) - -#define AD5360_READBACK_TYPE(x) ((x) << 13) -#define AD5360_READBACK_ADDR(x) ((x) << 7) - -#define AD5360_CHAN_ADDR(chan) ((chan) + 0x8) - -#define AD5360_CMD_WRITE_DATA 0x3 -#define AD5360_CMD_WRITE_OFFSET 0x2 -#define AD5360_CMD_WRITE_GAIN 0x1 -#define AD5360_CMD_SPECIAL_FUNCTION 0x0 - -/* Special function register addresses */ -#define AD5360_REG_SF_NOP 0x0 -#define AD5360_REG_SF_CTRL 0x1 -#define AD5360_REG_SF_OFS(x) (0x2 + (x)) -#define AD5360_REG_SF_READBACK 0x5 - -#define AD5360_SF_CTRL_PWR_DOWN BIT(0) - -#define AD5360_READBACK_X1A 0x0 -#define AD5360_READBACK_X1B 0x1 -#define AD5360_READBACK_OFFSET 0x2 -#define AD5360_READBACK_GAIN 0x3 -#define AD5360_READBACK_SF 0x4 - - -/** - * struct ad5360_chip_info - chip specific information - * @channel_template: channel specification template - * @num_channels: number of channels - * @channels_per_group: number of channels per group - * @num_vrefs: number of vref supplies for the chip -*/ - -struct ad5360_chip_info { - struct iio_chan_spec channel_template; - unsigned int num_channels; - unsigned int channels_per_group; - unsigned int num_vrefs; -}; - -/** - * struct ad5360_state - driver instance specific data - * @spi: spi_device - * @chip_info: chip model specific constants, available modes etc - * @vref_reg: vref supply regulators - * @ctrl: control register cache - * @data: spi transfer buffers - */ - -struct ad5360_state { - struct spi_device *spi; - const struct ad5360_chip_info *chip_info; - struct regulator_bulk_data vref_reg[3]; - unsigned int ctrl; - - /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - */ - union { - __be32 d32; - u8 d8[4]; - } data[2] ____cacheline_aligned; -}; - -enum ad5360_type { - ID_AD5360, - ID_AD5361, - ID_AD5362, - ID_AD5363, - ID_AD5370, - ID_AD5371, - ID_AD5372, - ID_AD5373, -}; - -#define AD5360_CHANNEL(bits) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .output = 1, \ - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \ - IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \ - IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \ - .scan_type = IIO_ST('u', (bits), 16, 16 - (bits)) \ -} - -static const struct ad5360_chip_info ad5360_chip_info_tbl[] = { - [ID_AD5360] = { - .channel_template = AD5360_CHANNEL(16), - .num_channels = 16, - .channels_per_group = 8, - .num_vrefs = 2, - }, - [ID_AD5361] = { - .channel_template = AD5360_CHANNEL(14), - .num_channels = 16, - .channels_per_group = 8, - .num_vrefs = 2, - }, - [ID_AD5362] = { - .channel_template = AD5360_CHANNEL(16), - .num_channels = 8, - .channels_per_group = 4, - .num_vrefs = 2, - }, - [ID_AD5363] = { - .channel_template = AD5360_CHANNEL(14), - .num_channels = 8, - .channels_per_group = 4, - .num_vrefs = 2, - }, - [ID_AD5370] = { - .channel_template = AD5360_CHANNEL(16), - .num_channels = 40, - .channels_per_group = 8, - .num_vrefs = 2, - }, - [ID_AD5371] = { - .channel_template = AD5360_CHANNEL(14), - .num_channels = 40, - .channels_per_group = 8, - .num_vrefs = 3, - }, - [ID_AD5372] = { - .channel_template = AD5360_CHANNEL(16), - .num_channels = 32, - .channels_per_group = 8, - .num_vrefs = 2, - }, - [ID_AD5373] = { - .channel_template = AD5360_CHANNEL(14), - .num_channels = 32, - .channels_per_group = 8, - .num_vrefs = 2, - }, -}; - -static unsigned int ad5360_get_channel_vref_index(struct ad5360_state *st, - unsigned int channel) -{ - unsigned int i; - - /* The first groups have their own vref, while the remaining groups - * share the last vref */ - i = channel / st->chip_info->channels_per_group; - if (i >= st->chip_info->num_vrefs) - i = st->chip_info->num_vrefs - 1; - - return i; -} - -static int ad5360_get_channel_vref(struct ad5360_state *st, - unsigned int channel) -{ - unsigned int i = ad5360_get_channel_vref_index(st, channel); - - return regulator_get_voltage(st->vref_reg[i].consumer); -} - - -static int ad5360_write_unlocked(struct iio_dev *indio_dev, - unsigned int cmd, unsigned int addr, unsigned int val, - unsigned int shift) -{ - struct ad5360_state *st = iio_priv(indio_dev); - - val <<= shift; - val |= AD5360_CMD(cmd) | AD5360_ADDR(addr); - st->data[0].d32 = cpu_to_be32(val); - - return spi_write(st->spi, &st->data[0].d8[1], 3); -} - -static int ad5360_write(struct iio_dev *indio_dev, unsigned int cmd, - unsigned int addr, unsigned int val, unsigned int shift) -{ - int ret; - - mutex_lock(&indio_dev->mlock); - ret = ad5360_write_unlocked(indio_dev, cmd, addr, val, shift); - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static int ad5360_read(struct iio_dev *indio_dev, unsigned int type, - unsigned int addr) -{ - struct ad5360_state *st = iio_priv(indio_dev); - struct spi_message m; - int ret; - struct spi_transfer t[] = { - { - .tx_buf = &st->data[0].d8[1], - .len = 3, - .cs_change = 1, - }, { - .rx_buf = &st->data[1].d8[1], - .len = 3, - }, - }; - - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - spi_message_add_tail(&t[1], &m); - - mutex_lock(&indio_dev->mlock); - - st->data[0].d32 = cpu_to_be32(AD5360_CMD(AD5360_CMD_SPECIAL_FUNCTION) | - AD5360_ADDR(AD5360_REG_SF_READBACK) | - AD5360_READBACK_TYPE(type) | - AD5360_READBACK_ADDR(addr)); - - ret = spi_sync(st->spi, &m); - if (ret >= 0) - ret = be32_to_cpu(st->data[1].d32) & 0xffff; - - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static ssize_t ad5360_read_dac_powerdown(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5360_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", (bool)(st->ctrl & AD5360_SF_CTRL_PWR_DOWN)); -} - -static int ad5360_update_ctrl(struct iio_dev *indio_dev, unsigned int set, - unsigned int clr) -{ - struct ad5360_state *st = iio_priv(indio_dev); - unsigned int ret; - - mutex_lock(&indio_dev->mlock); - - st->ctrl |= set; - st->ctrl &= ~clr; - - ret = ad5360_write_unlocked(indio_dev, AD5360_CMD_SPECIAL_FUNCTION, - AD5360_REG_SF_CTRL, st->ctrl, 0); - - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static ssize_t ad5360_write_dac_powerdown(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - bool pwr_down; - int ret; - - ret = strtobool(buf, &pwr_down); - if (ret) - return ret; - - if (pwr_down) - ret = ad5360_update_ctrl(indio_dev, AD5360_SF_CTRL_PWR_DOWN, 0); - else - ret = ad5360_update_ctrl(indio_dev, 0, AD5360_SF_CTRL_PWR_DOWN); - - return ret ? ret : len; -} - -static IIO_DEVICE_ATTR(out_voltage_powerdown, - S_IRUGO | S_IWUSR, - ad5360_read_dac_powerdown, - ad5360_write_dac_powerdown, 0); - -static struct attribute *ad5360_attributes[] = { - &iio_dev_attr_out_voltage_powerdown.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad5360_attribute_group = { - .attrs = ad5360_attributes, -}; - -static int ad5360_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct ad5360_state *st = iio_priv(indio_dev); - int max_val = (1 << chan->scan_type.realbits); - unsigned int ofs_index; - - switch (mask) { - case 0: - if (val >= max_val || val < 0) - return -EINVAL; - - return ad5360_write(indio_dev, AD5360_CMD_WRITE_DATA, - chan->address, val, chan->scan_type.shift); - - case IIO_CHAN_INFO_CALIBBIAS: - if (val >= max_val || val < 0) - return -EINVAL; - - return ad5360_write(indio_dev, AD5360_CMD_WRITE_OFFSET, - chan->address, val, chan->scan_type.shift); - - case IIO_CHAN_INFO_CALIBSCALE: - if (val >= max_val || val < 0) - return -EINVAL; - - return ad5360_write(indio_dev, AD5360_CMD_WRITE_GAIN, - chan->address, val, chan->scan_type.shift); - - case IIO_CHAN_INFO_OFFSET: - if (val <= -max_val || val > 0) - return -EINVAL; - - val = -val; - - /* offset is supposed to have the same scale as raw, but it - * is always 14bits wide, so on a chip where the raw value has - * more bits, we need to shift offset. */ - val >>= (chan->scan_type.realbits - 14); - - /* There is one DAC offset register per vref. Changing one - * channels offset will also change the offset for all other - * channels which share the same vref supply. */ - ofs_index = ad5360_get_channel_vref_index(st, chan->channel); - return ad5360_write(indio_dev, AD5360_CMD_SPECIAL_FUNCTION, - AD5360_REG_SF_OFS(ofs_index), val, 0); - default: - break; - } - - return -EINVAL; -} - -static int ad5360_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - struct ad5360_state *st = iio_priv(indio_dev); - unsigned int ofs_index; - int scale_uv; - int ret; - - switch (m) { - case 0: - ret = ad5360_read(indio_dev, AD5360_READBACK_X1A, - chan->address); - if (ret < 0) - return ret; - *val = ret >> chan->scan_type.shift; - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - /* vout = 4 * vref * dac_code */ - scale_uv = ad5360_get_channel_vref(st, chan->channel) * 4 * 100; - if (scale_uv < 0) - return scale_uv; - - scale_uv >>= (chan->scan_type.realbits); - *val = scale_uv / 100000; - *val2 = (scale_uv % 100000) * 10; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_CALIBBIAS: - ret = ad5360_read(indio_dev, AD5360_READBACK_OFFSET, - chan->address); - if (ret < 0) - return ret; - *val = ret; - return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBSCALE: - ret = ad5360_read(indio_dev, AD5360_READBACK_GAIN, - chan->address); - if (ret < 0) - return ret; - *val = ret; - return IIO_VAL_INT; - case IIO_CHAN_INFO_OFFSET: - ofs_index = ad5360_get_channel_vref_index(st, chan->channel); - ret = ad5360_read(indio_dev, AD5360_READBACK_SF, - AD5360_REG_SF_OFS(ofs_index)); - if (ret < 0) - return ret; - - ret <<= (chan->scan_type.realbits - 14); - *val = -ret; - return IIO_VAL_INT; - } - - return -EINVAL; -} - -static const struct iio_info ad5360_info = { - .read_raw = ad5360_read_raw, - .write_raw = ad5360_write_raw, - .attrs = &ad5360_attribute_group, - .driver_module = THIS_MODULE, -}; - -static const char * const ad5360_vref_name[] = { - "vref0", "vref1", "vref2" -}; - -static int __devinit ad5360_alloc_channels(struct iio_dev *indio_dev) -{ - struct ad5360_state *st = iio_priv(indio_dev); - struct iio_chan_spec *channels; - unsigned int i; - - channels = kcalloc(sizeof(struct iio_chan_spec), - st->chip_info->num_channels, GFP_KERNEL); - - if (!channels) - return -ENOMEM; - - for (i = 0; i < st->chip_info->num_channels; ++i) { - channels[i] = st->chip_info->channel_template; - channels[i].channel = i; - channels[i].address = AD5360_CHAN_ADDR(i); - } - - indio_dev->channels = channels; - - return 0; -} - -static int __devinit ad5360_probe(struct spi_device *spi) -{ - enum ad5360_type type = spi_get_device_id(spi)->driver_data; - struct iio_dev *indio_dev; - struct ad5360_state *st; - unsigned int i; - int ret; - - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - dev_err(&spi->dev, "Failed to allocate iio device\n"); - return -ENOMEM; - } - - st = iio_priv(indio_dev); - spi_set_drvdata(spi, indio_dev); - - st->chip_info = &ad5360_chip_info_tbl[type]; - st->spi = spi; - - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->info = &ad5360_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->num_channels = st->chip_info->num_channels; - - ret = ad5360_alloc_channels(indio_dev); - if (ret) { - dev_err(&spi->dev, "Failed to allocate channel spec: %d\n", ret); - goto error_free; - } - - for (i = 0; i < st->chip_info->num_vrefs; ++i) - st->vref_reg[i].supply = ad5360_vref_name[i]; - - ret = regulator_bulk_get(&st->spi->dev, st->chip_info->num_vrefs, - st->vref_reg); - if (ret) { - dev_err(&spi->dev, "Failed to request vref regulators: %d\n", ret); - goto error_free_channels; - } - - ret = regulator_bulk_enable(st->chip_info->num_vrefs, st->vref_reg); - if (ret) { - dev_err(&spi->dev, "Failed to enable vref regulators: %d\n", ret); - goto error_free_reg; - } - - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(&spi->dev, "Failed to register iio device: %d\n", ret); - goto error_disable_reg; - } - - return 0; - -error_disable_reg: - regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg); -error_free_reg: - regulator_bulk_free(st->chip_info->num_vrefs, st->vref_reg); -error_free_channels: - kfree(indio_dev->channels); -error_free: - iio_free_device(indio_dev); - - return ret; -} - -static int __devexit ad5360_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad5360_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - kfree(indio_dev->channels); - - regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg); - regulator_bulk_free(st->chip_info->num_vrefs, st->vref_reg); - - iio_free_device(indio_dev); - - return 0; -} - -static const struct spi_device_id ad5360_ids[] = { - { "ad5360", ID_AD5360 }, - { "ad5361", ID_AD5361 }, - { "ad5362", ID_AD5362 }, - { "ad5363", ID_AD5363 }, - { "ad5370", ID_AD5370 }, - { "ad5371", ID_AD5371 }, - { "ad5372", ID_AD5372 }, - { "ad5373", ID_AD5373 }, - {} -}; -MODULE_DEVICE_TABLE(spi, ad5360_ids); - -static struct spi_driver ad5360_driver = { - .driver = { - .name = "ad5360", - .owner = THIS_MODULE, - }, - .probe = ad5360_probe, - .remove = __devexit_p(ad5360_remove), - .id_table = ad5360_ids, -}; -module_spi_driver(ad5360_driver); - -MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); -MODULE_DESCRIPTION("Analog Devices AD5360/61/62/63/70/71/72/73 DAC"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/dac/ad5380.c b/drivers/staging/iio/dac/ad5380.c deleted file mode 100644 index eff97ae05c4..00000000000 --- a/drivers/staging/iio/dac/ad5380.c +++ /dev/null @@ -1,676 +0,0 @@ -/* - * Analog devices AD5380, AD5381, AD5382, AD5383, AD5390, AD5391, AD5392 - * multi-channel Digital to Analog Converters driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include <linux/device.h> -#include <linux/err.h> -#include <linux/i2c.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/regmap.h> -#include <linux/regulator/consumer.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "dac.h" - - -#define AD5380_REG_DATA(x) (((x) << 2) | 3) -#define AD5380_REG_OFFSET(x) (((x) << 2) | 2) -#define AD5380_REG_GAIN(x) (((x) << 2) | 1) -#define AD5380_REG_SF_PWR_DOWN (8 << 2) -#define AD5380_REG_SF_PWR_UP (9 << 2) -#define AD5380_REG_SF_CTRL (12 << 2) - -#define AD5380_CTRL_PWR_DOWN_MODE_OFFSET 13 -#define AD5380_CTRL_INT_VREF_2V5 BIT(12) -#define AD5380_CTRL_INT_VREF_EN BIT(10) - -/** - * struct ad5380_chip_info - chip specific information - * @channel_template: channel specification template - * @num_channels: number of channels - * @int_vref: internal vref in uV -*/ - -struct ad5380_chip_info { - struct iio_chan_spec channel_template; - unsigned int num_channels; - unsigned int int_vref; -}; - -/** - * struct ad5380_state - driver instance specific data - * @regmap: regmap instance used by the device - * @chip_info: chip model specific constants, available modes etc - * @vref_reg: vref supply regulator - * @vref: actual reference voltage used in uA - * @pwr_down: whether the chip is currently in power down mode - */ - -struct ad5380_state { - struct regmap *regmap; - const struct ad5380_chip_info *chip_info; - struct regulator *vref_reg; - int vref; - bool pwr_down; -}; - -enum ad5380_type { - ID_AD5380_3, - ID_AD5380_5, - ID_AD5381_3, - ID_AD5381_5, - ID_AD5382_3, - ID_AD5382_5, - ID_AD5383_3, - ID_AD5383_5, - ID_AD5390_3, - ID_AD5390_5, - ID_AD5391_3, - ID_AD5391_5, - ID_AD5392_3, - ID_AD5392_5, -}; - -#define AD5380_CHANNEL(_bits) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .output = 1, \ - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | \ - IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \ - .scan_type = IIO_ST('u', (_bits), 16, 14 - (_bits)) \ -} - -static const struct ad5380_chip_info ad5380_chip_info_tbl[] = { - [ID_AD5380_3] = { - .channel_template = AD5380_CHANNEL(14), - .num_channels = 40, - .int_vref = 1250000, - }, - [ID_AD5380_5] = { - .channel_template = AD5380_CHANNEL(14), - .num_channels = 40, - .int_vref = 2500000, - }, - [ID_AD5381_3] = { - .channel_template = AD5380_CHANNEL(12), - .num_channels = 16, - .int_vref = 1250000, - }, - [ID_AD5381_5] = { - .channel_template = AD5380_CHANNEL(12), - .num_channels = 16, - .int_vref = 2500000, - }, - [ID_AD5382_3] = { - .channel_template = AD5380_CHANNEL(14), - .num_channels = 32, - .int_vref = 1250000, - }, - [ID_AD5382_5] = { - .channel_template = AD5380_CHANNEL(14), - .num_channels = 32, - .int_vref = 2500000, - }, - [ID_AD5383_3] = { - .channel_template = AD5380_CHANNEL(12), - .num_channels = 32, - .int_vref = 1250000, - }, - [ID_AD5383_5] = { - .channel_template = AD5380_CHANNEL(12), - .num_channels = 32, - .int_vref = 2500000, - }, - [ID_AD5390_3] = { - .channel_template = AD5380_CHANNEL(14), - .num_channels = 16, - .int_vref = 1250000, - }, - [ID_AD5390_5] = { - .channel_template = AD5380_CHANNEL(14), - .num_channels = 16, - .int_vref = 2500000, - }, - [ID_AD5391_3] = { - .channel_template = AD5380_CHANNEL(12), - .num_channels = 16, - .int_vref = 1250000, - }, - [ID_AD5391_5] = { - .channel_template = AD5380_CHANNEL(12), - .num_channels = 16, - .int_vref = 2500000, - }, - [ID_AD5392_3] = { - .channel_template = AD5380_CHANNEL(14), - .num_channels = 8, - .int_vref = 1250000, - }, - [ID_AD5392_5] = { - .channel_template = AD5380_CHANNEL(14), - .num_channels = 8, - .int_vref = 2500000, - }, -}; - -static ssize_t ad5380_read_dac_powerdown(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5380_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", st->pwr_down); -} - -static ssize_t ad5380_write_dac_powerdown(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5380_state *st = iio_priv(indio_dev); - bool pwr_down; - int ret; - - ret = strtobool(buf, &pwr_down); - if (ret) - return ret; - - mutex_lock(&indio_dev->mlock); - - if (pwr_down) - ret = regmap_write(st->regmap, AD5380_REG_SF_PWR_DOWN, 0); - else - ret = regmap_write(st->regmap, AD5380_REG_SF_PWR_UP, 0); - - st->pwr_down = pwr_down; - - mutex_unlock(&indio_dev->mlock); - - return ret ? ret : len; -} - -static IIO_DEVICE_ATTR(out_voltage_powerdown, - S_IRUGO | S_IWUSR, - ad5380_read_dac_powerdown, - ad5380_write_dac_powerdown, 0); - -static const char ad5380_powerdown_modes[][15] = { - [0] = "100kohm_to_gnd", - [1] = "three_state", -}; - -static ssize_t ad5380_read_powerdown_mode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5380_state *st = iio_priv(indio_dev); - unsigned int mode; - int ret; - - ret = regmap_read(st->regmap, AD5380_REG_SF_CTRL, &mode); - if (ret) - return ret; - - mode = (mode >> AD5380_CTRL_PWR_DOWN_MODE_OFFSET) & 1; - - return sprintf(buf, "%s\n", ad5380_powerdown_modes[mode]); -} - -static ssize_t ad5380_write_powerdown_mode(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5380_state *st = iio_priv(indio_dev); - unsigned int i; - int ret; - - for (i = 0; i < ARRAY_SIZE(ad5380_powerdown_modes); ++i) { - if (sysfs_streq(buf, ad5380_powerdown_modes[i])) - break; - } - - if (i == ARRAY_SIZE(ad5380_powerdown_modes)) - return -EINVAL; - - ret = regmap_update_bits(st->regmap, AD5380_REG_SF_CTRL, - 1 << AD5380_CTRL_PWR_DOWN_MODE_OFFSET, - i << AD5380_CTRL_PWR_DOWN_MODE_OFFSET); - - return ret ? ret : len; -} - -static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, - S_IRUGO | S_IWUSR, - ad5380_read_powerdown_mode, - ad5380_write_powerdown_mode, 0); - -static IIO_CONST_ATTR(out_voltage_powerdown_mode_available, - "100kohm_to_gnd three_state"); - -static struct attribute *ad5380_attributes[] = { - &iio_dev_attr_out_voltage_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad5380_attribute_group = { - .attrs = ad5380_attributes, -}; - -static unsigned int ad5380_info_to_reg(struct iio_chan_spec const *chan, - long info) -{ - switch (info) { - case 0: - return AD5380_REG_DATA(chan->address); - case IIO_CHAN_INFO_CALIBBIAS: - return AD5380_REG_OFFSET(chan->address); - case IIO_CHAN_INFO_CALIBSCALE: - return AD5380_REG_GAIN(chan->address); - default: - break; - } - - return 0; -} - -static int ad5380_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int val, int val2, long info) -{ - const unsigned int max_val = (1 << chan->scan_type.realbits); - struct ad5380_state *st = iio_priv(indio_dev); - - switch (info) { - case 0: - case IIO_CHAN_INFO_CALIBSCALE: - if (val >= max_val || val < 0) - return -EINVAL; - - return regmap_write(st->regmap, - ad5380_info_to_reg(chan, info), - val << chan->scan_type.shift); - case IIO_CHAN_INFO_CALIBBIAS: - val += (1 << chan->scan_type.realbits) / 2; - if (val >= max_val || val < 0) - return -EINVAL; - - return regmap_write(st->regmap, - AD5380_REG_OFFSET(chan->address), - val << chan->scan_type.shift); - default: - break; - } - return -EINVAL; -} - -static int ad5380_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int *val, int *val2, long info) -{ - struct ad5380_state *st = iio_priv(indio_dev); - unsigned long scale_uv; - int ret; - - switch (info) { - case 0: - case IIO_CHAN_INFO_CALIBSCALE: - ret = regmap_read(st->regmap, ad5380_info_to_reg(chan, info), - val); - if (ret) - return ret; - *val >>= chan->scan_type.shift; - return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBBIAS: - ret = regmap_read(st->regmap, AD5380_REG_OFFSET(chan->address), - val); - if (ret) - return ret; - *val >>= chan->scan_type.shift; - val -= (1 << chan->scan_type.realbits) / 2; - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - scale_uv = ((2 * st->vref) >> chan->scan_type.realbits) * 100; - *val = scale_uv / 100000; - *val2 = (scale_uv % 100000) * 10; - return IIO_VAL_INT_PLUS_MICRO; - default: - break; - } - - return -EINVAL; -} - -static const struct iio_info ad5380_info = { - .read_raw = ad5380_read_raw, - .write_raw = ad5380_write_raw, - .attrs = &ad5380_attribute_group, - .driver_module = THIS_MODULE, -}; - -static int __devinit ad5380_alloc_channels(struct iio_dev *indio_dev) -{ - struct ad5380_state *st = iio_priv(indio_dev); - struct iio_chan_spec *channels; - unsigned int i; - - channels = kcalloc(sizeof(struct iio_chan_spec), - st->chip_info->num_channels, GFP_KERNEL); - - if (!channels) - return -ENOMEM; - - for (i = 0; i < st->chip_info->num_channels; ++i) { - channels[i] = st->chip_info->channel_template; - channels[i].channel = i; - channels[i].address = i; - } - - indio_dev->channels = channels; - - return 0; -} - -static int __devinit ad5380_probe(struct device *dev, struct regmap *regmap, - enum ad5380_type type, const char *name) -{ - struct iio_dev *indio_dev; - struct ad5380_state *st; - unsigned int ctrl = 0; - int ret; - - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - dev_err(dev, "Failed to allocate iio device\n"); - ret = -ENOMEM; - goto error_regmap_exit; - } - - st = iio_priv(indio_dev); - dev_set_drvdata(dev, indio_dev); - - st->chip_info = &ad5380_chip_info_tbl[type]; - st->regmap = regmap; - - indio_dev->dev.parent = dev; - indio_dev->name = name; - indio_dev->info = &ad5380_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->num_channels = st->chip_info->num_channels; - - ret = ad5380_alloc_channels(indio_dev); - if (ret) { - dev_err(dev, "Failed to allocate channel spec: %d\n", ret); - goto error_free; - } - - if (st->chip_info->int_vref == 2500000) - ctrl |= AD5380_CTRL_INT_VREF_2V5; - - st->vref_reg = regulator_get(dev, "vref"); - if (!IS_ERR(st->vref_reg)) { - ret = regulator_enable(st->vref_reg); - if (ret) { - dev_err(dev, "Failed to enable vref regulators: %d\n", - ret); - goto error_free_reg; - } - - st->vref = regulator_get_voltage(st->vref_reg); - } else { - st->vref = st->chip_info->int_vref; - ctrl |= AD5380_CTRL_INT_VREF_EN; - } - - ret = regmap_write(st->regmap, AD5380_REG_SF_CTRL, ctrl); - if (ret) { - dev_err(dev, "Failed to write to device: %d\n", ret); - goto error_disable_reg; - } - - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(dev, "Failed to register iio device: %d\n", ret); - goto error_disable_reg; - } - - return 0; - -error_disable_reg: - if (!IS_ERR(st->vref_reg)) - regulator_disable(st->vref_reg); -error_free_reg: - if (!IS_ERR(st->vref_reg)) - regulator_put(st->vref_reg); - - kfree(indio_dev->channels); -error_free: - iio_free_device(indio_dev); -error_regmap_exit: - regmap_exit(regmap); - - return ret; -} - -static int __devexit ad5380_remove(struct device *dev) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5380_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - kfree(indio_dev->channels); - - if (!IS_ERR(st->vref_reg)) { - regulator_disable(st->vref_reg); - regulator_put(st->vref_reg); - } - - regmap_exit(st->regmap); - iio_free_device(indio_dev); - - return 0; -} - -static bool ad5380_reg_false(struct device *dev, unsigned int reg) -{ - return false; -} - -static const struct regmap_config ad5380_regmap_config = { - .reg_bits = 10, - .val_bits = 14, - - .max_register = AD5380_REG_DATA(40), - .cache_type = REGCACHE_RBTREE, - - .volatile_reg = ad5380_reg_false, - .readable_reg = ad5380_reg_false, -}; - -#if IS_ENABLED(CONFIG_SPI_MASTER) - -static int __devinit ad5380_spi_probe(struct spi_device *spi) -{ - const struct spi_device_id *id = spi_get_device_id(spi); - struct regmap *regmap; - - regmap = regmap_init_spi(spi, &ad5380_regmap_config); - - if (IS_ERR(regmap)) - return PTR_ERR(regmap); - - return ad5380_probe(&spi->dev, regmap, id->driver_data, id->name); -} - -static int __devexit ad5380_spi_remove(struct spi_device *spi) -{ - return ad5380_remove(&spi->dev); -} - -static const struct spi_device_id ad5380_spi_ids[] = { - { "ad5380-3", ID_AD5380_3 }, - { "ad5380-5", ID_AD5380_5 }, - { "ad5381-3", ID_AD5381_3 }, - { "ad5381-5", ID_AD5381_5 }, - { "ad5382-3", ID_AD5382_3 }, - { "ad5382-5", ID_AD5382_5 }, - { "ad5383-3", ID_AD5383_3 }, - { "ad5383-5", ID_AD5383_5 }, - { "ad5384-3", ID_AD5380_3 }, - { "ad5384-5", ID_AD5380_5 }, - { "ad5390-3", ID_AD5390_3 }, - { "ad5390-5", ID_AD5390_5 }, - { "ad5391-3", ID_AD5391_3 }, - { "ad5391-5", ID_AD5391_5 }, - { "ad5392-3", ID_AD5392_3 }, - { "ad5392-5", ID_AD5392_5 }, - { } -}; -MODULE_DEVICE_TABLE(spi, ad5380_spi_ids); - -static struct spi_driver ad5380_spi_driver = { - .driver = { - .name = "ad5380", - .owner = THIS_MODULE, - }, - .probe = ad5380_spi_probe, - .remove = __devexit_p(ad5380_spi_remove), - .id_table = ad5380_spi_ids, -}; - -static inline int ad5380_spi_register_driver(void) -{ - return spi_register_driver(&ad5380_spi_driver); -} - -static inline void ad5380_spi_unregister_driver(void) -{ - spi_unregister_driver(&ad5380_spi_driver); -} - -#else - -static inline int ad5380_spi_register_driver(void) -{ - return 0; -} - -static inline void ad5380_spi_unregister_driver(void) -{ -} - -#endif - -#if IS_ENABLED(CONFIG_I2C) - -static int __devinit ad5380_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct regmap *regmap; - - regmap = regmap_init_i2c(i2c, &ad5380_regmap_config); - - if (IS_ERR(regmap)) - return PTR_ERR(regmap); - - return ad5380_probe(&i2c->dev, regmap, id->driver_data, id->name); -} - -static int __devexit ad5380_i2c_remove(struct i2c_client *i2c) -{ - return ad5380_remove(&i2c->dev); -} - -static const struct i2c_device_id ad5380_i2c_ids[] = { - { "ad5380-3", ID_AD5380_3 }, - { "ad5380-5", ID_AD5380_5 }, - { "ad5381-3", ID_AD5381_3 }, - { "ad5381-5", ID_AD5381_5 }, - { "ad5382-3", ID_AD5382_3 }, - { "ad5382-5", ID_AD5382_5 }, - { "ad5383-3", ID_AD5383_3 }, - { "ad5383-5", ID_AD5383_5 }, - { "ad5384-3", ID_AD5380_3 }, - { "ad5384-5", ID_AD5380_5 }, - { "ad5390-3", ID_AD5390_3 }, - { "ad5390-5", ID_AD5390_5 }, - { "ad5391-3", ID_AD5391_3 }, - { "ad5391-5", ID_AD5391_5 }, - { "ad5392-3", ID_AD5392_3 }, - { "ad5392-5", ID_AD5392_5 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ad5380_i2c_ids); - -static struct i2c_driver ad5380_i2c_driver = { - .driver = { - .name = "ad5380", - .owner = THIS_MODULE, - }, - .probe = ad5380_i2c_probe, - .remove = __devexit_p(ad5380_i2c_remove), - .id_table = ad5380_i2c_ids, -}; - -static inline int ad5380_i2c_register_driver(void) -{ - return i2c_add_driver(&ad5380_i2c_driver); -} - -static inline void ad5380_i2c_unregister_driver(void) -{ - i2c_del_driver(&ad5380_i2c_driver); -} - -#else - -static inline int ad5380_i2c_register_driver(void) -{ - return 0; -} - -static inline void ad5380_i2c_unregister_driver(void) -{ -} - -#endif - -static int __init ad5380_spi_init(void) -{ - int ret; - - ret = ad5380_spi_register_driver(); - if (ret) - return ret; - - ret = ad5380_i2c_register_driver(); - if (ret) { - ad5380_spi_unregister_driver(); - return ret; - } - - return 0; -} -module_init(ad5380_spi_init); - -static void __exit ad5380_spi_exit(void) -{ - ad5380_i2c_unregister_driver(); - ad5380_spi_unregister_driver(); - -} -module_exit(ad5380_spi_exit); - -MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); -MODULE_DESCRIPTION("Analog Devices AD5380/81/82/83/84/90/91/92 DAC"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/dac/ad5421.c b/drivers/staging/iio/dac/ad5421.c deleted file mode 100644 index 71ee8682476..00000000000 --- a/drivers/staging/iio/dac/ad5421.c +++ /dev/null @@ -1,555 +0,0 @@ -/* - * AD5421 Digital to analog converters driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include <linux/device.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" -#include "dac.h" -#include "ad5421.h" - - -#define AD5421_REG_DAC_DATA 0x1 -#define AD5421_REG_CTRL 0x2 -#define AD5421_REG_OFFSET 0x3 -#define AD5421_REG_GAIN 0x4 -/* load dac and fault shared the same register number. Writing to it will cause - * a dac load command, reading from it will return the fault status register */ -#define AD5421_REG_LOAD_DAC 0x5 -#define AD5421_REG_FAULT 0x5 -#define AD5421_REG_FORCE_ALARM_CURRENT 0x6 -#define AD5421_REG_RESET 0x7 -#define AD5421_REG_START_CONVERSION 0x8 -#define AD5421_REG_NOOP 0x9 - -#define AD5421_CTRL_WATCHDOG_DISABLE BIT(12) -#define AD5421_CTRL_AUTO_FAULT_READBACK BIT(11) -#define AD5421_CTRL_MIN_CURRENT BIT(9) -#define AD5421_CTRL_ADC_SOURCE_TEMP BIT(8) -#define AD5421_CTRL_ADC_ENABLE BIT(7) -#define AD5421_CTRL_PWR_DOWN_INT_VREF BIT(6) - -#define AD5421_FAULT_SPI BIT(15) -#define AD5421_FAULT_PEC BIT(14) -#define AD5421_FAULT_OVER_CURRENT BIT(13) -#define AD5421_FAULT_UNDER_CURRENT BIT(12) -#define AD5421_FAULT_TEMP_OVER_140 BIT(11) -#define AD5421_FAULT_TEMP_OVER_100 BIT(10) -#define AD5421_FAULT_UNDER_VOLTAGE_6V BIT(9) -#define AD5421_FAULT_UNDER_VOLTAGE_12V BIT(8) - -/* These bits will cause the fault pin to go high */ -#define AD5421_FAULT_TRIGGER_IRQ \ - (AD5421_FAULT_SPI | AD5421_FAULT_PEC | AD5421_FAULT_OVER_CURRENT | \ - AD5421_FAULT_UNDER_CURRENT | AD5421_FAULT_TEMP_OVER_140) - -/** - * struct ad5421_state - driver instance specific data - * @spi: spi_device - * @ctrl: control register cache - * @current_range: current range which the device is configured for - * @data: spi transfer buffers - * @fault_mask: software masking of events - */ -struct ad5421_state { - struct spi_device *spi; - unsigned int ctrl; - enum ad5421_current_range current_range; - unsigned int fault_mask; - - /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - */ - union { - u32 d32; - u8 d8[4]; - } data[2] ____cacheline_aligned; -}; - -static const struct iio_chan_spec ad5421_channels[] = { - { - .type = IIO_CURRENT, - .indexed = 1, - .output = 1, - .channel = 0, - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_OFFSET_SHARED_BIT | - IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, - .scan_type = IIO_ST('u', 16, 16, 0), - .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | - IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), - }, - { - .type = IIO_TEMP, - .channel = -1, - .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), - }, -}; - -static int ad5421_write_unlocked(struct iio_dev *indio_dev, - unsigned int reg, unsigned int val) -{ - struct ad5421_state *st = iio_priv(indio_dev); - - st->data[0].d32 = cpu_to_be32((reg << 16) | val); - - return spi_write(st->spi, &st->data[0].d8[1], 3); -} - -static int ad5421_write(struct iio_dev *indio_dev, unsigned int reg, - unsigned int val) -{ - int ret; - - mutex_lock(&indio_dev->mlock); - ret = ad5421_write_unlocked(indio_dev, reg, val); - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static int ad5421_read(struct iio_dev *indio_dev, unsigned int reg) -{ - struct ad5421_state *st = iio_priv(indio_dev); - struct spi_message m; - int ret; - struct spi_transfer t[] = { - { - .tx_buf = &st->data[0].d8[1], - .len = 3, - .cs_change = 1, - }, { - .rx_buf = &st->data[1].d8[1], - .len = 3, - }, - }; - - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - spi_message_add_tail(&t[1], &m); - - mutex_lock(&indio_dev->mlock); - - st->data[0].d32 = cpu_to_be32((1 << 23) | (reg << 16)); - - ret = spi_sync(st->spi, &m); - if (ret >= 0) - ret = be32_to_cpu(st->data[1].d32) & 0xffff; - - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static int ad5421_update_ctrl(struct iio_dev *indio_dev, unsigned int set, - unsigned int clr) -{ - struct ad5421_state *st = iio_priv(indio_dev); - unsigned int ret; - - mutex_lock(&indio_dev->mlock); - - st->ctrl &= ~clr; - st->ctrl |= set; - - ret = ad5421_write_unlocked(indio_dev, AD5421_REG_CTRL, st->ctrl); - - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static irqreturn_t ad5421_fault_handler(int irq, void *data) -{ - struct iio_dev *indio_dev = data; - struct ad5421_state *st = iio_priv(indio_dev); - unsigned int fault; - unsigned int old_fault = 0; - unsigned int events; - - fault = ad5421_read(indio_dev, AD5421_REG_FAULT); - if (!fault) - return IRQ_NONE; - - /* If we had a fault, this might mean that the DAC has lost its state - * and has been reset. Make sure that the control register actually - * contains what we expect it to contain. Otherwise the watchdog might - * be enabled and we get watchdog timeout faults, which will render the - * DAC unusable. */ - ad5421_update_ctrl(indio_dev, 0, 0); - - - /* The fault pin stays high as long as a fault condition is present and - * it is not possible to mask fault conditions. For certain fault - * conditions for example like over-temperature it takes some time - * until the fault condition disappears. If we would exit the interrupt - * handler immediately after handling the event it would be entered - * again instantly. Thus we fall back to polling in case we detect that - * a interrupt condition is still present. - */ - do { - /* 0xffff is a invalid value for the register and will only be - * read if there has been a communication error */ - if (fault == 0xffff) - fault = 0; - - /* we are only interested in new events */ - events = (old_fault ^ fault) & fault; - events &= st->fault_mask; - - if (events & AD5421_FAULT_OVER_CURRENT) { - iio_push_event(indio_dev, - IIO_UNMOD_EVENT_CODE(IIO_CURRENT, - 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - iio_get_time_ns()); - } - - if (events & AD5421_FAULT_UNDER_CURRENT) { - iio_push_event(indio_dev, - IIO_UNMOD_EVENT_CODE(IIO_CURRENT, - 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING), - iio_get_time_ns()); - } - - if (events & AD5421_FAULT_TEMP_OVER_140) { - iio_push_event(indio_dev, - IIO_UNMOD_EVENT_CODE(IIO_TEMP, - 0, - IIO_EV_TYPE_MAG, - IIO_EV_DIR_RISING), - iio_get_time_ns()); - } - - old_fault = fault; - fault = ad5421_read(indio_dev, AD5421_REG_FAULT); - - /* still active? go to sleep for some time */ - if (fault & AD5421_FAULT_TRIGGER_IRQ) - msleep(1000); - - } while (fault & AD5421_FAULT_TRIGGER_IRQ); - - - return IRQ_HANDLED; -} - -static void ad5421_get_current_min_max(struct ad5421_state *st, - unsigned int *min, unsigned int *max) -{ - /* The current range is configured using external pins, which are - * usually hard-wired and not run-time switchable. */ - switch (st->current_range) { - case AD5421_CURRENT_RANGE_4mA_20mA: - *min = 4000; - *max = 20000; - break; - case AD5421_CURRENT_RANGE_3mA8_21mA: - *min = 3800; - *max = 21000; - break; - case AD5421_CURRENT_RANGE_3mA2_24mA: - *min = 3200; - *max = 24000; - break; - default: - *min = 0; - *max = 1; - break; - } -} - -static inline unsigned int ad5421_get_offset(struct ad5421_state *st) -{ - unsigned int min, max; - - ad5421_get_current_min_max(st, &min, &max); - return (min * (1 << 16)) / (max - min); -} - -static inline unsigned int ad5421_get_scale(struct ad5421_state *st) -{ - unsigned int min, max; - - ad5421_get_current_min_max(st, &min, &max); - return ((max - min) * 1000) / (1 << 16); -} - -static int ad5421_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int *val, int *val2, long m) -{ - struct ad5421_state *st = iio_priv(indio_dev); - int ret; - - if (chan->type != IIO_CURRENT) - return -EINVAL; - - switch (m) { - case 0: - ret = ad5421_read(indio_dev, AD5421_REG_DAC_DATA); - if (ret < 0) - return ret; - *val = ret; - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - *val = 0; - *val2 = ad5421_get_scale(st); - return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_OFFSET: - *val = ad5421_get_offset(st); - return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBBIAS: - ret = ad5421_read(indio_dev, AD5421_REG_OFFSET); - if (ret < 0) - return ret; - *val = ret - 32768; - return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBSCALE: - ret = ad5421_read(indio_dev, AD5421_REG_GAIN); - if (ret < 0) - return ret; - *val = ret; - return IIO_VAL_INT; - } - - return -EINVAL; -} - -static int ad5421_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int val, int val2, long mask) -{ - const unsigned int max_val = 1 << 16; - - switch (mask) { - case 0: - if (val >= max_val || val < 0) - return -EINVAL; - - return ad5421_write(indio_dev, AD5421_REG_DAC_DATA, val); - case IIO_CHAN_INFO_CALIBBIAS: - val += 32768; - if (val >= max_val || val < 0) - return -EINVAL; - - return ad5421_write(indio_dev, AD5421_REG_OFFSET, val); - case IIO_CHAN_INFO_CALIBSCALE: - if (val >= max_val || val < 0) - return -EINVAL; - - return ad5421_write(indio_dev, AD5421_REG_GAIN, val); - default: - break; - } - - return -EINVAL; -} - -static int ad5421_write_event_config(struct iio_dev *indio_dev, - u64 event_code, int state) -{ - struct ad5421_state *st = iio_priv(indio_dev); - unsigned int mask; - - switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { - case IIO_CURRENT: - if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_RISING) - mask = AD5421_FAULT_OVER_CURRENT; - else - mask = AD5421_FAULT_UNDER_CURRENT; - break; - case IIO_TEMP: - mask = AD5421_FAULT_TEMP_OVER_140; - break; - default: - return -EINVAL; - } - - mutex_lock(&indio_dev->mlock); - if (state) - st->fault_mask |= mask; - else - st->fault_mask &= ~mask; - mutex_unlock(&indio_dev->mlock); - - return 0; -} - -static int ad5421_read_event_config(struct iio_dev *indio_dev, - u64 event_code) -{ - struct ad5421_state *st = iio_priv(indio_dev); - unsigned int mask; - - switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { - case IIO_CURRENT: - if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_RISING) - mask = AD5421_FAULT_OVER_CURRENT; - else - mask = AD5421_FAULT_UNDER_CURRENT; - break; - case IIO_TEMP: - mask = AD5421_FAULT_TEMP_OVER_140; - break; - default: - return -EINVAL; - } - - return (bool)(st->fault_mask & mask); -} - -static int ad5421_read_event_value(struct iio_dev *indio_dev, u64 event_code, - int *val) -{ - int ret; - - switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { - case IIO_CURRENT: - ret = ad5421_read(indio_dev, AD5421_REG_DAC_DATA); - if (ret < 0) - return ret; - *val = ret; - break; - case IIO_TEMP: - *val = 140000; - break; - default: - return -EINVAL; - } - - return 0; -} - -static const struct iio_info ad5421_info = { - .read_raw = ad5421_read_raw, - .write_raw = ad5421_write_raw, - .read_event_config = ad5421_read_event_config, - .write_event_config = ad5421_write_event_config, - .read_event_value = ad5421_read_event_value, - .driver_module = THIS_MODULE, -}; - -static int __devinit ad5421_probe(struct spi_device *spi) -{ - struct ad5421_platform_data *pdata = dev_get_platdata(&spi->dev); - struct iio_dev *indio_dev; - struct ad5421_state *st; - int ret; - - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - dev_err(&spi->dev, "Failed to allocate iio device\n"); - return -ENOMEM; - } - - st = iio_priv(indio_dev); - spi_set_drvdata(spi, indio_dev); - - st->spi = spi; - - indio_dev->dev.parent = &spi->dev; - indio_dev->name = "ad5421"; - indio_dev->info = &ad5421_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = ad5421_channels; - indio_dev->num_channels = ARRAY_SIZE(ad5421_channels); - - st->ctrl = AD5421_CTRL_WATCHDOG_DISABLE | - AD5421_CTRL_AUTO_FAULT_READBACK; - - if (pdata) { - st->current_range = pdata->current_range; - if (pdata->external_vref) - st->ctrl |= AD5421_CTRL_PWR_DOWN_INT_VREF; - } else { - st->current_range = AD5421_CURRENT_RANGE_4mA_20mA; - } - - /* write initial ctrl register value */ - ad5421_update_ctrl(indio_dev, 0, 0); - - if (spi->irq) { - ret = request_threaded_irq(spi->irq, - NULL, - ad5421_fault_handler, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, - "ad5421 fault", - indio_dev); - if (ret) - goto error_free; - } - - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(&spi->dev, "Failed to register iio device: %d\n", ret); - goto error_free_irq; - } - - return 0; - -error_free_irq: - if (spi->irq) - free_irq(spi->irq, indio_dev); -error_free: - iio_free_device(indio_dev); - - return ret; -} - -static int __devexit ad5421_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - iio_device_unregister(indio_dev); - if (spi->irq) - free_irq(spi->irq, indio_dev); - iio_free_device(indio_dev); - - return 0; -} - -static struct spi_driver ad5421_driver = { - .driver = { - .name = "ad5421", - .owner = THIS_MODULE, - }, - .probe = ad5421_probe, - .remove = __devexit_p(ad5421_remove), -}; - -static __init int ad5421_init(void) -{ - return spi_register_driver(&ad5421_driver); -} -module_init(ad5421_init); - -static __exit void ad5421_exit(void) -{ - spi_unregister_driver(&ad5421_driver); -} -module_exit(ad5421_exit); - -MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); -MODULE_DESCRIPTION("Analog Devices AD5421 DAC"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:ad5421"); diff --git a/drivers/staging/iio/dac/ad5421.h b/drivers/staging/iio/dac/ad5421.h deleted file mode 100644 index cd2bb84ff1b..00000000000 --- a/drivers/staging/iio/dac/ad5421.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef __IIO_DAC_AD5421_H__ -#define __IIO_DAC_AD5421_H__ - -/* - * TODO: This file needs to go into include/linux/iio - */ - -/** - * enum ad5421_current_range - Current range the AD5421 is configured for. - * @AD5421_CURRENT_RANGE_4mA_20mA: 4 mA to 20 mA (RANGE1,0 pins = 00) - * @AD5421_CURRENT_RANGE_3mA8_21mA: 3.8 mA to 21 mA (RANGE1,0 pins = x1) - * @AD5421_CURRENT_RANGE_3mA2_24mA: 3.2 mA to 24 mA (RANGE1,0 pins = 10) - */ - -enum ad5421_current_range { - AD5421_CURRENT_RANGE_4mA_20mA, - AD5421_CURRENT_RANGE_3mA8_21mA, - AD5421_CURRENT_RANGE_3mA2_24mA, -}; - -/** - * struct ad5421_platform_data - AD5421 DAC driver platform data - * @external_vref: whether an external reference voltage is used or not - * @current_range: Current range the AD5421 is configured for - */ - -struct ad5421_platform_data { - bool external_vref; - enum ad5421_current_range current_range; -}; - -#endif diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c deleted file mode 100644 index 693e7482524..00000000000 --- a/drivers/staging/iio/dac/ad5446.c +++ /dev/null @@ -1,453 +0,0 @@ -/* - * AD5446 SPI DAC 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 <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "dac.h" - -#include "ad5446.h" - -static void ad5446_store_sample(struct ad5446_state *st, unsigned val) -{ - st->data.d16 = cpu_to_be16(AD5446_LOAD | val); -} - -static void ad5542_store_sample(struct ad5446_state *st, unsigned val) -{ - st->data.d16 = cpu_to_be16(val); -} - -static void ad5620_store_sample(struct ad5446_state *st, unsigned val) -{ - st->data.d16 = cpu_to_be16(AD5620_LOAD | val); -} - -static void ad5660_store_sample(struct ad5446_state *st, unsigned val) -{ - val |= AD5660_LOAD; - st->data.d24[0] = (val >> 16) & 0xFF; - st->data.d24[1] = (val >> 8) & 0xFF; - st->data.d24[2] = val & 0xFF; -} - -static void ad5620_store_pwr_down(struct ad5446_state *st, unsigned mode) -{ - st->data.d16 = cpu_to_be16(mode << 14); -} - -static void ad5660_store_pwr_down(struct ad5446_state *st, unsigned mode) -{ - unsigned val = mode << 16; - - st->data.d24[0] = (val >> 16) & 0xFF; - st->data.d24[1] = (val >> 8) & 0xFF; - st->data.d24[2] = val & 0xFF; -} - -static ssize_t ad5446_write_powerdown_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5446_state *st = iio_priv(indio_dev); - - if (sysfs_streq(buf, "1kohm_to_gnd")) - st->pwr_down_mode = MODE_PWRDWN_1k; - else if (sysfs_streq(buf, "100kohm_to_gnd")) - st->pwr_down_mode = MODE_PWRDWN_100k; - else if (sysfs_streq(buf, "three_state")) - st->pwr_down_mode = MODE_PWRDWN_TRISTATE; - else - return -EINVAL; - - return len; -} - -static ssize_t ad5446_read_powerdown_mode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5446_state *st = iio_priv(indio_dev); - - char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"}; - - return sprintf(buf, "%s\n", mode[st->pwr_down_mode]); -} - -static ssize_t ad5446_read_dac_powerdown(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5446_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", st->pwr_down); -} - -static ssize_t ad5446_write_dac_powerdown(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5446_state *st = iio_priv(indio_dev); - unsigned long readin; - int ret; - - ret = strict_strtol(buf, 10, &readin); - if (ret) - return ret; - - if (readin > 1) - ret = -EINVAL; - - mutex_lock(&indio_dev->mlock); - st->pwr_down = readin; - - if (st->pwr_down) - st->chip_info->store_pwr_down(st, st->pwr_down_mode); - else - st->chip_info->store_sample(st, st->cached_val); - - ret = spi_sync(st->spi, &st->msg); - mutex_unlock(&indio_dev->mlock); - - return ret ? ret : len; -} - -static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO | S_IWUSR, - ad5446_read_powerdown_mode, - ad5446_write_powerdown_mode, 0); - -static IIO_CONST_ATTR(out_voltage_powerdown_mode_available, - "1kohm_to_gnd 100kohm_to_gnd three_state"); - -static IIO_DEVICE_ATTR(out_voltage0_powerdown, S_IRUGO | S_IWUSR, - ad5446_read_dac_powerdown, - ad5446_write_dac_powerdown, 0); - -static struct attribute *ad5446_attributes[] = { - &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - NULL, -}; - -static umode_t ad5446_attr_is_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5446_state *st = iio_priv(indio_dev); - - umode_t mode = attr->mode; - - if (!st->chip_info->store_pwr_down && - (attr == &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr || - attr == &iio_dev_attr_out_voltage_powerdown_mode. - dev_attr.attr || - attr == - &iio_const_attr_out_voltage_powerdown_mode_available. - dev_attr.attr)) - mode = 0; - - return mode; -} - -static const struct attribute_group ad5446_attribute_group = { - .attrs = ad5446_attributes, - .is_visible = ad5446_attr_is_visible, -}; - -#define AD5446_CHANNEL(bits, storage, shift) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .output = 1, \ - .channel = 0, \ - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ - .scan_type = IIO_ST('u', (bits), (storage), (shift)) \ -} - -static const struct ad5446_chip_info ad5446_chip_info_tbl[] = { - [ID_AD5444] = { - .channel = AD5446_CHANNEL(12, 16, 2), - .store_sample = ad5446_store_sample, - }, - [ID_AD5446] = { - .channel = AD5446_CHANNEL(14, 16, 0), - .store_sample = ad5446_store_sample, - }, - [ID_AD5541A] = { - .channel = AD5446_CHANNEL(16, 16, 0), - .store_sample = ad5542_store_sample, - }, - [ID_AD5542A] = { - .channel = AD5446_CHANNEL(16, 16, 0), - .store_sample = ad5542_store_sample, - }, - [ID_AD5543] = { - .channel = AD5446_CHANNEL(16, 16, 0), - .store_sample = ad5542_store_sample, - }, - [ID_AD5512A] = { - .channel = AD5446_CHANNEL(12, 16, 4), - .store_sample = ad5542_store_sample, - }, - [ID_AD5553] = { - .channel = AD5446_CHANNEL(14, 16, 0), - .store_sample = ad5542_store_sample, - }, - [ID_AD5601] = { - .channel = AD5446_CHANNEL(8, 16, 6), - .store_sample = ad5542_store_sample, - .store_pwr_down = ad5620_store_pwr_down, - }, - [ID_AD5611] = { - .channel = AD5446_CHANNEL(10, 16, 4), - .store_sample = ad5542_store_sample, - .store_pwr_down = ad5620_store_pwr_down, - }, - [ID_AD5621] = { - .channel = AD5446_CHANNEL(12, 16, 2), - .store_sample = ad5542_store_sample, - .store_pwr_down = ad5620_store_pwr_down, - }, - [ID_AD5620_2500] = { - .channel = AD5446_CHANNEL(12, 16, 2), - .int_vref_mv = 2500, - .store_sample = ad5620_store_sample, - .store_pwr_down = ad5620_store_pwr_down, - }, - [ID_AD5620_1250] = { - .channel = AD5446_CHANNEL(12, 16, 2), - .int_vref_mv = 1250, - .store_sample = ad5620_store_sample, - .store_pwr_down = ad5620_store_pwr_down, - }, - [ID_AD5640_2500] = { - .channel = AD5446_CHANNEL(14, 16, 0), - .int_vref_mv = 2500, - .store_sample = ad5620_store_sample, - .store_pwr_down = ad5620_store_pwr_down, - }, - [ID_AD5640_1250] = { - .channel = AD5446_CHANNEL(14, 16, 0), - .int_vref_mv = 1250, - .store_sample = ad5620_store_sample, - .store_pwr_down = ad5620_store_pwr_down, - }, - [ID_AD5660_2500] = { - .channel = AD5446_CHANNEL(16, 16, 0), - .int_vref_mv = 2500, - .store_sample = ad5660_store_sample, - .store_pwr_down = ad5660_store_pwr_down, - }, - [ID_AD5660_1250] = { - .channel = AD5446_CHANNEL(16, 16, 0), - .int_vref_mv = 1250, - .store_sample = ad5660_store_sample, - .store_pwr_down = ad5660_store_pwr_down, - }, -}; - -static int ad5446_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - struct ad5446_state *st = iio_priv(indio_dev); - unsigned long scale_uv; - - switch (m) { - case IIO_CHAN_INFO_SCALE: - scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; - - } - return -EINVAL; -} - -static int ad5446_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct ad5446_state *st = iio_priv(indio_dev); - int ret; - - switch (mask) { - case 0: - if (val >= (1 << chan->scan_type.realbits) || val < 0) - return -EINVAL; - - val <<= chan->scan_type.shift; - mutex_lock(&indio_dev->mlock); - st->cached_val = val; - st->chip_info->store_sample(st, val); - ret = spi_sync(st->spi, &st->msg); - mutex_unlock(&indio_dev->mlock); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static const struct iio_info ad5446_info = { - .read_raw = ad5446_read_raw, - .write_raw = ad5446_write_raw, - .attrs = &ad5446_attribute_group, - .driver_module = THIS_MODULE, -}; - -static int __devinit ad5446_probe(struct spi_device *spi) -{ - struct ad5446_state *st; - struct iio_dev *indio_dev; - struct regulator *reg; - int ret, voltage_uv = 0; - - reg = regulator_get(&spi->dev, "vcc"); - if (!IS_ERR(reg)) { - ret = regulator_enable(reg); - if (ret) - goto error_put_reg; - - voltage_uv = regulator_get_voltage(reg); - } - - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_disable_reg; - } - st = iio_priv(indio_dev); - st->chip_info = - &ad5446_chip_info_tbl[spi_get_device_id(spi)->driver_data]; - - spi_set_drvdata(spi, indio_dev); - st->reg = reg; - st->spi = spi; - - /* Estabilish that the iio_dev is a child of the spi device */ - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->info = &ad5446_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = &st->chip_info->channel; - indio_dev->num_channels = 1; - - /* Setup default message */ - - st->xfer.tx_buf = &st->data; - st->xfer.len = st->chip_info->channel.scan_type.storagebits / 8; - - spi_message_init(&st->msg); - spi_message_add_tail(&st->xfer, &st->msg); - - switch (spi_get_device_id(spi)->driver_data) { - case ID_AD5620_2500: - case ID_AD5620_1250: - case ID_AD5640_2500: - case ID_AD5640_1250: - case ID_AD5660_2500: - case ID_AD5660_1250: - st->vref_mv = st->chip_info->int_vref_mv; - break; - default: - if (voltage_uv) - st->vref_mv = voltage_uv / 1000; - else - dev_warn(&spi->dev, - "reference voltage unspecified\n"); - } - - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_device; - - return 0; - -error_free_device: - iio_free_device(indio_dev); -error_disable_reg: - if (!IS_ERR(reg)) - regulator_disable(reg); -error_put_reg: - if (!IS_ERR(reg)) - regulator_put(reg); - - return ret; -} - -static int ad5446_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad5446_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - if (!IS_ERR(st->reg)) { - regulator_disable(st->reg); - regulator_put(st->reg); - } - iio_free_device(indio_dev); - - return 0; -} - -static const struct spi_device_id ad5446_id[] = { - {"ad5444", ID_AD5444}, - {"ad5446", ID_AD5446}, - {"ad5512a", ID_AD5512A}, - {"ad5541a", ID_AD5541A}, - {"ad5542a", ID_AD5542A}, - {"ad5543", ID_AD5543}, - {"ad5553", ID_AD5553}, - {"ad5601", ID_AD5601}, - {"ad5611", ID_AD5611}, - {"ad5621", ID_AD5621}, - {"ad5620-2500", ID_AD5620_2500}, /* AD5620/40/60: */ - {"ad5620-1250", ID_AD5620_1250}, /* part numbers may look differently */ - {"ad5640-2500", ID_AD5640_2500}, - {"ad5640-1250", ID_AD5640_1250}, - {"ad5660-2500", ID_AD5660_2500}, - {"ad5660-1250", ID_AD5660_1250}, - {} -}; -MODULE_DEVICE_TABLE(spi, ad5446_id); - -static struct spi_driver ad5446_driver = { - .driver = { - .name = "ad5446", - .owner = THIS_MODULE, - }, - .probe = ad5446_probe, - .remove = __devexit_p(ad5446_remove), - .id_table = ad5446_id, -}; -module_spi_driver(ad5446_driver); - -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("Analog Devices AD5444/AD5446 DAC"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/dac/ad5446.h b/drivers/staging/iio/dac/ad5446.h deleted file mode 100644 index 4ea3476fb06..00000000000 --- a/drivers/staging/iio/dac/ad5446.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * AD5446 SPI DAC driver - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ -#ifndef IIO_DAC_AD5446_H_ -#define IIO_DAC_AD5446_H_ - -/* DAC Control Bits */ - -#define AD5446_LOAD (0x0 << 14) /* Load and update */ -#define AD5446_SDO_DIS (0x1 << 14) /* Disable SDO */ -#define AD5446_NOP (0x2 << 14) /* No operation */ -#define AD5446_CLK_RISING (0x3 << 14) /* Clock data on rising edge */ - -#define AD5620_LOAD (0x0 << 14) /* Load and update Norm Operation*/ -#define AD5620_PWRDWN_1k (0x1 << 14) /* Power-down: 1kOhm to GND */ -#define AD5620_PWRDWN_100k (0x2 << 14) /* Power-down: 100kOhm to GND */ -#define AD5620_PWRDWN_TRISTATE (0x3 << 14) /* Power-down: Three-state */ - -#define AD5660_LOAD (0x0 << 16) /* Load and update Norm Operation*/ -#define AD5660_PWRDWN_1k (0x1 << 16) /* Power-down: 1kOhm to GND */ -#define AD5660_PWRDWN_100k (0x2 << 16) /* Power-down: 100kOhm to GND */ -#define AD5660_PWRDWN_TRISTATE (0x3 << 16) /* Power-down: Three-state */ - -#define MODE_PWRDWN_1k 0x1 -#define MODE_PWRDWN_100k 0x2 -#define MODE_PWRDWN_TRISTATE 0x3 - -/** - * struct ad5446_state - driver instance specific data - * @spi: spi_device - * @chip_info: chip model specific constants, available modes etc - * @reg: supply regulator - * @poll_work: bottom half of polling interrupt handler - * @vref_mv: actual reference voltage used - * @xfer: default spi transfer - * @msg: default spi message - * @data: spi transmit buffer - */ - -struct ad5446_state { - struct spi_device *spi; - const struct ad5446_chip_info *chip_info; - struct regulator *reg; - struct work_struct poll_work; - unsigned short vref_mv; - unsigned cached_val; - unsigned pwr_down_mode; - unsigned pwr_down; - struct spi_transfer xfer; - struct spi_message msg; - union { - unsigned short d16; - unsigned char d24[3]; - } data; -}; - -/** - * struct ad5446_chip_info - chip specific information - * @channel: channel spec for the DAC - * @int_vref_mv: AD5620/40/60: the internal reference voltage - * @store_sample: chip specific helper function to store the datum - * @store_sample: chip specific helper function to store the powerpown cmd - */ - -struct ad5446_chip_info { - struct iio_chan_spec channel; - u16 int_vref_mv; - void (*store_sample) (struct ad5446_state *st, unsigned val); - void (*store_pwr_down) (struct ad5446_state *st, unsigned mode); -}; - -/** - * ad5446_supported_device_ids: - * The AD5620/40/60 parts are available in different fixed internal reference - * voltage options. The actual part numbers may look differently - * (and a bit cryptic), however this style is used to make clear which - * parts are supported here. - */ - -enum ad5446_supported_device_ids { - ID_AD5444, - ID_AD5446, - ID_AD5541A, - ID_AD5542A, - ID_AD5543, - ID_AD5512A, - ID_AD5553, - ID_AD5601, - ID_AD5611, - ID_AD5621, - ID_AD5620_2500, - ID_AD5620_1250, - ID_AD5640_2500, - ID_AD5640_1250, - ID_AD5660_2500, - ID_AD5660_1250, -}; - -#endif /* IIO_DAC_AD5446_H_ */ diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c deleted file mode 100644 index bc17205fe72..00000000000 --- a/drivers/staging/iio/dac/ad5504.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * AD5504, AD5501 High Voltage Digital to Analog Converter - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include <linux/interrupt.h> -#include <linux/fs.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/regulator/consumer.h> -#include <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" -#include "dac.h" -#include "ad5504.h" - -#define AD5504_CHANNEL(_chan) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .output = 1, \ - .channel = (_chan), \ - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ - .address = AD5504_ADDR_DAC(_chan), \ - .scan_type = IIO_ST('u', 12, 16, 0), \ -} - -static const struct iio_chan_spec ad5504_channels[] = { - AD5504_CHANNEL(0), - AD5504_CHANNEL(1), - AD5504_CHANNEL(2), - AD5504_CHANNEL(3), -}; - -static int ad5504_spi_write(struct spi_device *spi, u8 addr, u16 val) -{ - u16 tmp = cpu_to_be16(AD5504_CMD_WRITE | - AD5504_ADDR(addr) | - (val & AD5504_RES_MASK)); - - return spi_write(spi, (u8 *)&tmp, 2); -} - -static int ad5504_spi_read(struct spi_device *spi, u8 addr) -{ - u16 tmp = cpu_to_be16(AD5504_CMD_READ | AD5504_ADDR(addr)); - u16 val; - int ret; - struct spi_transfer t = { - .tx_buf = &tmp, - .rx_buf = &val, - .len = 2, - }; - struct spi_message m; - - spi_message_init(&m); - spi_message_add_tail(&t, &m); - ret = spi_sync(spi, &m); - - if (ret < 0) - return ret; - - return be16_to_cpu(val) & AD5504_RES_MASK; -} - -static int ad5504_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - struct ad5504_state *st = iio_priv(indio_dev); - unsigned long scale_uv; - int ret; - - switch (m) { - case 0: - ret = ad5504_spi_read(st->spi, chan->address); - if (ret < 0) - return ret; - - *val = ret; - - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; - - } - return -EINVAL; -} - -static int ad5504_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct ad5504_state *st = iio_priv(indio_dev); - int ret; - - switch (mask) { - case 0: - if (val >= (1 << chan->scan_type.realbits) || val < 0) - return -EINVAL; - - return ad5504_spi_write(st->spi, chan->address, val); - default: - ret = -EINVAL; - } - - return -EINVAL; -} - -static ssize_t ad5504_read_powerdown_mode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5504_state *st = iio_priv(indio_dev); - - const char mode[][14] = {"20kohm_to_gnd", "three_state"}; - - return sprintf(buf, "%s\n", mode[st->pwr_down_mode]); -} - -static ssize_t ad5504_write_powerdown_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5504_state *st = iio_priv(indio_dev); - int ret; - - if (sysfs_streq(buf, "20kohm_to_gnd")) - st->pwr_down_mode = AD5504_DAC_PWRDN_20K; - else if (sysfs_streq(buf, "three_state")) - st->pwr_down_mode = AD5504_DAC_PWRDN_3STATE; - else - ret = -EINVAL; - - return ret ? ret : len; -} - -static ssize_t ad5504_read_dac_powerdown(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5504_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - return sprintf(buf, "%d\n", - !(st->pwr_down_mask & (1 << this_attr->address))); -} - -static ssize_t ad5504_write_dac_powerdown(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - long readin; - int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5504_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = strict_strtol(buf, 10, &readin); - if (ret) - return ret; - - if (readin == 0) - st->pwr_down_mask |= (1 << this_attr->address); - else if (readin == 1) - st->pwr_down_mask &= ~(1 << this_attr->address); - else - ret = -EINVAL; - - ret = ad5504_spi_write(st->spi, AD5504_ADDR_CTRL, - AD5504_DAC_PWRDWN_MODE(st->pwr_down_mode) | - AD5504_DAC_PWR(st->pwr_down_mask)); - - /* writes to the CTRL register must be followed by a NOOP */ - ad5504_spi_write(st->spi, AD5504_ADDR_NOOP, 0); - - return ret ? ret : len; -} - -static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO | - S_IWUSR, ad5504_read_powerdown_mode, - ad5504_write_powerdown_mode, 0); - -static IIO_CONST_ATTR(out_voltage_powerdown_mode_available, - "20kohm_to_gnd three_state"); - -#define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr) \ - IIO_DEVICE_ATTR(out_voltage##_num##_powerdown, \ - S_IRUGO | S_IWUSR, _show, _store, _addr) -static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5504_read_dac_powerdown, - ad5504_write_dac_powerdown, 0); -static IIO_DEV_ATTR_DAC_POWERDOWN(1, ad5504_read_dac_powerdown, - ad5504_write_dac_powerdown, 1); -static IIO_DEV_ATTR_DAC_POWERDOWN(2, ad5504_read_dac_powerdown, - ad5504_write_dac_powerdown, 2); -static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5504_read_dac_powerdown, - ad5504_write_dac_powerdown, 3); - -static struct attribute *ad5504_attributes[] = { - &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage1_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage2_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage3_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad5504_attribute_group = { - .attrs = ad5504_attributes, -}; - -static struct attribute *ad5501_attributes[] = { - &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad5501_attribute_group = { - .attrs = ad5501_attributes, -}; - -static IIO_CONST_ATTR(temp0_thresh_rising_value, "110000"); -static IIO_CONST_ATTR(temp0_thresh_rising_en, "1"); - -static struct attribute *ad5504_ev_attributes[] = { - &iio_const_attr_temp0_thresh_rising_value.dev_attr.attr, - &iio_const_attr_temp0_thresh_rising_en.dev_attr.attr, - NULL, -}; - -static struct attribute_group ad5504_ev_attribute_group = { - .attrs = ad5504_ev_attributes, - .name = "events", -}; - -static irqreturn_t ad5504_event_handler(int irq, void *private) -{ - iio_push_event(private, - IIO_UNMOD_EVENT_CODE(IIO_TEMP, - 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - iio_get_time_ns()); - - return IRQ_HANDLED; -} - -static const struct iio_info ad5504_info = { - .write_raw = ad5504_write_raw, - .read_raw = ad5504_read_raw, - .attrs = &ad5504_attribute_group, - .event_attrs = &ad5504_ev_attribute_group, - .driver_module = THIS_MODULE, -}; - -static const struct iio_info ad5501_info = { - .write_raw = ad5504_write_raw, - .read_raw = ad5504_read_raw, - .attrs = &ad5501_attribute_group, - .event_attrs = &ad5504_ev_attribute_group, - .driver_module = THIS_MODULE, -}; - -static int __devinit ad5504_probe(struct spi_device *spi) -{ - struct ad5504_platform_data *pdata = spi->dev.platform_data; - struct iio_dev *indio_dev; - struct ad5504_state *st; - struct regulator *reg; - int ret, voltage_uv = 0; - - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - reg = regulator_get(&spi->dev, "vcc"); - if (!IS_ERR(reg)) { - ret = regulator_enable(reg); - if (ret) - goto error_put_reg; - - voltage_uv = regulator_get_voltage(reg); - } - - spi_set_drvdata(spi, indio_dev); - st = iio_priv(indio_dev); - if (voltage_uv) - st->vref_mv = voltage_uv / 1000; - else if (pdata) - st->vref_mv = pdata->vref_mv; - else - dev_warn(&spi->dev, "reference voltage unspecified\n"); - - st->reg = reg; - st->spi = spi; - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(st->spi)->name; - if (spi_get_device_id(st->spi)->driver_data == ID_AD5501) { - indio_dev->info = &ad5501_info; - indio_dev->num_channels = 1; - } else { - indio_dev->info = &ad5504_info; - indio_dev->num_channels = 4; - } - indio_dev->channels = ad5504_channels; - indio_dev->modes = INDIO_DIRECT_MODE; - - if (spi->irq) { - ret = request_threaded_irq(spi->irq, - NULL, - &ad5504_event_handler, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - spi_get_device_id(st->spi)->name, - indio_dev); - if (ret) - goto error_disable_reg; - } - - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_irq; - - return 0; - -error_free_irq: - free_irq(spi->irq, indio_dev); -error_disable_reg: - if (!IS_ERR(reg)) - regulator_disable(reg); -error_put_reg: - if (!IS_ERR(reg)) - regulator_put(reg); - - iio_free_device(indio_dev); -error_ret: - return ret; -} - -static int __devexit ad5504_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad5504_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - if (spi->irq) - free_irq(spi->irq, indio_dev); - - if (!IS_ERR(st->reg)) { - regulator_disable(st->reg); - regulator_put(st->reg); - } - iio_free_device(indio_dev); - - return 0; -} - -static const struct spi_device_id ad5504_id[] = { - {"ad5504", ID_AD5504}, - {"ad5501", ID_AD5501}, - {} -}; -MODULE_DEVICE_TABLE(spi, ad5504_id); - -static struct spi_driver ad5504_driver = { - .driver = { - .name = "ad5504", - .owner = THIS_MODULE, - }, - .probe = ad5504_probe, - .remove = __devexit_p(ad5504_remove), - .id_table = ad5504_id, -}; -module_spi_driver(ad5504_driver); - -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("Analog Devices AD5501/AD5501 DAC"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/dac/ad5504.h b/drivers/staging/iio/dac/ad5504.h deleted file mode 100644 index afe09522f53..00000000000 --- a/drivers/staging/iio/dac/ad5504.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * AD5504 SPI DAC driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#ifndef SPI_AD5504_H_ -#define SPI_AD5504_H_ - -#define AD5505_BITS 12 -#define AD5504_RES_MASK ((1 << (AD5505_BITS)) - 1) - -#define AD5504_CMD_READ (1 << 15) -#define AD5504_CMD_WRITE (0 << 15) -#define AD5504_ADDR(addr) ((addr) << 12) - -/* Registers */ -#define AD5504_ADDR_NOOP 0 -#define AD5504_ADDR_DAC(x) ((x) + 1) -#define AD5504_ADDR_ALL_DAC 5 -#define AD5504_ADDR_CTRL 7 - -/* Control Register */ -#define AD5504_DAC_PWR(ch) ((ch) << 2) -#define AD5504_DAC_PWRDWN_MODE(mode) ((mode) << 6) -#define AD5504_DAC_PWRDN_20K 0 -#define AD5504_DAC_PWRDN_3STATE 1 - -/* - * TODO: struct ad5504_platform_data needs to go into include/linux/iio - */ - -struct ad5504_platform_data { - u16 vref_mv; -}; - -/** - * struct ad5446_state - driver instance specific data - * @us: spi_device - * @reg: supply regulator - * @vref_mv: actual reference voltage used - * @pwr_down_mask power down mask - * @pwr_down_mode current power down mode - */ - -struct ad5504_state { - struct spi_device *spi; - struct regulator *reg; - unsigned short vref_mv; - unsigned pwr_down_mask; - unsigned pwr_down_mode; -}; - -/** - * ad5504_supported_device_ids: - */ - -enum ad5504_supported_device_ids { - ID_AD5504, - ID_AD5501, -}; - -#endif /* SPI_AD5504_H_ */ diff --git a/drivers/staging/iio/dac/ad5624r.h b/drivers/staging/iio/dac/ad5624r.h deleted file mode 100644 index 5dca3028cdf..00000000000 --- a/drivers/staging/iio/dac/ad5624r.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * AD5624R SPI DAC driver - * - * Copyright 2010-2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ -#ifndef SPI_AD5624R_H_ -#define SPI_AD5624R_H_ - -#define AD5624R_DAC_CHANNELS 4 - -#define AD5624R_ADDR_DAC0 0x0 -#define AD5624R_ADDR_DAC1 0x1 -#define AD5624R_ADDR_DAC2 0x2 -#define AD5624R_ADDR_DAC3 0x3 -#define AD5624R_ADDR_ALL_DAC 0x7 - -#define AD5624R_CMD_WRITE_INPUT_N 0x0 -#define AD5624R_CMD_UPDATE_DAC_N 0x1 -#define AD5624R_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2 -#define AD5624R_CMD_WRITE_INPUT_N_UPDATE_N 0x3 -#define AD5624R_CMD_POWERDOWN_DAC 0x4 -#define AD5624R_CMD_RESET 0x5 -#define AD5624R_CMD_LDAC_SETUP 0x6 -#define AD5624R_CMD_INTERNAL_REFER_SETUP 0x7 - -#define AD5624R_LDAC_PWRDN_NONE 0x0 -#define AD5624R_LDAC_PWRDN_1K 0x1 -#define AD5624R_LDAC_PWRDN_100K 0x2 -#define AD5624R_LDAC_PWRDN_3STATE 0x3 - -/** - * struct ad5624r_chip_info - chip specific information - * @channels: channel spec for the DAC - * @int_vref_mv: AD5620/40/60: the internal reference voltage - */ - -struct ad5624r_chip_info { - const struct iio_chan_spec *channels; - u16 int_vref_mv; -}; - -/** - * struct ad5446_state - driver instance specific data - * @indio_dev: the industrial I/O device - * @us: spi_device - * @chip_info: chip model specific constants, available modes etc - * @reg: supply regulator - * @vref_mv: actual reference voltage used - * @pwr_down_mask power down mask - * @pwr_down_mode current power down mode - */ - -struct ad5624r_state { - struct spi_device *us; - const struct ad5624r_chip_info *chip_info; - struct regulator *reg; - unsigned short vref_mv; - unsigned pwr_down_mask; - unsigned pwr_down_mode; -}; - -/** - * ad5624r_supported_device_ids: - * The AD5624/44/64 parts are available in different - * fixed internal reference voltage options. - */ - -enum ad5624r_supported_device_ids { - ID_AD5624R3, - ID_AD5644R3, - ID_AD5664R3, - ID_AD5624R5, - ID_AD5644R5, - ID_AD5664R5, -}; - -#endif /* SPI_AD5624R_H_ */ diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/staging/iio/dac/ad5624r_spi.c deleted file mode 100644 index 10c7484366e..00000000000 --- a/drivers/staging/iio/dac/ad5624r_spi.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * AD5624R, AD5644R, AD5664R Digital to analog convertors spi driver - * - * Copyright 2010-2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include <linux/interrupt.h> -#include <linux/fs.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/regulator/consumer.h> -#include <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "dac.h" -#include "ad5624r.h" - -#define AD5624R_CHANNEL(_chan, _bits) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .output = 1, \ - .channel = (_chan), \ - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ - .address = (_chan), \ - .scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)), \ -} - -#define DECLARE_AD5624R_CHANNELS(_name, _bits) \ - const struct iio_chan_spec _name##_channels[] = { \ - AD5624R_CHANNEL(0, _bits), \ - AD5624R_CHANNEL(1, _bits), \ - AD5624R_CHANNEL(2, _bits), \ - AD5624R_CHANNEL(3, _bits), \ -} - -static DECLARE_AD5624R_CHANNELS(ad5624r, 12); -static DECLARE_AD5624R_CHANNELS(ad5644r, 14); -static DECLARE_AD5624R_CHANNELS(ad5664r, 16); - -static const struct ad5624r_chip_info ad5624r_chip_info_tbl[] = { - [ID_AD5624R3] = { - .channels = ad5624r_channels, - .int_vref_mv = 1250, - }, - [ID_AD5624R5] = { - .channels = ad5624r_channels, - .int_vref_mv = 2500, - }, - [ID_AD5644R3] = { - .channels = ad5644r_channels, - .int_vref_mv = 1250, - }, - [ID_AD5644R5] = { - .channels = ad5644r_channels, - .int_vref_mv = 2500, - }, - [ID_AD5664R3] = { - .channels = ad5664r_channels, - .int_vref_mv = 1250, - }, - [ID_AD5664R5] = { - .channels = ad5664r_channels, - .int_vref_mv = 2500, - }, -}; - -static int ad5624r_spi_write(struct spi_device *spi, - u8 cmd, u8 addr, u16 val, u8 len) -{ - u32 data; - u8 msg[3]; - - /* - * The input shift register is 24 bits wide. The first two bits are - * don't care bits. The next three are the command bits, C2 to C0, - * followed by the 3-bit DAC address, A2 to A0, and then the - * 16-, 14-, 12-bit data-word. The data-word comprises the 16-, - * 14-, 12-bit input code followed by 0, 2, or 4 don't care bits, - * for the AD5664R, AD5644R, and AD5624R, respectively. - */ - data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << (16 - len)); - msg[0] = data >> 16; - msg[1] = data >> 8; - msg[2] = data; - - return spi_write(spi, msg, 3); -} - -static int ad5624r_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - struct ad5624r_state *st = iio_priv(indio_dev); - unsigned long scale_uv; - - switch (m) { - case IIO_CHAN_INFO_SCALE: - scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; - - } - return -EINVAL; -} - -static int ad5624r_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct ad5624r_state *st = iio_priv(indio_dev); - int ret; - - switch (mask) { - case 0: - if (val >= (1 << chan->scan_type.realbits) || val < 0) - return -EINVAL; - - return ad5624r_spi_write(st->us, - AD5624R_CMD_WRITE_INPUT_N_UPDATE_N, - chan->address, val, - chan->scan_type.shift); - default: - ret = -EINVAL; - } - - return -EINVAL; -} - -static ssize_t ad5624r_read_powerdown_mode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5624r_state *st = iio_priv(indio_dev); - - char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"}; - - return sprintf(buf, "%s\n", mode[st->pwr_down_mode]); -} - -static ssize_t ad5624r_write_powerdown_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5624r_state *st = iio_priv(indio_dev); - int ret; - - if (sysfs_streq(buf, "1kohm_to_gnd")) - st->pwr_down_mode = AD5624R_LDAC_PWRDN_1K; - else if (sysfs_streq(buf, "100kohm_to_gnd")) - st->pwr_down_mode = AD5624R_LDAC_PWRDN_100K; - else if (sysfs_streq(buf, "three_state")) - st->pwr_down_mode = AD5624R_LDAC_PWRDN_3STATE; - else - ret = -EINVAL; - - return ret ? ret : len; -} - -static ssize_t ad5624r_read_dac_powerdown(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5624r_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - return sprintf(buf, "%d\n", - !!(st->pwr_down_mask & (1 << this_attr->address))); -} - -static ssize_t ad5624r_write_dac_powerdown(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - long readin; - int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5624r_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = strict_strtol(buf, 10, &readin); - if (ret) - return ret; - - if (readin == 1) - st->pwr_down_mask |= (1 << this_attr->address); - else if (!readin) - st->pwr_down_mask &= ~(1 << this_attr->address); - else - ret = -EINVAL; - - ret = ad5624r_spi_write(st->us, AD5624R_CMD_POWERDOWN_DAC, 0, - (st->pwr_down_mode << 4) | - st->pwr_down_mask, 16); - - return ret ? ret : len; -} - -static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO | - S_IWUSR, ad5624r_read_powerdown_mode, - ad5624r_write_powerdown_mode, 0); - -static IIO_CONST_ATTR(out_voltage_powerdown_mode_available, - "1kohm_to_gnd 100kohm_to_gnd three_state"); - -#define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr) \ - IIO_DEVICE_ATTR(out_voltage##_num##_powerdown, \ - S_IRUGO | S_IWUSR, _show, _store, _addr) - -static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5624r_read_dac_powerdown, - ad5624r_write_dac_powerdown, 0); -static IIO_DEV_ATTR_DAC_POWERDOWN(1, ad5624r_read_dac_powerdown, - ad5624r_write_dac_powerdown, 1); -static IIO_DEV_ATTR_DAC_POWERDOWN(2, ad5624r_read_dac_powerdown, - ad5624r_write_dac_powerdown, 2); -static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5624r_read_dac_powerdown, - ad5624r_write_dac_powerdown, 3); - -static struct attribute *ad5624r_attributes[] = { - &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage1_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage2_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage3_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad5624r_attribute_group = { - .attrs = ad5624r_attributes, -}; - -static const struct iio_info ad5624r_info = { - .write_raw = ad5624r_write_raw, - .read_raw = ad5624r_read_raw, - .attrs = &ad5624r_attribute_group, - .driver_module = THIS_MODULE, -}; - -static int __devinit ad5624r_probe(struct spi_device *spi) -{ - struct ad5624r_state *st; - struct iio_dev *indio_dev; - int ret, voltage_uv = 0; - - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - st = iio_priv(indio_dev); - st->reg = regulator_get(&spi->dev, "vcc"); - if (!IS_ERR(st->reg)) { - ret = regulator_enable(st->reg); - if (ret) - goto error_put_reg; - - voltage_uv = regulator_get_voltage(st->reg); - } - - spi_set_drvdata(spi, indio_dev); - st->chip_info = - &ad5624r_chip_info_tbl[spi_get_device_id(spi)->driver_data]; - - if (voltage_uv) - st->vref_mv = voltage_uv / 1000; - else - st->vref_mv = st->chip_info->int_vref_mv; - - st->us = spi; - - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->info = &ad5624r_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = st->chip_info->channels; - indio_dev->num_channels = AD5624R_DAC_CHANNELS; - - ret = ad5624r_spi_write(spi, AD5624R_CMD_INTERNAL_REFER_SETUP, 0, - !!voltage_uv, 16); - if (ret) - goto error_disable_reg; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_disable_reg; - - return 0; - -error_disable_reg: - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); -error_put_reg: - if (!IS_ERR(st->reg)) - regulator_put(st->reg); - iio_free_device(indio_dev); -error_ret: - - return ret; -} - -static int __devexit ad5624r_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad5624r_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - if (!IS_ERR(st->reg)) { - regulator_disable(st->reg); - regulator_put(st->reg); - } - iio_free_device(indio_dev); - - return 0; -} - -static const struct spi_device_id ad5624r_id[] = { - {"ad5624r3", ID_AD5624R3}, - {"ad5644r3", ID_AD5644R3}, - {"ad5664r3", ID_AD5664R3}, - {"ad5624r5", ID_AD5624R5}, - {"ad5644r5", ID_AD5644R5}, - {"ad5664r5", ID_AD5664R5}, - {} -}; -MODULE_DEVICE_TABLE(spi, ad5624r_id); - -static struct spi_driver ad5624r_driver = { - .driver = { - .name = "ad5624r", - .owner = THIS_MODULE, - }, - .probe = ad5624r_probe, - .remove = __devexit_p(ad5624r_remove), - .id_table = ad5624r_id, -}; -module_spi_driver(ad5624r_driver); - -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_DESCRIPTION("Analog Devices AD5624/44/64R DAC spi driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/dac/ad5686.c b/drivers/staging/iio/dac/ad5686.c deleted file mode 100644 index ce2d6193dd8..00000000000 --- a/drivers/staging/iio/dac/ad5686.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * AD5686R, AD5685R, AD5684R Digital to analog converters driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include <linux/interrupt.h> -#include <linux/fs.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/regulator/consumer.h> -#include <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "dac.h" - -#define AD5686_DAC_CHANNELS 4 - -#define AD5686_ADDR(x) ((x) << 16) -#define AD5686_CMD(x) ((x) << 20) - -#define AD5686_ADDR_DAC(chan) (0x1 << (chan)) -#define AD5686_ADDR_ALL_DAC 0xF - -#define AD5686_CMD_NOOP 0x0 -#define AD5686_CMD_WRITE_INPUT_N 0x1 -#define AD5686_CMD_UPDATE_DAC_N 0x2 -#define AD5686_CMD_WRITE_INPUT_N_UPDATE_N 0x3 -#define AD5686_CMD_POWERDOWN_DAC 0x4 -#define AD5686_CMD_LDAC_MASK 0x5 -#define AD5686_CMD_RESET 0x6 -#define AD5686_CMD_INTERNAL_REFER_SETUP 0x7 -#define AD5686_CMD_DAISY_CHAIN_ENABLE 0x8 -#define AD5686_CMD_READBACK_ENABLE 0x9 - -#define AD5686_LDAC_PWRDN_NONE 0x0 -#define AD5686_LDAC_PWRDN_1K 0x1 -#define AD5686_LDAC_PWRDN_100K 0x2 -#define AD5686_LDAC_PWRDN_3STATE 0x3 - -/** - * struct ad5686_chip_info - chip specific information - * @int_vref_mv: AD5620/40/60: the internal reference voltage - * @channel: channel specification -*/ - -struct ad5686_chip_info { - u16 int_vref_mv; - struct iio_chan_spec channel[AD5686_DAC_CHANNELS]; -}; - -/** - * struct ad5446_state - driver instance specific data - * @spi: spi_device - * @chip_info: chip model specific constants, available modes etc - * @reg: supply regulator - * @vref_mv: actual reference voltage used - * @pwr_down_mask: power down mask - * @pwr_down_mode: current power down mode - * @data: spi transfer buffers - */ - -struct ad5686_state { - struct spi_device *spi; - const struct ad5686_chip_info *chip_info; - struct regulator *reg; - unsigned short vref_mv; - unsigned pwr_down_mask; - unsigned pwr_down_mode; - /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - */ - - union { - u32 d32; - u8 d8[4]; - } data[3] ____cacheline_aligned; -}; - -/** - * ad5686_supported_device_ids: - */ - -enum ad5686_supported_device_ids { - ID_AD5684, - ID_AD5685, - ID_AD5686, -}; -#define AD5868_CHANNEL(chan, bits, shift) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .output = 1, \ - .channel = chan, \ - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ - .address = AD5686_ADDR_DAC(chan), \ - .scan_type = IIO_ST('u', bits, 16, shift) \ -} -static const struct ad5686_chip_info ad5686_chip_info_tbl[] = { - [ID_AD5684] = { - .channel[0] = AD5868_CHANNEL(0, 12, 4), - .channel[1] = AD5868_CHANNEL(1, 12, 4), - .channel[2] = AD5868_CHANNEL(2, 12, 4), - .channel[3] = AD5868_CHANNEL(3, 12, 4), - .int_vref_mv = 2500, - }, - [ID_AD5685] = { - .channel[0] = AD5868_CHANNEL(0, 14, 2), - .channel[1] = AD5868_CHANNEL(1, 14, 2), - .channel[2] = AD5868_CHANNEL(2, 14, 2), - .channel[3] = AD5868_CHANNEL(3, 14, 2), - .int_vref_mv = 2500, - }, - [ID_AD5686] = { - .channel[0] = AD5868_CHANNEL(0, 16, 0), - .channel[1] = AD5868_CHANNEL(1, 16, 0), - .channel[2] = AD5868_CHANNEL(2, 16, 0), - .channel[3] = AD5868_CHANNEL(3, 16, 0), - .int_vref_mv = 2500, - }, -}; - -static int ad5686_spi_write(struct ad5686_state *st, - u8 cmd, u8 addr, u16 val, u8 shift) -{ - val <<= shift; - - st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) | - AD5686_ADDR(addr) | - val); - - return spi_write(st->spi, &st->data[0].d8[1], 3); -} - -static int ad5686_spi_read(struct ad5686_state *st, u8 addr) -{ - struct spi_transfer t[] = { - { - .tx_buf = &st->data[0].d8[1], - .len = 3, - .cs_change = 1, - }, { - .tx_buf = &st->data[1].d8[1], - .rx_buf = &st->data[2].d8[1], - .len = 3, - }, - }; - struct spi_message m; - int ret; - - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - spi_message_add_tail(&t[1], &m); - - st->data[0].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_READBACK_ENABLE) | - AD5686_ADDR(addr)); - st->data[1].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP)); - - ret = spi_sync(st->spi, &m); - if (ret < 0) - return ret; - - return be32_to_cpu(st->data[2].d32); -} - -static ssize_t ad5686_read_powerdown_mode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5686_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"}; - - return sprintf(buf, "%s\n", mode[(st->pwr_down_mode >> - (this_attr->address * 2)) & 0x3]); -} - -static ssize_t ad5686_write_powerdown_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5686_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - unsigned mode; - - if (sysfs_streq(buf, "1kohm_to_gnd")) - mode = AD5686_LDAC_PWRDN_1K; - else if (sysfs_streq(buf, "100kohm_to_gnd")) - mode = AD5686_LDAC_PWRDN_100K; - else if (sysfs_streq(buf, "three_state")) - mode = AD5686_LDAC_PWRDN_3STATE; - else - return -EINVAL; - - st->pwr_down_mode &= ~(0x3 << (this_attr->address * 2)); - st->pwr_down_mode |= (mode << (this_attr->address * 2)); - - return len; -} - -static ssize_t ad5686_read_dac_powerdown(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5686_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - return sprintf(buf, "%d\n", !!(st->pwr_down_mask & - (0x3 << (this_attr->address * 2)))); -} - -static ssize_t ad5686_write_dac_powerdown(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - bool readin; - int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5686_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = strtobool(buf, &readin); - if (ret) - return ret; - - if (readin == true) - st->pwr_down_mask |= (0x3 << (this_attr->address * 2)); - else - st->pwr_down_mask &= ~(0x3 << (this_attr->address * 2)); - - ret = ad5686_spi_write(st, AD5686_CMD_POWERDOWN_DAC, 0, - st->pwr_down_mask & st->pwr_down_mode, 0); - - return ret ? ret : len; -} - -static IIO_CONST_ATTR(out_voltage_powerdown_mode_available, - "1kohm_to_gnd 100kohm_to_gnd three_state"); - -#define IIO_DEV_ATTR_DAC_POWERDOWN_MODE(_num) \ - IIO_DEVICE_ATTR(out_voltage##_num##_powerdown_mode, \ - S_IRUGO | S_IWUSR, \ - ad5686_read_powerdown_mode, \ - ad5686_write_powerdown_mode, _num) - -static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(0); -static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(1); -static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(2); -static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(3); - -#define IIO_DEV_ATTR_DAC_POWERDOWN(_num) \ - IIO_DEVICE_ATTR(out_voltage##_num##_powerdown, \ - S_IRUGO | S_IWUSR, \ - ad5686_read_dac_powerdown, \ - ad5686_write_dac_powerdown, _num) - -static IIO_DEV_ATTR_DAC_POWERDOWN(0); -static IIO_DEV_ATTR_DAC_POWERDOWN(1); -static IIO_DEV_ATTR_DAC_POWERDOWN(2); -static IIO_DEV_ATTR_DAC_POWERDOWN(3); - -static struct attribute *ad5686_attributes[] = { - &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage1_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage2_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage3_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage0_powerdown_mode.dev_attr.attr, - &iio_dev_attr_out_voltage1_powerdown_mode.dev_attr.attr, - &iio_dev_attr_out_voltage2_powerdown_mode.dev_attr.attr, - &iio_dev_attr_out_voltage3_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad5686_attribute_group = { - .attrs = ad5686_attributes, -}; - -static int ad5686_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - struct ad5686_state *st = iio_priv(indio_dev); - unsigned long scale_uv; - int ret; - - switch (m) { - case 0: - mutex_lock(&indio_dev->mlock); - ret = ad5686_spi_read(st, chan->address); - mutex_unlock(&indio_dev->mlock); - if (ret < 0) - return ret; - *val = ret; - return IIO_VAL_INT; - break; - case IIO_CHAN_INFO_SCALE: - scale_uv = (st->vref_mv * 100000) - >> (chan->scan_type.realbits); - *val = scale_uv / 100000; - *val2 = (scale_uv % 100000) * 10; - return IIO_VAL_INT_PLUS_MICRO; - - } - return -EINVAL; -} - -static int ad5686_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct ad5686_state *st = iio_priv(indio_dev); - int ret; - - switch (mask) { - case 0: - if (val > (1 << chan->scan_type.realbits) || val < 0) - return -EINVAL; - - mutex_lock(&indio_dev->mlock); - ret = ad5686_spi_write(st, - AD5686_CMD_WRITE_INPUT_N_UPDATE_N, - chan->address, - val, - chan->scan_type.shift); - mutex_unlock(&indio_dev->mlock); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static const struct iio_info ad5686_info = { - .read_raw = ad5686_read_raw, - .write_raw = ad5686_write_raw, - .attrs = &ad5686_attribute_group, - .driver_module = THIS_MODULE, -}; - -static int __devinit ad5686_probe(struct spi_device *spi) -{ - struct ad5686_state *st; - struct iio_dev *indio_dev; - int ret, regdone = 0, voltage_uv = 0; - - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) - return -ENOMEM; - - st = iio_priv(indio_dev); - spi_set_drvdata(spi, indio_dev); - - st->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 = - &ad5686_chip_info_tbl[spi_get_device_id(spi)->driver_data]; - - if (voltage_uv) - st->vref_mv = voltage_uv / 1000; - else - st->vref_mv = st->chip_info->int_vref_mv; - - st->spi = spi; - - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->info = &ad5686_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = st->chip_info->channel; - indio_dev->num_channels = AD5686_DAC_CHANNELS; - - regdone = 1; - ret = ad5686_spi_write(st, AD5686_CMD_INTERNAL_REFER_SETUP, 0, - !!voltage_uv, 0); - if (ret) - goto error_disable_reg; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_disable_reg; - - return 0; - -error_disable_reg: - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); -error_put_reg: - if (!IS_ERR(st->reg)) - regulator_put(st->reg); - - iio_free_device(indio_dev); - - return ret; -} - -static int __devexit ad5686_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad5686_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - if (!IS_ERR(st->reg)) { - regulator_disable(st->reg); - regulator_put(st->reg); - } - iio_free_device(indio_dev); - - return 0; -} - -static const struct spi_device_id ad5686_id[] = { - {"ad5684", ID_AD5684}, - {"ad5685", ID_AD5685}, - {"ad5686", ID_AD5686}, - {} -}; -MODULE_DEVICE_TABLE(spi, ad5686_id); - -static struct spi_driver ad5686_driver = { - .driver = { - .name = "ad5686", - .owner = THIS_MODULE, - }, - .probe = ad5686_probe, - .remove = __devexit_p(ad5686_remove), - .id_table = ad5686_id, -}; -module_spi_driver(ad5686_driver); - -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("Analog Devices AD5686/85/84 DAC"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/dac/ad5764.c b/drivers/staging/iio/dac/ad5764.c deleted file mode 100644 index ff91480ae65..00000000000 --- a/drivers/staging/iio/dac/ad5764.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Analog devices AD5764, AD5764R, AD5744, AD5744R quad-channel - * Digital to Analog Converters driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include <linux/device.h> -#include <linux/err.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/regulator/consumer.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "dac.h" - -#define AD5764_REG_SF_NOP 0x0 -#define AD5764_REG_SF_CONFIG 0x1 -#define AD5764_REG_SF_CLEAR 0x4 -#define AD5764_REG_SF_LOAD 0x5 -#define AD5764_REG_DATA(x) ((2 << 3) | (x)) -#define AD5764_REG_COARSE_GAIN(x) ((3 << 3) | (x)) -#define AD5764_REG_FINE_GAIN(x) ((4 << 3) | (x)) -#define AD5764_REG_OFFSET(x) ((5 << 3) | (x)) - -#define AD5764_NUM_CHANNELS 4 - -/** - * struct ad5764_chip_info - chip specific information - * @int_vref: Value of the internal reference voltage in uV - 0 if external - * reference voltage is used - * @channel channel specification -*/ - -struct ad5764_chip_info { - unsigned long int_vref; - const struct iio_chan_spec *channels; -}; - -/** - * struct ad5764_state - driver instance specific data - * @spi: spi_device - * @chip_info: chip info - * @vref_reg: vref supply regulators - * @data: spi transfer buffers - */ - -struct ad5764_state { - struct spi_device *spi; - const struct ad5764_chip_info *chip_info; - struct regulator_bulk_data vref_reg[2]; - - /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - */ - union { - __be32 d32; - u8 d8[4]; - } data[2] ____cacheline_aligned; -}; - -enum ad5764_type { - ID_AD5744, - ID_AD5744R, - ID_AD5764, - ID_AD5764R, -}; - -#define AD5764_CHANNEL(_chan, _bits) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .output = 1, \ - .channel = (_chan), \ - .address = (_chan), \ - .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT | \ - IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \ - IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \ - .scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)) \ -} - -#define DECLARE_AD5764_CHANNELS(_name, _bits) \ -const struct iio_chan_spec _name##_channels[] = { \ - AD5764_CHANNEL(0, (_bits)), \ - AD5764_CHANNEL(1, (_bits)), \ - AD5764_CHANNEL(2, (_bits)), \ - AD5764_CHANNEL(3, (_bits)), \ -}; - -static DECLARE_AD5764_CHANNELS(ad5764, 16); -static DECLARE_AD5764_CHANNELS(ad5744, 14); - -static const struct ad5764_chip_info ad5764_chip_infos[] = { - [ID_AD5744] = { - .int_vref = 0, - .channels = ad5744_channels, - }, - [ID_AD5744R] = { - .int_vref = 5000000, - .channels = ad5744_channels, - }, - [ID_AD5764] = { - .int_vref = 0, - .channels = ad5764_channels, - }, - [ID_AD5764R] = { - .int_vref = 5000000, - .channels = ad5764_channels, - }, -}; - -static int ad5764_write(struct iio_dev *indio_dev, unsigned int reg, - unsigned int val) -{ - struct ad5764_state *st = iio_priv(indio_dev); - int ret; - - mutex_lock(&indio_dev->mlock); - st->data[0].d32 = cpu_to_be32((reg << 16) | val); - - ret = spi_write(st->spi, &st->data[0].d8[1], 3); - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static int ad5764_read(struct iio_dev *indio_dev, unsigned int reg, - unsigned int *val) -{ - struct ad5764_state *st = iio_priv(indio_dev); - struct spi_message m; - int ret; - struct spi_transfer t[] = { - { - .tx_buf = &st->data[0].d8[1], - .len = 3, - .cs_change = 1, - }, { - .rx_buf = &st->data[1].d8[1], - .len = 3, - }, - }; - - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - spi_message_add_tail(&t[1], &m); - - mutex_lock(&indio_dev->mlock); - - st->data[0].d32 = cpu_to_be32((1 << 23) | (reg << 16)); - - ret = spi_sync(st->spi, &m); - if (ret >= 0) - *val = be32_to_cpu(st->data[1].d32) & 0xffff; - - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static int ad5764_chan_info_to_reg(struct iio_chan_spec const *chan, long info) -{ - switch (info) { - case 0: - return AD5764_REG_DATA(chan->address); - case IIO_CHAN_INFO_CALIBBIAS: - return AD5764_REG_OFFSET(chan->address); - case IIO_CHAN_INFO_CALIBSCALE: - return AD5764_REG_FINE_GAIN(chan->address); - default: - break; - } - - return 0; -} - -static int ad5764_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int val, int val2, long info) -{ - const int max_val = (1 << chan->scan_type.realbits); - unsigned int reg; - - switch (info) { - case 0: - if (val >= max_val || val < 0) - return -EINVAL; - val <<= chan->scan_type.shift; - break; - case IIO_CHAN_INFO_CALIBBIAS: - if (val >= 128 || val < -128) - return -EINVAL; - break; - case IIO_CHAN_INFO_CALIBSCALE: - if (val >= 32 || val < -32) - return -EINVAL; - break; - default: - return -EINVAL; - } - - reg = ad5764_chan_info_to_reg(chan, info); - return ad5764_write(indio_dev, reg, (u16)val); -} - -static int ad5764_get_channel_vref(struct ad5764_state *st, - unsigned int channel) -{ - if (st->chip_info->int_vref) - return st->chip_info->int_vref; - else - return regulator_get_voltage(st->vref_reg[channel / 2].consumer); -} - -static int ad5764_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int *val, int *val2, long info) -{ - struct ad5764_state *st = iio_priv(indio_dev); - unsigned long scale_uv; - unsigned int reg; - int vref; - int ret; - - switch (info) { - case 0: - reg = AD5764_REG_DATA(chan->address); - ret = ad5764_read(indio_dev, reg, val); - if (ret < 0) - return ret; - *val >>= chan->scan_type.shift; - return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBBIAS: - reg = AD5764_REG_OFFSET(chan->address); - ret = ad5764_read(indio_dev, reg, val); - if (ret < 0) - return ret; - *val = sign_extend32(*val, 7); - return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBSCALE: - reg = AD5764_REG_FINE_GAIN(chan->address); - ret = ad5764_read(indio_dev, reg, val); - if (ret < 0) - return ret; - *val = sign_extend32(*val, 5); - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - /* vout = 4 * vref + ((dac_code / 65535) - 0.5) */ - vref = ad5764_get_channel_vref(st, chan->channel); - if (vref < 0) - return vref; - - scale_uv = (vref * 4 * 100) >> chan->scan_type.realbits; - *val = scale_uv / 100000; - *val2 = (scale_uv % 100000) * 10; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_OFFSET: - *val = -(1 << chan->scan_type.realbits) / 2; - return IIO_VAL_INT; - } - - return -EINVAL; -} - -static const struct iio_info ad5764_info = { - .read_raw = ad5764_read_raw, - .write_raw = ad5764_write_raw, - .driver_module = THIS_MODULE, -}; - -static int __devinit ad5764_probe(struct spi_device *spi) -{ - enum ad5764_type type = spi_get_device_id(spi)->driver_data; - struct iio_dev *indio_dev; - struct ad5764_state *st; - int ret; - - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - dev_err(&spi->dev, "Failed to allocate iio device\n"); - return -ENOMEM; - } - - st = iio_priv(indio_dev); - spi_set_drvdata(spi, indio_dev); - - st->spi = spi; - st->chip_info = &ad5764_chip_infos[type]; - - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->info = &ad5764_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->num_channels = AD5764_NUM_CHANNELS; - indio_dev->channels = st->chip_info->channels; - - if (st->chip_info->int_vref == 0) { - st->vref_reg[0].supply = "vrefAB"; - st->vref_reg[1].supply = "vrefCD"; - - ret = regulator_bulk_get(&st->spi->dev, - ARRAY_SIZE(st->vref_reg), st->vref_reg); - if (ret) { - dev_err(&spi->dev, "Failed to request vref regulators: %d\n", - ret); - goto error_free; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(st->vref_reg), - st->vref_reg); - if (ret) { - dev_err(&spi->dev, "Failed to enable vref regulators: %d\n", - ret); - goto error_free_reg; - } - } - - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(&spi->dev, "Failed to register iio device: %d\n", ret); - goto error_disable_reg; - } - - return 0; - -error_disable_reg: - if (st->chip_info->int_vref == 0) - regulator_bulk_disable(ARRAY_SIZE(st->vref_reg), st->vref_reg); -error_free_reg: - if (st->chip_info->int_vref == 0) - regulator_bulk_free(ARRAY_SIZE(st->vref_reg), st->vref_reg); -error_free: - iio_free_device(indio_dev); - - return ret; -} - -static int __devexit ad5764_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad5764_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - if (st->chip_info->int_vref == 0) { - regulator_bulk_disable(ARRAY_SIZE(st->vref_reg), st->vref_reg); - regulator_bulk_free(ARRAY_SIZE(st->vref_reg), st->vref_reg); - } - - iio_free_device(indio_dev); - - return 0; -} - -static const struct spi_device_id ad5764_ids[] = { - { "ad5744", ID_AD5744 }, - { "ad5744r", ID_AD5744R }, - { "ad5764", ID_AD5764 }, - { "ad5764r", ID_AD5764R }, - { } -}; -MODULE_DEVICE_TABLE(spi, ad5764_ids); - -static struct spi_driver ad5764_driver = { - .driver = { - .name = "ad5764", - .owner = THIS_MODULE, - }, - .probe = ad5764_probe, - .remove = __devexit_p(ad5764_remove), - .id_table = ad5764_ids, -}; - -static int __init ad5764_spi_init(void) -{ - return spi_register_driver(&ad5764_driver); -} -module_init(ad5764_spi_init); - -static void __exit ad5764_spi_exit(void) -{ - spi_unregister_driver(&ad5764_driver); -} -module_exit(ad5764_spi_exit); - -MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); -MODULE_DESCRIPTION("Analog Devices AD5744/AD5744R/AD5764/AD5764R DAC"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c deleted file mode 100644 index ac45636a8d7..00000000000 --- a/drivers/staging/iio/dac/ad5791.c +++ /dev/null @@ -1,420 +0,0 @@ -/* - * AD5760, AD5780, AD5781, AD5790, AD5791 Voltage Output Digital to Analog - * Converter - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include <linux/interrupt.h> -#include <linux/fs.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/regulator/consumer.h> -#include <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "dac.h" -#include "ad5791.h" - -static int ad5791_spi_write(struct spi_device *spi, u8 addr, u32 val) -{ - union { - u32 d32; - u8 d8[4]; - } data; - - data.d32 = cpu_to_be32(AD5791_CMD_WRITE | - AD5791_ADDR(addr) | - (val & AD5791_DAC_MASK)); - - return spi_write(spi, &data.d8[1], 3); -} - -static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val) -{ - union { - u32 d32; - u8 d8[4]; - } data[3]; - int ret; - struct spi_message msg; - struct spi_transfer xfers[] = { - { - .tx_buf = &data[0].d8[1], - .bits_per_word = 8, - .len = 3, - .cs_change = 1, - }, { - .tx_buf = &data[1].d8[1], - .rx_buf = &data[2].d8[1], - .bits_per_word = 8, - .len = 3, - }, - }; - - data[0].d32 = cpu_to_be32(AD5791_CMD_READ | - AD5791_ADDR(addr)); - data[1].d32 = cpu_to_be32(AD5791_ADDR(AD5791_ADDR_NOOP)); - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(spi, &msg); - - *val = be32_to_cpu(data[2].d32); - - return ret; -} - -#define AD5791_CHAN(bits, shift) { \ - .type = IIO_VOLTAGE, \ - .output = 1, \ - .indexed = 1, \ - .address = AD5791_ADDR_DAC0, \ - .channel = 0, \ - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | \ - IIO_CHAN_INFO_OFFSET_SHARED_BIT, \ - .scan_type = IIO_ST('u', bits, 24, shift) \ -} - -static const struct iio_chan_spec ad5791_channels[] = { - [ID_AD5760] = AD5791_CHAN(16, 4), - [ID_AD5780] = AD5791_CHAN(18, 2), - [ID_AD5781] = AD5791_CHAN(18, 2), - [ID_AD5791] = AD5791_CHAN(20, 0) -}; - -static ssize_t ad5791_read_powerdown_mode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5791_state *st = iio_priv(indio_dev); - - const char mode[][14] = {"6kohm_to_gnd", "three_state"}; - - return sprintf(buf, "%s\n", mode[st->pwr_down_mode]); -} - -static ssize_t ad5791_write_powerdown_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5791_state *st = iio_priv(indio_dev); - int ret; - - if (sysfs_streq(buf, "6kohm_to_gnd")) - st->pwr_down_mode = AD5791_DAC_PWRDN_6K; - else if (sysfs_streq(buf, "three_state")) - st->pwr_down_mode = AD5791_DAC_PWRDN_3STATE; - else - ret = -EINVAL; - - return ret ? ret : len; -} - -static ssize_t ad5791_read_dac_powerdown(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5791_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", st->pwr_down); -} - -static ssize_t ad5791_write_dac_powerdown(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - long readin; - int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5791_state *st = iio_priv(indio_dev); - - ret = strict_strtol(buf, 10, &readin); - if (ret) - return ret; - - if (readin == 0) { - st->pwr_down = false; - st->ctrl &= ~(AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI); - } else if (readin == 1) { - st->pwr_down = true; - if (st->pwr_down_mode == AD5791_DAC_PWRDN_6K) - st->ctrl |= AD5791_CTRL_OPGND; - else if (st->pwr_down_mode == AD5791_DAC_PWRDN_3STATE) - st->ctrl |= AD5791_CTRL_DACTRI; - } else - ret = -EINVAL; - - ret = ad5791_spi_write(st->spi, AD5791_ADDR_CTRL, st->ctrl); - - return ret ? ret : len; -} - -static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO | - S_IWUSR, ad5791_read_powerdown_mode, - ad5791_write_powerdown_mode, 0); - -static IIO_CONST_ATTR(out_voltage_powerdown_mode_available, - "6kohm_to_gnd three_state"); - -#define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr) \ - IIO_DEVICE_ATTR(out_voltage##_num##_powerdown, \ - S_IRUGO | S_IWUSR, _show, _store, _addr) - -static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5791_read_dac_powerdown, - ad5791_write_dac_powerdown, 0); - -static struct attribute *ad5791_attributes[] = { - &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad5791_attribute_group = { - .attrs = ad5791_attributes, -}; - -static int ad5791_get_lin_comp(unsigned int span) -{ - if (span <= 10000) - return AD5791_LINCOMP_0_10; - else if (span <= 12000) - return AD5791_LINCOMP_10_12; - else if (span <= 16000) - return AD5791_LINCOMP_12_16; - else if (span <= 19000) - return AD5791_LINCOMP_16_19; - else - return AD5791_LINCOMP_19_20; -} - -static int ad5780_get_lin_comp(unsigned int span) -{ - if (span <= 10000) - return AD5780_LINCOMP_0_10; - else - return AD5780_LINCOMP_10_20; -} -static const struct ad5791_chip_info ad5791_chip_info_tbl[] = { - [ID_AD5760] = { - .get_lin_comp = ad5780_get_lin_comp, - }, - [ID_AD5780] = { - .get_lin_comp = ad5780_get_lin_comp, - }, - [ID_AD5781] = { - .get_lin_comp = ad5791_get_lin_comp, - }, - [ID_AD5791] = { - .get_lin_comp = ad5791_get_lin_comp, - }, -}; - -static int ad5791_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - struct ad5791_state *st = iio_priv(indio_dev); - u64 val64; - int ret; - - switch (m) { - case 0: - ret = ad5791_spi_read(st->spi, chan->address, val); - if (ret) - return ret; - *val &= AD5791_DAC_MASK; - *val >>= chan->scan_type.shift; - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - *val = 0; - *val2 = (((u64)st->vref_mv) * 1000000ULL) >> chan->scan_type.realbits; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_OFFSET: - val64 = (((u64)st->vref_neg_mv) << chan->scan_type.realbits); - do_div(val64, st->vref_mv); - *val = -val64; - return IIO_VAL_INT; - default: - return -EINVAL; - } - -}; - - -static int ad5791_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct ad5791_state *st = iio_priv(indio_dev); - - switch (mask) { - case 0: - val &= AD5791_RES_MASK(chan->scan_type.realbits); - val <<= chan->scan_type.shift; - - return ad5791_spi_write(st->spi, chan->address, val); - - default: - return -EINVAL; - } -} - -static const struct iio_info ad5791_info = { - .read_raw = &ad5791_read_raw, - .write_raw = &ad5791_write_raw, - .attrs = &ad5791_attribute_group, - .driver_module = THIS_MODULE, -}; - -static int __devinit ad5791_probe(struct spi_device *spi) -{ - struct ad5791_platform_data *pdata = spi->dev.platform_data; - struct iio_dev *indio_dev; - struct ad5791_state *st; - int ret, pos_voltage_uv = 0, neg_voltage_uv = 0; - - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - st = iio_priv(indio_dev); - st->reg_vdd = regulator_get(&spi->dev, "vdd"); - if (!IS_ERR(st->reg_vdd)) { - ret = regulator_enable(st->reg_vdd); - if (ret) - goto error_put_reg_pos; - - pos_voltage_uv = regulator_get_voltage(st->reg_vdd); - } - - st->reg_vss = regulator_get(&spi->dev, "vss"); - if (!IS_ERR(st->reg_vss)) { - ret = regulator_enable(st->reg_vss); - if (ret) - goto error_put_reg_neg; - - neg_voltage_uv = regulator_get_voltage(st->reg_vss); - } - - st->pwr_down = true; - st->spi = spi; - - if (!IS_ERR(st->reg_vss) && !IS_ERR(st->reg_vdd)) { - st->vref_mv = (pos_voltage_uv + neg_voltage_uv) / 1000; - st->vref_neg_mv = neg_voltage_uv / 1000; - } else if (pdata) { - st->vref_mv = pdata->vref_pos_mv + pdata->vref_neg_mv; - st->vref_neg_mv = pdata->vref_neg_mv; - } else { - dev_warn(&spi->dev, "reference voltage unspecified\n"); - } - - ret = ad5791_spi_write(spi, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET); - if (ret) - goto error_disable_reg_neg; - - st->chip_info = &ad5791_chip_info_tbl[spi_get_device_id(spi) - ->driver_data]; - - - st->ctrl = AD5761_CTRL_LINCOMP(st->chip_info->get_lin_comp(st->vref_mv)) - | ((pdata && pdata->use_rbuf_gain2) ? 0 : AD5791_CTRL_RBUF) | - AD5791_CTRL_BIN2SC; - - ret = ad5791_spi_write(spi, AD5791_ADDR_CTRL, st->ctrl | - AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI); - if (ret) - goto error_disable_reg_neg; - - spi_set_drvdata(spi, indio_dev); - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &ad5791_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels - = &ad5791_channels[spi_get_device_id(spi)->driver_data]; - indio_dev->num_channels = 1; - indio_dev->name = spi_get_device_id(st->spi)->name; - ret = iio_device_register(indio_dev); - if (ret) - goto error_disable_reg_neg; - - return 0; - -error_disable_reg_neg: - if (!IS_ERR(st->reg_vss)) - regulator_disable(st->reg_vss); -error_put_reg_neg: - if (!IS_ERR(st->reg_vss)) - regulator_put(st->reg_vss); - - if (!IS_ERR(st->reg_vdd)) - regulator_disable(st->reg_vdd); -error_put_reg_pos: - if (!IS_ERR(st->reg_vdd)) - regulator_put(st->reg_vdd); - iio_free_device(indio_dev); -error_ret: - - return ret; -} - -static int __devexit ad5791_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad5791_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - if (!IS_ERR(st->reg_vdd)) { - regulator_disable(st->reg_vdd); - regulator_put(st->reg_vdd); - } - - if (!IS_ERR(st->reg_vss)) { - regulator_disable(st->reg_vss); - regulator_put(st->reg_vss); - } - iio_free_device(indio_dev); - - return 0; -} - -static const struct spi_device_id ad5791_id[] = { - {"ad5760", ID_AD5760}, - {"ad5780", ID_AD5780}, - {"ad5781", ID_AD5781}, - {"ad5790", ID_AD5791}, - {"ad5791", ID_AD5791}, - {} -}; -MODULE_DEVICE_TABLE(spi, ad5791_id); - -static struct spi_driver ad5791_driver = { - .driver = { - .name = "ad5791", - .owner = THIS_MODULE, - }, - .probe = ad5791_probe, - .remove = __devexit_p(ad5791_remove), - .id_table = ad5791_id, -}; -module_spi_driver(ad5791_driver); - -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("Analog Devices AD5760/AD5780/AD5781/AD5790/AD5791 DAC"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/dac/ad5791.h b/drivers/staging/iio/dac/ad5791.h deleted file mode 100644 index fd7edbdb4ec..00000000000 --- a/drivers/staging/iio/dac/ad5791.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * AD5791 SPI DAC driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#ifndef SPI_AD5791_H_ -#define SPI_AD5791_H_ - -#define AD5791_RES_MASK(x) ((1 << (x)) - 1) -#define AD5791_DAC_MASK AD5791_RES_MASK(20) -#define AD5791_DAC_MSB (1 << 19) - -#define AD5791_CMD_READ (1 << 23) -#define AD5791_CMD_WRITE (0 << 23) -#define AD5791_ADDR(addr) ((addr) << 20) - -/* Registers */ -#define AD5791_ADDR_NOOP 0 -#define AD5791_ADDR_DAC0 1 -#define AD5791_ADDR_CTRL 2 -#define AD5791_ADDR_CLRCODE 3 -#define AD5791_ADDR_SW_CTRL 4 - -/* Control Register */ -#define AD5791_CTRL_RBUF (1 << 1) -#define AD5791_CTRL_OPGND (1 << 2) -#define AD5791_CTRL_DACTRI (1 << 3) -#define AD5791_CTRL_BIN2SC (1 << 4) -#define AD5791_CTRL_SDODIS (1 << 5) -#define AD5761_CTRL_LINCOMP(x) ((x) << 6) - -#define AD5791_LINCOMP_0_10 0 -#define AD5791_LINCOMP_10_12 1 -#define AD5791_LINCOMP_12_16 2 -#define AD5791_LINCOMP_16_19 3 -#define AD5791_LINCOMP_19_20 12 - -#define AD5780_LINCOMP_0_10 0 -#define AD5780_LINCOMP_10_20 12 - -/* Software Control Register */ -#define AD5791_SWCTRL_LDAC (1 << 0) -#define AD5791_SWCTRL_CLR (1 << 1) -#define AD5791_SWCTRL_RESET (1 << 2) - -#define AD5791_DAC_PWRDN_6K 0 -#define AD5791_DAC_PWRDN_3STATE 1 - -/* - * TODO: struct ad5791_platform_data needs to go into include/linux/iio - */ - -/** - * struct ad5791_platform_data - platform specific information - * @vref_pos_mv: Vdd Positive Analog Supply Volatge (mV) - * @vref_neg_mv: Vdd Negative Analog Supply Volatge (mV) - * @use_rbuf_gain2: ext. amplifier connected in gain of two configuration - */ - -struct ad5791_platform_data { - u16 vref_pos_mv; - u16 vref_neg_mv; - bool use_rbuf_gain2; -}; - -/** - * struct ad5791_chip_info - chip specific information - * @get_lin_comp: function pointer to the device specific function - */ - -struct ad5791_chip_info { - int (*get_lin_comp) (unsigned int span); -}; - -/** - * struct ad5791_state - driver instance specific data - * @us: spi_device - * @reg_vdd: positive supply regulator - * @reg_vss: negative supply regulator - * @chip_info: chip model specific constants - * @vref_mv: actual reference voltage used - * @vref_neg_mv: voltage of the negative supply - * @pwr_down_mode current power down mode - */ - -struct ad5791_state { - struct spi_device *spi; - struct regulator *reg_vdd; - struct regulator *reg_vss; - const struct ad5791_chip_info *chip_info; - unsigned short vref_mv; - unsigned int vref_neg_mv; - unsigned ctrl; - unsigned pwr_down_mode; - bool pwr_down; -}; - -/** - * ad5791_supported_device_ids: - */ - -enum ad5791_supported_device_ids { - ID_AD5760, - ID_AD5780, - ID_AD5781, - ID_AD5791, -}; - -#endif /* SPI_AD5791_H_ */ diff --git a/drivers/staging/iio/dac/dac.h b/drivers/staging/iio/dac/dac.h deleted file mode 100644 index 0754d715cf9..00000000000 --- a/drivers/staging/iio/dac/dac.h +++ /dev/null @@ -1,6 +0,0 @@ -/* - * dac.h - sysfs attributes associated with DACs - */ - -#define IIO_DEV_ATTR_OUT_RAW(_num, _store, _addr) \ - IIO_DEVICE_ATTR(out_voltage##_num##_raw, S_IWUSR, NULL, _store, _addr) diff --git a/drivers/staging/iio/dac/max517.c b/drivers/staging/iio/dac/max517.c deleted file mode 100644 index a4df6d7443c..00000000000 --- a/drivers/staging/iio/dac/max517.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * max517.c - Support for Maxim MAX517, MAX518 and MAX519 - * - * Copyright (C) 2010, 2011 Roland Stigge <stigge@antcom.de> - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/jiffies.h> -#include <linux/i2c.h> -#include <linux/err.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "dac.h" - -#include "max517.h" - -#define MAX517_DRV_NAME "max517" - -/* Commands */ -#define COMMAND_CHANNEL0 0x00 -#define COMMAND_CHANNEL1 0x01 /* for MAX518 and MAX519 */ -#define COMMAND_PD 0x08 /* Power Down */ - -enum max517_device_ids { - ID_MAX517, - ID_MAX518, - ID_MAX519, -}; - -struct max517_data { - struct iio_dev *indio_dev; - struct i2c_client *client; - unsigned short vref_mv[2]; -}; - -/* - * channel: bit 0: channel 1 - * bit 1: channel 2 - * (this way, it's possible to set both channels at once) - */ -static ssize_t max517_set_value(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count, int channel) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct max517_data *data = iio_priv(indio_dev); - struct i2c_client *client = data->client; - u8 outbuf[4]; /* 1x or 2x command + value */ - int outbuf_size = 0; - int res; - long val; - - res = strict_strtol(buf, 10, &val); - - if (res) - return res; - - if (val < 0 || val > 255) - return -EINVAL; - - if (channel & 1) { - outbuf[outbuf_size++] = COMMAND_CHANNEL0; - outbuf[outbuf_size++] = val; - } - if (channel & 2) { - outbuf[outbuf_size++] = COMMAND_CHANNEL1; - outbuf[outbuf_size++] = val; - } - - /* - * At this point, there are always 1 or 2 two-byte commands in - * outbuf. With 2 commands, the device can set two outputs - * simultaneously, latching the values upon the end of the I2C - * transfer. - */ - - res = i2c_master_send(client, outbuf, outbuf_size); - if (res < 0) - return res; - - return count; -} - -static ssize_t max517_set_value_1(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - return max517_set_value(dev, attr, buf, count, 1); -} -static IIO_DEV_ATTR_OUT_RAW(1, max517_set_value_1, 0); - -static ssize_t max517_set_value_2(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - return max517_set_value(dev, attr, buf, count, 2); -} -static IIO_DEV_ATTR_OUT_RAW(2, max517_set_value_2, 1); - -static ssize_t max517_set_value_both(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - return max517_set_value(dev, attr, buf, count, 3); -} -static IIO_DEVICE_ATTR_NAMED(out_voltage1and2_raw, - out_voltage1&2_raw, S_IWUSR, NULL, - max517_set_value_both, -1); - -static ssize_t max517_show_scale(struct device *dev, - struct device_attribute *attr, - char *buf, int channel) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct max517_data *data = iio_priv(indio_dev); - /* Corresponds to Vref / 2^(bits) */ - unsigned int scale_uv = (data->vref_mv[channel - 1] * 1000) >> 8; - - return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); -} - -static ssize_t max517_show_scale1(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return max517_show_scale(dev, attr, buf, 1); -} -static IIO_DEVICE_ATTR(out_voltage1_scale, S_IRUGO, - max517_show_scale1, NULL, 0); - -static ssize_t max517_show_scale2(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return max517_show_scale(dev, attr, buf, 2); -} -static IIO_DEVICE_ATTR(out_voltage2_scale, S_IRUGO, - max517_show_scale2, NULL, 0); - -/* On MAX517 variant, we have one output */ -static struct attribute *max517_attributes[] = { - &iio_dev_attr_out_voltage1_raw.dev_attr.attr, - &iio_dev_attr_out_voltage1_scale.dev_attr.attr, - NULL -}; - -static struct attribute_group max517_attribute_group = { - .attrs = max517_attributes, -}; - -/* On MAX518 and MAX519 variant, we have two outputs */ -static struct attribute *max518_attributes[] = { - &iio_dev_attr_out_voltage1_raw.dev_attr.attr, - &iio_dev_attr_out_voltage1_scale.dev_attr.attr, - &iio_dev_attr_out_voltage2_raw.dev_attr.attr, - &iio_dev_attr_out_voltage2_scale.dev_attr.attr, - &iio_dev_attr_out_voltage1and2_raw.dev_attr.attr, - NULL -}; - -static struct attribute_group max518_attribute_group = { - .attrs = max518_attributes, -}; - -static int max517_suspend(struct i2c_client *client, pm_message_t mesg) -{ - u8 outbuf = COMMAND_PD; - - return i2c_master_send(client, &outbuf, 1); -} - -static int max517_resume(struct i2c_client *client) -{ - u8 outbuf = 0; - - return i2c_master_send(client, &outbuf, 1); -} - -static const struct iio_info max517_info = { - .attrs = &max517_attribute_group, - .driver_module = THIS_MODULE, -}; - -static const struct iio_info max518_info = { - .attrs = &max518_attribute_group, - .driver_module = THIS_MODULE, -}; - -static int max517_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct max517_data *data; - struct iio_dev *indio_dev; - struct max517_platform_data *platform_data = client->dev.platform_data; - int err; - - indio_dev = iio_allocate_device(sizeof(*data)); - if (indio_dev == NULL) { - err = -ENOMEM; - goto exit; - } - data = iio_priv(indio_dev); - i2c_set_clientdata(client, indio_dev); - data->client = client; - - /* establish that the iio_dev is a child of the i2c device */ - indio_dev->dev.parent = &client->dev; - - /* reduced attribute set for MAX517 */ - if (id->driver_data == ID_MAX517) - indio_dev->info = &max517_info; - else - indio_dev->info = &max518_info; - indio_dev->modes = INDIO_DIRECT_MODE; - - /* - * Reference voltage on MAX518 and default is 5V, else take vref_mv - * from platform_data - */ - if (id->driver_data == ID_MAX518 || !platform_data) { - data->vref_mv[0] = data->vref_mv[1] = 5000; /* mV */ - } else { - data->vref_mv[0] = platform_data->vref_mv[0]; - data->vref_mv[1] = platform_data->vref_mv[1]; - } - - err = iio_device_register(indio_dev); - if (err) - goto exit_free_device; - - dev_info(&client->dev, "DAC registered\n"); - - return 0; - -exit_free_device: - iio_free_device(indio_dev); -exit: - return err; -} - -static int max517_remove(struct i2c_client *client) -{ - iio_free_device(i2c_get_clientdata(client)); - - return 0; -} - -static const struct i2c_device_id max517_id[] = { - { "max517", ID_MAX517 }, - { "max518", ID_MAX518 }, - { "max519", ID_MAX519 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, max517_id); - -static struct i2c_driver max517_driver = { - .driver = { - .name = MAX517_DRV_NAME, - }, - .probe = max517_probe, - .remove = max517_remove, - .suspend = max517_suspend, - .resume = max517_resume, - .id_table = max517_id, -}; -module_i2c_driver(max517_driver); - -MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>"); -MODULE_DESCRIPTION("MAX517/MAX518/MAX519 8-bit DAC"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/dac/max517.h b/drivers/staging/iio/dac/max517.h deleted file mode 100644 index 8106cf24642..00000000000 --- a/drivers/staging/iio/dac/max517.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * MAX517 DAC driver - * - * Copyright 2011 Roland Stigge <stigge@antcom.de> - * - * Licensed under the GPL-2 or later. - */ -#ifndef IIO_DAC_MAX517_H_ -#define IIO_DAC_MAX517_H_ - -/* - * TODO: struct max517_platform_data needs to go into include/linux/iio - */ - -struct max517_platform_data { - u16 vref_mv[2]; -}; - -#endif /* IIO_DAC_MAX517_H_ */ diff --git a/drivers/staging/iio/dds/dds.h b/drivers/staging/iio/dds/dds.h deleted file mode 100644 index d8ac3a93baf..00000000000 --- a/drivers/staging/iio/dds/dds.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * dds.h - sysfs attributes associated with DDS devices - * - * Copyright (c) 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -/** - * /sys/bus/iio/devices/.../ddsX_freqY - */ - -#define IIO_DEV_ATTR_FREQ(_channel, _num, _mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(dds##_channel##_freq##_num, \ - _mode, _show, _store, _addr) - -/** - * /sys/bus/iio/devices/.../ddsX_freqY_scale - */ - -#define IIO_CONST_ATTR_FREQ_SCALE(_channel, _string) \ - IIO_CONST_ATTR(dds##_channel##_freq_scale, _string) - -/** - * /sys/bus/iio/devices/.../ddsX_freqsymbol - */ - -#define IIO_DEV_ATTR_FREQSYMBOL(_channel, _mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(dds##_channel##_freqsymbol, \ - _mode, _show, _store, _addr); - -/** - * /sys/bus/iio/devices/.../ddsX_phaseY - */ - -#define IIO_DEV_ATTR_PHASE(_channel, _num, _mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(dds##_channel##_phase##_num, \ - _mode, _show, _store, _addr) - -/** - * /sys/bus/iio/devices/.../ddsX_phaseY_scale - */ - -#define IIO_CONST_ATTR_PHASE_SCALE(_channel, _string) \ - IIO_CONST_ATTR(dds##_channel##_phase_scale, _string) - -/** - * /sys/bus/iio/devices/.../ddsX_phasesymbol - */ - -#define IIO_DEV_ATTR_PHASESYMBOL(_channel, _mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(dds##_channel##_phasesymbol, \ - _mode, _show, _store, _addr); - -/** - * /sys/bus/iio/devices/.../ddsX_pincontrol_en - */ - -#define IIO_DEV_ATTR_PINCONTROL_EN(_channel, _mode, _show, _store, _addr)\ - IIO_DEVICE_ATTR(dds##_channel##_pincontrol_en, \ - _mode, _show, _store, _addr); - -/** - * /sys/bus/iio/devices/.../ddsX_pincontrol_freq_en - */ - -#define IIO_DEV_ATTR_PINCONTROL_FREQ_EN(_channel, _mode, _show, _store, _addr)\ - IIO_DEVICE_ATTR(dds##_channel##_pincontrol_freq_en, \ - _mode, _show, _store, _addr); - -/** - * /sys/bus/iio/devices/.../ddsX_pincontrol_phase_en - */ - -#define IIO_DEV_ATTR_PINCONTROL_PHASE_EN(_channel, _mode, _show, _store, _addr)\ - IIO_DEVICE_ATTR(dds##_channel##_pincontrol_phase_en, \ - _mode, _show, _store, _addr); - -/** - * /sys/bus/iio/devices/.../ddsX_out_enable - */ - -#define IIO_DEV_ATTR_OUT_ENABLE(_channel, _mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(dds##_channel##_out_enable, \ - _mode, _show, _store, _addr); - -/** - * /sys/bus/iio/devices/.../ddsX_outY_enable - */ - -#define IIO_DEV_ATTR_OUTY_ENABLE(_channel, _output, \ - _mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(dds##_channel##_out##_output##_enable, \ - _mode, _show, _store, _addr); - -/** - * /sys/bus/iio/devices/.../ddsX_outY_wavetype - */ - -#define IIO_DEV_ATTR_OUT_WAVETYPE(_channel, _output, _store, _addr) \ - IIO_DEVICE_ATTR(dds##_channel##_out##_output##_wavetype, \ - S_IWUSR, NULL, _store, _addr); - -/** - * /sys/bus/iio/devices/.../ddsX_outY_wavetype_available - */ - -#define IIO_CONST_ATTR_OUT_WAVETYPES_AVAILABLE(_channel, _output, _modes)\ - IIO_CONST_ATTR(dds##_channel##_out##_output##_wavetype_available,\ - _modes); diff --git a/drivers/staging/iio/events.h b/drivers/staging/iio/events.h deleted file mode 100644 index bfb63400fa6..00000000000 --- a/drivers/staging/iio/events.h +++ /dev/null @@ -1,103 +0,0 @@ -/* The industrial I/O - event passing to userspace - * - * Copyright (c) 2008-2011 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ -#ifndef _IIO_EVENTS_H_ -#define _IIO_EVENTS_H_ - -#include <linux/ioctl.h> -#include <linux/types.h> -#include "types.h" - -/** - * struct iio_event_data - The actual event being pushed to userspace - * @id: event identifier - * @timestamp: best estimate of time of event occurrence (often from - * the interrupt handler) - */ -struct iio_event_data { - __u64 id; - __s64 timestamp; -}; - -#define IIO_GET_EVENT_FD_IOCTL _IOR('i', 0x90, int) - -enum iio_event_type { - IIO_EV_TYPE_THRESH, - IIO_EV_TYPE_MAG, - IIO_EV_TYPE_ROC, - IIO_EV_TYPE_THRESH_ADAPTIVE, - IIO_EV_TYPE_MAG_ADAPTIVE, -}; - -enum iio_event_direction { - IIO_EV_DIR_EITHER, - IIO_EV_DIR_RISING, - IIO_EV_DIR_FALLING, -}; - -/** - * IIO_EVENT_CODE() - create event identifier - * @chan_type: Type of the channel. Should be one of enum iio_chan_type. - * @diff: Whether the event is for an differential channel or not. - * @modifier: Modifier for the channel. Should be one of enum iio_modifier. - * @direction: Direction of the event. One of enum iio_event_direction. - * @type: Type of the event. Should be one enum iio_event_type. - * @chan: Channel number for non-differential channels. - * @chan1: First channel number for differential channels. - * @chan2: Second channel number for differential channels. - */ - -#define IIO_EVENT_CODE(chan_type, diff, modifier, direction, \ - type, chan, chan1, chan2) \ - (((u64)type << 56) | ((u64)diff << 55) | \ - ((u64)direction << 48) | ((u64)modifier << 40) | \ - ((u64)chan_type << 32) | (((u16)chan2) << 16) | ((u16)chan1) | \ - ((u16)chan)) - - -#define IIO_EV_DIR_MAX 4 -#define IIO_EV_BIT(type, direction) \ - (1 << (type*IIO_EV_DIR_MAX + direction)) - -/** - * IIO_MOD_EVENT_CODE() - create event identifier for modified channels - * @chan_type: Type of the channel. Should be one of enum iio_chan_type. - * @number: Channel number. - * @modifier: Modifier for the channel. Should be one of enum iio_modifier. - * @type: Type of the event. Should be one enum iio_event_type. - * @direction: Direction of the event. One of enum iio_event_direction. - */ - -#define IIO_MOD_EVENT_CODE(chan_type, number, modifier, \ - type, direction) \ - IIO_EVENT_CODE(chan_type, 0, modifier, direction, type, number, 0, 0) - -/** - * IIO_UNMOD_EVENT_CODE() - create event identifier for unmodified channels - * @chan_type: Type of the channel. Should be one of enum iio_chan_type. - * @number: Channel number. - * @type: Type of the event. Should be one enum iio_event_type. - * @direction: Direction of the event. One of enum iio_event_direction. - */ - -#define IIO_UNMOD_EVENT_CODE(chan_type, number, type, direction) \ - IIO_EVENT_CODE(chan_type, 0, 0, direction, type, number, 0, 0) - -#define IIO_EVENT_CODE_EXTRACT_TYPE(mask) ((mask >> 56) & 0xFF) - -#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0xCF) - -#define IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(mask) ((mask >> 32) & 0xFF) - -/* Event code number extraction depends on which type of event we have. - * Perhaps review this function in the future*/ -#define IIO_EVENT_CODE_EXTRACT_NUM(mask) ((__s16)(mask & 0xFFFF)) - -#define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 40) & 0xFF) - -#endif diff --git a/drivers/staging/iio/dds/Kconfig b/drivers/staging/iio/frequency/Kconfig index 93b7141b2c1..93b7141b2c1 100644 --- a/drivers/staging/iio/dds/Kconfig +++ b/drivers/staging/iio/frequency/Kconfig diff --git a/drivers/staging/iio/dds/Makefile b/drivers/staging/iio/frequency/Makefile index 147746176b9..147746176b9 100644 --- a/drivers/staging/iio/dds/Makefile +++ b/drivers/staging/iio/frequency/Makefile diff --git a/drivers/staging/iio/dds/ad5930.c b/drivers/staging/iio/frequency/ad5930.c index 9c32d1beae2..a4aeee6ffdf 100644 --- a/drivers/staging/iio/dds/ad5930.c +++ b/drivers/staging/iio/frequency/ad5930.c @@ -16,8 +16,8 @@ #include <linux/sysfs.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #define DRV_NAME "ad5930" @@ -44,11 +44,10 @@ static ssize_t ad5930_set_parameter(struct device *dev, const char *buf, size_t len) { - struct spi_message msg; struct spi_transfer xfer; int ret; struct ad5903_config *config = (struct ad5903_config *)buf; - struct iio_dev *idev = dev_get_drvdata(dev); + struct iio_dev *idev = dev_to_iio_dev(dev); struct ad5930_state *st = iio_priv(idev); config->control = (config->control & ~value_mask); @@ -64,9 +63,7 @@ static ssize_t ad5930_set_parameter(struct device *dev, xfer.tx_buf = config; mutex_lock(&st->lock); - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; error_ret: @@ -91,17 +88,15 @@ static const struct iio_info ad5930_info = { .driver_module = THIS_MODULE, }; -static int __devinit ad5930_probe(struct spi_device *spi) +static int ad5930_probe(struct spi_device *spi) { struct ad5930_state *st; struct iio_dev *idev; int ret = 0; - idev = iio_allocate_device(sizeof(*st)); - if (idev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + idev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!idev) + return -ENOMEM; spi_set_drvdata(spi, idev); st = iio_priv(idev); @@ -113,24 +108,18 @@ static int __devinit ad5930_probe(struct spi_device *spi) ret = iio_device_register(idev); if (ret) - goto error_free_dev; + return ret; spi->max_speed_hz = 2000000; spi->mode = SPI_MODE_3; spi->bits_per_word = 16; spi_setup(spi); return 0; - -error_free_dev: - iio_free_device(idev); -error_ret: - return ret; } -static int __devexit ad5930_remove(struct spi_device *spi) +static int ad5930_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); return 0; } @@ -141,7 +130,7 @@ static struct spi_driver ad5930_driver = { .owner = THIS_MODULE, }, .probe = ad5930_probe, - .remove = __devexit_p(ad5930_remove), + .remove = ad5930_remove, }; module_spi_driver(ad5930_driver); diff --git a/drivers/staging/iio/dds/ad9832.c b/drivers/staging/iio/frequency/ad9832.c index 2ccf25dd928..c7d0307c8e7 100644 --- a/drivers/staging/iio/dds/ad9832.c +++ b/drivers/staging/iio/frequency/ad9832.c @@ -16,8 +16,8 @@ #include <linux/module.h> #include <asm/div64.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #include "dds.h" #include "ad9832.h" @@ -77,13 +77,13 @@ static ssize_t ad9832_write(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad9832_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; - long val; + unsigned long val; - ret = strict_strtoul(buf, 10, &val); + ret = kstrtoul(buf, 10, &val); if (ret) goto error_ret; @@ -177,18 +177,18 @@ static IIO_DEV_ATTR_OUT_ENABLE(0, S_IWUSR, NULL, ad9832_write, AD9832_OUTPUT_EN); static struct attribute *ad9832_attributes[] = { - &iio_dev_attr_dds0_freq0.dev_attr.attr, - &iio_dev_attr_dds0_freq1.dev_attr.attr, - &iio_const_attr_dds0_freq_scale.dev_attr.attr, - &iio_dev_attr_dds0_phase0.dev_attr.attr, - &iio_dev_attr_dds0_phase1.dev_attr.attr, - &iio_dev_attr_dds0_phase2.dev_attr.attr, - &iio_dev_attr_dds0_phase3.dev_attr.attr, - &iio_const_attr_dds0_phase_scale.dev_attr.attr, - &iio_dev_attr_dds0_pincontrol_en.dev_attr.attr, - &iio_dev_attr_dds0_freqsymbol.dev_attr.attr, - &iio_dev_attr_dds0_phasesymbol.dev_attr.attr, - &iio_dev_attr_dds0_out_enable.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_frequency0.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_frequency1.dev_attr.attr, + &iio_const_attr_out_altvoltage0_frequency_scale.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phase0.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phase1.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phase2.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phase3.dev_attr.attr, + &iio_const_attr_out_altvoltage0_phase_scale.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_pincontrol_en.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_frequencysymbol.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phasesymbol.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out_enable.dev_attr.attr, NULL, }; @@ -201,7 +201,7 @@ static const struct iio_info ad9832_info = { .driver_module = THIS_MODULE, }; -static int __devinit ad9832_probe(struct spi_device *spi) +static int ad9832_probe(struct spi_device *spi) { struct ad9832_platform_data *pdata = spi->dev.platform_data; struct iio_dev *indio_dev; @@ -214,14 +214,14 @@ static int __devinit ad9832_probe(struct spi_device *spi) return -ENODEV; } - reg = regulator_get(&spi->dev, "vcc"); + reg = devm_regulator_get(&spi->dev, "vcc"); if (!IS_ERR(reg)) { ret = regulator_enable(reg); if (ret) - goto error_put_reg; + return ret; } - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_disable_reg; @@ -279,62 +279,54 @@ static int __devinit ad9832_probe(struct spi_device *spi) ret = spi_sync(st->spi, &st->msg); if (ret) { dev_err(&spi->dev, "device init failed\n"); - goto error_free_device; + goto error_disable_reg; } ret = ad9832_write_frequency(st, AD9832_FREQ0HM, pdata->freq0); if (ret) - goto error_free_device; + goto error_disable_reg; ret = ad9832_write_frequency(st, AD9832_FREQ1HM, pdata->freq1); if (ret) - goto error_free_device; + goto error_disable_reg; ret = ad9832_write_phase(st, AD9832_PHASE0H, pdata->phase0); if (ret) - goto error_free_device; + goto error_disable_reg; ret = ad9832_write_phase(st, AD9832_PHASE1H, pdata->phase1); if (ret) - goto error_free_device; + goto error_disable_reg; ret = ad9832_write_phase(st, AD9832_PHASE2H, pdata->phase2); if (ret) - goto error_free_device; + goto error_disable_reg; ret = ad9832_write_phase(st, AD9832_PHASE3H, pdata->phase3); if (ret) - goto error_free_device; + goto error_disable_reg; ret = iio_device_register(indio_dev); if (ret) - goto error_free_device; + goto error_disable_reg; return 0; -error_free_device: - iio_free_device(indio_dev); error_disable_reg: if (!IS_ERR(reg)) regulator_disable(reg); -error_put_reg: - if (!IS_ERR(reg)) - regulator_put(reg); return ret; } -static int __devexit ad9832_remove(struct spi_device *spi) +static int ad9832_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad9832_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - if (!IS_ERR(st->reg)) { + if (!IS_ERR(st->reg)) regulator_disable(st->reg); - regulator_put(st->reg); - } - iio_free_device(indio_dev); return 0; } @@ -352,7 +344,7 @@ static struct spi_driver ad9832_driver = { .owner = THIS_MODULE, }, .probe = ad9832_probe, - .remove = __devexit_p(ad9832_remove), + .remove = ad9832_remove, .id_table = ad9832_id, }; module_spi_driver(ad9832_driver); diff --git a/drivers/staging/iio/dds/ad9832.h b/drivers/staging/iio/frequency/ad9832.h index c5b701f8aab..386f4dc8c9a 100644 --- a/drivers/staging/iio/dds/ad9832.h +++ b/drivers/staging/iio/frequency/ad9832.h @@ -92,9 +92,9 @@ struct ad9832_state { * transfer buffers to live in their own cache lines. */ union { - unsigned short freq_data[4]____cacheline_aligned; - unsigned short phase_data[2]; - unsigned short data; + __be16 freq_data[4]____cacheline_aligned; + __be16 phase_data[2]; + __be16 data; }; }; diff --git a/drivers/staging/iio/dds/ad9834.c b/drivers/staging/iio/frequency/ad9834.c index 5e67104fea1..86cda617609 100644 --- a/drivers/staging/iio/dds/ad9834.c +++ b/drivers/staging/iio/frequency/ad9834.c @@ -19,8 +19,8 @@ #include <linux/module.h> #include <asm/div64.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #include "dds.h" #include "ad9834.h" @@ -66,13 +66,13 @@ static ssize_t ad9834_write(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad9834_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; - long val; + unsigned long val; - ret = strict_strtoul(buf, 10, &val); + ret = kstrtoul(buf, 10, &val); if (ret) goto error_ret; @@ -145,7 +145,7 @@ static ssize_t ad9834_store_wavetype(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad9834_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret = 0; @@ -203,7 +203,7 @@ static ssize_t ad9834_show_out0_wavetype_available(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad9834_state *st = iio_priv(indio_dev); char *str; @@ -218,14 +218,14 @@ static ssize_t ad9834_show_out0_wavetype_available(struct device *dev, } -static IIO_DEVICE_ATTR(dds0_out0_wavetype_available, S_IRUGO, +static IIO_DEVICE_ATTR(out_altvoltage0_out0_wavetype_available, S_IRUGO, ad9834_show_out0_wavetype_available, NULL, 0); static ssize_t ad9834_show_out1_wavetype_available(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad9834_state *st = iio_priv(indio_dev); char *str; @@ -237,7 +237,7 @@ static ssize_t ad9834_show_out1_wavetype_available(struct device *dev, return sprintf(buf, "%s\n", str); } -static IIO_DEVICE_ATTR(dds0_out1_wavetype_available, S_IRUGO, +static IIO_DEVICE_ATTR(out_altvoltage0_out1_wavetype_available, S_IRUGO, ad9834_show_out1_wavetype_available, NULL, 0); /** @@ -263,47 +263,45 @@ static IIO_DEV_ATTR_OUT_WAVETYPE(0, 0, ad9834_store_wavetype, 0); static IIO_DEV_ATTR_OUT_WAVETYPE(0, 1, ad9834_store_wavetype, 1); static struct attribute *ad9834_attributes[] = { - &iio_dev_attr_dds0_freq0.dev_attr.attr, - &iio_dev_attr_dds0_freq1.dev_attr.attr, - &iio_const_attr_dds0_freq_scale.dev_attr.attr, - &iio_dev_attr_dds0_phase0.dev_attr.attr, - &iio_dev_attr_dds0_phase1.dev_attr.attr, - &iio_const_attr_dds0_phase_scale.dev_attr.attr, - &iio_dev_attr_dds0_pincontrol_en.dev_attr.attr, - &iio_dev_attr_dds0_freqsymbol.dev_attr.attr, - &iio_dev_attr_dds0_phasesymbol.dev_attr.attr, - &iio_dev_attr_dds0_out_enable.dev_attr.attr, - &iio_dev_attr_dds0_out1_enable.dev_attr.attr, - &iio_dev_attr_dds0_out0_wavetype.dev_attr.attr, - &iio_dev_attr_dds0_out1_wavetype.dev_attr.attr, - &iio_dev_attr_dds0_out0_wavetype_available.dev_attr.attr, - &iio_dev_attr_dds0_out1_wavetype_available.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_frequency0.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_frequency1.dev_attr.attr, + &iio_const_attr_out_altvoltage0_frequency_scale.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phase0.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phase1.dev_attr.attr, + &iio_const_attr_out_altvoltage0_phase_scale.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_pincontrol_en.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_frequencysymbol.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phasesymbol.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out_enable.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out1_enable.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out0_wavetype.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out1_wavetype.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out0_wavetype_available.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out1_wavetype_available.dev_attr.attr, NULL, }; -static umode_t ad9834_attr_is_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad9834_state *st = iio_priv(indio_dev); - - umode_t mode = attr->mode; - - if (((st->devid == ID_AD9833) || (st->devid == ID_AD9837)) && - ((attr == &iio_dev_attr_dds0_out1_enable.dev_attr.attr) || - (attr == &iio_dev_attr_dds0_out1_wavetype.dev_attr.attr) || - (attr == - &iio_dev_attr_dds0_out1_wavetype_available.dev_attr.attr) || - (attr == &iio_dev_attr_dds0_pincontrol_en.dev_attr.attr))) - mode = 0; - - return mode; -} +static struct attribute *ad9833_attributes[] = { + &iio_dev_attr_out_altvoltage0_frequency0.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_frequency1.dev_attr.attr, + &iio_const_attr_out_altvoltage0_frequency_scale.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phase0.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phase1.dev_attr.attr, + &iio_const_attr_out_altvoltage0_phase_scale.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_frequencysymbol.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phasesymbol.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out_enable.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out0_wavetype.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out0_wavetype_available.dev_attr.attr, + NULL, +}; static const struct attribute_group ad9834_attribute_group = { .attrs = ad9834_attributes, - .is_visible = ad9834_attr_is_visible, +}; + +static const struct attribute_group ad9833_attribute_group = { + .attrs = ad9833_attributes, }; static const struct iio_info ad9834_info = { @@ -311,7 +309,12 @@ static const struct iio_info ad9834_info = { .driver_module = THIS_MODULE, }; -static int __devinit ad9834_probe(struct spi_device *spi) +static const struct iio_info ad9833_info = { + .attrs = &ad9833_attribute_group, + .driver_module = THIS_MODULE, +}; + +static int ad9834_probe(struct spi_device *spi) { struct ad9834_platform_data *pdata = spi->dev.platform_data; struct ad9834_state *st; @@ -324,14 +327,14 @@ static int __devinit ad9834_probe(struct spi_device *spi) return -ENODEV; } - reg = regulator_get(&spi->dev, "vcc"); + reg = devm_regulator_get(&spi->dev, "vcc"); if (!IS_ERR(reg)) { ret = regulator_enable(reg); if (ret) - goto error_put_reg; + return ret; } - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_disable_reg; @@ -344,7 +347,15 @@ static int __devinit ad9834_probe(struct spi_device *spi) st->reg = reg; indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->info = &ad9834_info; + switch (st->devid) { + case ID_AD9833: + case ID_AD9837: + indio_dev->info = &ad9833_info; + break; + default: + indio_dev->info = &ad9834_info; + break; + } indio_dev->modes = INDIO_DIRECT_MODE; /* Setup default messages */ @@ -377,53 +388,46 @@ static int __devinit ad9834_probe(struct spi_device *spi) ret = spi_sync(st->spi, &st->msg); if (ret) { dev_err(&spi->dev, "device init failed\n"); - goto error_free_device; + goto error_disable_reg; } ret = ad9834_write_frequency(st, AD9834_REG_FREQ0, pdata->freq0); if (ret) - goto error_free_device; + goto error_disable_reg; ret = ad9834_write_frequency(st, AD9834_REG_FREQ1, pdata->freq1); if (ret) - goto error_free_device; + goto error_disable_reg; ret = ad9834_write_phase(st, AD9834_REG_PHASE0, pdata->phase0); if (ret) - goto error_free_device; + goto error_disable_reg; ret = ad9834_write_phase(st, AD9834_REG_PHASE1, pdata->phase1); if (ret) - goto error_free_device; + goto error_disable_reg; ret = iio_device_register(indio_dev); if (ret) - goto error_free_device; + goto error_disable_reg; return 0; -error_free_device: - iio_free_device(indio_dev); error_disable_reg: if (!IS_ERR(reg)) regulator_disable(reg); -error_put_reg: - if (!IS_ERR(reg)) - regulator_put(reg); + return ret; } -static int __devexit ad9834_remove(struct spi_device *spi) +static int ad9834_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad9834_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - if (!IS_ERR(st->reg)) { + if (!IS_ERR(st->reg)) regulator_disable(st->reg); - regulator_put(st->reg); - } - iio_free_device(indio_dev); return 0; } @@ -443,7 +447,7 @@ static struct spi_driver ad9834_driver = { .owner = THIS_MODULE, }, .probe = ad9834_probe, - .remove = __devexit_p(ad9834_remove), + .remove = ad9834_remove, .id_table = ad9834_id, }; module_spi_driver(ad9834_driver); diff --git a/drivers/staging/iio/dds/ad9834.h b/drivers/staging/iio/frequency/ad9834.h index ed5ed8d0007..8ca6e52bae6 100644 --- a/drivers/staging/iio/dds/ad9834.h +++ b/drivers/staging/iio/frequency/ad9834.h @@ -65,8 +65,8 @@ struct ad9834_state { * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. */ - unsigned short data ____cacheline_aligned; - unsigned short freq_data[2] ; + __be16 data ____cacheline_aligned; + __be16 freq_data[2]; }; diff --git a/drivers/staging/iio/dds/ad9850.c b/drivers/staging/iio/frequency/ad9850.c index f4f731bb219..af877ff680e 100644 --- a/drivers/staging/iio/dds/ad9850.c +++ b/drivers/staging/iio/frequency/ad9850.c @@ -16,8 +16,8 @@ #include <linux/sysfs.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #define DRV_NAME "ad9850" @@ -39,20 +39,17 @@ static ssize_t ad9850_set_parameter(struct device *dev, const char *buf, size_t len) { - struct spi_message msg; struct spi_transfer xfer; int ret; struct ad9850_config *config = (struct ad9850_config *)buf; - struct iio_dev *idev = dev_get_drvdata(dev); + struct iio_dev *idev = dev_to_iio_dev(dev); struct ad9850_state *st = iio_priv(idev); xfer.len = len; xfer.tx_buf = config; mutex_lock(&st->lock); - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; error_ret: @@ -77,17 +74,15 @@ static const struct iio_info ad9850_info = { .driver_module = THIS_MODULE, }; -static int __devinit ad9850_probe(struct spi_device *spi) +static int ad9850_probe(struct spi_device *spi) { struct ad9850_state *st; struct iio_dev *idev; int ret = 0; - idev = iio_allocate_device(sizeof(*st)); - if (idev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + idev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!idev) + return -ENOMEM; spi_set_drvdata(spi, idev); st = iio_priv(idev); mutex_init(&st->lock); @@ -99,24 +94,18 @@ static int __devinit ad9850_probe(struct spi_device *spi) ret = iio_device_register(idev); if (ret) - goto error_free_dev; + return ret; spi->max_speed_hz = 2000000; spi->mode = SPI_MODE_3; spi->bits_per_word = 16; spi_setup(spi); return 0; - -error_free_dev: - iio_free_device(idev); -error_ret: - return ret; } -static int __devexit ad9850_remove(struct spi_device *spi) +static int ad9850_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); return 0; } @@ -127,7 +116,7 @@ static struct spi_driver ad9850_driver = { .owner = THIS_MODULE, }, .probe = ad9850_probe, - .remove = __devexit_p(ad9850_remove), + .remove = ad9850_remove, }; module_spi_driver(ad9850_driver); diff --git a/drivers/staging/iio/dds/ad9852.c b/drivers/staging/iio/frequency/ad9852.c index 554266c615a..11e4367375d 100644 --- a/drivers/staging/iio/dds/ad9852.c +++ b/drivers/staging/iio/frequency/ad9852.c @@ -16,8 +16,8 @@ #include <linux/sysfs.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #define DRV_NAME "ad9852" @@ -67,110 +67,87 @@ static ssize_t ad9852_set_parameter(struct device *dev, const char *buf, size_t len) { - struct spi_message msg; struct spi_transfer xfer; int ret; struct ad9852_config *config = (struct ad9852_config *)buf; - struct iio_dev *idev = dev_get_drvdata(dev); + struct iio_dev *idev = dev_to_iio_dev(dev); struct ad9852_state *st = iio_priv(idev); xfer.len = 3; xfer.tx_buf = &config->phajst0[0]; mutex_lock(&st->lock); - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 3; xfer.tx_buf = &config->phajst1[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 6; xfer.tx_buf = &config->fretun1[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 6; xfer.tx_buf = &config->fretun2[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 6; xfer.tx_buf = &config->dltafre[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 5; xfer.tx_buf = &config->updtclk[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 4; xfer.tx_buf = &config->ramprat[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 5; xfer.tx_buf = &config->control[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 3; xfer.tx_buf = &config->outpskm[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 2; xfer.tx_buf = &config->outpskr[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 3; xfer.tx_buf = &config->daccntl[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; error_ret: @@ -183,7 +160,6 @@ static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9852_set_parameter, 0); static void ad9852_init(struct ad9852_state *st) { - struct spi_message msg; struct spi_transfer xfer; int ret; u8 config[5]; @@ -199,9 +175,7 @@ static void ad9852_init(struct ad9852_state *st) xfer.len = 5; xfer.tx_buf = &config; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; @@ -226,17 +200,15 @@ static const struct iio_info ad9852_info = { .driver_module = THIS_MODULE, }; -static int __devinit ad9852_probe(struct spi_device *spi) +static int ad9852_probe(struct spi_device *spi) { struct ad9852_state *st; struct iio_dev *idev; int ret = 0; - idev = iio_allocate_device(sizeof(*st)); - if (idev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + idev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!idev) + return -ENOMEM; st = iio_priv(idev); spi_set_drvdata(spi, idev); mutex_init(&st->lock); @@ -248,7 +220,7 @@ static int __devinit ad9852_probe(struct spi_device *spi) ret = iio_device_register(idev); if (ret) - goto error_free_dev; + return ret; spi->max_speed_hz = 2000000; spi->mode = SPI_MODE_3; spi->bits_per_word = 8; @@ -256,18 +228,11 @@ static int __devinit ad9852_probe(struct spi_device *spi) ad9852_init(st); return 0; - -error_free_dev: - iio_free_device(idev); - -error_ret: - return ret; } -static int __devexit ad9852_remove(struct spi_device *spi) +static int ad9852_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); return 0; } @@ -278,7 +243,7 @@ static struct spi_driver ad9852_driver = { .owner = THIS_MODULE, }, .probe = ad9852_probe, - .remove = __devexit_p(ad9852_remove), + .remove = ad9852_remove, }; module_spi_driver(ad9852_driver); diff --git a/drivers/staging/iio/dds/ad9910.c b/drivers/staging/iio/frequency/ad9910.c index 3985766d6f8..755e0482681 100644 --- a/drivers/staging/iio/dds/ad9910.c +++ b/drivers/staging/iio/frequency/ad9910.c @@ -16,8 +16,8 @@ #include <linux/sysfs.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #define DRV_NAME "ad9910" @@ -119,163 +119,128 @@ static ssize_t ad9910_set_parameter(struct device *dev, const char *buf, size_t len) { - struct spi_message msg; struct spi_transfer xfer; int ret; struct ad9910_config *config = (struct ad9910_config *)buf; - struct iio_dev *idev = dev_get_drvdata(dev); + struct iio_dev *idev = dev_to_iio_dev(dev); struct ad9910_state *st = iio_priv(idev); xfer.len = 5; xfer.tx_buf = &config->auxdac[0]; mutex_lock(&st->lock); - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 5; xfer.tx_buf = &config->ioupd[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 5; xfer.tx_buf = &config->ftw[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 3; xfer.tx_buf = &config->pow[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 5; xfer.tx_buf = &config->asf[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 5; xfer.tx_buf = &config->multc[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->dig_rampl[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->dig_ramps[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 5; xfer.tx_buf = &config->dig_rampr[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->sin_tonep0[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->sin_tonep1[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->sin_tonep2[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->sin_tonep3[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->sin_tonep4[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->sin_tonep5[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->sin_tonep6[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->sin_tonep7[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; error_ret: @@ -288,7 +253,6 @@ static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9910_set_parameter, 0); static void ad9910_init(struct ad9910_state *st) { - struct spi_message msg; struct spi_transfer xfer; int ret; u8 cfr[5]; @@ -304,9 +268,7 @@ static void ad9910_init(struct ad9910_state *st) xfer.len = 5; xfer.tx_buf = 𝔠 - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; @@ -319,9 +281,7 @@ static void ad9910_init(struct ad9910_state *st) xfer.len = 5; xfer.tx_buf = 𝔠 - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; @@ -334,9 +294,7 @@ static void ad9910_init(struct ad9910_state *st) xfer.len = 5; xfer.tx_buf = 𝔠 - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; @@ -361,17 +319,15 @@ static const struct iio_info ad9910_info = { .driver_module = THIS_MODULE, }; -static int __devinit ad9910_probe(struct spi_device *spi) +static int ad9910_probe(struct spi_device *spi) { struct ad9910_state *st; struct iio_dev *idev; int ret = 0; - idev = iio_allocate_device(sizeof(*st)); - if (idev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + idev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!idev) + return -ENOMEM; spi_set_drvdata(spi, idev); st = iio_priv(idev); mutex_init(&st->lock); @@ -383,24 +339,18 @@ static int __devinit ad9910_probe(struct spi_device *spi) ret = iio_device_register(idev); if (ret) - goto error_free_dev; + return ret; spi->max_speed_hz = 2000000; spi->mode = SPI_MODE_3; spi->bits_per_word = 8; spi_setup(spi); ad9910_init(st); return 0; - -error_free_dev: - iio_free_device(idev); -error_ret: - return ret; } -static int __devexit ad9910_remove(struct spi_device *spi) +static int ad9910_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); return 0; } @@ -411,7 +361,7 @@ static struct spi_driver ad9910_driver = { .owner = THIS_MODULE, }, .probe = ad9910_probe, - .remove = __devexit_p(ad9910_remove), + .remove = ad9910_remove, }; module_spi_driver(ad9910_driver); diff --git a/drivers/staging/iio/dds/ad9951.c b/drivers/staging/iio/frequency/ad9951.c index 4d150048002..5e8990a0210 100644 --- a/drivers/staging/iio/dds/ad9951.c +++ b/drivers/staging/iio/frequency/ad9951.c @@ -16,8 +16,8 @@ #include <linux/sysfs.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #define DRV_NAME "ad9951" @@ -60,47 +60,38 @@ static ssize_t ad9951_set_parameter(struct device *dev, const char *buf, size_t len) { - struct spi_message msg; struct spi_transfer xfer; int ret; struct ad9951_config *config = (struct ad9951_config *)buf; - struct iio_dev *idev = dev_get_drvdata(dev); + struct iio_dev *idev = dev_to_iio_dev(dev); struct ad9951_state *st = iio_priv(idev); xfer.len = 3; xfer.tx_buf = &config->asf[0]; mutex_lock(&st->lock); - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 2; xfer.tx_buf = &config->arr[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 5; xfer.tx_buf = &config->ftw0[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 3; xfer.tx_buf = &config->ftw1[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; error_ret: @@ -113,7 +104,6 @@ static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9951_set_parameter, 0); static void ad9951_init(struct ad9951_state *st) { - struct spi_message msg; struct spi_transfer xfer; int ret; u8 cfr[5]; @@ -129,9 +119,7 @@ static void ad9951_init(struct ad9951_state *st) xfer.len = 5; xfer.tx_buf = 𝔠 - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; @@ -143,9 +131,7 @@ static void ad9951_init(struct ad9951_state *st) xfer.len = 4; xfer.tx_buf = 𝔠 - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; @@ -170,17 +156,15 @@ static const struct iio_info ad9951_info = { .driver_module = THIS_MODULE, }; -static int __devinit ad9951_probe(struct spi_device *spi) +static int ad9951_probe(struct spi_device *spi) { struct ad9951_state *st; struct iio_dev *idev; int ret = 0; - idev = iio_allocate_device(sizeof(*st)); - if (idev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + idev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!idev) + return -ENOMEM; spi_set_drvdata(spi, idev); st = iio_priv(idev); mutex_init(&st->lock); @@ -193,25 +177,18 @@ static int __devinit ad9951_probe(struct spi_device *spi) ret = iio_device_register(idev); if (ret) - goto error_free_dev; + return ret; spi->max_speed_hz = 2000000; spi->mode = SPI_MODE_3; spi->bits_per_word = 8; spi_setup(spi); ad9951_init(st); return 0; - -error_free_dev: - iio_free_device(idev); - -error_ret: - return ret; } -static int __devexit ad9951_remove(struct spi_device *spi) +static int ad9951_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); return 0; } @@ -222,7 +199,7 @@ static struct spi_driver ad9951_driver = { .owner = THIS_MODULE, }, .probe = ad9951_probe, - .remove = __devexit_p(ad9951_remove), + .remove = ad9951_remove, }; module_spi_driver(ad9951_driver); diff --git a/drivers/staging/iio/frequency/dds.h b/drivers/staging/iio/frequency/dds.h new file mode 100644 index 00000000000..c3342f6e052 --- /dev/null +++ b/drivers/staging/iio/frequency/dds.h @@ -0,0 +1,110 @@ +/* + * dds.h - sysfs attributes associated with DDS devices + * + * Copyright (c) 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +/** + * /sys/bus/iio/devices/.../out_altvoltageX_frequencyY + */ + +#define IIO_DEV_ATTR_FREQ(_channel, _num, _mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_frequency##_num, \ + _mode, _show, _store, _addr) + +/** + * /sys/bus/iio/devices/.../out_altvoltageX_frequencyY_scale + */ + +#define IIO_CONST_ATTR_FREQ_SCALE(_channel, _string) \ + IIO_CONST_ATTR(out_altvoltage##_channel##_frequency_scale, _string) + +/** + * /sys/bus/iio/devices/.../out_altvoltageX_frequencysymbol + */ + +#define IIO_DEV_ATTR_FREQSYMBOL(_channel, _mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_frequencysymbol, \ + _mode, _show, _store, _addr); + +/** + * /sys/bus/iio/devices/.../out_altvoltageX_phaseY + */ + +#define IIO_DEV_ATTR_PHASE(_channel, _num, _mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_phase##_num, \ + _mode, _show, _store, _addr) + +/** + * /sys/bus/iio/devices/.../out_altvoltageX_phaseY_scale + */ + +#define IIO_CONST_ATTR_PHASE_SCALE(_channel, _string) \ + IIO_CONST_ATTR(out_altvoltage##_channel##_phase_scale, _string) + +/** + * /sys/bus/iio/devices/.../out_altvoltageX_phasesymbol + */ + +#define IIO_DEV_ATTR_PHASESYMBOL(_channel, _mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_phasesymbol, \ + _mode, _show, _store, _addr); + +/** + * /sys/bus/iio/devices/.../out_altvoltageX_pincontrol_en + */ + +#define IIO_DEV_ATTR_PINCONTROL_EN(_channel, _mode, _show, _store, _addr)\ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_pincontrol_en, \ + _mode, _show, _store, _addr); + +/** + * /sys/bus/iio/devices/.../out_altvoltageX_pincontrol_frequency_en + */ + +#define IIO_DEV_ATTR_PINCONTROL_FREQ_EN(_channel, _mode, _show, _store, _addr)\ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_pincontrol_frequency_en,\ + _mode, _show, _store, _addr); + +/** + * /sys/bus/iio/devices/.../out_altvoltageX_pincontrol_phase_en + */ + +#define IIO_DEV_ATTR_PINCONTROL_PHASE_EN(_channel, _mode, _show, _store, _addr)\ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_pincontrol_phase_en, \ + _mode, _show, _store, _addr); + +/** + * /sys/bus/iio/devices/.../out_altvoltageX_out_enable + */ + +#define IIO_DEV_ATTR_OUT_ENABLE(_channel, _mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_out_enable, \ + _mode, _show, _store, _addr); + +/** + * /sys/bus/iio/devices/.../out_altvoltageX_outY_enable + */ + +#define IIO_DEV_ATTR_OUTY_ENABLE(_channel, _output, \ + _mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_out##_output##_enable,\ + _mode, _show, _store, _addr); + +/** + * /sys/bus/iio/devices/.../out_altvoltageX_outY_wavetype + */ + +#define IIO_DEV_ATTR_OUT_WAVETYPE(_channel, _output, _store, _addr) \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_out##_output##_wavetype,\ + S_IWUSR, NULL, _store, _addr); + +/** + * /sys/bus/iio/devices/.../out_altvoltageX_outY_wavetype_available + */ + +#define IIO_CONST_ATTR_OUT_WAVETYPES_AVAILABLE(_channel, _output, _modes)\ + IIO_CONST_ATTR( \ + out_altvoltage##_channel##_out##_output##_wavetype_available, _modes); diff --git a/drivers/staging/iio/gyro/Kconfig b/drivers/staging/iio/gyro/Kconfig index ea295b25308..88b199bb292 100644 --- a/drivers/staging/iio/gyro/Kconfig +++ b/drivers/staging/iio/gyro/Kconfig @@ -10,40 +10,4 @@ config ADIS16060 Say yes here to build support for Analog Devices adis16060 wide bandwidth yaw rate gyroscope with SPI. -config ADIS16080 - tristate "Analog Devices ADIS16080/100 Yaw Rate Gyroscope with SPI driver" - depends on SPI - help - Say yes here to build support for Analog Devices adis16080/100 Yaw Rate - Gyroscope with SPI. - -config ADIS16130 - tristate "Analog Devices ADIS16130 High Precision Angular Rate Sensor driver" - depends on SPI - help - Say yes here to build support for Analog Devices ADIS16130 High Precision - Angular Rate Sensor driver. - -config ADIS16260 - tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver" - depends on SPI - select IIO_TRIGGER if IIO_BUFFER - select IIO_SW_RING if IIO_BUFFER - help - Say yes here to build support for Analog Devices ADIS16260 ADIS16265 - ADIS16250 ADIS16255 and ADIS16251 programmable digital gyroscope sensors. - - This driver can also be built as a module. If so, the module - will be called adis16260. - -config ADXRS450 - tristate "Analog Devices ADXRS450/3 Digital Output Gyroscope SPI driver" - depends on SPI - help - Say yes here to build support for Analog Devices ADXRS450 and ADXRS453 - programmable digital output gyroscope. - - This driver can also be built as a module. If so, the module - will be called adxrs450. - endmenu diff --git a/drivers/staging/iio/gyro/Makefile b/drivers/staging/iio/gyro/Makefile index 9ba5ec15170..cf22d6d55e2 100644 --- a/drivers/staging/iio/gyro/Makefile +++ b/drivers/staging/iio/gyro/Makefile @@ -4,19 +4,3 @@ adis16060-y := adis16060_core.o obj-$(CONFIG_ADIS16060) += adis16060.o - -adis16080-y := adis16080_core.o -obj-$(CONFIG_ADIS16080) += adis16080.o - -adis16130-y := adis16130_core.o -obj-$(CONFIG_ADIS16130) += adis16130.o - -adis16260-y := adis16260_core.o -adis16260-$(CONFIG_IIO_BUFFER) += adis16260_ring.o adis16260_trigger.o -obj-$(CONFIG_ADIS16260) += adis16260.o - -adis16251-y := adis16251_core.o -obj-$(CONFIG_ADIS16251) += adis16251.o - -adxrs450-y := adxrs450_core.o -obj-$(CONFIG_ADXRS450) += adxrs450.o diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c index c0ca7093e0e..d5d395c2e3e 100644 --- a/drivers/staging/iio/gyro/adis16060_core.c +++ b/drivers/staging/iio/gyro/adis16060_core.c @@ -14,10 +14,9 @@ #include <linux/spi/spi.h> #include <linux/slab.h> #include <linux/sysfs.h> -#include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #define ADIS16060_GYRO 0x20 /* Measure Angular Rate (Gyro) */ #define ADIS16060_TEMP_OUT 0x10 /* Measure Temperature */ @@ -86,7 +85,7 @@ static int adis16060_read_raw(struct iio_dev *indio_dev, int ret; switch (mask) { - case 0: + case IIO_CHAN_INFO_RAW: /* Take the iio_dev status lock */ mutex_lock(&indio_dev->mlock); ret = adis16060_spi_write(indio_dev, chan->address); @@ -121,39 +120,40 @@ static const struct iio_chan_spec adis16060_channels[] = { .type = IIO_ANGL_VEL, .modified = 1, .channel2 = IIO_MOD_Z, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .address = ADIS16060_GYRO, }, { .type = IIO_VOLTAGE, .indexed = 1, .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .address = ADIS16060_AIN1, }, { .type = IIO_VOLTAGE, .indexed = 1, .channel = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .address = ADIS16060_AIN2, }, { .type = IIO_TEMP, .indexed = 1, .channel = 0, - .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), .address = ADIS16060_TEMP_OUT, } }; -static int __devinit adis16060_r_probe(struct spi_device *spi) +static int adis16060_r_probe(struct spi_device *spi) { int ret; struct adis16060_state *st; struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; /* this is only used for removal purposes */ spi_set_drvdata(spi, indio_dev); st = iio_priv(indio_dev); @@ -167,29 +167,15 @@ static int __devinit adis16060_r_probe(struct spi_device *spi) indio_dev->channels = adis16060_channels; indio_dev->num_channels = ARRAY_SIZE(adis16060_channels); - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(&spi->dev, indio_dev); if (ret) - goto error_free_dev; + return ret; adis16060_iio_dev = indio_dev; return 0; - -error_free_dev: - iio_free_device(indio_dev); -error_ret: - return ret; -} - -/* fixme, confirm ordering in this function */ -static int adis16060_r_remove(struct spi_device *spi) -{ - iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); - - return 0; } -static int __devinit adis16060_w_probe(struct spi_device *spi) +static int adis16060_w_probe(struct spi_device *spi) { int ret; struct iio_dev *indio_dev = adis16060_iio_dev; @@ -218,7 +204,6 @@ static struct spi_driver adis16060_r_driver = { .owner = THIS_MODULE, }, .probe = adis16060_r_probe, - .remove = __devexit_p(adis16060_r_remove), }; static struct spi_driver adis16060_w_driver = { @@ -227,7 +212,7 @@ static struct spi_driver adis16060_w_driver = { .owner = THIS_MODULE, }, .probe = adis16060_w_probe, - .remove = __devexit_p(adis16060_w_remove), + .remove = adis16060_w_remove, }; static __init int adis16060_init(void) diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c deleted file mode 100644 index 1815490db8b..00000000000 --- a/drivers/staging/iio/gyro/adis16080_core.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * ADIS16080/100 Yaw Rate Gyroscope with SPI driver - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ -#include <linux/delay.h> -#include <linux/mutex.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" - -#define ADIS16080_DIN_GYRO (0 << 10) /* Gyroscope output */ -#define ADIS16080_DIN_TEMP (1 << 10) /* Temperature output */ -#define ADIS16080_DIN_AIN1 (2 << 10) -#define ADIS16080_DIN_AIN2 (3 << 10) - -/* - * 1: Write contents on DIN to control register. - * 0: No changes to control register. - */ - -#define ADIS16080_DIN_WRITE (1 << 15) - -/** - * struct adis16080_state - device instance specific data - * @us: actual spi_device to write data - * @buf: transmit or receive buffer - * @buf_lock: mutex to protect tx and rx - **/ -struct adis16080_state { - struct spi_device *us; - struct mutex buf_lock; - - u8 buf[2] ____cacheline_aligned; -}; - -static int adis16080_spi_write(struct iio_dev *indio_dev, - u16 val) -{ - int ret; - struct adis16080_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - st->buf[0] = val >> 8; - st->buf[1] = val; - - ret = spi_write(st->us, st->buf, 2); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int adis16080_spi_read(struct iio_dev *indio_dev, - u16 *val) -{ - int ret; - struct adis16080_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - - ret = spi_read(st->us, st->buf, 2); - - if (ret == 0) - *val = ((st->buf[0] & 0xF) << 8) | st->buf[1]; - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int adis16080_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long mask) -{ - int ret = -EINVAL; - u16 ut; - /* Take the iio_dev status lock */ - - mutex_lock(&indio_dev->mlock); - switch (mask) { - case 0: - ret = adis16080_spi_write(indio_dev, - chan->address | - ADIS16080_DIN_WRITE); - if (ret < 0) - break; - ret = adis16080_spi_read(indio_dev, &ut); - if (ret < 0) - break; - *val = ut; - ret = IIO_VAL_INT; - break; - } - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static const struct iio_chan_spec adis16080_channels[] = { - { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_Z, - .address = ADIS16080_DIN_GYRO, - }, { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .address = ADIS16080_DIN_AIN1, - }, { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .address = ADIS16080_DIN_AIN2, - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .address = ADIS16080_DIN_TEMP, - } -}; - -static const struct iio_info adis16080_info = { - .read_raw = &adis16080_read_raw, - .driver_module = THIS_MODULE, -}; - -static int __devinit adis16080_probe(struct spi_device *spi) -{ - int ret; - struct adis16080_state *st; - struct iio_dev *indio_dev; - - /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - st = iio_priv(indio_dev); - /* this is only used for removal purposes */ - spi_set_drvdata(spi, indio_dev); - - /* Allocate the comms buffers */ - st->us = spi; - mutex_init(&st->buf_lock); - - indio_dev->name = spi->dev.driver->name; - indio_dev->channels = adis16080_channels; - indio_dev->num_channels = ARRAY_SIZE(adis16080_channels); - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &adis16080_info; - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - return 0; - -error_free_dev: - iio_free_device(indio_dev); -error_ret: - return ret; -} - -/* fixme, confirm ordering in this function */ -static int adis16080_remove(struct spi_device *spi) -{ - iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); - - return 0; -} - -static struct spi_driver adis16080_driver = { - .driver = { - .name = "adis16080", - .owner = THIS_MODULE, - }, - .probe = adis16080_probe, - .remove = __devexit_p(adis16080_remove), -}; -module_spi_driver(adis16080_driver); - -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_DESCRIPTION("Analog Devices ADIS16080/100 Yaw Rate Gyroscope Driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:adis16080"); diff --git a/drivers/staging/iio/gyro/adis16130_core.c b/drivers/staging/iio/gyro/adis16130_core.c deleted file mode 100644 index 947eb86f05d..00000000000 --- a/drivers/staging/iio/gyro/adis16130_core.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * ADIS16130 Digital Output, High Precision Angular Rate Sensor driver - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/delay.h> -#include <linux/mutex.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/list.h> -#include <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" - -#define ADIS16130_CON 0x0 -#define ADIS16130_CON_RD (1 << 6) -#define ADIS16130_IOP 0x1 - -/* 1 = data-ready signal low when unread data on all channels; */ -#define ADIS16130_IOP_ALL_RDY (1 << 3) -#define ADIS16130_IOP_SYNC (1 << 0) /* 1 = synchronization enabled */ -#define ADIS16130_RATEDATA 0x8 /* Gyroscope output, rate of rotation */ -#define ADIS16130_TEMPDATA 0xA /* Temperature output */ -#define ADIS16130_RATECS 0x28 /* Gyroscope channel setup */ -#define ADIS16130_RATECS_EN (1 << 3) /* 1 = channel enable; */ -#define ADIS16130_TEMPCS 0x2A /* Temperature channel setup */ -#define ADIS16130_TEMPCS_EN (1 << 3) -#define ADIS16130_RATECONV 0x30 -#define ADIS16130_TEMPCONV 0x32 -#define ADIS16130_MODE 0x38 -#define ADIS16130_MODE_24BIT (1 << 1) /* 1 = 24-bit resolution; */ - -/** - * struct adis16130_state - device instance specific data - * @us: actual spi_device to write data - * @buf_lock: mutex to protect tx and rx - * @buf: unified tx/rx buffer - **/ -struct adis16130_state { - struct spi_device *us; - struct mutex buf_lock; - u8 buf[4] ____cacheline_aligned; -}; - -static int adis16130_spi_read(struct iio_dev *indio_dev, u8 reg_addr, u32 *val) -{ - int ret; - struct adis16130_state *st = iio_priv(indio_dev); - struct spi_message msg; - struct spi_transfer xfer = { - .tx_buf = st->buf, - .rx_buf = st->buf, - .len = 4, - }; - - mutex_lock(&st->buf_lock); - - st->buf[0] = ADIS16130_CON_RD | reg_addr; - st->buf[1] = st->buf[2] = st->buf[3] = 0; - - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->us, &msg); - ret = spi_read(st->us, st->buf, 4); - - if (ret == 0) - *val = (st->buf[1] << 16) | (st->buf[2] << 8) | st->buf[3]; - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int adis16130_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) -{ - int ret; - u32 temp; - - /* Take the iio_dev status lock */ - mutex_lock(&indio_dev->mlock); - ret = adis16130_spi_read(indio_dev, chan->address, &temp); - mutex_unlock(&indio_dev->mlock); - if (ret) - return ret; - *val = temp; - return IIO_VAL_INT; -} - -static const struct iio_chan_spec adis16130_channels[] = { - { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_Z, - .address = ADIS16130_RATEDATA, - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .address = ADIS16130_TEMPDATA, - } -}; - -static const struct iio_info adis16130_info = { - .read_raw = &adis16130_read_raw, - .driver_module = THIS_MODULE, -}; - -static int __devinit adis16130_probe(struct spi_device *spi) -{ - int ret; - struct adis16130_state *st; - struct iio_dev *indio_dev; - - /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - st = iio_priv(indio_dev); - /* this is only used for removal purposes */ - spi_set_drvdata(spi, indio_dev); - st->us = spi; - mutex_init(&st->buf_lock); - indio_dev->name = spi->dev.driver->name; - indio_dev->channels = adis16130_channels; - indio_dev->num_channels = ARRAY_SIZE(adis16130_channels); - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &adis16130_info; - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - - return 0; - -error_free_dev: - iio_free_device(indio_dev); - -error_ret: - return ret; -} - -/* fixme, confirm ordering in this function */ -static int adis16130_remove(struct spi_device *spi) -{ - iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); - - return 0; -} - -static struct spi_driver adis16130_driver = { - .driver = { - .name = "adis16130", - .owner = THIS_MODULE, - }, - .probe = adis16130_probe, - .remove = __devexit_p(adis16130_remove), -}; -module_spi_driver(adis16130_driver); - -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_DESCRIPTION("Analog Devices ADIS16130 High Precision Angular Rate"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:adis16130"); diff --git a/drivers/staging/iio/gyro/adis16260.h b/drivers/staging/iio/gyro/adis16260.h deleted file mode 100644 index 4c4b25129c6..00000000000 --- a/drivers/staging/iio/gyro/adis16260.h +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef SPI_ADIS16260_H_ -#define SPI_ADIS16260_H_ -#include "adis16260_platform_data.h" - -#define ADIS16260_STARTUP_DELAY 220 /* ms */ - -#define ADIS16260_READ_REG(a) a -#define ADIS16260_WRITE_REG(a) ((a) | 0x80) - -#define ADIS16260_FLASH_CNT 0x00 /* Flash memory write count */ -#define ADIS16260_SUPPLY_OUT 0x02 /* Power supply measurement */ -#define ADIS16260_GYRO_OUT 0x04 /* X-axis gyroscope output */ -#define ADIS16260_AUX_ADC 0x0A /* analog input channel measurement */ -#define ADIS16260_TEMP_OUT 0x0C /* internal temperature measurement */ -#define ADIS16260_ANGL_OUT 0x0E /* angle displacement */ -#define ADIS16260_GYRO_OFF 0x14 /* Calibration, offset/bias adjustment */ -#define ADIS16260_GYRO_SCALE 0x16 /* Calibration, scale adjustment */ -#define ADIS16260_ALM_MAG1 0x20 /* Alarm 1 magnitude/polarity setting */ -#define ADIS16260_ALM_MAG2 0x22 /* Alarm 2 magnitude/polarity setting */ -#define ADIS16260_ALM_SMPL1 0x24 /* Alarm 1 dynamic rate of change setting */ -#define ADIS16260_ALM_SMPL2 0x26 /* Alarm 2 dynamic rate of change setting */ -#define ADIS16260_ALM_CTRL 0x28 /* Alarm control */ -#define ADIS16260_AUX_DAC 0x30 /* Auxiliary DAC data */ -#define ADIS16260_GPIO_CTRL 0x32 /* Control, digital I/O line */ -#define ADIS16260_MSC_CTRL 0x34 /* Control, data ready, self-test settings */ -#define ADIS16260_SMPL_PRD 0x36 /* Control, internal sample rate */ -#define ADIS16260_SENS_AVG 0x38 /* Control, dynamic range, filtering */ -#define ADIS16260_SLP_CNT 0x3A /* Control, sleep mode initiation */ -#define ADIS16260_DIAG_STAT 0x3C /* Diagnostic, error flags */ -#define ADIS16260_GLOB_CMD 0x3E /* Control, global commands */ -#define ADIS16260_LOT_ID1 0x52 /* Lot Identification Code 1 */ -#define ADIS16260_LOT_ID2 0x54 /* Lot Identification Code 2 */ -#define ADIS16260_PROD_ID 0x56 /* Product identifier; - * convert to decimal = 16,265/16,260 */ -#define ADIS16260_SERIAL_NUM 0x58 /* Serial number */ - -#define ADIS16260_OUTPUTS 5 - -#define ADIS16260_ERROR_ACTIVE (1<<14) -#define ADIS16260_NEW_DATA (1<<15) - -/* MSC_CTRL */ -#define ADIS16260_MSC_CTRL_MEM_TEST (1<<11) -/* Internal self-test enable */ -#define ADIS16260_MSC_CTRL_INT_SELF_TEST (1<<10) -#define ADIS16260_MSC_CTRL_NEG_SELF_TEST (1<<9) -#define ADIS16260_MSC_CTRL_POS_SELF_TEST (1<<8) -#define ADIS16260_MSC_CTRL_DATA_RDY_EN (1<<2) -#define ADIS16260_MSC_CTRL_DATA_RDY_POL_HIGH (1<<1) -#define ADIS16260_MSC_CTRL_DATA_RDY_DIO2 (1<<0) - -/* SMPL_PRD */ -/* Time base (tB): 0 = 1.953 ms, 1 = 60.54 ms */ -#define ADIS16260_SMPL_PRD_TIME_BASE (1<<7) -#define ADIS16260_SMPL_PRD_DIV_MASK 0x7F - -/* SLP_CNT */ -#define ADIS16260_SLP_CNT_POWER_OFF 0x80 - -/* DIAG_STAT */ -#define ADIS16260_DIAG_STAT_ALARM2 (1<<9) -#define ADIS16260_DIAG_STAT_ALARM1 (1<<8) -#define ADIS16260_DIAG_STAT_FLASH_CHK (1<<6) -#define ADIS16260_DIAG_STAT_SELF_TEST (1<<5) -#define ADIS16260_DIAG_STAT_OVERFLOW (1<<4) -#define ADIS16260_DIAG_STAT_SPI_FAIL (1<<3) -#define ADIS16260_DIAG_STAT_FLASH_UPT (1<<2) -#define ADIS16260_DIAG_STAT_POWER_HIGH (1<<1) -#define ADIS16260_DIAG_STAT_POWER_LOW (1<<0) - -/* GLOB_CMD */ -#define ADIS16260_GLOB_CMD_SW_RESET (1<<7) -#define ADIS16260_GLOB_CMD_FLASH_UPD (1<<3) -#define ADIS16260_GLOB_CMD_DAC_LATCH (1<<2) -#define ADIS16260_GLOB_CMD_FAC_CALIB (1<<1) -#define ADIS16260_GLOB_CMD_AUTO_NULL (1<<0) - -#define ADIS16260_MAX_TX 24 -#define ADIS16260_MAX_RX 24 - -#define ADIS16260_SPI_SLOW (u32)(300 * 1000) -#define ADIS16260_SPI_BURST (u32)(1000 * 1000) -#define ADIS16260_SPI_FAST (u32)(2000 * 1000) - -/** - * struct adis16260_state - device instance specific data - * @us: actual spi_device - * @trig: data ready trigger registered with iio - * @buf_lock: mutex to protect tx and rx - * @negate: negate the scale parameter - * @tx: transmit buffer - * @rx: receive buffer - **/ -struct adis16260_state { - struct spi_device *us; - struct iio_trigger *trig; - struct mutex buf_lock; - unsigned negate:1; - u8 tx[ADIS16260_MAX_TX] ____cacheline_aligned; - u8 rx[ADIS16260_MAX_RX]; -}; - -int adis16260_set_irq(struct iio_dev *indio_dev, bool enable); - -/* At the moment triggers are only used for ring buffer - * filling. This may change! - */ - -#define ADIS16260_SCAN_SUPPLY 0 -#define ADIS16260_SCAN_GYRO 1 -#define ADIS16260_SCAN_AUX_ADC 2 -#define ADIS16260_SCAN_TEMP 3 -#define ADIS16260_SCAN_ANGL 4 - -#ifdef CONFIG_IIO_BUFFER -void adis16260_remove_trigger(struct iio_dev *indio_dev); -int adis16260_probe_trigger(struct iio_dev *indio_dev); - -ssize_t adis16260_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf); - - -int adis16260_configure_ring(struct iio_dev *indio_dev); -void adis16260_unconfigure_ring(struct iio_dev *indio_dev); - -#else /* CONFIG_IIO_BUFFER */ - -static inline void adis16260_remove_trigger(struct iio_dev *indio_dev) -{ -} - -static inline int adis16260_probe_trigger(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline ssize_t -adis16260_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return 0; -} - -static int adis16260_configure_ring(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline void adis16260_unconfigure_ring(struct iio_dev *indio_dev) -{ -} - -#endif /* CONFIG_IIO_BUFFER */ -#endif /* SPI_ADIS16260_H_ */ diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c deleted file mode 100644 index 8f6af47e955..00000000000 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ /dev/null @@ -1,723 +0,0 @@ -/* - * ADIS16260/ADIS16265 Programmable Digital Gyroscope Sensor Driver - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/delay.h> -#include <linux/mutex.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/list.h> -#include <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" - -#include "adis16260.h" - -#define DRIVER_NAME "adis16260" - -static int adis16260_check_status(struct iio_dev *indio_dev); - -/** - * adis16260_spi_write_reg_8() - write single byte to a register - * @indio_dev: iio_dev for the device - * @reg_address: the address of the register to be written - * @val: the value to write - **/ -static int adis16260_spi_write_reg_8(struct iio_dev *indio_dev, - u8 reg_address, - u8 val) -{ - int ret; - struct adis16260_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16260_WRITE_REG(reg_address); - st->tx[1] = val; - - ret = spi_write(st->us, st->tx, 2); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/** - * adis16260_spi_write_reg_16() - write 2 bytes to a pair of registers - * @indio_dev: iio_dev for the device - * @reg_address: the address of the lower of the two registers. Second register - * is assumed to have address one greater. - * @val: value to be written - **/ -static int adis16260_spi_write_reg_16(struct iio_dev *indio_dev, - u8 lower_reg_address, - u16 value) -{ - int ret; - struct spi_message msg; - struct adis16260_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 20, - }, { - .tx_buf = st->tx + 2, - .bits_per_word = 8, - .len = 2, - .delay_usecs = 20, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16260_WRITE_REG(lower_reg_address); - st->tx[1] = value & 0xFF; - st->tx[2] = ADIS16260_WRITE_REG(lower_reg_address + 1); - st->tx[3] = (value >> 8) & 0xFF; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/** - * adis16260_spi_read_reg_16() - read 2 bytes from a 16-bit register - * @indio_dev: iio_dev for the device - * @reg_address: the address of the lower of the two registers. Second register - * is assumed to have address one greater. - * @val: somewhere to pass back the value read - **/ -static int adis16260_spi_read_reg_16(struct iio_dev *indio_dev, - u8 lower_reg_address, - u16 *val) -{ - struct spi_message msg; - struct adis16260_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 30, - }, { - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 2, - .delay_usecs = 30, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16260_READ_REG(lower_reg_address); - st->tx[1] = 0; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - if (ret) { - dev_err(&st->us->dev, - "problem when reading 16 bit register 0x%02X", - lower_reg_address); - goto error_ret; - } - *val = (st->rx[0] << 8) | st->rx[1]; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -static ssize_t adis16260_read_frequency_available(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16260_state *st = iio_priv(indio_dev); - if (spi_get_device_id(st->us)->driver_data) - return sprintf(buf, "%s\n", "0.129 ~ 256"); - else - return sprintf(buf, "%s\n", "256 2048"); -} - -static ssize_t adis16260_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16260_state *st = iio_priv(indio_dev); - int ret, len = 0; - u16 t; - int sps; - ret = adis16260_spi_read_reg_16(indio_dev, - ADIS16260_SMPL_PRD, - &t); - if (ret) - return ret; - - if (spi_get_device_id(st->us)->driver_data) /* If an adis16251 */ - sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 8 : 256; - else - sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 66 : 2048; - sps /= (t & ADIS16260_SMPL_PRD_DIV_MASK) + 1; - len = sprintf(buf, "%d SPS\n", sps); - return len; -} - -static ssize_t adis16260_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16260_state *st = iio_priv(indio_dev); - long val; - int ret; - u8 t; - - ret = strict_strtol(buf, 10, &val); - if (ret) - return ret; - - mutex_lock(&indio_dev->mlock); - if (spi_get_device_id(st->us)) { - t = (256 / val); - if (t > 0) - t--; - t &= ADIS16260_SMPL_PRD_DIV_MASK; - } else { - t = (2048 / val); - if (t > 0) - t--; - t &= ADIS16260_SMPL_PRD_DIV_MASK; - } - if ((t & ADIS16260_SMPL_PRD_DIV_MASK) >= 0x0A) - st->us->max_speed_hz = ADIS16260_SPI_SLOW; - else - st->us->max_speed_hz = ADIS16260_SPI_FAST; - ret = adis16260_spi_write_reg_8(indio_dev, - ADIS16260_SMPL_PRD, - t); - - mutex_unlock(&indio_dev->mlock); - - return ret ? ret : len; -} - -static int adis16260_reset(struct iio_dev *indio_dev) -{ - int ret; - ret = adis16260_spi_write_reg_8(indio_dev, - ADIS16260_GLOB_CMD, - ADIS16260_GLOB_CMD_SW_RESET); - if (ret) - dev_err(&indio_dev->dev, "problem resetting device"); - - return ret; -} - -static ssize_t adis16260_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - if (len < 1) - return -EINVAL; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return adis16260_reset(indio_dev); - } - return -EINVAL; -} - -int adis16260_set_irq(struct iio_dev *indio_dev, bool enable) -{ - int ret; - u16 msc; - ret = adis16260_spi_read_reg_16(indio_dev, ADIS16260_MSC_CTRL, &msc); - if (ret) - goto error_ret; - - msc |= ADIS16260_MSC_CTRL_DATA_RDY_POL_HIGH; - if (enable) - msc |= ADIS16260_MSC_CTRL_DATA_RDY_EN; - else - msc &= ~ADIS16260_MSC_CTRL_DATA_RDY_EN; - - ret = adis16260_spi_write_reg_16(indio_dev, ADIS16260_MSC_CTRL, msc); - if (ret) - goto error_ret; - -error_ret: - return ret; -} - -/* Power down the device */ -static int adis16260_stop_device(struct iio_dev *indio_dev) -{ - int ret; - u16 val = ADIS16260_SLP_CNT_POWER_OFF; - - ret = adis16260_spi_write_reg_16(indio_dev, ADIS16260_SLP_CNT, val); - if (ret) - dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT"); - - return ret; -} - -static int adis16260_self_test(struct iio_dev *indio_dev) -{ - int ret; - ret = adis16260_spi_write_reg_16(indio_dev, - ADIS16260_MSC_CTRL, - ADIS16260_MSC_CTRL_MEM_TEST); - if (ret) { - dev_err(&indio_dev->dev, "problem starting self test"); - goto err_ret; - } - - adis16260_check_status(indio_dev); - -err_ret: - return ret; -} - -static int adis16260_check_status(struct iio_dev *indio_dev) -{ - u16 status; - int ret; - struct device *dev = &indio_dev->dev; - - ret = adis16260_spi_read_reg_16(indio_dev, - ADIS16260_DIAG_STAT, - &status); - - if (ret < 0) { - dev_err(dev, "Reading status failed\n"); - goto error_ret; - } - ret = status & 0x7F; - if (status & ADIS16260_DIAG_STAT_FLASH_CHK) - dev_err(dev, "Flash checksum error\n"); - if (status & ADIS16260_DIAG_STAT_SELF_TEST) - dev_err(dev, "Self test error\n"); - if (status & ADIS16260_DIAG_STAT_OVERFLOW) - dev_err(dev, "Sensor overrange\n"); - if (status & ADIS16260_DIAG_STAT_SPI_FAIL) - dev_err(dev, "SPI failure\n"); - if (status & ADIS16260_DIAG_STAT_FLASH_UPT) - dev_err(dev, "Flash update failed\n"); - if (status & ADIS16260_DIAG_STAT_POWER_HIGH) - dev_err(dev, "Power supply above 5.25V\n"); - if (status & ADIS16260_DIAG_STAT_POWER_LOW) - dev_err(dev, "Power supply below 4.75V\n"); - -error_ret: - return ret; -} - -static int adis16260_initial_setup(struct iio_dev *indio_dev) -{ - int ret; - struct device *dev = &indio_dev->dev; - - /* Disable IRQ */ - ret = adis16260_set_irq(indio_dev, false); - if (ret) { - dev_err(dev, "disable irq failed"); - goto err_ret; - } - - /* Do self test */ - ret = adis16260_self_test(indio_dev); - if (ret) { - dev_err(dev, "self test failure"); - goto err_ret; - } - - /* Read status register to check the result */ - ret = adis16260_check_status(indio_dev); - if (ret) { - adis16260_reset(indio_dev); - dev_err(dev, "device not playing ball -> reset"); - msleep(ADIS16260_STARTUP_DELAY); - ret = adis16260_check_status(indio_dev); - if (ret) { - dev_err(dev, "giving up"); - goto err_ret; - } - } - -err_ret: - return ret; -} - -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - adis16260_read_frequency, - adis16260_write_frequency); - -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16260_write_reset, 0); - -static IIO_DEVICE_ATTR(sampling_frequency_available, - S_IRUGO, adis16260_read_frequency_available, NULL, 0); - -enum adis16260_channel { - gyro, - temp, - in_supply, - in_aux, - angle, -}; -#define ADIS16260_GYRO_CHANNEL_SET(axis, mod) \ - struct iio_chan_spec adis16260_channels_##axis[] = { \ - IIO_CHAN(IIO_ANGL_VEL, 1, 0, 0, NULL, 0, mod, \ - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \ - IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ - gyro, ADIS16260_SCAN_GYRO, \ - IIO_ST('s', 14, 16, 0), 0), \ - IIO_CHAN(IIO_ANGL, 1, 0, 0, NULL, 0, mod, \ - 0, \ - angle, ADIS16260_SCAN_ANGL, \ - IIO_ST('u', 14, 16, 0), 0), \ - IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, \ - IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \ - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ - temp, ADIS16260_SCAN_TEMP, \ - IIO_ST('u', 12, 16, 0), 0), \ - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0, \ - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ - in_supply, ADIS16260_SCAN_SUPPLY, \ - IIO_ST('u', 12, 16, 0), 0), \ - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, \ - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ - in_aux, ADIS16260_SCAN_AUX_ADC, \ - IIO_ST('u', 12, 16, 0), 0), \ - IIO_CHAN_SOFT_TIMESTAMP(5) \ - } - -static const ADIS16260_GYRO_CHANNEL_SET(x, IIO_MOD_X); -static const ADIS16260_GYRO_CHANNEL_SET(y, IIO_MOD_Y); -static const ADIS16260_GYRO_CHANNEL_SET(z, IIO_MOD_Z); - -static const u8 adis16260_addresses[5][3] = { - [gyro] = { ADIS16260_GYRO_OUT, - ADIS16260_GYRO_OFF, - ADIS16260_GYRO_SCALE }, - [angle] = { ADIS16260_ANGL_OUT }, - [in_supply] = { ADIS16260_SUPPLY_OUT }, - [in_aux] = { ADIS16260_AUX_ADC }, - [temp] = { ADIS16260_TEMP_OUT }, -}; -static int adis16260_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) -{ - struct adis16260_state *st = iio_priv(indio_dev); - int ret; - int bits; - u8 addr; - s16 val16; - - switch (mask) { - case 0: - mutex_lock(&indio_dev->mlock); - addr = adis16260_addresses[chan->address][0]; - ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16); - if (ret) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - - if (val16 & ADIS16260_ERROR_ACTIVE) { - ret = adis16260_check_status(indio_dev); - if (ret) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - } - val16 = val16 & ((1 << chan->scan_type.realbits) - 1); - if (chan->scan_type.sign == 's') - val16 = (s16)(val16 << - (16 - chan->scan_type.realbits)) >> - (16 - chan->scan_type.realbits); - *val = val16; - mutex_unlock(&indio_dev->mlock); - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_ANGL_VEL: - *val = 0; - if (spi_get_device_id(st->us)->driver_data) - *val2 = 320; - else - *val2 = 1278; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_VOLTAGE: - *val = 0; - if (chan->channel == 0) - *val2 = 18315; - else - *val2 = 610500; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_TEMP: - *val = 0; - *val2 = 145300; - return IIO_VAL_INT_PLUS_MICRO; - default: - return -EINVAL; - } - break; - case IIO_CHAN_INFO_OFFSET: - *val = 25; - return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBBIAS: - switch (chan->type) { - case IIO_ANGL_VEL: - bits = 12; - break; - default: - return -EINVAL; - }; - mutex_lock(&indio_dev->mlock); - addr = adis16260_addresses[chan->address][1]; - ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16); - if (ret) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - val16 &= (1 << bits) - 1; - val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); - *val = val16; - mutex_unlock(&indio_dev->mlock); - return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBSCALE: - switch (chan->type) { - case IIO_ANGL_VEL: - bits = 12; - break; - default: - return -EINVAL; - }; - mutex_lock(&indio_dev->mlock); - addr = adis16260_addresses[chan->address][2]; - ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16); - if (ret) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - *val = (1 << bits) - 1; - mutex_unlock(&indio_dev->mlock); - return IIO_VAL_INT; - } - return -EINVAL; -} - -static int adis16260_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - int bits = 12; - s16 val16; - u8 addr; - switch (mask) { - case IIO_CHAN_INFO_CALIBBIAS: - val16 = val & ((1 << bits) - 1); - addr = adis16260_addresses[chan->address][1]; - return adis16260_spi_write_reg_16(indio_dev, addr, val16); - case IIO_CHAN_INFO_CALIBSCALE: - val16 = val & ((1 << bits) - 1); - addr = adis16260_addresses[chan->address][2]; - return adis16260_spi_write_reg_16(indio_dev, addr, val16); - } - return -EINVAL; -} - -static struct attribute *adis16260_attributes[] = { - &iio_dev_attr_sampling_frequency.dev_attr.attr, - &iio_dev_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_reset.dev_attr.attr, - NULL -}; - -static const struct attribute_group adis16260_attribute_group = { - .attrs = adis16260_attributes, -}; - -static const struct iio_info adis16260_info = { - .attrs = &adis16260_attribute_group, - .read_raw = &adis16260_read_raw, - .write_raw = &adis16260_write_raw, - .driver_module = THIS_MODULE, -}; - -static int __devinit adis16260_probe(struct spi_device *spi) -{ - int ret; - struct adis16260_platform_data *pd = spi->dev.platform_data; - struct adis16260_state *st; - struct iio_dev *indio_dev; - - /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - st = iio_priv(indio_dev); - if (pd) - st->negate = pd->negate; - /* this is only used for removal purposes */ - spi_set_drvdata(spi, st); - - st->us = spi; - mutex_init(&st->buf_lock); - - indio_dev->name = spi_get_device_id(st->us)->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &adis16260_info; - indio_dev->num_channels - = ARRAY_SIZE(adis16260_channels_x); - if (pd && pd->direction) - switch (pd->direction) { - case 'x': - indio_dev->channels = adis16260_channels_x; - break; - case 'y': - indio_dev->channels = adis16260_channels_y; - break; - case 'z': - indio_dev->channels = adis16260_channels_z; - break; - default: - return -EINVAL; - } - else - indio_dev->channels = adis16260_channels_x; - indio_dev->num_channels = ARRAY_SIZE(adis16260_channels_x); - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = adis16260_configure_ring(indio_dev); - if (ret) - goto error_free_dev; - - ret = iio_buffer_register(indio_dev, - indio_dev->channels, - ARRAY_SIZE(adis16260_channels_x)); - if (ret) { - printk(KERN_ERR "failed to initialize the ring\n"); - goto error_unreg_ring_funcs; - } - if (indio_dev->buffer) { - /* Set default scan mode */ - iio_scan_mask_set(indio_dev, indio_dev->buffer, - ADIS16260_SCAN_SUPPLY); - iio_scan_mask_set(indio_dev, indio_dev->buffer, - ADIS16260_SCAN_GYRO); - iio_scan_mask_set(indio_dev, indio_dev->buffer, - ADIS16260_SCAN_AUX_ADC); - iio_scan_mask_set(indio_dev, indio_dev->buffer, - ADIS16260_SCAN_TEMP); - iio_scan_mask_set(indio_dev, indio_dev->buffer, - ADIS16260_SCAN_ANGL); - } - if (spi->irq) { - ret = adis16260_probe_trigger(indio_dev); - if (ret) - goto error_uninitialize_ring; - } - - /* Get the device into a sane initial state */ - ret = adis16260_initial_setup(indio_dev); - if (ret) - goto error_remove_trigger; - ret = iio_device_register(indio_dev); - if (ret) - goto error_remove_trigger; - - return 0; - -error_remove_trigger: - adis16260_remove_trigger(indio_dev); -error_uninitialize_ring: - iio_buffer_unregister(indio_dev); -error_unreg_ring_funcs: - adis16260_unconfigure_ring(indio_dev); -error_free_dev: - iio_free_device(indio_dev); -error_ret: - return ret; -} - -static int adis16260_remove(struct spi_device *spi) -{ - int ret; - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - iio_device_unregister(indio_dev); - - ret = adis16260_stop_device(indio_dev); - if (ret) - goto err_ret; - - flush_scheduled_work(); - - adis16260_remove_trigger(indio_dev); - iio_buffer_unregister(indio_dev); - adis16260_unconfigure_ring(indio_dev); - iio_free_device(indio_dev); - -err_ret: - return ret; -} - -/* - * These parts do not need to be differentiated until someone adds - * support for the on chip filtering. - */ -static const struct spi_device_id adis16260_id[] = { - {"adis16260", 0}, - {"adis16265", 0}, - {"adis16250", 0}, - {"adis16255", 0}, - {"adis16251", 1}, - {} -}; -MODULE_DEVICE_TABLE(spi, adis16260_id); - -static struct spi_driver adis16260_driver = { - .driver = { - .name = "adis16260", - .owner = THIS_MODULE, - }, - .probe = adis16260_probe, - .remove = __devexit_p(adis16260_remove), - .id_table = adis16260_id, -}; -module_spi_driver(adis16260_driver); - -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_DESCRIPTION("Analog Devices ADIS16260/5 Digital Gyroscope Sensor"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/gyro/adis16260_platform_data.h b/drivers/staging/iio/gyro/adis16260_platform_data.h deleted file mode 100644 index 12802e97be9..00000000000 --- a/drivers/staging/iio/gyro/adis16260_platform_data.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * ADIS16260 Programmable Digital Gyroscope Sensor Driver Platform Data - * - * Based on adis16255.h Matthia Brugger <m_brugger&web.de> - * - * Copyright (C) 2010 Fraunhofer Institute for Integrated Circuits - * - * Licensed under the GPL-2 or later. - */ - -/** - * struct adis16260_platform_data - instance specific data - * @direction: x y or z - * @negate: flag to indicate value should be inverted. - **/ -struct adis16260_platform_data { - char direction; - unsigned negate:1; -}; diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c deleted file mode 100644 index 699a6152c40..00000000000 --- a/drivers/staging/iio/gyro/adis16260_ring.c +++ /dev/null @@ -1,140 +0,0 @@ -#include <linux/export.h> -#include <linux/interrupt.h> -#include <linux/mutex.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> - -#include "../iio.h" -#include "../ring_sw.h" -#include "../trigger_consumer.h" -#include "adis16260.h" - -/** - * adis16260_read_ring_data() read data registers which will be placed into ring - * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @rx: somewhere to pass back the value read - **/ -static int adis16260_read_ring_data(struct device *dev, u8 *rx) -{ - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16260_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[ADIS16260_OUTPUTS + 1]; - int ret; - int i; - - mutex_lock(&st->buf_lock); - - spi_message_init(&msg); - - memset(xfers, 0, sizeof(xfers)); - for (i = 0; i <= ADIS16260_OUTPUTS; i++) { - xfers[i].bits_per_word = 8; - xfers[i].cs_change = 1; - xfers[i].len = 2; - xfers[i].delay_usecs = 30; - xfers[i].tx_buf = st->tx + 2 * i; - if (i < 2) /* SUPPLY_OUT:0x02 GYRO_OUT:0x04 */ - st->tx[2 * i] - = ADIS16260_READ_REG(ADIS16260_SUPPLY_OUT - + 2 * i); - else /* 0x06 to 0x09 is reserved */ - st->tx[2 * i] - = ADIS16260_READ_REG(ADIS16260_SUPPLY_OUT - + 2 * i + 4); - st->tx[2 * i + 1] = 0; - if (i >= 1) - xfers[i].rx_buf = rx + 2 * (i - 1); - spi_message_add_tail(&xfers[i], &msg); - } - - ret = spi_sync(st->us, &msg); - if (ret) - dev_err(&st->us->dev, "problem when burst reading"); - - mutex_unlock(&st->buf_lock); - - return ret; -} - -static irqreturn_t adis16260_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct adis16260_state *st = iio_priv(indio_dev); - struct iio_buffer *ring = indio_dev->buffer; - int i = 0; - s16 *data; - size_t datasize = ring->access->get_bytes_per_datum(ring); - - data = kmalloc(datasize , GFP_KERNEL); - if (data == NULL) { - dev_err(&st->us->dev, "memory alloc failed in ring bh"); - return -ENOMEM; - } - - if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) && - adis16260_read_ring_data(&indio_dev->dev, st->rx) >= 0) - for (; i < bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength); i++) - data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2])); - - /* Guaranteed to be aligned with 8 byte boundary */ - if (ring->scan_timestamp) - *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - - ring->access->store_to(ring, (u8 *)data, pf->timestamp); - - iio_trigger_notify_done(indio_dev->trig); - kfree(data); - - return IRQ_HANDLED; -} - -void adis16260_unconfigure_ring(struct iio_dev *indio_dev) -{ - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->buffer); -} - -static const struct iio_buffer_setup_ops adis16260_ring_setup_ops = { - .preenable = &iio_sw_buffer_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, -}; - -int adis16260_configure_ring(struct iio_dev *indio_dev) -{ - int ret = 0; - struct iio_buffer *ring; - - ring = iio_sw_rb_allocate(indio_dev); - if (!ring) { - ret = -ENOMEM; - return ret; - } - indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ - ring->access = &ring_sw_access_funcs; - ring->scan_timestamp = true; - indio_dev->setup_ops = &adis16260_ring_setup_ops; - - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, - &adis16260_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "adis16260_consumer%d", - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_iio_sw_rb_free; - } - - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; - -error_iio_sw_rb_free: - iio_sw_rb_free(indio_dev->buffer); - return ret; -} diff --git a/drivers/staging/iio/gyro/adis16260_trigger.c b/drivers/staging/iio/gyro/adis16260_trigger.c deleted file mode 100644 index 8299cd18d70..00000000000 --- a/drivers/staging/iio/gyro/adis16260_trigger.c +++ /dev/null @@ -1,75 +0,0 @@ -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/export.h> - -#include "../iio.h" -#include "../trigger.h" -#include "adis16260.h" - -/** - * adis16260_data_rdy_trigger_set_state() set datardy interrupt state - **/ -static int adis16260_data_rdy_trigger_set_state(struct iio_trigger *trig, - bool state) -{ - struct iio_dev *indio_dev = trig->private_data; - - dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); - return adis16260_set_irq(indio_dev, state); -} - -static const struct iio_trigger_ops adis16260_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &adis16260_data_rdy_trigger_set_state, -}; - -int adis16260_probe_trigger(struct iio_dev *indio_dev) -{ - int ret; - struct adis16260_state *st = iio_priv(indio_dev); - - st->trig = iio_allocate_trigger("%s-dev%d", - spi_get_device_id(st->us)->name, - indio_dev->id); - if (st->trig == NULL) { - ret = -ENOMEM; - goto error_ret; - } - - ret = request_irq(st->us->irq, - &iio_trigger_generic_data_rdy_poll, - IRQF_TRIGGER_RISING, - "adis16260", - st->trig); - if (ret) - goto error_free_trig; - - st->trig->dev.parent = &st->us->dev; - st->trig->ops = &adis16260_trigger_ops; - st->trig->private_data = indio_dev; - ret = iio_trigger_register(st->trig); - - /* select default trigger */ - indio_dev->trig = st->trig; - if (ret) - goto error_free_irq; - - return 0; - -error_free_irq: - free_irq(st->us->irq, st->trig); -error_free_trig: - iio_free_trigger(st->trig); -error_ret: - return ret; -} - -void adis16260_remove_trigger(struct iio_dev *indio_dev) -{ - struct adis16260_state *st = iio_priv(indio_dev); - - iio_trigger_unregister(st->trig); - free_irq(st->us->irq, st->trig); - iio_free_trigger(st->trig); -} diff --git a/drivers/staging/iio/gyro/adxrs450.h b/drivers/staging/iio/gyro/adxrs450.h deleted file mode 100644 index af0c870100b..00000000000 --- a/drivers/staging/iio/gyro/adxrs450.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef SPI_ADXRS450_H_ -#define SPI_ADXRS450_H_ - -#define ADXRS450_STARTUP_DELAY 50 /* ms */ - -/* The MSB for the spi commands */ -#define ADXRS450_SENSOR_DATA 0x20 -#define ADXRS450_WRITE_DATA 0x40 -#define ADXRS450_READ_DATA 0x80 - -#define ADXRS450_RATE1 0x00 /* Rate Registers */ -#define ADXRS450_TEMP1 0x02 /* Temperature Registers */ -#define ADXRS450_LOCST1 0x04 /* Low CST Memory Registers */ -#define ADXRS450_HICST1 0x06 /* High CST Memory Registers */ -#define ADXRS450_QUAD1 0x08 /* Quad Memory Registers */ -#define ADXRS450_FAULT1 0x0A /* Fault Registers */ -#define ADXRS450_PID1 0x0C /* Part ID Register 1 */ -#define ADXRS450_SNH 0x0E /* Serial Number Registers, 4 bytes */ -#define ADXRS450_SNL 0x10 -#define ADXRS450_DNC1 0x12 /* Dynamic Null Correction Registers */ -/* Check bits */ -#define ADXRS450_P 0x01 -#define ADXRS450_CHK 0x02 -#define ADXRS450_CST 0x04 -#define ADXRS450_PWR 0x08 -#define ADXRS450_POR 0x10 -#define ADXRS450_NVM 0x20 -#define ADXRS450_Q 0x40 -#define ADXRS450_PLL 0x80 -#define ADXRS450_UV 0x100 -#define ADXRS450_OV 0x200 -#define ADXRS450_AMP 0x400 -#define ADXRS450_FAIL 0x800 - -#define ADXRS450_WRERR_MASK (0x7 << 29) - -#define ADXRS450_MAX_RX 4 -#define ADXRS450_MAX_TX 4 - -#define ADXRS450_GET_ST(a) ((a >> 26) & 0x3) - -enum { - ID_ADXRS450, - ID_ADXRS453, -}; - -/** - * struct adxrs450_state - device instance specific data - * @us: actual spi_device - * @buf_lock: mutex to protect tx and rx - * @tx: transmit buffer - * @rx: recieve buffer - **/ -struct adxrs450_state { - struct spi_device *us; - struct mutex buf_lock; - u8 tx[ADXRS450_MAX_RX] ____cacheline_aligned; - u8 rx[ADXRS450_MAX_TX]; - -}; - -#endif /* SPI_ADXRS450_H_ */ diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c deleted file mode 100644 index 15e2496f70c..00000000000 --- a/drivers/staging/iio/gyro/adxrs450_core.c +++ /dev/null @@ -1,436 +0,0 @@ -/* - * ADXRS450/ADXRS453 Digital Output Gyroscope Driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/delay.h> -#include <linux/mutex.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/list.h> -#include <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" - -#include "adxrs450.h" - -/** - * adxrs450_spi_read_reg_16() - read 2 bytes from a register pair - * @dev: device associated with child of actual iio_dev - * @reg_address: the address of the lower of the two registers,which should be an even address, - * Second register's address is reg_address + 1. - * @val: somewhere to pass back the value read - **/ -static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, - u8 reg_address, - u16 *val) -{ - struct adxrs450_state *st = iio_priv(indio_dev); - int ret; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADXRS450_READ_DATA | (reg_address >> 7); - st->tx[1] = reg_address << 1; - st->tx[2] = 0; - st->tx[3] = 0; - - if (!(hweight32(be32_to_cpu(*(u32 *)st->tx)) & 1)) - st->tx[3] |= ADXRS450_P; - - ret = spi_write(st->us, st->tx, 4); - if (ret) { - dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n", - reg_address); - goto error_ret; - } - ret = spi_read(st->us, st->rx, 4); - if (ret) { - dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n", - reg_address); - goto error_ret; - } - - *val = (be32_to_cpu(*(u32 *)st->rx) >> 5) & 0xFFFF; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -/** - * adxrs450_spi_write_reg_16() - write 2 bytes data to a register pair - * @dev: device associated with child of actual actual iio_dev - * @reg_address: the address of the lower of the two registers,which should be an even address, - * Second register's address is reg_address + 1. - * @val: value to be written. - **/ -static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev, - u8 reg_address, - u16 val) -{ - struct adxrs450_state *st = iio_priv(indio_dev); - int ret; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADXRS450_WRITE_DATA | reg_address >> 7; - st->tx[1] = reg_address << 1 | val >> 15; - st->tx[2] = val >> 7; - st->tx[3] = val << 1; - - if (!(hweight32(be32_to_cpu(*(u32 *)st->tx)) & 1)) - st->tx[3] |= ADXRS450_P; - - ret = spi_write(st->us, st->tx, 4); - if (ret) - dev_err(&st->us->dev, "problem while writing 16 bit register 0x%02x\n", - reg_address); - msleep(1); /* enforce sequential transfer delay 0.1ms */ - mutex_unlock(&st->buf_lock); - return ret; -} - -/** - * adxrs450_spi_sensor_data() - read 2 bytes sensor data - * @dev: device associated with child of actual iio_dev - * @val: somewhere to pass back the value read - **/ -static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) -{ - struct adxrs450_state *st = iio_priv(indio_dev); - int ret; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADXRS450_SENSOR_DATA; - st->tx[1] = 0; - st->tx[2] = 0; - st->tx[3] = 0; - - ret = spi_write(st->us, st->tx, 4); - if (ret) { - dev_err(&st->us->dev, "Problem while reading sensor data\n"); - goto error_ret; - } - - ret = spi_read(st->us, st->rx, 4); - if (ret) { - dev_err(&st->us->dev, "Problem while reading sensor data\n"); - goto error_ret; - } - - *val = (be32_to_cpu(*(u32 *)st->rx) >> 10) & 0xFFFF; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -/** - * adxrs450_spi_initial() - use for initializing procedure. - * @st: device instance specific data - * @val: somewhere to pass back the value read - **/ -static int adxrs450_spi_initial(struct adxrs450_state *st, - u32 *val, char chk) -{ - struct spi_message msg; - int ret; - struct spi_transfer xfers = { - .tx_buf = st->tx, - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 4, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADXRS450_SENSOR_DATA; - st->tx[1] = 0; - st->tx[2] = 0; - st->tx[3] = 0; - if (chk) - st->tx[3] |= (ADXRS450_CHK | ADXRS450_P); - spi_message_init(&msg); - spi_message_add_tail(&xfers, &msg); - ret = spi_sync(st->us, &msg); - if (ret) { - dev_err(&st->us->dev, "Problem while reading initializing data\n"); - goto error_ret; - } - - *val = be32_to_cpu(*(u32 *)st->rx); - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -/* Recommended Startup Sequence by spec */ -static int adxrs450_initial_setup(struct iio_dev *indio_dev) -{ - u32 t; - u16 data; - int ret; - struct adxrs450_state *st = iio_priv(indio_dev); - - msleep(ADXRS450_STARTUP_DELAY*2); - ret = adxrs450_spi_initial(st, &t, 1); - if (ret) - return ret; - if (t != 0x01) - dev_warn(&st->us->dev, "The initial power on response " - "is not correct! Restart without reset?\n"); - - msleep(ADXRS450_STARTUP_DELAY); - ret = adxrs450_spi_initial(st, &t, 0); - if (ret) - return ret; - - msleep(ADXRS450_STARTUP_DELAY); - ret = adxrs450_spi_initial(st, &t, 0); - if (ret) - return ret; - if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) { - dev_err(&st->us->dev, "The second response is not correct!\n"); - return -EIO; - - } - ret = adxrs450_spi_initial(st, &t, 0); - if (ret) - return ret; - if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) { - dev_err(&st->us->dev, "The third response is not correct!\n"); - return -EIO; - - } - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_FAULT1, &data); - if (ret) - return ret; - if (data & 0x0fff) { - dev_err(&st->us->dev, "The device is not in normal status!\n"); - return -EINVAL; - } - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_PID1, &data); - if (ret) - return ret; - dev_info(&st->us->dev, "The Part ID is 0x%x\n", data); - - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_SNL, &data); - if (ret) - return ret; - t = data; - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_SNH, &data); - if (ret) - return ret; - t |= data << 16; - dev_info(&st->us->dev, "The Serial Number is 0x%x\n", t); - - return 0; -} - -static int adxrs450_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - int ret; - switch (mask) { - case IIO_CHAN_INFO_CALIBBIAS: - ret = adxrs450_spi_write_reg_16(indio_dev, - ADXRS450_DNC1, - val & 0x3FF); - break; - default: - ret = -EINVAL; - break; - } - return ret; -} - -static int adxrs450_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long mask) -{ - int ret; - s16 t; - - switch (mask) { - case 0: - switch (chan->type) { - case IIO_ANGL_VEL: - ret = adxrs450_spi_sensor_data(indio_dev, &t); - if (ret) - break; - *val = t; - ret = IIO_VAL_INT; - break; - case IIO_TEMP: - ret = adxrs450_spi_read_reg_16(indio_dev, - ADXRS450_TEMP1, &t); - if (ret) - break; - *val = (t >> 6) + 225; - ret = IIO_VAL_INT; - break; - default: - ret = -EINVAL; - break; - } - break; - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_ANGL_VEL: - *val = 0; - *val2 = 218166; - return IIO_VAL_INT_PLUS_NANO; - case IIO_TEMP: - *val = 200; - *val2 = 0; - return IIO_VAL_INT; - default: - return -EINVAL; - } - break; - case IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW: - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t); - if (ret) - break; - *val = t; - ret = IIO_VAL_INT; - break; - case IIO_CHAN_INFO_CALIBBIAS: - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_DNC1, &t); - if (ret) - break; - *val = t; - ret = IIO_VAL_INT; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static const struct iio_chan_spec adxrs450_channels[2][2] = { - [ID_ADXRS450] = { - { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - } - }, - [ID_ADXRS453] = { - { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT | - IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT, - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - } - }, -}; - -static const struct iio_info adxrs450_info = { - .driver_module = THIS_MODULE, - .read_raw = &adxrs450_read_raw, - .write_raw = &adxrs450_write_raw, -}; - -static int __devinit adxrs450_probe(struct spi_device *spi) -{ - int ret; - struct adxrs450_state *st; - struct iio_dev *indio_dev; - - /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - st = iio_priv(indio_dev); - st->us = spi; - mutex_init(&st->buf_lock); - /* This is only used for removal purposes */ - spi_set_drvdata(spi, indio_dev); - - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &adxrs450_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = - adxrs450_channels[spi_get_device_id(spi)->driver_data]; - indio_dev->num_channels = ARRAY_SIZE(adxrs450_channels); - indio_dev->name = spi->dev.driver->name; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - - /* Get the device into a sane initial state */ - ret = adxrs450_initial_setup(indio_dev); - if (ret) - goto error_initial; - return 0; -error_initial: - iio_device_unregister(indio_dev); -error_free_dev: - iio_free_device(indio_dev); - -error_ret: - return ret; -} - -static int adxrs450_remove(struct spi_device *spi) -{ - iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); - - return 0; -} - -static const struct spi_device_id adxrs450_id[] = { - {"adxrs450", ID_ADXRS450}, - {"adxrs453", ID_ADXRS453}, - {} -}; -MODULE_DEVICE_TABLE(spi, adxrs450_id); - -static struct spi_driver adxrs450_driver = { - .driver = { - .name = "adxrs450", - .owner = THIS_MODULE, - }, - .probe = adxrs450_probe, - .remove = __devexit_p(adxrs450_remove), - .id_table = adxrs450_id, -}; -module_spi_driver(adxrs450_driver); - -MODULE_AUTHOR("Cliff Cai <cliff.cai@xxxxxxxxxx>"); -MODULE_DESCRIPTION("Analog Devices ADXRS450/ADXRS453 Gyroscope SPI driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h deleted file mode 100644 index be6ced31f65..00000000000 --- a/drivers/staging/iio/iio.h +++ /dev/null @@ -1,427 +0,0 @@ - -/* The industrial I/O core - * - * 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. - */ -#ifndef _INDUSTRIAL_IO_H_ -#define _INDUSTRIAL_IO_H_ - -#include <linux/device.h> -#include <linux/cdev.h> -#include "types.h" -/* IIO TODO LIST */ -/* - * Provide means of adjusting timer accuracy. - * Currently assumes nano seconds. - */ - -enum iio_data_type { - IIO_RAW, - IIO_PROCESSED, -}; - -/* Could add the raw attributes as well - allowing buffer only devices */ -enum iio_chan_info_enum { - /* 0 is reserverd for raw attributes */ - IIO_CHAN_INFO_SCALE = 1, - IIO_CHAN_INFO_OFFSET, - IIO_CHAN_INFO_CALIBSCALE, - IIO_CHAN_INFO_CALIBBIAS, - IIO_CHAN_INFO_PEAK, - IIO_CHAN_INFO_PEAK_SCALE, - IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW, - IIO_CHAN_INFO_AVERAGE_RAW, - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY, -}; - -#define IIO_CHAN_INFO_SHARED_BIT(type) BIT(type*2) -#define IIO_CHAN_INFO_SEPARATE_BIT(type) BIT(type*2 + 1) - -#define IIO_CHAN_INFO_SCALE_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_SCALE) -#define IIO_CHAN_INFO_SCALE_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_SCALE) -#define IIO_CHAN_INFO_OFFSET_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_OFFSET) -#define IIO_CHAN_INFO_OFFSET_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_OFFSET) -#define IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_CALIBSCALE) -#define IIO_CHAN_INFO_CALIBSCALE_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_CALIBSCALE) -#define IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_CALIBBIAS) -#define IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_CALIBBIAS) -#define IIO_CHAN_INFO_PEAK_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PEAK) -#define IIO_CHAN_INFO_PEAK_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PEAK) -#define IIO_CHAN_INFO_PEAKSCALE_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PEAKSCALE) -#define IIO_CHAN_INFO_PEAKSCALE_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PEAKSCALE) -#define IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT( \ - IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW) -#define IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT( \ - IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW) -#define IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_AVERAGE_RAW) -#define IIO_CHAN_INFO_AVERAGE_RAW_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_AVERAGE_RAW) -#define IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT( \ - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) -#define IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT( \ - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) - -enum iio_endian { - IIO_CPU, - IIO_BE, - IIO_LE, -}; - -/** - * struct iio_chan_spec - specification of a single channel - * @type: What type of measurement is the channel making. - * @channel: What number or name do we wish to asign the channel. - * @channel2: If there is a second number for a differential - * channel then this is it. If modified is set then the - * value here specifies the modifier. - * @address: Driver specific identifier. - * @scan_index: Monotonic index to give ordering in scans when read - * from a buffer. - * @scan_type: Sign: 's' or 'u' to specify signed or unsigned - * realbits: Number of valid bits of data - * storage_bits: Realbits + padding - * shift: Shift right by this before masking out - * realbits. - * endianness: little or big endian - * @info_mask: What information is to be exported about this channel. - * This includes calibbias, scale etc. - * @event_mask: What events can this channel produce. - * @extend_name: Allows labeling of channel attributes with an - * informative name. Note this has no effect codes etc, - * unlike modifiers. - * @datasheet_name: A name used in in kernel mapping of channels. It should - * corrspond to the first name that the channel is referred - * to by in the datasheet (e.g. IND), or the nearest - * possible compound name (e.g. IND-INC). - * @processed_val: Flag to specify the data access attribute should be - * *_input rather than *_raw. - * @modified: Does a modifier apply to this channel. What these are - * depends on the channel type. Modifier is set in - * channel2. Examples are IIO_MOD_X for axial sensors about - * the 'x' axis. - * @indexed: Specify the channel has a numerical index. If not, - * the value in channel will be suppressed for attribute - * but not for event codes. Typically set it to 0 when - * the index is false. - * @differential: Channel is differential. - */ -struct iio_chan_spec { - enum iio_chan_type type; - int channel; - int channel2; - unsigned long address; - int scan_index; - struct { - char sign; - u8 realbits; - u8 storagebits; - u8 shift; - enum iio_endian endianness; - } scan_type; - long info_mask; - long event_mask; - char *extend_name; - const char *datasheet_name; - unsigned processed_val:1; - unsigned modified:1; - unsigned indexed:1; - unsigned output:1; - unsigned differential:1; -}; - -#define IIO_ST(si, rb, sb, sh) \ - { .sign = si, .realbits = rb, .storagebits = sb, .shift = sh } - -/* Macro assumes input channels */ -#define IIO_CHAN(_type, _mod, _indexed, _proc, _name, _chan, _chan2, \ - _inf_mask, _address, _si, _stype, _event_mask) \ - { .type = _type, \ - .output = 0, \ - .modified = _mod, \ - .indexed = _indexed, \ - .processed_val = _proc, \ - .extend_name = _name, \ - .channel = _chan, \ - .channel2 = _chan2, \ - .info_mask = _inf_mask, \ - .address = _address, \ - .scan_index = _si, \ - .scan_type = _stype, \ - .event_mask = _event_mask } - -#define IIO_CHAN_SOFT_TIMESTAMP(_si) \ - { .type = IIO_TIMESTAMP, .channel = -1, \ - .scan_index = _si, .scan_type = IIO_ST('s', 64, 64, 0) } - -/** - * iio_get_time_ns() - utility function to get a time stamp for events etc - **/ -static inline s64 iio_get_time_ns(void) -{ - struct timespec ts; - /* - * calls getnstimeofday. - * If hrtimers then up to ns accurate, if not microsecond. - */ - ktime_get_real_ts(&ts); - - return timespec_to_ns(&ts); -} - -/* Device operating modes */ -#define INDIO_DIRECT_MODE 0x01 -#define INDIO_BUFFER_TRIGGERED 0x02 -#define INDIO_BUFFER_HARDWARE 0x08 - -#define INDIO_ALL_BUFFER_MODES \ - (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE) - -/* Vast majority of this is set by the industrialio subsystem on a - * call to iio_device_register. */ -#define IIO_VAL_INT 1 -#define IIO_VAL_INT_PLUS_MICRO 2 -#define IIO_VAL_INT_PLUS_NANO 3 - -struct iio_trigger; /* forward declaration */ -struct iio_dev; - -/** - * struct iio_info - constant information about device - * @driver_module: module structure used to ensure correct - * ownership of chrdevs etc - * @event_attrs: event control attributes - * @attrs: general purpose device attributes - * @read_raw: function to request a value from the device. - * mask specifies which value. Note 0 means a reading of - * the channel in question. Return value will specify the - * type of value returned by the device. val and val2 will - * contain the elements making up the returned value. - * @write_raw: function to write a value to the device. - * Parameters are the same as for read_raw. - * @write_raw_get_fmt: callback function to query the expected - * format/precision. If not set by the driver, write_raw - * returns IIO_VAL_INT_PLUS_MICRO. - * @read_event_config: find out if the event is enabled. - * @write_event_config: set if the event is enabled. - * @read_event_value: read a value associated with the event. Meaning - * is event dependant. event_code specifies which event. - * @write_event_value: write the value associate with the event. - * Meaning is event dependent. - * @validate_trigger: function to validate the trigger when the - * current trigger gets changed. - **/ -struct iio_info { - struct module *driver_module; - struct attribute_group *event_attrs; - const struct attribute_group *attrs; - - int (*read_raw)(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long mask); - - int (*write_raw)(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask); - - int (*write_raw_get_fmt)(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - long mask); - - int (*read_event_config)(struct iio_dev *indio_dev, - u64 event_code); - - int (*write_event_config)(struct iio_dev *indio_dev, - u64 event_code, - int state); - - int (*read_event_value)(struct iio_dev *indio_dev, - u64 event_code, - int *val); - int (*write_event_value)(struct iio_dev *indio_dev, - u64 event_code, - int val); - int (*validate_trigger)(struct iio_dev *indio_dev, - struct iio_trigger *trig); - int (*update_scan_mode)(struct iio_dev *indio_dev, - const unsigned long *scan_mask); -}; - -/** - * struct iio_buffer_setup_ops - buffer setup related callbacks - * @preenable: [DRIVER] function to run prior to marking buffer enabled - * @postenable: [DRIVER] function to run after marking buffer enabled - * @predisable: [DRIVER] function to run prior to marking buffer - * disabled - * @postdisable: [DRIVER] function to run after marking buffer disabled - */ -struct iio_buffer_setup_ops { - int (*preenable)(struct iio_dev *); - int (*postenable)(struct iio_dev *); - int (*predisable)(struct iio_dev *); - int (*postdisable)(struct iio_dev *); -}; - -/** - * struct iio_dev - industrial I/O device - * @id: [INTERN] used to identify device internally - * @modes: [DRIVER] operating modes supported by device - * @currentmode: [DRIVER] current operating mode - * @dev: [DRIVER] device structure, should be assigned a parent - * and owner - * @event_interface: [INTERN] event chrdevs associated with interrupt lines - * @buffer: [DRIVER] any buffer present - * @mlock: [INTERN] lock used to prevent simultaneous device state - * changes - * @available_scan_masks: [DRIVER] optional array of allowed bitmasks - * @masklength: [INTERN] the length of the mask established from - * channels - * @active_scan_mask: [INTERN] union of all scan masks requested by buffers - * @trig: [INTERN] current device trigger (buffer modes) - * @pollfunc: [DRIVER] function run on trigger being received - * @channels: [DRIVER] channel specification structure table - * @num_channels: [DRIVER] number of chanels specified in @channels. - * @channel_attr_list: [INTERN] keep track of automatically created channel - * attributes - * @chan_attr_group: [INTERN] group for all attrs in base directory - * @name: [DRIVER] name of the device. - * @info: [DRIVER] callbacks and constant info from driver - * @chrdev: [INTERN] associated character device - * @groups: [INTERN] attribute groups - * @groupcounter: [INTERN] index of next attribute group - * @flags: [INTERN] file ops related flags including busy flag. - **/ -struct iio_dev { - int id; - - int modes; - int currentmode; - struct device dev; - - struct iio_event_interface *event_interface; - - struct iio_buffer *buffer; - struct mutex mlock; - - unsigned long *available_scan_masks; - unsigned masklength; - unsigned long *active_scan_mask; - struct iio_trigger *trig; - struct iio_poll_func *pollfunc; - - struct iio_chan_spec const *channels; - int num_channels; - - struct list_head channel_attr_list; - struct attribute_group chan_attr_group; - const char *name; - const struct iio_info *info; - const struct iio_buffer_setup_ops *setup_ops; - struct cdev chrdev; -#define IIO_MAX_GROUPS 6 - const struct attribute_group *groups[IIO_MAX_GROUPS + 1]; - int groupcounter; - - unsigned long flags; -}; - -/** - * iio_find_channel_from_si() - get channel from its scan index - * @indio_dev: device - * @si: scan index to match - */ -const struct iio_chan_spec -*iio_find_channel_from_si(struct iio_dev *indio_dev, int si); - -/** - * iio_device_register() - register a device with the IIO subsystem - * @indio_dev: Device structure filled by the device driver - **/ -int iio_device_register(struct iio_dev *indio_dev); - -/** - * iio_device_unregister() - unregister a device from the IIO subsystem - * @indio_dev: Device structure representing the device. - **/ -void iio_device_unregister(struct iio_dev *indio_dev); - -/** - * iio_push_event() - try to add event to the list for userspace reading - * @indio_dev: IIO device structure - * @ev_code: What event - * @timestamp: When the event occurred - **/ -int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp); - -extern struct bus_type iio_bus_type; - -/** - * iio_put_device() - reference counted deallocation of struct device - * @dev: the iio_device containing the device - **/ -static inline void iio_put_device(struct iio_dev *indio_dev) -{ - if (indio_dev) - put_device(&indio_dev->dev); -}; - -/* Can we make this smaller? */ -#define IIO_ALIGN L1_CACHE_BYTES -/** - * iio_allocate_device() - allocate an iio_dev from a driver - * @sizeof_priv: Space to allocate for private structure. - **/ -struct iio_dev *iio_allocate_device(int sizeof_priv); - -static inline void *iio_priv(const struct iio_dev *indio_dev) -{ - return (char *)indio_dev + ALIGN(sizeof(struct iio_dev), IIO_ALIGN); -} - -static inline struct iio_dev *iio_priv_to_dev(void *priv) -{ - return (struct iio_dev *)((char *)priv - - ALIGN(sizeof(struct iio_dev), IIO_ALIGN)); -} - -/** - * iio_free_device() - free an iio_dev from a driver - * @dev: the iio_dev associated with the device - **/ -void iio_free_device(struct iio_dev *indio_dev); - -/** - * iio_buffer_enabled() - helper function to test if the buffer is enabled - * @indio_dev: IIO device info structure for device - **/ -static inline bool iio_buffer_enabled(struct iio_dev *indio_dev) -{ - return indio_dev->currentmode - & (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE); -}; - -#endif /* _INDUSTRIAL_IO_H_ */ diff --git a/drivers/staging/iio/iio_core.h b/drivers/staging/iio/iio_core.h deleted file mode 100644 index 107cfb1cbb0..00000000000 --- a/drivers/staging/iio/iio_core.h +++ /dev/null @@ -1,52 +0,0 @@ -/* The industrial I/O core function defs. - * - * Copyright (c) 2008 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * These definitions are meant for use only within the IIO core, not individual - * drivers. - */ - -#ifndef _IIO_CORE_H_ -#define _IIO_CORE_H_ - -int __iio_add_chan_devattr(const char *postfix, - struct iio_chan_spec const *chan, - ssize_t (*func)(struct device *dev, - struct device_attribute *attr, - char *buf), - ssize_t (*writefunc)(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len), - u64 mask, - bool generic, - struct device *dev, - struct list_head *attr_list); - -/* Event interface flags */ -#define IIO_BUSY_BIT_POS 1 - -#ifdef CONFIG_IIO_BUFFER -struct poll_table_struct; - -unsigned int iio_buffer_poll(struct file *filp, - struct poll_table_struct *wait); -ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, - size_t n, loff_t *f_ps); - - -#define iio_buffer_poll_addr (&iio_buffer_poll) -#define iio_buffer_read_first_n_outer_addr (&iio_buffer_read_first_n_outer) - -#else - -#define iio_buffer_poll_addr NULL -#define iio_buffer_read_first_n_outer_addr NULL - -#endif - -#endif diff --git a/drivers/staging/iio/iio_core_trigger.h b/drivers/staging/iio/iio_core_trigger.h deleted file mode 100644 index 6f7c56fcbe7..00000000000 --- a/drivers/staging/iio/iio_core_trigger.h +++ /dev/null @@ -1,46 +0,0 @@ - -/* The industrial I/O core, trigger consumer handling functions - * - * Copyright (c) 2008 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -#ifdef CONFIG_IIO_TRIGGER -/** - * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers - * @indio_dev: iio_dev associated with the device that will consume the trigger - **/ -void iio_device_register_trigger_consumer(struct iio_dev *indio_dev); - -/** - * iio_device_unregister_trigger_consumer() - reverse the registration process - * @indio_dev: iio_dev associated with the device that consumed the trigger - **/ -void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev); - -#else - -/** - * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers - * @indio_dev: iio_dev associated with the device that will consume the trigger - **/ -static int iio_device_register_trigger_consumer(struct iio_dev *indio_dev) -{ - return 0; -}; - -/** - * iio_device_unregister_trigger_consumer() - reverse the registration process - * @indio_dev: iio_dev associated with the device that consumed the trigger - **/ -static void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev) -{ -}; - -#endif /* CONFIG_TRIGGER_CONSUMER */ - - - diff --git a/drivers/staging/iio/iio_dummy_evgen.c b/drivers/staging/iio/iio_dummy_evgen.c index cdbf289bfe2..132d278c501 100644 --- a/drivers/staging/iio/iio_dummy_evgen.c +++ b/drivers/staging/iio/iio_dummy_evgen.c @@ -22,8 +22,8 @@ #include <linux/sysfs.h> #include "iio_dummy_evgen.h" -#include "iio.h" -#include "sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> /* Fiddly bit of faking and irq without hardware */ #define IIO_EVENTGEN_NO 10 @@ -32,7 +32,7 @@ * @chip: irq chip we are faking * @base: base of irq range * @enabled: mask of which irqs are enabled - * @inuse: mask of which irqs actually have anyone connected + * @inuse: mask of which irqs are connected * @lock: protect the evgen state */ struct iio_dummy_eventgen { @@ -108,7 +108,7 @@ int iio_dummy_evgen_get_irq(void) mutex_lock(&iio_evgen->lock); for (i = 0; i < IIO_EVENTGEN_NO; i++) - if (iio_evgen->inuse[i] == false) { + if (!iio_evgen->inuse[i]) { ret = iio_evgen->base + i; iio_evgen->inuse[i] = true; break; @@ -216,6 +216,6 @@ static __exit void iio_dummy_evgen_exit(void) } module_exit(iio_dummy_evgen_exit); -MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); +MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); MODULE_DESCRIPTION("IIO dummy driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c index e3a94572bb4..fd334a03a49 100644 --- a/drivers/staging/iio/iio_simple_dummy.c +++ b/drivers/staging/iio/iio_simple_dummy.c @@ -19,15 +19,15 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include "iio.h" -#include "sysfs.h" -#include "events.h" -#include "buffer.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/events.h> +#include <linux/iio/buffer.h> #include "iio_simple_dummy.h" /* * A few elements needed to fake a bus for this driver - * Note instances parmeter controls how many of these + * Note instances parameter controls how many of these * dummy devices are registered. */ static unsigned instances = 1; @@ -54,16 +54,30 @@ struct iio_dummy_accel_calibscale { static const struct iio_dummy_accel_calibscale dummy_scales[] = { { 0, 100, 0x8 }, /* 0.000100 */ { 0, 133, 0x7 }, /* 0.000133 */ - { 733, 13, 0x9 }, /* 733.00013 */ + { 733, 13, 0x9 }, /* 733.000013 */ }; +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS + +/* + * simple event - triggered when value rises above + * a threshold + */ +static const struct iio_event_spec iio_dummy_event = { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), +}; + +#endif + /* * iio_dummy_channels - Description of available channels * * This array of structures tells the IIO core about what the device * actually provides for a given channel. */ -static struct iio_chan_spec iio_dummy_channels[] = { +static const struct iio_chan_spec iio_dummy_channels[] = { /* indexed ADC channel in_voltage0_raw etc */ { .type = IIO_VOLTAGE, @@ -71,19 +85,30 @@ static struct iio_chan_spec iio_dummy_channels[] = { .indexed = 1, .channel = 0, /* What other information is available? */ - .info_mask = + .info_mask_separate = + /* + * in_voltage0_raw + * Raw (unscaled no bias removal etc) measurement + * from the device. + */ + BIT(IIO_CHAN_INFO_RAW) | /* * in_voltage0_offset * Offset for userspace to apply prior to scale * when converting to standard units (microvolts) */ - IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | + BIT(IIO_CHAN_INFO_OFFSET) | /* * in_voltage0_scale * Multipler for userspace to apply post offset * when converting to standard units (microvolts) */ - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + BIT(IIO_CHAN_INFO_SCALE), + /* + * sampling_frequency + * The frequency in Hz at which the channels are sampled + */ + .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), /* The ordering of elements in the buffer via an enum */ .scan_index = voltage0, .scan_type = { /* Description of storage in buffer */ @@ -93,12 +118,8 @@ static struct iio_chan_spec iio_dummy_channels[] = { .shift = 0, /* zero shift */ }, #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS - /* - * simple event - triggered when value rises above - * a threshold - */ - .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), + .event_spec = &iio_dummy_event, + .num_event_specs = 1, #endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ }, /* Differential ADC channel in_voltage1-voltage2_raw etc*/ @@ -112,13 +133,22 @@ static struct iio_chan_spec iio_dummy_channels[] = { .indexed = 1, .channel = 1, .channel2 = 2, - .info_mask = + /* + * in_voltage1-voltage2_raw + * Raw (unscaled no bias removal etc) measurement + * from the device. + */ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), /* * in_voltage-voltage_scale * Shared version of scale - shared by differential * input channels of type IIO_VOLTAGE. */ - IIO_CHAN_INFO_SCALE_SHARED_BIT, + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + /* + * sampling_frequency + * The frequency in Hz at which the channels are sampled + */ .scan_index = diffvoltage1m2, .scan_type = { /* Description of storage in buffer */ .sign = 's', /* signed */ @@ -134,8 +164,9 @@ static struct iio_chan_spec iio_dummy_channels[] = { .indexed = 1, .channel = 3, .channel2 = 4, - .info_mask = - IIO_CHAN_INFO_SCALE_SHARED_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), .scan_index = diffvoltage3m4, .scan_type = { .sign = 's', @@ -153,18 +184,20 @@ static struct iio_chan_spec iio_dummy_channels[] = { .modified = 1, /* Channel 2 is use for modifiers */ .channel2 = IIO_MOD_X, - .info_mask = + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | /* - * Internal bias correction value. Applied + * Internal bias and gain correction values. Applied * by the hardware or driver prior to userspace * seeing the readings. Typically part of hardware * calibration. */ - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, + BIT(IIO_CHAN_INFO_CALIBSCALE) | + BIT(IIO_CHAN_INFO_CALIBBIAS), + .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), .scan_index = accelx, .scan_type = { /* Description of storage in buffer */ .sign = 's', /* signed */ - .realbits = 16, /* 12 bits */ + .realbits = 16, /* 16 bits */ .storagebits = 16, /* 16 bits used for storage */ .shift = 0, /* zero shift */ }, @@ -177,6 +210,7 @@ static struct iio_chan_spec iio_dummy_channels[] = { /* DAC channel out_voltage0_raw */ { .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .output = 1, .indexed = 1, .channel = 0, @@ -189,8 +223,8 @@ static struct iio_chan_spec iio_dummy_channels[] = { * @chan: the channel whose data is to be read * @val: first element of returned value (typically INT) * @val2: second element of returned value (typically MICRO) - * @mask: what we actually want to read. 0 is the channel, everything else - * is as per the info_mask in iio_chan_spec. + * @mask: what we actually want to read as per the info_mask_* + * in iio_chan_spec. */ static int iio_dummy_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, @@ -203,7 +237,7 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev, mutex_lock(&st->lock); switch (mask) { - case 0: /* magic value - channel value read */ + case IIO_CHAN_INFO_RAW: /* magic value - channel value read */ switch (chan->type) { case IIO_VOLTAGE: if (chan->output) { @@ -259,6 +293,11 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev, *val2 = st->accel_calibscale->val2; ret = IIO_VAL_INT_PLUS_MICRO; break; + case IIO_CHAN_INFO_SAMP_FREQ: + *val = 3; + *val2 = 33; + ret = IIO_VAL_INT_PLUS_NANO; + break; default: break; } @@ -269,11 +308,11 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev, /** * iio_dummy_write_raw() - data write function. * @indio_dev: the struct iio_dev associated with this device instance - * @chan: the channel whose data is to be read - * @val: first element of returned value (typically INT) - * @val2: second element of returned value (typically MICRO) - * @mask: what we actually want to read. 0 is the channel, everything else - * is as per the info_mask in iio_chan_spec. + * @chan: the channel whose data is to be written + * @val: first element of value to set (typically INT) + * @val2: second element of value to set (typically MICRO) + * @mask: what we actually want to write as per the info_mask_* + * in iio_chan_spec. * * Note that all raw writes are assumed IIO_VAL_INT and info mask elements * are assumed to be IIO_INT_PLUS_MICRO unless the callback write_raw_get_fmt @@ -290,7 +329,7 @@ static int iio_dummy_write_raw(struct iio_dev *indio_dev, struct iio_dummy_state *st = iio_priv(indio_dev); switch (mask) { - case 0: + case IIO_CHAN_INFO_RAW: if (chan->output == 0) return -EINVAL; @@ -299,7 +338,7 @@ static int iio_dummy_write_raw(struct iio_dev *indio_dev, st->dac_val = val; mutex_unlock(&st->lock); return 0; - case IIO_CHAN_INFO_CALIBBIAS: + case IIO_CHAN_INFO_CALIBSCALE: mutex_lock(&st->lock); /* Compare against table - hard matching here */ for (i = 0; i < ARRAY_SIZE(dummy_scales); i++) @@ -312,6 +351,12 @@ static int iio_dummy_write_raw(struct iio_dev *indio_dev, st->accel_calibscale = &dummy_scales[i]; mutex_unlock(&st->lock); return ret; + case IIO_CHAN_INFO_CALIBBIAS: + mutex_lock(&st->lock); + st->accel_calibbias = val; + mutex_unlock(&st->lock); + return 0; + default: return -EINVAL; } @@ -363,7 +408,7 @@ static int iio_dummy_init_device(struct iio_dev *indio_dev) * const struct i2c_device_id *id) * SPI: iio_dummy_probe(struct spi_device *spi) */ -static int __devinit iio_dummy_probe(int index) +static int iio_dummy_probe(int index) { int ret; struct iio_dev *indio_dev; @@ -377,7 +422,7 @@ static int __devinit iio_dummy_probe(int index) * It also has a region (accessed by iio_priv() * for chip specific state information. */ - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -430,34 +475,27 @@ static int __devinit iio_dummy_probe(int index) if (ret < 0) goto error_free_device; - /* Configure buffered capture support. */ - ret = iio_simple_dummy_configure_buffer(indio_dev); - if (ret < 0) - goto error_unregister_events; - /* - * Register the channels with the buffer, but avoid the output - * channel being registered by reducing the number of channels by 1. + * Configure buffered capture support and register the channels with the + * buffer, but avoid the output channel being registered by reducing the + * number of channels by 1. */ - ret = iio_buffer_register(indio_dev, iio_dummy_channels, 5); + ret = iio_simple_dummy_configure_buffer(indio_dev, + iio_dummy_channels, 5); if (ret < 0) - goto error_unconfigure_buffer; + goto error_unregister_events; ret = iio_device_register(indio_dev); if (ret < 0) - goto error_unregister_buffer; + goto error_unconfigure_buffer; return 0; -error_unregister_buffer: - iio_buffer_unregister(indio_dev); error_unconfigure_buffer: iio_simple_dummy_unconfigure_buffer(indio_dev); error_unregister_events: iio_simple_dummy_events_unregister(indio_dev); error_free_device: - /* Note free device should only be called, before registration - * has succeeded. */ - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -486,7 +524,6 @@ static int iio_dummy_remove(int index) /* Device specific code to power down etc */ /* Buffered capture related cleanup */ - iio_buffer_unregister(indio_dev); iio_simple_dummy_unconfigure_buffer(indio_dev); ret = iio_simple_dummy_events_unregister(indio_dev); @@ -494,7 +531,7 @@ static int iio_dummy_remove(int index) goto error_ret; /* Free all structures */ - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; @@ -517,6 +554,7 @@ static __init int iio_dummy_init(void) instances = 1; return -EINVAL; } + /* Fake a bus */ iio_dummy_devs = kcalloc(instances, sizeof(*iio_dummy_devs), GFP_KERNEL); @@ -545,6 +583,6 @@ static __exit void iio_dummy_exit(void) } module_exit(iio_dummy_exit); -MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); +MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); MODULE_DESCRIPTION("IIO dummy driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/iio_simple_dummy.h b/drivers/staging/iio/iio_simple_dummy.h index 53975d916fc..b126196cdf3 100644 --- a/drivers/staging/iio/iio_simple_dummy.h +++ b/drivers/staging/iio/iio_simple_dummy.h @@ -45,19 +45,29 @@ struct iio_dummy_state { struct iio_dev; int iio_simple_dummy_read_event_config(struct iio_dev *indio_dev, - u64 event_code); + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir); int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, - u64 event_code, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, int state); int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev, - u64 event_code, - int *val); + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, int *val, + int *val2); int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev, - u64 event_code, - int val); + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, int val, + int val2); int iio_simple_dummy_events_register(struct iio_dev *indio_dev); int iio_simple_dummy_events_unregister(struct iio_dev *indio_dev); @@ -95,10 +105,12 @@ enum iio_simple_dummy_scan_elements { }; #ifdef CONFIG_IIO_SIMPLE_DUMMY_BUFFER -int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev); +int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, + const struct iio_chan_spec *channels, unsigned int num_channels); void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev); #else -static inline int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) +static inline int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, + const struct iio_chan_spec *channels, unsigned int num_channels) { return 0; }; diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c index d6a1c0e82a5..46c134b2a5d 100644 --- a/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -18,9 +18,9 @@ #include <linux/irq.h> #include <linux/bitmap.h> -#include "iio.h" -#include "trigger_consumer.h" -#include "kfifo_buf.h" +#include <linux/iio/iio.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/kfifo_buf.h> #include "iio_simple_dummy.h" @@ -37,7 +37,7 @@ static const s16 fakedata[] = { * @irq: the interrupt number * @p: private data - always a pointer to the poll func. * - * This is the guts of buffered capture. On a trigger event occuring, + * This is the guts of buffered capture. On a trigger event occurring, * if the pollfunc is attached then this handler is called as a threaded * interrupt (and hence may sleep). It is responsible for grabbing data * from the device and pushing it into the associated buffer. @@ -46,16 +46,12 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) { struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; - struct iio_buffer *buffer = indio_dev->buffer; int len = 0; - /* - * The datasize is obtained from the buffer. It was stored when - * the preenable setup function was called. - */ - size_t datasize = buffer->access->get_bytes_per_datum(buffer); - u16 *data = kmalloc(datasize, GFP_KERNEL); + u16 *data; + + data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); if (data == NULL) - return -ENOMEM; + goto done; if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) { /* @@ -64,37 +60,34 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) * up a fast read. The capture will consist of all of them. * Hence we just call the grab data function and fill the * buffer without processing. - * sofware scans: can be considered to be random access + * software scans: can be considered to be random access * so efficient reading is just a case of minimal bus * transactions. * software culled hardware scans: * occasionally a driver may process the nearest hardware * scan to avoid storing elements that are not desired. This - * is the fidliest option by far. - * Here lets pretend we have random access. And the values are + * is the fiddliest option by far. + * Here let's pretend we have random access. And the values are * in the constant table fakedata. */ int i, j; for (i = 0, j = 0; i < bitmap_weight(indio_dev->active_scan_mask, indio_dev->masklength); - i++) { - j = find_next_bit(buffer->scan_mask, - indio_dev->masklength, j + 1); - /* random access read form the 'device' */ + i++, j++) { + j = find_next_bit(indio_dev->active_scan_mask, + indio_dev->masklength, j); + /* random access read from the 'device' */ data[i] = fakedata[j]; len += 2; } } - /* Store a timestampe at an 8 byte boundary */ - if (buffer->scan_timestamp) - *(s64 *)(((phys_addr_t)data + len - + sizeof(s64) - 1) & ~(sizeof(s64) - 1)) - = iio_get_time_ns(); - buffer->access->store_to(buffer, (u8 *)data, pf->timestamp); + + iio_push_to_buffers_with_timestamp(indio_dev, data, iio_get_time_ns()); kfree(data); +done: /* * Tell the core we are done with this trigger and ready for the * next one. @@ -106,14 +99,6 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) static const struct iio_buffer_setup_ops iio_simple_dummy_buffer_setup_ops = { /* - * iio_sw_buffer_preenable: - * Generic function for equal sized ring elements + 64 bit timestamp - * Assumes that any combination of channels can be enabled. - * Typically replaced to implement restrictions on what combinations - * can be captured (hardware scan modes). - */ - .preenable = &iio_sw_buffer_preenable, - /* * iio_triggered_buffer_postenable: * Generic function that simply attaches the pollfunc to the trigger. * Replace this to mess with hardware state before we attach the @@ -129,7 +114,8 @@ static const struct iio_buffer_setup_ops iio_simple_dummy_buffer_setup_ops = { .predisable = &iio_triggered_buffer_predisable, }; -int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) +int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, + const struct iio_chan_spec *channels, unsigned int num_channels) { int ret; struct iio_buffer *buffer; @@ -141,9 +127,7 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) goto error_ret; } - indio_dev->buffer = buffer; - /* Tell the core how to access the buffer */ - buffer->access = &kfifo_access_funcs; + iio_device_attach_buffer(indio_dev, buffer); /* Enable timestamps by default */ buffer->scan_timestamp = true; @@ -160,7 +144,7 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) * occurs, this function is run. Typically this grabs data * from the device. * - * NULL for the top half. This is normally implemented only if we + * NULL for the bottom half. This is normally implemented only if we * either want to ping a capture now pin (no sleeping) or grab * a timestamp as close as possible to a data ready trigger firing. * @@ -187,8 +171,15 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) * driven by a trigger. */ indio_dev->modes |= INDIO_BUFFER_TRIGGERED; + + ret = iio_buffer_register(indio_dev, channels, num_channels); + if (ret) + goto error_dealloc_pollfunc; + return 0; +error_dealloc_pollfunc: + iio_dealloc_pollfunc(indio_dev->pollfunc); error_free_buffer: iio_kfifo_free(indio_dev->buffer); error_ret: @@ -202,6 +193,7 @@ error_ret: */ void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev) { + iio_buffer_unregister(indio_dev); iio_dealloc_pollfunc(indio_dev->pollfunc); iio_kfifo_free(indio_dev->buffer); } diff --git a/drivers/staging/iio/iio_simple_dummy_events.c b/drivers/staging/iio/iio_simple_dummy_events.c index 449c7a5ece8..812ebd05a7f 100644 --- a/drivers/staging/iio/iio_simple_dummy_events.c +++ b/drivers/staging/iio/iio_simple_dummy_events.c @@ -12,9 +12,9 @@ #include <linux/interrupt.h> #include <linux/irq.h> -#include "iio.h" -#include "sysfs.h" -#include "events.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/events.h> #include "iio_simple_dummy.h" /* Evgen 'fakes' interrupt events for this example */ @@ -23,13 +23,17 @@ /** * iio_simple_dummy_read_event_config() - is event enabled? * @indio_dev: the device instance data - * @event_code: event code of the event being queried + * @chan: channel for the event whose state is being queried + * @type: type of the event whose state is being queried + * @dir: direction of the vent whose state is being queried * * This function would normally query the relevant registers or a cache to * discover if the event generation is enabled on the device. */ int iio_simple_dummy_read_event_config(struct iio_dev *indio_dev, - u64 event_code) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) { struct iio_dummy_state *st = iio_priv(indio_dev); @@ -39,7 +43,9 @@ int iio_simple_dummy_read_event_config(struct iio_dev *indio_dev, /** * iio_simple_dummy_write_event_config() - set whether event is enabled * @indio_dev: the device instance data - * @event_code: event code of event being enabled/disabled + * @chan: channel for the event whose state is being set + * @type: type of the event whose state is being set + * @dir: direction of the vent whose state is being set * @state: whether to enable or disable the device. * * This function would normally set the relevant registers on the devices @@ -47,7 +53,9 @@ int iio_simple_dummy_read_event_config(struct iio_dev *indio_dev, * value. */ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, - u64 event_code, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, int state) { struct iio_dummy_state *st = iio_priv(indio_dev); @@ -56,12 +64,11 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, * Deliberately over the top code splitting to illustrate * how this is done when multiple events exist. */ - switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { + switch (chan->type) { case IIO_VOLTAGE: - switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) { + switch (type) { case IIO_EV_TYPE_THRESH: - if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_RISING) + if (dir == IIO_EV_DIR_RISING) st->event_en = state; else return -EINVAL; @@ -79,7 +86,10 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, /** * iio_simple_dummy_read_event_value() - get value associated with event * @indio_dev: device instance specific data - * @event_code: event code for the event whose value is being queried + * @chan: channel for the event whose value is being read + * @type: type of the event whose value is being read + * @dir: direction of the vent whose value is being read + * @info: info type of the event whose value is being read * @val: value for the event code. * * Many devices provide a large set of events of which only a subset may @@ -89,25 +99,34 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, * the enabled event is changed. */ int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev, - u64 event_code, - int *val) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) { struct iio_dummy_state *st = iio_priv(indio_dev); *val = st->event_val; - return 0; + return IIO_VAL_INT; } /** * iio_simple_dummy_write_event_value() - set value associate with event * @indio_dev: device instance specific data - * @event_code: event code for the event whose value is being set + * @chan: channel for the event whose value is being set + * @type: type of the event whose value is being set + * @dir: direction of the vent whose value is being set + * @info: info type of the event whose value is being set * @val: the value to be set. */ int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev, - u64 event_code, - int val) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) { struct iio_dummy_state *st = iio_priv(indio_dev); @@ -122,7 +141,7 @@ int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev, * @private: pointer to device instance state. * * This handler is responsible for querying the device to find out what - * event occured and for then pushing that event towards userspace. + * event occurred and for then pushing that event towards userspace. * Here only one event occurs so we push that directly on with locally * grabbed timestamp. */ diff --git a/drivers/staging/iio/impedance-analyzer/Kconfig b/drivers/staging/iio/impedance-analyzer/Kconfig index ad0ff765e4b..dd97b6bb3fd 100644 --- a/drivers/staging/iio/impedance-analyzer/Kconfig +++ b/drivers/staging/iio/impedance-analyzer/Kconfig @@ -7,7 +7,7 @@ config AD5933 tristate "Analog Devices AD5933, AD5934 driver" depends on I2C select IIO_BUFFER - select IIO_SW_RING + select IIO_KFIFO_BUF help Say yes here to build support for Analog Devices Impedance Converter, Network Analyzer, AD5933/4, provides direct access via sysfs. diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 9a2ca55625f..2b96665da8a 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -19,10 +19,10 @@ #include <linux/module.h> #include <asm/div64.h> -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" -#include "../ring_sw.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> +#include <linux/iio/kfifo_buf.h> #include "ad5933.h" @@ -108,16 +108,47 @@ static struct ad5933_platform_data ad5933_default_pdata = { .vref_mv = 3300, }; -static struct iio_chan_spec ad5933_channels[] = { - IIO_CHAN(IIO_TEMP, 0, 1, 1, NULL, 0, 0, 0, - 0, AD5933_REG_TEMP_DATA, IIO_ST('s', 14, 16, 0), 0), - /* Ring Channels */ - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "real_raw", 0, 0, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - AD5933_REG_REAL_DATA, 0, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "imag_raw", 0, 0, - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - AD5933_REG_IMAG_DATA, 1, IIO_ST('s', 16, 16, 0), 0), +static const struct iio_chan_spec ad5933_channels[] = { + { + .type = IIO_TEMP, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .address = AD5933_REG_TEMP_DATA, + .scan_type = { + .sign = 's', + .realbits = 14, + .storagebits = 16, + }, + }, { /* Ring Channels */ + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .extend_name = "real_raw", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .address = AD5933_REG_REAL_DATA, + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + }, + }, { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .extend_name = "imag_raw", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .address = AD5933_REG_IMAG_DATA, + .scan_index = 1, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + }, + }, }; static int ad5933_i2c_write(struct i2c_client *client, @@ -260,7 +291,7 @@ static ssize_t ad5933_show_frequency(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5933_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; @@ -289,13 +320,13 @@ static ssize_t ad5933_store_frequency(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5933_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - long val; + unsigned long val; int ret; - ret = strict_strtoul(buf, 10, &val); + ret = kstrtoul(buf, 10, &val); if (ret) return ret; @@ -323,7 +354,7 @@ static ssize_t ad5933_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5933_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret = 0, len = 0; @@ -366,15 +397,15 @@ static ssize_t ad5933_store(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5933_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - long val; + u16 val; int i, ret = 0; unsigned short dat; if (this_attr->address != AD5933_IN_PGA_GAIN) { - ret = strict_strtol(buf, 10, &val); + ret = kstrtou16(buf, 10, &val); if (ret) return ret; } @@ -403,7 +434,7 @@ static ssize_t ad5933_store(struct device *dev, ret = ad5933_cmd(st, 0); break; case AD5933_OUT_SETTLING_CYCLES: - val = clamp(val, 0L, 0x7FFL); + val = clamp(val, (u16)0, (u16)0x7FF); st->settling_cycles = val; /* 2x, 4x handling, see datasheet */ @@ -417,7 +448,7 @@ static ssize_t ad5933_store(struct device *dev, AD5933_REG_SETTLING_CYCLES, 2, (u8 *)&dat); break; case AD5933_FREQ_POINTS: - val = clamp(val, 0L, 511L); + val = clamp(val, (u16)0, (u16)511); st->freq_points = val; dat = cpu_to_be16(val); @@ -495,7 +526,8 @@ static int ad5933_read_raw(struct iio_dev *indio_dev, mutex_lock(&indio_dev->mlock); switch (m) { - case 0: + case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_PROCESSED: if (iio_buffer_enabled(indio_dev)) { ret = -EBUSY; goto out; @@ -537,20 +569,11 @@ static const struct iio_info ad5933_info = { static int ad5933_ring_preenable(struct iio_dev *indio_dev) { struct ad5933_state *st = iio_priv(indio_dev); - size_t d_size; int ret; if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) return -EINVAL; - d_size = bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength) * - ad5933_channels[1].scan_type.storagebits / 8; - - if (indio_dev->buffer->access->set_bytes_per_datum) - indio_dev->buffer->access-> - set_bytes_per_datum(indio_dev->buffer, d_size); - ret = ad5933_reset(st); if (ret < 0) return ret; @@ -603,12 +626,13 @@ static const struct iio_buffer_setup_ops ad5933_ring_setup_ops = { static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev) { - indio_dev->buffer = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->buffer) + struct iio_buffer *buffer; + + buffer = iio_kfifo_allocate(indio_dev); + if (!buffer) return -ENOMEM; - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; + iio_device_attach_buffer(indio_dev, buffer); /* Ring buffer functions - here trigger setup related */ indio_dev->setup_ops = &ad5933_ring_setup_ops; @@ -623,7 +647,6 @@ static void ad5933_work(struct work_struct *work) struct ad5933_state *st = container_of(work, struct ad5933_state, work.work); struct iio_dev *indio_dev = i2c_get_clientdata(st->client); - struct iio_buffer *ring = indio_dev->buffer; signed short buf[2]; unsigned char status; @@ -653,8 +676,7 @@ static void ad5933_work(struct work_struct *work) } else { buf[0] = be16_to_cpu(buf[0]); } - /* save datum to the ring */ - ring->access->store_to(ring, (u8 *)buf, iio_get_time_ns()); + iio_push_to_buffers(indio_dev, buf); } else { /* no data available - try again later */ schedule_delayed_work(&st->work, st->poll_time_jiffies); @@ -675,13 +697,15 @@ static void ad5933_work(struct work_struct *work) mutex_unlock(&indio_dev->mlock); } -static int __devinit ad5933_probe(struct i2c_client *client, +static int ad5933_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret, voltage_uv = 0; struct ad5933_platform_data *pdata = client->dev.platform_data; struct ad5933_state *st; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); + struct iio_dev *indio_dev; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; @@ -694,11 +718,11 @@ static int __devinit ad5933_probe(struct i2c_client *client, else st->pdata = pdata; - st->reg = regulator_get(&client->dev, "vcc"); + st->reg = devm_regulator_get(&client->dev, "vcc"); if (!IS_ERR(st->reg)) { ret = regulator_enable(st->reg); if (ret) - goto error_put_reg; + return ret; voltage_uv = regulator_get_voltage(st->reg); } @@ -752,32 +776,24 @@ static int __devinit ad5933_probe(struct i2c_client *client, error_uninitialize_ring: iio_buffer_unregister(indio_dev); error_unreg_ring: - iio_sw_rb_free(indio_dev->buffer); + iio_kfifo_free(indio_dev->buffer); error_disable_reg: if (!IS_ERR(st->reg)) regulator_disable(st->reg); -error_put_reg: - if (!IS_ERR(st->reg)) - regulator_put(st->reg); - - iio_free_device(indio_dev); return ret; } -static __devexit int ad5933_remove(struct i2c_client *client) +static int ad5933_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); struct ad5933_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); iio_buffer_unregister(indio_dev); - iio_sw_rb_free(indio_dev->buffer); - if (!IS_ERR(st->reg)) { + iio_kfifo_free(indio_dev->buffer); + if (!IS_ERR(st->reg)) regulator_disable(st->reg); - regulator_put(st->reg); - } - iio_free_device(indio_dev); return 0; } @@ -795,7 +811,7 @@ static struct i2c_driver ad5933_driver = { .name = "ad5933", }, .probe = ad5933_probe, - .remove = __devexit_p(ad5933_remove), + .remove = ad5933_remove, .id_table = ad5933_id, }; module_i2c_driver(ad5933_driver); diff --git a/drivers/staging/iio/imu/Kconfig b/drivers/staging/iio/imu/Kconfig deleted file mode 100644 index 2c2f47de263..00000000000 --- a/drivers/staging/iio/imu/Kconfig +++ /dev/null @@ -1,17 +0,0 @@ -# -# IIO imu drivers configuration -# -menu "Inertial measurement units" - -config ADIS16400 - tristate "Analog Devices ADIS16400 and similar IMU SPI driver" - depends on SPI - select IIO_SW_RING if IIO_BUFFER - select IIO_TRIGGER if IIO_BUFFER - help - Say yes here to build support for Analog Devices adis16300, adis16344, - adis16350, adis16354, adis16355, adis16360, adis16362, adis16364, - adis16365, adis16400 and adis16405 triaxial inertial sensors - (adis16400 series also have magnetometers). - -endmenu diff --git a/drivers/staging/iio/imu/Makefile b/drivers/staging/iio/imu/Makefile deleted file mode 100644 index 3400a13d152..00000000000 --- a/drivers/staging/iio/imu/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# Makefile for Inertial Measurement Units -# - -adis16400-y := adis16400_core.o -adis16400-$(CONFIG_IIO_BUFFER) += adis16400_ring.o adis16400_trigger.o -obj-$(CONFIG_ADIS16400) += adis16400.o diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h deleted file mode 100644 index 83d133efaac..00000000000 --- a/drivers/staging/iio/imu/adis16400.h +++ /dev/null @@ -1,230 +0,0 @@ -/* - * adis16400.h support Analog Devices ADIS16400 - * 3d 18g accelerometers, - * 3d gyroscopes, - * 3d 2.5gauss magnetometers via SPI - * - * Copyright (c) 2009 Manuel Stahl <manuel.stahl@iis.fraunhofer.de> - * Copyright (c) 2007 Jonathan Cameron <jic23@cam.ac.uk> - * - * Loosely based upon lis3l02dq.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef SPI_ADIS16400_H_ -#define SPI_ADIS16400_H_ - -#define ADIS16400_STARTUP_DELAY 290 /* ms */ -#define ADIS16400_MTEST_DELAY 90 /* ms */ - -#define ADIS16400_READ_REG(a) a -#define ADIS16400_WRITE_REG(a) ((a) | 0x80) - -#define ADIS16400_FLASH_CNT 0x00 /* Flash memory write count */ -#define ADIS16400_SUPPLY_OUT 0x02 /* Power supply measurement */ -#define ADIS16400_XGYRO_OUT 0x04 /* X-axis gyroscope output */ -#define ADIS16400_YGYRO_OUT 0x06 /* Y-axis gyroscope output */ -#define ADIS16400_ZGYRO_OUT 0x08 /* Z-axis gyroscope output */ -#define ADIS16400_XACCL_OUT 0x0A /* X-axis accelerometer output */ -#define ADIS16400_YACCL_OUT 0x0C /* Y-axis accelerometer output */ -#define ADIS16400_ZACCL_OUT 0x0E /* Z-axis accelerometer output */ -#define ADIS16400_XMAGN_OUT 0x10 /* X-axis magnetometer measurement */ -#define ADIS16400_YMAGN_OUT 0x12 /* Y-axis magnetometer measurement */ -#define ADIS16400_ZMAGN_OUT 0x14 /* Z-axis magnetometer measurement */ -#define ADIS16400_TEMP_OUT 0x16 /* Temperature output */ -#define ADIS16400_AUX_ADC 0x18 /* Auxiliary ADC measurement */ - -#define ADIS16350_XTEMP_OUT 0x10 /* X-axis gyroscope temperature measurement */ -#define ADIS16350_YTEMP_OUT 0x12 /* Y-axis gyroscope temperature measurement */ -#define ADIS16350_ZTEMP_OUT 0x14 /* Z-axis gyroscope temperature measurement */ - -#define ADIS16300_PITCH_OUT 0x12 /* X axis inclinometer output measurement */ -#define ADIS16300_ROLL_OUT 0x12 /* Y axis inclinometer output measurement */ - -/* Calibration parameters */ -#define ADIS16400_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */ -#define ADIS16400_YGYRO_OFF 0x1C /* Y-axis gyroscope bias offset factor */ -#define ADIS16400_ZGYRO_OFF 0x1E /* Z-axis gyroscope bias offset factor */ -#define ADIS16400_XACCL_OFF 0x20 /* X-axis acceleration bias offset factor */ -#define ADIS16400_YACCL_OFF 0x22 /* Y-axis acceleration bias offset factor */ -#define ADIS16400_ZACCL_OFF 0x24 /* Z-axis acceleration bias offset factor */ -#define ADIS16400_XMAGN_HIF 0x26 /* X-axis magnetometer, hard-iron factor */ -#define ADIS16400_YMAGN_HIF 0x28 /* Y-axis magnetometer, hard-iron factor */ -#define ADIS16400_ZMAGN_HIF 0x2A /* Z-axis magnetometer, hard-iron factor */ -#define ADIS16400_XMAGN_SIF 0x2C /* X-axis magnetometer, soft-iron factor */ -#define ADIS16400_YMAGN_SIF 0x2E /* Y-axis magnetometer, soft-iron factor */ -#define ADIS16400_ZMAGN_SIF 0x30 /* Z-axis magnetometer, soft-iron factor */ - -#define ADIS16400_GPIO_CTRL 0x32 /* Auxiliary digital input/output control */ -#define ADIS16400_MSC_CTRL 0x34 /* Miscellaneous control */ -#define ADIS16400_SMPL_PRD 0x36 /* Internal sample period (rate) control */ -#define ADIS16400_SENS_AVG 0x38 /* Dynamic range and digital filter control */ -#define ADIS16400_SLP_CNT 0x3A /* Sleep mode control */ -#define ADIS16400_DIAG_STAT 0x3C /* System status */ - -/* Alarm functions */ -#define ADIS16400_GLOB_CMD 0x3E /* System command */ -#define ADIS16400_ALM_MAG1 0x40 /* Alarm 1 amplitude threshold */ -#define ADIS16400_ALM_MAG2 0x42 /* Alarm 2 amplitude threshold */ -#define ADIS16400_ALM_SMPL1 0x44 /* Alarm 1 sample size */ -#define ADIS16400_ALM_SMPL2 0x46 /* Alarm 2 sample size */ -#define ADIS16400_ALM_CTRL 0x48 /* Alarm control */ -#define ADIS16400_AUX_DAC 0x4A /* Auxiliary DAC data */ - -#define ADIS16400_PRODUCT_ID 0x56 /* Product identifier */ - -#define ADIS16400_ERROR_ACTIVE (1<<14) -#define ADIS16400_NEW_DATA (1<<14) - -/* MSC_CTRL */ -#define ADIS16400_MSC_CTRL_MEM_TEST (1<<11) -#define ADIS16400_MSC_CTRL_INT_SELF_TEST (1<<10) -#define ADIS16400_MSC_CTRL_NEG_SELF_TEST (1<<9) -#define ADIS16400_MSC_CTRL_POS_SELF_TEST (1<<8) -#define ADIS16400_MSC_CTRL_GYRO_BIAS (1<<7) -#define ADIS16400_MSC_CTRL_ACCL_ALIGN (1<<6) -#define ADIS16400_MSC_CTRL_DATA_RDY_EN (1<<2) -#define ADIS16400_MSC_CTRL_DATA_RDY_POL_HIGH (1<<1) -#define ADIS16400_MSC_CTRL_DATA_RDY_DIO2 (1<<0) - -/* SMPL_PRD */ -#define ADIS16400_SMPL_PRD_TIME_BASE (1<<7) -#define ADIS16400_SMPL_PRD_DIV_MASK 0x7F - -/* DIAG_STAT */ -#define ADIS16400_DIAG_STAT_ZACCL_FAIL (1<<15) -#define ADIS16400_DIAG_STAT_YACCL_FAIL (1<<14) -#define ADIS16400_DIAG_STAT_XACCL_FAIL (1<<13) -#define ADIS16400_DIAG_STAT_XGYRO_FAIL (1<<12) -#define ADIS16400_DIAG_STAT_YGYRO_FAIL (1<<11) -#define ADIS16400_DIAG_STAT_ZGYRO_FAIL (1<<10) -#define ADIS16400_DIAG_STAT_ALARM2 (1<<9) -#define ADIS16400_DIAG_STAT_ALARM1 (1<<8) -#define ADIS16400_DIAG_STAT_FLASH_CHK (1<<6) -#define ADIS16400_DIAG_STAT_SELF_TEST (1<<5) -#define ADIS16400_DIAG_STAT_OVERFLOW (1<<4) -#define ADIS16400_DIAG_STAT_SPI_FAIL (1<<3) -#define ADIS16400_DIAG_STAT_FLASH_UPT (1<<2) -#define ADIS16400_DIAG_STAT_POWER_HIGH (1<<1) -#define ADIS16400_DIAG_STAT_POWER_LOW (1<<0) - -/* GLOB_CMD */ -#define ADIS16400_GLOB_CMD_SW_RESET (1<<7) -#define ADIS16400_GLOB_CMD_P_AUTO_NULL (1<<4) -#define ADIS16400_GLOB_CMD_FLASH_UPD (1<<3) -#define ADIS16400_GLOB_CMD_DAC_LATCH (1<<2) -#define ADIS16400_GLOB_CMD_FAC_CALIB (1<<1) -#define ADIS16400_GLOB_CMD_AUTO_NULL (1<<0) - -/* SLP_CNT */ -#define ADIS16400_SLP_CNT_POWER_OFF (1<<8) - -#define ADIS16400_MAX_TX 24 -#define ADIS16400_MAX_RX 24 - -#define ADIS16400_SPI_SLOW (u32)(300 * 1000) -#define ADIS16400_SPI_BURST (u32)(1000 * 1000) -#define ADIS16400_SPI_FAST (u32)(2000 * 1000) - -#define ADIS16400_HAS_PROD_ID 1 -#define ADIS16400_NO_BURST 2 -struct adis16400_chip_info { - const struct iio_chan_spec *channels; - const int num_channels; - const int product_id; - const long flags; - unsigned int gyro_scale_micro; - unsigned int accel_scale_micro; - unsigned long default_scan_mask; -}; - -/** - * struct adis16400_state - device instance specific data - * @us: actual spi_device - * @trig: data ready trigger registered with iio - * @tx: transmit buffer - * @rx: receive buffer - * @buf_lock: mutex to protect tx and rx - * @filt_int: integer part of requested filter frequency - **/ -struct adis16400_state { - struct spi_device *us; - struct iio_trigger *trig; - struct mutex buf_lock; - struct adis16400_chip_info *variant; - int filt_int; - - u8 tx[ADIS16400_MAX_TX] ____cacheline_aligned; - u8 rx[ADIS16400_MAX_RX] ____cacheline_aligned; -}; - -int adis16400_set_irq(struct iio_dev *indio_dev, bool enable); - -/* At the moment triggers are only used for ring buffer - * filling. This may change! - */ - -#define ADIS16400_SCAN_SUPPLY 0 -#define ADIS16400_SCAN_GYRO_X 1 -#define ADIS16400_SCAN_GYRO_Y 2 -#define ADIS16400_SCAN_GYRO_Z 3 -#define ADIS16400_SCAN_ACC_X 4 -#define ADIS16400_SCAN_ACC_Y 5 -#define ADIS16400_SCAN_ACC_Z 6 -#define ADIS16400_SCAN_MAGN_X 7 -#define ADIS16350_SCAN_TEMP_X 7 -#define ADIS16400_SCAN_MAGN_Y 8 -#define ADIS16350_SCAN_TEMP_Y 8 -#define ADIS16400_SCAN_MAGN_Z 9 -#define ADIS16350_SCAN_TEMP_Z 9 -#define ADIS16400_SCAN_TEMP 10 -#define ADIS16350_SCAN_ADC_0 10 -#define ADIS16400_SCAN_ADC_0 11 -#define ADIS16300_SCAN_INCLI_X 12 -#define ADIS16300_SCAN_INCLI_Y 13 - -#ifdef CONFIG_IIO_BUFFER -void adis16400_remove_trigger(struct iio_dev *indio_dev); -int adis16400_probe_trigger(struct iio_dev *indio_dev); - -ssize_t adis16400_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf); - - -int adis16400_configure_ring(struct iio_dev *indio_dev); -void adis16400_unconfigure_ring(struct iio_dev *indio_dev); - -#else /* CONFIG_IIO_BUFFER */ - -static inline void adis16400_remove_trigger(struct iio_dev *indio_dev) -{ -} - -static inline int adis16400_probe_trigger(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline ssize_t -adis16400_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return 0; -} - -static int adis16400_configure_ring(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline void adis16400_unconfigure_ring(struct iio_dev *indio_dev) -{ -} - -#endif /* CONFIG_IIO_BUFFER */ -#endif /* SPI_ADIS16400_H_ */ diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c deleted file mode 100644 index e73ad7818d8..00000000000 --- a/drivers/staging/iio/imu/adis16400_core.c +++ /dev/null @@ -1,1238 +0,0 @@ -/* - * adis16400.c support Analog Devices ADIS16400/5 - * 3d 2g Linear Accelerometers, - * 3d Gyroscopes, - * 3d Magnetometers via SPI - * - * Copyright (c) 2009 Manuel Stahl <manuel.stahl@iis.fraunhofer.de> - * Copyright (c) 2007 Jonathan Cameron <jic23@cam.ac.uk> - * Copyright (c) 2011 Analog Devices Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/delay.h> -#include <linux/mutex.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/list.h> -#include <linux/module.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" -#include "adis16400.h" - -enum adis16400_chip_variant { - ADIS16300, - ADIS16334, - ADIS16350, - ADIS16360, - ADIS16362, - ADIS16364, - ADIS16365, - ADIS16400, -}; - -/** - * adis16400_spi_write_reg_8() - write single byte to a register - * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @reg_address: the address of the register to be written - * @val: the value to write - */ -static int adis16400_spi_write_reg_8(struct iio_dev *indio_dev, - u8 reg_address, - u8 val) -{ - int ret; - struct adis16400_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16400_WRITE_REG(reg_address); - st->tx[1] = val; - - ret = spi_write(st->us, st->tx, 2); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/** - * adis16400_spi_write_reg_16() - write 2 bytes to a pair of registers - * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @reg_address: the address of the lower of the two registers. Second register - * is assumed to have address one greater. - * @val: value to be written - * - * At the moment the spi framework doesn't allow global setting of cs_change. - * This means that use cannot be made of spi_write. - */ -static int adis16400_spi_write_reg_16(struct iio_dev *indio_dev, - u8 lower_reg_address, - u16 value) -{ - int ret; - struct spi_message msg; - struct adis16400_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - }, { - .tx_buf = st->tx + 2, - .bits_per_word = 8, - .len = 2, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16400_WRITE_REG(lower_reg_address); - st->tx[1] = value & 0xFF; - st->tx[2] = ADIS16400_WRITE_REG(lower_reg_address + 1); - st->tx[3] = (value >> 8) & 0xFF; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/** - * adis16400_spi_read_reg_16() - read 2 bytes from a 16-bit register - * @indio_dev: iio device - * @reg_address: the address of the lower of the two registers. Second register - * is assumed to have address one greater. - * @val: somewhere to pass back the value read - * - * At the moment the spi framework doesn't allow global setting of cs_change. - * This means that use cannot be made of spi_read. - **/ -static int adis16400_spi_read_reg_16(struct iio_dev *indio_dev, - u8 lower_reg_address, - u16 *val) -{ - struct spi_message msg; - struct adis16400_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - }, { - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 2, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16400_READ_REG(lower_reg_address); - st->tx[1] = 0; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - if (ret) { - dev_err(&st->us->dev, - "problem when reading 16 bit register 0x%02X", - lower_reg_address); - goto error_ret; - } - *val = (st->rx[0] << 8) | st->rx[1]; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -static int adis16400_get_freq(struct iio_dev *indio_dev) -{ - u16 t; - int sps, ret; - - ret = adis16400_spi_read_reg_16(indio_dev, ADIS16400_SMPL_PRD, &t); - if (ret < 0) - return ret; - sps = (t & ADIS16400_SMPL_PRD_TIME_BASE) ? 53 : 1638; - sps /= (t & ADIS16400_SMPL_PRD_DIV_MASK) + 1; - - return sps; -} - -static ssize_t adis16400_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - int ret, len = 0; - ret = adis16400_get_freq(indio_dev); - if (ret < 0) - return ret; - len = sprintf(buf, "%d SPS\n", ret); - return len; -} - -static const unsigned adis16400_3db_divisors[] = { - [0] = 2, /* Special case */ - [1] = 5, - [2] = 10, - [3] = 50, - [4] = 200, -}; - -static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val) -{ - int i, ret; - u16 val16; - for (i = ARRAY_SIZE(adis16400_3db_divisors) - 1; i >= 0; i--) - if (sps/adis16400_3db_divisors[i] > val) - break; - if (i == -1) - ret = -EINVAL; - else { - ret = adis16400_spi_read_reg_16(indio_dev, - ADIS16400_SENS_AVG, - &val16); - if (ret < 0) - goto error_ret; - - ret = adis16400_spi_write_reg_16(indio_dev, - ADIS16400_SENS_AVG, - (val16 & ~0x03) | i); - } -error_ret: - return ret; -} - -static ssize_t adis16400_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16400_state *st = iio_priv(indio_dev); - long val; - int ret; - u8 t; - - ret = strict_strtol(buf, 10, &val); - if (ret) - return ret; - - mutex_lock(&indio_dev->mlock); - - t = (1638 / val); - if (t > 0) - t--; - t &= ADIS16400_SMPL_PRD_DIV_MASK; - if ((t & ADIS16400_SMPL_PRD_DIV_MASK) >= 0x0A) - st->us->max_speed_hz = ADIS16400_SPI_SLOW; - else - st->us->max_speed_hz = ADIS16400_SPI_FAST; - - ret = adis16400_spi_write_reg_8(indio_dev, - ADIS16400_SMPL_PRD, - t); - - /* Also update the filter */ - mutex_unlock(&indio_dev->mlock); - - return ret ? ret : len; -} - -static int adis16400_reset(struct iio_dev *indio_dev) -{ - int ret; - ret = adis16400_spi_write_reg_8(indio_dev, - ADIS16400_GLOB_CMD, - ADIS16400_GLOB_CMD_SW_RESET); - if (ret) - dev_err(&indio_dev->dev, "problem resetting device"); - - return ret; -} - -static ssize_t adis16400_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - bool val; - int ret; - - ret = strtobool(buf, &val); - if (ret < 0) - return ret; - if (val) { - ret = adis16400_reset(dev_get_drvdata(dev)); - if (ret < 0) - return ret; - } - - return len; -} - -int adis16400_set_irq(struct iio_dev *indio_dev, bool enable) -{ - int ret; - u16 msc; - - ret = adis16400_spi_read_reg_16(indio_dev, ADIS16400_MSC_CTRL, &msc); - if (ret) - goto error_ret; - - msc |= ADIS16400_MSC_CTRL_DATA_RDY_POL_HIGH; - if (enable) - msc |= ADIS16400_MSC_CTRL_DATA_RDY_EN; - else - msc &= ~ADIS16400_MSC_CTRL_DATA_RDY_EN; - - ret = adis16400_spi_write_reg_16(indio_dev, ADIS16400_MSC_CTRL, msc); - if (ret) - goto error_ret; - -error_ret: - return ret; -} - -/* Power down the device */ -static int adis16400_stop_device(struct iio_dev *indio_dev) -{ - int ret; - u16 val = ADIS16400_SLP_CNT_POWER_OFF; - - ret = adis16400_spi_write_reg_16(indio_dev, ADIS16400_SLP_CNT, val); - if (ret) - dev_err(&indio_dev->dev, - "problem with turning device off: SLP_CNT"); - - return ret; -} - -static int adis16400_check_status(struct iio_dev *indio_dev) -{ - u16 status; - int ret; - struct device *dev = &indio_dev->dev; - - ret = adis16400_spi_read_reg_16(indio_dev, - ADIS16400_DIAG_STAT, &status); - - if (ret < 0) { - dev_err(dev, "Reading status failed\n"); - goto error_ret; - } - ret = status; - if (status & ADIS16400_DIAG_STAT_ZACCL_FAIL) - dev_err(dev, "Z-axis accelerometer self-test failure\n"); - if (status & ADIS16400_DIAG_STAT_YACCL_FAIL) - dev_err(dev, "Y-axis accelerometer self-test failure\n"); - if (status & ADIS16400_DIAG_STAT_XACCL_FAIL) - dev_err(dev, "X-axis accelerometer self-test failure\n"); - if (status & ADIS16400_DIAG_STAT_XGYRO_FAIL) - dev_err(dev, "X-axis gyroscope self-test failure\n"); - if (status & ADIS16400_DIAG_STAT_YGYRO_FAIL) - dev_err(dev, "Y-axis gyroscope self-test failure\n"); - if (status & ADIS16400_DIAG_STAT_ZGYRO_FAIL) - dev_err(dev, "Z-axis gyroscope self-test failure\n"); - if (status & ADIS16400_DIAG_STAT_ALARM2) - dev_err(dev, "Alarm 2 active\n"); - if (status & ADIS16400_DIAG_STAT_ALARM1) - dev_err(dev, "Alarm 1 active\n"); - if (status & ADIS16400_DIAG_STAT_FLASH_CHK) - dev_err(dev, "Flash checksum error\n"); - if (status & ADIS16400_DIAG_STAT_SELF_TEST) - dev_err(dev, "Self test error\n"); - if (status & ADIS16400_DIAG_STAT_OVERFLOW) - dev_err(dev, "Sensor overrange\n"); - if (status & ADIS16400_DIAG_STAT_SPI_FAIL) - dev_err(dev, "SPI failure\n"); - if (status & ADIS16400_DIAG_STAT_FLASH_UPT) - dev_err(dev, "Flash update failed\n"); - if (status & ADIS16400_DIAG_STAT_POWER_HIGH) - dev_err(dev, "Power supply above 5.25V\n"); - if (status & ADIS16400_DIAG_STAT_POWER_LOW) - dev_err(dev, "Power supply below 4.75V\n"); - -error_ret: - return ret; -} - -static int adis16400_self_test(struct iio_dev *indio_dev) -{ - int ret; - ret = adis16400_spi_write_reg_16(indio_dev, - ADIS16400_MSC_CTRL, - ADIS16400_MSC_CTRL_MEM_TEST); - if (ret) { - dev_err(&indio_dev->dev, "problem starting self test"); - goto err_ret; - } - - msleep(ADIS16400_MTEST_DELAY); - adis16400_check_status(indio_dev); - -err_ret: - return ret; -} - -static int adis16400_initial_setup(struct iio_dev *indio_dev) -{ - int ret; - u16 prod_id, smp_prd; - struct adis16400_state *st = iio_priv(indio_dev); - - /* use low spi speed for init */ - st->us->max_speed_hz = ADIS16400_SPI_SLOW; - st->us->mode = SPI_MODE_3; - spi_setup(st->us); - - ret = adis16400_set_irq(indio_dev, false); - if (ret) { - dev_err(&indio_dev->dev, "disable irq failed"); - goto err_ret; - } - - ret = adis16400_self_test(indio_dev); - if (ret) { - dev_err(&indio_dev->dev, "self test failure"); - goto err_ret; - } - - ret = adis16400_check_status(indio_dev); - if (ret) { - adis16400_reset(indio_dev); - dev_err(&indio_dev->dev, "device not playing ball -> reset"); - msleep(ADIS16400_STARTUP_DELAY); - ret = adis16400_check_status(indio_dev); - if (ret) { - dev_err(&indio_dev->dev, "giving up"); - goto err_ret; - } - } - if (st->variant->flags & ADIS16400_HAS_PROD_ID) { - ret = adis16400_spi_read_reg_16(indio_dev, - ADIS16400_PRODUCT_ID, &prod_id); - if (ret) - goto err_ret; - - if ((prod_id & 0xF000) != st->variant->product_id) - dev_warn(&indio_dev->dev, "incorrect id"); - - dev_info(&indio_dev->dev, "%s: prod_id 0x%04x at CS%d (irq %d)\n", - indio_dev->name, prod_id, - st->us->chip_select, st->us->irq); - } - /* use high spi speed if possible */ - ret = adis16400_spi_read_reg_16(indio_dev, - ADIS16400_SMPL_PRD, &smp_prd); - if (!ret && (smp_prd & ADIS16400_SMPL_PRD_DIV_MASK) < 0x0A) { - st->us->max_speed_hz = ADIS16400_SPI_SLOW; - spi_setup(st->us); - } - -err_ret: - return ret; -} - -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - adis16400_read_frequency, - adis16400_write_frequency); - -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16400_write_reset, 0); - -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("409 546 819 1638"); - -enum adis16400_chan { - in_supply, - gyro_x, - gyro_y, - gyro_z, - accel_x, - accel_y, - accel_z, - magn_x, - magn_y, - magn_z, - temp, - temp0, temp1, temp2, - in1, - incli_x, - incli_y, -}; - -static u8 adis16400_addresses[17][2] = { - [in_supply] = { ADIS16400_SUPPLY_OUT }, - [gyro_x] = { ADIS16400_XGYRO_OUT, ADIS16400_XGYRO_OFF }, - [gyro_y] = { ADIS16400_YGYRO_OUT, ADIS16400_YGYRO_OFF }, - [gyro_z] = { ADIS16400_ZGYRO_OUT, ADIS16400_ZGYRO_OFF }, - [accel_x] = { ADIS16400_XACCL_OUT, ADIS16400_XACCL_OFF }, - [accel_y] = { ADIS16400_YACCL_OUT, ADIS16400_YACCL_OFF }, - [accel_z] = { ADIS16400_ZACCL_OUT, ADIS16400_ZACCL_OFF }, - [magn_x] = { ADIS16400_XMAGN_OUT }, - [magn_y] = { ADIS16400_YMAGN_OUT }, - [magn_z] = { ADIS16400_ZMAGN_OUT }, - [temp] = { ADIS16400_TEMP_OUT }, - [temp0] = { ADIS16350_XTEMP_OUT }, - [temp1] = { ADIS16350_YTEMP_OUT }, - [temp2] = { ADIS16350_ZTEMP_OUT }, - [in1] = { ADIS16400_AUX_ADC }, - [incli_x] = { ADIS16300_PITCH_OUT }, - [incli_y] = { ADIS16300_ROLL_OUT } -}; - - -static int adis16400_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct adis16400_state *st = iio_priv(indio_dev); - int ret, sps; - - switch (mask) { - case IIO_CHAN_INFO_CALIBBIAS: - mutex_lock(&indio_dev->mlock); - ret = adis16400_spi_write_reg_16(indio_dev, - adis16400_addresses[chan->address][1], - val); - mutex_unlock(&indio_dev->mlock); - return ret; - case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - /* Need to cache values so we can update if the frequency - changes */ - mutex_lock(&indio_dev->mlock); - st->filt_int = val; - /* Work out update to current value */ - sps = adis16400_get_freq(indio_dev); - if (sps < 0) { - mutex_unlock(&indio_dev->mlock); - return sps; - } - - ret = adis16400_set_filter(indio_dev, sps, val); - mutex_unlock(&indio_dev->mlock); - return ret; - default: - return -EINVAL; - } -} - -static int adis16400_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long mask) -{ - struct adis16400_state *st = iio_priv(indio_dev); - int ret, shift; - s16 val16; - - switch (mask) { - case 0: - mutex_lock(&indio_dev->mlock); - ret = adis16400_spi_read_reg_16(indio_dev, - adis16400_addresses[chan->address][0], - &val16); - if (ret) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - val16 &= (1 << chan->scan_type.realbits) - 1; - if (chan->scan_type.sign == 's') { - shift = 16 - chan->scan_type.realbits; - val16 = (s16)(val16 << shift) >> shift; - } - *val = val16; - mutex_unlock(&indio_dev->mlock); - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_ANGL_VEL: - *val = 0; - *val2 = st->variant->gyro_scale_micro; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_VOLTAGE: - *val = 0; - if (chan->channel == 0) - *val2 = 2418; - else - *val2 = 806; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_ACCEL: - *val = 0; - *val2 = st->variant->accel_scale_micro; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_MAGN: - *val = 0; - *val2 = 500; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_TEMP: - *val = 0; - *val2 = 140000; - return IIO_VAL_INT_PLUS_MICRO; - default: - return -EINVAL; - } - case IIO_CHAN_INFO_CALIBBIAS: - mutex_lock(&indio_dev->mlock); - ret = adis16400_spi_read_reg_16(indio_dev, - adis16400_addresses[chan->address][1], - &val16); - mutex_unlock(&indio_dev->mlock); - if (ret) - return ret; - val16 = ((val16 & 0xFFF) << 4) >> 4; - *val = val16; - return IIO_VAL_INT; - case IIO_CHAN_INFO_OFFSET: - /* currently only temperature */ - *val = 198; - *val2 = 160000; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - mutex_lock(&indio_dev->mlock); - /* Need both the number of taps and the sampling frequency */ - ret = adis16400_spi_read_reg_16(indio_dev, - ADIS16400_SENS_AVG, - &val16); - if (ret < 0) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - ret = adis16400_get_freq(indio_dev); - if (ret > 0) - *val = ret/adis16400_3db_divisors[val16 & 0x03]; - *val2 = 0; - mutex_unlock(&indio_dev->mlock); - if (ret < 0) - return ret; - return IIO_VAL_INT_PLUS_MICRO; - default: - return -EINVAL; - } -} - -static struct iio_chan_spec adis16400_channels[] = { - { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .extend_name = "supply", - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - .address = in_supply, - .scan_index = ADIS16400_SCAN_SUPPLY, - .scan_type = IIO_ST('u', 14, 16, 0) - }, { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_X, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = gyro_x, - .scan_index = ADIS16400_SCAN_GYRO_X, - .scan_type = IIO_ST('s', 14, 16, 0) - }, { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_Y, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = gyro_y, - .scan_index = ADIS16400_SCAN_GYRO_Y, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = gyro_z, - .scan_index = ADIS16400_SCAN_GYRO_Z, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_X, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = accel_x, - .scan_index = ADIS16400_SCAN_ACC_X, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_Y, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = accel_y, - .scan_index = ADIS16400_SCAN_ACC_Y, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = accel_z, - .scan_index = ADIS16400_SCAN_ACC_Z, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_MAGN, - .modified = 1, - .channel2 = IIO_MOD_X, - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = magn_x, - .scan_index = ADIS16400_SCAN_MAGN_X, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_MAGN, - .modified = 1, - .channel2 = IIO_MOD_Y, - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = magn_y, - .scan_index = ADIS16400_SCAN_MAGN_Y, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_MAGN, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = magn_z, - .scan_index = ADIS16400_SCAN_MAGN_Z, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - .address = temp, - .scan_index = ADIS16400_SCAN_TEMP, - .scan_type = IIO_ST('s', 12, 16, 0), - }, { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - .address = in1, - .scan_index = ADIS16400_SCAN_ADC_0, - .scan_type = IIO_ST('s', 12, 16, 0), - }, - IIO_CHAN_SOFT_TIMESTAMP(12) -}; - -static struct iio_chan_spec adis16350_channels[] = { - { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .extend_name = "supply", - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - .address = in_supply, - .scan_index = ADIS16400_SCAN_SUPPLY, - .scan_type = IIO_ST('u', 12, 16, 0) - }, { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_X, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = gyro_x, - .scan_index = ADIS16400_SCAN_GYRO_X, - .scan_type = IIO_ST('s', 14, 16, 0) - }, { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_Y, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = gyro_y, - .scan_index = ADIS16400_SCAN_GYRO_Y, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = gyro_z, - .scan_index = ADIS16400_SCAN_GYRO_Z, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_X, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = accel_x, - .scan_index = ADIS16400_SCAN_ACC_X, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_Y, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = accel_y, - .scan_index = ADIS16400_SCAN_ACC_Y, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = accel_z, - .scan_index = ADIS16400_SCAN_ACC_Z, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .extend_name = "x", - .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = temp0, - .scan_index = ADIS16350_SCAN_TEMP_X, - .scan_type = IIO_ST('s', 12, 16, 0), - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 1, - .extend_name = "y", - .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = temp1, - .scan_index = ADIS16350_SCAN_TEMP_Y, - .scan_type = IIO_ST('s', 12, 16, 0), - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 2, - .extend_name = "z", - .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - .address = temp2, - .scan_index = ADIS16350_SCAN_TEMP_Z, - .scan_type = IIO_ST('s', 12, 16, 0), - }, { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - .address = in1, - .scan_index = ADIS16350_SCAN_ADC_0, - .scan_type = IIO_ST('s', 12, 16, 0), - }, - IIO_CHAN_SOFT_TIMESTAMP(11) -}; - -static struct iio_chan_spec adis16300_channels[] = { - { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .extend_name = "supply", - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - .address = in_supply, - .scan_index = ADIS16400_SCAN_SUPPLY, - .scan_type = IIO_ST('u', 12, 16, 0) - }, { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_X, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = gyro_x, - .scan_index = ADIS16400_SCAN_GYRO_X, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_X, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = accel_x, - .scan_index = ADIS16400_SCAN_ACC_X, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_Y, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = accel_y, - .scan_index = ADIS16400_SCAN_ACC_Y, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = accel_z, - .scan_index = ADIS16400_SCAN_ACC_Z, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - .address = temp, - .scan_index = ADIS16400_SCAN_TEMP, - .scan_type = IIO_ST('s', 12, 16, 0), - }, { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - .address = in1, - .scan_index = ADIS16350_SCAN_ADC_0, - .scan_type = IIO_ST('s', 12, 16, 0), - }, { - .type = IIO_INCLI, - .modified = 1, - .channel2 = IIO_MOD_X, - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, - .address = incli_x, - .scan_index = ADIS16300_SCAN_INCLI_X, - .scan_type = IIO_ST('s', 13, 16, 0), - }, { - .type = IIO_INCLI, - .modified = 1, - .channel2 = IIO_MOD_Y, - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, - .address = incli_y, - .scan_index = ADIS16300_SCAN_INCLI_Y, - .scan_type = IIO_ST('s', 13, 16, 0), - }, - IIO_CHAN_SOFT_TIMESTAMP(14) -}; - -static const struct iio_chan_spec adis16334_channels[] = { - { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_X, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = gyro_x, - .scan_index = ADIS16400_SCAN_GYRO_X, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_Y, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = gyro_y, - .scan_index = ADIS16400_SCAN_GYRO_Y, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = gyro_z, - .scan_index = ADIS16400_SCAN_GYRO_Z, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_X, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = accel_x, - .scan_index = ADIS16400_SCAN_ACC_X, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_Y, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = accel_y, - .scan_index = ADIS16400_SCAN_ACC_Y, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, - .address = accel_z, - .scan_index = ADIS16400_SCAN_ACC_Z, - .scan_type = IIO_ST('s', 14, 16, 0), - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT, - .address = accel_z, - .scan_index = ADIS16400_SCAN_ACC_Z, - .scan_type = IIO_ST('s', 14, 16, 0), - }, - IIO_CHAN_SOFT_TIMESTAMP(12) -}; - -static struct attribute *adis16400_attributes[] = { - &iio_dev_attr_sampling_frequency.dev_attr.attr, - &iio_const_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_reset.dev_attr.attr, - NULL -}; - -static const struct attribute_group adis16400_attribute_group = { - .attrs = adis16400_attributes, -}; - -static struct adis16400_chip_info adis16400_chips[] = { - [ADIS16300] = { - .channels = adis16300_channels, - .num_channels = ARRAY_SIZE(adis16300_channels), - .gyro_scale_micro = 873, - .accel_scale_micro = 5884, - .default_scan_mask = (1 << ADIS16400_SCAN_SUPPLY) | - (1 << ADIS16400_SCAN_GYRO_X) | (1 << ADIS16400_SCAN_ACC_X) | - (1 << ADIS16400_SCAN_ACC_Y) | (1 << ADIS16400_SCAN_ACC_Z) | - (1 << ADIS16400_SCAN_TEMP) | (1 << ADIS16400_SCAN_ADC_0) | - (1 << ADIS16300_SCAN_INCLI_X) | (1 << ADIS16300_SCAN_INCLI_Y) | - (1 << 14), - }, - [ADIS16334] = { - .channels = adis16334_channels, - .num_channels = ARRAY_SIZE(adis16334_channels), - .gyro_scale_micro = 873, - .accel_scale_micro = 981, - .default_scan_mask = (1 << ADIS16400_SCAN_GYRO_X) | - (1 << ADIS16400_SCAN_GYRO_Y) | (1 << ADIS16400_SCAN_GYRO_Z) | - (1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) | - (1 << ADIS16400_SCAN_ACC_Z), - }, - [ADIS16350] = { - .channels = adis16350_channels, - .num_channels = ARRAY_SIZE(adis16350_channels), - .gyro_scale_micro = 872664, - .accel_scale_micro = 24732, - .default_scan_mask = 0x7FF, - .flags = ADIS16400_NO_BURST, - }, - [ADIS16360] = { - .channels = adis16350_channels, - .num_channels = ARRAY_SIZE(adis16350_channels), - .flags = ADIS16400_HAS_PROD_ID, - .product_id = 0x3FE8, - .gyro_scale_micro = 1279, - .accel_scale_micro = 24732, - .default_scan_mask = 0x7FF, - }, - [ADIS16362] = { - .channels = adis16350_channels, - .num_channels = ARRAY_SIZE(adis16350_channels), - .flags = ADIS16400_HAS_PROD_ID, - .product_id = 0x3FEA, - .gyro_scale_micro = 1279, - .accel_scale_micro = 24732, - .default_scan_mask = 0x7FF, - }, - [ADIS16364] = { - .channels = adis16350_channels, - .num_channels = ARRAY_SIZE(adis16350_channels), - .flags = ADIS16400_HAS_PROD_ID, - .product_id = 0x3FEC, - .gyro_scale_micro = 1279, - .accel_scale_micro = 24732, - .default_scan_mask = 0x7FF, - }, - [ADIS16365] = { - .channels = adis16350_channels, - .num_channels = ARRAY_SIZE(adis16350_channels), - .flags = ADIS16400_HAS_PROD_ID, - .product_id = 0x3FED, - .gyro_scale_micro = 1279, - .accel_scale_micro = 24732, - .default_scan_mask = 0x7FF, - }, - [ADIS16400] = { - .channels = adis16400_channels, - .num_channels = ARRAY_SIZE(adis16400_channels), - .flags = ADIS16400_HAS_PROD_ID, - .product_id = 0x4015, - .gyro_scale_micro = 873, - .accel_scale_micro = 32656, - .default_scan_mask = 0xFFF, - } -}; - -static const struct iio_info adis16400_info = { - .driver_module = THIS_MODULE, - .read_raw = &adis16400_read_raw, - .write_raw = &adis16400_write_raw, - .attrs = &adis16400_attribute_group, -}; - -static int __devinit adis16400_probe(struct spi_device *spi) -{ - int ret; - struct adis16400_state *st; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - st = iio_priv(indio_dev); - /* this is only used for removal purposes */ - spi_set_drvdata(spi, indio_dev); - - st->us = spi; - mutex_init(&st->buf_lock); - - /* setup the industrialio driver allocated elements */ - st->variant = &adis16400_chips[spi_get_device_id(spi)->driver_data]; - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->channels = st->variant->channels; - indio_dev->num_channels = st->variant->num_channels; - indio_dev->info = &adis16400_info; - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = adis16400_configure_ring(indio_dev); - if (ret) - goto error_free_dev; - - ret = iio_buffer_register(indio_dev, - st->variant->channels, - st->variant->num_channels); - if (ret) { - dev_err(&spi->dev, "failed to initialize the ring\n"); - goto error_unreg_ring_funcs; - } - - if (spi->irq) { - ret = adis16400_probe_trigger(indio_dev); - if (ret) - goto error_uninitialize_ring; - } - - /* Get the device into a sane initial state */ - ret = adis16400_initial_setup(indio_dev); - if (ret) - goto error_remove_trigger; - ret = iio_device_register(indio_dev); - if (ret) - goto error_remove_trigger; - - return 0; - -error_remove_trigger: - if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) - adis16400_remove_trigger(indio_dev); -error_uninitialize_ring: - iio_buffer_unregister(indio_dev); -error_unreg_ring_funcs: - adis16400_unconfigure_ring(indio_dev); -error_free_dev: - iio_free_device(indio_dev); -error_ret: - return ret; -} - -/* fixme, confirm ordering in this function */ -static int adis16400_remove(struct spi_device *spi) -{ - int ret; - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - iio_device_unregister(indio_dev); - ret = adis16400_stop_device(indio_dev); - if (ret) - goto err_ret; - - adis16400_remove_trigger(indio_dev); - iio_buffer_unregister(indio_dev); - adis16400_unconfigure_ring(indio_dev); - iio_free_device(indio_dev); - - return 0; - -err_ret: - return ret; -} - -static const struct spi_device_id adis16400_id[] = { - {"adis16300", ADIS16300}, - {"adis16334", ADIS16334}, - {"adis16350", ADIS16350}, - {"adis16354", ADIS16350}, - {"adis16355", ADIS16350}, - {"adis16360", ADIS16360}, - {"adis16362", ADIS16362}, - {"adis16364", ADIS16364}, - {"adis16365", ADIS16365}, - {"adis16400", ADIS16400}, - {"adis16405", ADIS16400}, - {} -}; -MODULE_DEVICE_TABLE(spi, adis16400_id); - -static struct spi_driver adis16400_driver = { - .driver = { - .name = "adis16400", - .owner = THIS_MODULE, - }, - .id_table = adis16400_id, - .probe = adis16400_probe, - .remove = __devexit_p(adis16400_remove), -}; -module_spi_driver(adis16400_driver); - -MODULE_AUTHOR("Manuel Stahl <manuel.stahl@iis.fraunhofer.de>"); -MODULE_DESCRIPTION("Analog Devices ADIS16400/5 IMU SPI driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c deleted file mode 100644 index ac22de573f3..00000000000 --- a/drivers/staging/iio/imu/adis16400_ring.c +++ /dev/null @@ -1,212 +0,0 @@ -#include <linux/interrupt.h> -#include <linux/mutex.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/bitops.h> -#include <linux/export.h> - -#include "../iio.h" -#include "../ring_sw.h" -#include "../trigger_consumer.h" -#include "adis16400.h" - -/** - * adis16400_spi_read_burst() - read all data registers - * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @rx: somewhere to pass back the value read (min size is 24 bytes) - **/ -static int adis16400_spi_read_burst(struct device *dev, u8 *rx) -{ - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16400_state *st = iio_priv(indio_dev); - u32 old_speed_hz = st->us->max_speed_hz; - int ret; - - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - }, { - .rx_buf = rx, - .bits_per_word = 8, - .len = 24, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16400_READ_REG(ADIS16400_GLOB_CMD); - st->tx[1] = 0; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - - st->us->max_speed_hz = min(ADIS16400_SPI_BURST, old_speed_hz); - spi_setup(st->us); - - ret = spi_sync(st->us, &msg); - if (ret) - dev_err(&st->us->dev, "problem when burst reading"); - - st->us->max_speed_hz = old_speed_hz; - spi_setup(st->us); - mutex_unlock(&st->buf_lock); - return ret; -} - -static const u16 read_all_tx_array[] = { - cpu_to_be16(ADIS16400_READ_REG(ADIS16400_SUPPLY_OUT)), - cpu_to_be16(ADIS16400_READ_REG(ADIS16400_XGYRO_OUT)), - cpu_to_be16(ADIS16400_READ_REG(ADIS16400_YGYRO_OUT)), - cpu_to_be16(ADIS16400_READ_REG(ADIS16400_ZGYRO_OUT)), - cpu_to_be16(ADIS16400_READ_REG(ADIS16400_XACCL_OUT)), - cpu_to_be16(ADIS16400_READ_REG(ADIS16400_YACCL_OUT)), - cpu_to_be16(ADIS16400_READ_REG(ADIS16400_ZACCL_OUT)), - cpu_to_be16(ADIS16400_READ_REG(ADIS16350_XTEMP_OUT)), - cpu_to_be16(ADIS16400_READ_REG(ADIS16350_YTEMP_OUT)), - cpu_to_be16(ADIS16400_READ_REG(ADIS16350_ZTEMP_OUT)), - cpu_to_be16(ADIS16400_READ_REG(ADIS16400_AUX_ADC)), -}; - -static int adis16350_spi_read_all(struct device *dev, u8 *rx) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16400_state *st = iio_priv(indio_dev); - - struct spi_message msg; - int i, j = 0, ret; - struct spi_transfer *xfers; - int scan_count = bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength); - - xfers = kzalloc(sizeof(*xfers)*(scan_count + 1), - GFP_KERNEL); - if (xfers == NULL) - return -ENOMEM; - - for (i = 0; i < ARRAY_SIZE(read_all_tx_array); i++) - if (test_bit(i, indio_dev->active_scan_mask)) { - xfers[j].tx_buf = &read_all_tx_array[i]; - xfers[j].bits_per_word = 16; - xfers[j].len = 2; - xfers[j + 1].rx_buf = rx + j*2; - j++; - } - xfers[j].bits_per_word = 16; - xfers[j].len = 2; - - spi_message_init(&msg); - for (j = 0; j < scan_count + 1; j++) - spi_message_add_tail(&xfers[j], &msg); - - ret = spi_sync(st->us, &msg); - kfree(xfers); - - return ret; -} - -/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device - * specific to be rolled into the core. - */ -static irqreturn_t adis16400_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct adis16400_state *st = iio_priv(indio_dev); - struct iio_buffer *ring = indio_dev->buffer; - int i = 0, j, ret = 0; - s16 *data; - size_t datasize = ring->access->get_bytes_per_datum(ring); - /* Asumption that long is enough for maximum channels */ - unsigned long mask = *indio_dev->active_scan_mask; - int scan_count = bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength); - data = kmalloc(datasize , GFP_KERNEL); - if (data == NULL) { - dev_err(&st->us->dev, "memory alloc failed in ring bh"); - return -ENOMEM; - } - - if (scan_count) { - if (st->variant->flags & ADIS16400_NO_BURST) { - ret = adis16350_spi_read_all(&indio_dev->dev, st->rx); - if (ret < 0) - goto err; - for (; i < scan_count; i++) - data[i] = *(s16 *)(st->rx + i*2); - } else { - ret = adis16400_spi_read_burst(&indio_dev->dev, st->rx); - if (ret < 0) - goto err; - for (; i < scan_count; i++) { - j = __ffs(mask); - mask &= ~(1 << j); - data[i] = be16_to_cpup( - (__be16 *)&(st->rx[j*2])); - } - } - } - /* Guaranteed to be aligned with 8 byte boundary */ - if (ring->scan_timestamp) - *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - ring->access->store_to(indio_dev->buffer, (u8 *) data, pf->timestamp); - - iio_trigger_notify_done(indio_dev->trig); - - kfree(data); - return IRQ_HANDLED; - -err: - kfree(data); - return ret; -} - -void adis16400_unconfigure_ring(struct iio_dev *indio_dev) -{ - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->buffer); -} - -static const struct iio_buffer_setup_ops adis16400_ring_setup_ops = { - .preenable = &iio_sw_buffer_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, -}; - -int adis16400_configure_ring(struct iio_dev *indio_dev) -{ - int ret = 0; - struct iio_buffer *ring; - - ring = iio_sw_rb_allocate(indio_dev); - if (!ring) { - ret = -ENOMEM; - return ret; - } - indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ - ring->access = &ring_sw_access_funcs; - ring->scan_timestamp = true; - indio_dev->setup_ops = &adis16400_ring_setup_ops; - - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, - &adis16400_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "%s_consumer%d", - indio_dev->name, - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_iio_sw_rb_free; - } - - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - return 0; -error_iio_sw_rb_free: - iio_sw_rb_free(indio_dev->buffer); - return ret; -} diff --git a/drivers/staging/iio/imu/adis16400_trigger.c b/drivers/staging/iio/imu/adis16400_trigger.c deleted file mode 100644 index 5bf00075752..00000000000 --- a/drivers/staging/iio/imu/adis16400_trigger.c +++ /dev/null @@ -1,74 +0,0 @@ -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/export.h> - -#include "../iio.h" -#include "../trigger.h" -#include "adis16400.h" - -/** - * adis16400_data_rdy_trigger_set_state() set datardy interrupt state - **/ -static int adis16400_data_rdy_trigger_set_state(struct iio_trigger *trig, - bool state) -{ - struct iio_dev *indio_dev = trig->private_data; - - dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); - return adis16400_set_irq(indio_dev, state); -} - -static const struct iio_trigger_ops adis16400_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &adis16400_data_rdy_trigger_set_state, -}; - -int adis16400_probe_trigger(struct iio_dev *indio_dev) -{ - int ret; - struct adis16400_state *st = iio_priv(indio_dev); - - st->trig = iio_allocate_trigger("%s-dev%d", - indio_dev->name, - indio_dev->id); - if (st->trig == NULL) { - ret = -ENOMEM; - goto error_ret; - } - - ret = request_irq(st->us->irq, - &iio_trigger_generic_data_rdy_poll, - IRQF_TRIGGER_RISING, - "adis16400", - st->trig); - if (ret) - goto error_free_trig; - st->trig->dev.parent = &st->us->dev; - st->trig->private_data = indio_dev; - st->trig->ops = &adis16400_trigger_ops; - ret = iio_trigger_register(st->trig); - - /* select default trigger */ - indio_dev->trig = st->trig; - if (ret) - goto error_free_irq; - - return 0; - -error_free_irq: - free_irq(st->us->irq, st->trig); -error_free_trig: - iio_free_trigger(st->trig); -error_ret: - return ret; -} - -void adis16400_remove_trigger(struct iio_dev *indio_dev) -{ - struct adis16400_state *st = iio_priv(indio_dev); - - iio_trigger_unregister(st->trig); - free_irq(st->us->irq, st->trig); - iio_free_trigger(st->trig); -} diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c deleted file mode 100644 index d7b1e9e435a..00000000000 --- a/drivers/staging/iio/industrialio-buffer.c +++ /dev/null @@ -1,734 +0,0 @@ -/* The industrial I/O core - * - * 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. - * - * Handling of buffer allocation / resizing. - * - * - * Things to look at here. - * - Better memory allocation techniques? - * - Alternative access techniques? - */ -#include <linux/kernel.h> -#include <linux/export.h> -#include <linux/device.h> -#include <linux/fs.h> -#include <linux/cdev.h> -#include <linux/slab.h> -#include <linux/poll.h> - -#include "iio.h" -#include "iio_core.h" -#include "sysfs.h" -#include "buffer.h" - -static const char * const iio_endian_prefix[] = { - [IIO_BE] = "be", - [IIO_LE] = "le", -}; - -/** - * iio_buffer_read_first_n_outer() - chrdev read for buffer access - * - * This function relies on all buffer implementations having an - * iio_buffer as their first element. - **/ -ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, - size_t n, loff_t *f_ps) -{ - struct iio_dev *indio_dev = filp->private_data; - struct iio_buffer *rb = indio_dev->buffer; - - if (!rb || !rb->access->read_first_n) - return -EINVAL; - return rb->access->read_first_n(rb, n, buf); -} - -/** - * iio_buffer_poll() - poll the buffer to find out if it has data - */ -unsigned int iio_buffer_poll(struct file *filp, - struct poll_table_struct *wait) -{ - struct iio_dev *indio_dev = filp->private_data; - struct iio_buffer *rb = indio_dev->buffer; - - poll_wait(filp, &rb->pollq, wait); - if (rb->stufftoread) - return POLLIN | POLLRDNORM; - /* need a way of knowing if there may be enough data... */ - return 0; -} - -void iio_buffer_init(struct iio_buffer *buffer) -{ - INIT_LIST_HEAD(&buffer->demux_list); - init_waitqueue_head(&buffer->pollq); -} -EXPORT_SYMBOL(iio_buffer_init); - -static ssize_t iio_show_scan_index(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%u\n", to_iio_dev_attr(attr)->c->scan_index); -} - -static ssize_t iio_show_fixed_type(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - u8 type = this_attr->c->scan_type.endianness; - - if (type == IIO_CPU) { -#ifdef __LITTLE_ENDIAN - type = IIO_LE; -#else - type = IIO_BE; -#endif - } - return sprintf(buf, "%s:%c%d/%d>>%u\n", - iio_endian_prefix[type], - this_attr->c->scan_type.sign, - this_attr->c->scan_type.realbits, - this_attr->c->scan_type.storagebits, - this_attr->c->scan_type.shift); -} - -static ssize_t iio_scan_el_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - - ret = test_bit(to_iio_dev_attr(attr)->address, - indio_dev->buffer->scan_mask); - - return sprintf(buf, "%d\n", ret); -} - -static int iio_scan_mask_clear(struct iio_buffer *buffer, int bit) -{ - clear_bit(bit, buffer->scan_mask); - return 0; -} - -static ssize_t iio_scan_el_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - int ret = 0; - bool state; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_buffer *buffer = indio_dev->buffer; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - state = !(buf[0] == '0'); - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { - ret = -EBUSY; - goto error_ret; - } - ret = iio_scan_mask_query(indio_dev, buffer, this_attr->address); - if (ret < 0) - goto error_ret; - if (!state && ret) { - ret = iio_scan_mask_clear(buffer, this_attr->address); - if (ret) - goto error_ret; - } else if (state && !ret) { - ret = iio_scan_mask_set(indio_dev, buffer, this_attr->address); - if (ret) - goto error_ret; - } - -error_ret: - mutex_unlock(&indio_dev->mlock); - - return ret < 0 ? ret : len; - -} - -static 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->buffer->scan_timestamp); -} - -static ssize_t iio_scan_el_ts_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - int ret = 0; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - bool state; - - state = !(buf[0] == '0'); - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { - ret = -EBUSY; - goto error_ret; - } - indio_dev->buffer->scan_timestamp = state; -error_ret: - mutex_unlock(&indio_dev->mlock); - - return ret ? ret : len; -} - -static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan) -{ - int ret, attrcount = 0; - struct iio_buffer *buffer = indio_dev->buffer; - - ret = __iio_add_chan_devattr("index", - chan, - &iio_show_scan_index, - NULL, - 0, - 0, - &indio_dev->dev, - &buffer->scan_el_dev_attr_list); - if (ret) - goto error_ret; - attrcount++; - ret = __iio_add_chan_devattr("type", - chan, - &iio_show_fixed_type, - NULL, - 0, - 0, - &indio_dev->dev, - &buffer->scan_el_dev_attr_list); - if (ret) - goto error_ret; - attrcount++; - if (chan->type != IIO_TIMESTAMP) - ret = __iio_add_chan_devattr("en", - chan, - &iio_scan_el_show, - &iio_scan_el_store, - chan->scan_index, - 0, - &indio_dev->dev, - &buffer->scan_el_dev_attr_list); - else - ret = __iio_add_chan_devattr("en", - chan, - &iio_scan_el_ts_show, - &iio_scan_el_ts_store, - chan->scan_index, - 0, - &indio_dev->dev, - &buffer->scan_el_dev_attr_list); - attrcount++; - ret = attrcount; -error_ret: - return ret; -} - -static void iio_buffer_remove_and_free_scan_dev_attr(struct iio_dev *indio_dev, - struct iio_dev_attr *p) -{ - kfree(p->dev_attr.attr.name); - kfree(p); -} - -static void __iio_buffer_attr_cleanup(struct iio_dev *indio_dev) -{ - struct iio_dev_attr *p, *n; - struct iio_buffer *buffer = indio_dev->buffer; - - list_for_each_entry_safe(p, n, - &buffer->scan_el_dev_attr_list, l) - iio_buffer_remove_and_free_scan_dev_attr(indio_dev, p); -} - -static const char * const iio_scan_elements_group_name = "scan_elements"; - -int iio_buffer_register(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, - int num_channels) -{ - struct iio_dev_attr *p; - struct attribute **attr; - struct iio_buffer *buffer = indio_dev->buffer; - int ret, i, attrn, attrcount, attrcount_orig = 0; - - if (buffer->attrs) - indio_dev->groups[indio_dev->groupcounter++] = buffer->attrs; - - if (buffer->scan_el_attrs != NULL) { - attr = buffer->scan_el_attrs->attrs; - while (*attr++ != NULL) - attrcount_orig++; - } - attrcount = attrcount_orig; - INIT_LIST_HEAD(&buffer->scan_el_dev_attr_list); - if (channels) { - /* new magic */ - for (i = 0; i < num_channels; i++) { - /* Establish necessary mask length */ - if (channels[i].scan_index > - (int)indio_dev->masklength - 1) - indio_dev->masklength - = indio_dev->channels[i].scan_index + 1; - - ret = iio_buffer_add_channel_sysfs(indio_dev, - &channels[i]); - if (ret < 0) - goto error_cleanup_dynamic; - attrcount += ret; - if (channels[i].type == IIO_TIMESTAMP) - buffer->scan_index_timestamp = - channels[i].scan_index; - } - if (indio_dev->masklength && buffer->scan_mask == NULL) { - buffer->scan_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength), - sizeof(*buffer->scan_mask), - GFP_KERNEL); - if (buffer->scan_mask == NULL) { - ret = -ENOMEM; - goto error_cleanup_dynamic; - } - } - } - - buffer->scan_el_group.name = iio_scan_elements_group_name; - - buffer->scan_el_group.attrs = kcalloc(attrcount + 1, - sizeof(buffer->scan_el_group.attrs[0]), - GFP_KERNEL); - if (buffer->scan_el_group.attrs == NULL) { - ret = -ENOMEM; - goto error_free_scan_mask; - } - if (buffer->scan_el_attrs) - memcpy(buffer->scan_el_group.attrs, buffer->scan_el_attrs, - sizeof(buffer->scan_el_group.attrs[0])*attrcount_orig); - attrn = attrcount_orig; - - list_for_each_entry(p, &buffer->scan_el_dev_attr_list, l) - buffer->scan_el_group.attrs[attrn++] = &p->dev_attr.attr; - indio_dev->groups[indio_dev->groupcounter++] = &buffer->scan_el_group; - - return 0; - -error_free_scan_mask: - kfree(buffer->scan_mask); -error_cleanup_dynamic: - __iio_buffer_attr_cleanup(indio_dev); - - return ret; -} -EXPORT_SYMBOL(iio_buffer_register); - -void iio_buffer_unregister(struct iio_dev *indio_dev) -{ - kfree(indio_dev->buffer->scan_mask); - kfree(indio_dev->buffer->scan_el_group.attrs); - __iio_buffer_attr_cleanup(indio_dev); -} -EXPORT_SYMBOL(iio_buffer_unregister); - -ssize_t iio_buffer_read_length(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_buffer *buffer = indio_dev->buffer; - - if (buffer->access->get_length) - return sprintf(buf, "%d\n", - buffer->access->get_length(buffer)); - - return 0; -} -EXPORT_SYMBOL(iio_buffer_read_length); - -ssize_t iio_buffer_write_length(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - int ret; - ulong val; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_buffer *buffer = indio_dev->buffer; - - ret = strict_strtoul(buf, 10, &val); - if (ret) - return ret; - - if (buffer->access->get_length) - if (val == buffer->access->get_length(buffer)) - return len; - - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { - ret = -EBUSY; - } else { - if (buffer->access->set_length) - buffer->access->set_length(buffer, val); - ret = 0; - } - mutex_unlock(&indio_dev->mlock); - - return ret ? ret : len; -} -EXPORT_SYMBOL(iio_buffer_write_length); - -ssize_t iio_buffer_store_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - int ret; - bool requested_state, current_state; - int previous_mode; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_buffer *buffer = indio_dev->buffer; - - mutex_lock(&indio_dev->mlock); - previous_mode = indio_dev->currentmode; - requested_state = !(buf[0] == '0'); - current_state = iio_buffer_enabled(indio_dev); - if (current_state == requested_state) { - printk(KERN_INFO "iio-buffer, current state requested again\n"); - goto done; - } - if (requested_state) { - if (indio_dev->setup_ops->preenable) { - ret = indio_dev->setup_ops->preenable(indio_dev); - if (ret) { - printk(KERN_ERR - "Buffer not started:" - "buffer preenable failed\n"); - goto error_ret; - } - } - if (buffer->access->request_update) { - ret = buffer->access->request_update(buffer); - if (ret) { - printk(KERN_INFO - "Buffer not started:" - "buffer parameter update failed\n"); - goto error_ret; - } - } - /* Definitely possible for devices to support both of these.*/ - if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) { - if (!indio_dev->trig) { - printk(KERN_INFO - "Buffer not started: no trigger\n"); - ret = -EINVAL; - goto error_ret; - } - indio_dev->currentmode = INDIO_BUFFER_TRIGGERED; - } else if (indio_dev->modes & INDIO_BUFFER_HARDWARE) - indio_dev->currentmode = INDIO_BUFFER_HARDWARE; - else { /* should never be reached */ - ret = -EINVAL; - goto error_ret; - } - - if (indio_dev->setup_ops->postenable) { - ret = indio_dev->setup_ops->postenable(indio_dev); - if (ret) { - printk(KERN_INFO - "Buffer not started:" - "postenable failed\n"); - indio_dev->currentmode = previous_mode; - if (indio_dev->setup_ops->postdisable) - indio_dev->setup_ops-> - postdisable(indio_dev); - goto error_ret; - } - } - } else { - if (indio_dev->setup_ops->predisable) { - ret = indio_dev->setup_ops->predisable(indio_dev); - if (ret) - goto error_ret; - } - indio_dev->currentmode = INDIO_DIRECT_MODE; - if (indio_dev->setup_ops->postdisable) { - ret = indio_dev->setup_ops->postdisable(indio_dev); - if (ret) - goto error_ret; - } - } -done: - mutex_unlock(&indio_dev->mlock); - return len; - -error_ret: - mutex_unlock(&indio_dev->mlock); - return ret; -} -EXPORT_SYMBOL(iio_buffer_store_enable); - -ssize_t iio_buffer_show_enable(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", iio_buffer_enabled(indio_dev)); -} -EXPORT_SYMBOL(iio_buffer_show_enable); - -/* note NULL used as error indicator as it doesn't make sense. */ -static unsigned long *iio_scan_mask_match(unsigned long *av_masks, - unsigned int masklength, - unsigned long *mask) -{ - if (bitmap_empty(mask, masklength)) - return NULL; - while (*av_masks) { - if (bitmap_subset(mask, av_masks, masklength)) - return av_masks; - av_masks += BITS_TO_LONGS(masklength); - } - return NULL; -} - -int iio_sw_buffer_preenable(struct iio_dev *indio_dev) -{ - struct iio_buffer *buffer = indio_dev->buffer; - const struct iio_chan_spec *ch; - unsigned bytes = 0; - int length, i; - dev_dbg(&indio_dev->dev, "%s\n", __func__); - - /* How much space will the demuxed element take? */ - for_each_set_bit(i, buffer->scan_mask, - indio_dev->masklength) { - ch = iio_find_channel_from_si(indio_dev, i); - length = ch->scan_type.storagebits/8; - bytes = ALIGN(bytes, length); - bytes += length; - } - if (buffer->scan_timestamp) { - ch = iio_find_channel_from_si(indio_dev, - buffer->scan_index_timestamp); - length = ch->scan_type.storagebits/8; - bytes = ALIGN(bytes, length); - bytes += length; - } - buffer->access->set_bytes_per_datum(buffer, bytes); - - /* What scan mask do we actually have ?*/ - if (indio_dev->available_scan_masks) - indio_dev->active_scan_mask = - iio_scan_mask_match(indio_dev->available_scan_masks, - indio_dev->masklength, - buffer->scan_mask); - else - indio_dev->active_scan_mask = buffer->scan_mask; - iio_update_demux(indio_dev); - - if (indio_dev->info->update_scan_mode) - return indio_dev->info - ->update_scan_mode(indio_dev, - indio_dev->active_scan_mask); - return 0; -} -EXPORT_SYMBOL(iio_sw_buffer_preenable); - -/** - * iio_scan_mask_set() - set particular bit in the scan mask - * @buffer: the buffer whose scan mask we are interested in - * @bit: the bit to be set. - **/ -int iio_scan_mask_set(struct iio_dev *indio_dev, - struct iio_buffer *buffer, int bit) -{ - unsigned long *mask; - unsigned long *trialmask; - - trialmask = kmalloc(sizeof(*trialmask)* - BITS_TO_LONGS(indio_dev->masklength), - GFP_KERNEL); - - if (trialmask == NULL) - return -ENOMEM; - if (!indio_dev->masklength) { - WARN_ON("trying to set scanmask prior to registering buffer\n"); - kfree(trialmask); - return -EINVAL; - } - bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength); - set_bit(bit, trialmask); - - if (indio_dev->available_scan_masks) { - mask = iio_scan_mask_match(indio_dev->available_scan_masks, - indio_dev->masklength, - trialmask); - if (!mask) { - kfree(trialmask); - return -EINVAL; - } - } - bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength); - - kfree(trialmask); - - return 0; -}; -EXPORT_SYMBOL_GPL(iio_scan_mask_set); - -int iio_scan_mask_query(struct iio_dev *indio_dev, - struct iio_buffer *buffer, int bit) -{ - if (bit > indio_dev->masklength) - return -EINVAL; - - if (!buffer->scan_mask) - return 0; - - return test_bit(bit, buffer->scan_mask); -}; -EXPORT_SYMBOL_GPL(iio_scan_mask_query); - -/** - * struct iio_demux_table() - table describing demux memcpy ops - * @from: index to copy from - * @to: index to copy to - * @length: how many bytes to copy - * @l: list head used for management - */ -struct iio_demux_table { - unsigned from; - unsigned to; - unsigned length; - struct list_head l; -}; - -static unsigned char *iio_demux(struct iio_buffer *buffer, - unsigned char *datain) -{ - struct iio_demux_table *t; - - if (list_empty(&buffer->demux_list)) - return datain; - list_for_each_entry(t, &buffer->demux_list, l) - memcpy(buffer->demux_bounce + t->to, - datain + t->from, t->length); - - return buffer->demux_bounce; -} - -int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data, - s64 timestamp) -{ - unsigned char *dataout = iio_demux(buffer, data); - - return buffer->access->store_to(buffer, dataout, timestamp); -} -EXPORT_SYMBOL_GPL(iio_push_to_buffer); - -int iio_update_demux(struct iio_dev *indio_dev) -{ - const struct iio_chan_spec *ch; - struct iio_buffer *buffer = indio_dev->buffer; - int ret, in_ind = -1, out_ind, length; - unsigned in_loc = 0, out_loc = 0; - struct iio_demux_table *p, *q; - - /* Clear out any old demux */ - list_for_each_entry_safe(p, q, &buffer->demux_list, l) { - list_del(&p->l); - kfree(p); - } - kfree(buffer->demux_bounce); - buffer->demux_bounce = NULL; - - /* First work out which scan mode we will actually have */ - if (bitmap_equal(indio_dev->active_scan_mask, - buffer->scan_mask, - indio_dev->masklength)) - return 0; - - /* Now we have the two masks, work from least sig and build up sizes */ - for_each_set_bit(out_ind, - indio_dev->active_scan_mask, - indio_dev->masklength) { - in_ind = find_next_bit(indio_dev->active_scan_mask, - indio_dev->masklength, - in_ind + 1); - while (in_ind != out_ind) { - in_ind = find_next_bit(indio_dev->active_scan_mask, - indio_dev->masklength, - in_ind + 1); - ch = iio_find_channel_from_si(indio_dev, in_ind); - length = ch->scan_type.storagebits/8; - /* Make sure we are aligned */ - in_loc += length; - if (in_loc % length) - in_loc += length - in_loc % length; - } - p = kmalloc(sizeof(*p), GFP_KERNEL); - if (p == NULL) { - ret = -ENOMEM; - goto error_clear_mux_table; - } - ch = iio_find_channel_from_si(indio_dev, in_ind); - length = ch->scan_type.storagebits/8; - if (out_loc % length) - out_loc += length - out_loc % length; - if (in_loc % length) - in_loc += length - in_loc % length; - p->from = in_loc; - p->to = out_loc; - p->length = length; - list_add_tail(&p->l, &buffer->demux_list); - out_loc += length; - in_loc += length; - } - /* Relies on scan_timestamp being last */ - if (buffer->scan_timestamp) { - p = kmalloc(sizeof(*p), GFP_KERNEL); - if (p == NULL) { - ret = -ENOMEM; - goto error_clear_mux_table; - } - ch = iio_find_channel_from_si(indio_dev, - buffer->scan_index_timestamp); - length = ch->scan_type.storagebits/8; - if (out_loc % length) - out_loc += length - out_loc % length; - if (in_loc % length) - in_loc += length - in_loc % length; - p->from = in_loc; - p->to = out_loc; - p->length = length; - list_add_tail(&p->l, &buffer->demux_list); - out_loc += length; - in_loc += length; - } - buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL); - if (buffer->demux_bounce == NULL) { - ret = -ENOMEM; - goto error_clear_mux_table; - } - return 0; - -error_clear_mux_table: - list_for_each_entry_safe(p, q, &buffer->demux_list, l) { - list_del(&p->l); - kfree(p); - } - return ret; -} -EXPORT_SYMBOL_GPL(iio_update_demux); diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c deleted file mode 100644 index 19f897f3c85..00000000000 --- a/drivers/staging/iio/industrialio-core.c +++ /dev/null @@ -1,1187 +0,0 @@ -/* The industrial I/O core - * - * 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. - * - * Based on elements of hwmon and input subsystems. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/idr.h> -#include <linux/kdev_t.h> -#include <linux/err.h> -#include <linux/device.h> -#include <linux/fs.h> -#include <linux/poll.h> -#include <linux/sched.h> -#include <linux/wait.h> -#include <linux/cdev.h> -#include <linux/slab.h> -#include <linux/anon_inodes.h> -#include "iio.h" -#include "iio_core.h" -#include "iio_core_trigger.h" -#include "sysfs.h" -#include "events.h" - -/* IDA to assign each registered device a unique id*/ -static DEFINE_IDA(iio_ida); - -static dev_t iio_devt; - -#define IIO_DEV_MAX 256 -struct bus_type iio_bus_type = { - .name = "iio", -}; -EXPORT_SYMBOL(iio_bus_type); - -static const char * const iio_data_type_name[] = { - [IIO_RAW] = "raw", - [IIO_PROCESSED] = "input", -}; - -static const char * const iio_direction[] = { - [0] = "in", - [1] = "out", -}; - -static const char * const iio_chan_type_name_spec[] = { - [IIO_VOLTAGE] = "voltage", - [IIO_CURRENT] = "current", - [IIO_POWER] = "power", - [IIO_ACCEL] = "accel", - [IIO_ANGL_VEL] = "anglvel", - [IIO_MAGN] = "magn", - [IIO_LIGHT] = "illuminance", - [IIO_INTENSITY] = "intensity", - [IIO_PROXIMITY] = "proximity", - [IIO_TEMP] = "temp", - [IIO_INCLI] = "incli", - [IIO_ROT] = "rot", - [IIO_ANGL] = "angl", - [IIO_TIMESTAMP] = "timestamp", - [IIO_CAPACITANCE] = "capacitance", -}; - -static const char * const iio_modifier_names[] = { - [IIO_MOD_X] = "x", - [IIO_MOD_Y] = "y", - [IIO_MOD_Z] = "z", - [IIO_MOD_LIGHT_BOTH] = "both", - [IIO_MOD_LIGHT_IR] = "ir", -}; - -/* relies on pairs of these shared then separate */ -static const char * const iio_chan_info_postfix[] = { - [IIO_CHAN_INFO_SCALE] = "scale", - [IIO_CHAN_INFO_OFFSET] = "offset", - [IIO_CHAN_INFO_CALIBSCALE] = "calibscale", - [IIO_CHAN_INFO_CALIBBIAS] = "calibbias", - [IIO_CHAN_INFO_PEAK] = "peak_raw", - [IIO_CHAN_INFO_PEAK_SCALE] = "peak_scale", - [IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW] = "quadrature_correction_raw", - [IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw", - [IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY] - = "filter_low_pass_3db_frequency", -}; - -const struct iio_chan_spec -*iio_find_channel_from_si(struct iio_dev *indio_dev, int si) -{ - int i; - - for (i = 0; i < indio_dev->num_channels; i++) - if (indio_dev->channels[i].scan_index == si) - return &indio_dev->channels[i]; - return NULL; -} - -/** - * struct iio_detected_event_list - list element for events that have occurred - * @list: linked list header - * @ev: the event itself - */ -struct iio_detected_event_list { - struct list_head list; - struct iio_event_data ev; -}; - -/** - * struct iio_event_interface - chrdev interface for an event line - * @dev: device assocated with event interface - * @wait: wait queue to allow blocking reads of events - * @event_list_lock: mutex to protect the list of detected events - * @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 - * @flags: file operations related flags including busy flag. - */ -struct iio_event_interface { - wait_queue_head_t wait; - struct mutex event_list_lock; - struct list_head det_events; - int max_events; - int current_events; - struct list_head dev_attr_list; - unsigned long flags; - struct attribute_group group; -}; - -int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) -{ - struct iio_event_interface *ev_int = indio_dev->event_interface; - struct iio_detected_event_list *ev; - int ret = 0; - - /* Does anyone care? */ - mutex_lock(&ev_int->event_list_lock); - if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { - if (ev_int->current_events == ev_int->max_events) { - mutex_unlock(&ev_int->event_list_lock); - return 0; - } - ev = kmalloc(sizeof(*ev), GFP_KERNEL); - if (ev == NULL) { - ret = -ENOMEM; - mutex_unlock(&ev_int->event_list_lock); - goto error_ret; - } - ev->ev.id = ev_code; - ev->ev.timestamp = timestamp; - - list_add_tail(&ev->list, &ev_int->det_events); - ev_int->current_events++; - mutex_unlock(&ev_int->event_list_lock); - wake_up_interruptible(&ev_int->wait); - } else - mutex_unlock(&ev_int->event_list_lock); - -error_ret: - return ret; -} -EXPORT_SYMBOL(iio_push_event); - -/* This turns up an awful lot */ -ssize_t iio_read_const_attr(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string); -} -EXPORT_SYMBOL(iio_read_const_attr); - -static ssize_t iio_event_chrdev_read(struct file *filep, - char __user *buf, - size_t count, - loff_t *f_ps) -{ - struct iio_event_interface *ev_int = filep->private_data; - struct iio_detected_event_list *el; - size_t len = sizeof(el->ev); - int ret; - - if (count < len) - return -EINVAL; - - mutex_lock(&ev_int->event_list_lock); - if (list_empty(&ev_int->det_events)) { - if (filep->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - goto error_mutex_unlock; - } - mutex_unlock(&ev_int->event_list_lock); - /* Blocking on device; waiting for something to be there */ - ret = wait_event_interruptible(ev_int->wait, - !list_empty(&ev_int - ->det_events)); - if (ret) - goto error_ret; - /* Single access device so no one else can get the data */ - mutex_lock(&ev_int->event_list_lock); - } - - el = list_first_entry(&ev_int->det_events, - struct iio_detected_event_list, - list); - if (copy_to_user(buf, &(el->ev), len)) { - ret = -EFAULT; - goto error_mutex_unlock; - } - list_del(&el->list); - ev_int->current_events--; - mutex_unlock(&ev_int->event_list_lock); - kfree(el); - - return len; - -error_mutex_unlock: - mutex_unlock(&ev_int->event_list_lock); -error_ret: - - return ret; -} - -static int iio_event_chrdev_release(struct inode *inode, struct file *filep) -{ - struct iio_event_interface *ev_int = filep->private_data; - struct iio_detected_event_list *el, *t; - - mutex_lock(&ev_int->event_list_lock); - clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); - /* - * In order to maintain a clean state for reopening, - * clear out any awaiting events. The mask will prevent - * any new __iio_push_event calls running. - */ - list_for_each_entry_safe(el, t, &ev_int->det_events, list) { - list_del(&el->list); - kfree(el); - } - ev_int->current_events = 0; - mutex_unlock(&ev_int->event_list_lock); - - return 0; -} - -static const struct file_operations iio_event_chrdev_fileops = { - .read = iio_event_chrdev_read, - .release = iio_event_chrdev_release, - .owner = THIS_MODULE, - .llseek = noop_llseek, -}; - -static int iio_event_getfd(struct iio_dev *indio_dev) -{ - struct iio_event_interface *ev_int = indio_dev->event_interface; - int fd; - - if (ev_int == NULL) - return -ENODEV; - - mutex_lock(&ev_int->event_list_lock); - if (test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { - mutex_unlock(&ev_int->event_list_lock); - return -EBUSY; - } - mutex_unlock(&ev_int->event_list_lock); - fd = anon_inode_getfd("iio:event", - &iio_event_chrdev_fileops, ev_int, O_RDONLY); - if (fd < 0) { - mutex_lock(&ev_int->event_list_lock); - clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); - mutex_unlock(&ev_int->event_list_lock); - } - return fd; -} - -static int __init iio_init(void) -{ - int ret; - - /* Register sysfs bus */ - ret = bus_register(&iio_bus_type); - if (ret < 0) { - printk(KERN_ERR - "%s could not register bus type\n", - __FILE__); - goto error_nothing; - } - - ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio"); - if (ret < 0) { - printk(KERN_ERR "%s: failed to allocate char dev region\n", - __FILE__); - goto error_unregister_bus_type; - } - - return 0; - -error_unregister_bus_type: - bus_unregister(&iio_bus_type); -error_nothing: - return ret; -} - -static void __exit iio_exit(void) -{ - if (iio_devt) - unregister_chrdev_region(iio_devt, IIO_DEV_MAX); - bus_unregister(&iio_bus_type); -} - -static ssize_t iio_read_channel_info(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int val, val2; - int ret = indio_dev->info->read_raw(indio_dev, this_attr->c, - &val, &val2, this_attr->address); - - if (ret < 0) - return ret; - - if (ret == IIO_VAL_INT) - return sprintf(buf, "%d\n", val); - else if (ret == IIO_VAL_INT_PLUS_MICRO) { - if (val2 < 0) - return sprintf(buf, "-%d.%06u\n", val, -val2); - else - return sprintf(buf, "%d.%06u\n", val, val2); - } else if (ret == IIO_VAL_INT_PLUS_NANO) { - if (val2 < 0) - return sprintf(buf, "-%d.%09u\n", val, -val2); - else - return sprintf(buf, "%d.%09u\n", val, val2); - } else - return 0; -} - -static ssize_t iio_write_channel_info(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret, integer = 0, fract = 0, fract_mult = 100000; - bool integer_part = true, negative = false; - - /* Assumes decimal - precision based on number of digits */ - if (!indio_dev->info->write_raw) - return -EINVAL; - - if (indio_dev->info->write_raw_get_fmt) - switch (indio_dev->info->write_raw_get_fmt(indio_dev, - this_attr->c, this_attr->address)) { - case IIO_VAL_INT_PLUS_MICRO: - fract_mult = 100000; - break; - case IIO_VAL_INT_PLUS_NANO: - fract_mult = 100000000; - break; - default: - return -EINVAL; - } - - if (buf[0] == '-') { - negative = true; - buf++; - } - - while (*buf) { - if ('0' <= *buf && *buf <= '9') { - if (integer_part) - integer = integer*10 + *buf - '0'; - else { - fract += fract_mult*(*buf - '0'); - if (fract_mult == 1) - break; - fract_mult /= 10; - } - } else if (*buf == '\n') { - if (*(buf + 1) == '\0') - break; - else - return -EINVAL; - } else if (*buf == '.') { - integer_part = false; - } else { - return -EINVAL; - } - buf++; - } - if (negative) { - if (integer) - integer = -integer; - else - fract = -fract; - } - - ret = indio_dev->info->write_raw(indio_dev, this_attr->c, - integer, fract, this_attr->address); - if (ret) - return ret; - - return len; -} - -static -int __iio_device_attr_init(struct device_attribute *dev_attr, - const char *postfix, - struct iio_chan_spec const *chan, - ssize_t (*readfunc)(struct device *dev, - struct device_attribute *attr, - char *buf), - ssize_t (*writefunc)(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len), - bool generic) -{ - int ret; - char *name_format, *full_postfix; - sysfs_attr_init(&dev_attr->attr); - - /* Build up postfix of <extend_name>_<modifier>_postfix */ - if (chan->modified && !generic) { - if (chan->extend_name) - full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", - iio_modifier_names[chan - ->channel2], - chan->extend_name, - postfix); - else - full_postfix = kasprintf(GFP_KERNEL, "%s_%s", - iio_modifier_names[chan - ->channel2], - postfix); - } else { - if (chan->extend_name == NULL) - full_postfix = kstrdup(postfix, GFP_KERNEL); - else - full_postfix = kasprintf(GFP_KERNEL, - "%s_%s", - chan->extend_name, - postfix); - } - if (full_postfix == NULL) { - ret = -ENOMEM; - goto error_ret; - } - - if (chan->differential) { /* Differential can not have modifier */ - if (generic) - name_format - = kasprintf(GFP_KERNEL, "%s_%s-%s_%s", - iio_direction[chan->output], - iio_chan_type_name_spec[chan->type], - iio_chan_type_name_spec[chan->type], - full_postfix); - else if (chan->indexed) - name_format - = kasprintf(GFP_KERNEL, "%s_%s%d-%s%d_%s", - iio_direction[chan->output], - iio_chan_type_name_spec[chan->type], - chan->channel, - iio_chan_type_name_spec[chan->type], - chan->channel2, - full_postfix); - else { - WARN_ON("Differential channels must be indexed\n"); - ret = -EINVAL; - goto error_free_full_postfix; - } - } else { /* Single ended */ - if (generic) - name_format - = kasprintf(GFP_KERNEL, "%s_%s_%s", - iio_direction[chan->output], - iio_chan_type_name_spec[chan->type], - full_postfix); - else if (chan->indexed) - name_format - = kasprintf(GFP_KERNEL, "%s_%s%d_%s", - iio_direction[chan->output], - iio_chan_type_name_spec[chan->type], - chan->channel, - full_postfix); - else - name_format - = kasprintf(GFP_KERNEL, "%s_%s_%s", - iio_direction[chan->output], - iio_chan_type_name_spec[chan->type], - full_postfix); - } - if (name_format == NULL) { - ret = -ENOMEM; - goto error_free_full_postfix; - } - dev_attr->attr.name = kasprintf(GFP_KERNEL, - name_format, - chan->channel, - chan->channel2); - if (dev_attr->attr.name == NULL) { - ret = -ENOMEM; - goto error_free_name_format; - } - - if (readfunc) { - dev_attr->attr.mode |= S_IRUGO; - dev_attr->show = readfunc; - } - - if (writefunc) { - dev_attr->attr.mode |= S_IWUSR; - dev_attr->store = writefunc; - } - kfree(name_format); - kfree(full_postfix); - - return 0; - -error_free_name_format: - kfree(name_format); -error_free_full_postfix: - kfree(full_postfix); -error_ret: - return ret; -} - -static void __iio_device_attr_deinit(struct device_attribute *dev_attr) -{ - kfree(dev_attr->attr.name); -} - -int __iio_add_chan_devattr(const char *postfix, - struct iio_chan_spec const *chan, - ssize_t (*readfunc)(struct device *dev, - struct device_attribute *attr, - char *buf), - ssize_t (*writefunc)(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len), - u64 mask, - bool generic, - struct device *dev, - struct list_head *attr_list) -{ - int ret; - struct iio_dev_attr *iio_attr, *t; - - iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL); - if (iio_attr == NULL) { - ret = -ENOMEM; - goto error_ret; - } - ret = __iio_device_attr_init(&iio_attr->dev_attr, - postfix, chan, - readfunc, writefunc, generic); - if (ret) - goto error_iio_dev_attr_free; - iio_attr->c = chan; - iio_attr->address = mask; - list_for_each_entry(t, attr_list, l) - if (strcmp(t->dev_attr.attr.name, - iio_attr->dev_attr.attr.name) == 0) { - if (!generic) - dev_err(dev, "tried to double register : %s\n", - t->dev_attr.attr.name); - ret = -EBUSY; - goto error_device_attr_deinit; - } - list_add(&iio_attr->l, attr_list); - - return 0; - -error_device_attr_deinit: - __iio_device_attr_deinit(&iio_attr->dev_attr); -error_iio_dev_attr_free: - kfree(iio_attr); -error_ret: - return ret; -} - -static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan) -{ - int ret, i, attrcount = 0; - - if (chan->channel < 0) - return 0; - - ret = __iio_add_chan_devattr(iio_data_type_name[chan->processed_val], - chan, - &iio_read_channel_info, - (chan->output ? - &iio_write_channel_info : NULL), - 0, - 0, - &indio_dev->dev, - &indio_dev->channel_attr_list); - if (ret) - goto error_ret; - attrcount++; - - for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) { - ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2], - chan, - &iio_read_channel_info, - &iio_write_channel_info, - i/2, - !(i%2), - &indio_dev->dev, - &indio_dev->channel_attr_list); - if (ret == -EBUSY && (i%2 == 0)) { - ret = 0; - continue; - } - if (ret < 0) - goto error_ret; - attrcount++; - } - ret = attrcount; -error_ret: - return ret; -} - -static void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev, - struct iio_dev_attr *p) -{ - kfree(p->dev_attr.attr.name); - kfree(p); -} - -static ssize_t iio_show_dev_name(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", indio_dev->name); -} - -static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL); - -static int iio_device_register_sysfs(struct iio_dev *indio_dev) -{ - int i, ret = 0, attrcount, attrn, attrcount_orig = 0; - struct iio_dev_attr *p, *n; - struct attribute **attr; - - /* First count elements in any existing group */ - if (indio_dev->info->attrs) { - attr = indio_dev->info->attrs->attrs; - while (*attr++ != NULL) - attrcount_orig++; - } - attrcount = attrcount_orig; - /* - * New channel registration method - relies on the fact a group does - * not need to be initialized if it is name is NULL. - */ - INIT_LIST_HEAD(&indio_dev->channel_attr_list); - if (indio_dev->channels) - for (i = 0; i < indio_dev->num_channels; i++) { - ret = iio_device_add_channel_sysfs(indio_dev, - &indio_dev - ->channels[i]); - if (ret < 0) - goto error_clear_attrs; - attrcount += ret; - } - - if (indio_dev->name) - attrcount++; - - indio_dev->chan_attr_group.attrs = kcalloc(attrcount + 1, - sizeof(indio_dev->chan_attr_group.attrs[0]), - GFP_KERNEL); - if (indio_dev->chan_attr_group.attrs == NULL) { - ret = -ENOMEM; - goto error_clear_attrs; - } - /* Copy across original attributes */ - if (indio_dev->info->attrs) - memcpy(indio_dev->chan_attr_group.attrs, - indio_dev->info->attrs->attrs, - sizeof(indio_dev->chan_attr_group.attrs[0]) - *attrcount_orig); - attrn = attrcount_orig; - /* Add all elements from the list. */ - list_for_each_entry(p, &indio_dev->channel_attr_list, l) - indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr; - if (indio_dev->name) - indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr; - - indio_dev->groups[indio_dev->groupcounter++] = - &indio_dev->chan_attr_group; - - return 0; - -error_clear_attrs: - list_for_each_entry_safe(p, n, - &indio_dev->channel_attr_list, l) { - list_del(&p->l); - iio_device_remove_and_free_read_attr(indio_dev, p); - } - - return ret; -} - -static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) -{ - - struct iio_dev_attr *p, *n; - - list_for_each_entry_safe(p, n, &indio_dev->channel_attr_list, l) { - list_del(&p->l); - iio_device_remove_and_free_read_attr(indio_dev, p); - } - kfree(indio_dev->chan_attr_group.attrs); -} - -static const char * const iio_ev_type_text[] = { - [IIO_EV_TYPE_THRESH] = "thresh", - [IIO_EV_TYPE_MAG] = "mag", - [IIO_EV_TYPE_ROC] = "roc", - [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", - [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", -}; - -static const char * const iio_ev_dir_text[] = { - [IIO_EV_DIR_EITHER] = "either", - [IIO_EV_DIR_RISING] = "rising", - [IIO_EV_DIR_FALLING] = "falling" -}; - -static ssize_t iio_ev_state_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret; - bool val; - - ret = strtobool(buf, &val); - if (ret < 0) - return ret; - - ret = indio_dev->info->write_event_config(indio_dev, - this_attr->address, - val); - return (ret < 0) ? ret : len; -} - -static ssize_t iio_ev_state_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int val = indio_dev->info->read_event_config(indio_dev, - this_attr->address); - - if (val < 0) - return val; - else - return sprintf(buf, "%d\n", val); -} - -static ssize_t iio_ev_value_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int val, ret; - - ret = indio_dev->info->read_event_value(indio_dev, - this_attr->address, &val); - if (ret < 0) - return ret; - - return sprintf(buf, "%d\n", val); -} - -static ssize_t iio_ev_value_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - unsigned long val; - int ret; - - if (!indio_dev->info->write_event_value) - return -EINVAL; - - ret = strict_strtoul(buf, 10, &val); - if (ret) - return ret; - - ret = indio_dev->info->write_event_value(indio_dev, this_attr->address, - val); - if (ret < 0) - return ret; - - return len; -} - -static int iio_device_add_event_sysfs(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan) -{ - int ret = 0, i, attrcount = 0; - u64 mask = 0; - char *postfix; - if (!chan->event_mask) - return 0; - - for_each_set_bit(i, &chan->event_mask, sizeof(chan->event_mask)*8) { - postfix = kasprintf(GFP_KERNEL, "%s_%s_en", - iio_ev_type_text[i/IIO_EV_DIR_MAX], - iio_ev_dir_text[i%IIO_EV_DIR_MAX]); - if (postfix == NULL) { - ret = -ENOMEM; - goto error_ret; - } - if (chan->modified) - mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel, - i/IIO_EV_DIR_MAX, - i%IIO_EV_DIR_MAX); - else if (chan->differential) - mask = IIO_EVENT_CODE(chan->type, - 0, 0, - i%IIO_EV_DIR_MAX, - i/IIO_EV_DIR_MAX, - 0, - chan->channel, - chan->channel2); - else - mask = IIO_UNMOD_EVENT_CODE(chan->type, - chan->channel, - i/IIO_EV_DIR_MAX, - i%IIO_EV_DIR_MAX); - - ret = __iio_add_chan_devattr(postfix, - chan, - &iio_ev_state_show, - iio_ev_state_store, - mask, - 0, - &indio_dev->dev, - &indio_dev->event_interface-> - dev_attr_list); - kfree(postfix); - if (ret) - goto error_ret; - attrcount++; - postfix = kasprintf(GFP_KERNEL, "%s_%s_value", - iio_ev_type_text[i/IIO_EV_DIR_MAX], - iio_ev_dir_text[i%IIO_EV_DIR_MAX]); - if (postfix == NULL) { - ret = -ENOMEM; - goto error_ret; - } - ret = __iio_add_chan_devattr(postfix, chan, - iio_ev_value_show, - iio_ev_value_store, - mask, - 0, - &indio_dev->dev, - &indio_dev->event_interface-> - dev_attr_list); - kfree(postfix); - if (ret) - goto error_ret; - attrcount++; - } - ret = attrcount; -error_ret: - return ret; -} - -static inline void __iio_remove_event_config_attrs(struct iio_dev *indio_dev) -{ - struct iio_dev_attr *p, *n; - list_for_each_entry_safe(p, n, - &indio_dev->event_interface-> - dev_attr_list, l) { - kfree(p->dev_attr.attr.name); - kfree(p); - } -} - -static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev) -{ - int j, ret, attrcount = 0; - - INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list); - /* Dynically created from the channels array */ - for (j = 0; j < indio_dev->num_channels; j++) { - ret = iio_device_add_event_sysfs(indio_dev, - &indio_dev->channels[j]); - if (ret < 0) - goto error_clear_attrs; - attrcount += ret; - } - return attrcount; - -error_clear_attrs: - __iio_remove_event_config_attrs(indio_dev); - - return ret; -} - -static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev) -{ - int j; - - for (j = 0; j < indio_dev->num_channels; j++) - if (indio_dev->channels[j].event_mask != 0) - return true; - return false; -} - -static void iio_setup_ev_int(struct iio_event_interface *ev_int) -{ - mutex_init(&ev_int->event_list_lock); - /* discussion point - make this variable? */ - ev_int->max_events = 10; - ev_int->current_events = 0; - INIT_LIST_HEAD(&ev_int->det_events); - init_waitqueue_head(&ev_int->wait); -} - -static const char *iio_event_group_name = "events"; -static int iio_device_register_eventset(struct iio_dev *indio_dev) -{ - struct iio_dev_attr *p; - int ret = 0, attrcount_orig = 0, attrcount, attrn; - struct attribute **attr; - - if (!(indio_dev->info->event_attrs || - iio_check_for_dynamic_events(indio_dev))) - return 0; - - indio_dev->event_interface = - kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL); - if (indio_dev->event_interface == NULL) { - ret = -ENOMEM; - goto error_ret; - } - - iio_setup_ev_int(indio_dev->event_interface); - if (indio_dev->info->event_attrs != NULL) { - attr = indio_dev->info->event_attrs->attrs; - while (*attr++ != NULL) - attrcount_orig++; - } - attrcount = attrcount_orig; - if (indio_dev->channels) { - ret = __iio_add_event_config_attrs(indio_dev); - if (ret < 0) - goto error_free_setup_event_lines; - attrcount += ret; - } - - indio_dev->event_interface->group.name = iio_event_group_name; - indio_dev->event_interface->group.attrs = kcalloc(attrcount + 1, - sizeof(indio_dev->event_interface->group.attrs[0]), - GFP_KERNEL); - if (indio_dev->event_interface->group.attrs == NULL) { - ret = -ENOMEM; - goto error_free_setup_event_lines; - } - if (indio_dev->info->event_attrs) - memcpy(indio_dev->event_interface->group.attrs, - indio_dev->info->event_attrs->attrs, - sizeof(indio_dev->event_interface->group.attrs[0]) - *attrcount_orig); - attrn = attrcount_orig; - /* Add all elements from the list. */ - list_for_each_entry(p, - &indio_dev->event_interface->dev_attr_list, - l) - indio_dev->event_interface->group.attrs[attrn++] = - &p->dev_attr.attr; - indio_dev->groups[indio_dev->groupcounter++] = - &indio_dev->event_interface->group; - - return 0; - -error_free_setup_event_lines: - __iio_remove_event_config_attrs(indio_dev); - kfree(indio_dev->event_interface); -error_ret: - - return ret; -} - -static void iio_device_unregister_eventset(struct iio_dev *indio_dev) -{ - if (indio_dev->event_interface == NULL) - return; - __iio_remove_event_config_attrs(indio_dev); - kfree(indio_dev->event_interface->group.attrs); - kfree(indio_dev->event_interface); -} - -static void iio_dev_release(struct device *device) -{ - struct iio_dev *indio_dev = container_of(device, struct iio_dev, dev); - cdev_del(&indio_dev->chrdev); - if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) - iio_device_unregister_trigger_consumer(indio_dev); - iio_device_unregister_eventset(indio_dev); - iio_device_unregister_sysfs(indio_dev); -} - -static struct device_type iio_dev_type = { - .name = "iio_device", - .release = iio_dev_release, -}; - -struct iio_dev *iio_allocate_device(int sizeof_priv) -{ - struct iio_dev *dev; - size_t alloc_size; - - alloc_size = sizeof(struct iio_dev); - if (sizeof_priv) { - alloc_size = ALIGN(alloc_size, IIO_ALIGN); - alloc_size += sizeof_priv; - } - /* ensure 32-byte alignment of whole construct ? */ - alloc_size += IIO_ALIGN - 1; - - dev = kzalloc(alloc_size, GFP_KERNEL); - - if (dev) { - dev->dev.groups = dev->groups; - dev->dev.type = &iio_dev_type; - dev->dev.bus = &iio_bus_type; - device_initialize(&dev->dev); - dev_set_drvdata(&dev->dev, (void *)dev); - mutex_init(&dev->mlock); - - dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); - if (dev->id < 0) { - /* cannot use a dev_err as the name isn't available */ - printk(KERN_ERR "Failed to get id\n"); - kfree(dev); - return NULL; - } - dev_set_name(&dev->dev, "iio:device%d", dev->id); - } - - return dev; -} -EXPORT_SYMBOL(iio_allocate_device); - -void iio_free_device(struct iio_dev *dev) -{ - if (dev) { - ida_simple_remove(&iio_ida, dev->id); - kfree(dev); - } -} -EXPORT_SYMBOL(iio_free_device); - -/** - * iio_chrdev_open() - chrdev file open for buffer access and ioctls - **/ -static int iio_chrdev_open(struct inode *inode, struct file *filp) -{ - struct iio_dev *indio_dev = container_of(inode->i_cdev, - struct iio_dev, chrdev); - - if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags)) - return -EBUSY; - - filp->private_data = indio_dev; - - return 0; -} - -/** - * iio_chrdev_release() - chrdev file close buffer access and ioctls - **/ -static int iio_chrdev_release(struct inode *inode, struct file *filp) -{ - struct iio_dev *indio_dev = container_of(inode->i_cdev, - struct iio_dev, chrdev); - clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags); - return 0; -} - -/* Somewhat of a cross file organization violation - ioctls here are actually - * event related */ -static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - struct iio_dev *indio_dev = filp->private_data; - int __user *ip = (int __user *)arg; - int fd; - - if (cmd == IIO_GET_EVENT_FD_IOCTL) { - fd = iio_event_getfd(indio_dev); - if (copy_to_user(ip, &fd, sizeof(fd))) - return -EFAULT; - return 0; - } - return -EINVAL; -} - -static const struct file_operations iio_buffer_fileops = { - .read = iio_buffer_read_first_n_outer_addr, - .release = iio_chrdev_release, - .open = iio_chrdev_open, - .poll = iio_buffer_poll_addr, - .owner = THIS_MODULE, - .llseek = noop_llseek, - .unlocked_ioctl = iio_ioctl, - .compat_ioctl = iio_ioctl, -}; - -int iio_device_register(struct iio_dev *indio_dev) -{ - int ret; - - /* configure elements for the chrdev */ - indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); - - ret = iio_device_register_sysfs(indio_dev); - if (ret) { - dev_err(indio_dev->dev.parent, - "Failed to register sysfs interfaces\n"); - goto error_ret; - } - ret = iio_device_register_eventset(indio_dev); - if (ret) { - dev_err(indio_dev->dev.parent, - "Failed to register event set\n"); - goto error_free_sysfs; - } - if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) - iio_device_register_trigger_consumer(indio_dev); - - ret = device_add(&indio_dev->dev); - if (ret < 0) - goto error_unreg_eventset; - cdev_init(&indio_dev->chrdev, &iio_buffer_fileops); - indio_dev->chrdev.owner = indio_dev->info->driver_module; - ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1); - if (ret < 0) - goto error_del_device; - return 0; - -error_del_device: - device_del(&indio_dev->dev); -error_unreg_eventset: - iio_device_unregister_eventset(indio_dev); -error_free_sysfs: - iio_device_unregister_sysfs(indio_dev); -error_ret: - return ret; -} -EXPORT_SYMBOL(iio_device_register); - -void iio_device_unregister(struct iio_dev *indio_dev) -{ - device_unregister(&indio_dev->dev); -} -EXPORT_SYMBOL(iio_device_unregister); -subsys_initcall(iio_init); -module_exit(iio_exit); - -MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); -MODULE_DESCRIPTION("Industrial I/O core"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/industrialio-trigger.c b/drivers/staging/iio/industrialio-trigger.c deleted file mode 100644 index 47ecadd4818..00000000000 --- a/drivers/staging/iio/industrialio-trigger.c +++ /dev/null @@ -1,509 +0,0 @@ -/* The industrial I/O core, trigger handling functions - * - * Copyright (c) 2008 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -#include <linux/kernel.h> -#include <linux/idr.h> -#include <linux/err.h> -#include <linux/device.h> -#include <linux/interrupt.h> -#include <linux/list.h> -#include <linux/slab.h> - -#include "iio.h" -#include "trigger.h" -#include "iio_core.h" -#include "iio_core_trigger.h" -#include "trigger_consumer.h" - -/* RFC - Question of approach - * Make the common case (single sensor single trigger) - * simple by starting trigger capture from when first sensors - * is added. - * - * Complex simultaneous start requires use of 'hold' functionality - * of the trigger. (not implemented) - * - * Any other suggestions? - */ - -static DEFINE_IDA(iio_trigger_ida); - -/* Single list of all available triggers */ -static LIST_HEAD(iio_trigger_list); -static DEFINE_MUTEX(iio_trigger_list_lock); - -/** - * iio_trigger_read_name() - retrieve useful identifying name - **/ -static ssize_t iio_trigger_read_name(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_trigger *trig = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", trig->name); -} - -static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL); - -/** - * iio_trigger_register_sysfs() - create a device for this trigger - * @trig_info: the trigger - * - * Also adds any control attribute registered by the trigger driver - **/ -static int iio_trigger_register_sysfs(struct iio_trigger *trig_info) -{ - return sysfs_add_file_to_group(&trig_info->dev.kobj, - &dev_attr_name.attr, - NULL); -} - -static void iio_trigger_unregister_sysfs(struct iio_trigger *trig_info) -{ - sysfs_remove_file_from_group(&trig_info->dev.kobj, - &dev_attr_name.attr, - NULL); -} - -int iio_trigger_register(struct iio_trigger *trig_info) -{ - int ret; - - trig_info->id = ida_simple_get(&iio_trigger_ida, 0, 0, GFP_KERNEL); - if (trig_info->id < 0) { - ret = trig_info->id; - goto error_ret; - } - /* Set the name used for the sysfs directory etc */ - dev_set_name(&trig_info->dev, "trigger%ld", - (unsigned long) trig_info->id); - - ret = device_add(&trig_info->dev); - if (ret) - goto error_unregister_id; - - ret = iio_trigger_register_sysfs(trig_info); - if (ret) - goto error_device_del; - - /* Add to list of available triggers held by the IIO core */ - mutex_lock(&iio_trigger_list_lock); - list_add_tail(&trig_info->list, &iio_trigger_list); - mutex_unlock(&iio_trigger_list_lock); - - return 0; - -error_device_del: - device_del(&trig_info->dev); -error_unregister_id: - ida_simple_remove(&iio_trigger_ida, trig_info->id); -error_ret: - return ret; -} -EXPORT_SYMBOL(iio_trigger_register); - -void iio_trigger_unregister(struct iio_trigger *trig_info) -{ - mutex_lock(&iio_trigger_list_lock); - list_del(&trig_info->list); - mutex_unlock(&iio_trigger_list_lock); - - iio_trigger_unregister_sysfs(trig_info); - ida_simple_remove(&iio_trigger_ida, trig_info->id); - /* Possible issue in here */ - device_unregister(&trig_info->dev); -} -EXPORT_SYMBOL(iio_trigger_unregister); - -static struct iio_trigger *iio_trigger_find_by_name(const char *name, - size_t len) -{ - struct iio_trigger *trig = NULL, *iter; - - mutex_lock(&iio_trigger_list_lock); - list_for_each_entry(iter, &iio_trigger_list, list) - if (sysfs_streq(iter->name, name)) { - trig = iter; - break; - } - mutex_unlock(&iio_trigger_list_lock); - - return trig; -} - -void iio_trigger_poll(struct iio_trigger *trig, s64 time) -{ - int i; - if (!trig->use_count) - for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) - if (trig->subirqs[i].enabled) { - trig->use_count++; - generic_handle_irq(trig->subirq_base + i); - } -} -EXPORT_SYMBOL(iio_trigger_poll); - -irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private) -{ - iio_trigger_poll(private, iio_get_time_ns()); - return IRQ_HANDLED; -} -EXPORT_SYMBOL(iio_trigger_generic_data_rdy_poll); - -void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time) -{ - int i; - if (!trig->use_count) - for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) - if (trig->subirqs[i].enabled) { - trig->use_count++; - handle_nested_irq(trig->subirq_base + i); - } -} -EXPORT_SYMBOL(iio_trigger_poll_chained); - -void iio_trigger_notify_done(struct iio_trigger *trig) -{ - trig->use_count--; - if (trig->use_count == 0 && trig->ops && trig->ops->try_reenable) - if (trig->ops->try_reenable(trig)) - /* Missed and interrupt so launch new poll now */ - iio_trigger_poll(trig, 0); -} -EXPORT_SYMBOL(iio_trigger_notify_done); - -/* Trigger Consumer related functions */ -static int iio_trigger_get_irq(struct iio_trigger *trig) -{ - int ret; - mutex_lock(&trig->pool_lock); - ret = bitmap_find_free_region(trig->pool, - CONFIG_IIO_CONSUMERS_PER_TRIGGER, - ilog2(1)); - mutex_unlock(&trig->pool_lock); - if (ret >= 0) - ret += trig->subirq_base; - - return ret; -} - -static void iio_trigger_put_irq(struct iio_trigger *trig, int irq) -{ - mutex_lock(&trig->pool_lock); - clear_bit(irq - trig->subirq_base, trig->pool); - mutex_unlock(&trig->pool_lock); -} - -/* Complexity in here. With certain triggers (datardy) an acknowledgement - * may be needed if the pollfuncs do not include the data read for the - * triggering device. - * This is not currently handled. Alternative of not enabling trigger unless - * the relevant function is in there may be the best option. - */ -/* Worth protecting against double additions?*/ -static int iio_trigger_attach_poll_func(struct iio_trigger *trig, - struct iio_poll_func *pf) -{ - int ret = 0; - bool notinuse - = bitmap_empty(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER); - - /* Prevent the module being removed whilst attached to a trigger */ - __module_get(pf->indio_dev->info->driver_module); - pf->irq = iio_trigger_get_irq(trig); - ret = request_threaded_irq(pf->irq, pf->h, pf->thread, - pf->type, pf->name, - pf); - if (ret < 0) { - module_put(pf->indio_dev->info->driver_module); - return ret; - } - - if (trig->ops && trig->ops->set_trigger_state && notinuse) { - ret = trig->ops->set_trigger_state(trig, true); - if (ret < 0) - module_put(pf->indio_dev->info->driver_module); - } - - return ret; -} - -static int iio_trigger_dettach_poll_func(struct iio_trigger *trig, - struct iio_poll_func *pf) -{ - int ret = 0; - bool no_other_users - = (bitmap_weight(trig->pool, - CONFIG_IIO_CONSUMERS_PER_TRIGGER) - == 1); - if (trig->ops && trig->ops->set_trigger_state && no_other_users) { - ret = trig->ops->set_trigger_state(trig, false); - if (ret) - goto error_ret; - } - iio_trigger_put_irq(trig, pf->irq); - free_irq(pf->irq, pf); - module_put(pf->indio_dev->info->driver_module); - -error_ret: - return ret; -} - -irqreturn_t iio_pollfunc_store_time(int irq, void *p) -{ - struct iio_poll_func *pf = p; - pf->timestamp = iio_get_time_ns(); - return IRQ_WAKE_THREAD; -} -EXPORT_SYMBOL(iio_pollfunc_store_time); - -struct iio_poll_func -*iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p), - irqreturn_t (*thread)(int irq, void *p), - int type, - struct iio_dev *indio_dev, - const char *fmt, - ...) -{ - va_list vargs; - struct iio_poll_func *pf; - - pf = kmalloc(sizeof *pf, GFP_KERNEL); - if (pf == NULL) - return NULL; - va_start(vargs, fmt); - pf->name = kvasprintf(GFP_KERNEL, fmt, vargs); - va_end(vargs); - if (pf->name == NULL) { - kfree(pf); - return NULL; - } - pf->h = h; - pf->thread = thread; - pf->type = type; - pf->indio_dev = indio_dev; - - return pf; -} -EXPORT_SYMBOL_GPL(iio_alloc_pollfunc); - -void iio_dealloc_pollfunc(struct iio_poll_func *pf) -{ - kfree(pf->name); - kfree(pf); -} -EXPORT_SYMBOL_GPL(iio_dealloc_pollfunc); - -/** - * iio_trigger_read_current() - trigger consumer sysfs query which trigger - * - * For trigger consumers the current_trigger interface allows the trigger - * used by the device to be queried. - **/ -static ssize_t iio_trigger_read_current(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - - if (indio_dev->trig) - return sprintf(buf, "%s\n", indio_dev->trig->name); - return 0; -} - -/** - * iio_trigger_write_current() trigger consumer sysfs set current trigger - * - * For trigger consumers the current_trigger interface allows the trigger - * used for this device to be specified at run time based on the triggers - * name. - **/ -static ssize_t iio_trigger_write_current(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_trigger *oldtrig = indio_dev->trig; - struct iio_trigger *trig; - int ret; - - mutex_lock(&indio_dev->mlock); - if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { - mutex_unlock(&indio_dev->mlock); - return -EBUSY; - } - mutex_unlock(&indio_dev->mlock); - - trig = iio_trigger_find_by_name(buf, len); - if (oldtrig == trig) - return len; - - if (trig && indio_dev->info->validate_trigger) { - ret = indio_dev->info->validate_trigger(indio_dev, trig); - if (ret) - return ret; - } - - if (trig && trig->ops && trig->ops->validate_device) { - ret = trig->ops->validate_device(trig, indio_dev); - if (ret) - return ret; - } - - indio_dev->trig = trig; - - if (oldtrig && indio_dev->trig != oldtrig) - iio_put_trigger(oldtrig); - if (indio_dev->trig) - iio_get_trigger(indio_dev->trig); - - return len; -} - -static DEVICE_ATTR(current_trigger, S_IRUGO | S_IWUSR, - iio_trigger_read_current, - iio_trigger_write_current); - -static struct attribute *iio_trigger_consumer_attrs[] = { - &dev_attr_current_trigger.attr, - NULL, -}; - -static const struct attribute_group iio_trigger_consumer_attr_group = { - .name = "trigger", - .attrs = iio_trigger_consumer_attrs, -}; - -static void iio_trig_release(struct device *device) -{ - struct iio_trigger *trig = to_iio_trigger(device); - int i; - - if (trig->subirq_base) { - for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) { - irq_modify_status(trig->subirq_base + i, - IRQ_NOAUTOEN, - IRQ_NOREQUEST | IRQ_NOPROBE); - irq_set_chip(trig->subirq_base + i, - NULL); - irq_set_handler(trig->subirq_base + i, - NULL); - } - - irq_free_descs(trig->subirq_base, - CONFIG_IIO_CONSUMERS_PER_TRIGGER); - } - kfree(trig->name); - kfree(trig); -} - -static struct device_type iio_trig_type = { - .release = iio_trig_release, -}; - -static void iio_trig_subirqmask(struct irq_data *d) -{ - struct irq_chip *chip = irq_data_get_irq_chip(d); - struct iio_trigger *trig - = container_of(chip, - struct iio_trigger, subirq_chip); - trig->subirqs[d->irq - trig->subirq_base].enabled = false; -} - -static void iio_trig_subirqunmask(struct irq_data *d) -{ - struct irq_chip *chip = irq_data_get_irq_chip(d); - struct iio_trigger *trig - = container_of(chip, - struct iio_trigger, subirq_chip); - trig->subirqs[d->irq - trig->subirq_base].enabled = true; -} - -struct iio_trigger *iio_allocate_trigger(const char *fmt, ...) -{ - va_list vargs; - struct iio_trigger *trig; - trig = kzalloc(sizeof *trig, GFP_KERNEL); - if (trig) { - int i; - trig->dev.type = &iio_trig_type; - trig->dev.bus = &iio_bus_type; - device_initialize(&trig->dev); - dev_set_drvdata(&trig->dev, (void *)trig); - - mutex_init(&trig->pool_lock); - trig->subirq_base - = irq_alloc_descs(-1, 0, - CONFIG_IIO_CONSUMERS_PER_TRIGGER, - 0); - if (trig->subirq_base < 0) { - kfree(trig); - return NULL; - } - va_start(vargs, fmt); - trig->name = kvasprintf(GFP_KERNEL, fmt, vargs); - va_end(vargs); - if (trig->name == NULL) { - irq_free_descs(trig->subirq_base, - CONFIG_IIO_CONSUMERS_PER_TRIGGER); - kfree(trig); - return NULL; - } - trig->subirq_chip.name = trig->name; - trig->subirq_chip.irq_mask = &iio_trig_subirqmask; - trig->subirq_chip.irq_unmask = &iio_trig_subirqunmask; - for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) { - irq_set_chip(trig->subirq_base + i, - &trig->subirq_chip); - irq_set_handler(trig->subirq_base + i, - &handle_simple_irq); - irq_modify_status(trig->subirq_base + i, - IRQ_NOREQUEST | IRQ_NOAUTOEN, - IRQ_NOPROBE); - } - get_device(&trig->dev); - } - return trig; -} -EXPORT_SYMBOL(iio_allocate_trigger); - -void iio_free_trigger(struct iio_trigger *trig) -{ - if (trig) - put_device(&trig->dev); -} -EXPORT_SYMBOL(iio_free_trigger); - -void iio_device_register_trigger_consumer(struct iio_dev *indio_dev) -{ - indio_dev->groups[indio_dev->groupcounter++] = - &iio_trigger_consumer_attr_group; -} - -void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev) -{ - /* Clean up and associated but not attached triggers references */ - if (indio_dev->trig) - iio_put_trigger(indio_dev->trig); -} - -int iio_triggered_buffer_postenable(struct iio_dev *indio_dev) -{ - return iio_trigger_attach_poll_func(indio_dev->trig, - indio_dev->pollfunc); -} -EXPORT_SYMBOL(iio_triggered_buffer_postenable); - -int iio_triggered_buffer_predisable(struct iio_dev *indio_dev) -{ - return iio_trigger_dettach_poll_func(indio_dev->trig, - indio_dev->pollfunc); -} -EXPORT_SYMBOL(iio_triggered_buffer_predisable); diff --git a/drivers/staging/iio/kfifo_buf.c b/drivers/staging/iio/kfifo_buf.c deleted file mode 100644 index e1e9c06cde4..00000000000 --- a/drivers/staging/iio/kfifo_buf.c +++ /dev/null @@ -1,151 +0,0 @@ -#include <linux/slab.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/workqueue.h> -#include <linux/kfifo.h> -#include <linux/mutex.h> - -#include "kfifo_buf.h" - -struct iio_kfifo { - struct iio_buffer buffer; - struct kfifo kf; - int update_needed; -}; - -#define iio_to_kfifo(r) container_of(r, struct iio_kfifo, buffer) - -static inline int __iio_allocate_kfifo(struct iio_kfifo *buf, - int bytes_per_datum, int length) -{ - if ((length == 0) || (bytes_per_datum == 0)) - return -EINVAL; - - __iio_update_buffer(&buf->buffer, bytes_per_datum, length); - return kfifo_alloc(&buf->kf, bytes_per_datum*length, GFP_KERNEL); -} - -static int iio_request_update_kfifo(struct iio_buffer *r) -{ - int ret = 0; - struct iio_kfifo *buf = iio_to_kfifo(r); - - if (!buf->update_needed) - goto error_ret; - kfifo_free(&buf->kf); - ret = __iio_allocate_kfifo(buf, buf->buffer.bytes_per_datum, - buf->buffer.length); -error_ret: - return ret; -} - -static int iio_get_length_kfifo(struct iio_buffer *r) -{ - return r->length; -} - -static IIO_BUFFER_ENABLE_ATTR; -static IIO_BUFFER_LENGTH_ATTR; - -static struct attribute *iio_kfifo_attributes[] = { - &dev_attr_length.attr, - &dev_attr_enable.attr, - NULL, -}; - -static struct attribute_group iio_kfifo_attribute_group = { - .attrs = iio_kfifo_attributes, - .name = "buffer", -}; - -struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) -{ - struct iio_kfifo *kf; - - kf = kzalloc(sizeof *kf, GFP_KERNEL); - if (!kf) - return NULL; - kf->update_needed = true; - iio_buffer_init(&kf->buffer); - kf->buffer.attrs = &iio_kfifo_attribute_group; - - return &kf->buffer; -} -EXPORT_SYMBOL(iio_kfifo_allocate); - -static int iio_get_bytes_per_datum_kfifo(struct iio_buffer *r) -{ - return r->bytes_per_datum; -} - -static int iio_mark_update_needed_kfifo(struct iio_buffer *r) -{ - struct iio_kfifo *kf = iio_to_kfifo(r); - kf->update_needed = true; - return 0; -} - -static int iio_set_bytes_per_datum_kfifo(struct iio_buffer *r, size_t bpd) -{ - if (r->bytes_per_datum != bpd) { - r->bytes_per_datum = bpd; - iio_mark_update_needed_kfifo(r); - } - return 0; -} - -static int iio_set_length_kfifo(struct iio_buffer *r, int length) -{ - if (r->length != length) { - r->length = length; - iio_mark_update_needed_kfifo(r); - } - return 0; -} - -void iio_kfifo_free(struct iio_buffer *r) -{ - kfree(iio_to_kfifo(r)); -} -EXPORT_SYMBOL(iio_kfifo_free); - -static int iio_store_to_kfifo(struct iio_buffer *r, - u8 *data, - s64 timestamp) -{ - int ret; - struct iio_kfifo *kf = iio_to_kfifo(r); - ret = kfifo_in(&kf->kf, data, r->bytes_per_datum); - if (ret != r->bytes_per_datum) - return -EBUSY; - return 0; -} - -static int iio_read_first_n_kfifo(struct iio_buffer *r, - size_t n, char __user *buf) -{ - int ret, copied; - struct iio_kfifo *kf = iio_to_kfifo(r); - - if (n < r->bytes_per_datum) - return -EINVAL; - - n = rounddown(n, r->bytes_per_datum); - ret = kfifo_to_user(&kf->kf, buf, n, &copied); - - return copied; -} - -const struct iio_buffer_access_funcs kfifo_access_funcs = { - .store_to = &iio_store_to_kfifo, - .read_first_n = &iio_read_first_n_kfifo, - .request_update = &iio_request_update_kfifo, - .get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo, - .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, - .get_length = &iio_get_length_kfifo, - .set_length = &iio_set_length_kfifo, -}; -EXPORT_SYMBOL(kfifo_access_funcs); - -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/kfifo_buf.h b/drivers/staging/iio/kfifo_buf.h deleted file mode 100644 index cc2bd9a1ccf..00000000000 --- a/drivers/staging/iio/kfifo_buf.h +++ /dev/null @@ -1,10 +0,0 @@ - -#include <linux/kfifo.h> -#include "iio.h" -#include "buffer.h" - -extern const struct iio_buffer_access_funcs kfifo_access_funcs; - -struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev); -void iio_kfifo_free(struct iio_buffer *r); - diff --git a/drivers/staging/iio/light/Kconfig b/drivers/staging/iio/light/Kconfig index e7e9159d989..ca8d6e66c89 100644 --- a/drivers/staging/iio/light/Kconfig +++ b/drivers/staging/iio/light/Kconfig @@ -4,25 +4,26 @@ menu "Light sensors" 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. - -config SENSORS_TSL2563 - tristate "TAOS TSL2560, TSL2561, TSL2562 and TSL2563 ambient light sensors" + tristate "ISL 29018 light and proximity sensor" depends on I2C + select REGMAP_I2C + default n help - If you say yes here you get support for the Taos TSL2560, - TSL2561, TSL2562 and TSL2563 ambient light sensors. + 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. - This driver can also be built as a module. If so, the module - will be called tsl2563. +config SENSORS_ISL29028 + tristate "Intersil ISL29028 Concurrent Light and Proximity Sensor" + depends on I2C + select REGMAP_I2C + help + Provides driver for the Intersil's ISL29028 device. + This driver supports the sysfs interface to get the ALS, IR intensity, + Proximity value via iio. The ISL29028 provides the concurrent sensing + of ambient light and proximity. config TSL2583 tristate "TAOS TSL2580, TSL2581 and TSL2583 light-to-digital converters" @@ -31,4 +32,12 @@ config TSL2583 Provides support for the TAOS tsl2580, tsl2581 and tsl2583 devices. Access ALS data via iio, sysfs. +config TSL2x7x + tristate "TAOS TSL/TMD2x71 and TSL/TMD2x72 Family of light and proximity sensors" + depends on I2C + help + Support for: tsl2571, tsl2671, tmd2671, tsl2771, tmd2771, tsl2572, tsl2672, + tmd2672, tsl2772, tmd2772 devices. + Provides iio_events and direct access via sysfs. + endmenu diff --git a/drivers/staging/iio/light/Makefile b/drivers/staging/iio/light/Makefile index 3011fbfa8dc..9960fdf7c15 100644 --- a/drivers/staging/iio/light/Makefile +++ b/drivers/staging/iio/light/Makefile @@ -2,6 +2,7 @@ # Makefile for industrial I/O Light sensors # -obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o obj-$(CONFIG_SENSORS_ISL29018) += isl29018.o +obj-$(CONFIG_SENSORS_ISL29028) += isl29028.o obj-$(CONFIG_TSL2583) += tsl2583.o +obj-$(CONFIG_TSL2x7x) += tsl2x7x_core.o diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 849d6a564af..3660a43b5f0 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -26,9 +26,11 @@ #include <linux/err.h> #include <linux/mutex.h> #include <linux/delay.h> +#include <linux/regmap.h> #include <linux/slab.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> + #define CONVERSION_TIME_MS 100 #define ISL29018_REG_ADD_COMMAND1 0x00 @@ -51,49 +53,24 @@ #define ISL29018_REG_ADD_DATA_LSB 0x02 #define ISL29018_REG_ADD_DATA_MSB 0x03 -#define ISL29018_MAX_REGS (ISL29018_REG_ADD_DATA_MSB+1) #define ISL29018_REG_TEST 0x08 #define ISL29018_TEST_SHIFT 0 #define ISL29018_TEST_MASK (0xFF << ISL29018_TEST_SHIFT) struct isl29018_chip { - struct i2c_client *client; + struct device *dev; + struct regmap *regmap; struct mutex lock; unsigned int lux_scale; + unsigned int lux_uscale; unsigned int range; unsigned int adc_bit; int prox_scheme; - u8 reg_cache[ISL29018_MAX_REGS]; + bool suspended; }; -static int isl29018_write_data(struct i2c_client *client, u8 reg, - u8 val, u8 mask, u8 shift) -{ - u8 regval = val; - int ret; - struct isl29018_chip *chip = iio_priv(i2c_get_clientdata(client)); - - /* don't cache or mask REG_TEST */ - if (reg < ISL29018_MAX_REGS) { - 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); - } else { - /* don't update cache on err */ - if (reg < ISL29018_MAX_REGS) - chip->reg_cache[reg] = regval; - } - - return ret; -} - -static int isl29018_set_range(struct i2c_client *client, unsigned long range, +static int isl29018_set_range(struct isl29018_chip *chip, unsigned long range, unsigned int *new_range) { static const unsigned long supp_ranges[] = {1000, 4000, 16000, 64000}; @@ -109,11 +86,11 @@ static int isl29018_set_range(struct i2c_client *client, unsigned long range, if (i >= ARRAY_SIZE(supp_ranges)) return -EINVAL; - return isl29018_write_data(client, ISL29018_REG_ADD_COMMANDII, - i, COMMANDII_RANGE_MASK, COMMANDII_RANGE_SHIFT); + return regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, + COMMANDII_RANGE_MASK, i << COMMANDII_RANGE_SHIFT); } -static int isl29018_set_resolution(struct i2c_client *client, +static int isl29018_set_resolution(struct isl29018_chip *chip, unsigned long adcbit, unsigned int *conf_adc_bit) { static const unsigned long supp_adcbit[] = {16, 12, 8, 4}; @@ -129,62 +106,72 @@ static int isl29018_set_resolution(struct i2c_client *client, if (i >= ARRAY_SIZE(supp_adcbit)) return -EINVAL; - return isl29018_write_data(client, ISL29018_REG_ADD_COMMANDII, - i, COMMANDII_RESOLUTION_MASK, - COMMANDII_RESOLUTION_SHIFT); + return regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, + COMMANDII_RESOLUTION_MASK, + i << COMMANDII_RESOLUTION_SHIFT); } -static int isl29018_read_sensor_input(struct i2c_client *client, int mode) +static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode) { int status; - int lsb; - int msb; + unsigned int lsb; + unsigned int msb; /* Set mode */ - status = isl29018_write_data(client, ISL29018_REG_ADD_COMMAND1, - mode, COMMMAND1_OPMODE_MASK, COMMMAND1_OPMODE_SHIFT); + status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1, + mode << COMMMAND1_OPMODE_SHIFT); if (status) { - dev_err(&client->dev, "Error in setting operating mode\n"); + dev_err(chip->dev, + "Error in setting operating mode err %d\n", status); 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; + status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_LSB, &lsb); + if (status < 0) { + dev_err(chip->dev, + "Error in reading LSB DATA with err %d\n", status); + return status; } - 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; + status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_MSB, &msb); + if (status < 0) { + dev_err(chip->dev, + "Error in reading MSB DATA with error %d\n", status); + return status; } - dev_vdbg(&client->dev, "MSB 0x%x and LSB 0x%x\n", msb, lsb); + dev_vdbg(chip->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) +static int isl29018_read_lux(struct isl29018_chip *chip, int *lux) { int lux_data; - struct isl29018_chip *chip = iio_priv(i2c_get_clientdata(client)); + unsigned int data_x_range, lux_unshifted; - lux_data = isl29018_read_sensor_input(client, - COMMMAND1_OPMODE_ALS_ONCE); + lux_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_ALS_ONCE); if (lux_data < 0) return lux_data; - *lux = (lux_data * chip->range * chip->lux_scale) >> chip->adc_bit; + /* To support fractional scaling, separate the unshifted lux + * into two calculations: int scaling and micro-scaling. + * lux_uscale ranges from 0-999999, so about 20 bits. Split + * the /1,000,000 in two to reduce the risk of over/underflow. + */ + data_x_range = lux_data * chip->range; + lux_unshifted = data_x_range * chip->lux_scale; + lux_unshifted += data_x_range / 1000 * chip->lux_uscale / 1000; + *lux = lux_unshifted >> chip->adc_bit; return 0; } -static int isl29018_read_ir(struct i2c_client *client, int *ir) +static int isl29018_read_ir(struct isl29018_chip *chip, int *ir) { int ir_data; - ir_data = isl29018_read_sensor_input(client, COMMMAND1_OPMODE_IR_ONCE); + ir_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_IR_ONCE); if (ir_data < 0) return ir_data; @@ -194,7 +181,7 @@ static int isl29018_read_ir(struct i2c_client *client, int *ir) return 0; } -static int isl29018_read_proximity_ir(struct i2c_client *client, int scheme, +static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme, int *near_ir) { int status; @@ -202,14 +189,15 @@ static int isl29018_read_proximity_ir(struct i2c_client *client, int scheme, 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); + status = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, + COMMANDII_SCHEME_MASK, + scheme << COMMANDII_SCHEME_SHIFT); if (status) { - dev_err(&client->dev, "Error in setting operating mode\n"); + dev_err(chip->dev, "Error in setting operating mode\n"); return status; } - prox_data = isl29018_read_sensor_input(client, + prox_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_PROX_ONCE); if (prox_data < 0) return prox_data; @@ -219,8 +207,7 @@ static int isl29018_read_proximity_ir(struct i2c_client *client, int scheme, return 0; } - ir_data = isl29018_read_sensor_input(client, - COMMMAND1_OPMODE_IR_ONCE); + ir_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_IR_ONCE); if (ir_data < 0) return ir_data; @@ -238,7 +225,7 @@ static int isl29018_read_proximity_ir(struct i2c_client *client, int scheme, static ssize_t show_range(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct isl29018_chip *chip = iio_priv(indio_dev); return sprintf(buf, "%u\n", chip->range); @@ -247,14 +234,13 @@ static ssize_t show_range(struct device *dev, 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 iio_dev *indio_dev = dev_to_iio_dev(dev); struct isl29018_chip *chip = iio_priv(indio_dev); - struct i2c_client *client = chip->client; int status; unsigned long lval; unsigned int new_range; - if (strict_strtoul(buf, 10, &lval)) + if (kstrtoul(buf, 10, &lval)) return -EINVAL; if (!(lval == 1000UL || lval == 4000UL || @@ -264,10 +250,11 @@ static ssize_t store_range(struct device *dev, } mutex_lock(&chip->lock); - status = isl29018_set_range(client, lval, &new_range); + status = isl29018_set_range(chip, lval, &new_range); if (status < 0) { mutex_unlock(&chip->lock); - dev_err(dev, "Error in setting max range\n"); + dev_err(dev, + "Error in setting max range with err %d\n", status); return status; } chip->range = new_range; @@ -280,7 +267,7 @@ static ssize_t store_range(struct device *dev, static ssize_t show_resolution(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct isl29018_chip *chip = iio_priv(indio_dev); return sprintf(buf, "%u\n", chip->adc_bit); @@ -289,22 +276,21 @@ static ssize_t show_resolution(struct device *dev, 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 iio_dev *indio_dev = dev_to_iio_dev(dev); struct isl29018_chip *chip = iio_priv(indio_dev); - struct i2c_client *client = chip->client; int status; - unsigned long lval; + unsigned int val; unsigned int new_adc_bit; - if (strict_strtoul(buf, 10, &lval)) + if (kstrtouint(buf, 10, &val)) return -EINVAL; - if (!(lval == 4 || lval == 8 || lval == 12 || lval == 16)) { + if (!(val == 4 || val == 8 || val == 12 || val == 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); + status = isl29018_set_resolution(chip, val, &new_adc_bit); if (status < 0) { mutex_unlock(&chip->lock); dev_err(dev, "Error in setting resolution\n"); @@ -317,35 +303,35 @@ static ssize_t store_resolution(struct device *dev, } /* proximity scheme */ -static ssize_t show_prox_infrared_supression(struct device *dev, +static ssize_t show_prox_infrared_suppression(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct isl29018_chip *chip = iio_priv(indio_dev); /* return the "proximity scheme" i.e. if the chip does on chip - infrared supression (1 means perform on chip supression) */ + infrared suppression (1 means perform on chip suppression) */ return sprintf(buf, "%d\n", chip->prox_scheme); } -static ssize_t store_prox_infrared_supression(struct device *dev, +static ssize_t store_prox_infrared_suppression(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct isl29018_chip *chip = iio_priv(indio_dev); - unsigned long lval; + int val; - if (strict_strtoul(buf, 10, &lval)) + if (kstrtoint(buf, 10, &val)) return -EINVAL; - if (!(lval == 0UL || lval == 1UL)) { + if (!(val == 0 || val == 1)) { 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) */ + infrared suppression (1 means perform on chip suppression) */ mutex_lock(&chip->lock); - chip->prox_scheme = (int)lval; + chip->prox_scheme = val; mutex_unlock(&chip->lock); return count; @@ -364,11 +350,13 @@ static int isl29018_write_raw(struct iio_dev *indio_dev, mutex_lock(&chip->lock); if (mask == IIO_CHAN_INFO_CALIBSCALE && chan->type == IIO_LIGHT) { chip->lux_scale = val; + /* With no write_raw_get_fmt(), val2 is a MICRO fraction. */ + chip->lux_uscale = val2; ret = 0; } mutex_unlock(&chip->lock); - return 0; + return ret; } static int isl29018_read_raw(struct iio_dev *indio_dev, @@ -379,20 +367,24 @@ static int isl29018_read_raw(struct iio_dev *indio_dev, { int ret = -EINVAL; struct isl29018_chip *chip = iio_priv(indio_dev); - struct i2c_client *client = chip->client; mutex_lock(&chip->lock); + if (chip->suspended) { + mutex_unlock(&chip->lock); + return -EBUSY; + } switch (mask) { - case 0: + case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_PROCESSED: switch (chan->type) { case IIO_LIGHT: - ret = isl29018_read_lux(client, val); + ret = isl29018_read_lux(chip, val); break; case IIO_INTENSITY: - ret = isl29018_read_ir(client, val); + ret = isl29018_read_ir(chip, val); break; case IIO_PROXIMITY: - ret = isl29018_read_proximity_ir(client, + ret = isl29018_read_proximity_ir(chip, chip->prox_scheme, val); break; default: @@ -404,7 +396,8 @@ static int isl29018_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_CALIBSCALE: if (chan->type == IIO_LIGHT) { *val = chip->lux_scale; - ret = IIO_VAL_INT; + *val2 = chip->lux_uscale; + ret = IIO_VAL_INT_PLUS_MICRO; } break; default: @@ -419,15 +412,17 @@ static const struct iio_chan_spec isl29018_channels[] = { .type = IIO_LIGHT, .indexed = 1, .channel = 0, - .processed_val = IIO_PROCESSED, - .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_CALIBSCALE), }, { .type = IIO_INTENSITY, .modified = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .channel2 = IIO_MOD_LIGHT_IR, }, { /* Unindexed in current ABI. But perhaps it should be. */ .type = IIO_PROXIMITY, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), } }; @@ -436,10 +431,10 @@ 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, +static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_suppression, S_IRUGO | S_IWUSR, - show_prox_infrared_supression, - store_prox_infrared_supression, 0); + show_prox_infrared_suppression, + store_prox_infrared_suppression, 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) @@ -448,7 +443,7 @@ static struct attribute *isl29018_attributes[] = { 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(proximity_on_chip_ambient_infrared_suppression), NULL }; @@ -456,15 +451,12 @@ static const struct attribute_group isl29108_group = { .attrs = isl29018_attributes, }; -static int isl29018_chip_init(struct i2c_client *client) +static int isl29018_chip_init(struct isl29018_chip *chip) { - struct isl29018_chip *chip = iio_priv(i2c_get_clientdata(client)); int status; int new_adc_bit; unsigned int new_range; - memset(chip->reg_cache, 0, sizeof(chip->reg_cache)); - /* Code added per Intersil Application Note 1534: * When VDD sinks to approximately 1.8V or below, some of * the part's registers may change their state. When VDD @@ -485,10 +477,9 @@ static int isl29018_chip_init(struct i2c_client *client) * the same thing EXCEPT the data sheet asks for a 1ms delay after * writing the CMD1 register. */ - status = isl29018_write_data(client, ISL29018_REG_TEST, 0, - ISL29018_TEST_MASK, ISL29018_TEST_SHIFT); + status = regmap_write(chip->regmap, ISL29018_REG_TEST, 0x0); if (status < 0) { - dev_err(&client->dev, "Failed to clear isl29018 TEST reg." + dev_err(chip->dev, "Failed to clear isl29018 TEST reg." "(%d)\n", status); return status; } @@ -497,10 +488,9 @@ static int isl29018_chip_init(struct i2c_client *client) * "Operating Mode" (COMMAND1) register is reprogrammed when * data is read from the device. */ - status = isl29018_write_data(client, ISL29018_REG_ADD_COMMAND1, 0, - 0xff, 0); + status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1, 0); if (status < 0) { - dev_err(&client->dev, "Failed to clear isl29018 CMD1 reg." + dev_err(chip->dev, "Failed to clear isl29018 CMD1 reg." "(%d)\n", status); return status; } @@ -508,13 +498,13 @@ static int isl29018_chip_init(struct i2c_client *client) msleep(1); /* per data sheet, page 10 */ /* set defaults */ - status = isl29018_set_range(client, chip->range, &new_range); + status = isl29018_set_range(chip, chip->range, &new_range); if (status < 0) { - dev_err(&client->dev, "Init of isl29018 fails\n"); + dev_err(chip->dev, "Init of isl29018 fails\n"); return status; } - status = isl29018_set_resolution(client, chip->adc_bit, + status = isl29018_set_resolution(chip, chip->adc_bit, &new_adc_bit); return 0; @@ -527,33 +517,67 @@ static const struct iio_info isl29108_info = { .write_raw = &isl29018_write_raw, }; -static int __devinit isl29018_probe(struct i2c_client *client, +static bool is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ISL29018_REG_ADD_DATA_LSB: + case ISL29018_REG_ADD_DATA_MSB: + case ISL29018_REG_ADD_COMMAND1: + case ISL29018_REG_TEST: + return true; + default: + return false; + } +} + +/* + * isl29018_regmap_config: regmap configuration. + * Use RBTREE mechanism for caching. + */ +static const struct regmap_config isl29018_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .volatile_reg = is_volatile_reg, + .max_register = ISL29018_REG_TEST, + .num_reg_defaults_raw = ISL29018_REG_TEST + 1, + .cache_type = REGCACHE_RBTREE, +}; + +static int isl29018_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct isl29018_chip *chip; struct iio_dev *indio_dev; int err; - indio_dev = iio_allocate_device(sizeof(*chip)); + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); if (indio_dev == NULL) { dev_err(&client->dev, "iio allocation fails\n"); - err = -ENOMEM; - goto exit; + return -ENOMEM; } chip = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); - chip->client = client; + chip->dev = &client->dev; mutex_init(&chip->lock); chip->lux_scale = 1; + chip->lux_uscale = 0; chip->range = 1000; chip->adc_bit = 16; + chip->suspended = false; + + chip->regmap = devm_regmap_init_i2c(client, &isl29018_regmap_config); + if (IS_ERR(chip->regmap)) { + err = PTR_ERR(chip->regmap); + dev_err(chip->dev, "regmap initialization failed: %d\n", err); + return err; + } - err = isl29018_chip_init(client); + err = isl29018_chip_init(chip); if (err) - goto exit_iio_free; + return err; indio_dev->info = &isl29108_info; indio_dev->channels = isl29018_channels; @@ -561,30 +585,53 @@ static int __devinit isl29018_probe(struct i2c_client *client, indio_dev->name = id->name; indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; - err = iio_device_register(indio_dev); + err = devm_iio_device_register(&client->dev, indio_dev); if (err) { dev_err(&client->dev, "iio registration fails\n"); - goto exit_iio_free; + return err; } return 0; -exit_iio_free: - iio_free_device(indio_dev); -exit: - return err; } -static int __devexit isl29018_remove(struct i2c_client *client) +#ifdef CONFIG_PM_SLEEP +static int isl29018_suspend(struct device *dev) { - struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev)); + + mutex_lock(&chip->lock); - dev_dbg(&client->dev, "%s()\n", __func__); - iio_device_unregister(indio_dev); - iio_free_device(indio_dev); + /* Since this driver uses only polling commands, we are by default in + * auto shutdown (ie, power-down) mode. + * So we do not have much to do here. + */ + chip->suspended = true; + mutex_unlock(&chip->lock); return 0; } +static int isl29018_resume(struct device *dev) +{ + struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev)); + int err; + + mutex_lock(&chip->lock); + + err = isl29018_chip_init(chip); + if (!err) + chip->suspended = false; + + mutex_unlock(&chip->lock); + return err; +} + +static SIMPLE_DEV_PM_OPS(isl29018_pm_ops, isl29018_suspend, isl29018_resume); +#define ISL29018_PM_OPS (&isl29018_pm_ops) +#else +#define ISL29018_PM_OPS NULL +#endif + static const struct i2c_device_id isl29018_id[] = { {"isl29018", 0}, {} @@ -592,14 +639,21 @@ static const struct i2c_device_id isl29018_id[] = { MODULE_DEVICE_TABLE(i2c, isl29018_id); +static const struct of_device_id isl29018_of_match[] = { + { .compatible = "isil,isl29018", }, + { }, +}; +MODULE_DEVICE_TABLE(of, isl29018_of_match); + static struct i2c_driver isl29018_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "isl29018", + .pm = ISL29018_PM_OPS, .owner = THIS_MODULE, + .of_match_table = isl29018_of_match, }, .probe = isl29018_probe, - .remove = __devexit_p(isl29018_remove), .id_table = isl29018_id, }; module_i2c_driver(isl29018_driver); diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c new file mode 100644 index 00000000000..6014625920b --- /dev/null +++ b/drivers/staging/iio/light/isl29028.c @@ -0,0 +1,561 @@ +/* + * IIO driver for the light sensor ISL29028. + * ISL29028 is Concurrent Ambient Light and Proximity Sensor + * + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>. + */ + +#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 <linux/regmap.h> +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> + +#define CONVERSION_TIME_MS 100 + +#define ISL29028_REG_CONFIGURE 0x01 + +#define CONFIGURE_ALS_IR_MODE_ALS 0 +#define CONFIGURE_ALS_IR_MODE_IR BIT(0) +#define CONFIGURE_ALS_IR_MODE_MASK BIT(0) + +#define CONFIGURE_ALS_RANGE_LOW_LUX 0 +#define CONFIGURE_ALS_RANGE_HIGH_LUX BIT(1) +#define CONFIGURE_ALS_RANGE_MASK BIT(1) + +#define CONFIGURE_ALS_DIS 0 +#define CONFIGURE_ALS_EN BIT(2) +#define CONFIGURE_ALS_EN_MASK BIT(2) + +#define CONFIGURE_PROX_DRIVE BIT(3) + +#define CONFIGURE_PROX_SLP_SH 4 +#define CONFIGURE_PROX_SLP_MASK (7 << CONFIGURE_PROX_SLP_SH) + +#define CONFIGURE_PROX_EN BIT(7) +#define CONFIGURE_PROX_EN_MASK BIT(7) + +#define ISL29028_REG_INTERRUPT 0x02 + +#define ISL29028_REG_PROX_DATA 0x08 +#define ISL29028_REG_ALSIR_L 0x09 +#define ISL29028_REG_ALSIR_U 0x0A + +#define ISL29028_REG_TEST1_MODE 0x0E +#define ISL29028_REG_TEST2_MODE 0x0F + +#define ISL29028_NUM_REGS (ISL29028_REG_TEST2_MODE + 1) + +enum als_ir_mode { + MODE_NONE = 0, + MODE_ALS, + MODE_IR +}; + +struct isl29028_chip { + struct device *dev; + struct mutex lock; + struct regmap *regmap; + + unsigned int prox_sampling; + bool enable_prox; + + int lux_scale; + int als_ir_mode; +}; + +static int isl29028_set_proxim_sampling(struct isl29028_chip *chip, + unsigned int sampling) +{ + static unsigned int prox_period[] = {800, 400, 200, 100, 75, 50, 12, 0}; + int sel; + unsigned int period = DIV_ROUND_UP(1000, sampling); + + for (sel = 0; sel < ARRAY_SIZE(prox_period); ++sel) { + if (period >= prox_period[sel]) + break; + } + return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, + CONFIGURE_PROX_SLP_MASK, sel << CONFIGURE_PROX_SLP_SH); +} + +static int isl29028_enable_proximity(struct isl29028_chip *chip, bool enable) +{ + int ret; + int val = 0; + + if (enable) + val = CONFIGURE_PROX_EN; + ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, + CONFIGURE_PROX_EN_MASK, val); + if (ret < 0) + return ret; + + /* Wait for conversion to be complete for first sample */ + mdelay(DIV_ROUND_UP(1000, chip->prox_sampling)); + return 0; +} + +static int isl29028_set_als_scale(struct isl29028_chip *chip, int lux_scale) +{ + int val = (lux_scale == 2000) ? CONFIGURE_ALS_RANGE_HIGH_LUX : + CONFIGURE_ALS_RANGE_LOW_LUX; + + return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, + CONFIGURE_ALS_RANGE_MASK, val); +} + +static int isl29028_set_als_ir_mode(struct isl29028_chip *chip, + enum als_ir_mode mode) +{ + int ret = 0; + + switch (mode) { + case MODE_ALS: + ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, + CONFIGURE_ALS_IR_MODE_MASK, CONFIGURE_ALS_IR_MODE_ALS); + if (ret < 0) + return ret; + + ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, + CONFIGURE_ALS_RANGE_MASK, CONFIGURE_ALS_RANGE_HIGH_LUX); + break; + + case MODE_IR: + ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, + CONFIGURE_ALS_IR_MODE_MASK, CONFIGURE_ALS_IR_MODE_IR); + break; + + case MODE_NONE: + return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, + CONFIGURE_ALS_EN_MASK, CONFIGURE_ALS_DIS); + } + + if (ret < 0) + return ret; + + /* Enable the ALS/IR */ + ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, + CONFIGURE_ALS_EN_MASK, CONFIGURE_ALS_EN); + if (ret < 0) + return ret; + + /* Need to wait for conversion time if ALS/IR mode enabled */ + mdelay(CONVERSION_TIME_MS); + return 0; +} + +static int isl29028_read_als_ir(struct isl29028_chip *chip, int *als_ir) +{ + unsigned int lsb; + unsigned int msb; + int ret; + + ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_L, &lsb); + if (ret < 0) { + dev_err(chip->dev, + "Error in reading register ALSIR_L err %d\n", ret); + return ret; + } + + ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_U, &msb); + if (ret < 0) { + dev_err(chip->dev, + "Error in reading register ALSIR_U err %d\n", ret); + return ret; + } + + *als_ir = ((msb & 0xF) << 8) | (lsb & 0xFF); + return 0; +} + +static int isl29028_read_proxim(struct isl29028_chip *chip, int *prox) +{ + unsigned int data; + int ret; + + ret = regmap_read(chip->regmap, ISL29028_REG_PROX_DATA, &data); + if (ret < 0) { + dev_err(chip->dev, "Error in reading register %d, error %d\n", + ISL29028_REG_PROX_DATA, ret); + return ret; + } + *prox = data; + return 0; +} + +static int isl29028_proxim_get(struct isl29028_chip *chip, int *prox_data) +{ + int ret; + + if (!chip->enable_prox) { + ret = isl29028_enable_proximity(chip, true); + if (ret < 0) + return ret; + chip->enable_prox = true; + } + return isl29028_read_proxim(chip, prox_data); +} + +static int isl29028_als_get(struct isl29028_chip *chip, int *als_data) +{ + int ret; + int als_ir_data; + + if (chip->als_ir_mode != MODE_ALS) { + ret = isl29028_set_als_ir_mode(chip, MODE_ALS); + if (ret < 0) { + dev_err(chip->dev, + "Error in enabling ALS mode err %d\n", ret); + return ret; + } + chip->als_ir_mode = MODE_ALS; + } + + ret = isl29028_read_als_ir(chip, &als_ir_data); + if (ret < 0) + return ret; + + /* + * convert als data count to lux. + * if lux_scale = 125, lux = count * 0.031 + * if lux_scale = 2000, lux = count * 0.49 + */ + if (chip->lux_scale == 125) + als_ir_data = (als_ir_data * 31) / 1000; + else + als_ir_data = (als_ir_data * 49) / 100; + + *als_data = als_ir_data; + return 0; +} + +static int isl29028_ir_get(struct isl29028_chip *chip, int *ir_data) +{ + int ret; + + if (chip->als_ir_mode != MODE_IR) { + ret = isl29028_set_als_ir_mode(chip, MODE_IR); + if (ret < 0) { + dev_err(chip->dev, + "Error in enabling IR mode err %d\n", ret); + return ret; + } + chip->als_ir_mode = MODE_IR; + } + return isl29028_read_als_ir(chip, ir_data); +} + +/* Channel IO */ +static int isl29028_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long mask) +{ + struct isl29028_chip *chip = iio_priv(indio_dev); + int ret = -EINVAL; + + mutex_lock(&chip->lock); + switch (chan->type) { + case IIO_PROXIMITY: + if (mask != IIO_CHAN_INFO_SAMP_FREQ) { + dev_err(chip->dev, + "proximity: mask value 0x%08lx not supported\n", + mask); + break; + } + if (val < 1 || val > 100) { + dev_err(chip->dev, + "Samp_freq %d is not in range[1:100]\n", val); + break; + } + ret = isl29028_set_proxim_sampling(chip, val); + if (ret < 0) { + dev_err(chip->dev, + "Setting proximity samp_freq fail, err %d\n", + ret); + break; + } + chip->prox_sampling = val; + break; + + case IIO_LIGHT: + if (mask != IIO_CHAN_INFO_SCALE) { + dev_err(chip->dev, + "light: mask value 0x%08lx not supported\n", + mask); + break; + } + if ((val != 125) && (val != 2000)) { + dev_err(chip->dev, + "lux scale %d is invalid [125, 2000]\n", val); + break; + } + ret = isl29028_set_als_scale(chip, val); + if (ret < 0) { + dev_err(chip->dev, + "Setting lux scale fail with error %d\n", ret); + break; + } + chip->lux_scale = val; + break; + + default: + dev_err(chip->dev, "Unsupported channel type\n"); + break; + } + mutex_unlock(&chip->lock); + return ret; +} + +static int isl29028_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, long mask) +{ + struct isl29028_chip *chip = iio_priv(indio_dev); + int ret = -EINVAL; + + mutex_lock(&chip->lock); + switch (mask) { + case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_PROCESSED: + switch (chan->type) { + case IIO_LIGHT: + ret = isl29028_als_get(chip, val); + break; + case IIO_INTENSITY: + ret = isl29028_ir_get(chip, val); + break; + case IIO_PROXIMITY: + ret = isl29028_proxim_get(chip, val); + break; + default: + break; + } + if (ret < 0) + break; + ret = IIO_VAL_INT; + break; + + case IIO_CHAN_INFO_SAMP_FREQ: + if (chan->type != IIO_PROXIMITY) + break; + *val = chip->prox_sampling; + ret = IIO_VAL_INT; + break; + + case IIO_CHAN_INFO_SCALE: + if (chan->type != IIO_LIGHT) + break; + *val = chip->lux_scale; + ret = IIO_VAL_INT; + break; + + default: + dev_err(chip->dev, "mask value 0x%08lx not supported\n", mask); + break; + } + mutex_unlock(&chip->lock); + return ret; +} + +static IIO_CONST_ATTR(in_proximity_sampling_frequency_available, + "1, 3, 5, 10, 13, 20, 83, 100"); +static IIO_CONST_ATTR(in_illuminance_scale_available, "125, 2000"); + +#define ISL29028_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr) +#define ISL29028_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr) +static struct attribute *isl29028_attributes[] = { + ISL29028_CONST_ATTR(in_proximity_sampling_frequency_available), + ISL29028_CONST_ATTR(in_illuminance_scale_available), + NULL, +}; + +static const struct attribute_group isl29108_group = { + .attrs = isl29028_attributes, +}; + +static const struct iio_chan_spec isl29028_channels[] = { + { + .type = IIO_LIGHT, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_SCALE), + }, { + .type = IIO_INTENSITY, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + }, { + .type = IIO_PROXIMITY, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SAMP_FREQ), + } +}; + +static const struct iio_info isl29028_info = { + .attrs = &isl29108_group, + .driver_module = THIS_MODULE, + .read_raw = &isl29028_read_raw, + .write_raw = &isl29028_write_raw, +}; + +static int isl29028_chip_init(struct isl29028_chip *chip) +{ + int ret; + + chip->enable_prox = false; + chip->prox_sampling = 20; + chip->lux_scale = 2000; + chip->als_ir_mode = MODE_NONE; + + ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0); + if (ret < 0) { + dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n", + __func__, ISL29028_REG_TEST1_MODE, ret); + return ret; + } + ret = regmap_write(chip->regmap, ISL29028_REG_TEST2_MODE, 0x0); + if (ret < 0) { + dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n", + __func__, ISL29028_REG_TEST2_MODE, ret); + return ret; + } + + ret = regmap_write(chip->regmap, ISL29028_REG_CONFIGURE, 0x0); + if (ret < 0) { + dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n", + __func__, ISL29028_REG_CONFIGURE, ret); + return ret; + } + + ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling); + if (ret < 0) { + dev_err(chip->dev, "%s(): setting the proximity, err = %d\n", + __func__, ret); + return ret; + } + + ret = isl29028_set_als_scale(chip, chip->lux_scale); + if (ret < 0) + dev_err(chip->dev, "%s(): setting als scale failed, err = %d\n", + __func__, ret); + return ret; +} + +static bool is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ISL29028_REG_INTERRUPT: + case ISL29028_REG_PROX_DATA: + case ISL29028_REG_ALSIR_L: + case ISL29028_REG_ALSIR_U: + return true; + default: + return false; + } +} + +static const struct regmap_config isl29028_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .volatile_reg = is_volatile_reg, + .max_register = ISL29028_NUM_REGS - 1, + .num_reg_defaults_raw = ISL29028_NUM_REGS, + .cache_type = REGCACHE_RBTREE, +}; + +static int isl29028_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct isl29028_chip *chip; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); + if (!indio_dev) { + dev_err(&client->dev, "iio allocation fails\n"); + return -ENOMEM; + } + + chip = iio_priv(indio_dev); + + i2c_set_clientdata(client, indio_dev); + chip->dev = &client->dev; + mutex_init(&chip->lock); + + chip->regmap = devm_regmap_init_i2c(client, &isl29028_regmap_config); + if (IS_ERR(chip->regmap)) { + ret = PTR_ERR(chip->regmap); + dev_err(chip->dev, "regmap initialization failed: %d\n", ret); + return ret; + } + + ret = isl29028_chip_init(chip); + if (ret < 0) { + dev_err(chip->dev, "chip initialization failed: %d\n", ret); + return ret; + } + + indio_dev->info = &isl29028_info; + indio_dev->channels = isl29028_channels; + indio_dev->num_channels = ARRAY_SIZE(isl29028_channels); + indio_dev->name = id->name; + indio_dev->dev.parent = &client->dev; + indio_dev->modes = INDIO_DIRECT_MODE; + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(chip->dev, "iio registration fails with error %d\n", + ret); + return ret; + } + return 0; +} + +static int isl29028_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + return 0; +} + +static const struct i2c_device_id isl29028_id[] = { + {"isl29028", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, isl29028_id); + +static const struct of_device_id isl29028_of_match[] = { + { .compatible = "isil,isl29028", }, + { }, +}; +MODULE_DEVICE_TABLE(of, isl29028_of_match); + +static struct i2c_driver isl29028_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "isl29028", + .owner = THIS_MODULE, + .of_match_table = isl29028_of_match, + }, + .probe = isl29028_probe, + .remove = isl29028_remove, + .id_table = isl29028_id, +}; + +module_i2c_driver(isl29028_driver); + +MODULE_DESCRIPTION("ISL29028 Ambient Light and Proximity Sensor driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c deleted file mode 100644 index ffca85e81ef..00000000000 --- a/drivers/staging/iio/light/tsl2563.c +++ /dev/null @@ -1,876 +0,0 @@ -/* - * drivers/i2c/chips/tsl2563.c - * - * Copyright (C) 2008 Nokia Corporation - * - * Written by Timo O. Karjalainen <timo.o.karjalainen@nokia.com> - * Contact: Amit Kucheria <amit.kucheria@verdurent.com> - * - * Converted to IIO driver - * Amit Kucheria <amit.kucheria@verdurent.com> - * - * 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 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 St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#include <linux/module.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/sched.h> -#include <linux/mutex.h> -#include <linux/delay.h> -#include <linux/pm.h> -#include <linux/err.h> -#include <linux/slab.h> - -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" -#include "tsl2563.h" - -/* Use this many bits for fraction part. */ -#define ADC_FRAC_BITS (14) - -/* Given number of 1/10000's in ADC_FRAC_BITS precision. */ -#define FRAC10K(f) (((f) * (1L << (ADC_FRAC_BITS))) / (10000)) - -/* Bits used for fraction in calibration coefficients.*/ -#define CALIB_FRAC_BITS (10) -/* 0.5 in CALIB_FRAC_BITS precision */ -#define CALIB_FRAC_HALF (1 << (CALIB_FRAC_BITS - 1)) -/* Make a fraction from a number n that was multiplied with b. */ -#define CALIB_FRAC(n, b) (((n) << CALIB_FRAC_BITS) / (b)) -/* Decimal 10^(digits in sysfs presentation) */ -#define CALIB_BASE_SYSFS (1000) - -#define TSL2563_CMD (0x80) -#define TSL2563_CLEARINT (0x40) - -#define TSL2563_REG_CTRL (0x00) -#define TSL2563_REG_TIMING (0x01) -#define TSL2563_REG_LOWLOW (0x02) /* data0 low threshold, 2 bytes */ -#define TSL2563_REG_LOWHIGH (0x03) -#define TSL2563_REG_HIGHLOW (0x04) /* data0 high threshold, 2 bytes */ -#define TSL2563_REG_HIGHHIGH (0x05) -#define TSL2563_REG_INT (0x06) -#define TSL2563_REG_ID (0x0a) -#define TSL2563_REG_DATA0LOW (0x0c) /* broadband sensor value, 2 bytes */ -#define TSL2563_REG_DATA0HIGH (0x0d) -#define TSL2563_REG_DATA1LOW (0x0e) /* infrared sensor value, 2 bytes */ -#define TSL2563_REG_DATA1HIGH (0x0f) - -#define TSL2563_CMD_POWER_ON (0x03) -#define TSL2563_CMD_POWER_OFF (0x00) -#define TSL2563_CTRL_POWER_MASK (0x03) - -#define TSL2563_TIMING_13MS (0x00) -#define TSL2563_TIMING_100MS (0x01) -#define TSL2563_TIMING_400MS (0x02) -#define TSL2563_TIMING_MASK (0x03) -#define TSL2563_TIMING_GAIN16 (0x10) -#define TSL2563_TIMING_GAIN1 (0x00) - -#define TSL2563_INT_DISBLED (0x00) -#define TSL2563_INT_LEVEL (0x10) -#define TSL2563_INT_PERSIST(n) ((n) & 0x0F) - -struct tsl2563_gainlevel_coeff { - u8 gaintime; - u16 min; - u16 max; -}; - -static const struct tsl2563_gainlevel_coeff tsl2563_gainlevel_table[] = { - { - .gaintime = TSL2563_TIMING_400MS | TSL2563_TIMING_GAIN16, - .min = 0, - .max = 65534, - }, { - .gaintime = TSL2563_TIMING_400MS | TSL2563_TIMING_GAIN1, - .min = 2048, - .max = 65534, - }, { - .gaintime = TSL2563_TIMING_100MS | TSL2563_TIMING_GAIN1, - .min = 4095, - .max = 37177, - }, { - .gaintime = TSL2563_TIMING_13MS | TSL2563_TIMING_GAIN1, - .min = 3000, - .max = 65535, - }, -}; - -struct tsl2563_chip { - struct mutex lock; - struct i2c_client *client; - struct delayed_work poweroff_work; - - /* Remember state for suspend and resume functions */ - pm_message_t state; - - struct tsl2563_gainlevel_coeff const *gainlevel; - - u16 low_thres; - u16 high_thres; - u8 intr; - bool int_enabled; - - /* Calibration coefficients */ - u32 calib0; - u32 calib1; - int cover_comp_gain; - - /* Cache current values, to be returned while suspended */ - u32 data0; - u32 data1; -}; - -static int tsl2563_set_power(struct tsl2563_chip *chip, int on) -{ - struct i2c_client *client = chip->client; - u8 cmd; - - cmd = on ? TSL2563_CMD_POWER_ON : TSL2563_CMD_POWER_OFF; - return i2c_smbus_write_byte_data(client, - TSL2563_CMD | TSL2563_REG_CTRL, cmd); -} - -/* - * Return value is 0 for off, 1 for on, or a negative error - * code if reading failed. - */ -static int tsl2563_get_power(struct tsl2563_chip *chip) -{ - struct i2c_client *client = chip->client; - int ret; - - ret = i2c_smbus_read_byte_data(client, TSL2563_CMD | TSL2563_REG_CTRL); - if (ret < 0) - return ret; - - return (ret & TSL2563_CTRL_POWER_MASK) == TSL2563_CMD_POWER_ON; -} - -static int tsl2563_configure(struct tsl2563_chip *chip) -{ - int ret; - - ret = i2c_smbus_write_byte_data(chip->client, - TSL2563_CMD | TSL2563_REG_TIMING, - chip->gainlevel->gaintime); - if (ret) - goto error_ret; - ret = i2c_smbus_write_byte_data(chip->client, - TSL2563_CMD | TSL2563_REG_HIGHLOW, - chip->high_thres & 0xFF); - if (ret) - goto error_ret; - ret = i2c_smbus_write_byte_data(chip->client, - TSL2563_CMD | TSL2563_REG_HIGHHIGH, - (chip->high_thres >> 8) & 0xFF); - if (ret) - goto error_ret; - ret = i2c_smbus_write_byte_data(chip->client, - TSL2563_CMD | TSL2563_REG_LOWLOW, - chip->low_thres & 0xFF); - if (ret) - goto error_ret; - ret = i2c_smbus_write_byte_data(chip->client, - TSL2563_CMD | TSL2563_REG_LOWHIGH, - (chip->low_thres >> 8) & 0xFF); -/* Interrupt register is automatically written anyway if it is relevant - so is not here */ -error_ret: - return ret; -} - -static void tsl2563_poweroff_work(struct work_struct *work) -{ - struct tsl2563_chip *chip = - container_of(work, struct tsl2563_chip, poweroff_work.work); - tsl2563_set_power(chip, 0); -} - -static int tsl2563_detect(struct tsl2563_chip *chip) -{ - int ret; - - ret = tsl2563_set_power(chip, 1); - if (ret) - return ret; - - ret = tsl2563_get_power(chip); - if (ret < 0) - return ret; - - return ret ? 0 : -ENODEV; -} - -static int tsl2563_read_id(struct tsl2563_chip *chip, u8 *id) -{ - struct i2c_client *client = chip->client; - int ret; - - ret = i2c_smbus_read_byte_data(client, TSL2563_CMD | TSL2563_REG_ID); - if (ret < 0) - return ret; - - *id = ret; - - return 0; -} - -/* - * "Normalized" ADC value is one obtained with 400ms of integration time and - * 16x gain. This function returns the number of bits of shift needed to - * convert between normalized values and HW values obtained using given - * timing and gain settings. - */ -static int adc_shiftbits(u8 timing) -{ - int shift = 0; - - switch (timing & TSL2563_TIMING_MASK) { - case TSL2563_TIMING_13MS: - shift += 5; - break; - case TSL2563_TIMING_100MS: - shift += 2; - break; - case TSL2563_TIMING_400MS: - /* no-op */ - break; - } - - if (!(timing & TSL2563_TIMING_GAIN16)) - shift += 4; - - return shift; -} - -/* Convert a HW ADC value to normalized scale. */ -static u32 normalize_adc(u16 adc, u8 timing) -{ - return adc << adc_shiftbits(timing); -} - -static void tsl2563_wait_adc(struct tsl2563_chip *chip) -{ - unsigned int delay; - - switch (chip->gainlevel->gaintime & TSL2563_TIMING_MASK) { - case TSL2563_TIMING_13MS: - delay = 14; - break; - case TSL2563_TIMING_100MS: - delay = 101; - break; - default: - delay = 402; - } - /* - * TODO: Make sure that we wait at least required delay but why we - * have to extend it one tick more? - */ - schedule_timeout_interruptible(msecs_to_jiffies(delay) + 2); -} - -static int tsl2563_adjust_gainlevel(struct tsl2563_chip *chip, u16 adc) -{ - struct i2c_client *client = chip->client; - - if (adc > chip->gainlevel->max || adc < chip->gainlevel->min) { - - (adc > chip->gainlevel->max) ? - chip->gainlevel++ : chip->gainlevel--; - - i2c_smbus_write_byte_data(client, - TSL2563_CMD | TSL2563_REG_TIMING, - chip->gainlevel->gaintime); - - tsl2563_wait_adc(chip); - tsl2563_wait_adc(chip); - - return 1; - } else - return 0; -} - -static int tsl2563_get_adc(struct tsl2563_chip *chip) -{ - struct i2c_client *client = chip->client; - u16 adc0, adc1; - int retry = 1; - int ret = 0; - - if (chip->state.event != PM_EVENT_ON) - goto out; - - if (!chip->int_enabled) { - cancel_delayed_work(&chip->poweroff_work); - - if (!tsl2563_get_power(chip)) { - ret = tsl2563_set_power(chip, 1); - if (ret) - goto out; - ret = tsl2563_configure(chip); - if (ret) - goto out; - tsl2563_wait_adc(chip); - } - } - - while (retry) { - ret = i2c_smbus_read_word_data(client, - TSL2563_CMD | TSL2563_REG_DATA0LOW); - if (ret < 0) - goto out; - adc0 = ret; - - ret = i2c_smbus_read_word_data(client, - TSL2563_CMD | TSL2563_REG_DATA1LOW); - if (ret < 0) - goto out; - adc1 = ret; - - retry = tsl2563_adjust_gainlevel(chip, adc0); - } - - chip->data0 = normalize_adc(adc0, chip->gainlevel->gaintime); - chip->data1 = normalize_adc(adc1, chip->gainlevel->gaintime); - - if (!chip->int_enabled) - schedule_delayed_work(&chip->poweroff_work, 5 * HZ); - - ret = 0; -out: - return ret; -} - -static inline int calib_to_sysfs(u32 calib) -{ - return (int) (((calib * CALIB_BASE_SYSFS) + - CALIB_FRAC_HALF) >> CALIB_FRAC_BITS); -} - -static inline u32 calib_from_sysfs(int value) -{ - return (((u32) value) << CALIB_FRAC_BITS) / CALIB_BASE_SYSFS; -} - -/* - * Conversions between lux and ADC values. - * - * The basic formula is lux = c0 * adc0 - c1 * adc1, where c0 and c1 are - * appropriate constants. Different constants are needed for different - * kinds of light, determined by the ratio adc1/adc0 (basically the ratio - * of the intensities in infrared and visible wavelengths). lux_table below - * lists the upper threshold of the adc1/adc0 ratio and the corresponding - * constants. - */ - -struct tsl2563_lux_coeff { - unsigned long ch_ratio; - unsigned long ch0_coeff; - unsigned long ch1_coeff; -}; - -static const struct tsl2563_lux_coeff lux_table[] = { - { - .ch_ratio = FRAC10K(1300), - .ch0_coeff = FRAC10K(315), - .ch1_coeff = FRAC10K(262), - }, { - .ch_ratio = FRAC10K(2600), - .ch0_coeff = FRAC10K(337), - .ch1_coeff = FRAC10K(430), - }, { - .ch_ratio = FRAC10K(3900), - .ch0_coeff = FRAC10K(363), - .ch1_coeff = FRAC10K(529), - }, { - .ch_ratio = FRAC10K(5200), - .ch0_coeff = FRAC10K(392), - .ch1_coeff = FRAC10K(605), - }, { - .ch_ratio = FRAC10K(6500), - .ch0_coeff = FRAC10K(229), - .ch1_coeff = FRAC10K(291), - }, { - .ch_ratio = FRAC10K(8000), - .ch0_coeff = FRAC10K(157), - .ch1_coeff = FRAC10K(180), - }, { - .ch_ratio = FRAC10K(13000), - .ch0_coeff = FRAC10K(34), - .ch1_coeff = FRAC10K(26), - }, { - .ch_ratio = ULONG_MAX, - .ch0_coeff = 0, - .ch1_coeff = 0, - }, -}; - -/* - * Convert normalized, scaled ADC values to lux. - */ -static unsigned int adc_to_lux(u32 adc0, u32 adc1) -{ - const struct tsl2563_lux_coeff *lp = lux_table; - unsigned long ratio, lux, ch0 = adc0, ch1 = adc1; - - ratio = ch0 ? ((ch1 << ADC_FRAC_BITS) / ch0) : ULONG_MAX; - - while (lp->ch_ratio < ratio) - lp++; - - lux = ch0 * lp->ch0_coeff - ch1 * lp->ch1_coeff; - - return (unsigned int) (lux >> ADC_FRAC_BITS); -} - -/*--------------------------------------------------------------*/ -/* Sysfs interface */ -/*--------------------------------------------------------------*/ - - -/* Apply calibration coefficient to ADC count. */ -static u32 calib_adc(u32 adc, u32 calib) -{ - unsigned long scaled = adc; - - scaled *= calib; - scaled >>= CALIB_FRAC_BITS; - - return (u32) scaled; -} - -static int tsl2563_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct tsl2563_chip *chip = iio_priv(indio_dev); - - if (chan->channel == 0) - chip->calib0 = calib_from_sysfs(val); - else - chip->calib1 = calib_from_sysfs(val); - - return 0; -} - -static int tsl2563_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - int ret = -EINVAL; - u32 calib0, calib1; - struct tsl2563_chip *chip = iio_priv(indio_dev); - - mutex_lock(&chip->lock); - switch (m) { - case 0: - switch (chan->type) { - case IIO_LIGHT: - ret = tsl2563_get_adc(chip); - if (ret) - goto error_ret; - calib0 = calib_adc(chip->data0, chip->calib0) * - chip->cover_comp_gain; - calib1 = calib_adc(chip->data1, chip->calib1) * - chip->cover_comp_gain; - *val = adc_to_lux(calib0, calib1); - ret = IIO_VAL_INT; - break; - case IIO_INTENSITY: - ret = tsl2563_get_adc(chip); - if (ret) - goto error_ret; - if (chan->channel == 0) - *val = chip->data0; - else - *val = chip->data1; - ret = IIO_VAL_INT; - break; - default: - break; - } - break; - - case IIO_CHAN_INFO_CALIBSCALE: - if (chan->channel == 0) - *val = calib_to_sysfs(chip->calib0); - else - *val = calib_to_sysfs(chip->calib1); - ret = IIO_VAL_INT; - break; - default: - ret = -EINVAL; - goto error_ret; - } - -error_ret: - mutex_unlock(&chip->lock); - return ret; -} - -static const struct iio_chan_spec tsl2563_channels[] = { - { - .type = IIO_LIGHT, - .indexed = 1, - .channel = 0, - }, { - .type = IIO_INTENSITY, - .modified = 1, - .channel2 = IIO_MOD_LIGHT_BOTH, - .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, - .event_mask = (IIO_EV_BIT(IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING) | - IIO_EV_BIT(IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING)), - }, { - .type = IIO_INTENSITY, - .modified = 1, - .channel2 = IIO_MOD_LIGHT_IR, - .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, - } -}; - -static int tsl2563_read_thresh(struct iio_dev *indio_dev, - u64 event_code, - int *val) -{ - struct tsl2563_chip *chip = iio_priv(indio_dev); - - switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) { - case IIO_EV_DIR_RISING: - *val = chip->high_thres; - break; - case IIO_EV_DIR_FALLING: - *val = chip->low_thres; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int tsl2563_write_thresh(struct iio_dev *indio_dev, - u64 event_code, - int val) -{ - struct tsl2563_chip *chip = iio_priv(indio_dev); - int ret; - u8 address; - - if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING) - address = TSL2563_REG_HIGHLOW; - else - address = TSL2563_REG_LOWLOW; - mutex_lock(&chip->lock); - ret = i2c_smbus_write_byte_data(chip->client, TSL2563_CMD | address, - val & 0xFF); - if (ret) - goto error_ret; - ret = i2c_smbus_write_byte_data(chip->client, - TSL2563_CMD | (address + 1), - (val >> 8) & 0xFF); - if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING) - chip->high_thres = val; - else - chip->low_thres = val; - -error_ret: - mutex_unlock(&chip->lock); - - return ret; -} - -static irqreturn_t tsl2563_event_handler(int irq, void *private) -{ - struct iio_dev *dev_info = private; - struct tsl2563_chip *chip = iio_priv(dev_info); - - iio_push_event(dev_info, - IIO_UNMOD_EVENT_CODE(IIO_LIGHT, - 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_EITHER), - iio_get_time_ns()); - - /* clear the interrupt and push the event */ - i2c_smbus_write_byte(chip->client, TSL2563_CMD | TSL2563_CLEARINT); - return IRQ_HANDLED; -} - -static int tsl2563_write_interrupt_config(struct iio_dev *indio_dev, - u64 event_code, - int state) -{ - struct tsl2563_chip *chip = iio_priv(indio_dev); - int ret = 0; - - mutex_lock(&chip->lock); - if (state && !(chip->intr & 0x30)) { - chip->intr &= ~0x30; - chip->intr |= 0x10; - /* ensure the chip is actually on */ - cancel_delayed_work(&chip->poweroff_work); - if (!tsl2563_get_power(chip)) { - ret = tsl2563_set_power(chip, 1); - if (ret) - goto out; - ret = tsl2563_configure(chip); - if (ret) - goto out; - } - ret = i2c_smbus_write_byte_data(chip->client, - TSL2563_CMD | TSL2563_REG_INT, - chip->intr); - chip->int_enabled = true; - } - - if (!state && (chip->intr & 0x30)) { - chip->intr |= ~0x30; - ret = i2c_smbus_write_byte_data(chip->client, - TSL2563_CMD | TSL2563_REG_INT, - chip->intr); - chip->int_enabled = false; - /* now the interrupt is not enabled, we can go to sleep */ - schedule_delayed_work(&chip->poweroff_work, 5 * HZ); - } -out: - mutex_unlock(&chip->lock); - - return ret; -} - -static int tsl2563_read_interrupt_config(struct iio_dev *indio_dev, - u64 event_code) -{ - struct tsl2563_chip *chip = iio_priv(indio_dev); - int ret; - - mutex_lock(&chip->lock); - ret = i2c_smbus_read_byte_data(chip->client, - TSL2563_CMD | TSL2563_REG_INT); - mutex_unlock(&chip->lock); - if (ret < 0) - goto error_ret; - ret = !!(ret & 0x30); -error_ret: - - return ret; -} - -/*--------------------------------------------------------------*/ -/* Probe, Attach, Remove */ -/*--------------------------------------------------------------*/ -static struct i2c_driver tsl2563_i2c_driver; - -static const struct iio_info tsl2563_info_no_irq = { - .driver_module = THIS_MODULE, - .read_raw = &tsl2563_read_raw, - .write_raw = &tsl2563_write_raw, -}; - -static const struct iio_info tsl2563_info = { - .driver_module = THIS_MODULE, - .read_raw = &tsl2563_read_raw, - .write_raw = &tsl2563_write_raw, - .read_event_value = &tsl2563_read_thresh, - .write_event_value = &tsl2563_write_thresh, - .read_event_config = &tsl2563_read_interrupt_config, - .write_event_config = &tsl2563_write_interrupt_config, -}; - -static int __devinit tsl2563_probe(struct i2c_client *client, - const struct i2c_device_id *device_id) -{ - struct iio_dev *indio_dev; - struct tsl2563_chip *chip; - struct tsl2563_platform_data *pdata = client->dev.platform_data; - int err = 0; - int ret; - u8 id = 0; - - indio_dev = iio_allocate_device(sizeof(*chip)); - if (!indio_dev) - return -ENOMEM; - - chip = iio_priv(indio_dev); - - i2c_set_clientdata(client, chip); - chip->client = client; - - err = tsl2563_detect(chip); - if (err) { - dev_err(&client->dev, "device not found, error %d\n", -err); - goto fail1; - } - - err = tsl2563_read_id(chip, &id); - if (err) - goto fail1; - - mutex_init(&chip->lock); - - /* Default values used until userspace says otherwise */ - chip->low_thres = 0x0; - chip->high_thres = 0xffff; - chip->gainlevel = tsl2563_gainlevel_table; - chip->intr = TSL2563_INT_PERSIST(4); - chip->calib0 = calib_from_sysfs(CALIB_BASE_SYSFS); - chip->calib1 = calib_from_sysfs(CALIB_BASE_SYSFS); - - if (pdata) - chip->cover_comp_gain = pdata->cover_comp_gain; - else - chip->cover_comp_gain = 1; - - dev_info(&client->dev, "model %d, rev. %d\n", id >> 4, id & 0x0f); - indio_dev->name = client->name; - indio_dev->channels = tsl2563_channels; - indio_dev->num_channels = ARRAY_SIZE(tsl2563_channels); - indio_dev->dev.parent = &client->dev; - indio_dev->modes = INDIO_DIRECT_MODE; - if (client->irq) - indio_dev->info = &tsl2563_info; - else - indio_dev->info = &tsl2563_info_no_irq; - if (client->irq) { - ret = request_threaded_irq(client->irq, - NULL, - &tsl2563_event_handler, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - "tsl2563_event", - indio_dev); - if (ret) - goto fail2; - } - err = tsl2563_configure(chip); - if (err) - goto fail3; - - INIT_DELAYED_WORK(&chip->poweroff_work, tsl2563_poweroff_work); - /* The interrupt cannot yet be enabled so this is fine without lock */ - schedule_delayed_work(&chip->poweroff_work, 5 * HZ); - - ret = iio_device_register(indio_dev); - if (ret) - goto fail3; - - return 0; -fail3: - if (client->irq) - free_irq(client->irq, indio_dev); -fail2: - iio_free_device(indio_dev); -fail1: - kfree(chip); - return err; -} - -static int tsl2563_remove(struct i2c_client *client) -{ - struct tsl2563_chip *chip = i2c_get_clientdata(client); - struct iio_dev *indio_dev = iio_priv_to_dev(chip); - - iio_device_unregister(indio_dev); - if (!chip->int_enabled) - cancel_delayed_work(&chip->poweroff_work); - /* Ensure that interrupts are disabled - then flush any bottom halves */ - chip->intr |= ~0x30; - i2c_smbus_write_byte_data(chip->client, TSL2563_CMD | TSL2563_REG_INT, - chip->intr); - flush_scheduled_work(); - tsl2563_set_power(chip, 0); - if (client->irq) - free_irq(client->irq, indio_dev); - - iio_free_device(indio_dev); - - return 0; -} - -static int tsl2563_suspend(struct i2c_client *client, pm_message_t state) -{ - struct tsl2563_chip *chip = i2c_get_clientdata(client); - int ret; - - mutex_lock(&chip->lock); - - ret = tsl2563_set_power(chip, 0); - if (ret) - goto out; - - chip->state = state; - -out: - mutex_unlock(&chip->lock); - return ret; -} - -static int tsl2563_resume(struct i2c_client *client) -{ - struct tsl2563_chip *chip = i2c_get_clientdata(client); - int ret; - - mutex_lock(&chip->lock); - - ret = tsl2563_set_power(chip, 1); - if (ret) - goto out; - - ret = tsl2563_configure(chip); - if (ret) - goto out; - - chip->state.event = PM_EVENT_ON; - -out: - mutex_unlock(&chip->lock); - return ret; -} - -static const struct i2c_device_id tsl2563_id[] = { - { "tsl2560", 0 }, - { "tsl2561", 1 }, - { "tsl2562", 2 }, - { "tsl2563", 3 }, - {} -}; -MODULE_DEVICE_TABLE(i2c, tsl2563_id); - -static struct i2c_driver tsl2563_i2c_driver = { - .driver = { - .name = "tsl2563", - }, - .suspend = tsl2563_suspend, - .resume = tsl2563_resume, - .probe = tsl2563_probe, - .remove = __devexit_p(tsl2563_remove), - .id_table = tsl2563_id, -}; -module_i2c_driver(tsl2563_i2c_driver); - -MODULE_AUTHOR("Nokia Corporation"); -MODULE_DESCRIPTION("tsl2563 light sensor driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/light/tsl2563.h b/drivers/staging/iio/light/tsl2563.h deleted file mode 100644 index b97368bd7ff..00000000000 --- a/drivers/staging/iio/light/tsl2563.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __LINUX_TSL2563_H -#define __LINUX_TSL2563_H - -struct tsl2563_platform_data { - int cover_comp_gain; -}; - -#endif /* __LINUX_TSL2563_H */ - diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 5b6455a238d..fa964987966 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -28,7 +28,7 @@ #include <linux/unistd.h> #include <linux/slab.h> #include <linux/module.h> -#include "../iio.h" +#include <linux/iio/iio.h> #define TSL258X_MAX_DEVICE_REGS 32 @@ -113,7 +113,7 @@ struct taos_lux { /* This structure is intentionally large to accommodate updates via sysfs. */ /* Sized to 11 = max 10 segments + 1 termination segment */ -/* Assumption is is one and only one type of glass used */ +/* Assumption is one and only one type of glass used */ static struct taos_lux taos_device_lux[11] = { { 9830, 8520, 15729 }, { 12452, 10807, 23344 }, @@ -165,8 +165,9 @@ taos_i2c_read(struct i2c_client *client, u8 reg, u8 *val, unsigned int len) /* select register to write */ ret = i2c_smbus_write_byte(client, (TSL258X_CMD_REG | reg)); if (ret < 0) { - dev_err(&client->dev, "taos_i2c_read failed to write" - " register %x\n", reg); + dev_err(&client->dev, + "taos_i2c_read failed to write register %x\n", + reg); return ret; } /* read the data */ @@ -211,7 +212,7 @@ static int taos_get_lux(struct iio_dev *indio_dev) if (chip->taos_chip_status != TSL258X_CHIP_WORKING) { /* device is not enabled */ dev_err(&chip->client->dev, "taos_get_lux device is not enabled\n"); - ret = -EBUSY ; + ret = -EBUSY; goto out_unlock; } @@ -231,8 +232,9 @@ static int taos_get_lux(struct iio_dev *indio_dev) int reg = TSL258X_CMD_REG | (TSL258X_ALS_CHAN0LO + i); ret = taos_i2c_read(chip->client, reg, &buf[i], 1); if (ret < 0) { - dev_err(&chip->client->dev, "taos_get_lux failed to read" - " register %x\n", reg); + dev_err(&chip->client->dev, + "taos_get_lux failed to read register %x\n", + reg); goto out_unlock; } } @@ -410,7 +412,7 @@ static int taos_chip_on(struct iio_dev *indio_dev) return -EINVAL; } - /* determine als integration regster */ + /* determine als integration register */ als_count = (chip->taos_settings.als_time * 100 + 135) / 270; if (als_count == 0) als_count = 1; /* ensure at least one cycle */ @@ -433,7 +435,7 @@ static int taos_chip_on(struct iio_dev *indio_dev) TSL258X_CMD_REG | TSL258X_CNTRL, utmp); if (ret < 0) { dev_err(&chip->client->dev, "taos_chip_on failed on CNTRL reg.\n"); - return -1; + return ret; } /* Use the following shadow copy for our delay before enabling ADC. @@ -445,11 +447,11 @@ static int taos_chip_on(struct iio_dev *indio_dev) if (ret < 0) { dev_err(&chip->client->dev, "taos_chip_on failed on reg %d.\n", i); - return -1; + return ret; } } - msleep(3); + usleep_range(3000, 3500); /* NOW enable the ADC * initialize the desired mode of operation */ utmp = TSL258X_CNTL_PWR_ON | TSL258X_CNTL_ADC_ENBL; @@ -458,7 +460,7 @@ static int taos_chip_on(struct iio_dev *indio_dev) utmp); if (ret < 0) { dev_err(&chip->client->dev, "taos_chip_on failed on 2nd CTRL reg.\n"); - return -1; + return ret; } chip->taos_chip_status = TSL258X_CHIP_WORKING; @@ -483,7 +485,7 @@ static int taos_chip_off(struct iio_dev *indio_dev) static ssize_t taos_power_state_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2583_chip *chip = iio_priv(indio_dev); return sprintf(buf, "%d\n", chip->taos_chip_status); @@ -492,10 +494,10 @@ static ssize_t taos_power_state_show(struct device *dev, static ssize_t taos_power_state_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); - unsigned long value; + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + int value; - if (strict_strtoul(buf, 0, &value)) + if (kstrtoint(buf, 0, &value)) return -EINVAL; if (value == 0) @@ -509,7 +511,7 @@ static ssize_t taos_power_state_store(struct device *dev, static ssize_t taos_gain_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2583_chip *chip = iio_priv(indio_dev); char gain[4] = {0}; @@ -534,11 +536,11 @@ static ssize_t taos_gain_show(struct device *dev, static ssize_t taos_gain_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2583_chip *chip = iio_priv(indio_dev); - unsigned long value; + int value; - if (strict_strtoul(buf, 0, &value)) + if (kstrtoint(buf, 0, &value)) return -EINVAL; switch (value) { @@ -571,7 +573,7 @@ static ssize_t taos_gain_available_show(struct device *dev, static ssize_t taos_als_time_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2583_chip *chip = iio_priv(indio_dev); return sprintf(buf, "%d\n", chip->taos_settings.als_time); @@ -580,11 +582,11 @@ static ssize_t taos_als_time_show(struct device *dev, static ssize_t taos_als_time_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2583_chip *chip = iio_priv(indio_dev); - unsigned long value; + int value; - if (strict_strtoul(buf, 0, &value)) + if (kstrtoint(buf, 0, &value)) return -EINVAL; if ((value < 50) || (value > 650)) @@ -608,7 +610,7 @@ static ssize_t taos_als_time_available_show(struct device *dev, static ssize_t taos_als_trim_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2583_chip *chip = iio_priv(indio_dev); return sprintf(buf, "%d\n", chip->taos_settings.als_gain_trim); @@ -617,11 +619,11 @@ static ssize_t taos_als_trim_show(struct device *dev, static ssize_t taos_als_trim_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2583_chip *chip = iio_priv(indio_dev); - unsigned long value; + int value; - if (strict_strtoul(buf, 0, &value)) + if (kstrtoint(buf, 0, &value)) return -EINVAL; if (value) @@ -633,7 +635,7 @@ static ssize_t taos_als_trim_store(struct device *dev, static ssize_t taos_als_cal_target_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2583_chip *chip = iio_priv(indio_dev); return sprintf(buf, "%d\n", chip->taos_settings.als_cal_target); @@ -642,11 +644,11 @@ static ssize_t taos_als_cal_target_show(struct device *dev, static ssize_t taos_als_cal_target_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2583_chip *chip = iio_priv(indio_dev); - unsigned long value; + int value; - if (strict_strtoul(buf, 0, &value)) + if (kstrtoint(buf, 0, &value)) return -EINVAL; if (value) @@ -660,7 +662,7 @@ static ssize_t taos_lux_show(struct device *dev, struct device_attribute *attr, { int ret; - ret = taos_get_lux(dev_get_drvdata(dev)); + ret = taos_get_lux(dev_to_iio_dev(dev)); if (ret < 0) return ret; @@ -670,10 +672,10 @@ static ssize_t taos_lux_show(struct device *dev, struct device_attribute *attr, static ssize_t taos_do_calibrate(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); - unsigned long value; + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + int value; - if (strict_strtoul(buf, 0, &value)) + if (kstrtoint(buf, 0, &value)) return -EINVAL; if (value == 1) @@ -708,7 +710,7 @@ static ssize_t taos_luxtable_show(struct device *dev, static ssize_t taos_luxtable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2583_chip *chip = iio_priv(indio_dev); int value[ARRAY_SIZE(taos_device_lux)*3 + 1]; int n; @@ -799,7 +801,7 @@ static const struct iio_info tsl2583_info = { * Client probe function - When a valid device is found, the driver's device * data structure is updated, and initialization completes successfully. */ -static int __devinit taos_probe(struct i2c_client *clientp, +static int taos_probe(struct i2c_client *clientp, const struct i2c_device_id *idp) { int i, ret; @@ -809,18 +811,13 @@ static int __devinit taos_probe(struct i2c_client *clientp, if (!i2c_check_functionality(clientp->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - dev_err(&clientp->dev, - "taos_probe() - i2c smbus byte data " - "functions unsupported\n"); + dev_err(&clientp->dev, "taos_probe() - i2c smbus byte data func unsupported\n"); return -EOPNOTSUPP; } - indio_dev = iio_allocate_device(sizeof(*chip)); - if (indio_dev == NULL) { - ret = -ENOMEM; - dev_err(&clientp->dev, "iio allocation failed\n"); - goto fail1; - } + indio_dev = devm_iio_device_alloc(&clientp->dev, sizeof(*chip)); + if (!indio_dev) + return -ENOMEM; chip = iio_priv(indio_dev); chip->client = clientp; i2c_set_clientdata(clientp, indio_dev); @@ -833,31 +830,33 @@ static int __devinit taos_probe(struct i2c_client *clientp, ret = i2c_smbus_write_byte(clientp, (TSL258X_CMD_REG | (TSL258X_CNTRL + i))); if (ret < 0) { - dev_err(&clientp->dev, "i2c_smbus_write_bytes() to cmd " - "reg failed in taos_probe(), err = %d\n", ret); - goto fail2; + dev_err(&clientp->dev, + "i2c_smbus_write_byte to cmd reg failed in taos_probe(), err = %d\n", + ret); + return ret; } ret = i2c_smbus_read_byte(clientp); if (ret < 0) { - dev_err(&clientp->dev, "i2c_smbus_read_byte from " - "reg failed in taos_probe(), err = %d\n", ret); - - goto fail2; + dev_err(&clientp->dev, + "i2c_smbus_read_byte from reg failed in taos_probe(), err = %d\n", + ret); + return ret; } buf[i] = ret; } if (!taos_tsl258x_device(buf)) { - dev_info(&clientp->dev, "i2c device found but does not match " - "expected id in taos_probe()\n"); - goto fail2; + dev_info(&clientp->dev, + "i2c device found but does not match expected id in taos_probe()\n"); + return -EINVAL; } ret = i2c_smbus_write_byte(clientp, (TSL258X_CMD_REG | TSL258X_CNTRL)); if (ret < 0) { - dev_err(&clientp->dev, "i2c_smbus_write_byte() to cmd reg " - "failed in taos_probe(), err = %d\n", ret); - goto fail2; + dev_err(&clientp->dev, + "i2c_smbus_write_byte() to cmd reg failed in taos_probe(), err = %d\n", + ret); + return ret; } indio_dev->info = &tsl2583_info; @@ -867,7 +866,7 @@ static int __devinit taos_probe(struct i2c_client *clientp, ret = iio_device_register(indio_dev); if (ret) { dev_err(&clientp->dev, "iio registration failed\n"); - goto fail2; + return ret; } /* Load up the V2 defaults (these are hard coded defaults for now) */ @@ -878,15 +877,12 @@ static int __devinit taos_probe(struct i2c_client *clientp, dev_info(&clientp->dev, "Light sensor found.\n"); return 0; -fail1: - iio_free_device(indio_dev); -fail2: - return ret; } -static int taos_suspend(struct i2c_client *client, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int taos_suspend(struct device *dev) { - struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); struct tsl2583_chip *chip = iio_priv(indio_dev); int ret = 0; @@ -901,9 +897,9 @@ static int taos_suspend(struct i2c_client *client, pm_message_t state) return ret; } -static int taos_resume(struct i2c_client *client) +static int taos_resume(struct device *dev) { - struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); struct tsl2583_chip *chip = iio_priv(indio_dev); int ret = 0; @@ -916,11 +912,15 @@ static int taos_resume(struct i2c_client *client) return ret; } +static SIMPLE_DEV_PM_OPS(taos_pm_ops, taos_suspend, taos_resume); +#define TAOS_PM_OPS (&taos_pm_ops) +#else +#define TAOS_PM_OPS NULL +#endif -static int __devexit taos_remove(struct i2c_client *client) +static int taos_remove(struct i2c_client *client) { iio_device_unregister(i2c_get_clientdata(client)); - iio_free_device(i2c_get_clientdata(client)); return 0; } @@ -937,12 +937,11 @@ MODULE_DEVICE_TABLE(i2c, taos_idtable); static struct i2c_driver taos_driver = { .driver = { .name = "tsl2583", + .pm = TAOS_PM_OPS, }, .id_table = taos_idtable, - .suspend = taos_suspend, - .resume = taos_resume, .probe = taos_probe, - .remove = __devexit_p(taos_remove), + .remove = taos_remove, }; module_i2c_driver(taos_driver); diff --git a/drivers/staging/iio/light/tsl2x7x.h b/drivers/staging/iio/light/tsl2x7x.h new file mode 100644 index 00000000000..c4acf5ff179 --- /dev/null +++ b/drivers/staging/iio/light/tsl2x7x.h @@ -0,0 +1,100 @@ +/* + * Device driver for monitoring ambient light intensity (lux) + * and proximity (prox) within the TAOS TSL2X7X family of devices. + * + * Copyright (c) 2012, TAOS Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __TSL2X7X_H +#define __TSL2X7X_H +#include <linux/pm.h> + +/* Max number of segments allowable in LUX table */ +#define TSL2X7X_MAX_LUX_TABLE_SIZE 9 +#define MAX_DEFAULT_TABLE_BYTES (sizeof(int) * TSL2X7X_MAX_LUX_TABLE_SIZE) + +struct iio_dev; + +struct tsl2x7x_lux { + unsigned int ratio; + unsigned int ch0; + unsigned int ch1; +}; + +/** + * struct tsl2x7x_default_settings - power on defaults unless + * overridden by platform data. + * @als_time: ALS Integration time - multiple of 50mS + * @als_gain: Index into the ALS gain table. + * @als_gain_trim: default gain trim to account for + * aperture effects. + * @wait_time: Time between PRX and ALS cycles + * in 2.7 periods + * @prx_time: 5.2ms prox integration time - + * decrease in 2.7ms periods + * @prx_gain: Proximity gain index + * @prox_config: Prox configuration filters. + * @als_cal_target: Known external ALS reading for + * calibration. + * @interrupts_en: Enable/Disable - 0x00 = none, 0x10 = als, + * 0x20 = prx, 0x30 = bth + * @persistence: H/W Filters, Number of 'out of limits' + * ADC readings PRX/ALS. + * @als_thresh_low: CH0 'low' count to trigger interrupt. + * @als_thresh_high: CH0 'high' count to trigger interrupt. + * @prox_thres_low: Low threshold proximity detection. + * @prox_thres_high: High threshold proximity detection + * @prox_pulse_count: Number if proximity emitter pulses + * @prox_max_samples_cal: Used for prox cal. + */ +struct tsl2x7x_settings { + int als_time; + int als_gain; + int als_gain_trim; + int wait_time; + int prx_time; + int prox_gain; + int prox_config; + int als_cal_target; + u8 interrupts_en; + u8 persistence; + int als_thresh_low; + int als_thresh_high; + int prox_thres_low; + int prox_thres_high; + int prox_pulse_count; + int prox_max_samples_cal; +}; + +/** + * struct tsl2X7X_platform_data - Platform callback, glass and defaults + * @platform_power: Suspend/resume platform callback + * @power_on: Power on callback + * @power_off: Power off callback + * @platform_lux_table: Device specific glass coefficents + * @platform_default_settings: Device specific power on defaults + * + */ +struct tsl2X7X_platform_data { + int (*platform_power)(struct device *dev, pm_message_t); + int (*power_on) (struct iio_dev *indio_dev); + int (*power_off) (struct i2c_client *dev); + struct tsl2x7x_lux platform_lux_table[TSL2X7X_MAX_LUX_TABLE_SIZE]; + struct tsl2x7x_settings *platform_default_settings; +}; + +#endif /* __TSL2X7X_H */ diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c new file mode 100644 index 00000000000..ab338e3ddd0 --- /dev/null +++ b/drivers/staging/iio/light/tsl2x7x_core.c @@ -0,0 +1,2037 @@ +/* + * Device driver for monitoring ambient light intensity in (lux) + * and proximity detection (prox) within the TAOS TSL2X7X family of devices. + * + * Copyright (c) 2012, TAOS Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <linux/kernel.h> +#include <linux/i2c.h> +#include <linux/errno.h> +#include <linux/delay.h> +#include <linux/mutex.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/iio/events.h> +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include "tsl2x7x.h" + +/* Cal defs*/ +#define PROX_STAT_CAL 0 +#define PROX_STAT_SAMP 1 +#define MAX_SAMPLES_CAL 200 + +/* TSL2X7X Device ID */ +#define TRITON_ID 0x00 +#define SWORDFISH_ID 0x30 +#define HALIBUT_ID 0x20 + +/* Lux calculation constants */ +#define TSL2X7X_LUX_CALC_OVER_FLOW 65535 + +/* TAOS Register definitions - note: + * depending on device, some of these register are not used and the + * register address is benign. + */ +/* 2X7X register offsets */ +#define TSL2X7X_MAX_CONFIG_REG 16 + +/* Device Registers and Masks */ +#define TSL2X7X_CNTRL 0x00 +#define TSL2X7X_ALS_TIME 0X01 +#define TSL2X7X_PRX_TIME 0x02 +#define TSL2X7X_WAIT_TIME 0x03 +#define TSL2X7X_ALS_MINTHRESHLO 0X04 +#define TSL2X7X_ALS_MINTHRESHHI 0X05 +#define TSL2X7X_ALS_MAXTHRESHLO 0X06 +#define TSL2X7X_ALS_MAXTHRESHHI 0X07 +#define TSL2X7X_PRX_MINTHRESHLO 0X08 +#define TSL2X7X_PRX_MINTHRESHHI 0X09 +#define TSL2X7X_PRX_MAXTHRESHLO 0X0A +#define TSL2X7X_PRX_MAXTHRESHHI 0X0B +#define TSL2X7X_PERSISTENCE 0x0C +#define TSL2X7X_PRX_CONFIG 0x0D +#define TSL2X7X_PRX_COUNT 0x0E +#define TSL2X7X_GAIN 0x0F +#define TSL2X7X_NOTUSED 0x10 +#define TSL2X7X_REVID 0x11 +#define TSL2X7X_CHIPID 0x12 +#define TSL2X7X_STATUS 0x13 +#define TSL2X7X_ALS_CHAN0LO 0x14 +#define TSL2X7X_ALS_CHAN0HI 0x15 +#define TSL2X7X_ALS_CHAN1LO 0x16 +#define TSL2X7X_ALS_CHAN1HI 0x17 +#define TSL2X7X_PRX_LO 0x18 +#define TSL2X7X_PRX_HI 0x19 + +/* tsl2X7X cmd reg masks */ +#define TSL2X7X_CMD_REG 0x80 +#define TSL2X7X_CMD_SPL_FN 0x60 + +#define TSL2X7X_CMD_PROX_INT_CLR 0X05 +#define TSL2X7X_CMD_ALS_INT_CLR 0x06 +#define TSL2X7X_CMD_PROXALS_INT_CLR 0X07 + +/* tsl2X7X cntrl reg masks */ +#define TSL2X7X_CNTL_ADC_ENBL 0x02 +#define TSL2X7X_CNTL_PWR_ON 0x01 + +/* tsl2X7X status reg masks */ +#define TSL2X7X_STA_ADC_VALID 0x01 +#define TSL2X7X_STA_PRX_VALID 0x02 +#define TSL2X7X_STA_ADC_PRX_VALID (TSL2X7X_STA_ADC_VALID |\ + TSL2X7X_STA_PRX_VALID) +#define TSL2X7X_STA_ALS_INTR 0x10 +#define TSL2X7X_STA_PRX_INTR 0x20 + +/* tsl2X7X cntrl reg masks */ +#define TSL2X7X_CNTL_REG_CLEAR 0x00 +#define TSL2X7X_CNTL_PROX_INT_ENBL 0X20 +#define TSL2X7X_CNTL_ALS_INT_ENBL 0X10 +#define TSL2X7X_CNTL_WAIT_TMR_ENBL 0X08 +#define TSL2X7X_CNTL_PROX_DET_ENBL 0X04 +#define TSL2X7X_CNTL_PWRON 0x01 +#define TSL2X7X_CNTL_ALSPON_ENBL 0x03 +#define TSL2X7X_CNTL_INTALSPON_ENBL 0x13 +#define TSL2X7X_CNTL_PROXPON_ENBL 0x0F +#define TSL2X7X_CNTL_INTPROXPON_ENBL 0x2F + +/*Prox diode to use */ +#define TSL2X7X_DIODE0 0x10 +#define TSL2X7X_DIODE1 0x20 +#define TSL2X7X_DIODE_BOTH 0x30 + +/* LED Power */ +#define TSL2X7X_mA100 0x00 +#define TSL2X7X_mA50 0x40 +#define TSL2X7X_mA25 0x80 +#define TSL2X7X_mA13 0xD0 +#define TSL2X7X_MAX_TIMER_CNT (0xFF) + +#define TSL2X7X_MIN_ITIME 3 + +/* TAOS txx2x7x Device family members */ +enum { + tsl2571, + tsl2671, + tmd2671, + tsl2771, + tmd2771, + tsl2572, + tsl2672, + tmd2672, + tsl2772, + tmd2772 +}; + +enum { + TSL2X7X_CHIP_UNKNOWN = 0, + TSL2X7X_CHIP_WORKING = 1, + TSL2X7X_CHIP_SUSPENDED = 2 +}; + +struct tsl2x7x_parse_result { + int integer; + int fract; +}; + +/* Per-device data */ +struct tsl2x7x_als_info { + u16 als_ch0; + u16 als_ch1; + u16 lux; +}; + +struct tsl2x7x_prox_stat { + int min; + int max; + int mean; + unsigned long stddev; +}; + +struct tsl2x7x_chip_info { + int chan_table_elements; + struct iio_chan_spec channel[4]; + const struct iio_info *info; +}; + +struct tsl2X7X_chip { + kernel_ulong_t id; + struct mutex prox_mutex; + struct mutex als_mutex; + struct i2c_client *client; + u16 prox_data; + struct tsl2x7x_als_info als_cur_info; + struct tsl2x7x_settings tsl2x7x_settings; + struct tsl2X7X_platform_data *pdata; + int als_time_scale; + int als_saturation; + int tsl2x7x_chip_status; + u8 tsl2x7x_config[TSL2X7X_MAX_CONFIG_REG]; + const struct tsl2x7x_chip_info *chip_info; + const struct iio_info *info; + s64 event_timestamp; + /* This structure is intentionally large to accommodate + * updates via sysfs. */ + /* Sized to 9 = max 8 segments + 1 termination segment */ + struct tsl2x7x_lux tsl2x7x_device_lux[TSL2X7X_MAX_LUX_TABLE_SIZE]; +}; + +/* Different devices require different coefficents */ +static const struct tsl2x7x_lux tsl2x71_lux_table[] = { + { 14461, 611, 1211 }, + { 18540, 352, 623 }, + { 0, 0, 0 }, +}; + +static const struct tsl2x7x_lux tmd2x71_lux_table[] = { + { 11635, 115, 256 }, + { 15536, 87, 179 }, + { 0, 0, 0 }, +}; + +static const struct tsl2x7x_lux tsl2x72_lux_table[] = { + { 14013, 466, 917 }, + { 18222, 310, 552 }, + { 0, 0, 0 }, +}; + +static const struct tsl2x7x_lux tmd2x72_lux_table[] = { + { 13218, 130, 262 }, + { 17592, 92, 169 }, + { 0, 0, 0 }, +}; + +static const struct tsl2x7x_lux *tsl2x7x_default_lux_table_group[] = { + [tsl2571] = tsl2x71_lux_table, + [tsl2671] = tsl2x71_lux_table, + [tmd2671] = tmd2x71_lux_table, + [tsl2771] = tsl2x71_lux_table, + [tmd2771] = tmd2x71_lux_table, + [tsl2572] = tsl2x72_lux_table, + [tsl2672] = tsl2x72_lux_table, + [tmd2672] = tmd2x72_lux_table, + [tsl2772] = tsl2x72_lux_table, + [tmd2772] = tmd2x72_lux_table, +}; + +static const struct tsl2x7x_settings tsl2x7x_default_settings = { + .als_time = 219, /* 101 ms */ + .als_gain = 0, + .prx_time = 254, /* 5.4 ms */ + .prox_gain = 1, + .wait_time = 245, + .prox_config = 0, + .als_gain_trim = 1000, + .als_cal_target = 150, + .als_thresh_low = 200, + .als_thresh_high = 256, + .persistence = 255, + .interrupts_en = 0, + .prox_thres_low = 0, + .prox_thres_high = 512, + .prox_max_samples_cal = 30, + .prox_pulse_count = 8 +}; + +static const s16 tsl2X7X_als_gainadj[] = { + 1, + 8, + 16, + 120 +}; + +static const s16 tsl2X7X_prx_gainadj[] = { + 1, + 2, + 4, + 8 +}; + +/* Channel variations */ +enum { + ALS, + PRX, + ALSPRX, + PRX2, + ALSPRX2, +}; + +static const u8 device_channel_config[] = { + ALS, + PRX, + PRX, + ALSPRX, + ALSPRX, + ALS, + PRX2, + PRX2, + ALSPRX2, + ALSPRX2 +}; + +/** + * tsl2x7x_i2c_read() - Read a byte from a register. + * @client: i2c client + * @reg: device register to read from + * @*val: pointer to location to store register contents. + * + */ +static int +tsl2x7x_i2c_read(struct i2c_client *client, u8 reg, u8 *val) +{ + int ret = 0; + + /* select register to write */ + ret = i2c_smbus_write_byte(client, (TSL2X7X_CMD_REG | reg)); + if (ret < 0) { + dev_err(&client->dev, "%s: failed to write register %x\n" + , __func__, reg); + return ret; + } + + /* read the data */ + ret = i2c_smbus_read_byte(client); + if (ret >= 0) + *val = (u8)ret; + else + dev_err(&client->dev, "%s: failed to read register %x\n" + , __func__, reg); + + return ret; +} + +/** + * tsl2x7x_get_lux() - Reads and calculates current lux value. + * @indio_dev: pointer to IIO device + * + * The raw ch0 and ch1 values of the ambient light sensed in the last + * integration cycle are read from the device. + * Time scale factor array values are adjusted based on the integration time. + * The raw values are multiplied by a scale factor, and device gain is obtained + * using gain index. Limit checks are done next, then the ratio of a multiple + * of ch1 value, to the ch0 value, is calculated. Array tsl2x7x_device_lux[] + * is then scanned to find the first ratio value that is just above the ratio + * we just calculated. The ch0 and ch1 multiplier constants in the array are + * then used along with the time scale factor array values, to calculate the + * lux. + */ +static int tsl2x7x_get_lux(struct iio_dev *indio_dev) +{ + u16 ch0, ch1; /* separated ch0/ch1 data from device */ + u32 lux; /* raw lux calculated from device data */ + u64 lux64; + u32 ratio; + u8 buf[4]; + struct tsl2x7x_lux *p; + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + int i, ret; + u32 ch0lux = 0; + u32 ch1lux = 0; + + if (mutex_trylock(&chip->als_mutex) == 0) + return chip->als_cur_info.lux; /* busy, so return LAST VALUE */ + + if (chip->tsl2x7x_chip_status != TSL2X7X_CHIP_WORKING) { + /* device is not enabled */ + dev_err(&chip->client->dev, "%s: device is not enabled\n", + __func__); + ret = -EBUSY; + goto out_unlock; + } + + ret = tsl2x7x_i2c_read(chip->client, + (TSL2X7X_CMD_REG | TSL2X7X_STATUS), &buf[0]); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: Failed to read STATUS Reg\n", __func__); + goto out_unlock; + } + /* is data new & valid */ + if (!(buf[0] & TSL2X7X_STA_ADC_VALID)) { + dev_err(&chip->client->dev, + "%s: data not valid yet\n", __func__); + ret = chip->als_cur_info.lux; /* return LAST VALUE */ + goto out_unlock; + } + + for (i = 0; i < 4; i++) { + ret = tsl2x7x_i2c_read(chip->client, + (TSL2X7X_CMD_REG | (TSL2X7X_ALS_CHAN0LO + i)), + &buf[i]); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: failed to read. err=%x\n", __func__, ret); + goto out_unlock; + } + } + + /* clear any existing interrupt status */ + ret = i2c_smbus_write_byte(chip->client, + (TSL2X7X_CMD_REG | + TSL2X7X_CMD_SPL_FN | + TSL2X7X_CMD_ALS_INT_CLR)); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: i2c_write_command failed - err = %d\n", + __func__, ret); + goto out_unlock; /* have no data, so return failure */ + } + + /* extract ALS/lux data */ + ch0 = le16_to_cpup((const __le16 *)&buf[0]); + ch1 = le16_to_cpup((const __le16 *)&buf[2]); + + chip->als_cur_info.als_ch0 = ch0; + chip->als_cur_info.als_ch1 = ch1; + + if ((ch0 >= chip->als_saturation) || (ch1 >= chip->als_saturation)) { + lux = TSL2X7X_LUX_CALC_OVER_FLOW; + goto return_max; + } + + if (ch0 == 0) { + /* have no data, so return LAST VALUE */ + ret = chip->als_cur_info.lux; + goto out_unlock; + } + /* calculate ratio */ + ratio = (ch1 << 15) / ch0; + /* convert to unscaled lux using the pointer to the table */ + p = (struct tsl2x7x_lux *) chip->tsl2x7x_device_lux; + while (p->ratio != 0 && p->ratio < ratio) + p++; + + if (p->ratio == 0) { + lux = 0; + } else { + ch0lux = DIV_ROUND_UP((ch0 * p->ch0), + tsl2X7X_als_gainadj[chip->tsl2x7x_settings.als_gain]); + ch1lux = DIV_ROUND_UP((ch1 * p->ch1), + tsl2X7X_als_gainadj[chip->tsl2x7x_settings.als_gain]); + lux = ch0lux - ch1lux; + } + + /* note: lux is 31 bit max at this point */ + if (ch1lux > ch0lux) { + dev_dbg(&chip->client->dev, "ch1lux > ch0lux-return last value\n"); + ret = chip->als_cur_info.lux; + goto out_unlock; + } + + /* adjust for active time scale */ + if (chip->als_time_scale == 0) + lux = 0; + else + lux = (lux + (chip->als_time_scale >> 1)) / + chip->als_time_scale; + + /* adjust for active gain scale + * The tsl2x7x_device_lux tables have a factor of 256 built-in. + * User-specified gain provides a multiplier. + * Apply user-specified gain before shifting right to retain precision. + * Use 64 bits to avoid overflow on multiplication. + * Then go back to 32 bits before division to avoid using div_u64(). + */ + + lux64 = lux; + lux64 = lux64 * chip->tsl2x7x_settings.als_gain_trim; + lux64 >>= 8; + lux = lux64; + lux = (lux + 500) / 1000; + + if (lux > TSL2X7X_LUX_CALC_OVER_FLOW) /* check for overflow */ + lux = TSL2X7X_LUX_CALC_OVER_FLOW; + + /* Update the structure with the latest lux. */ +return_max: + chip->als_cur_info.lux = lux; + ret = lux; + +out_unlock: + mutex_unlock(&chip->als_mutex); + + return ret; +} + +/** + * tsl2x7x_get_prox() - Reads proximity data registers and updates + * chip->prox_data. + * + * @indio_dev: pointer to IIO device + */ +static int tsl2x7x_get_prox(struct iio_dev *indio_dev) +{ + int i; + int ret; + u8 status; + u8 chdata[2]; + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + + if (mutex_trylock(&chip->prox_mutex) == 0) { + dev_err(&chip->client->dev, + "%s: Can't get prox mutex\n", __func__); + return -EBUSY; + } + + ret = tsl2x7x_i2c_read(chip->client, + (TSL2X7X_CMD_REG | TSL2X7X_STATUS), &status); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: i2c err=%d\n", __func__, ret); + goto prox_poll_err; + } + + switch (chip->id) { + case tsl2571: + case tsl2671: + case tmd2671: + case tsl2771: + case tmd2771: + if (!(status & TSL2X7X_STA_ADC_VALID)) + goto prox_poll_err; + break; + case tsl2572: + case tsl2672: + case tmd2672: + case tsl2772: + case tmd2772: + if (!(status & TSL2X7X_STA_PRX_VALID)) + goto prox_poll_err; + break; + } + + for (i = 0; i < 2; i++) { + ret = tsl2x7x_i2c_read(chip->client, + (TSL2X7X_CMD_REG | + (TSL2X7X_PRX_LO + i)), &chdata[i]); + if (ret < 0) + goto prox_poll_err; + } + + chip->prox_data = + le16_to_cpup((const __le16 *)&chdata[0]); + +prox_poll_err: + + mutex_unlock(&chip->prox_mutex); + + return chip->prox_data; +} + +/** + * tsl2x7x_defaults() - Populates the device nominal operating parameters + * with those provided by a 'platform' data struct or + * with prefined defaults. + * + * @chip: pointer to device structure. + */ +static void tsl2x7x_defaults(struct tsl2X7X_chip *chip) +{ + /* If Operational settings defined elsewhere.. */ + if (chip->pdata && chip->pdata->platform_default_settings) + memcpy(&(chip->tsl2x7x_settings), + chip->pdata->platform_default_settings, + sizeof(tsl2x7x_default_settings)); + else + memcpy(&(chip->tsl2x7x_settings), + &tsl2x7x_default_settings, + sizeof(tsl2x7x_default_settings)); + + /* Load up the proper lux table. */ + if (chip->pdata && chip->pdata->platform_lux_table[0].ratio != 0) + memcpy(chip->tsl2x7x_device_lux, + chip->pdata->platform_lux_table, + sizeof(chip->pdata->platform_lux_table)); + else + memcpy(chip->tsl2x7x_device_lux, + (struct tsl2x7x_lux *)tsl2x7x_default_lux_table_group[chip->id], + MAX_DEFAULT_TABLE_BYTES); +} + +/** + * tsl2x7x_als_calibrate() - Obtain single reading and calculate + * the als_gain_trim. + * + * @indio_dev: pointer to IIO device + */ +static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev) +{ + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + u8 reg_val; + int gain_trim_val; + int ret; + int lux_val; + + ret = i2c_smbus_write_byte(chip->client, + (TSL2X7X_CMD_REG | TSL2X7X_CNTRL)); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: failed to write CNTRL register, ret=%d\n", + __func__, ret); + return ret; + } + + reg_val = i2c_smbus_read_byte(chip->client); + if ((reg_val & (TSL2X7X_CNTL_ADC_ENBL | TSL2X7X_CNTL_PWR_ON)) + != (TSL2X7X_CNTL_ADC_ENBL | TSL2X7X_CNTL_PWR_ON)) { + dev_err(&chip->client->dev, + "%s: failed: ADC not enabled\n", __func__); + return -1; + } + + ret = i2c_smbus_write_byte(chip->client, + (TSL2X7X_CMD_REG | TSL2X7X_CNTRL)); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: failed to write ctrl reg: ret=%d\n", + __func__, ret); + return ret; + } + + reg_val = i2c_smbus_read_byte(chip->client); + if ((reg_val & TSL2X7X_STA_ADC_VALID) != TSL2X7X_STA_ADC_VALID) { + dev_err(&chip->client->dev, + "%s: failed: STATUS - ADC not valid.\n", __func__); + return -ENODATA; + } + + lux_val = tsl2x7x_get_lux(indio_dev); + if (lux_val < 0) { + dev_err(&chip->client->dev, + "%s: failed to get lux\n", __func__); + return lux_val; + } + + gain_trim_val = (((chip->tsl2x7x_settings.als_cal_target) + * chip->tsl2x7x_settings.als_gain_trim) / lux_val); + if ((gain_trim_val < 250) || (gain_trim_val > 4000)) + return -ERANGE; + + chip->tsl2x7x_settings.als_gain_trim = gain_trim_val; + dev_info(&chip->client->dev, + "%s als_calibrate completed\n", chip->client->name); + + return (int) gain_trim_val; +} + +static int tsl2x7x_chip_on(struct iio_dev *indio_dev) +{ + int i; + int ret = 0; + u8 *dev_reg; + u8 utmp; + int als_count; + int als_time; + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + u8 reg_val = 0; + + if (chip->pdata && chip->pdata->power_on) + chip->pdata->power_on(indio_dev); + + /* Non calculated parameters */ + chip->tsl2x7x_config[TSL2X7X_PRX_TIME] = + chip->tsl2x7x_settings.prx_time; + chip->tsl2x7x_config[TSL2X7X_WAIT_TIME] = + chip->tsl2x7x_settings.wait_time; + chip->tsl2x7x_config[TSL2X7X_PRX_CONFIG] = + chip->tsl2x7x_settings.prox_config; + + chip->tsl2x7x_config[TSL2X7X_ALS_MINTHRESHLO] = + (chip->tsl2x7x_settings.als_thresh_low) & 0xFF; + chip->tsl2x7x_config[TSL2X7X_ALS_MINTHRESHHI] = + (chip->tsl2x7x_settings.als_thresh_low >> 8) & 0xFF; + chip->tsl2x7x_config[TSL2X7X_ALS_MAXTHRESHLO] = + (chip->tsl2x7x_settings.als_thresh_high) & 0xFF; + chip->tsl2x7x_config[TSL2X7X_ALS_MAXTHRESHHI] = + (chip->tsl2x7x_settings.als_thresh_high >> 8) & 0xFF; + chip->tsl2x7x_config[TSL2X7X_PERSISTENCE] = + chip->tsl2x7x_settings.persistence; + + chip->tsl2x7x_config[TSL2X7X_PRX_COUNT] = + chip->tsl2x7x_settings.prox_pulse_count; + chip->tsl2x7x_config[TSL2X7X_PRX_MINTHRESHLO] = + (chip->tsl2x7x_settings.prox_thres_low) & 0xFF; + chip->tsl2x7x_config[TSL2X7X_PRX_MINTHRESHHI] = + (chip->tsl2x7x_settings.prox_thres_low >> 8) & 0xFF; + chip->tsl2x7x_config[TSL2X7X_PRX_MAXTHRESHLO] = + (chip->tsl2x7x_settings.prox_thres_high) & 0xFF; + chip->tsl2x7x_config[TSL2X7X_PRX_MAXTHRESHHI] = + (chip->tsl2x7x_settings.prox_thres_high >> 8) & 0xFF; + + /* and make sure we're not already on */ + if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_WORKING) { + /* if forcing a register update - turn off, then on */ + dev_info(&chip->client->dev, "device is already enabled\n"); + return -EINVAL; + } + + /* determine als integration register */ + als_count = (chip->tsl2x7x_settings.als_time * 100 + 135) / 270; + if (als_count == 0) + als_count = 1; /* ensure at least one cycle */ + + /* convert back to time (encompasses overrides) */ + als_time = (als_count * 27 + 5) / 10; + chip->tsl2x7x_config[TSL2X7X_ALS_TIME] = 256 - als_count; + + /* Set the gain based on tsl2x7x_settings struct */ + chip->tsl2x7x_config[TSL2X7X_GAIN] = + (chip->tsl2x7x_settings.als_gain | + (TSL2X7X_mA100 | TSL2X7X_DIODE1) + | ((chip->tsl2x7x_settings.prox_gain) << 2)); + + /* set chip struct re scaling and saturation */ + chip->als_saturation = als_count * 922; /* 90% of full scale */ + chip->als_time_scale = (als_time + 25) / 50; + + /* TSL2X7X Specific power-on / adc enable sequence + * Power on the device 1st. */ + utmp = TSL2X7X_CNTL_PWR_ON; + ret = i2c_smbus_write_byte_data(chip->client, + TSL2X7X_CMD_REG | TSL2X7X_CNTRL, utmp); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: failed on CNTRL reg.\n", __func__); + return ret; + } + + /* Use the following shadow copy for our delay before enabling ADC. + * Write all the registers. */ + for (i = 0, dev_reg = chip->tsl2x7x_config; + i < TSL2X7X_MAX_CONFIG_REG; i++) { + ret = i2c_smbus_write_byte_data(chip->client, + TSL2X7X_CMD_REG + i, *dev_reg++); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: failed on write to reg %d.\n", __func__, i); + return ret; + } + } + + mdelay(3); /* Power-on settling time */ + + /* NOW enable the ADC + * initialize the desired mode of operation */ + utmp = TSL2X7X_CNTL_PWR_ON | + TSL2X7X_CNTL_ADC_ENBL | + TSL2X7X_CNTL_PROX_DET_ENBL; + ret = i2c_smbus_write_byte_data(chip->client, + TSL2X7X_CMD_REG | TSL2X7X_CNTRL, utmp); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: failed on 2nd CTRL reg.\n", __func__); + return ret; + } + + chip->tsl2x7x_chip_status = TSL2X7X_CHIP_WORKING; + + if (chip->tsl2x7x_settings.interrupts_en != 0) { + dev_info(&chip->client->dev, "Setting Up Interrupt(s)\n"); + + reg_val = TSL2X7X_CNTL_PWR_ON | TSL2X7X_CNTL_ADC_ENBL; + if ((chip->tsl2x7x_settings.interrupts_en == 0x20) || + (chip->tsl2x7x_settings.interrupts_en == 0x30)) + reg_val |= TSL2X7X_CNTL_PROX_DET_ENBL; + + reg_val |= chip->tsl2x7x_settings.interrupts_en; + ret = i2c_smbus_write_byte_data(chip->client, + (TSL2X7X_CMD_REG | TSL2X7X_CNTRL), reg_val); + if (ret < 0) + dev_err(&chip->client->dev, + "%s: failed in tsl2x7x_IOCTL_INT_SET.\n", + __func__); + + /* Clear out any initial interrupts */ + ret = i2c_smbus_write_byte(chip->client, + TSL2X7X_CMD_REG | TSL2X7X_CMD_SPL_FN | + TSL2X7X_CMD_PROXALS_INT_CLR); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: Failed to clear Int status\n", + __func__); + return ret; + } + } + + return ret; +} + +static int tsl2x7x_chip_off(struct iio_dev *indio_dev) +{ + int ret; + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + + /* turn device off */ + chip->tsl2x7x_chip_status = TSL2X7X_CHIP_SUSPENDED; + + ret = i2c_smbus_write_byte_data(chip->client, + TSL2X7X_CMD_REG | TSL2X7X_CNTRL, 0x00); + + if (chip->pdata && chip->pdata->power_off) + chip->pdata->power_off(chip->client); + + return ret; +} + +/** + * tsl2x7x_invoke_change + * @indio_dev: pointer to IIO device + * + * Obtain and lock both ALS and PROX resources, + * determine and save device state (On/Off), + * cycle device to implement updated parameter, + * put device back into proper state, and unlock + * resource. + */ +static +int tsl2x7x_invoke_change(struct iio_dev *indio_dev) +{ + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + int device_status = chip->tsl2x7x_chip_status; + + mutex_lock(&chip->als_mutex); + mutex_lock(&chip->prox_mutex); + + if (device_status == TSL2X7X_CHIP_WORKING) + tsl2x7x_chip_off(indio_dev); + + tsl2x7x_chip_on(indio_dev); + + if (device_status != TSL2X7X_CHIP_WORKING) + tsl2x7x_chip_off(indio_dev); + + mutex_unlock(&chip->prox_mutex); + mutex_unlock(&chip->als_mutex); + + return 0; +} + +static +void tsl2x7x_prox_calculate(int *data, int length, + struct tsl2x7x_prox_stat *statP) +{ + int i; + int sample_sum; + int tmp; + + if (length == 0) + length = 1; + + sample_sum = 0; + statP->min = INT_MAX; + statP->max = INT_MIN; + for (i = 0; i < length; i++) { + sample_sum += data[i]; + statP->min = min(statP->min, data[i]); + statP->max = max(statP->max, data[i]); + } + + statP->mean = sample_sum / length; + sample_sum = 0; + for (i = 0; i < length; i++) { + tmp = data[i] - statP->mean; + sample_sum += tmp * tmp; + } + statP->stddev = int_sqrt((long)sample_sum)/length; +} + +/** + * tsl2x7x_prox_cal() - Calculates std. and sets thresholds. + * @indio_dev: pointer to IIO device + * + * Calculates a standard deviation based on the samples, + * and sets the threshold accordingly. + */ +static void tsl2x7x_prox_cal(struct iio_dev *indio_dev) +{ + int prox_history[MAX_SAMPLES_CAL + 1]; + int i; + struct tsl2x7x_prox_stat prox_stat_data[2]; + struct tsl2x7x_prox_stat *calP; + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + u8 tmp_irq_settings; + u8 current_state = chip->tsl2x7x_chip_status; + + if (chip->tsl2x7x_settings.prox_max_samples_cal > MAX_SAMPLES_CAL) { + dev_err(&chip->client->dev, + "%s: max prox samples cal is too big: %d\n", + __func__, chip->tsl2x7x_settings.prox_max_samples_cal); + chip->tsl2x7x_settings.prox_max_samples_cal = MAX_SAMPLES_CAL; + } + + /* have to stop to change settings */ + tsl2x7x_chip_off(indio_dev); + + /* Enable proximity detection save just in case prox not wanted yet*/ + tmp_irq_settings = chip->tsl2x7x_settings.interrupts_en; + chip->tsl2x7x_settings.interrupts_en |= TSL2X7X_CNTL_PROX_INT_ENBL; + + /*turn on device if not already on*/ + tsl2x7x_chip_on(indio_dev); + + /*gather the samples*/ + for (i = 0; i < chip->tsl2x7x_settings.prox_max_samples_cal; i++) { + mdelay(15); + tsl2x7x_get_prox(indio_dev); + prox_history[i] = chip->prox_data; + dev_info(&chip->client->dev, "2 i=%d prox data= %d\n", + i, chip->prox_data); + } + + tsl2x7x_chip_off(indio_dev); + calP = &prox_stat_data[PROX_STAT_CAL]; + tsl2x7x_prox_calculate(prox_history, + chip->tsl2x7x_settings.prox_max_samples_cal, calP); + chip->tsl2x7x_settings.prox_thres_high = (calP->max << 1) - calP->mean; + + dev_info(&chip->client->dev, " cal min=%d mean=%d max=%d\n", + calP->min, calP->mean, calP->max); + dev_info(&chip->client->dev, + "%s proximity threshold set to %d\n", + chip->client->name, chip->tsl2x7x_settings.prox_thres_high); + + /* back to the way they were */ + chip->tsl2x7x_settings.interrupts_en = tmp_irq_settings; + if (current_state == TSL2X7X_CHIP_WORKING) + tsl2x7x_chip_on(indio_dev); +} + +static ssize_t tsl2x7x_power_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); + + return snprintf(buf, PAGE_SIZE, "%d\n", chip->tsl2x7x_chip_status); +} + +static ssize_t tsl2x7x_power_state_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + bool value; + + if (strtobool(buf, &value)) + return -EINVAL; + + if (value) + tsl2x7x_chip_on(indio_dev); + else + tsl2x7x_chip_off(indio_dev); + + return len; +} + +static ssize_t tsl2x7x_gain_available_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); + + switch (chip->id) { + case tsl2571: + case tsl2671: + case tmd2671: + case tsl2771: + case tmd2771: + return snprintf(buf, PAGE_SIZE, "%s\n", "1 8 16 128"); + } + + return snprintf(buf, PAGE_SIZE, "%s\n", "1 8 16 120"); +} + +static ssize_t tsl2x7x_prox_gain_available_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", "1 2 4 8"); +} + +static ssize_t tsl2x7x_als_time_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); + int y, z; + + y = (TSL2X7X_MAX_TIMER_CNT - (u8)chip->tsl2x7x_settings.als_time) + 1; + z = y * TSL2X7X_MIN_ITIME; + y /= 1000; + z %= 1000; + + return snprintf(buf, PAGE_SIZE, "%d.%03d\n", y, z); +} + +static ssize_t tsl2x7x_als_time_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + struct tsl2x7x_parse_result result; + int ret; + + ret = iio_str_to_fixpoint(buf, 100, &result.integer, &result.fract); + if (ret) + return ret; + + result.fract /= 3; + chip->tsl2x7x_settings.als_time = + (TSL2X7X_MAX_TIMER_CNT - (u8)result.fract); + + dev_info(&chip->client->dev, "%s: als time = %d", + __func__, chip->tsl2x7x_settings.als_time); + + tsl2x7x_invoke_change(indio_dev); + + return IIO_VAL_INT_PLUS_MICRO; +} + +static IIO_CONST_ATTR(in_illuminance0_integration_time_available, + ".00272 - .696"); + +static ssize_t tsl2x7x_als_cal_target_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); + + return snprintf(buf, PAGE_SIZE, "%d\n", + chip->tsl2x7x_settings.als_cal_target); +} + +static ssize_t tsl2x7x_als_cal_target_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + unsigned long value; + + if (kstrtoul(buf, 0, &value)) + return -EINVAL; + + if (value) + chip->tsl2x7x_settings.als_cal_target = value; + + tsl2x7x_invoke_change(indio_dev); + + return len; +} + +/* persistence settings */ +static ssize_t tsl2x7x_als_persistence_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); + int y, z, filter_delay; + + /* Determine integration time */ + y = (TSL2X7X_MAX_TIMER_CNT - (u8)chip->tsl2x7x_settings.als_time) + 1; + z = y * TSL2X7X_MIN_ITIME; + filter_delay = z * (chip->tsl2x7x_settings.persistence & 0x0F); + y = (filter_delay / 1000); + z = (filter_delay % 1000); + + return snprintf(buf, PAGE_SIZE, "%d.%03d\n", y, z); +} + +static ssize_t tsl2x7x_als_persistence_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + struct tsl2x7x_parse_result result; + int y, z, filter_delay; + int ret; + + ret = iio_str_to_fixpoint(buf, 100, &result.integer, &result.fract); + if (ret) + return ret; + + y = (TSL2X7X_MAX_TIMER_CNT - (u8)chip->tsl2x7x_settings.als_time) + 1; + z = y * TSL2X7X_MIN_ITIME; + + filter_delay = + DIV_ROUND_UP(((result.integer * 1000) + result.fract), z); + + chip->tsl2x7x_settings.persistence &= 0xF0; + chip->tsl2x7x_settings.persistence |= (filter_delay & 0x0F); + + dev_info(&chip->client->dev, "%s: als persistence = %d", + __func__, filter_delay); + + tsl2x7x_invoke_change(indio_dev); + + return IIO_VAL_INT_PLUS_MICRO; +} + +static ssize_t tsl2x7x_prox_persistence_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); + int y, z, filter_delay; + + /* Determine integration time */ + y = (TSL2X7X_MAX_TIMER_CNT - (u8)chip->tsl2x7x_settings.prx_time) + 1; + z = y * TSL2X7X_MIN_ITIME; + filter_delay = z * ((chip->tsl2x7x_settings.persistence & 0xF0) >> 4); + y = (filter_delay / 1000); + z = (filter_delay % 1000); + + return snprintf(buf, PAGE_SIZE, "%d.%03d\n", y, z); +} + +static ssize_t tsl2x7x_prox_persistence_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + struct tsl2x7x_parse_result result; + int y, z, filter_delay; + int ret; + + ret = iio_str_to_fixpoint(buf, 100, &result.integer, &result.fract); + if (ret) + return ret; + + y = (TSL2X7X_MAX_TIMER_CNT - (u8)chip->tsl2x7x_settings.prx_time) + 1; + z = y * TSL2X7X_MIN_ITIME; + + filter_delay = + DIV_ROUND_UP(((result.integer * 1000) + result.fract), z); + + chip->tsl2x7x_settings.persistence &= 0x0F; + chip->tsl2x7x_settings.persistence |= ((filter_delay << 4) & 0xF0); + + dev_info(&chip->client->dev, "%s: prox persistence = %d", + __func__, filter_delay); + + tsl2x7x_invoke_change(indio_dev); + + return IIO_VAL_INT_PLUS_MICRO; +} + +static ssize_t tsl2x7x_do_calibrate(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + bool value; + + if (strtobool(buf, &value)) + return -EINVAL; + + if (value) + tsl2x7x_als_calibrate(indio_dev); + + tsl2x7x_invoke_change(indio_dev); + + return len; +} + +static ssize_t tsl2x7x_luxtable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); + int i = 0; + int offset = 0; + + while (i < (TSL2X7X_MAX_LUX_TABLE_SIZE * 3)) { + offset += snprintf(buf + offset, PAGE_SIZE, "%d,%d,%d,", + chip->tsl2x7x_device_lux[i].ratio, + chip->tsl2x7x_device_lux[i].ch0, + chip->tsl2x7x_device_lux[i].ch1); + if (chip->tsl2x7x_device_lux[i].ratio == 0) { + /* We just printed the first "0" entry. + * Now get rid of the extra "," and break. */ + offset--; + break; + } + i++; + } + + offset += snprintf(buf + offset, PAGE_SIZE, "\n"); + return offset; +} + +static ssize_t tsl2x7x_luxtable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + int value[ARRAY_SIZE(chip->tsl2x7x_device_lux)*3 + 1]; + int n; + + get_options(buf, ARRAY_SIZE(value), value); + + /* We now have an array of ints starting at value[1], and + * enumerated by value[0]. + * We expect each group of three ints is one table entry, + * and the last table entry is all 0. + */ + n = value[0]; + if ((n % 3) || n < 6 || + n > ((ARRAY_SIZE(chip->tsl2x7x_device_lux) - 1) * 3)) { + dev_info(dev, "LUX TABLE INPUT ERROR 1 Value[0]=%d\n", n); + return -EINVAL; + } + + if ((value[(n - 2)] | value[(n - 1)] | value[n]) != 0) { + dev_info(dev, "LUX TABLE INPUT ERROR 2 Value[0]=%d\n", n); + return -EINVAL; + } + + if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_WORKING) + tsl2x7x_chip_off(indio_dev); + + /* Zero out the table */ + memset(chip->tsl2x7x_device_lux, 0, sizeof(chip->tsl2x7x_device_lux)); + memcpy(chip->tsl2x7x_device_lux, &value[1], (value[0] * 4)); + + tsl2x7x_invoke_change(indio_dev); + + return len; +} + +static ssize_t tsl2x7x_do_prox_calibrate(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + bool value; + + if (strtobool(buf, &value)) + return -EINVAL; + + if (value) + tsl2x7x_prox_cal(indio_dev); + + tsl2x7x_invoke_change(indio_dev); + + return len; +} + +static int tsl2x7x_read_interrupt_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + int ret; + + if (chan->type == IIO_INTENSITY) + ret = !!(chip->tsl2x7x_settings.interrupts_en & 0x10); + else + ret = !!(chip->tsl2x7x_settings.interrupts_en & 0x20); + + return ret; +} + +static int tsl2x7x_write_interrupt_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int val) +{ + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + + if (chan->type == IIO_INTENSITY) { + if (val) + chip->tsl2x7x_settings.interrupts_en |= 0x10; + else + chip->tsl2x7x_settings.interrupts_en &= 0x20; + } else { + if (val) + chip->tsl2x7x_settings.interrupts_en |= 0x20; + else + chip->tsl2x7x_settings.interrupts_en &= 0x10; + } + + tsl2x7x_invoke_change(indio_dev); + + return 0; +} + +static int tsl2x7x_write_thresh(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + + if (chan->type == IIO_INTENSITY) { + switch (dir) { + case IIO_EV_DIR_RISING: + chip->tsl2x7x_settings.als_thresh_high = val; + break; + case IIO_EV_DIR_FALLING: + chip->tsl2x7x_settings.als_thresh_low = val; + break; + default: + return -EINVAL; + } + } else { + switch (dir) { + case IIO_EV_DIR_RISING: + chip->tsl2x7x_settings.prox_thres_high = val; + break; + case IIO_EV_DIR_FALLING: + chip->tsl2x7x_settings.prox_thres_low = val; + break; + default: + return -EINVAL; + } + } + + tsl2x7x_invoke_change(indio_dev); + + return 0; +} + +static int tsl2x7x_read_thresh(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + + if (chan->type == IIO_INTENSITY) { + switch (dir) { + case IIO_EV_DIR_RISING: + *val = chip->tsl2x7x_settings.als_thresh_high; + break; + case IIO_EV_DIR_FALLING: + *val = chip->tsl2x7x_settings.als_thresh_low; + break; + default: + return -EINVAL; + } + } else { + switch (dir) { + case IIO_EV_DIR_RISING: + *val = chip->tsl2x7x_settings.prox_thres_high; + break; + case IIO_EV_DIR_FALLING: + *val = chip->tsl2x7x_settings.prox_thres_low; + break; + default: + return -EINVAL; + } + } + + return IIO_VAL_INT; +} + +static int tsl2x7x_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + int ret = -EINVAL; + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + switch (chan->type) { + case IIO_LIGHT: + tsl2x7x_get_lux(indio_dev); + *val = chip->als_cur_info.lux; + ret = IIO_VAL_INT; + break; + default: + return -EINVAL; + } + break; + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_INTENSITY: + tsl2x7x_get_lux(indio_dev); + if (chan->channel == 0) + *val = chip->als_cur_info.als_ch0; + else + *val = chip->als_cur_info.als_ch1; + ret = IIO_VAL_INT; + break; + case IIO_PROXIMITY: + tsl2x7x_get_prox(indio_dev); + *val = chip->prox_data; + ret = IIO_VAL_INT; + break; + default: + return -EINVAL; + } + break; + case IIO_CHAN_INFO_CALIBSCALE: + if (chan->type == IIO_LIGHT) + *val = + tsl2X7X_als_gainadj[chip->tsl2x7x_settings.als_gain]; + else + *val = + tsl2X7X_prx_gainadj[chip->tsl2x7x_settings.prox_gain]; + ret = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_CALIBBIAS: + *val = chip->tsl2x7x_settings.als_gain_trim; + ret = IIO_VAL_INT; + break; + + default: + ret = -EINVAL; + } + + return ret; +} + +static int tsl2x7x_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_CALIBSCALE: + if (chan->type == IIO_INTENSITY) { + switch (val) { + case 1: + chip->tsl2x7x_settings.als_gain = 0; + break; + case 8: + chip->tsl2x7x_settings.als_gain = 1; + break; + case 16: + chip->tsl2x7x_settings.als_gain = 2; + break; + case 120: + switch (chip->id) { + case tsl2572: + case tsl2672: + case tmd2672: + case tsl2772: + case tmd2772: + return -EINVAL; + } + chip->tsl2x7x_settings.als_gain = 3; + break; + case 128: + switch (chip->id) { + case tsl2571: + case tsl2671: + case tmd2671: + case tsl2771: + case tmd2771: + return -EINVAL; + } + chip->tsl2x7x_settings.als_gain = 3; + break; + default: + return -EINVAL; + } + } else { + switch (val) { + case 1: + chip->tsl2x7x_settings.prox_gain = 0; + break; + case 2: + chip->tsl2x7x_settings.prox_gain = 1; + break; + case 4: + chip->tsl2x7x_settings.prox_gain = 2; + break; + case 8: + chip->tsl2x7x_settings.prox_gain = 3; + break; + default: + return -EINVAL; + } + } + break; + case IIO_CHAN_INFO_CALIBBIAS: + chip->tsl2x7x_settings.als_gain_trim = val; + break; + + default: + return -EINVAL; + } + + tsl2x7x_invoke_change(indio_dev); + + return 0; +} + +static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, + tsl2x7x_power_state_show, tsl2x7x_power_state_store); + +static DEVICE_ATTR(in_proximity0_calibscale_available, S_IRUGO, + tsl2x7x_prox_gain_available_show, NULL); + +static DEVICE_ATTR(in_illuminance0_calibscale_available, S_IRUGO, + tsl2x7x_gain_available_show, NULL); + +static DEVICE_ATTR(in_illuminance0_integration_time, S_IRUGO | S_IWUSR, + tsl2x7x_als_time_show, tsl2x7x_als_time_store); + +static DEVICE_ATTR(in_illuminance0_target_input, S_IRUGO | S_IWUSR, + tsl2x7x_als_cal_target_show, tsl2x7x_als_cal_target_store); + +static DEVICE_ATTR(in_illuminance0_calibrate, S_IWUSR, NULL, + tsl2x7x_do_calibrate); + +static DEVICE_ATTR(in_proximity0_calibrate, S_IWUSR, NULL, + tsl2x7x_do_prox_calibrate); + +static DEVICE_ATTR(in_illuminance0_lux_table, S_IRUGO | S_IWUSR, + tsl2x7x_luxtable_show, tsl2x7x_luxtable_store); + +static DEVICE_ATTR(in_intensity0_thresh_period, S_IRUGO | S_IWUSR, + tsl2x7x_als_persistence_show, tsl2x7x_als_persistence_store); + +static DEVICE_ATTR(in_proximity0_thresh_period, S_IRUGO | S_IWUSR, + tsl2x7x_prox_persistence_show, tsl2x7x_prox_persistence_store); + +/* Use the default register values to identify the Taos device */ +static int tsl2x7x_device_id(unsigned char *id, int target) +{ + switch (target) { + case tsl2571: + case tsl2671: + case tsl2771: + return (*id & 0xf0) == TRITON_ID; + case tmd2671: + case tmd2771: + return (*id & 0xf0) == HALIBUT_ID; + case tsl2572: + case tsl2672: + case tmd2672: + case tsl2772: + case tmd2772: + return (*id & 0xf0) == SWORDFISH_ID; + } + + return -EINVAL; +} + +static irqreturn_t tsl2x7x_event_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + s64 timestamp = iio_get_time_ns(); + int ret; + u8 value; + + value = i2c_smbus_read_byte_data(chip->client, + TSL2X7X_CMD_REG | TSL2X7X_STATUS); + + /* What type of interrupt do we need to process */ + if (value & TSL2X7X_STA_PRX_INTR) { + tsl2x7x_get_prox(indio_dev); /* freshen data for ABI */ + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, + 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_EITHER), + timestamp); + } + + if (value & TSL2X7X_STA_ALS_INTR) { + tsl2x7x_get_lux(indio_dev); /* freshen data for ABI */ + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_LIGHT, + 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_EITHER), + timestamp); + } + /* Clear interrupt now that we have handled it. */ + ret = i2c_smbus_write_byte(chip->client, + TSL2X7X_CMD_REG | TSL2X7X_CMD_SPL_FN | + TSL2X7X_CMD_PROXALS_INT_CLR); + if (ret < 0) + dev_err(&chip->client->dev, + "%s: Failed to clear irq from event handler. err = %d\n", + __func__, ret); + + return IRQ_HANDLED; +} + +static struct attribute *tsl2x7x_ALS_device_attrs[] = { + &dev_attr_power_state.attr, + &dev_attr_in_illuminance0_calibscale_available.attr, + &dev_attr_in_illuminance0_integration_time.attr, + &iio_const_attr_in_illuminance0_integration_time_available\ + .dev_attr.attr, + &dev_attr_in_illuminance0_target_input.attr, + &dev_attr_in_illuminance0_calibrate.attr, + &dev_attr_in_illuminance0_lux_table.attr, + NULL +}; + +static struct attribute *tsl2x7x_PRX_device_attrs[] = { + &dev_attr_power_state.attr, + &dev_attr_in_proximity0_calibrate.attr, + NULL +}; + +static struct attribute *tsl2x7x_ALSPRX_device_attrs[] = { + &dev_attr_power_state.attr, + &dev_attr_in_illuminance0_calibscale_available.attr, + &dev_attr_in_illuminance0_integration_time.attr, + &iio_const_attr_in_illuminance0_integration_time_available\ + .dev_attr.attr, + &dev_attr_in_illuminance0_target_input.attr, + &dev_attr_in_illuminance0_calibrate.attr, + &dev_attr_in_illuminance0_lux_table.attr, + &dev_attr_in_proximity0_calibrate.attr, + NULL +}; + +static struct attribute *tsl2x7x_PRX2_device_attrs[] = { + &dev_attr_power_state.attr, + &dev_attr_in_proximity0_calibrate.attr, + &dev_attr_in_proximity0_calibscale_available.attr, + NULL +}; + +static struct attribute *tsl2x7x_ALSPRX2_device_attrs[] = { + &dev_attr_power_state.attr, + &dev_attr_in_illuminance0_calibscale_available.attr, + &dev_attr_in_illuminance0_integration_time.attr, + &iio_const_attr_in_illuminance0_integration_time_available\ + .dev_attr.attr, + &dev_attr_in_illuminance0_target_input.attr, + &dev_attr_in_illuminance0_calibrate.attr, + &dev_attr_in_illuminance0_lux_table.attr, + &dev_attr_in_proximity0_calibrate.attr, + &dev_attr_in_proximity0_calibscale_available.attr, + NULL +}; + +static struct attribute *tsl2X7X_ALS_event_attrs[] = { + &dev_attr_in_intensity0_thresh_period.attr, + NULL, +}; +static struct attribute *tsl2X7X_PRX_event_attrs[] = { + &dev_attr_in_proximity0_thresh_period.attr, + NULL, +}; + +static struct attribute *tsl2X7X_ALSPRX_event_attrs[] = { + &dev_attr_in_intensity0_thresh_period.attr, + &dev_attr_in_proximity0_thresh_period.attr, + NULL, +}; + +static const struct attribute_group tsl2X7X_device_attr_group_tbl[] = { + [ALS] = { + .attrs = tsl2x7x_ALS_device_attrs, + }, + [PRX] = { + .attrs = tsl2x7x_PRX_device_attrs, + }, + [ALSPRX] = { + .attrs = tsl2x7x_ALSPRX_device_attrs, + }, + [PRX2] = { + .attrs = tsl2x7x_PRX2_device_attrs, + }, + [ALSPRX2] = { + .attrs = tsl2x7x_ALSPRX2_device_attrs, + }, +}; + +static struct attribute_group tsl2X7X_event_attr_group_tbl[] = { + [ALS] = { + .attrs = tsl2X7X_ALS_event_attrs, + .name = "events", + }, + [PRX] = { + .attrs = tsl2X7X_PRX_event_attrs, + .name = "events", + }, + [ALSPRX] = { + .attrs = tsl2X7X_ALSPRX_event_attrs, + .name = "events", + }, +}; + +static const struct iio_info tsl2X7X_device_info[] = { + [ALS] = { + .attrs = &tsl2X7X_device_attr_group_tbl[ALS], + .event_attrs = &tsl2X7X_event_attr_group_tbl[ALS], + .driver_module = THIS_MODULE, + .read_raw = &tsl2x7x_read_raw, + .write_raw = &tsl2x7x_write_raw, + .read_event_value = &tsl2x7x_read_thresh, + .write_event_value = &tsl2x7x_write_thresh, + .read_event_config = &tsl2x7x_read_interrupt_config, + .write_event_config = &tsl2x7x_write_interrupt_config, + }, + [PRX] = { + .attrs = &tsl2X7X_device_attr_group_tbl[PRX], + .event_attrs = &tsl2X7X_event_attr_group_tbl[PRX], + .driver_module = THIS_MODULE, + .read_raw = &tsl2x7x_read_raw, + .write_raw = &tsl2x7x_write_raw, + .read_event_value = &tsl2x7x_read_thresh, + .write_event_value = &tsl2x7x_write_thresh, + .read_event_config = &tsl2x7x_read_interrupt_config, + .write_event_config = &tsl2x7x_write_interrupt_config, + }, + [ALSPRX] = { + .attrs = &tsl2X7X_device_attr_group_tbl[ALSPRX], + .event_attrs = &tsl2X7X_event_attr_group_tbl[ALSPRX], + .driver_module = THIS_MODULE, + .read_raw = &tsl2x7x_read_raw, + .write_raw = &tsl2x7x_write_raw, + .read_event_value = &tsl2x7x_read_thresh, + .write_event_value = &tsl2x7x_write_thresh, + .read_event_config = &tsl2x7x_read_interrupt_config, + .write_event_config = &tsl2x7x_write_interrupt_config, + }, + [PRX2] = { + .attrs = &tsl2X7X_device_attr_group_tbl[PRX2], + .event_attrs = &tsl2X7X_event_attr_group_tbl[PRX], + .driver_module = THIS_MODULE, + .read_raw = &tsl2x7x_read_raw, + .write_raw = &tsl2x7x_write_raw, + .read_event_value = &tsl2x7x_read_thresh, + .write_event_value = &tsl2x7x_write_thresh, + .read_event_config = &tsl2x7x_read_interrupt_config, + .write_event_config = &tsl2x7x_write_interrupt_config, + }, + [ALSPRX2] = { + .attrs = &tsl2X7X_device_attr_group_tbl[ALSPRX2], + .event_attrs = &tsl2X7X_event_attr_group_tbl[ALSPRX], + .driver_module = THIS_MODULE, + .read_raw = &tsl2x7x_read_raw, + .write_raw = &tsl2x7x_write_raw, + .read_event_value = &tsl2x7x_read_thresh, + .write_event_value = &tsl2x7x_write_thresh, + .read_event_config = &tsl2x7x_read_interrupt_config, + .write_event_config = &tsl2x7x_write_interrupt_config, + }, +}; + +static const struct iio_event_spec tsl2x7x_events[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, +}; + +static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { + [ALS] = { + .channel = { + { + .type = IIO_LIGHT, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + }, { + .type = IIO_INTENSITY, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | + BIT(IIO_CHAN_INFO_CALIBBIAS), + .event_spec = tsl2x7x_events, + .num_event_specs = ARRAY_SIZE(tsl2x7x_events), + }, { + .type = IIO_INTENSITY, + .indexed = 1, + .channel = 1, + }, + }, + .chan_table_elements = 3, + .info = &tsl2X7X_device_info[ALS], + }, + [PRX] = { + .channel = { + { + .type = IIO_PROXIMITY, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .event_spec = tsl2x7x_events, + .num_event_specs = ARRAY_SIZE(tsl2x7x_events), + }, + }, + .chan_table_elements = 1, + .info = &tsl2X7X_device_info[PRX], + }, + [ALSPRX] = { + .channel = { + { + .type = IIO_LIGHT, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) + }, { + .type = IIO_INTENSITY, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | + BIT(IIO_CHAN_INFO_CALIBBIAS), + .event_spec = tsl2x7x_events, + .num_event_specs = ARRAY_SIZE(tsl2x7x_events), + }, { + .type = IIO_INTENSITY, + .indexed = 1, + .channel = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + }, { + .type = IIO_PROXIMITY, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .event_spec = tsl2x7x_events, + .num_event_specs = ARRAY_SIZE(tsl2x7x_events), + }, + }, + .chan_table_elements = 4, + .info = &tsl2X7X_device_info[ALSPRX], + }, + [PRX2] = { + .channel = { + { + .type = IIO_PROXIMITY, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE), + .event_spec = tsl2x7x_events, + .num_event_specs = ARRAY_SIZE(tsl2x7x_events), + }, + }, + .chan_table_elements = 1, + .info = &tsl2X7X_device_info[PRX2], + }, + [ALSPRX2] = { + .channel = { + { + .type = IIO_LIGHT, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + }, { + .type = IIO_INTENSITY, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | + BIT(IIO_CHAN_INFO_CALIBBIAS), + .event_spec = tsl2x7x_events, + .num_event_specs = ARRAY_SIZE(tsl2x7x_events), + }, { + .type = IIO_INTENSITY, + .indexed = 1, + .channel = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + }, { + .type = IIO_PROXIMITY, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE), + .event_spec = tsl2x7x_events, + .num_event_specs = ARRAY_SIZE(tsl2x7x_events), + }, + }, + .chan_table_elements = 4, + .info = &tsl2X7X_device_info[ALSPRX2], + }, +}; + +static int tsl2x7x_probe(struct i2c_client *clientp, + const struct i2c_device_id *id) +{ + int ret; + unsigned char device_id; + struct iio_dev *indio_dev; + struct tsl2X7X_chip *chip; + + indio_dev = devm_iio_device_alloc(&clientp->dev, sizeof(*chip)); + if (!indio_dev) + return -ENOMEM; + + chip = iio_priv(indio_dev); + chip->client = clientp; + i2c_set_clientdata(clientp, indio_dev); + + ret = tsl2x7x_i2c_read(chip->client, + TSL2X7X_CHIPID, &device_id); + if (ret < 0) + return ret; + + if ((!tsl2x7x_device_id(&device_id, id->driver_data)) || + (tsl2x7x_device_id(&device_id, id->driver_data) == -EINVAL)) { + dev_info(&chip->client->dev, + "%s: i2c device found does not match expected id\n", + __func__); + return -EINVAL; + } + + ret = i2c_smbus_write_byte(clientp, (TSL2X7X_CMD_REG | TSL2X7X_CNTRL)); + if (ret < 0) { + dev_err(&clientp->dev, "%s: write to cmd reg failed. err = %d\n", + __func__, ret); + return ret; + } + + /* ALS and PROX functions can be invoked via user space poll + * or H/W interrupt. If busy return last sample. */ + mutex_init(&chip->als_mutex); + mutex_init(&chip->prox_mutex); + + chip->tsl2x7x_chip_status = TSL2X7X_CHIP_UNKNOWN; + chip->pdata = clientp->dev.platform_data; + chip->id = id->driver_data; + chip->chip_info = + &tsl2x7x_chip_info_tbl[device_channel_config[id->driver_data]]; + + indio_dev->info = chip->chip_info->info; + indio_dev->dev.parent = &clientp->dev; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->name = chip->client->name; + indio_dev->channels = chip->chip_info->channel; + indio_dev->num_channels = chip->chip_info->chan_table_elements; + + if (clientp->irq) { + ret = devm_request_threaded_irq(&clientp->dev, clientp->irq, + NULL, + &tsl2x7x_event_handler, + IRQF_TRIGGER_RISING | + IRQF_ONESHOT, + "TSL2X7X_event", + indio_dev); + if (ret) { + dev_err(&clientp->dev, + "%s: irq request failed", __func__); + return ret; + } + } + + /* Load up the defaults */ + tsl2x7x_defaults(chip); + /* Make sure the chip is on */ + tsl2x7x_chip_on(indio_dev); + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&clientp->dev, + "%s: iio registration failed\n", __func__); + return ret; + } + + dev_info(&clientp->dev, "%s Light sensor found.\n", id->name); + + return 0; +} + +static int tsl2x7x_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + int ret = 0; + + if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_WORKING) { + ret = tsl2x7x_chip_off(indio_dev); + chip->tsl2x7x_chip_status = TSL2X7X_CHIP_SUSPENDED; + } + + if (chip->pdata && chip->pdata->platform_power) { + pm_message_t pmm = {PM_EVENT_SUSPEND}; + chip->pdata->platform_power(dev, pmm); + } + + return ret; +} + +static int tsl2x7x_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct tsl2X7X_chip *chip = iio_priv(indio_dev); + int ret = 0; + + if (chip->pdata && chip->pdata->platform_power) { + pm_message_t pmm = {PM_EVENT_RESUME}; + chip->pdata->platform_power(dev, pmm); + } + + if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_SUSPENDED) + ret = tsl2x7x_chip_on(indio_dev); + + return ret; +} + +static int tsl2x7x_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + tsl2x7x_chip_off(indio_dev); + + iio_device_unregister(indio_dev); + + return 0; +} + +static struct i2c_device_id tsl2x7x_idtable[] = { + { "tsl2571", tsl2571 }, + { "tsl2671", tsl2671 }, + { "tmd2671", tmd2671 }, + { "tsl2771", tsl2771 }, + { "tmd2771", tmd2771 }, + { "tsl2572", tsl2572 }, + { "tsl2672", tsl2672 }, + { "tmd2672", tmd2672 }, + { "tsl2772", tsl2772 }, + { "tmd2772", tmd2772 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, tsl2x7x_idtable); + +static const struct dev_pm_ops tsl2x7x_pm_ops = { + .suspend = tsl2x7x_suspend, + .resume = tsl2x7x_resume, +}; + +/* Driver definition */ +static struct i2c_driver tsl2x7x_driver = { + .driver = { + .name = "tsl2x7x", + .pm = &tsl2x7x_pm_ops, + }, + .id_table = tsl2x7x_idtable, + .probe = tsl2x7x_probe, + .remove = tsl2x7x_remove, +}; + +module_i2c_driver(tsl2x7x_driver); + +MODULE_AUTHOR("J. August Brenner<jbrenner@taosinc.com>"); +MODULE_DESCRIPTION("TAOS tsl2x7x ambient and proximity light sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/magnetometer/Kconfig b/drivers/staging/iio/magnetometer/Kconfig index 722c4e13f71..34634da1f9f 100644 --- a/drivers/staging/iio/magnetometer/Kconfig +++ b/drivers/staging/iio/magnetometer/Kconfig @@ -3,25 +3,16 @@ # menu "Magnetometer sensors" -config SENSORS_AK8975 - tristate "Asahi Kasei AK8975 3-Axis Magnetometer" - depends on I2C - depends on GENERIC_GPIO - 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" + tristate "Honeywell HMC5843/5883/5883L 3-Axis Magnetometer" depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER help - Say Y here to add support for the Honeywell HMC 5843 3-Axis - Magnetometer (digital compass). + Say Y here to add support for the Honeywell HMC5843, HMC5883 and + HMC5883L 3-Axis Magnetometer (digital compass). To compile this driver as a module, choose M here: the module - will be called hmc5843 + will be called hmc5843. endmenu diff --git a/drivers/staging/iio/magnetometer/Makefile b/drivers/staging/iio/magnetometer/Makefile index f2a753f8079..f9bfb2e11d7 100644 --- a/drivers/staging/iio/magnetometer/Makefile +++ b/drivers/staging/iio/magnetometer/Makefile @@ -2,5 +2,4 @@ # 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 deleted file mode 100644 index 3158f12cb05..00000000000 --- a/drivers/staging/iio/magnetometer/ak8975.c +++ /dev/null @@ -1,579 +0,0 @@ -/* - * 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 "../sysfs.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 attribute_group attrs; - struct mutex lock; - u8 asa[3]; - long raw_to_gauss[3]; - bool mode; - u8 reg_cache[AK8975_MAX_REGS]; - int eoc_gpio; - int eoc_irq; -}; - -static const int ak8975_index_to_reg[] = { - AK8975_REG_HXL, AK8975_REG_HYL, AK8975_REG_HZL, -}; - -/* - * Helper function to write to the I2C device's registers. - */ -static int ak8975_write_data(struct i2c_client *client, - u8 reg, u8 val, u8 mask, u8 shift) -{ - struct ak8975_data *data = i2c_get_clientdata(client); - u8 regval; - int ret; - - regval = (data->reg_cache[reg] & ~mask) | (val << shift); - ret = i2c_smbus_write_byte_data(client, reg, regval); - if (ret < 0) { - dev_err(&client->dev, "Write to device fails status %x\n", ret); - return ret; - } - 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) -{ - int ret; - struct i2c_msg msg[2] = { - { - .addr = client->addr, - .flags = I2C_M_NOSTART, - .len = 1, - .buf = ®, - }, { - .addr = client->addr, - .flags = I2C_M_RD, - .len = length, - .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 (in Gauss units) for each axis and - * store in the device data. - * - * This scale factor is axis-dependent, and is derived from 3 calibration - * factors ASA(x), ASA(y), and ASA(z). - * - * These ASA values are read from the sensor device at start of day, and - * cached in the device context struct. - * - * Adjusting the flux value with the sensitivity adjustment value should be - * done via the following formula: - * - * Hadj = H * ( ( ( (ASA-128)*0.5 ) / 128 ) + 1 ) - * - * where H is the raw value, ASA is the sensitivity adjustment, and Hadj - * is the resultant adjusted value. - * - * We reduce the formula to: - * - * Hadj = H * (ASA + 128) / 256 - * - * H is in the range of -4096 to 4095. The magnetometer has a range of - * +-1229uT. To go from the raw value to uT is: - * - * HuT = H * 1229/4096, or roughly, 3/10. - * - * Since 1uT = 100 gauss, our final scale factor becomes: - * - * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100 - * Hadj = H * ((ASA + 128) * 30 / 256 - * - * Since ASA doesn't change, we cache the resultant scale factor into the - * device context in ak8975_setup(). - */ - data->raw_to_gauss[0] = ((data->asa[0] + 128) * 30) >> 8; - data->raw_to_gauss[1] = ((data->asa[1] + 128) * 30) >> 8; - data->raw_to_gauss[2] = ((data->asa[2] + 128) * 30) >> 8; - - 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 = iio_priv(indio_dev); - - return sprintf(buf, "%u\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 = iio_priv(indio_dev); - struct i2c_client *client = data->client; - bool value; - int ret; - - /* Convert mode string and do some basic sanity checking on it. - only 0 or 1 are valid. */ - ret = strtobool(buf, &value); - if (ret < 0) - return ret; - - mutex_lock(&data->lock); - - /* Write the mode to the device. */ - if (data->mode != value) { - ret = ak8975_write_data(client, - AK8975_REG_CNTL, - (u8)value, - 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 = value; - } - - mutex_unlock(&data->lock); - - return count; -} - -static int wait_conversion_complete_gpio(struct ak8975_data *data) -{ - struct i2c_client *client = data->client; - u8 read_status; - u32 timeout_ms = AK8975_MAX_CONVERSION_TIMEOUT; - int ret; - - /* Wait for the conversion to complete. */ - while (timeout_ms) { - msleep(AK8975_CONVERSION_DONE_POLL_TIME); - if (gpio_get_value(data->eoc_gpio)) - break; - timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME; - } - if (!timeout_ms) { - dev_err(&client->dev, "Conversion timeout happened\n"); - return -EINVAL; - } - - ret = ak8975_read_data(client, AK8975_REG_ST1, 1, &read_status); - if (ret < 0) { - dev_err(&client->dev, "Error in reading ST1\n"); - return ret; - } - return read_status; -} - -static int wait_conversion_complete_polled(struct ak8975_data *data) -{ - struct i2c_client *client = data->client; - u8 read_status; - u32 timeout_ms = AK8975_MAX_CONVERSION_TIMEOUT; - int ret; - - /* Wait for the conversion to complete. */ - while (timeout_ms) { - msleep(AK8975_CONVERSION_DONE_POLL_TIME); - ret = ak8975_read_data(client, AK8975_REG_ST1, 1, &read_status); - if (ret < 0) { - dev_err(&client->dev, "Error in reading ST1\n"); - return ret; - } - if (read_status) - break; - timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME; - } - if (!timeout_ms) { - dev_err(&client->dev, "Conversion timeout happened\n"); - return -EINVAL; - } - return read_status; -} - -/* - * Emits the raw flux value for the x, y, or z axis. - */ -static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) -{ - struct ak8975_data *data = iio_priv(indio_dev); - struct i2c_client *client = data->client; - 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. */ - if (gpio_is_valid(data->eoc_gpio)) - ret = wait_conversion_complete_gpio(data); - else - ret = wait_conversion_complete_polled(data); - if (ret < 0) - goto exit; - - read_status = ret; - - 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, ak8975_index_to_reg[index], - 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); - *val = raw; - return IIO_VAL_INT; - -exit: - mutex_unlock(&data->lock); - return ret; -} - -static int ak8975_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) -{ - struct ak8975_data *data = iio_priv(indio_dev); - - switch (mask) { - case 0: - return ak8975_read_axis(indio_dev, chan->address, val); - case IIO_CHAN_INFO_SCALE: - *val = data->raw_to_gauss[chan->address]; - return IIO_VAL_INT; - } - return -EINVAL; -} - -#define AK8975_CHANNEL(axis, index) \ - { \ - .type = IIO_MAGN, \ - .modified = 1, \ - .channel2 = IIO_MOD_##axis, \ - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ - .address = index, \ - } - -static const struct iio_chan_spec ak8975_channels[] = { - AK8975_CHANNEL(X, 0), AK8975_CHANNEL(Y, 1), AK8975_CHANNEL(Z, 2), -}; - -static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, show_mode, store_mode, 0); - -static struct attribute *ak8975_attr[] = { - &iio_dev_attr_mode.dev_attr.attr, - NULL -}; - -static struct attribute_group ak8975_attr_group = { - .attrs = ak8975_attr, -}; - -static const struct iio_info ak8975_info = { - .attrs = &ak8975_attr_group, - .read_raw = &ak8975_read_raw, - .driver_module = THIS_MODULE, -}; - -static int ak8975_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct ak8975_data *data; - struct iio_dev *indio_dev; - int eoc_gpio; - int err; - - /* Grab and set up the supplied GPIO. */ - if (client->dev.platform_data == NULL) - eoc_gpio = -1; - else - eoc_gpio = *(int *)(client->dev.platform_data); - - /* We may not have a GPIO based IRQ to scan, that is fine, we will - poll if so */ - if (gpio_is_valid(eoc_gpio)) { - err = gpio_request(eoc_gpio, "ak_8975"); - if (err < 0) { - dev_err(&client->dev, - "failed to request GPIO %d, error %d\n", - eoc_gpio, err); - goto exit; - } - - err = gpio_direction_input(eoc_gpio); - if (err < 0) { - dev_err(&client->dev, - "Failed to configure input direction for GPIO %d, error %d\n", - eoc_gpio, err); - goto exit_gpio; - } - } - - /* Register with IIO */ - indio_dev = iio_allocate_device(sizeof(*data)); - if (indio_dev == NULL) { - err = -ENOMEM; - goto exit_gpio; - } - data = iio_priv(indio_dev); - /* 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_free_iio; - } - - i2c_set_clientdata(client, indio_dev); - data->client = client; - mutex_init(&data->lock); - data->eoc_irq = client->irq; - data->eoc_gpio = eoc_gpio; - indio_dev->dev.parent = &client->dev; - indio_dev->channels = ak8975_channels; - indio_dev->num_channels = ARRAY_SIZE(ak8975_channels); - indio_dev->info = &ak8975_info; - indio_dev->modes = INDIO_DIRECT_MODE; - - err = iio_device_register(indio_dev); - if (err < 0) - goto exit_free_iio; - - return 0; - -exit_free_iio: - iio_free_device(indio_dev); -exit_gpio: - if (gpio_is_valid(eoc_gpio)) - gpio_free(eoc_gpio); -exit: - return err; -} - -static int ak8975_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct ak8975_data *data = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - if (gpio_is_valid(data->eoc_gpio)) - gpio_free(data->eoc_gpio); - - iio_free_device(indio_dev); - - 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, -}; -module_i2c_driver(ak8975_driver); - -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 f2e85a9cf19..d4f4dd90c69 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -1,6 +1,8 @@ /* Copyright (C) 2010 Texas Instruments Author: Shubhrajyoti Datta <shubhrajyoti@ti.com> - Acknowledgement: Jonathan Cameron <jic23@cam.ac.uk> for valuable inputs. + Acknowledgement: Jonathan Cameron <jic23@kernel.org> for valuable inputs. + + Support for HMC5883 and HMC5883L by Peter Meerwald <pmeerw@pmeerw.net>. 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 @@ -18,250 +20,214 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/i2c.h> -#include <linux/slab.h> -#include <linux/types.h> -#include "../iio.h" -#include "../sysfs.h" - -#define HMC5843_I2C_ADDRESS 0x1E +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/buffer.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/delay.h> #define HMC5843_CONFIG_REG_A 0x00 #define HMC5843_CONFIG_REG_B 0x01 #define HMC5843_MODE_REG 0x02 -#define HMC5843_DATA_OUT_X_MSB_REG 0x03 -#define HMC5843_DATA_OUT_X_LSB_REG 0x04 -#define HMC5843_DATA_OUT_Y_MSB_REG 0x05 -#define HMC5843_DATA_OUT_Y_LSB_REG 0x06 -#define HMC5843_DATA_OUT_Z_MSB_REG 0x07 -#define HMC5843_DATA_OUT_Z_LSB_REG 0x08 +#define HMC5843_DATA_OUT_MSB_REGS 0x03 #define HMC5843_STATUS_REG 0x09 -#define HMC5843_ID_REG_A 0x0A -#define HMC5843_ID_REG_B 0x0B -#define HMC5843_ID_REG_C 0x0C - -#define HMC5843_ID_REG_LENGTH 0x03 -#define HMC5843_ID_STRING "H43" +#define HMC5843_ID_REG 0x0a -/* - * Range settings in (+-)Ga - * */ -#define RANGE_GAIN_OFFSET 0x05 - -#define RANGE_0_7 0x00 -#define RANGE_1_0 0x01 /* default */ -#define RANGE_1_5 0x02 -#define RANGE_2_0 0x03 -#define RANGE_3_2 0x04 -#define RANGE_3_8 0x05 -#define RANGE_4_5 0x06 -#define RANGE_6_5 0x07 /* Not recommended */ +enum hmc5843_ids { + HMC5843_ID, + HMC5883_ID, + HMC5883L_ID, +}; /* - * Device status + * Range gain settings in (+-)Ga + * Beware: HMC5843 and HMC5883 have different recommended sensor field + * ranges; default corresponds to +-1.0 Ga and +-1.3 Ga, respectively */ -#define DATA_READY 0x01 -#define DATA_OUTPUT_LOCK 0x02 -#define VOLTAGE_REGULATOR_ENABLED 0x04 +#define HMC5843_RANGE_GAIN_OFFSET 0x05 +#define HMC5843_RANGE_GAIN_DEFAULT 0x01 +#define HMC5843_RANGE_GAINS 8 -/* - * Mode register configuration - */ -#define MODE_CONVERSION_CONTINUOUS 0x00 -#define MODE_CONVERSION_SINGLE 0x01 -#define MODE_IDLE 0x02 -#define MODE_SLEEP 0x03 - -/* Minimum Data Output Rate in 1/10 Hz */ -#define RATE_OFFSET 0x02 -#define RATE_BITMASK 0x1C -#define RATE_5 0x00 -#define RATE_10 0x01 -#define RATE_20 0x02 -#define RATE_50 0x03 -#define RATE_100 0x04 -#define RATE_200 0x05 -#define RATE_500 0x06 -#define RATE_NOT_USED 0x07 +/* Device status */ +#define HMC5843_DATA_READY 0x01 +#define HMC5843_DATA_OUTPUT_LOCK 0x02 + +/* Mode register configuration */ +#define HMC5843_MODE_CONVERSION_CONTINUOUS 0x00 +#define HMC5843_MODE_CONVERSION_SINGLE 0x01 +#define HMC5843_MODE_IDLE 0x02 +#define HMC5843_MODE_SLEEP 0x03 +#define HMC5843_MODE_MASK 0x03 /* - * Device Configutration + * HMC5843: Minimum data output rate + * HMC5883: Typical data output rate */ -#define CONF_NORMAL 0x00 -#define CONF_POSITIVE_BIAS 0x01 -#define CONF_NEGATIVE_BIAS 0x02 -#define CONF_NOT_USED 0x03 -#define MEAS_CONF_MASK 0x03 - -static int hmc5843_regval_to_nanoscale[] = { +#define HMC5843_RATE_OFFSET 0x02 +#define HMC5843_RATE_DEFAULT 0x04 +#define HMC5843_RATES 7 + +/* Device measurement configuration */ +#define HMC5843_MEAS_CONF_NORMAL 0x00 +#define HMC5843_MEAS_CONF_POSITIVE_BIAS 0x01 +#define HMC5843_MEAS_CONF_NEGATIVE_BIAS 0x02 +#define HMC5843_MEAS_CONF_MASK 0x03 + +/* Scaling factors: 10000000/Gain */ +static const int hmc5843_regval_to_nanoscale[HMC5843_RANGE_GAINS] = { 6173, 7692, 10309, 12821, 18868, 21739, 25641, 35714 }; -static const int regval_to_input_field_mg[] = { - 700, - 1000, - 1500, - 2000, - 3200, - 3800, - 4500, - 6500 +static const int hmc5883_regval_to_nanoscale[HMC5843_RANGE_GAINS] = { + 7812, 9766, 13021, 16287, 24096, 27701, 32573, 45662 +}; + +static const int hmc5883l_regval_to_nanoscale[HMC5843_RANGE_GAINS] = { + 7299, 9174, 12195, 15152, 22727, 25641, 30303, 43478 }; -static const char * const regval_to_samp_freq[] = { - "0.5", - "1", - "2", - "5", - "10", - "20", - "50", + +/* + * From the datasheet: + * Value | HMC5843 | HMC5883/HMC5883L + * | Data output rate (Hz) | Data output rate (Hz) + * 0 | 0.5 | 0.75 + * 1 | 1 | 1.5 + * 2 | 2 | 3 + * 3 | 5 | 7.5 + * 4 | 10 (default) | 15 + * 5 | 20 | 30 + * 6 | 50 | 75 + * 7 | Not used | Not used + */ +static const int hmc5843_regval_to_samp_freq[7][2] = { + {0, 500000}, {1, 0}, {2, 0}, {5, 0}, {10, 0}, {20, 0}, {50, 0} }; -/* Addresses to scan: 0x1E */ -static const unsigned short normal_i2c[] = { HMC5843_I2C_ADDRESS, - I2C_CLIENT_END }; +static const int hmc5883_regval_to_samp_freq[7][2] = { + {0, 750000}, {1, 500000}, {3, 0}, {7, 500000}, {15, 0}, {30, 0}, + {75, 0} +}; + +/* Describe chip variants */ +struct hmc5843_chip_info { + const struct iio_chan_spec *channels; + const int (*regval_to_samp_freq)[2]; + const int *regval_to_nanoscale; +}; /* Each client has this additional data */ struct hmc5843_data { + struct i2c_client *client; struct mutex lock; - u8 rate; - u8 meas_conf; - u8 operating_mode; - u8 range; + u8 rate; + u8 meas_conf; + u8 operating_mode; + u8 range; + const struct hmc5843_chip_info *variant; + __be16 buffer[8]; /* 3x 16-bit channels + padding + 64-bit timestamp */ }; -static void hmc5843_init_client(struct i2c_client *client); +/* The lower two bits contain the current conversion mode */ +static s32 hmc5843_set_mode(struct hmc5843_data *data, u8 operating_mode) +{ + int ret; + + mutex_lock(&data->lock); + ret = i2c_smbus_write_byte_data(data->client, HMC5843_MODE_REG, + operating_mode & HMC5843_MODE_MASK); + if (ret >= 0) + data->operating_mode = operating_mode; + mutex_unlock(&data->lock); + + return ret; +} -static s32 hmc5843_configure(struct i2c_client *client, - u8 operating_mode) +static int hmc5843_wait_measurement(struct hmc5843_data *data) { - /* The lower two bits contain the current conversion mode */ - return i2c_smbus_write_byte_data(client, - HMC5843_MODE_REG, - (operating_mode & 0x03)); + s32 result; + int tries = 150; + + while (tries-- > 0) { + result = i2c_smbus_read_byte_data(data->client, + HMC5843_STATUS_REG); + if (result < 0) + return result; + if (result & HMC5843_DATA_READY) + break; + msleep(20); + } + + if (tries < 0) { + dev_err(&data->client->dev, "data not ready\n"); + return -EIO; + } + + return 0; } -/* Return the measurement value from the specified channel */ -static int hmc5843_read_measurement(struct iio_dev *indio_dev, - int address, - int *val) +/* Return the measurement value from the specified channel */ +static int hmc5843_read_measurement(struct hmc5843_data *data, + int idx, int *val) { - struct i2c_client *client = to_i2c_client(indio_dev->dev.parent); - struct hmc5843_data *data = iio_priv(indio_dev); s32 result; + __be16 values[3]; mutex_lock(&data->lock); - result = i2c_smbus_read_byte_data(client, HMC5843_STATUS_REG); - while (!(result & DATA_READY)) - result = i2c_smbus_read_byte_data(client, HMC5843_STATUS_REG); - - result = i2c_smbus_read_word_data(client, address); + result = hmc5843_wait_measurement(data); + if (result < 0) { + mutex_unlock(&data->lock); + return result; + } + result = i2c_smbus_read_i2c_block_data(data->client, + HMC5843_DATA_OUT_MSB_REGS, sizeof(values), (u8 *) values); mutex_unlock(&data->lock); if (result < 0) return -EINVAL; - *val = (s16)swab16((u16)result); + *val = sign_extend32(be16_to_cpu(values[idx]), 15); return IIO_VAL_INT; } - /* - * From the datasheet - * 0 - Continuous-Conversion Mode: In continuous-conversion mode, the - * device continuously performs conversions an places the result in the - * data register. + * API for setting the measurement configuration to + * Normal, Positive bias and Negative bias * - * 1 - Single-Conversion Mode : device performs a single measurement, - * sets RDY high and returned to sleep mode + * From the datasheet: + * 0 - Normal measurement configuration (default): In normal measurement + * configuration the device follows normal measurement flow. Pins BP + * and BN are left floating and high impedance. * - * 2 - Idle Mode : Device is placed in idle mode. + * 1 - Positive bias configuration: In positive bias configuration, a + * positive current is forced across the resistive load on pins BP + * and BN. * - * 3 - Sleep Mode. Device is placed in sleep mode. + * 2 - Negative bias configuration. In negative bias configuration, a + * negative current is forced across the resistive load on pins BP + * and BN. * */ -static ssize_t hmc5843_show_operating_mode(struct device *dev, - struct device_attribute *attr, - char *buf) +static s32 hmc5843_set_meas_conf(struct hmc5843_data *data, u8 meas_conf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct hmc5843_data *data = iio_priv(indio_dev); - return sprintf(buf, "%d\n", data->operating_mode); -} + int ret; -static ssize_t hmc5843_set_operating_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct i2c_client *client = to_i2c_client(indio_dev->dev.parent); - struct hmc5843_data *data = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - unsigned long operating_mode = 0; - s32 status; - int error; mutex_lock(&data->lock); - error = strict_strtoul(buf, 10, &operating_mode); - if (error) { - count = error; - goto exit; - } - dev_dbg(dev, "set Conversion mode to %lu\n", operating_mode); - if (operating_mode > MODE_SLEEP) { - count = -EINVAL; - goto exit; - } - - status = i2c_smbus_write_byte_data(client, this_attr->address, - operating_mode); - if (status) { - count = -EINVAL; - goto exit; - } - data->operating_mode = operating_mode; - -exit: + ret = i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_A, + (meas_conf & HMC5843_MEAS_CONF_MASK) | + (data->rate << HMC5843_RATE_OFFSET)); + if (ret >= 0) + data->meas_conf = meas_conf; mutex_unlock(&data->lock); - return count; -} -static IIO_DEVICE_ATTR(operating_mode, - S_IWUSR | S_IRUGO, - hmc5843_show_operating_mode, - hmc5843_set_operating_mode, - HMC5843_MODE_REG); -/* - * API for setting the measurement configuration to - * Normal, Positive bias and Negative bias - * From the datasheet - * - * Normal measurement configuration (default): In normal measurement - * configuration the device follows normal measurement flow. Pins BP and BN - * are left floating and high impedance. - * - * Positive bias configuration: In positive bias configuration, a positive - * current is forced across the resistive load on pins BP and BN. - * - * Negative bias configuration. In negative bias configuration, a negative - * current is forced across the resistive load on pins BP and BN. - * - */ -static s32 hmc5843_set_meas_conf(struct i2c_client *client, - u8 meas_conf) -{ - struct hmc5843_data *data = i2c_get_clientdata(client); - u8 reg_val; - reg_val = (meas_conf & MEAS_CONF_MASK) | (data->rate << RATE_OFFSET); - return i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_A, reg_val); + return ret; } static ssize_t hmc5843_show_measurement_configuration(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct hmc5843_data *data = iio_priv(indio_dev); + struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev)); return sprintf(buf, "%d\n", data->meas_conf); } @@ -270,228 +236,248 @@ static ssize_t hmc5843_set_measurement_configuration(struct device *dev, const char *buf, size_t count) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct i2c_client *client = to_i2c_client(indio_dev->dev.parent); - struct hmc5843_data *data = i2c_get_clientdata(client); + struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev)); unsigned long meas_conf = 0; - int error = strict_strtoul(buf, 10, &meas_conf); - if (error) - return error; - mutex_lock(&data->lock); + int ret; - dev_dbg(dev, "set mode to %lu\n", meas_conf); - if (hmc5843_set_meas_conf(client, meas_conf)) { - count = -EINVAL; - goto exit; - } - data->meas_conf = meas_conf; + ret = kstrtoul(buf, 10, &meas_conf); + if (ret) + return ret; + if (meas_conf >= HMC5843_MEAS_CONF_MASK) + return -EINVAL; -exit: - mutex_unlock(&data->lock); - return count; + ret = hmc5843_set_meas_conf(data, meas_conf); + + return (ret < 0) ? ret : count; } + static IIO_DEVICE_ATTR(meas_conf, S_IWUSR | S_IRUGO, hmc5843_show_measurement_configuration, hmc5843_set_measurement_configuration, 0); -/* - * From Datasheet - * The table shows the minimum data output - * Value | Minimum data output rate(Hz) - * 0 | 0.5 - * 1 | 1 - * 2 | 2 - * 3 | 5 - * 4 | 10 (default) - * 5 | 20 - * 6 | 50 - * 7 | Not used - */ -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) +static ssize_t hmc5843_show_samp_freq_avail(struct device *dev, + struct device_attribute *attr, char *buf) { - struct hmc5843_data *data = i2c_get_clientdata(client); - u8 reg_val; + struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev)); + size_t len = 0; + int i; - reg_val = (data->meas_conf) | (rate << RATE_OFFSET); - if (rate >= RATE_NOT_USED) { - dev_err(&client->dev, - "This data output rate is not supported\n"); - return -EINVAL; - } - return i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_A, reg_val); + for (i = 0; i < HMC5843_RATES; i++) + len += scnprintf(buf + len, PAGE_SIZE - len, + "%d.%d ", data->variant->regval_to_samp_freq[i][0], + data->variant->regval_to_samp_freq[i][1]); + + /* replace trailing space by newline */ + buf[len - 1] = '\n'; + + return len; } -static ssize_t set_sampling_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ +static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hmc5843_show_samp_freq_avail); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct i2c_client *client = to_i2c_client(indio_dev->dev.parent); - struct hmc5843_data *data = iio_priv(indio_dev); - unsigned long rate = 0; - - if (strncmp(buf, "0.5" , 3) == 0) - rate = RATE_5; - else if (strncmp(buf, "1" , 1) == 0) - rate = RATE_10; - else if (strncmp(buf, "2", 1) == 0) - rate = RATE_20; - else if (strncmp(buf, "5", 1) == 0) - rate = RATE_50; - else if (strncmp(buf, "10", 2) == 0) - rate = RATE_100; - else if (strncmp(buf, "20" , 2) == 0) - rate = RATE_200; - else if (strncmp(buf, "50" , 2) == 0) - rate = RATE_500; - else - return -EINVAL; +static int hmc5843_set_samp_freq(struct hmc5843_data *data, u8 rate) +{ + int ret; mutex_lock(&data->lock); - dev_dbg(dev, "set rate to %lu\n", rate); - if (hmc5843_set_rate(client, rate)) { - count = -EINVAL; - goto exit; - } - data->rate = rate; - -exit: + ret = i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_A, + data->meas_conf | (rate << HMC5843_RATE_OFFSET)); + if (ret >= 0) + data->rate = rate; mutex_unlock(&data->lock); - return count; + + return ret; } -static ssize_t show_sampling_frequency(struct device *dev, - struct device_attribute *attr, char *buf) +static int hmc5843_get_samp_freq_index(struct hmc5843_data *data, + int val, int val2) { - 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); - s32 rate; - - rate = i2c_smbus_read_byte_data(client, this_attr->address); - if (rate < 0) - return rate; - rate = (rate & RATE_BITMASK) >> RATE_OFFSET; - return sprintf(buf, "%s\n", regval_to_samp_freq[rate]); + int i; + + for (i = 0; i < HMC5843_RATES; i++) + if (val == data->variant->regval_to_samp_freq[i][0] && + val2 == data->variant->regval_to_samp_freq[i][1]) + return i; + + return -EINVAL; } -static IIO_DEVICE_ATTR(sampling_frequency, - S_IWUSR | S_IRUGO, - show_sampling_frequency, - set_sampling_frequency, - HMC5843_CONFIG_REG_A); -/* - * From Datasheet - * Nominal gain settings - * Value | Sensor Input Field Range(Ga) | Gain(counts/ milli-gauss) - *0 |(+-)0.7 |1620 - *1 |(+-)1.0 |1300 - *2 |(+-)1.5 |970 - *3 |(+-)2.0 |780 - *4 |(+-)3.2 |530 - *5 |(+-)3.8 |460 - *6 |(+-)4.5 |390 - *7 |(+-)6.5 |280 - */ -static ssize_t show_range(struct device *dev, - struct device_attribute *attr, - char *buf) +static int hmc5843_set_range_gain(struct hmc5843_data *data, u8 range) { - u8 range; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct hmc5843_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->lock); + ret = i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_B, + range << HMC5843_RANGE_GAIN_OFFSET); + if (ret >= 0) + data->range = range; + mutex_unlock(&data->lock); - range = data->range; - return sprintf(buf, "%d\n", regval_to_input_field_mg[range]); + return ret; } -static ssize_t set_range(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) +static ssize_t hmc5843_show_scale_avail(struct device *dev, + struct device_attribute *attr, char *buf) { - 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); - struct hmc5843_data *data = iio_priv(indio_dev); - unsigned long range = 0; - int error; - mutex_lock(&data->lock); - error = strict_strtoul(buf, 10, &range); - if (error) { - count = error; - goto exit; - } - dev_dbg(dev, "set range to %lu\n", range); + struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev)); - if (range > RANGE_6_5) { - count = -EINVAL; - goto exit; - } + size_t len = 0; + int i; - data->range = range; - range = range << RANGE_GAIN_OFFSET; - if (i2c_smbus_write_byte_data(client, this_attr->address, range)) - count = -EINVAL; + for (i = 0; i < HMC5843_RANGE_GAINS; i++) + len += scnprintf(buf + len, PAGE_SIZE - len, + "0.%09d ", data->variant->regval_to_nanoscale[i]); -exit: - mutex_unlock(&data->lock); - return count; + /* replace trailing space by newline */ + buf[len - 1] = '\n'; + return len; +} + +static IIO_DEVICE_ATTR(scale_available, S_IRUGO, + hmc5843_show_scale_avail, NULL, 0); + +static int hmc5843_get_scale_index(struct hmc5843_data *data, int val, int val2) +{ + int i; + + if (val != 0) + return -EINVAL; + + for (i = 0; i < HMC5843_RANGE_GAINS; i++) + if (val2 == data->variant->regval_to_nanoscale[i]) + return i; + + return -EINVAL; } -static IIO_DEVICE_ATTR(in_magn_range, - S_IWUSR | S_IRUGO, - show_range, - set_range, - HMC5843_CONFIG_REG_B); static int hmc5843_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) + int *val, int *val2, long mask) { struct hmc5843_data *data = iio_priv(indio_dev); switch (mask) { - case 0: - return hmc5843_read_measurement(indio_dev, - chan->address, - val); + case IIO_CHAN_INFO_RAW: + return hmc5843_read_measurement(data, chan->scan_index, val); case IIO_CHAN_INFO_SCALE: *val = 0; - *val2 = hmc5843_regval_to_nanoscale[data->range]; + *val2 = data->variant->regval_to_nanoscale[data->range]; return IIO_VAL_INT_PLUS_NANO; - }; + case IIO_CHAN_INFO_SAMP_FREQ: + *val = data->variant->regval_to_samp_freq[data->rate][0]; + *val2 = data->variant->regval_to_samp_freq[data->rate][1]; + return IIO_VAL_INT_PLUS_MICRO; + } return -EINVAL; } -#define HMC5843_CHANNEL(axis, add) \ +static int hmc5843_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct hmc5843_data *data = iio_priv(indio_dev); + int rate, range; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + rate = hmc5843_get_samp_freq_index(data, val, val2); + if (rate < 0) + return -EINVAL; + + return hmc5843_set_samp_freq(data, rate); + case IIO_CHAN_INFO_SCALE: + range = hmc5843_get_scale_index(data, val, val2); + if (range < 0) + return -EINVAL; + + return hmc5843_set_range_gain(data, range); + default: + return -EINVAL; + } +} + +static int hmc5843_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SCALE: + return IIO_VAL_INT_PLUS_NANO; + default: + return -EINVAL; + } +} + +static irqreturn_t hmc5843_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct hmc5843_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->lock); + ret = hmc5843_wait_measurement(data); + if (ret < 0) { + mutex_unlock(&data->lock); + goto done; + } + + ret = i2c_smbus_read_i2c_block_data(data->client, + HMC5843_DATA_OUT_MSB_REGS, 3 * sizeof(__be16), + (u8 *) data->buffer); + mutex_unlock(&data->lock); + if (ret < 0) + goto done; + + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_get_time_ns()); + +done: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +#define HMC5843_CHANNEL(axis, idx) \ { \ .type = IIO_MAGN, \ .modified = 1, \ .channel2 = IIO_MOD_##axis, \ - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ - .address = add \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = idx, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_BE, \ + }, \ } static const struct iio_chan_spec hmc5843_channels[] = { - HMC5843_CHANNEL(X, HMC5843_DATA_OUT_X_MSB_REG), - HMC5843_CHANNEL(Y, HMC5843_DATA_OUT_Y_MSB_REG), - HMC5843_CHANNEL(Z, HMC5843_DATA_OUT_Z_MSB_REG), + HMC5843_CHANNEL(X, 0), + HMC5843_CHANNEL(Y, 1), + HMC5843_CHANNEL(Z, 2), + IIO_CHAN_SOFT_TIMESTAMP(3), +}; + +/* Beware: Y and Z are exchanged on HMC5883 */ +static const struct iio_chan_spec hmc5883_channels[] = { + HMC5843_CHANNEL(X, 0), + HMC5843_CHANNEL(Z, 1), + HMC5843_CHANNEL(Y, 2), + IIO_CHAN_SOFT_TIMESTAMP(3), }; static struct attribute *hmc5843_attributes[] = { &iio_dev_attr_meas_conf.dev_attr.attr, - &iio_dev_attr_operating_mode.dev_attr.attr, - &iio_dev_attr_sampling_frequency.dev_attr.attr, - &iio_dev_attr_in_magn_range.dev_attr.attr, - &iio_const_attr_sampling_frequency_available.dev_attr.attr, + &iio_dev_attr_scale_available.dev_attr.attr, + &iio_dev_attr_sampling_frequency_available.dev_attr.attr, NULL }; @@ -499,81 +485,104 @@ static const struct attribute_group hmc5843_group = { .attrs = hmc5843_attributes, }; -static int hmc5843_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - unsigned char id_str[HMC5843_ID_REG_LENGTH]; - - if (client->addr != HMC5843_I2C_ADDRESS) - return -ENODEV; - - if (i2c_smbus_read_i2c_block_data(client, HMC5843_ID_REG_A, - HMC5843_ID_REG_LENGTH, id_str) - != HMC5843_ID_REG_LENGTH) - return -ENODEV; +static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = { + [HMC5843_ID] = { + .channels = hmc5843_channels, + .regval_to_samp_freq = hmc5843_regval_to_samp_freq, + .regval_to_nanoscale = hmc5843_regval_to_nanoscale, + }, + [HMC5883_ID] = { + .channels = hmc5883_channels, + .regval_to_samp_freq = hmc5883_regval_to_samp_freq, + .regval_to_nanoscale = hmc5883_regval_to_nanoscale, + }, + [HMC5883L_ID] = { + .channels = hmc5883_channels, + .regval_to_samp_freq = hmc5883_regval_to_samp_freq, + .regval_to_nanoscale = hmc5883l_regval_to_nanoscale, + }, +}; - if (0 != strncmp(id_str, HMC5843_ID_STRING, HMC5843_ID_REG_LENGTH)) +static int hmc5843_init(struct hmc5843_data *data) +{ + int ret; + u8 id[3]; + + ret = i2c_smbus_read_i2c_block_data(data->client, HMC5843_ID_REG, + sizeof(id), id); + if (ret < 0) + return ret; + if (id[0] != 'H' || id[1] != '4' || id[2] != '3') { + dev_err(&data->client->dev, "no HMC5843/5883/5883L sensor\n"); return -ENODEV; + } - return 0; -} - -/* Called when we have found a new HMC5843. */ -static void hmc5843_init_client(struct i2c_client *client) -{ - struct hmc5843_data *data = i2c_get_clientdata(client); - hmc5843_set_meas_conf(client, data->meas_conf); - hmc5843_set_rate(client, data->rate); - hmc5843_configure(client, data->operating_mode); - i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_B, data->range); - mutex_init(&data->lock); - pr_info("HMC5843 initialized\n"); + ret = hmc5843_set_meas_conf(data, HMC5843_MEAS_CONF_NORMAL); + if (ret < 0) + return ret; + ret = hmc5843_set_samp_freq(data, HMC5843_RATE_DEFAULT); + if (ret < 0) + return ret; + ret = hmc5843_set_range_gain(data, HMC5843_RANGE_GAIN_DEFAULT); + if (ret < 0) + return ret; + return hmc5843_set_mode(data, HMC5843_MODE_CONVERSION_CONTINUOUS); } static const struct iio_info hmc5843_info = { .attrs = &hmc5843_group, .read_raw = &hmc5843_read_raw, + .write_raw = &hmc5843_write_raw, + .write_raw_get_fmt = &hmc5843_write_raw_get_fmt, .driver_module = THIS_MODULE, }; +static const unsigned long hmc5843_scan_masks[] = {0x7, 0}; + static int hmc5843_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct hmc5843_data *data; struct iio_dev *indio_dev; - int err = 0; + int ret; - indio_dev = iio_allocate_device(sizeof(*data)); - if (indio_dev == NULL) { - err = -ENOMEM; - goto exit; - } - data = iio_priv(indio_dev); - /* default settings at probe */ + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (indio_dev == NULL) + return -ENOMEM; - data->meas_conf = CONF_NORMAL; - data->range = RANGE_1_0; - data->operating_mode = MODE_CONVERSION_CONTINUOUS; + /* default settings at probe */ + data = iio_priv(indio_dev); + data->client = client; + data->variant = &hmc5843_chip_info_tbl[id->driver_data]; + mutex_init(&data->lock); i2c_set_clientdata(client, indio_dev); - - /* Initialize the HMC5843 chip */ - hmc5843_init_client(client); - indio_dev->info = &hmc5843_info; indio_dev->name = id->name; - indio_dev->channels = hmc5843_channels; - indio_dev->num_channels = ARRAY_SIZE(hmc5843_channels); indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; - err = iio_device_register(indio_dev); - if (err) - goto exit_free2; + indio_dev->channels = data->variant->channels; + indio_dev->num_channels = 4; + indio_dev->available_scan_masks = hmc5843_scan_masks; + + ret = hmc5843_init(data); + if (ret < 0) + return ret; + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + hmc5843_trigger_handler, NULL); + if (ret < 0) + return ret; + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto buffer_cleanup; + return 0; -exit_free2: - iio_free_device(indio_dev); -exit: - return err; + +buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); + return ret; } static int hmc5843_remove(struct i2c_client *client) @@ -581,46 +590,63 @@ static int hmc5843_remove(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); iio_device_unregister(indio_dev); - /* sleep mode to save power */ - hmc5843_configure(client, MODE_SLEEP); - iio_free_device(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + + /* sleep mode to save power */ + hmc5843_set_mode(iio_priv(indio_dev), HMC5843_MODE_SLEEP); return 0; } -static int hmc5843_suspend(struct i2c_client *client, pm_message_t mesg) +#ifdef CONFIG_PM_SLEEP +static int hmc5843_suspend(struct device *dev) { - hmc5843_configure(client, MODE_SLEEP); - return 0; + struct hmc5843_data *data = iio_priv(i2c_get_clientdata( + to_i2c_client(dev))); + + return hmc5843_set_mode(data, HMC5843_MODE_SLEEP); } -static int hmc5843_resume(struct i2c_client *client) +static int hmc5843_resume(struct device *dev) { - struct hmc5843_data *data = i2c_get_clientdata(client); - hmc5843_configure(client, data->operating_mode); - return 0; + struct hmc5843_data *data = iio_priv(i2c_get_clientdata( + to_i2c_client(dev))); + + return hmc5843_set_mode(data, HMC5843_MODE_CONVERSION_CONTINUOUS); } +static SIMPLE_DEV_PM_OPS(hmc5843_pm_ops, hmc5843_suspend, hmc5843_resume); +#define HMC5843_PM_OPS (&hmc5843_pm_ops) +#else +#define HMC5843_PM_OPS NULL +#endif + static const struct i2c_device_id hmc5843_id[] = { - { "hmc5843", 0 }, + { "hmc5843", HMC5843_ID }, + { "hmc5883", HMC5883_ID }, + { "hmc5883l", HMC5883L_ID }, { } }; MODULE_DEVICE_TABLE(i2c, hmc5843_id); +static const struct of_device_id hmc5843_of_match[] = { + { .compatible = "honeywell,hmc5843" }, + {} +}; +MODULE_DEVICE_TABLE(of, hmc5843_of_match); + static struct i2c_driver hmc5843_driver = { .driver = { .name = "hmc5843", + .pm = HMC5843_PM_OPS, + .of_match_table = hmc5843_of_match, }, .id_table = hmc5843_id, .probe = hmc5843_probe, .remove = hmc5843_remove, - .detect = hmc5843_detect, - .address_list = normal_i2c, - .suspend = hmc5843_suspend, - .resume = hmc5843_resume, }; module_i2c_driver(hmc5843_driver); -MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti@ti.com"); -MODULE_DESCRIPTION("HMC5843 driver"); +MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti@ti.com>"); +MODULE_DESCRIPTION("HMC5843/5883/5883L driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/meter/Kconfig b/drivers/staging/iio/meter/Kconfig index d290d273841..e53274b64ae 100644 --- a/drivers/staging/iio/meter/Kconfig +++ b/drivers/staging/iio/meter/Kconfig @@ -21,7 +21,7 @@ config ADE7758 tristate "Analog Devices ADE7758 Poly Phase Multifunction Energy Metering IC Driver" depends on SPI select IIO_TRIGGER if IIO_BUFFER - select IIO_SW_RING if IIO_BUFFER + select IIO_KFIFO_BUF if IIO_BUFFER help Say yes here to build support for Analog Devices ADE7758 Polyphase Multifunction Energy Metering IC with Per Phase Information Driver. diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c index 57baac6c0d4..00492cad7c5 100644 --- a/drivers/staging/iio/meter/ade7753.c +++ b/drivers/staging/iio/meter/ade7753.c @@ -18,8 +18,8 @@ #include <linux/list.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #include "meter.h" #include "ade7753.h" @@ -28,7 +28,7 @@ static int ade7753_spi_write_reg_8(struct device *dev, u8 val) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7753_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -46,7 +46,7 @@ static int ade7753_spi_write_reg_16(struct device *dev, u16 value) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7753_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -63,7 +63,7 @@ static int ade7753_spi_read_reg_8(struct device *dev, u8 reg_address, u8 *val) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7753_state *st = iio_priv(indio_dev); ssize_t ret; @@ -82,11 +82,11 @@ static int ade7753_spi_read_reg_16(struct device *dev, u8 reg_address, u16 *val) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7753_state *st = iio_priv(indio_dev); ssize_t ret; - ret = spi_w8r16(st->us, ADE7753_READ_REG(reg_address)); + ret = spi_w8r16be(st->us, ADE7753_READ_REG(reg_address)); if (ret < 0) { dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", reg_address); @@ -94,7 +94,6 @@ static int ade7753_spi_read_reg_16(struct device *dev, } *val = ret; - *val = be16_to_cpup(val); return 0; } @@ -103,8 +102,7 @@ static int ade7753_spi_read_reg_24(struct device *dev, u8 reg_address, u32 *val) { - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7753_state *st = iio_priv(indio_dev); int ret; struct spi_transfer xfers[] = { @@ -122,10 +120,7 @@ static int ade7753_spi_read_reg_24(struct device *dev, mutex_lock(&st->buf_lock); st->tx[0] = ADE7753_READ_REG(reg_address); - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X", reg_address); @@ -190,9 +185,9 @@ static ssize_t ade7753_write_8bit(struct device *dev, { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; - long val; + u8 val; - ret = strict_strtol(buf, 10, &val); + ret = kstrtou8(buf, 10, &val); if (ret) goto error_ret; ret = ade7753_spi_write_reg_8(dev, this_attr->address, val); @@ -208,9 +203,9 @@ static ssize_t ade7753_write_16bit(struct device *dev, { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; - long val; + u16 val; - ret = strict_strtol(buf, 10, &val); + ret = kstrtou16(buf, 10, &val); if (ret) goto error_ret; ret = ade7753_spi_write_reg_16(dev, this_attr->address, val); @@ -229,21 +224,6 @@ static int ade7753_reset(struct device *dev) return ade7753_spi_write_reg_16(dev, ADE7753_MODE, val); } -static ssize_t ade7753_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - if (len < 1) - return -1; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return ade7753_reset(dev); - } - return -1; -} - static IIO_DEV_ATTR_AENERGY(ade7753_read_24bit, ADE7753_AENERGY); static IIO_DEV_ATTR_LAENERGY(ade7753_read_24bit, ADE7753_LAENERGY); static IIO_DEV_ATTR_VAENERGY(ade7753_read_24bit, ADE7753_VAENERGY); @@ -416,15 +396,17 @@ static ssize_t ade7753_write_frequency(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7753_state *st = iio_priv(indio_dev); - unsigned long val; + u16 val; int ret; u16 reg, t; - ret = strict_strtol(buf, 10, &val); + ret = kstrtou16(buf, 10, &val); if (ret) return ret; + if (val == 0) + return -EINVAL; mutex_lock(&indio_dev->mlock); @@ -460,8 +442,6 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, ade7753_read_frequency, ade7753_write_frequency); -static IIO_DEV_ATTR_RESET(ade7753_write_reset); - static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500"); static struct attribute *ade7753_attributes[] = { @@ -470,7 +450,6 @@ static struct attribute *ade7753_attributes[] = { &iio_const_attr_in_temp_scale.dev_attr.attr, &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_reset.dev_attr.attr, &iio_dev_attr_phcal.dev_attr.attr, &iio_dev_attr_cfden.dev_attr.attr, &iio_dev_attr_aenergy.dev_attr.attr, @@ -510,18 +489,16 @@ static const struct iio_info ade7753_info = { .driver_module = THIS_MODULE, }; -static int __devinit ade7753_probe(struct spi_device *spi) +static int ade7753_probe(struct spi_device *spi) { int ret; struct ade7753_state *st; struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; /* this is only used for removal purposes */ spi_set_drvdata(spi, indio_dev); @@ -537,36 +514,24 @@ static int __devinit ade7753_probe(struct spi_device *spi) /* Get the device into a sane initial state */ ret = ade7753_initial_setup(indio_dev); if (ret) - goto error_free_dev; + return ret; ret = iio_device_register(indio_dev); if (ret) - goto error_free_dev; + return ret; return 0; - -error_free_dev: - iio_free_device(indio_dev); - -error_ret: - return ret; } /* fixme, confirm ordering in this function */ static int ade7753_remove(struct spi_device *spi) { - int ret; struct iio_dev *indio_dev = spi_get_drvdata(spi); iio_device_unregister(indio_dev); + ade7753_stop_device(&indio_dev->dev); - ret = ade7753_stop_device(&(indio_dev->dev)); - if (ret) - goto err_ret; - - iio_free_device(indio_dev); -err_ret: - return ret; + return 0; } static struct spi_driver ade7753_driver = { @@ -575,7 +540,7 @@ static struct spi_driver ade7753_driver = { .owner = THIS_MODULE, }, .probe = ade7753_probe, - .remove = __devexit_p(ade7753_remove), + .remove = ade7753_remove, }; module_spi_driver(ade7753_driver); diff --git a/drivers/staging/iio/meter/ade7753.h b/drivers/staging/iio/meter/ade7753.h index 3f059d3d939..a9d93cc1c41 100644 --- a/drivers/staging/iio/meter/ade7753.h +++ b/drivers/staging/iio/meter/ade7753.h @@ -55,8 +55,6 @@ #define ADE7753_SPI_BURST (u32)(1000 * 1000) #define ADE7753_SPI_FAST (u32)(2000 * 1000) -#define DRIVER_NAME "ade7753" - /** * struct ade7753_state - device instance specific data * @us: actual spi_device diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c index 8d81c92007e..e0aa13ab365 100644 --- a/drivers/staging/iio/meter/ade7754.c +++ b/drivers/staging/iio/meter/ade7754.c @@ -18,8 +18,8 @@ #include <linux/list.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #include "meter.h" #include "ade7754.h" @@ -28,7 +28,7 @@ static int ade7754_spi_write_reg_8(struct device *dev, u8 val) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7754_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -46,7 +46,7 @@ static int ade7754_spi_write_reg_16(struct device *dev, u16 value) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7754_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -63,7 +63,7 @@ static int ade7754_spi_read_reg_8(struct device *dev, u8 reg_address, u8 *val) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7754_state *st = iio_priv(indio_dev); int ret; @@ -82,11 +82,11 @@ static int ade7754_spi_read_reg_16(struct device *dev, u8 reg_address, u16 *val) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7754_state *st = iio_priv(indio_dev); int ret; - ret = spi_w8r16(st->us, ADE7754_READ_REG(reg_address)); + ret = spi_w8r16be(st->us, ADE7754_READ_REG(reg_address)); if (ret < 0) { dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", reg_address); @@ -94,7 +94,6 @@ static int ade7754_spi_read_reg_16(struct device *dev, } *val = ret; - *val = be16_to_cpup(val); return 0; } @@ -103,8 +102,7 @@ static int ade7754_spi_read_reg_24(struct device *dev, u8 reg_address, u32 *val) { - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7754_state *st = iio_priv(indio_dev); int ret; struct spi_transfer xfers[] = { @@ -122,9 +120,7 @@ static int ade7754_spi_read_reg_24(struct device *dev, st->tx[2] = 0; st->tx[3] = 0; - spi_message_init(&msg); - spi_message_add_tail(xfers, &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X", reg_address); @@ -189,9 +185,9 @@ static ssize_t ade7754_write_8bit(struct device *dev, { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; - long val; + u8 val; - ret = strict_strtol(buf, 10, &val); + ret = kstrtou8(buf, 10, &val); if (ret) goto error_ret; ret = ade7754_spi_write_reg_8(dev, this_attr->address, val); @@ -207,9 +203,9 @@ static ssize_t ade7754_write_16bit(struct device *dev, { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; - long val; + u16 val; - ret = strict_strtol(buf, 10, &val); + ret = kstrtou16(buf, 10, &val); if (ret) goto error_ret; ret = ade7754_spi_write_reg_16(dev, this_attr->address, val); @@ -227,22 +223,6 @@ static int ade7754_reset(struct device *dev) return ade7754_spi_write_reg_8(dev, ADE7754_OPMODE, val); } - -static ssize_t ade7754_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - if (len < 1) - return -1; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return ade7754_reset(dev); - } - return -1; -} - static IIO_DEV_ATTR_AENERGY(ade7754_read_24bit, ADE7754_AENERGY); static IIO_DEV_ATTR_LAENERGY(ade7754_read_24bit, ADE7754_LAENERGY); static IIO_DEV_ATTR_VAENERGY(ade7754_read_24bit, ADE7754_VAENERGY); @@ -436,15 +416,17 @@ static ssize_t ade7754_write_frequency(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7754_state *st = iio_priv(indio_dev); - unsigned long val; + u16 val; int ret; u8 reg, t; - ret = strict_strtol(buf, 10, &val); + ret = kstrtou16(buf, 10, &val); if (ret) return ret; + if (val == 0) + return -EINVAL; mutex_lock(&indio_dev->mlock); @@ -479,8 +461,6 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, ade7754_read_frequency, ade7754_write_frequency); -static IIO_DEV_ATTR_RESET(ade7754_write_reset); - static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26000 13000 65000 33000"); static struct attribute *ade7754_attributes[] = { @@ -489,7 +469,6 @@ static struct attribute *ade7754_attributes[] = { &iio_const_attr_in_temp_scale.dev_attr.attr, &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_reset.dev_attr.attr, &iio_dev_attr_aenergy.dev_attr.attr, &iio_dev_attr_laenergy.dev_attr.attr, &iio_dev_attr_vaenergy.dev_attr.attr, @@ -533,18 +512,16 @@ static const struct iio_info ade7754_info = { .driver_module = THIS_MODULE, }; -static int __devinit ade7754_probe(struct spi_device *spi) +static int ade7754_probe(struct spi_device *spi) { int ret; struct ade7754_state *st; struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; /* this is only used for removal purposes */ spi_set_drvdata(spi, indio_dev); @@ -560,36 +537,23 @@ static int __devinit ade7754_probe(struct spi_device *spi) /* Get the device into a sane initial state */ ret = ade7754_initial_setup(indio_dev); if (ret) - goto error_free_dev; + return ret; ret = iio_device_register(indio_dev); if (ret) - goto error_free_dev; + return ret; return 0; - -error_free_dev: - iio_free_device(indio_dev); - -error_ret: - return ret; } /* fixme, confirm ordering in this function */ static int ade7754_remove(struct spi_device *spi) { - int ret; struct iio_dev *indio_dev = spi_get_drvdata(spi); iio_device_unregister(indio_dev); - ret = ade7754_stop_device(&(indio_dev->dev)); - if (ret) - goto err_ret; - - iio_free_device(indio_dev); - -err_ret: - return ret; + ade7754_stop_device(&indio_dev->dev); + return 0; } static struct spi_driver ade7754_driver = { @@ -598,7 +562,7 @@ static struct spi_driver ade7754_driver = { .owner = THIS_MODULE, }, .probe = ade7754_probe, - .remove = __devexit_p(ade7754_remove), + .remove = ade7754_remove, }; module_spi_driver(ade7754_driver); diff --git a/drivers/staging/iio/meter/ade7754.h b/drivers/staging/iio/meter/ade7754.h index 6121125520f..e42ffc387a1 100644 --- a/drivers/staging/iio/meter/ade7754.h +++ b/drivers/staging/iio/meter/ade7754.h @@ -73,8 +73,6 @@ #define ADE7754_SPI_BURST (u32)(1000 * 1000) #define ADE7754_SPI_FAST (u32)(2000 * 1000) -#define DRIVER_NAME "ade7754" - /** * struct ade7754_state - device instance specific data * @us: actual spi_device diff --git a/drivers/staging/iio/meter/ade7758.h b/drivers/staging/iio/meter/ade7758.h index bdd1b05bf7a..07318203a83 100644 --- a/drivers/staging/iio/meter/ade7758.h +++ b/drivers/staging/iio/meter/ade7758.h @@ -105,9 +105,6 @@ #define AD7758_APP_PWR 4 #define AD7758_WT(p, w) (((w) << 2) | (p)) -#define DRIVER_NAME "ade7758" - - /** * struct ade7758_state - device instance specific data * @us: actual spi_device @@ -122,8 +119,7 @@ struct ade7758_state { u8 *tx; u8 *rx; struct mutex buf_lock; - unsigned long available_scan_masks[AD7758_NUM_WAVESRC]; - struct iio_chan_spec *ade7758_ring_channels; + const struct iio_chan_spec *ade7758_ring_channels; struct spi_transfer ring_xfer[4]; struct spi_message ring_msg; /* diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index dcb20294dfe..cba183e2483 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -18,9 +18,9 @@ #include <linux/list.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> #include "meter.h" #include "ade7758.h" @@ -29,7 +29,7 @@ int ade7758_spi_write_reg_8(struct device *dev, u8 val) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7758_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -47,8 +47,7 @@ static int ade7758_spi_write_reg_16(struct device *dev, u16 value) { int ret; - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7758_state *st = iio_priv(indio_dev); struct spi_transfer xfers[] = { { @@ -63,9 +62,7 @@ static int ade7758_spi_write_reg_16(struct device *dev, st->tx[1] = (value >> 8) & 0xFF; st->tx[2] = value & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(xfers, &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); mutex_unlock(&st->buf_lock); return ret; @@ -76,8 +73,7 @@ static int ade7758_spi_write_reg_24(struct device *dev, u32 value) { int ret; - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7758_state *st = iio_priv(indio_dev); struct spi_transfer xfers[] = { { @@ -93,9 +89,7 @@ static int ade7758_spi_write_reg_24(struct device *dev, st->tx[2] = (value >> 8) & 0xFF; st->tx[3] = value & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(xfers, &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); mutex_unlock(&st->buf_lock); return ret; @@ -105,8 +99,7 @@ int ade7758_spi_read_reg_8(struct device *dev, u8 reg_address, u8 *val) { - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7758_state *st = iio_priv(indio_dev); int ret; struct spi_transfer xfers[] = { @@ -128,10 +121,7 @@ int ade7758_spi_read_reg_8(struct device *dev, st->tx[0] = ADE7758_READ_REG(reg_address); st->tx[1] = 0; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X", reg_address); @@ -148,8 +138,7 @@ static int ade7758_spi_read_reg_16(struct device *dev, u8 reg_address, u16 *val) { - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7758_state *st = iio_priv(indio_dev); int ret; struct spi_transfer xfers[] = { @@ -173,10 +162,7 @@ static int ade7758_spi_read_reg_16(struct device *dev, st->tx[1] = 0; st->tx[2] = 0; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", reg_address); @@ -194,8 +180,7 @@ static int ade7758_spi_read_reg_24(struct device *dev, u8 reg_address, u32 *val) { - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7758_state *st = iio_priv(indio_dev); int ret; struct spi_transfer xfers[] = { @@ -219,10 +204,7 @@ static int ade7758_spi_read_reg_24(struct device *dev, st->tx[2] = 0; st->tx[3] = 0; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X", reg_address); @@ -287,9 +269,9 @@ static ssize_t ade7758_write_8bit(struct device *dev, { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; - long val; + u8 val; - ret = strict_strtol(buf, 10, &val); + ret = kstrtou8(buf, 10, &val); if (ret) goto error_ret; ret = ade7758_spi_write_reg_8(dev, this_attr->address, val); @@ -305,9 +287,9 @@ static ssize_t ade7758_write_16bit(struct device *dev, { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; - long val; + u16 val; - ret = strict_strtol(buf, 10, &val); + ret = kstrtou16(buf, 10, &val); if (ret) goto error_ret; ret = ade7758_spi_write_reg_16(dev, this_attr->address, val); @@ -331,21 +313,6 @@ static int ade7758_reset(struct device *dev) return ret; } -static ssize_t ade7758_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - if (len < 1) - return -1; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return ade7758_reset(dev); - } - return len; -} - static IIO_DEV_ATTR_VPEAK(S_IWUSR | S_IRUGO, ade7758_read_8bit, ade7758_write_8bit, @@ -534,12 +501,12 @@ static ssize_t ade7758_write_frequency(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); - unsigned long val; + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + u16 val; int ret; u8 reg, t; - ret = strict_strtol(buf, 10, &val); + ret = kstrtou16(buf, 10, &val); if (ret) return ret; @@ -609,8 +576,6 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, ade7758_read_frequency, ade7758_write_frequency); -static IIO_DEV_ATTR_RESET(ade7758_write_reset); - static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26040 13020 6510 3255"); static struct attribute *ade7758_attributes[] = { @@ -619,7 +584,6 @@ static struct attribute *ade7758_attributes[] = { &iio_const_attr_in_temp_scale.dev_attr.attr, &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_reset.dev_attr.attr, &iio_dev_attr_awatthr.dev_attr.attr, &iio_dev_attr_bwatthr.dev_attr.attr, &iio_dev_attr_cwatthr.dev_attr.attr, @@ -661,67 +625,218 @@ static const struct attribute_group ade7758_attribute_group = { .attrs = ade7758_attributes, }; -static struct iio_chan_spec ade7758_channels[] = { - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "raw", 0, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - AD7758_WT(AD7758_PHASE_A, AD7758_VOLTAGE), - 0, IIO_ST('s', 24, 32, 0), 0), - IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 0, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - AD7758_WT(AD7758_PHASE_A, AD7758_CURRENT), - 1, IIO_ST('s', 24, 32, 0), 0), - IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 0, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - AD7758_WT(AD7758_PHASE_A, AD7758_APP_PWR), - 2, IIO_ST('s', 24, 32, 0), 0), - IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 0, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - AD7758_WT(AD7758_PHASE_A, AD7758_ACT_PWR), - 3, IIO_ST('s', 24, 32, 0), 0), - IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 0, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - AD7758_WT(AD7758_PHASE_A, AD7758_REACT_PWR), - 4, IIO_ST('s', 24, 32, 0), 0), - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "raw", 1, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - AD7758_WT(AD7758_PHASE_B, AD7758_VOLTAGE), - 5, IIO_ST('s', 24, 32, 0), 0), - IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 1, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - AD7758_WT(AD7758_PHASE_B, AD7758_CURRENT), - 6, IIO_ST('s', 24, 32, 0), 0), - IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 1, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - AD7758_WT(AD7758_PHASE_B, AD7758_APP_PWR), - 7, IIO_ST('s', 24, 32, 0), 0), - IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 1, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - AD7758_WT(AD7758_PHASE_B, AD7758_ACT_PWR), - 8, IIO_ST('s', 24, 32, 0), 0), - IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 1, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - AD7758_WT(AD7758_PHASE_B, AD7758_REACT_PWR), - 9, IIO_ST('s', 24, 32, 0), 0), - IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "raw", 2, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - AD7758_WT(AD7758_PHASE_C, AD7758_VOLTAGE), - 10, IIO_ST('s', 24, 32, 0), 0), - IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 2, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - AD7758_WT(AD7758_PHASE_C, AD7758_CURRENT), - 11, IIO_ST('s', 24, 32, 0), 0), - IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 2, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - AD7758_WT(AD7758_PHASE_C, AD7758_APP_PWR), - 12, IIO_ST('s', 24, 32, 0), 0), - IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 2, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - AD7758_WT(AD7758_PHASE_C, AD7758_ACT_PWR), - 13, IIO_ST('s', 24, 32, 0), 0), - IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 2, 0, - IIO_CHAN_INFO_SCALE_SHARED_BIT, - AD7758_WT(AD7758_PHASE_C, AD7758_REACT_PWR), - 14, IIO_ST('s', 24, 32, 0), 0), +static const struct iio_chan_spec ade7758_channels[] = { + { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .extend_name = "raw", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_A, AD7758_VOLTAGE), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + }, + }, { + .type = IIO_CURRENT, + .indexed = 1, + .channel = 0, + .extend_name = "raw", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_A, AD7758_CURRENT), + .scan_index = 1, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + }, + }, { + .type = IIO_POWER, + .indexed = 1, + .channel = 0, + .extend_name = "apparent_raw", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_A, AD7758_APP_PWR), + .scan_index = 2, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + }, + }, { + .type = IIO_POWER, + .indexed = 1, + .channel = 0, + .extend_name = "active_raw", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_A, AD7758_ACT_PWR), + .scan_index = 3, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + }, + }, { + .type = IIO_POWER, + .indexed = 1, + .channel = 0, + .extend_name = "reactive_raw", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_A, AD7758_REACT_PWR), + .scan_index = 4, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + }, + }, { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 1, + .extend_name = "raw", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_B, AD7758_VOLTAGE), + .scan_index = 5, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + }, + }, { + .type = IIO_CURRENT, + .indexed = 1, + .channel = 1, + .extend_name = "raw", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_B, AD7758_CURRENT), + .scan_index = 6, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + }, + }, { + .type = IIO_POWER, + .indexed = 1, + .channel = 1, + .extend_name = "apparent_raw", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_B, AD7758_APP_PWR), + .scan_index = 7, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + }, + }, { + .type = IIO_POWER, + .indexed = 1, + .channel = 1, + .extend_name = "active_raw", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_B, AD7758_ACT_PWR), + .scan_index = 8, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + }, + }, { + .type = IIO_POWER, + .indexed = 1, + .channel = 1, + .extend_name = "reactive_raw", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_B, AD7758_REACT_PWR), + .scan_index = 9, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + }, + }, { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 2, + .extend_name = "raw", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_C, AD7758_VOLTAGE), + .scan_index = 10, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + }, + }, { + .type = IIO_CURRENT, + .indexed = 1, + .channel = 2, + .extend_name = "raw", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_C, AD7758_CURRENT), + .scan_index = 11, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + }, + }, { + .type = IIO_POWER, + .indexed = 1, + .channel = 2, + .extend_name = "apparent_raw", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_C, AD7758_APP_PWR), + .scan_index = 12, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + }, + }, { + .type = IIO_POWER, + .indexed = 1, + .channel = 2, + .extend_name = "active_raw", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_C, AD7758_ACT_PWR), + .scan_index = 13, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + }, + }, { + .type = IIO_POWER, + .indexed = 1, + .channel = 2, + .extend_name = "reactive_raw", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_C, AD7758_REACT_PWR), + .scan_index = 14, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + }, + }, IIO_CHAN_SOFT_TIMESTAMP(15), }; @@ -730,16 +845,15 @@ static const struct iio_info ade7758_info = { .driver_module = THIS_MODULE, }; -static int __devinit ade7758_probe(struct spi_device *spi) +static int ade7758_probe(struct spi_device *spi) { - int i, ret; + int ret; struct ade7758_state *st; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); + struct iio_dev *indio_dev; - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; st = iio_priv(indio_dev); /* this is only used for removal purposes */ @@ -747,10 +861,8 @@ static int __devinit ade7758_probe(struct spi_device *spi) /* Allocate the comms buffers */ st->rx = kcalloc(ADE7758_MAX_RX, sizeof(*st->rx), GFP_KERNEL); - if (st->rx == NULL) { - ret = -ENOMEM; - goto error_free_dev; - } + if (!st->rx) + return -ENOMEM; st->tx = kcalloc(ADE7758_MAX_TX, sizeof(*st->tx), GFP_KERNEL); if (st->tx == NULL) { ret = -ENOMEM; @@ -765,11 +877,6 @@ static int __devinit ade7758_probe(struct spi_device *spi) indio_dev->info = &ade7758_info; indio_dev->modes = INDIO_DIRECT_MODE; - for (i = 0; i < AD7758_NUM_WAVESRC; i++) - set_bit(i, &st->available_scan_masks[i]); - - indio_dev->available_scan_masks = st->available_scan_masks; - ret = ade7758_configure_ring(indio_dev); if (ret) goto error_free_tx; @@ -800,7 +907,7 @@ static int __devinit ade7758_probe(struct spi_device *spi) return 0; error_remove_trigger: - if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) + if (spi->irq) ade7758_remove_trigger(indio_dev); error_uninitialize_ring: ade7758_uninitialize_ring(indio_dev); @@ -810,9 +917,6 @@ error_free_tx: kfree(st->tx); error_free_rx: kfree(st->rx); -error_free_dev: - iio_free_device(indio_dev); -error_ret: return ret; } @@ -820,23 +924,16 @@ static int ade7758_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ade7758_state *st = iio_priv(indio_dev); - int ret; iio_device_unregister(indio_dev); - ret = ade7758_stop_device(&indio_dev->dev); - if (ret) - goto err_ret; - + ade7758_stop_device(&indio_dev->dev); ade7758_remove_trigger(indio_dev); ade7758_uninitialize_ring(indio_dev); ade7758_unconfigure_ring(indio_dev); kfree(st->tx); kfree(st->rx); - iio_free_device(indio_dev); - -err_ret: - return ret; + return 0; } static const struct spi_device_id ade7758_id[] = { @@ -851,7 +948,7 @@ static struct spi_driver ade7758_driver = { .owner = THIS_MODULE, }, .probe = ade7758_probe, - .remove = __devexit_p(ade7758_remove), + .remove = ade7758_remove, .id_table = ade7758_id, }; module_spi_driver(ade7758_driver); diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c index f29f2b278fe..c0accf8cce9 100644 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ b/drivers/staging/iio/meter/ade7758_ring.c @@ -12,18 +12,17 @@ #include <linux/slab.h> #include <asm/unaligned.h> -#include "../iio.h" -#include "../ring_sw.h" -#include "../trigger_consumer.h" +#include <linux/iio/iio.h> +#include <linux/iio/kfifo_buf.h> +#include <linux/iio/trigger_consumer.h> #include "ade7758.h" /** * ade7758_spi_read_burst() - read data registers - * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @indio_dev: the IIO device **/ -static int ade7758_spi_read_burst(struct device *dev) +static int ade7758_spi_read_burst(struct iio_dev *indio_dev) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ade7758_state *st = iio_priv(indio_dev); int ret; @@ -55,27 +54,22 @@ out: return ret; } -/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device +/* Whilst this makes a lot of calls to iio_sw_ring functions - it is too device * specific to be rolled into the core. */ static irqreturn_t ade7758_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; - struct iio_buffer *ring = indio_dev->buffer; struct ade7758_state *st = iio_priv(indio_dev); s64 dat64[2]; u32 *dat32 = (u32 *)dat64; if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) - if (ade7758_spi_read_burst(&indio_dev->dev) >= 0) + if (ade7758_spi_read_burst(indio_dev) >= 0) *dat32 = get_unaligned_be32(&st->rx_buf[5]) & 0xFFFFFF; - /* Guaranteed to be aligned with 8 byte boundary */ - if (ring->scan_timestamp) - dat64[1] = pf->timestamp; - - ring->access->store_to(ring, (u8 *)dat64, pf->timestamp); + iio_push_to_buffers_with_timestamp(indio_dev, dat64, pf->timestamp); iio_trigger_notify_done(indio_dev->trig); @@ -85,15 +79,13 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p) /** * ade7758_ring_preenable() setup the parameters of the ring before enabling * - * The complex nature of the setting of the nuber of bytes per datum is due + * The complex nature of the setting of the number of bytes per datum is due * to this driver currently ensuring that the timestamp is stored at an 8 * byte boundary. **/ static int ade7758_ring_preenable(struct iio_dev *indio_dev) { struct ade7758_state *st = iio_priv(indio_dev); - struct iio_buffer *ring = indio_dev->buffer; - size_t d_size; unsigned channel; if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) @@ -102,19 +94,6 @@ static int ade7758_ring_preenable(struct iio_dev *indio_dev) channel = find_first_bit(indio_dev->active_scan_mask, indio_dev->masklength); - d_size = st->ade7758_ring_channels[channel].scan_type.storagebits / 8; - - if (ring->scan_timestamp) { - d_size += sizeof(s64); - - if (d_size % sizeof(s64)) - d_size += sizeof(s64) - (d_size % sizeof(s64)); - } - - if (indio_dev->buffer->access->set_bytes_per_datum) - indio_dev->buffer->access-> - set_bytes_per_datum(indio_dev->buffer, d_size); - ade7758_write_waveform_type(&indio_dev->dev, st->ade7758_ring_channels[channel].address); @@ -125,27 +104,29 @@ static const struct iio_buffer_setup_ops ade7758_ring_setup_ops = { .preenable = &ade7758_ring_preenable, .postenable = &iio_triggered_buffer_postenable, .predisable = &iio_triggered_buffer_predisable, + .validate_scan_mask = &iio_validate_scan_mask_onehot, }; void ade7758_unconfigure_ring(struct iio_dev *indio_dev) { iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->buffer); + iio_kfifo_free(indio_dev->buffer); } int ade7758_configure_ring(struct iio_dev *indio_dev) { struct ade7758_state *st = iio_priv(indio_dev); + struct iio_buffer *buffer; int ret = 0; - indio_dev->buffer = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->buffer) { + buffer = iio_kfifo_allocate(indio_dev); + if (!buffer) { ret = -ENOMEM; return ret; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; + iio_device_attach_buffer(indio_dev, buffer); + indio_dev->setup_ops = &ade7758_ring_setup_ops; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, @@ -156,7 +137,7 @@ int ade7758_configure_ring(struct iio_dev *indio_dev) indio_dev->id); if (indio_dev->pollfunc == NULL) { ret = -ENOMEM; - goto error_iio_sw_rb_free; + goto error_iio_kfifo_free; } indio_dev->modes |= INDIO_BUFFER_TRIGGERED; @@ -196,8 +177,8 @@ int ade7758_configure_ring(struct iio_dev *indio_dev) return 0; -error_iio_sw_rb_free: - iio_sw_rb_free(indio_dev->buffer); +error_iio_kfifo_free: + iio_kfifo_free(indio_dev->buffer); return ret; } diff --git a/drivers/staging/iio/meter/ade7758_trigger.c b/drivers/staging/iio/meter/ade7758_trigger.c index b6569c70665..7a94ddd42f5 100644 --- a/drivers/staging/iio/meter/ade7758_trigger.c +++ b/drivers/staging/iio/meter/ade7758_trigger.c @@ -11,8 +11,8 @@ #include <linux/spi/spi.h> #include <linux/export.h> -#include "../iio.h" -#include "../trigger.h" +#include <linux/iio/iio.h> +#include <linux/iio/trigger.h> #include "ade7758.h" /** @@ -32,7 +32,7 @@ static irqreturn_t ade7758_data_rdy_trig_poll(int irq, void *private) static int ade7758_data_rdy_trigger_set_state(struct iio_trigger *trig, bool state) { - struct iio_dev *indio_dev = trig->private_data; + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); return ade7758_set_irq(&indio_dev->dev, state); @@ -44,7 +44,7 @@ static int ade7758_data_rdy_trigger_set_state(struct iio_trigger *trig, **/ static int ade7758_trig_try_reen(struct iio_trigger *trig) { - struct iio_dev *indio_dev = trig->private_data; + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); struct ade7758_state *st = iio_priv(indio_dev); enable_irq(st->us->irq); @@ -63,7 +63,7 @@ int ade7758_probe_trigger(struct iio_dev *indio_dev) struct ade7758_state *st = iio_priv(indio_dev); int ret; - st->trig = iio_allocate_trigger("%s-dev%d", + st->trig = iio_trigger_alloc("%s-dev%d", spi_get_device_id(st->us)->name, indio_dev->id); if (st->trig == NULL) { @@ -81,7 +81,7 @@ int ade7758_probe_trigger(struct iio_dev *indio_dev) st->trig->dev.parent = &st->us->dev; st->trig->ops = &ade7758_trigger_ops; - st->trig->private_data = indio_dev; + iio_trigger_set_drvdata(st->trig, indio_dev); ret = iio_trigger_register(st->trig); /* select default trigger */ @@ -94,7 +94,7 @@ int ade7758_probe_trigger(struct iio_dev *indio_dev) error_free_irq: free_irq(st->us->irq, st->trig); error_free_trig: - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); error_ret: return ret; } @@ -105,5 +105,5 @@ void ade7758_remove_trigger(struct iio_dev *indio_dev) iio_trigger_unregister(st->trig); free_irq(st->us->irq, st->trig); - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); } diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c index 0beab478dcd..ea0c9debf8b 100644 --- a/drivers/staging/iio/meter/ade7759.c +++ b/drivers/staging/iio/meter/ade7759.c @@ -18,8 +18,8 @@ #include <linux/list.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #include "meter.h" #include "ade7759.h" @@ -28,7 +28,7 @@ static int ade7759_spi_write_reg_8(struct device *dev, u8 val) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7759_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -46,7 +46,7 @@ static int ade7759_spi_write_reg_16(struct device *dev, u16 value) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7759_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -63,7 +63,7 @@ static int ade7759_spi_read_reg_8(struct device *dev, u8 reg_address, u8 *val) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7759_state *st = iio_priv(indio_dev); int ret; @@ -82,11 +82,11 @@ static int ade7759_spi_read_reg_16(struct device *dev, u8 reg_address, u16 *val) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7759_state *st = iio_priv(indio_dev); int ret; - ret = spi_w8r16(st->us, ADE7759_READ_REG(reg_address)); + ret = spi_w8r16be(st->us, ADE7759_READ_REG(reg_address)); if (ret < 0) { dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", reg_address); @@ -94,7 +94,6 @@ static int ade7759_spi_read_reg_16(struct device *dev, } *val = ret; - *val = be16_to_cpup(val); return 0; } @@ -103,8 +102,7 @@ static int ade7759_spi_read_reg_40(struct device *dev, u8 reg_address, u64 *val) { - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7759_state *st = iio_priv(indio_dev); int ret; struct spi_transfer xfers[] = { @@ -120,9 +118,7 @@ static int ade7759_spi_read_reg_40(struct device *dev, st->tx[0] = ADE7759_READ_REG(reg_address); memset(&st->tx[1], 0 , 5); - spi_message_init(&msg); - spi_message_add_tail(xfers, &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 40 bit register 0x%02X", reg_address); @@ -188,9 +184,9 @@ static ssize_t ade7759_write_8bit(struct device *dev, { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; - long val; + u8 val; - ret = strict_strtol(buf, 10, &val); + ret = kstrtou8(buf, 10, &val); if (ret) goto error_ret; ret = ade7759_spi_write_reg_8(dev, this_attr->address, val); @@ -206,9 +202,9 @@ static ssize_t ade7759_write_16bit(struct device *dev, { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; - long val; + u16 val; - ret = strict_strtol(buf, 10, &val); + ret = kstrtou16(buf, 10, &val); if (ret) goto error_ret; ret = ade7759_spi_write_reg_16(dev, this_attr->address, val); @@ -232,21 +228,6 @@ static int ade7759_reset(struct device *dev) return ret; } -static ssize_t ade7759_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - if (len < 1) - return -1; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return ade7759_reset(dev); - } - return -1; -} - static IIO_DEV_ATTR_AENERGY(ade7759_read_40bit, ADE7759_AENERGY); static IIO_DEV_ATTR_CFDEN(S_IWUSR | S_IRUGO, ade7759_read_16bit, @@ -376,15 +357,17 @@ static ssize_t ade7759_write_frequency(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7759_state *st = iio_priv(indio_dev); - unsigned long val; + u16 val; int ret; u16 reg, t; - ret = strict_strtol(buf, 10, &val); + ret = kstrtou16(buf, 10, &val); if (ret) return ret; + if (val == 0) + return -EINVAL; mutex_lock(&indio_dev->mlock); @@ -419,8 +402,6 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, ade7759_read_frequency, ade7759_write_frequency); -static IIO_DEV_ATTR_RESET(ade7759_write_reset); - static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500"); static struct attribute *ade7759_attributes[] = { @@ -429,7 +410,6 @@ static struct attribute *ade7759_attributes[] = { &iio_const_attr_in_temp_scale.dev_attr.attr, &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_reset.dev_attr.attr, &iio_dev_attr_phcal.dev_attr.attr, &iio_dev_attr_cfden.dev_attr.attr, &iio_dev_attr_aenergy.dev_attr.attr, @@ -456,18 +436,16 @@ static const struct iio_info ade7759_info = { .driver_module = THIS_MODULE, }; -static int __devinit ade7759_probe(struct spi_device *spi) +static int ade7759_probe(struct spi_device *spi) { int ret; struct ade7759_state *st; struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; /* this is only used for removal purposes */ spi_set_drvdata(spi, indio_dev); @@ -482,35 +460,24 @@ static int __devinit ade7759_probe(struct spi_device *spi) /* Get the device into a sane initial state */ ret = ade7759_initial_setup(indio_dev); if (ret) - goto error_free_dev; + return ret; ret = iio_device_register(indio_dev); if (ret) - goto error_free_dev; + return ret; return 0; - -error_free_dev: - iio_free_device(indio_dev); -error_ret: - return ret; } /* fixme, confirm ordering in this function */ static int ade7759_remove(struct spi_device *spi) { - int ret; struct iio_dev *indio_dev = spi_get_drvdata(spi); iio_device_unregister(indio_dev); - ret = ade7759_stop_device(&(indio_dev->dev)); - if (ret) - goto err_ret; - - iio_free_device(indio_dev); + ade7759_stop_device(&indio_dev->dev); -err_ret: - return ret; + return 0; } static struct spi_driver ade7759_driver = { @@ -519,7 +486,7 @@ static struct spi_driver ade7759_driver = { .owner = THIS_MODULE, }, .probe = ade7759_probe, - .remove = __devexit_p(ade7759_remove), + .remove = ade7759_remove, }; module_spi_driver(ade7759_driver); diff --git a/drivers/staging/iio/meter/ade7759.h b/drivers/staging/iio/meter/ade7759.h index c81d23d730d..f9ff1f8e737 100644 --- a/drivers/staging/iio/meter/ade7759.h +++ b/drivers/staging/iio/meter/ade7759.h @@ -36,8 +36,6 @@ #define ADE7759_SPI_BURST (u32)(1000 * 1000) #define ADE7759_SPI_FAST (u32)(2000 * 1000) -#define DRIVER_NAME "ade7759" - /** * struct ade7759_state - device instance specific data * @us: actual spi_device diff --git a/drivers/staging/iio/meter/ade7854-i2c.c b/drivers/staging/iio/meter/ade7854-i2c.c index 1e1faa0479d..5b33c7f1aa9 100644 --- a/drivers/staging/iio/meter/ade7854-i2c.c +++ b/drivers/staging/iio/meter/ade7854-i2c.c @@ -12,7 +12,7 @@ #include <linux/slab.h> #include <linux/module.h> -#include "../iio.h" +#include <linux/iio/iio.h> #include "ade7854.h" static int ade7854_i2c_write_reg_8(struct device *dev, @@ -20,7 +20,7 @@ static int ade7854_i2c_write_reg_8(struct device *dev, u8 value) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -39,7 +39,7 @@ static int ade7854_i2c_write_reg_16(struct device *dev, u16 value) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -59,7 +59,7 @@ static int ade7854_i2c_write_reg_24(struct device *dev, u32 value) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -80,7 +80,7 @@ static int ade7854_i2c_write_reg_32(struct device *dev, u32 value) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -101,7 +101,7 @@ static int ade7854_i2c_read_reg_8(struct device *dev, u16 reg_address, u8 *val) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); int ret; @@ -127,7 +127,7 @@ static int ade7854_i2c_read_reg_16(struct device *dev, u16 reg_address, u16 *val) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); int ret; @@ -153,7 +153,7 @@ static int ade7854_i2c_read_reg_24(struct device *dev, u16 reg_address, u32 *val) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); int ret; @@ -179,7 +179,7 @@ static int ade7854_i2c_read_reg_32(struct device *dev, u16 reg_address, u32 *val) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); int ret; @@ -201,14 +201,14 @@ out: return ret; } -static int __devinit ade7854_i2c_probe(struct i2c_client *client, +static int ade7854_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret; struct ade7854_state *st; struct iio_dev *indio_dev; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; st = iio_priv(indio_dev); @@ -225,13 +225,11 @@ static int __devinit ade7854_i2c_probe(struct i2c_client *client, st->irq = client->irq; ret = ade7854_probe(indio_dev, &client->dev); - if (ret) - iio_free_device(indio_dev); return ret; } -static int __devexit ade7854_i2c_remove(struct i2c_client *client) +static int ade7854_i2c_remove(struct i2c_client *client) { return ade7854_remove(i2c_get_clientdata(client)); } @@ -250,7 +248,7 @@ static struct i2c_driver ade7854_i2c_driver = { .name = "ade7854", }, .probe = ade7854_i2c_probe, - .remove = __devexit_p(ade7854_i2c_remove), + .remove = ade7854_i2c_remove, .id_table = ade7854_id, }; module_i2c_driver(ade7854_i2c_driver); diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c index 81121862c1b..94f73bbbc0f 100644 --- a/drivers/staging/iio/meter/ade7854-spi.c +++ b/drivers/staging/iio/meter/ade7854-spi.c @@ -12,7 +12,7 @@ #include <linux/slab.h> #include <linux/module.h> -#include "../iio.h" +#include <linux/iio/iio.h> #include "ade7854.h" static int ade7854_spi_write_reg_8(struct device *dev, @@ -20,8 +20,7 @@ static int ade7854_spi_write_reg_8(struct device *dev, u8 value) { int ret; - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); struct spi_transfer xfer = { .tx_buf = st->tx, @@ -35,9 +34,7 @@ static int ade7854_spi_write_reg_8(struct device *dev, st->tx[2] = reg_address & 0xFF; st->tx[3] = value & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->spi, &msg); + ret = spi_sync_transfer(st->spi, &xfer, 1); mutex_unlock(&st->buf_lock); return ret; @@ -48,8 +45,7 @@ static int ade7854_spi_write_reg_16(struct device *dev, u16 value) { int ret; - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); struct spi_transfer xfer = { .tx_buf = st->tx, @@ -64,9 +60,7 @@ static int ade7854_spi_write_reg_16(struct device *dev, st->tx[3] = (value >> 8) & 0xFF; st->tx[4] = value & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->spi, &msg); + ret = spi_sync_transfer(st->spi, &xfer, 1); mutex_unlock(&st->buf_lock); return ret; @@ -77,8 +71,7 @@ static int ade7854_spi_write_reg_24(struct device *dev, u32 value) { int ret; - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); struct spi_transfer xfer = { .tx_buf = st->tx, @@ -94,9 +87,7 @@ static int ade7854_spi_write_reg_24(struct device *dev, st->tx[4] = (value >> 8) & 0xFF; st->tx[5] = value & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->spi, &msg); + ret = spi_sync_transfer(st->spi, &xfer, 1); mutex_unlock(&st->buf_lock); return ret; @@ -107,8 +98,7 @@ static int ade7854_spi_write_reg_32(struct device *dev, u32 value) { int ret; - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); struct spi_transfer xfer = { .tx_buf = st->tx, @@ -125,9 +115,7 @@ static int ade7854_spi_write_reg_32(struct device *dev, st->tx[5] = (value >> 8) & 0xFF; st->tx[6] = value & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->spi, &msg); + ret = spi_sync_transfer(st->spi, &xfer, 1); mutex_unlock(&st->buf_lock); return ret; @@ -137,8 +125,7 @@ static int ade7854_spi_read_reg_8(struct device *dev, u16 reg_address, u8 *val) { - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); int ret; struct spi_transfer xfers[] = { @@ -159,10 +146,7 @@ static int ade7854_spi_read_reg_8(struct device *dev, st->tx[1] = (reg_address >> 8) & 0xFF; st->tx[2] = reg_address & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->spi, &msg); + ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->spi->dev, "problem when reading 8 bit register 0x%02X", reg_address); @@ -179,8 +163,7 @@ static int ade7854_spi_read_reg_16(struct device *dev, u16 reg_address, u16 *val) { - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); int ret; struct spi_transfer xfers[] = { @@ -200,10 +183,7 @@ static int ade7854_spi_read_reg_16(struct device *dev, st->tx[1] = (reg_address >> 8) & 0xFF; st->tx[2] = reg_address & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->spi, &msg); + ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->spi->dev, "problem when reading 16 bit register 0x%02X", reg_address); @@ -220,8 +200,7 @@ static int ade7854_spi_read_reg_24(struct device *dev, u16 reg_address, u32 *val) { - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); int ret; struct spi_transfer xfers[] = { @@ -242,10 +221,7 @@ static int ade7854_spi_read_reg_24(struct device *dev, st->tx[1] = (reg_address >> 8) & 0xFF; st->tx[2] = reg_address & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->spi, &msg); + ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->spi->dev, "problem when reading 24 bit register 0x%02X", reg_address); @@ -262,8 +238,7 @@ static int ade7854_spi_read_reg_32(struct device *dev, u16 reg_address, u32 *val) { - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); int ret; struct spi_transfer xfers[] = { @@ -284,10 +259,7 @@ static int ade7854_spi_read_reg_32(struct device *dev, st->tx[1] = (reg_address >> 8) & 0xFF; st->tx[2] = reg_address & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->spi, &msg); + ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->spi->dev, "problem when reading 32 bit register 0x%02X", reg_address); @@ -300,13 +272,13 @@ error_ret: return ret; } -static int __devinit ade7854_spi_probe(struct spi_device *spi) +static int ade7854_spi_probe(struct spi_device *spi) { int ret; struct ade7854_state *st; struct iio_dev *indio_dev; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; st = iio_priv(indio_dev); @@ -324,10 +296,8 @@ static int __devinit ade7854_spi_probe(struct spi_device *spi) ret = ade7854_probe(indio_dev, &spi->dev); - if (ret) - iio_free_device(indio_dev); - return 0; + return ret; } static int ade7854_spi_remove(struct spi_device *spi) @@ -351,7 +321,7 @@ static struct spi_driver ade7854_driver = { .owner = THIS_MODULE, }, .probe = ade7854_spi_probe, - .remove = __devexit_p(ade7854_spi_remove), + .remove = ade7854_spi_remove, .id_table = ade7854_id, }; module_spi_driver(ade7854_driver); diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c index 49c01c5c1b5..d620bbd603a 100644 --- a/drivers/staging/iio/meter/ade7854.c +++ b/drivers/staging/iio/meter/ade7854.c @@ -17,8 +17,8 @@ #include <linux/list.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #include "meter.h" #include "ade7854.h" @@ -28,7 +28,7 @@ static ssize_t ade7854_read_8bit(struct device *dev, { int ret; u8 val = 0; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); @@ -45,7 +45,7 @@ static ssize_t ade7854_read_16bit(struct device *dev, { int ret; u16 val = 0; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); @@ -62,7 +62,7 @@ static ssize_t ade7854_read_24bit(struct device *dev, { int ret; u32 val; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); @@ -80,7 +80,7 @@ static ssize_t ade7854_read_32bit(struct device *dev, int ret; u32 val = 0; struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); ret = st->read_reg_32(dev, this_attr->address, &val); @@ -96,13 +96,13 @@ static ssize_t ade7854_write_8bit(struct device *dev, size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); int ret; - long val; + u8 val; - ret = strict_strtol(buf, 10, &val); + ret = kstrtou8(buf, 10, &val); if (ret) goto error_ret; ret = st->write_reg_8(dev, this_attr->address, val); @@ -117,13 +117,13 @@ static ssize_t ade7854_write_16bit(struct device *dev, size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); int ret; - long val; + u16 val; - ret = strict_strtol(buf, 10, &val); + ret = kstrtou16(buf, 10, &val); if (ret) goto error_ret; ret = st->write_reg_16(dev, this_attr->address, val); @@ -138,13 +138,13 @@ static ssize_t ade7854_write_24bit(struct device *dev, size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); int ret; - long val; + u32 val; - ret = strict_strtol(buf, 10, &val); + ret = kstrtou32(buf, 10, &val); if (ret) goto error_ret; ret = st->write_reg_24(dev, this_attr->address, val); @@ -159,13 +159,13 @@ static ssize_t ade7854_write_32bit(struct device *dev, size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); int ret; - long val; + u32 val; - ret = strict_strtol(buf, 10, &val); + ret = kstrtou32(buf, 10, &val); if (ret) goto error_ret; ret = st->write_reg_32(dev, this_attr->address, val); @@ -176,7 +176,7 @@ error_ret: static int ade7854_reset(struct device *dev) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); u16 val; @@ -186,22 +186,6 @@ static int ade7854_reset(struct device *dev) return st->write_reg_16(dev, ADE7854_CONFIG, val); } - -static ssize_t ade7854_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - if (len < 1) - return -1; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return ade7854_reset(dev); - } - return -1; -} - static IIO_DEV_ATTR_AIGAIN(S_IWUSR | S_IRUGO, ade7854_read_24bit, ade7854_write_24bit, @@ -425,7 +409,7 @@ static IIO_DEV_ATTR_CVAHR(ade7854_read_32bit, static int ade7854_set_irq(struct device *dev, bool enable) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); int ret; @@ -468,8 +452,6 @@ err_ret: return ret; } -static IIO_DEV_ATTR_RESET(ade7854_write_reset); - static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("8000"); static IIO_CONST_ATTR(name, "ade7854"); @@ -515,7 +497,6 @@ static struct attribute *ade7854_attributes[] = { &iio_dev_attr_bvahr.dev_attr.attr, &iio_dev_attr_cvahr.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_reset.dev_attr.attr, &iio_const_attr_name.dev_attr.attr, &iio_dev_attr_vpeak.dev_attr.attr, &iio_dev_attr_ipeak.dev_attr.attr, @@ -569,7 +550,7 @@ int ade7854_probe(struct iio_dev *indio_dev, struct device *dev) ret = iio_device_register(indio_dev); if (ret) - goto error_free_dev; + return ret; /* Get the device into a sane initial state */ ret = ade7854_initial_setup(indio_dev); @@ -580,9 +561,6 @@ int ade7854_probe(struct iio_dev *indio_dev, struct device *dev) error_unreg_dev: iio_device_unregister(indio_dev); -error_free_dev: - iio_free_device(indio_dev); - return ret; } EXPORT_SYMBOL(ade7854_probe); @@ -590,7 +568,6 @@ EXPORT_SYMBOL(ade7854_probe); int ade7854_remove(struct iio_dev *indio_dev) { iio_device_unregister(indio_dev); - iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/meter/ade7854.h b/drivers/staging/iio/meter/ade7854.h index 2c96e8695d5..06534577f6c 100644 --- a/drivers/staging/iio/meter/ade7854.h +++ b/drivers/staging/iio/meter/ade7854.h @@ -142,8 +142,6 @@ #define ADE7854_SPI_BURST (u32)(1000 * 1000) #define ADE7854_SPI_FAST (u32)(2000 * 1000) -#define DRIVER_NAME "ade7854" - /** * struct ade7854_state - device instance specific data * @spi: actual spi_device diff --git a/drivers/staging/iio/meter/meter.h b/drivers/staging/iio/meter/meter.h index 142c50d71fd..23e1b5f480a 100644 --- a/drivers/staging/iio/meter/meter.h +++ b/drivers/staging/iio/meter/meter.h @@ -1,4 +1,4 @@ -#include "../sysfs.h" +#include <linux/iio/sysfs.h> /* metering ic types of attribute */ @@ -362,7 +362,7 @@ #define IIO_EVENT_ATTR_CYCEND(_evlist, _show, _store, _mask) \ IIO_EVENT_ATTR_SH(cycend, _evlist, _show, _store, _mask) -/* on the rising and falling edge of the the voltage waveform */ +/* on the rising and falling edge of the voltage waveform */ #define IIO_EVENT_ATTR_ZERO_CROSS(_evlist, _show, _store, _mask) \ IIO_EVENT_ATTR_SH(zero_cross, _evlist, _show, _store, _mask) diff --git a/drivers/staging/iio/resolver/Kconfig b/drivers/staging/iio/resolver/Kconfig index 49f69ef986f..ce360f16321 100644 --- a/drivers/staging/iio/resolver/Kconfig +++ b/drivers/staging/iio/resolver/Kconfig @@ -13,7 +13,7 @@ config AD2S90 config AD2S1200 tristate "Analog Devices ad2s1200/ad2s1205 driver" depends on SPI - depends on GENERIC_GPIO + depends on GPIOLIB help Say yes here to build support for Analog Devices spi resolver to digital converters, ad2s1200 and ad2s1205, provides direct access @@ -22,7 +22,7 @@ config AD2S1200 config AD2S1210 tristate "Analog Devices ad2s1210 driver" depends on SPI - depends on GENERIC_GPIO + depends on GPIOLIB help Say yes here to build support for Analog Devices spi resolver to digital converters, ad2s1210, provides direct access via sysfs. diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c index d8ce854c189..017d2f8379b 100644 --- a/drivers/staging/iio/resolver/ad2s1200.c +++ b/drivers/staging/iio/resolver/ad2s1200.c @@ -19,8 +19,8 @@ #include <linux/gpio.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #define DRV_NAME "ad2s1200" @@ -70,6 +70,7 @@ static int ad2s1200_read_raw(struct iio_dev *indio_dev, vel = (((s16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); vel = (vel << 4) >> 4; *val = vel; + break; default: mutex_unlock(&st->lock); return -EINVAL; @@ -85,10 +86,12 @@ static const struct iio_chan_spec ad2s1200_channels[] = { .type = IIO_ANGL, .indexed = 1, .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), }, { .type = IIO_ANGL_VEL, .indexed = 1, .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), } }; @@ -97,24 +100,25 @@ static const struct iio_info ad2s1200_info = { .driver_module = THIS_MODULE, }; -static int __devinit ad2s1200_probe(struct spi_device *spi) +static int ad2s1200_probe(struct spi_device *spi) { struct ad2s1200_state *st; struct iio_dev *indio_dev; int pn, ret = 0; unsigned short *pins = spi->dev.platform_data; - for (pn = 0; pn < AD2S1200_PN; pn++) - if (gpio_request_one(pins[pn], GPIOF_DIR_OUT, DRV_NAME)) { - pr_err("%s: request gpio pin %d failed\n", - DRV_NAME, pins[pn]); - goto error_ret; + for (pn = 0; pn < AD2S1200_PN; pn++) { + ret = devm_gpio_request_one(&spi->dev, pins[pn], GPIOF_DIR_OUT, + DRV_NAME); + if (ret) { + dev_err(&spi->dev, "request gpio pin %d failed\n", + pins[pn]); + return ret; } - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; spi_set_drvdata(spi, indio_dev); st = iio_priv(indio_dev); mutex_init(&st->lock); @@ -129,30 +133,15 @@ static int __devinit ad2s1200_probe(struct spi_device *spi) indio_dev->num_channels = ARRAY_SIZE(ad2s1200_channels); indio_dev->name = spi_get_device_id(spi)->name; - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(&spi->dev, indio_dev); if (ret) - goto error_free_dev; + return ret; spi->max_speed_hz = AD2S1200_HZ; spi->mode = SPI_MODE_3; spi_setup(spi); return 0; - -error_free_dev: - iio_free_device(indio_dev); -error_ret: - for (--pn; pn >= 0; pn--) - gpio_free(pins[pn]); - return ret; -} - -static int __devexit ad2s1200_remove(struct spi_device *spi) -{ - iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); - - return 0; } static const struct spi_device_id ad2s1200_id[] = { @@ -168,7 +157,6 @@ static struct spi_driver ad2s1200_driver = { .owner = THIS_MODULE, }, .probe = ad2s1200_probe, - .remove = __devexit_p(ad2s1200_remove), .id_table = ad2s1200_id, }; module_spi_driver(ad2s1200_driver); diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c index c439fcf72be..7fbaba41c87 100644 --- a/drivers/staging/iio/resolver/ad2s1210.c +++ b/drivers/staging/iio/resolver/ad2s1210.c @@ -18,8 +18,8 @@ #include <linux/gpio.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #include "ad2s1210.h" #define DRV_NAME "ad2s1210" @@ -130,15 +130,12 @@ static int ad2s1210_config_read(struct ad2s1210_state *st, .rx_buf = st->rx, .tx_buf = st->tx, }; - struct spi_message msg; int ret = 0; ad2s1210_set_mode(MOD_CONFIG, st); - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); st->tx[0] = address | AD2S1210_MSB_IS_HIGH; st->tx[1] = AD2S1210_REG_FAULT; - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret < 0) return ret; st->old_data = true; @@ -195,26 +192,11 @@ static inline int ad2s1210_soft_reset(struct ad2s1210_state *st) return ad2s1210_config_write(st, 0x0); } -static ssize_t ad2s1210_store_softreset(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); - int ret; - - mutex_lock(&st->lock); - ret = ad2s1210_soft_reset(st); - mutex_unlock(&st->lock); - - return ret < 0 ? ret : len; -} - static ssize_t ad2s1210_show_fclkin(struct device *dev, struct device_attribute *attr, char *buf) { - struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); + struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev)); return sprintf(buf, "%d\n", st->fclkin); } @@ -223,11 +205,11 @@ static ssize_t ad2s1210_store_fclkin(struct device *dev, const char *buf, size_t len) { - struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); - unsigned long fclkin; + struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev)); + unsigned int fclkin; int ret; - ret = strict_strtoul(buf, 10, &fclkin); + ret = kstrtouint(buf, 10, &fclkin); if (ret) return ret; if (fclkin < AD2S1210_MIN_CLKIN || fclkin > AD2S1210_MAX_CLKIN) { @@ -252,7 +234,7 @@ static ssize_t ad2s1210_show_fexcit(struct device *dev, struct device_attribute *attr, char *buf) { - struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); + struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev)); return sprintf(buf, "%d\n", st->fexcit); } @@ -260,11 +242,11 @@ static ssize_t ad2s1210_store_fexcit(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); - unsigned long fexcit; + struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev)); + unsigned int fexcit; int ret; - ret = strict_strtoul(buf, 10, &fexcit); + ret = kstrtouint(buf, 10, &fexcit); if (ret < 0) return ret; if (fexcit < AD2S1210_MIN_EXCIT || fexcit > AD2S1210_MAX_EXCIT) { @@ -287,7 +269,7 @@ static ssize_t ad2s1210_show_control(struct device *dev, struct device_attribute *attr, char *buf) { - struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); + struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev)); int ret; mutex_lock(&st->lock); ret = ad2s1210_config_read(st, AD2S1210_REG_CONTROL); @@ -299,12 +281,12 @@ static ssize_t ad2s1210_store_control(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); - unsigned long udata; + struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev)); + unsigned char udata; unsigned char data; int ret; - ret = strict_strtoul(buf, 16, &udata); + ret = kstrtou8(buf, 16, &udata); if (ret) return -EINVAL; @@ -330,7 +312,7 @@ static ssize_t ad2s1210_store_control(struct device *dev, if (st->pdata->gpioin) { data = ad2s1210_read_resolution_pin(st); if (data != st->resolution) - pr_warning("ad2s1210: resolution settings not match\n"); + pr_warn("ad2s1210: resolution settings not match\n"); } else ad2s1210_set_resolution_pin(st); @@ -345,7 +327,7 @@ error_ret: static ssize_t ad2s1210_show_resolution(struct device *dev, struct device_attribute *attr, char *buf) { - struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); + struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev)); return sprintf(buf, "%d\n", st->resolution); } @@ -353,12 +335,12 @@ static ssize_t ad2s1210_store_resolution(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); + struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev)); unsigned char data; - unsigned long udata; + unsigned char udata; int ret; - ret = strict_strtoul(buf, 10, &udata); + ret = kstrtou8(buf, 10, &udata); if (ret || udata < 10 || udata > 16) { pr_err("ad2s1210: resolution out of range\n"); return -EINVAL; @@ -390,7 +372,7 @@ static ssize_t ad2s1210_store_resolution(struct device *dev, if (st->pdata->gpioin) { data = ad2s1210_read_resolution_pin(st); if (data != st->resolution) - pr_warning("ad2s1210: resolution settings not match\n"); + pr_warn("ad2s1210: resolution settings not match\n"); } else ad2s1210_set_resolution_pin(st); ret = len; @@ -403,7 +385,7 @@ error_ret: static ssize_t ad2s1210_show_fault(struct device *dev, struct device_attribute *attr, char *buf) { - struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); + struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev)); int ret; mutex_lock(&st->lock); @@ -418,7 +400,7 @@ static ssize_t ad2s1210_clear_fault(struct device *dev, const char *buf, size_t len) { - struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); + struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev)); int ret; mutex_lock(&st->lock); @@ -441,7 +423,7 @@ static ssize_t ad2s1210_show_reg(struct device *dev, struct device_attribute *attr, char *buf) { - struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); + struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev)); struct iio_dev_attr *iattr = to_iio_dev_attr(attr); int ret; @@ -455,12 +437,12 @@ static ssize_t ad2s1210_show_reg(struct device *dev, static ssize_t ad2s1210_store_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); - unsigned long data; + struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev)); + unsigned char data; int ret; struct iio_dev_attr *iattr = to_iio_dev_attr(attr); - ret = strict_strtoul(buf, 10, &data); + ret = kstrtou8(buf, 10, &data); if (ret) return -EINVAL; mutex_lock(&st->lock); @@ -539,8 +521,6 @@ error_ret: return ret; } -static IIO_DEVICE_ATTR(reset, S_IWUSR, - NULL, ad2s1210_store_softreset, 0); static IIO_DEVICE_ATTR(fclkin, S_IRUGO | S_IWUSR, ad2s1210_show_fclkin, ad2s1210_store_fclkin, 0); static IIO_DEVICE_ATTR(fexcit, S_IRUGO | S_IWUSR, @@ -575,20 +555,21 @@ static IIO_DEVICE_ATTR(lot_low_thrd, S_IRUGO | S_IWUSR, AD2S1210_REG_LOT_LOW_THRD); -static struct iio_chan_spec ad2s1210_channels[] = { +static const struct iio_chan_spec ad2s1210_channels[] = { { .type = IIO_ANGL, .indexed = 1, .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), }, { .type = IIO_ANGL_VEL, .indexed = 1, .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), } }; static struct attribute *ad2s1210_attributes[] = { - &iio_dev_attr_reset.dev_attr.attr, &iio_dev_attr_fclkin.dev_attr.attr, &iio_dev_attr_fexcit.dev_attr.attr, &iio_dev_attr_control.dev_attr.attr, @@ -608,7 +589,7 @@ static const struct attribute_group ad2s1210_attribute_group = { .attrs = ad2s1210_attributes, }; -static int __devinit ad2s1210_initial(struct ad2s1210_state *st) +static int ad2s1210_initial(struct ad2s1210_state *st) { unsigned char data; int ret; @@ -679,7 +660,7 @@ static void ad2s1210_free_gpios(struct ad2s1210_state *st) gpio_free_array(ad2s1210_gpios, ARRAY_SIZE(ad2s1210_gpios)); } -static int __devinit ad2s1210_probe(struct spi_device *spi) +static int ad2s1210_probe(struct spi_device *spi) { struct iio_dev *indio_dev; struct ad2s1210_state *st; @@ -688,16 +669,14 @@ static int __devinit ad2s1210_probe(struct spi_device *spi) if (spi->dev.platform_data == NULL) return -EINVAL; - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; st = iio_priv(indio_dev); st->pdata = spi->dev.platform_data; ret = ad2s1210_setup_gpios(st); if (ret < 0) - goto error_free_dev; + return ret; spi_set_drvdata(spi, indio_dev); @@ -728,19 +707,15 @@ static int __devinit ad2s1210_probe(struct spi_device *spi) error_free_gpios: ad2s1210_free_gpios(st); -error_free_dev: - iio_free_device(indio_dev); -error_ret: return ret; } -static int __devexit ad2s1210_remove(struct spi_device *spi) +static int ad2s1210_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); iio_device_unregister(indio_dev); ad2s1210_free_gpios(iio_priv(indio_dev)); - iio_free_device(indio_dev); return 0; } @@ -757,7 +732,7 @@ static struct spi_driver ad2s1210_driver = { .owner = THIS_MODULE, }, .probe = ad2s1210_probe, - .remove = __devexit_p(ad2s1210_remove), + .remove = ad2s1210_remove, .id_table = ad2s1210_id, }; module_spi_driver(ad2s1210_driver); diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c index 2a86f582ddf..e24c5890652 100644 --- a/drivers/staging/iio/resolver/ad2s90.c +++ b/drivers/staging/iio/resolver/ad2s90.c @@ -16,8 +16,8 @@ #include <linux/sysfs.h> #include <linux/module.h> -#include "../iio.h" -#include "../sysfs.h" +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> struct ad2s90_state { struct mutex lock; @@ -55,19 +55,18 @@ static const struct iio_chan_spec ad2s90_chan = { .type = IIO_ANGL, .indexed = 1, .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), }; -static int __devinit ad2s90_probe(struct spi_device *spi) +static int ad2s90_probe(struct spi_device *spi) { struct iio_dev *indio_dev; struct ad2s90_state *st; int ret = 0; - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; st = iio_priv(indio_dev); spi_set_drvdata(spi, indio_dev); @@ -82,7 +81,7 @@ static int __devinit ad2s90_probe(struct spi_device *spi) ret = iio_device_register(indio_dev); if (ret) - goto error_free_dev; + return ret; /* need 600ns between CS and the first falling edge of SCLK */ spi->max_speed_hz = 830000; @@ -90,17 +89,11 @@ static int __devinit ad2s90_probe(struct spi_device *spi) spi_setup(spi); return 0; - -error_free_dev: - iio_free_device(indio_dev); -error_ret: - return ret; } -static int __devexit ad2s90_remove(struct spi_device *spi) +static int ad2s90_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); return 0; } @@ -117,7 +110,7 @@ static struct spi_driver ad2s90_driver = { .owner = THIS_MODULE, }, .probe = ad2s90_probe, - .remove = __devexit_p(ad2s90_remove), + .remove = ad2s90_remove, .id_table = ad2s90_id, }; module_spi_driver(ad2s90_driver); diff --git a/drivers/staging/iio/ring_hw.h b/drivers/staging/iio/ring_hw.h index cad8a2ed9b6..39c14a71586 100644 --- a/drivers/staging/iio/ring_hw.h +++ b/drivers/staging/iio/ring_hw.h @@ -5,7 +5,7 @@ * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * - * Copyright (c) 2009 Jonathan Cameron <jic23@cam.ac.uk> + * Copyright (c) 2009 Jonathan Cameron <jic23@kernel.org> * */ diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c deleted file mode 100644 index 3e24ec45585..00000000000 --- a/drivers/staging/iio/ring_sw.c +++ /dev/null @@ -1,367 +0,0 @@ -/* The industrial I/O simple minimally locked ring buffer. - * - * 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. - */ - -#include <linux/slab.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/workqueue.h> -#include <linux/sched.h> -#include <linux/poll.h> -#include "ring_sw.h" -#include "trigger.h" - -/** - * struct iio_sw_ring_buffer - software ring buffer - * @buf: generic ring buffer elements - * @data: the ring buffer memory - * @read_p: read pointer (oldest available) - * @write_p: write pointer - * @half_p: half buffer length behind write_p (event generation) - * @update_needed: flag to indicated change in size requested - * - * Note that the first element of all ring buffers must be a - * struct iio_buffer. -**/ -struct iio_sw_ring_buffer { - struct iio_buffer buf; - unsigned char *data; - unsigned char *read_p; - unsigned char *write_p; - /* used to act as a point at which to signal an event */ - unsigned char *half_p; - int update_needed; -}; - -#define iio_to_sw_ring(r) container_of(r, struct iio_sw_ring_buffer, buf) - -static inline int __iio_allocate_sw_ring_buffer(struct iio_sw_ring_buffer *ring, - int bytes_per_datum, int length) -{ - if ((length == 0) || (bytes_per_datum == 0)) - return -EINVAL; - __iio_update_buffer(&ring->buf, bytes_per_datum, length); - ring->data = kmalloc(length*ring->buf.bytes_per_datum, GFP_ATOMIC); - ring->read_p = NULL; - ring->write_p = NULL; - ring->half_p = NULL; - return ring->data ? 0 : -ENOMEM; -} - -static inline void __iio_free_sw_ring_buffer(struct iio_sw_ring_buffer *ring) -{ - kfree(ring->data); -} - -/* Ring buffer related functionality */ -/* Store to ring is typically called in the bh of a data ready interrupt handler - * in the device driver */ -/* Lock always held if their is a chance this may be called */ -/* Only one of these per ring may run concurrently - enforced by drivers */ -static int iio_store_to_sw_ring(struct iio_sw_ring_buffer *ring, - unsigned char *data, s64 timestamp) -{ - int ret = 0; - unsigned char *temp_ptr, *change_test_ptr; - - /* initial store */ - if (unlikely(ring->write_p == NULL)) { - ring->write_p = ring->data; - /* Doesn't actually matter if this is out of the set - * 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.bytes_per_datum/2; - } - /* Copy data to where ever the current write pointer says */ - 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. - * Before this runs it is null and read attempts fail with -EAGAIN. - */ - barrier(); - /* 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.bytes_per_datum; - /* End of ring, back to the beginning */ - 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. - * Care needed with smp systems to ensure more than one ring fill - * is never scheduled. - */ - ring->write_p = temp_ptr; - - if (ring->read_p == NULL) - ring->read_p = ring->data; - /* Buffer full - move the read pointer and create / escalate - * ring event */ - /* Tricky case - if the read pointer moves before we adjust it. - * Handle by not pushing if it has moved - may result in occasional - * unnecessary buffer full events when it wasn't quite true. - */ - else if (ring->write_p == ring->read_p) { - change_test_ptr = ring->read_p; - temp_ptr = change_test_ptr + ring->buf.bytes_per_datum; - if (temp_ptr - == 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 - * change to the read pointer will be this or greater. - */ - if (change_test_ptr == ring->read_p) - ring->read_p = temp_ptr; - } - /* investigate if our event barrier has been passed */ - /* 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.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) { - ring->buf.stufftoread = true; - wake_up_interruptible(&ring->buf.pollq); - } - return ret; -} - -static int iio_read_first_n_sw_rb(struct iio_buffer *r, - size_t n, char __user *buf) -{ - struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); - - u8 *initial_read_p, *initial_write_p, *current_read_p, *end_read_p; - u8 *data; - int ret, max_copied, bytes_to_rip, dead_offset; - size_t data_available, buffer_size; - - /* A userspace program has probably made an error if it tries to - * read something that is not a whole number of bpds. - * Return an error. - */ - if (n % ring->buf.bytes_per_datum) { - ret = -EINVAL; - printk(KERN_INFO "Ring buffer read request not whole number of" - "samples: Request bytes %zd, Current bytes per datum %d\n", - n, ring->buf.bytes_per_datum); - goto error_ret; - } - - buffer_size = ring->buf.bytes_per_datum*ring->buf.length; - - /* Limit size to whole of ring buffer */ - bytes_to_rip = min_t(size_t, buffer_size, n); - - data = kmalloc(bytes_to_rip, GFP_KERNEL); - if (data == NULL) { - ret = -ENOMEM; - goto error_ret; - } - - /* build local copy */ - initial_read_p = ring->read_p; - if (unlikely(initial_read_p == NULL)) { /* No data here as yet */ - ret = 0; - goto error_free_data_cpy; - } - - initial_write_p = ring->write_p; - - /* Need a consistent pair */ - while ((initial_read_p != ring->read_p) - || (initial_write_p != ring->write_p)) { - initial_read_p = ring->read_p; - initial_write_p = ring->write_p; - } - if (initial_write_p == initial_read_p) { - /* No new data available.*/ - ret = 0; - goto error_free_data_cpy; - } - - if (initial_write_p >= initial_read_p) - data_available = initial_write_p - initial_read_p; - else - data_available = buffer_size - (initial_read_p - initial_write_p); - - if (data_available < bytes_to_rip) - bytes_to_rip = data_available; - - if (initial_read_p + bytes_to_rip >= ring->data + buffer_size) { - max_copied = ring->data + buffer_size - initial_read_p; - memcpy(data, initial_read_p, max_copied); - memcpy(data + max_copied, ring->data, bytes_to_rip - max_copied); - end_read_p = ring->data + bytes_to_rip - max_copied; - } else { - memcpy(data, initial_read_p, bytes_to_rip); - end_read_p = initial_read_p + bytes_to_rip; - } - - /* Now to verify which section was cleanly copied - i.e. how far - * read pointer has been pushed */ - current_read_p = ring->read_p; - - if (initial_read_p <= current_read_p) - dead_offset = current_read_p - initial_read_p; - else - dead_offset = buffer_size - (initial_read_p - current_read_p); - - /* possible issue if the initial write has been lapped or indeed - * the point we were reading to has been passed */ - /* No valid data read. - * In this case the read pointer is already correct having been - * pushed further than we would look. */ - if (bytes_to_rip - dead_offset < 0) { - ret = 0; - goto error_free_data_cpy; - } - - /* setup the next read position */ - /* Beware, this may fail due to concurrency fun and games. - * Possible that sufficient fill commands have run to push the read - * pointer past where we would be after the rip. If this occurs, leave - * it be. - */ - /* Tricky - deal with loops */ - - while (ring->read_p != end_read_p) - ring->read_p = end_read_p; - - ret = bytes_to_rip - dead_offset; - - if (copy_to_user(buf, data + dead_offset, ret)) { - ret = -EFAULT; - goto error_free_data_cpy; - } - - if (bytes_to_rip >= ring->buf.length*ring->buf.bytes_per_datum/2) - ring->buf.stufftoread = 0; - -error_free_data_cpy: - kfree(data); -error_ret: - - return ret; -} - -static int iio_store_to_sw_rb(struct iio_buffer *r, - u8 *data, - s64 timestamp) -{ - struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); - return iio_store_to_sw_ring(ring, data, timestamp); -} - -static int iio_request_update_sw_rb(struct iio_buffer *r) -{ - int ret = 0; - struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); - - r->stufftoread = false; - if (!ring->update_needed) - goto error_ret; - __iio_free_sw_ring_buffer(ring); - ret = __iio_allocate_sw_ring_buffer(ring, ring->buf.bytes_per_datum, - ring->buf.length); -error_ret: - return ret; -} - -static int iio_get_bytes_per_datum_sw_rb(struct iio_buffer *r) -{ - struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); - return ring->buf.bytes_per_datum; -} - -static int iio_mark_update_needed_sw_rb(struct iio_buffer *r) -{ - struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); - ring->update_needed = true; - return 0; -} - -static int iio_set_bytes_per_datum_sw_rb(struct iio_buffer *r, size_t bpd) -{ - if (r->bytes_per_datum != bpd) { - r->bytes_per_datum = bpd; - iio_mark_update_needed_sw_rb(r); - } - return 0; -} - -static int iio_get_length_sw_rb(struct iio_buffer *r) -{ - return r->length; -} - -static int iio_set_length_sw_rb(struct iio_buffer *r, int length) -{ - if (r->length != length) { - r->length = length; - iio_mark_update_needed_sw_rb(r); - } - return 0; -} - -static IIO_BUFFER_ENABLE_ATTR; -static IIO_BUFFER_LENGTH_ATTR; - -/* Standard set of ring buffer attributes */ -static struct attribute *iio_ring_attributes[] = { - &dev_attr_length.attr, - &dev_attr_enable.attr, - NULL, -}; - -static struct attribute_group iio_ring_attribute_group = { - .attrs = iio_ring_attributes, - .name = "buffer", -}; - -struct iio_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev) -{ - struct iio_buffer *buf; - struct iio_sw_ring_buffer *ring; - - ring = kzalloc(sizeof *ring, GFP_KERNEL); - if (!ring) - return NULL; - ring->update_needed = true; - buf = &ring->buf; - iio_buffer_init(buf); - buf->attrs = &iio_ring_attribute_group; - - return buf; -} -EXPORT_SYMBOL(iio_sw_rb_allocate); - -void iio_sw_rb_free(struct iio_buffer *r) -{ - kfree(iio_to_sw_ring(r)); -} -EXPORT_SYMBOL(iio_sw_rb_free); - -const struct iio_buffer_access_funcs ring_sw_access_funcs = { - .store_to = &iio_store_to_sw_rb, - .read_first_n = &iio_read_first_n_sw_rb, - .request_update = &iio_request_update_sw_rb, - .get_bytes_per_datum = &iio_get_bytes_per_datum_sw_rb, - .set_bytes_per_datum = &iio_set_bytes_per_datum_sw_rb, - .get_length = &iio_get_length_sw_rb, - .set_length = &iio_set_length_sw_rb, -}; -EXPORT_SYMBOL(ring_sw_access_funcs); - -MODULE_DESCRIPTION("Industrialio I/O software ring buffer"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/ring_sw.h b/drivers/staging/iio/ring_sw.h deleted file mode 100644 index e6a6e2c4096..00000000000 --- a/drivers/staging/iio/ring_sw.h +++ /dev/null @@ -1,35 +0,0 @@ -/* The industrial I/O simple minimally locked ring buffer. - * - * 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 code is deliberately kept separate from the main industrialio I/O core - * as it is intended that in the future a number of different software ring - * buffer implementations will exist with different characteristics to suit - * different applications. - * - * This particular one was designed for a data capture application where it was - * particularly important that no userspace reads would interrupt the capture - * process. To this end the ring is not locked during a read. - * - * Comments on this buffer design welcomed. It's far from efficient and some of - * my understanding of the effects of scheduling on this are somewhat limited. - * Frankly, to my mind, this is the current weak point in the industrial I/O - * patch set. - */ - -#ifndef _IIO_RING_SW_H_ -#define _IIO_RING_SW_H_ -#include "buffer.h" - -/** - * ring_sw_access_funcs - access functions for a software ring buffer - **/ -extern const struct iio_buffer_access_funcs ring_sw_access_funcs; - -struct iio_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev); -void iio_sw_rb_free(struct iio_buffer *ring); -#endif /* _IIO_RING_SW_H_ */ diff --git a/drivers/staging/iio/sysfs.h b/drivers/staging/iio/sysfs.h deleted file mode 100644 index bfedb73b850..00000000000 --- a/drivers/staging/iio/sysfs.h +++ /dev/null @@ -1,117 +0,0 @@ -/* The industrial I/O core - * - *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. - * - * General attributes - */ - -#ifndef _INDUSTRIAL_IO_SYSFS_H_ -#define _INDUSTRIAL_IO_SYSFS_H_ - -struct iio_chan_spec; - -/** - * struct iio_dev_attr - iio specific device attribute - * @dev_attr: underlying device attribute - * @address: associated register address - * @l: list head for maintaining list of dynamically created attrs. - */ -struct iio_dev_attr { - struct device_attribute dev_attr; - u64 address; - struct list_head l; - struct iio_chan_spec const *c; -}; - -#define to_iio_dev_attr(_dev_attr) \ - container_of(_dev_attr, struct iio_dev_attr, dev_attr) - -ssize_t iio_read_const_attr(struct device *dev, - struct device_attribute *attr, - char *len); - -/** - * struct iio_const_attr - constant device specific attribute - * often used for things like available modes - * @string: attribute string - * @dev_attr: underlying device attribute - */ -struct iio_const_attr { - const char *string; - struct device_attribute dev_attr; -}; - -#define to_iio_const_attr(_dev_attr) \ - container_of(_dev_attr, struct iio_const_attr, dev_attr) - -/* Some attributes will be hard coded (device dependent) and not require an - address, in these cases pass a negative */ -#define IIO_ATTR(_name, _mode, _show, _store, _addr) \ - { .dev_attr = __ATTR(_name, _mode, _show, _store), \ - .address = _addr } - -#define IIO_DEVICE_ATTR(_name, _mode, _show, _store, _addr) \ - struct iio_dev_attr iio_dev_attr_##_name \ - = IIO_ATTR(_name, _mode, _show, _store, _addr) - -#define IIO_DEVICE_ATTR_NAMED(_vname, _name, _mode, _show, _store, _addr) \ - struct iio_dev_attr iio_dev_attr_##_vname \ - = IIO_ATTR(_name, _mode, _show, _store, _addr) - -#define IIO_CONST_ATTR(_name, _string) \ - struct iio_const_attr iio_const_attr_##_name \ - = { .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 */ -/** - * IIO_DEV_ATTR_RESET: resets the device - **/ -#define IIO_DEV_ATTR_RESET(_store) \ - IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, _store, 0) - -/** - * IIO_DEV_ATTR_SAMP_FREQ - sets any internal clock frequency - * @_mode: sysfs file mode/permissions - * @_show: output method for the attribute - * @_store: input method for the attribute - **/ -#define IIO_DEV_ATTR_SAMP_FREQ(_mode, _show, _store) \ - IIO_DEVICE_ATTR(sampling_frequency, _mode, _show, _store, 0) - -/** - * IIO_DEV_ATTR_SAMP_FREQ_AVAIL - list available sampling frequencies - * @_show: output method for the attribute - * - * May be mode dependent on some devices - **/ -#define IIO_DEV_ATTR_SAMP_FREQ_AVAIL(_show) \ - IIO_DEVICE_ATTR(sampling_frequency_available, S_IRUGO, _show, NULL, 0) -/** - * IIO_CONST_ATTR_AVAIL_SAMP_FREQ - list available sampling frequencies - * @_string: frequency string for the attribute - * - * Constant version - **/ -#define IIO_CONST_ATTR_SAMP_FREQ_AVAIL(_string) \ - IIO_CONST_ATTR(sampling_frequency_available, _string) - -#define IIO_DEV_ATTR_TEMP_RAW(_show) \ - IIO_DEVICE_ATTR(in_temp_raw, S_IRUGO, _show, NULL, 0) - -#define IIO_CONST_ATTR_TEMP_OFFSET(_string) \ - IIO_CONST_ATTR(in_temp_offset, _string) - -#define IIO_CONST_ATTR_TEMP_SCALE(_string) \ - IIO_CONST_ATTR(in_temp_scale, _string) - -#endif /* _INDUSTRIAL_IO_SYSFS_H_ */ diff --git a/drivers/staging/iio/trigger.h b/drivers/staging/iio/trigger.h deleted file mode 100644 index 1cfca231db8..00000000000 --- a/drivers/staging/iio/trigger.h +++ /dev/null @@ -1,119 +0,0 @@ -/* The industrial I/O core, trigger handling functions - * - * Copyright (c) 2008 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ -#include <linux/irq.h> -#include <linux/module.h> - -#ifndef _IIO_TRIGGER_H_ -#define _IIO_TRIGGER_H_ - -struct iio_subirq { - bool enabled; -}; - -/** - * struct iio_trigger_ops - operations structure for an iio_trigger. - * @owner: used to monitor usage count of the trigger. - * @set_trigger_state: switch on/off the trigger on demand - * @try_reenable: function to reenable the trigger when the - * use count is zero (may be NULL) - * @validate_device: function to validate the device when the - * current trigger gets changed. - * - * This is typically static const within a driver and shared by - * instances of a given device. - **/ -struct iio_trigger_ops { - struct module *owner; - int (*set_trigger_state)(struct iio_trigger *trig, bool state); - int (*try_reenable)(struct iio_trigger *trig); - int (*validate_device)(struct iio_trigger *trig, - struct iio_dev *indio_dev); -}; - - -/** - * struct iio_trigger - industrial I/O trigger device - * - * @id: [INTERN] unique id number - * @name: [DRIVER] unique name - * @dev: [DRIVER] associated device (if relevant) - * @private_data: [DRIVER] device specific data - * @list: [INTERN] used in maintenance of global trigger list - * @alloc_list: [DRIVER] used for driver specific trigger list - * @use_count: use count for the trigger - * @subirq_chip: [INTERN] associate 'virtual' irq chip. - * @subirq_base: [INTERN] base number for irqs provided by trigger. - * @subirqs: [INTERN] information about the 'child' irqs. - * @pool: [INTERN] bitmap of irqs currently in use. - * @pool_lock: [INTERN] protection of the irq pool. - **/ -struct iio_trigger { - const struct iio_trigger_ops *ops; - int id; - const char *name; - struct device dev; - - void *private_data; - struct list_head list; - struct list_head alloc_list; - int use_count; - - struct irq_chip subirq_chip; - int subirq_base; - - struct iio_subirq subirqs[CONFIG_IIO_CONSUMERS_PER_TRIGGER]; - unsigned long pool[BITS_TO_LONGS(CONFIG_IIO_CONSUMERS_PER_TRIGGER)]; - struct mutex pool_lock; -}; - - -static inline struct iio_trigger *to_iio_trigger(struct device *d) -{ - return container_of(d, struct iio_trigger, dev); -}; - -static inline void iio_put_trigger(struct iio_trigger *trig) -{ - module_put(trig->ops->owner); - put_device(&trig->dev); -}; - -static inline void iio_get_trigger(struct iio_trigger *trig) -{ - get_device(&trig->dev); - __module_get(trig->ops->owner); -}; - -/** - * iio_trigger_register() - register a trigger with the IIO core - * @trig_info: trigger to be registered - **/ -int iio_trigger_register(struct iio_trigger *trig_info); - -/** - * iio_trigger_unregister() - unregister a trigger from the core - * @trig_info: trigger to be unregistered - **/ -void iio_trigger_unregister(struct iio_trigger *trig_info); - -/** - * iio_trigger_poll() - called on a trigger occurring - * @trig: trigger which occurred - * - * Typically called in relevant hardware interrupt handler. - **/ -void iio_trigger_poll(struct iio_trigger *trig, s64 time); -void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time); - -irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private); - -__printf(1, 2) struct iio_trigger *iio_allocate_trigger(const char *fmt, ...); -void iio_free_trigger(struct iio_trigger *trig); - -#endif /* _IIO_TRIGGER_H_ */ diff --git a/drivers/staging/iio/trigger/Kconfig b/drivers/staging/iio/trigger/Kconfig index b8abf5473dd..2fd18c60323 100644 --- a/drivers/staging/iio/trigger/Kconfig +++ b/drivers/staging/iio/trigger/Kconfig @@ -12,22 +12,6 @@ config IIO_PERIODIC_RTC_TRIGGER Provides support for using periodic capable real time clocks as IIO triggers. -config IIO_GPIO_TRIGGER - tristate "GPIO trigger" - depends on GENERIC_GPIO - help - Provides support for using GPIO pins as IIO triggers. - -config IIO_SYSFS_TRIGGER - tristate "SYSFS trigger" - depends on SYSFS - help - Provides support for using SYSFS entry as IIO triggers. - 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 iio-trig-sysfs. - config IIO_BFIN_TMR_TRIGGER tristate "Blackfin TIMER trigger" depends on BLACKFIN diff --git a/drivers/staging/iio/trigger/Makefile b/drivers/staging/iio/trigger/Makefile index b088b57da33..238481b78e7 100644 --- a/drivers/staging/iio/trigger/Makefile +++ b/drivers/staging/iio/trigger/Makefile @@ -3,6 +3,4 @@ # obj-$(CONFIG_IIO_PERIODIC_RTC_TRIGGER) += iio-trig-periodic-rtc.o -obj-$(CONFIG_IIO_GPIO_TRIGGER) += iio-trig-gpio.o -obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o obj-$(CONFIG_IIO_BFIN_TMR_TRIGGER) += iio-trig-bfin-timer.o diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c index 1cbb25dff8b..26e1ca0b780 100644 --- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c +++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c @@ -14,14 +14,18 @@ #include <linux/delay.h> #include <asm/gptimers.h> +#include <asm/portmux.h> -#include "../iio.h" -#include "../trigger.h" +#include <linux/iio/iio.h> +#include <linux/iio/trigger.h> + +#include "iio-trig-bfin-timer.h" struct bfin_timer { unsigned short id, bit; unsigned long irqbit; int irq; + int pin; }; /* @@ -30,22 +34,22 @@ struct bfin_timer { */ static struct bfin_timer iio_bfin_timer_code[MAX_BLACKFIN_GPTIMERS] = { - {TIMER0_id, TIMER0bit, TIMER_STATUS_TIMIL0, IRQ_TIMER0}, - {TIMER1_id, TIMER1bit, TIMER_STATUS_TIMIL1, IRQ_TIMER1}, - {TIMER2_id, TIMER2bit, TIMER_STATUS_TIMIL2, IRQ_TIMER2}, + {TIMER0_id, TIMER0bit, TIMER_STATUS_TIMIL0, IRQ_TIMER0, P_TMR0}, + {TIMER1_id, TIMER1bit, TIMER_STATUS_TIMIL1, IRQ_TIMER1, P_TMR1}, + {TIMER2_id, TIMER2bit, TIMER_STATUS_TIMIL2, IRQ_TIMER2, P_TMR2}, #if (MAX_BLACKFIN_GPTIMERS > 3) - {TIMER3_id, TIMER3bit, TIMER_STATUS_TIMIL3, IRQ_TIMER3}, - {TIMER4_id, TIMER4bit, TIMER_STATUS_TIMIL4, IRQ_TIMER4}, - {TIMER5_id, TIMER5bit, TIMER_STATUS_TIMIL5, IRQ_TIMER5}, - {TIMER6_id, TIMER6bit, TIMER_STATUS_TIMIL6, IRQ_TIMER6}, - {TIMER7_id, TIMER7bit, TIMER_STATUS_TIMIL7, IRQ_TIMER7}, + {TIMER3_id, TIMER3bit, TIMER_STATUS_TIMIL3, IRQ_TIMER3, P_TMR3}, + {TIMER4_id, TIMER4bit, TIMER_STATUS_TIMIL4, IRQ_TIMER4, P_TMR4}, + {TIMER5_id, TIMER5bit, TIMER_STATUS_TIMIL5, IRQ_TIMER5, P_TMR5}, + {TIMER6_id, TIMER6bit, TIMER_STATUS_TIMIL6, IRQ_TIMER6, P_TMR6}, + {TIMER7_id, TIMER7bit, TIMER_STATUS_TIMIL7, IRQ_TIMER7, P_TMR7}, #endif #if (MAX_BLACKFIN_GPTIMERS > 8) - {TIMER8_id, TIMER8bit, TIMER_STATUS_TIMIL8, IRQ_TIMER8}, - {TIMER9_id, TIMER9bit, TIMER_STATUS_TIMIL9, IRQ_TIMER9}, - {TIMER10_id, TIMER10bit, TIMER_STATUS_TIMIL10, IRQ_TIMER10}, + {TIMER8_id, TIMER8bit, TIMER_STATUS_TIMIL8, IRQ_TIMER8, P_TMR8}, + {TIMER9_id, TIMER9bit, TIMER_STATUS_TIMIL9, IRQ_TIMER9, P_TMR9}, + {TIMER10_id, TIMER10bit, TIMER_STATUS_TIMIL10, IRQ_TIMER10, P_TMR10}, #if (MAX_BLACKFIN_GPTIMERS > 11) - {TIMER11_id, TIMER11bit, TIMER_STATUS_TIMIL11, IRQ_TIMER11}, + {TIMER11_id, TIMER11bit, TIMER_STATUS_TIMIL11, IRQ_TIMER11, P_TMR11}, #endif #endif }; @@ -54,54 +58,78 @@ struct bfin_tmr_state { struct iio_trigger *trig; struct bfin_timer *t; unsigned timer_num; + bool output_enable; + unsigned int duty; int irq; }; +static int iio_bfin_tmr_set_state(struct iio_trigger *trig, bool state) +{ + struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig); + + if (get_gptimer_period(st->t->id) == 0) + return -EINVAL; + + if (state) + enable_gptimers(st->t->bit); + else + disable_gptimers(st->t->bit); + + return 0; +} + static ssize_t iio_bfin_tmr_frequency_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct iio_trigger *trig = dev_get_drvdata(dev); - struct bfin_tmr_state *st = trig->private_data; - long val; + struct iio_trigger *trig = to_iio_trigger(dev); + struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig); + unsigned int val; + bool enabled; int ret; - ret = strict_strtoul(buf, 10, &val); + ret = kstrtouint(buf, 10, &val); if (ret) - goto error_ret; + return ret; - if (val > 100000) { - ret = -EINVAL; - goto error_ret; - } + if (val > 100000) + return -EINVAL; - disable_gptimers(st->t->bit); + enabled = get_enabled_gptimers() & st->t->bit; + + if (enabled) + disable_gptimers(st->t->bit); - if (!val) - goto error_ret; + if (val == 0) + return count; val = get_sclk() / val; - if (val <= 4) { - ret = -EINVAL; - goto error_ret; - } + if (val <= 4 || val <= st->duty) + return -EINVAL; set_gptimer_period(st->t->id, val); - set_gptimer_pwidth(st->t->id, 1); - enable_gptimers(st->t->bit); + set_gptimer_pwidth(st->t->id, val - st->duty); + + if (enabled) + enable_gptimers(st->t->bit); -error_ret: - return ret ? ret : count; + return count; } static ssize_t iio_bfin_tmr_frequency_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_trigger *trig = dev_get_drvdata(dev); - struct bfin_tmr_state *st = trig->private_data; + struct iio_trigger *trig = to_iio_trigger(dev); + struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig); + unsigned int period = get_gptimer_period(st->t->id); + unsigned long val; + + if (period == 0) + val = 0; + else + val = get_sclk() / get_gptimer_period(st->t->id); - return sprintf(buf, "%lu\n", - get_sclk() / get_gptimer_period(st->t->id)); + return sprintf(buf, "%lu\n", val); } static DEVICE_ATTR(frequency, S_IRUGO | S_IWUSR, iio_bfin_tmr_frequency_show, @@ -121,7 +149,6 @@ static const struct attribute_group *iio_bfin_tmr_trigger_attr_groups[] = { NULL }; - static irqreturn_t iio_bfin_tmr_trigger_isr(int irq, void *devid) { struct bfin_tmr_state *st = devid; @@ -145,11 +172,14 @@ static int iio_bfin_tmr_get_number(int irq) static const struct iio_trigger_ops iio_bfin_tmr_trigger_ops = { .owner = THIS_MODULE, + .set_trigger_state = iio_bfin_tmr_set_state, }; -static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev) +static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev) { + struct iio_bfin_timer_trigger_pdata *pdata = pdev->dev.platform_data; struct bfin_tmr_state *st; + unsigned int config; int ret; st = kzalloc(sizeof(*st), GFP_KERNEL); @@ -172,15 +202,15 @@ static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev) st->timer_num = ret; st->t = &iio_bfin_timer_code[st->timer_num]; - st->trig = iio_allocate_trigger("bfintmr%d", st->timer_num); + st->trig = iio_trigger_alloc("bfintmr%d", st->timer_num); if (!st->trig) { ret = -ENOMEM; goto out1; } - st->trig->private_data = st; st->trig->ops = &iio_bfin_tmr_trigger_ops; st->trig->dev.groups = iio_bfin_tmr_trigger_attr_groups; + iio_trigger_set_drvdata(st->trig, st); ret = iio_trigger_register(st->trig); if (ret) goto out2; @@ -193,31 +223,63 @@ static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev) goto out4; } - set_gptimer_config(st->t->id, OUT_DIS | PWM_OUT | PERIOD_CNT | IRQ_ENA); + config = PWM_OUT | PERIOD_CNT | IRQ_ENA; + + if (pdata && pdata->output_enable) { + unsigned long long val; + + st->output_enable = true; + + ret = peripheral_request(st->t->pin, st->trig->name); + if (ret) + goto out_free_irq; + + val = (unsigned long long)get_sclk() * pdata->duty_ns; + do_div(val, NSEC_PER_SEC); + st->duty = val; + + /** + * The interrupt will be generated at the end of the period, + * since we want the interrupt to be generated at end of the + * pulse we invert both polarity and duty cycle, so that the + * pulse will be generated directly before the interrupt. + */ + if (pdata->active_low) + config |= PULSE_HI; + } else { + st->duty = 1; + config |= OUT_DIS; + } + + set_gptimer_config(st->t->id, config); dev_info(&pdev->dev, "iio trigger Blackfin TMR%d, IRQ-%d", st->timer_num, st->irq); platform_set_drvdata(pdev, st); return 0; +out_free_irq: + free_irq(st->irq, st); out4: iio_trigger_unregister(st->trig); out2: - iio_put_trigger(st->trig); + iio_trigger_put(st->trig); out1: kfree(st); out: return ret; } -static int __devexit iio_bfin_tmr_trigger_remove(struct platform_device *pdev) +static int iio_bfin_tmr_trigger_remove(struct platform_device *pdev) { struct bfin_tmr_state *st = platform_get_drvdata(pdev); disable_gptimers(st->t->bit); + if (st->output_enable) + peripheral_free(st->t->pin); free_irq(st->irq, st); iio_trigger_unregister(st->trig); - iio_put_trigger(st->trig); + iio_trigger_put(st->trig); kfree(st); return 0; @@ -229,20 +291,10 @@ static struct platform_driver iio_bfin_tmr_trigger_driver = { .owner = THIS_MODULE, }, .probe = iio_bfin_tmr_trigger_probe, - .remove = __devexit_p(iio_bfin_tmr_trigger_remove), + .remove = iio_bfin_tmr_trigger_remove, }; -static int __init iio_bfin_tmr_trig_init(void) -{ - return platform_driver_register(&iio_bfin_tmr_trigger_driver); -} -module_init(iio_bfin_tmr_trig_init); - -static void __exit iio_bfin_tmr_trig_exit(void) -{ - platform_driver_unregister(&iio_bfin_tmr_trigger_driver); -} -module_exit(iio_bfin_tmr_trig_exit); +module_platform_driver(iio_bfin_tmr_trigger_driver); MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); MODULE_DESCRIPTION("Blackfin system timer based trigger for the iio subsystem"); diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.h b/drivers/staging/iio/trigger/iio-trig-bfin-timer.h new file mode 100644 index 00000000000..c07321f8d94 --- /dev/null +++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.h @@ -0,0 +1,24 @@ +#ifndef __IIO_BFIN_TIMER_TRIGGER_H__ +#define __IIO_BFIN_TIMER_TRIGGER_H__ + +/** + * struct iio_bfin_timer_trigger_pdata - timer trigger platform data + * @output_enable: Enable external trigger pulse generation. + * @active_low: Whether the trigger pulse is active low. + * @duty_ns: Length of the trigger pulse in nanoseconds. + * + * This struct is used to configure the output pulse generation of the blackfin + * timer trigger. If output_enable is set to true an external trigger signal + * will generated on the pin corresponding to the timer. This is useful for + * converters which needs an external signal to start conversion. active_low and + * duty_ns are used to configure the type of the trigger pulse. If output_enable + * is set to false no external trigger pulse will be generated and active_low + * and duty_ns are ignored. + **/ +struct iio_bfin_timer_trigger_pdata { + bool output_enable; + bool active_low; + unsigned int duty_ns; +}; + +#endif diff --git a/drivers/staging/iio/trigger/iio-trig-gpio.c b/drivers/staging/iio/trigger/iio-trig-gpio.c deleted file mode 100644 index f2a65598162..00000000000 --- a/drivers/staging/iio/trigger/iio-trig-gpio.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Industrial I/O - gpio based trigger support - * - * 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. - * - * Currently this is more of a functioning proof of concept than a full - * fledged trigger driver. - * - * TODO: - * - * Add board config elements to allow specification of startup settings. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/interrupt.h> -#include <linux/gpio.h> -#include <linux/slab.h> - -#include "../iio.h" -#include "../trigger.h" - -static LIST_HEAD(iio_gpio_trigger_list); -static DEFINE_MUTEX(iio_gpio_trigger_list_lock); - -struct iio_gpio_trigger_info { - struct mutex in_use; - unsigned int irq; -}; -/* - * Need to reference count these triggers and only enable gpio interrupts - * as appropriate. - */ - -/* So what functionality do we want in here?... */ -/* set high / low as interrupt type? */ - -static irqreturn_t iio_gpio_trigger_poll(int irq, void *private) -{ - /* Timestamp not currently provided */ - iio_trigger_poll(private, 0); - return IRQ_HANDLED; -} - -static const struct iio_trigger_ops iio_gpio_trigger_ops = { - .owner = THIS_MODULE, -}; - -static int iio_gpio_trigger_probe(struct platform_device *pdev) -{ - struct iio_gpio_trigger_info *trig_info; - struct iio_trigger *trig, *trig2; - unsigned long irqflags; - struct resource *irq_res; - int irq, ret = 0, irq_res_cnt = 0; - - do { - irq_res = platform_get_resource(pdev, - IORESOURCE_IRQ, irq_res_cnt); - - if (irq_res == NULL) { - if (irq_res_cnt == 0) - dev_err(&pdev->dev, "No GPIO IRQs specified"); - break; - } - irqflags = (irq_res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED; - - for (irq = irq_res->start; irq <= irq_res->end; irq++) { - - trig = iio_allocate_trigger("irqtrig%d", irq); - if (!trig) { - ret = -ENOMEM; - goto error_free_completed_registrations; - } - - trig_info = kzalloc(sizeof(*trig_info), GFP_KERNEL); - if (!trig_info) { - ret = -ENOMEM; - goto error_put_trigger; - } - trig->private_data = trig_info; - trig_info->irq = irq; - trig->ops = &iio_gpio_trigger_ops; - ret = request_irq(irq, iio_gpio_trigger_poll, - irqflags, trig->name, trig); - if (ret) { - dev_err(&pdev->dev, - "request IRQ-%d failed", irq); - goto error_free_trig_info; - } - - ret = iio_trigger_register(trig); - if (ret) - goto error_release_irq; - - list_add_tail(&trig->alloc_list, - &iio_gpio_trigger_list); - } - - irq_res_cnt++; - } while (irq_res != NULL); - - - return 0; - -/* First clean up the partly allocated trigger */ -error_release_irq: - free_irq(irq, trig); -error_free_trig_info: - kfree(trig_info); -error_put_trigger: - iio_put_trigger(trig); -error_free_completed_registrations: - /* The rest should have been added to the iio_gpio_trigger_list */ - list_for_each_entry_safe(trig, - trig2, - &iio_gpio_trigger_list, - alloc_list) { - trig_info = trig->private_data; - free_irq(gpio_to_irq(trig_info->irq), trig); - kfree(trig_info); - iio_trigger_unregister(trig); - } - - return ret; -} - -static int iio_gpio_trigger_remove(struct platform_device *pdev) -{ - struct iio_trigger *trig, *trig2; - struct iio_gpio_trigger_info *trig_info; - - mutex_lock(&iio_gpio_trigger_list_lock); - list_for_each_entry_safe(trig, - trig2, - &iio_gpio_trigger_list, - alloc_list) { - trig_info = trig->private_data; - iio_trigger_unregister(trig); - free_irq(trig_info->irq, trig); - kfree(trig_info); - iio_put_trigger(trig); - } - mutex_unlock(&iio_gpio_trigger_list_lock); - - return 0; -} - -static struct platform_driver iio_gpio_trigger_driver = { - .probe = iio_gpio_trigger_probe, - .remove = iio_gpio_trigger_remove, - .driver = { - .name = "iio_gpio_trigger", - .owner = THIS_MODULE, - }, -}; - -static int __init iio_gpio_trig_init(void) -{ - return platform_driver_register(&iio_gpio_trigger_driver); -} -module_init(iio_gpio_trig_init); - -static void __exit iio_gpio_trig_exit(void) -{ - platform_driver_unregister(&iio_gpio_trigger_driver); -} -module_exit(iio_gpio_trig_exit); - -MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); -MODULE_DESCRIPTION("Example gpio trigger for the iio subsystem"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c index bd7416b2c56..38ecb4bb6e4 100644 --- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c +++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c @@ -16,8 +16,8 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/rtc.h> -#include "../iio.h" -#include "../trigger.h" +#include <linux/iio/iio.h> +#include <linux/iio/trigger.h> static LIST_HEAD(iio_prtc_trigger_list); static DEFINE_MUTEX(iio_prtc_trigger_list_lock); @@ -30,10 +30,11 @@ struct iio_prtc_trigger_info { static int iio_trig_periodic_rtc_set_state(struct iio_trigger *trig, bool state) { - struct iio_prtc_trigger_info *trig_info = trig->private_data; + struct iio_prtc_trigger_info *trig_info = iio_trigger_get_drvdata(trig); if (trig_info->frequency == 0) return -EINVAL; - printk(KERN_INFO "trigger frequency is %d\n", trig_info->frequency); + dev_info(&trig_info->rtc->dev, "trigger frequency is %d\n", + trig_info->frequency); return rtc_irq_set_state(trig_info->rtc, &trig_info->task, state); } @@ -41,8 +42,8 @@ static ssize_t iio_trig_periodic_read_freq(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_trigger *trig = dev_get_drvdata(dev); - struct iio_prtc_trigger_info *trig_info = trig->private_data; + struct iio_trigger *trig = to_iio_trigger(dev); + struct iio_prtc_trigger_info *trig_info = iio_trigger_get_drvdata(trig); return sprintf(buf, "%u\n", trig_info->frequency); } @@ -51,12 +52,12 @@ static ssize_t iio_trig_periodic_write_freq(struct device *dev, const char *buf, size_t len) { - struct iio_trigger *trig = dev_get_drvdata(dev); - struct iio_prtc_trigger_info *trig_info = trig->private_data; - unsigned long val; + struct iio_trigger *trig = to_iio_trigger(dev); + struct iio_prtc_trigger_info *trig_info = iio_trigger_get_drvdata(trig); + int val; int ret; - ret = strict_strtoul(buf, 10, &val); + ret = kstrtoint(buf, 10, &val); if (ret) goto error_ret; @@ -112,7 +113,7 @@ static int iio_trig_periodic_rtc_probe(struct platform_device *dev) for (i = 0;; i++) { if (pdata[i] == NULL) break; - trig = iio_allocate_trigger("periodic%s", pdata[i]); + trig = iio_trigger_alloc("periodic%s", pdata[i]); if (!trig) { ret = -ENOMEM; goto error_free_completed_registrations; @@ -124,7 +125,7 @@ static int iio_trig_periodic_rtc_probe(struct platform_device *dev) ret = -ENOMEM; goto error_put_trigger_and_remove_from_list; } - trig->private_data = trig_info; + iio_trigger_set_drvdata(trig, trig_info); trig->ops = &iio_prtc_trigger_ops; /* RTC access */ trig_info->rtc @@ -152,13 +153,13 @@ error_free_trig_info: kfree(trig_info); error_put_trigger_and_remove_from_list: list_del(&trig->alloc_list); - iio_put_trigger(trig); + iio_trigger_put(trig); error_free_completed_registrations: list_for_each_entry_safe(trig, trig2, &iio_prtc_trigger_list, alloc_list) { - trig_info = trig->private_data; + trig_info = iio_trigger_get_drvdata(trig); rtc_irq_unregister(trig_info->rtc, &trig_info->task); rtc_class_close(trig_info->rtc); kfree(trig_info); @@ -176,7 +177,7 @@ static int iio_trig_periodic_rtc_remove(struct platform_device *dev) trig2, &iio_prtc_trigger_list, alloc_list) { - trig_info = trig->private_data; + trig_info = iio_trigger_get_drvdata(trig); rtc_irq_unregister(trig_info->rtc, &trig_info->task); rtc_class_close(trig_info->rtc); kfree(trig_info); @@ -195,18 +196,8 @@ static struct platform_driver iio_trig_periodic_rtc_driver = { }, }; -static int __init iio_trig_periodic_rtc_init(void) -{ - return platform_driver_register(&iio_trig_periodic_rtc_driver); -} - -static void __exit iio_trig_periodic_rtc_exit(void) -{ - return platform_driver_unregister(&iio_trig_periodic_rtc_driver); -} +module_platform_driver(iio_trig_periodic_rtc_driver); -module_init(iio_trig_periodic_rtc_init); -module_exit(iio_trig_periodic_rtc_exit); -MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); +MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); MODULE_DESCRIPTION("Periodic realtime clock trigger for the iio subsystem"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/trigger/iio-trig-sysfs.c b/drivers/staging/iio/trigger/iio-trig-sysfs.c deleted file mode 100644 index 174dc65709d..00000000000 --- a/drivers/staging/iio/trigger/iio-trig-sysfs.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - * - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/list.h> - -#include "../iio.h" -#include "../trigger.h" - -struct iio_sysfs_trig { - struct iio_trigger *trig; - int id; - struct list_head l; -}; - -static LIST_HEAD(iio_sysfs_trig_list); -static DEFINE_MUTEX(iio_syfs_trig_list_mut); - -static int iio_sysfs_trigger_probe(int id); -static ssize_t iio_sysfs_trig_add(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - int ret; - unsigned long input; - - ret = strict_strtoul(buf, 10, &input); - if (ret) - return ret; - ret = iio_sysfs_trigger_probe(input); - if (ret) - return ret; - return len; -} -static DEVICE_ATTR(add_trigger, S_IWUSR, NULL, &iio_sysfs_trig_add); - -static int iio_sysfs_trigger_remove(int id); -static ssize_t iio_sysfs_trig_remove(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - int ret; - unsigned long input; - - ret = strict_strtoul(buf, 10, &input); - if (ret) - return ret; - ret = iio_sysfs_trigger_remove(input); - if (ret) - return ret; - return len; -} - -static DEVICE_ATTR(remove_trigger, S_IWUSR, NULL, &iio_sysfs_trig_remove); - -static struct attribute *iio_sysfs_trig_attrs[] = { - &dev_attr_add_trigger.attr, - &dev_attr_remove_trigger.attr, - NULL, -}; - -static const struct attribute_group iio_sysfs_trig_group = { - .attrs = iio_sysfs_trig_attrs, -}; - -static const struct attribute_group *iio_sysfs_trig_groups[] = { - &iio_sysfs_trig_group, - NULL -}; - - -/* Nothing to actually do upon release */ -static void iio_trigger_sysfs_release(struct device *dev) -{ -} - -static struct device iio_sysfs_trig_dev = { - .bus = &iio_bus_type, - .groups = iio_sysfs_trig_groups, - .release = &iio_trigger_sysfs_release, -}; - -static ssize_t iio_sysfs_trigger_poll(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct iio_trigger *trig = dev_get_drvdata(dev); - iio_trigger_poll_chained(trig, 0); - - return count; -} - -static DEVICE_ATTR(trigger_now, S_IWUSR, NULL, iio_sysfs_trigger_poll); - -static struct attribute *iio_sysfs_trigger_attrs[] = { - &dev_attr_trigger_now.attr, - NULL, -}; - -static const struct attribute_group iio_sysfs_trigger_attr_group = { - .attrs = iio_sysfs_trigger_attrs, -}; - -static const struct attribute_group *iio_sysfs_trigger_attr_groups[] = { - &iio_sysfs_trigger_attr_group, - NULL -}; - -static const struct iio_trigger_ops iio_sysfs_trigger_ops = { - .owner = THIS_MODULE, -}; - -static int iio_sysfs_trigger_probe(int id) -{ - struct iio_sysfs_trig *t; - int ret; - bool foundit = false; - mutex_lock(&iio_syfs_trig_list_mut); - list_for_each_entry(t, &iio_sysfs_trig_list, l) - if (id == t->id) { - foundit = true; - break; - } - if (foundit) { - ret = -EINVAL; - goto out1; - } - t = kmalloc(sizeof(*t), GFP_KERNEL); - if (t == NULL) { - ret = -ENOMEM; - goto out1; - } - t->id = id; - t->trig = iio_allocate_trigger("sysfstrig%d", id); - if (!t->trig) { - ret = -ENOMEM; - goto free_t; - } - - t->trig->dev.groups = iio_sysfs_trigger_attr_groups; - t->trig->ops = &iio_sysfs_trigger_ops; - t->trig->dev.parent = &iio_sysfs_trig_dev; - - ret = iio_trigger_register(t->trig); - if (ret) - goto out2; - list_add(&t->l, &iio_sysfs_trig_list); - __module_get(THIS_MODULE); - mutex_unlock(&iio_syfs_trig_list_mut); - return 0; - -out2: - iio_put_trigger(t->trig); -free_t: - kfree(t); -out1: - mutex_unlock(&iio_syfs_trig_list_mut); - return ret; -} - -static int iio_sysfs_trigger_remove(int id) -{ - bool foundit = false; - struct iio_sysfs_trig *t; - mutex_lock(&iio_syfs_trig_list_mut); - list_for_each_entry(t, &iio_sysfs_trig_list, l) - if (id == t->id) { - foundit = true; - break; - } - if (!foundit) { - mutex_unlock(&iio_syfs_trig_list_mut); - return -EINVAL; - } - - iio_trigger_unregister(t->trig); - iio_free_trigger(t->trig); - - list_del(&t->l); - kfree(t); - module_put(THIS_MODULE); - mutex_unlock(&iio_syfs_trig_list_mut); - return 0; -} - - -static int __init iio_sysfs_trig_init(void) -{ - device_initialize(&iio_sysfs_trig_dev); - dev_set_name(&iio_sysfs_trig_dev, "iio_sysfs_trigger"); - return device_add(&iio_sysfs_trig_dev); -} -module_init(iio_sysfs_trig_init); - -static void __exit iio_sysfs_trig_exit(void) -{ - device_unregister(&iio_sysfs_trig_dev); -} -module_exit(iio_sysfs_trig_exit); - -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("Sysfs based trigger for the iio subsystem"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:iio-trig-sysfs"); diff --git a/drivers/staging/iio/trigger_consumer.h b/drivers/staging/iio/trigger_consumer.h deleted file mode 100644 index 60d64b35694..00000000000 --- a/drivers/staging/iio/trigger_consumer.h +++ /dev/null @@ -1,52 +0,0 @@ -/* The industrial I/O core, trigger consumer functions - * - * Copyright (c) 2008-2011 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -/** - * struct iio_poll_func - poll function pair - * - * @indio_dev: data specific to device (passed into poll func) - * @h: the function that is actually run on trigger - * @thread: threaded interrupt part - * @type: the type of interrupt (basically if oneshot) - * @name: name used to identify the trigger consumer. - * @irq: the corresponding irq as allocated from the - * trigger pool - * @timestamp: some devices need a timestamp grabbed as soon - * as possible after the trigger - hence handler - * passes it via here. - **/ -struct iio_poll_func { - struct iio_dev *indio_dev; - irqreturn_t (*h)(int irq, void *p); - irqreturn_t (*thread)(int irq, void *p); - int type; - char *name; - int irq; - s64 timestamp; -}; - - -struct iio_poll_func -*iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p), - irqreturn_t (*thread)(int irq, void *p), - int type, - struct iio_dev *indio_dev, - const char *fmt, - ...); -void iio_dealloc_pollfunc(struct iio_poll_func *pf); -irqreturn_t iio_pollfunc_store_time(int irq, void *p); - -void iio_trigger_notify_done(struct iio_trigger *trig); - -/* - * Two functions for common case where all that happens is a pollfunc - * is attached and detached from a trigger - */ -int iio_triggered_buffer_postenable(struct iio_dev *indio_dev); -int iio_triggered_buffer_predisable(struct iio_dev *indio_dev); diff --git a/drivers/staging/iio/types.h b/drivers/staging/iio/types.h deleted file mode 100644 index b7d26474ad0..00000000000 --- a/drivers/staging/iio/types.h +++ /dev/null @@ -1,49 +0,0 @@ -/* industrial I/O data types needed both in and out of kernel - * - * 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. - */ - -#ifndef _IIO_TYPES_H_ -#define _IIO_TYPES_H_ - -enum iio_chan_type { - /* real channel types */ - IIO_VOLTAGE, - IIO_CURRENT, - IIO_POWER, - IIO_ACCEL, - IIO_ANGL_VEL, - IIO_MAGN, - IIO_LIGHT, - IIO_INTENSITY, - IIO_PROXIMITY, - IIO_TEMP, - IIO_INCLI, - IIO_ROT, - IIO_ANGL, - IIO_TIMESTAMP, - IIO_CAPACITANCE, -}; - -enum iio_modifier { - IIO_NO_MOD, - IIO_MOD_X, - IIO_MOD_Y, - IIO_MOD_Z, - IIO_MOD_X_AND_Y, - IIO_MOD_X_AND_Z, - IIO_MOD_Y_AND_Z, - IIO_MOD_X_AND_Y_AND_Z, - IIO_MOD_X_OR_Y, - IIO_MOD_X_OR_Z, - IIO_MOD_Y_OR_Z, - IIO_MOD_X_OR_Y_OR_Z, - IIO_MOD_LIGHT_BOTH, - IIO_MOD_LIGHT_IR, -}; - -#endif /* _IIO_TYPES_H_ */ |
