diff options
Diffstat (limited to 'drivers/staging/iio')
181 files changed, 14432 insertions, 10393 deletions
diff --git a/drivers/staging/iio/Documentation/generic_buffer.c b/drivers/staging/iio/Documentation/generic_buffer.c index f82894f..d580953 100644 --- a/drivers/staging/iio/Documentation/generic_buffer.c +++ b/drivers/staging/iio/Documentation/generic_buffer.c @@ -173,7 +173,7 @@ int main(int argc, char **argv) return -1; /* Find the device requested */ - dev_num = find_type_by_name(device_name, "device"); + dev_num = find_type_by_name(device_name, "iio:device"); if (dev_num < 0) { printf("Failed to find the %s\n", device_name); ret = -ENODEV; @@ -181,7 +181,7 @@ int main(int argc, char **argv) } printf("iio device number being used is %d\n", dev_num); - asprintf(&dev_dir_name, "%sdevice%d", iio_dir, dev_num); + 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 @@ -212,6 +212,7 @@ int main(int argc, char **argv) ret = build_channel_array(dev_dir_name, &infoarray, &num_channels); if (ret) { printf("Problem reading scan element information\n"); + printf("diag %s\n", dev_dir_name); goto error_free_triggername; } @@ -220,7 +221,8 @@ int main(int argc, char **argv) * As we know that the lis3l02dq has only one buffer this may * be built rather than found. */ - ret = asprintf(&buf_dir_name, "%sdevice%d:buffer0", iio_dir, dev_num); + ret = asprintf(&buf_dir_name, + "%siio:device%d/buffer", iio_dir, dev_num); if (ret < 0) { ret = -ENOMEM; goto error_free_triggername; @@ -251,9 +253,7 @@ int main(int argc, char **argv) goto error_free_buf_dir_name; } - ret = asprintf(&buffer_access, - "/dev/device%d:buffer0", - dev_num); + ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num); if (ret < 0) { ret = -ENOMEM; goto error_free_data; diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h index 150f440..75938b2 100644 --- a/drivers/staging/iio/Documentation/iio_utils.h +++ b/drivers/staging/iio/Documentation/iio_utils.h @@ -16,7 +16,7 @@ #define IIO_MAX_NAME_LENGTH 30 -#define FORMAT_SCAN_ELEMENTS_DIR "%s:buffer0/scan_elements" +#define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements" #define FORMAT_TYPE_FILE "%s_type" const char *iio_dir = "/sys/bus/iio/devices/"; diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio b/drivers/staging/iio/Documentation/sysfs-bus-iio index 467c49a..0d6823d 100644 --- a/drivers/staging/iio/Documentation/sysfs-bus-iio +++ b/drivers/staging/iio/Documentation/sysfs-bus-iio @@ -1,17 +1,11 @@ -What: /sys/bus/iio/devices/deviceX +What: /sys/bus/iio/devices/iio:deviceX KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: - Hardware chip or device accessed by on communication port. + Hardware chip or device accessed by one communication port. Corresponds to a grouping of sensor channels. X is the IIO index of the device. -What: /sys/bus/iio/devices/device[n]/power_state -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - This property gets/sets the device power state. - What: /sys/bus/iio/devices/triggerX KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org @@ -25,21 +19,22 @@ Description: generalize well and hence are not documented in this file. X is the IIO index of the trigger. -What: /sys/bus/iio/devices/deviceX:buffer +What: /sys/bus/iio/devices/iio:deviceX/buffer KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: - Link to /sys/class/iio/deviceX/deviceX:buffer. X indicates - the device with which this buffer buffer is associated. + Directory of attributes relating to the buffer for the device. -What: /sys/bus/iio/devices/deviceX/name +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/deviceX/sampling_frequency +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: @@ -50,42 +45,32 @@ Description: effects datardy triggers, hardware buffers and the sysfs direct access interfaces, it may be found in any of the relevant directories. If it effects all of the above - then it is to be found in the base device directory as here. + then it is to be found in the base device directory. -What: /sys/bus/iio/devices/deviceX/sampling_frequency_available +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/deviceX/range -KernelVersion: 2.6.38 -Contact: linux-iio@vger.kernel.org -Description: - Hardware dependent ADC Full Scale Range in mVolt. - -What: /sys/bus/iio/devices/deviceX/range_available -KernelVersion: 2.6.38 -Contact: linux-iio@vger.kernel.org -Description: - Hardware dependent supported vales for ADC Full Scale Range. - -What: /sys/bus/iio/devices/deviceX/oversampling_ratio +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/deviceX/oversampling_ratio_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/deviceX/inY_raw -What: /sys/bus/iio/devices/deviceX/inY_supply_raw +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: @@ -93,9 +78,10 @@ Description: 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. + unique to allow association with event codes. Units after + application of scale and offset are microvolts. -What: /sys/bus/iio/devices/deviceX/inY-inZ_raw +What: /sys/bus/iio/devices/iio:deviceX/in_voltageY-voltageZ_raw KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: @@ -103,52 +89,73 @@ Description: 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. + is required is a consistent labeling. Units after application + of scale and offset are microvolts. -What: /sys/bus/iio/devices/deviceX/temp_raw -What: /sys/bus/iio/devices/deviceX/temp_x_raw -What: /sys/bus/iio/devices/deviceX/temp_y_raw -What: /sys/bus/iio/devices/deviceX/temp_z_raw +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). + a gyroscope axis). Units after application of scale and offset + are milli degrees Celsuis. -What: /sys/bus/iio/devices/deviceX/tempX_input +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/deviceX/accel_x_raw -What: /sys/bus/iio/devices/deviceX/accel_y_raw -What: /sys/bus/iio/devices/deviceX/accel_z_raw +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) - channel m (not present if only one accelerometer channel at - this orientation). Has all of the equivalent parameters as per - inY. Units after application of scale and offset are m/s^2. - -What: /sys/bus/iio/devices/deviceX/gyro_x_raw -What: /sys/bus/iio/devices/deviceX/gyro_y_raw -What: /sys/bus/iio/devices/deviceX/gyro_z_raw + 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 inY. + per voltageY. Units after application of scale and offset are + radians per second. -What: /sys/bus/iio/devices/deviceX/incli_x_raw -What: /sys/bus/iio/devices/deviceX/incli_y_raw -What: /sys/bus/iio/devices/deviceX/incli_z_raw +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: @@ -156,63 +163,69 @@ Description: arbitrarily assigned). Data converted by application of offset and scale to Degrees. -What: /sys/bus/iio/devices/deviceX/magn_x_raw -What: /sys/bus/iio/devices/deviceX/magn_y_raw -What: /sys/bus/iio/devices/deviceX/magn_z_raw +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) channel m (not present if only one magnetometer - at this orientation). Data converted by application of - offset then scale to Gauss. Has all the equivalent modifiers - as per inY. - -What: /sys/bus/iio/devices/deviceX/accel_x_peak_raw -What: /sys/bus/iio/devices/deviceX/accel_y_peak_raw -What: /sys/bus/iio/devices/deviceX/accel_z_peak_raw + 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: - Some devices provide a store of the highest value seen since - some reset condition. These attributes allow access to this - and are otherwise the direct equivalent of the - <type>Y[_name]_raw attributes. + 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/deviceX/accel_xyz_squared_peak_raw +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/deviceX/accel_offset -What: /sys/bus/iio/devices/deviceX/temp_offset +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 is not - present, then the offset applies to all in channels of <type>. + 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. - -What: /sys/bus/iio/devices/deviceX/inY_scale -What: /sys/bus/iio/devices/deviceX/inY_supply_scale -What: /sys/bus/iio/devices/deviceX/in_scale -What: /sys/bus/iio/devices/deviceX/outY_scale -What: /sys/bus/iio/devices/deviceX/accel_scale -What: /sys/bus/iio/devices/deviceX/accel_peak_scale -What: /sys/bus/iio/devices/deviceX/gyro_scale -What: /sys/bus/iio/devices/deviceX/magn_scale -What: /sys/bus/iio/devices/deviceX/magn_x_scale -What: /sys/bus/iio/devices/deviceX/magn_y_scale -What: /sys/bus/iio/devices/deviceX/magn_z_scale + 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: @@ -220,32 +233,31 @@ Description: 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 is 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/deviceX/accel_x_calibbias -What: /sys/bus/iio/devices/deviceX/accel_y_calibbias -What: /sys/bus/iio/devices/deviceX/accel_z_calibbias -What: /sys/bus/iio/devices/deviceX/gyro_x_calibbias -What: /sys/bus/iio/devices/deviceX/gyro_y_calibbias -What: /sys/bus/iio/devices/deviceX/gyro_z_calibbias + 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). If shared across all channels, <type>_calibbias - is used. - -What /sys/bus/iio/devices/deviceX/inY_calibscale -What /sys/bus/iio/devices/deviceX/inY_supply_calibscale -What /sys/bus/iio/devices/deviceX/in_calibscale -What /sys/bus/iio/devices/deviceX/accel_x_calibscale -What /sys/bus/iio/devices/deviceX/accel_y_calibscale -What /sys/bus/iio/devices/deviceX/accel_z_calibscale -What /sys/bus/iio/devices/deviceX/gyro_x_calibscale -What /sys/bus/iio/devices/deviceX/gyro_y_calibscale -What /sys/bus/iio/devices/deviceX/gyro_z_calibscale + 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: @@ -253,14 +265,18 @@ Description: production inaccuracies). If shared across all channels, <type>_calibscale is used. -What: /sys/bus/iio/devices/deviceX/accel_scale_available +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/bus/iio/devices/deviceX/outY_raw +What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_raw KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: @@ -268,7 +284,7 @@ Description: channel Y. The number must always be specified and unique if the output corresponds to a single channel. -What: /sys/bus/iio/devices/deviceX/outY&Z_raw +What: /sys/bus/iio/devices/iio:deviceX/out_voltageY&Z_raw KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: @@ -277,8 +293,8 @@ Description: where a single output sets the value for multiple channels simultaneously. -What: /sys/bus/iio/devices/deviceX/outY_powerdown_mode -What: /sys/bus/iio/devices/deviceX/out_powerdown_mode +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: @@ -291,16 +307,16 @@ Description: outX_powerdown_mode_available. If Y is not present the mode is shared across all outputs. -What: /sys/bus/iio/devices/deviceX/outY_powerdown_mode_available -What: /sys/bus/iio/devices/deviceX/out_powerdown_mode_available +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/deviceX/outY_powerdown -What: /sys/bus/iio/devices/deviceX/out_powerdown +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: @@ -309,55 +325,47 @@ Description: normal operation. Y may be suppressed if all outputs are controlled together. -What: /sys/bus/iio/devices/deviceX/deviceX:eventY +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/bus/iio/devices/deviceX:event/dev -What: /sys/bus/iio/devices/deviceX:eventY/dev -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - major:minor character device numbers for the event line Y of - device X. - -What: /sys/.../deviceX:eventY/accel_x_thresh_rising_en -What: /sys/.../deviceX:eventY/accel_x_thresh_falling_en -What: /sys/.../deviceX:eventY/accel_y_thresh_rising_en -What: /sys/.../deviceX:eventY/accel_y_thresh_falling_en -What: /sys/.../deviceX:eventY/accel_z_thresh_rising_en -What: /sys/.../deviceX:eventY/accel_z_thresh_falling_en -What: /sys/.../deviceX:eventY/gyro_x_thresh_rising_en -What: /sys/.../deviceX:eventY/gyro_x_thresh_falling_en -What: /sys/.../deviceX:eventY/gyro_y_thresh_rising_en -What: /sys/.../deviceX:eventY/gyro_y_thresh_falling_en -What: /sys/.../deviceX:eventY/gyro_z_thresh_rising_en -What: /sys/.../deviceX:eventY/gyro_z_thresh_falling_en -What: /sys/.../deviceX:eventY/magn_x_thresh_rising_en -What: /sys/.../deviceX:eventY/magn_x_thresh_falling_en -What: /sys/.../deviceX:eventY/magn_y_thresh_rising_en -What: /sys/.../deviceX:eventY/magn_y_thresh_falling_en -What: /sys/.../deviceX:eventY/magn_z_thresh_rising_en -What: /sys/.../deviceX:eventY/magn_z_thresh_falling_en -What: /sys/.../deviceX:eventY/inZ_supply_thresh_rising_en -What: /sys/.../deviceX:eventY/inZ_supply_thresh_falling_en -What: /sys/.../deviceX:eventY/inZ_thresh_rising_en -What: /sys/.../deviceX:eventY/inZ_thresh_falling_en -What: /sys/.../deviceX:eventY/temp_thresh_rising_en -What: /sys/.../deviceX:eventY/temp_thresh_falling_en +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 called in (e.g. - <type>[Z][_name]_<raw|input>_thresh_value) or - <type>[Z][_name]_<raw|input>_thresh_rising_value and - <type>[Z][_name]_<raw|input>_thresh_falling_value may take + 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 @@ -369,30 +377,30 @@ Description: a given event type is enabled a future point (and not those for whatever event was previously enabled). -What: /sys/.../deviceX:eventY/accel_x_roc_rising_en -What: /sys/.../deviceX:eventY/accel_x_roc_falling_en -What: /sys/.../deviceX:eventY/accel_y_roc_rising_en -What: /sys/.../deviceX:eventY/accel_y_roc_falling_en -What: /sys/.../deviceX:eventY/accel_z_roc_rising_en -What: /sys/.../deviceX:eventY/accel_z_roc_falling_en -What: /sys/.../deviceX:eventY/gyro_x_roc_rising_en -What: /sys/.../deviceX:eventY/gyro_x_roc_falling_en -What: /sys/.../deviceX:eventY/gyro_y_roc_rising_en -What: /sys/.../deviceX:eventY/gyro_y_roc_falling_en -What: /sys/.../deviceX:eventY/gyro_z_roc_rising_en -What: /sys/.../deviceX:eventY/gyro_z_roc_falling_en -What: /sys/.../deviceX:eventY/magn_x_roc_rising_en -What: /sys/.../deviceX:eventY/magn_x_roc_falling_en -What: /sys/.../deviceX:eventY/magn_y_roc_rising_en -What: /sys/.../deviceX:eventY/magn_y_roc_falling_en -What: /sys/.../deviceX:eventY/magn_z_roc_rising_en -What: /sys/.../deviceX:eventY/magn_z_roc_falling_en -What: /sys/.../deviceX:eventY/inZ_supply_roc_rising_en -What: /sys/.../deviceX:eventY/inZ_supply_roc_falling_en -What: /sys/.../deviceX:eventY/inZ_roc_rising_en -What: /sys/.../deviceX:eventY/inZ_roc_falling_en -What: /sys/.../deviceX:eventY/temp_roc_rising_en -What: /sys/.../deviceX:eventY/temp_roc_falling_en +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: @@ -400,10 +408,10 @@ Description: 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 called in (e.g. - <type>[Z][_name]_<raw|input>_roc_value) or - <type>[Z][_name]_<raw|input>_roc_rising_value and - <type>[Z][_name]_<raw|input>_roc_falling_value may take + 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 @@ -415,73 +423,73 @@ Description: a given event type is enabled a future point (and not those for whatever event was previously enabled). -What: /sys/.../deviceX:eventY/accel_x_raw_thresh_rising_value -What: /sys/.../deviceX:eventY/accel_x_raw_thresh_falling_value -What: /sys/.../deviceX:eventY/accel_y_raw_thresh_rising_value -What: /sys/.../deviceX:eventY/accel_y_raw_thresh_falling_value -What: /sys/.../deviceX:eventY/accel_z_raw_thresh_rising_value -What: /sys/.../deviceX:eventY/accel_z_raw_thresh_falling_value -What: /sys/.../deviceX:eventY/gyro_x_raw_thresh_rising_value -What: /sys/.../deviceX:eventY/gyro_x_raw_thresh_falling_value -What: /sys/.../deviceX:eventY/gyro_y_raw_thresh_rising_value -What: /sys/.../deviceX:eventY/gyro_y_raw_thresh_falling_value -What: /sys/.../deviceX:eventY/gyro_z_raw_thresh_rising_value -What: /sys/.../deviceX:eventY/gyro_z_raw_thresh_falling_value -What: /sys/.../deviceX:eventY/magn_x_raw_thresh_rising_value -What: /sys/.../deviceX:eventY/magn_x_raw_thresh_falling_value -What: /sys/.../deviceX:eventY/magn_y_raw_thresh_rising_value -What: /sys/.../deviceX:eventY/magn_y_raw_thresh_falling_value -What: /sys/.../deviceX:eventY/magn_z_raw_thresh_rising_value -What: /sys/.../deviceX:eventY/magn_z_raw_thresh_falling_value -What: /sys/.../deviceX:eventY/inZ_supply_raw_thresh_rising_value -What: /sys/.../deviceX:eventY/inZ_supply_raw_thresh_falling_value -What: /sys/.../deviceX:eventY/inZ_raw_thresh_falling_value -What: /sys/.../deviceX:eventY/inZ_raw_thresh_falling_value -What: /sys/.../deviceX:eventY/temp_raw_thresh_falling_value -What: /sys/.../deviceX:eventY/temp_raw_thresh_falling_value +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>Z[_name]_thresh[_rising|falling]_en. - If separate attributes exist for the two directions, but + <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/.../deviceX:eventY/accel_x_raw_roc_rising_value -What: /sys/.../deviceX:eventY/accel_x_raw_roc_falling_value -What: /sys/.../deviceX:eventY/accel_y_raw_roc_rising_value -What: /sys/.../deviceX:eventY/accel_y_raw_roc_falling_value -What: /sys/.../deviceX:eventY/accel_z_raw_roc_rising_value -What: /sys/.../deviceX:eventY/accel_z_raw_roc_falling_value -What: /sys/.../deviceX:eventY/gyro_x_raw_roc_rising_value -What: /sys/.../deviceX:eventY/gyro_x_raw_roc_falling_value -What: /sys/.../deviceX:eventY/gyro_y_raw_roc_rising_value -What: /sys/.../deviceX:eventY/gyro_y_raw_roc_falling_value -What: /sys/.../deviceX:eventY/gyro_z_raw_roc_rising_value -What: /sys/.../deviceX:eventY/gyro_z_raw_roc_falling_value -What: /sys/.../deviceX:eventY/magn_x_raw_roc_rising_value -What: /sys/.../deviceX:eventY/magn_x_raw_roc_falling_value -What: /sys/.../deviceX:eventY/magn_y_raw_roc_rising_value -What: /sys/.../deviceX:eventY/magn_y_raw_roc_falling_value -What: /sys/.../deviceX:eventY/magn_z_raw_roc_rising_value -What: /sys/.../deviceX:eventY/magn_z_raw_roc_falling_value -What: /sys/.../deviceX:eventY/inZ_supply_raw_roc_rising_value -What: /sys/.../deviceX:eventY/inZ_supply_raw_roc_falling_value -What: /sys/.../deviceX:eventY/inZ_raw_roc_falling_value -What: /sys/.../deviceX:eventY/inZ_raw_roc_falling_value -What: /sys/.../deviceX:eventY/temp_raw_roc_falling_value -What: /sys/.../deviceX:eventY/temp_raw_roc_falling_value +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>[Z][_name]_roc[_rising|falling]_en. + <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. @@ -489,55 +497,55 @@ Description: value is in raw device units or in processed units (as _raw and _input do on sysfs direct channel read attributes). -What: /sys/.../deviceX:eventY/accel_x_thresh_rising_period -What: /sys/.../deviceX:eventY/accel_x_thresh_falling_period -hat: /sys/.../deviceX:eventY/accel_x_roc_rising_period -What: /sys/.../deviceX:eventY/accel_x_roc_falling_period -What: /sys/.../deviceX:eventY/accel_y_thresh_rising_period -What: /sys/.../deviceX:eventY/accel_y_thresh_falling_period -What: /sys/.../deviceX:eventY/accel_y_roc_rising_period -What: /sys/.../deviceX:eventY/accel_y_roc_falling_period -What: /sys/.../deviceX:eventY/accel_z_thresh_rising_period -What: /sys/.../deviceX:eventY/accel_z_thresh_falling_period -What: /sys/.../deviceX:eventY/accel_z_roc_rising_period -What: /sys/.../deviceX:eventY/accel_z_roc_falling_period -What: /sys/.../deviceX:eventY/gyro_x_thresh_rising_period -What: /sys/.../deviceX:eventY/gyro_x_thresh_falling_period -What: /sys/.../deviceX:eventY/gyro_x_roc_rising_period -What: /sys/.../deviceX:eventY/gyro_x_roc_falling_period -What: /sys/.../deviceX:eventY/gyro_y_thresh_rising_period -What: /sys/.../deviceX:eventY/gyro_y_thresh_falling_period -What: /sys/.../deviceX:eventY/gyro_y_roc_rising_period -What: /sys/.../deviceX:eventY/gyro_y_roc_falling_period -What: /sys/.../deviceX:eventY/gyro_z_thresh_rising_period -What: /sys/.../deviceX:eventY/gyro_z_thresh_falling_period -What: /sys/.../deviceX:eventY/gyro_z_roc_rising_period -What: /sys/.../deviceX:eventY/gyro_z_roc_falling_period -What: /sys/.../deviceX:eventY/magn_x_thresh_rising_period -What: /sys/.../deviceX:eventY/magn_x_thresh_falling_period -What: /sys/.../deviceX:eventY/magn_x_roc_rising_period -What: /sys/.../deviceX:eventY/magn_x_roc_falling_period -What: /sys/.../deviceX:eventY/magn_y_thresh_rising_period -What: /sys/.../deviceX:eventY/magn_y_thresh_falling_period -What: /sys/.../deviceX:eventY/magn_y_roc_rising_period -What: /sys/.../deviceX:eventY/magn_y_roc_falling_period -What: /sys/.../deviceX:eventY/magn_z_thresh_rising_period -What: /sys/.../deviceX:eventY/magn_z_thresh_falling_period -What: /sys/.../deviceX:eventY/magn_z_roc_rising_period -What: /sys/.../deviceX:eventY/magn_z_roc_falling_period -What: /sys/.../deviceX:eventY/inZ_supply_thresh_rising_period -What: /sys/.../deviceX:eventY/inZ_supply_thresh_falling_period -What: /sys/.../deviceX:eventY/inz_supply_roc_rising_period -What: /sys/.../deviceX:eventY/inZ_supply_roc_falling_period -What: /sys/.../deviceX:eventY/inZ_thresh_rising_period -What: /sys/.../deviceX:eventY/inZ_thresh_falling_period -What: /sys/.../deviceX:eventY/inZ_roc_rising_period -What: /sys/.../deviceX:eventY/inZ_roc_falling_period -What: /sys/.../deviceX:eventY/temp_thresh_rising_period -What: /sys/.../deviceX:eventY/temp_thresh_falling_period -What: /sys/.../deviceX:eventY/temp_roc_rising_period -What: /sys/.../deviceX:eventY/temp_roc_falling_period -What: /sys/.../deviceX:eventY/accel_x&y&z_mag_falling_period +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: @@ -545,31 +553,31 @@ Description: met before an event is generated. If direction is not specified then this period applies to both directions. -What: /sys/.../deviceX:eventY/accel_mag_en -What: /sys/.../deviceX:eventY/accel_mag_rising_en -What: /sys/.../deviceX:eventY/accel_mag_falling_en -What: /sys/.../deviceX:eventY/accel_x_mag_en -What: /sys/.../deviceX:eventY/accel_x_mag_rising_en -What: /sys/.../deviceX:eventY/accel_x_mag_falling_en -What: /sys/.../deviceX:eventY/accel_y_mag_en -What: /sys/.../deviceX:eventY/accel_y_mag_rising_en -What: /sys/.../deviceX:eventY/accel_y_mag_falling_en -What: /sys/.../deviceX:eventY/accel_z_mag_en -What: /sys/.../deviceX:eventY/accel_z_mag_rising_en -What: /sys/.../deviceX:eventY/accel_z_mag_falling_en -What: /sys/.../deviceX:eventY/accel_x&y&z_mag_rising_en -What: /sys/.../deviceX:eventY/accel_x&y&z_mag_falling_en +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 accel_x_thresh[_rising|_falling]_en, but here the + 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/.../accel_raw_mag_value -What: /sys/.../accel_x_raw_mag_rising_value -What: /sys/.../accel_y_raw_mag_rising_value -What: /sys/.../accel_z_raw_mag_rising_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: @@ -577,86 +585,75 @@ Description: number or direction is not specified, applies to all channels of this type. -What: /sys/bus/iio/devices/deviceX:buffer:event/dev -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - Buffer for device X event character device major:minor numbers. - -What: /sys/bus/iio/devices/deviceX:buffer:access/dev -KernelVersion: 2.6.35 -Contact: linux-iio@vger.kernel.org -Description: - Buffer for device X access character device major:minor numbers. - -What: /sys/bus/iio/devices/deviceX:buffer/trigger +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/deviceX:buffer/length +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/deviceX:buffer/bytes_per_datum +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/deviceX:buffer/enable +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/deviceX:buffer/scan_elements +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/bus/iio/devices/deviceX:buffer/scan_elements/accel_x_en -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/accel_y_en -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/accel_z_en -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/gyro_x_en -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/gyro_y_en -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/gyro_z_en -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/magn_x_en -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/magn_y_en -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/magn_z_en -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/timestamp_en -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/inY_supply_en -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/inY_en -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/inY-inZ_en -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/incli_x_en -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/incli_y_en +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/bus/iio/devices/deviceX:buffer/scan_elements/accel_type -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/gyro_type -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/magn_type -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/incli_type -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/inY_type -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/in-in_type -What: /sys/.../deviceX:buffer/scan_elements/inY_supply_type -What: /sys/.../deviceX:buffer/scan_elements/timestamp_type +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 [s|u]bits/storagebits[>>shift]. s or u specifies if + 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 @@ -673,27 +670,27 @@ Description: For other storage combinations this attribute will be extended appropriately. -What: /sys/.../deviceX:buffer/scan_elements/accel_type_available +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/bus/iio/devices/deviceX:buffer/scan_elements/inY_index -What: /sys/.../deviceX:buffer/scan_elements/inY_supply_index -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/accel_x_index -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/accel_y_index -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/accel_z_index -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/gyro_x_index -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/gyro_y_index -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/gyro_z_index -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/magn_x_index -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/magn_y_index -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/magn_z_index -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/incli_x_index -What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/incli_y_index -What: /sys/.../deviceX:buffer/scan_elements/timestamp_index +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: @@ -705,9 +702,30 @@ Description: and the relevant _type attributes to establish the data storage format. -What: /sys/bus/iio/devices/deviceX/gyro_z_quadrature_correction_raw +What: /sys/.../iio:deviceX/in_anglvel_z_quadrature_correction_raw KernelVersion: 2.6.38 -Contact: linux-iio@xxxxxxxxxxxxxxx +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-adc-ad7280a b/drivers/staging/iio/Documentation/sysfs-bus-iio-adc-ad7280a new file mode 100644 index 0000000..863d385 --- /dev/null +++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-adc-ad7280a @@ -0,0 +1,21 @@ +What: /sys/bus/iio/devices/deviceX/inY-inZ_balance_switch_en +KernelVersion: 3.0.0 +Contact: linux-iio@vger.kernel.org +Description: + Writing 1 enables the cell balance output switch corresponding + to input Y. Writing 0 disables it. If the inY-inZ_balance_timer + is set to a none zero value, the corresponding switch will + enable for the programmed amount of time, before it + automatically disables. + +What: /sys/bus/iio/devices/deviceX/inY-inZ_balance_timer +KernelVersion: 3.0.0 +Contact: linux-iio@vger.kernel.org +Description: + The inY-inZ_balance_timer file allows the user to program + individual times for each cell balance output. The AD7280A + allows the user to set the timer to a value from 0 minutes to + 36.9 minutes. The resolution of the timer is 71.5 sec. + The value written is the on-time in milliseconds. When the + timer value is set 0, the timer is disabled. The cell balance + outputs are controlled only by inY-inZ_balance_switch_en. diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-impedance-analyzer-ad5933 b/drivers/staging/iio/Documentation/sysfs-bus-iio-impedance-analyzer-ad5933 new file mode 100644 index 0000000..79c7e88 --- /dev/null +++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-impedance-analyzer-ad5933 @@ -0,0 +1,30 @@ +What: /sys/bus/iio/devices/iio:deviceX/outY_freq_start +KernelVersion: 3.1.0 +Contact: linux-iio@vger.kernel.org +Description: + Frequency sweep start frequency in Hz. + +What: /sys/bus/iio/devices/iio:deviceX/outY_freq_increment +KernelVersion: 3.1.0 +Contact: linux-iio@vger.kernel.org +Description: + Frequency increment in Hz (step size) between consecutive + frequency points along the sweep. + +What: /sys/bus/iio/devices/iio:deviceX/outY_freq_points +KernelVersion: 3.1.0 +Contact: linux-iio@vger.kernel.org +Description: + Number of frequency points (steps) in the frequency sweep. + This value, in conjunction with the outY_freq_start and the + outY_freq_increment, determines the frequency sweep range + for the sweep operation. + +What: /sys/bus/iio/devices/iio:deviceX/outY_settling_cycles +KernelVersion: 3.1.0 +Contact: linux-iio@vger.kernel.org +Description: + Number of output excitation cycles (settling time cycles) + that are allowed to pass through the unknown impedance, + after each frequency increment, and before the ADC is triggered + to perform a conversion sequence of the response signal. diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig index d329635..4ec9118 100644 --- a/drivers/staging/iio/Kconfig +++ b/drivers/staging/iio/Kconfig @@ -12,13 +12,13 @@ menuconfig IIO drivers/staging/iio/Documentation for more information. if IIO -config IIO_RING_BUFFER +config IIO_BUFFER bool "Enable buffer support within IIO" help Provide core support for various buffer based data acquisition methods. -if IIO_RING_BUFFER +if IIO_BUFFER config IIO_SW_RING select IIO_TRIGGER @@ -38,7 +38,7 @@ config IIO_KFIFO_BUF no buffer events so it is up to userspace to work out how often to read from the buffer. -endif # IIO_RINGBUFFER +endif # IIO_BUFFER config IIO_TRIGGER boolean "Enable triggered sampling support" @@ -59,9 +59,11 @@ config IIO_CONSUMERS_PER_TRIGGER 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/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" @@ -69,4 +71,31 @@ source "drivers/staging/iio/meter/Kconfig" source "drivers/staging/iio/resolver/Kconfig" source "drivers/staging/iio/trigger/Kconfig" +config IIO_DUMMY_EVGEN + tristate + +config IIO_SIMPLE_DUMMY + tristate "An example driver with no hardware requirements" + select IIO_SIMPLE_DUMMY_EVGEN if IIO_SIMPLE_DUMMY_EVENTS + help + Driver intended mainly as documentation for how to write + a driver. May also be useful for testing userspace code + without hardward. + +if IIO_SIMPLE_DUMMY + +config IIO_SIMPLE_DUMMY_EVENTS + boolean "Event generation support" + select IIO_DUMMY_EVGEN + help + 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. + +endif # IIO_SIMPLE_DUMMY + endif # IIO diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile index bb5c95c..1340aea 100644 --- a/drivers/staging/iio/Makefile +++ b/drivers/staging/iio/Makefile @@ -4,18 +4,27 @@ obj-$(CONFIG_IIO) += industrialio.o industrialio-y := industrialio-core.o -industrialio-$(CONFIG_IIO_RING_BUFFER) += industrialio-ring.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 +iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_BUFFER) += iio_simple_dummy_buffer.o + +obj-$(CONFIG_IIO_DUMMY_EVGEN) += iio_dummy_evgen.o + obj-y += accel/ obj-y += adc/ obj-y += addac/ +obj-y += cdc/ obj-y += dac/ obj-y += dds/ obj-y += gyro/ +obj-y += impedance-analyzer/ obj-y += imu/ obj-y += light/ obj-y += magnetometer/ diff --git a/drivers/staging/iio/accel/Kconfig b/drivers/staging/iio/accel/Kconfig index 81a33b6..5ab7167 100644 --- a/drivers/staging/iio/accel/Kconfig +++ b/drivers/staging/iio/accel/Kconfig @@ -1,13 +1,13 @@ # # Accelerometer drivers # -comment "Accelerometers" +menu "Accelerometers" config ADIS16201 tristate "Analog Devices ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer" depends on SPI - select IIO_TRIGGER if IIO_RING_BUFFER - select IIO_SW_RING if IIO_RING_BUFFER + select IIO_TRIGGER if IIO_BUFFER + select IIO_SW_RING 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_RING_BUFFER - select IIO_SW_RING if IIO_RING_BUFFER + select IIO_TRIGGER if IIO_BUFFER + select IIO_SW_RING 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_RING_BUFFER - select IIO_SW_RING if IIO_RING_BUFFER + select IIO_TRIGGER if IIO_BUFFER + select IIO_SW_RING 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_RING_BUFFER - select IIO_SW_RING if IIO_RING_BUFFER + select IIO_TRIGGER if IIO_BUFFER + select IIO_SW_RING if IIO_BUFFER help Say yes here to build support for Analog Devices adis16209 dual-axis digital inclinometer and accelerometer. @@ -49,8 +49,8 @@ config ADIS16220 config ADIS16240 tristate "Analog Devices ADIS16240 Programmable Impact Sensor and Recorder" depends on SPI - select IIO_TRIGGER if IIO_RING_BUFFER - select IIO_SW_RING if IIO_RING_BUFFER + select IIO_TRIGGER if IIO_BUFFER + select IIO_SW_RING if IIO_BUFFER help Say yes here to build support for Analog Devices adis16240 programmable impact Sensor and recorder. @@ -65,8 +65,9 @@ config KXSD9 config LIS3L02DQ tristate "ST Microelectronics LIS3L02DQ Accelerometer Driver" depends on SPI - select IIO_TRIGGER if IIO_RING_BUFFER - depends on !IIO_RING_BUFFER || IIO_KFIFO_BUF || IIO_SW_RING + select IIO_TRIGGER if IIO_BUFFER + depends on !IIO_BUFFER || IIO_KFIFO_BUF || IIO_SW_RING + depends on GENERIC_GPIO help Say yes here to build SPI support for the ST microelectronics accelerometer. The driver supplies direct access via sysfs files @@ -74,7 +75,7 @@ config LIS3L02DQ choice prompt "Buffer type" - depends on LIS3L02DQ && IIO_RING_BUFFER + depends on LIS3L02DQ && IIO_BUFFER config LIS3L02DQ_BUF_KFIFO depends on IIO_KFIFO_BUF @@ -94,9 +95,11 @@ config LIS3L02DQ_BUF_RING_SW endchoice config SCA3000 - depends on IIO_RING_BUFFER + depends on IIO_BUFFER depends on SPI tristate "VTI SCA3000 series accelerometers" help Say yes here to build support for the VTI SCA3000 series of SPI accelerometers. These devices use a hardware ring buffer. + +endmenu diff --git a/drivers/staging/iio/accel/Makefile b/drivers/staging/iio/accel/Makefile index 1b2a6d3..95c6666 100644 --- a/drivers/staging/iio/accel/Makefile +++ b/drivers/staging/iio/accel/Makefile @@ -3,32 +3,32 @@ # adis16201-y := adis16201_core.o -adis16201-$(CONFIG_IIO_RING_BUFFER) += adis16201_ring.o adis16201_trigger.o +adis16201-$(CONFIG_IIO_BUFFER) += adis16201_ring.o adis16201_trigger.o obj-$(CONFIG_ADIS16201) += adis16201.o adis16203-y := adis16203_core.o -adis16203-$(CONFIG_IIO_RING_BUFFER) += adis16203_ring.o adis16203_trigger.o +adis16203-$(CONFIG_IIO_BUFFER) += adis16203_ring.o adis16203_trigger.o obj-$(CONFIG_ADIS16203) += adis16203.o adis16204-y := adis16204_core.o -adis16204-$(CONFIG_IIO_RING_BUFFER) += adis16204_ring.o adis16204_trigger.o +adis16204-$(CONFIG_IIO_BUFFER) += adis16204_ring.o adis16204_trigger.o obj-$(CONFIG_ADIS16204) += adis16204.o adis16209-y := adis16209_core.o -adis16209-$(CONFIG_IIO_RING_BUFFER) += adis16209_ring.o adis16209_trigger.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_RING_BUFFER) += adis16240_ring.o adis16240_trigger.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_RING_BUFFER) += lis3l02dq_ring.o +lis3l02dq-$(CONFIG_IIO_BUFFER) += lis3l02dq_ring.o obj-$(CONFIG_LIS3L02DQ) += lis3l02dq.o sca3000-y := sca3000_core.o sca3000_ring.o diff --git a/drivers/staging/iio/accel/accel.h b/drivers/staging/iio/accel/accel.h deleted file mode 100644 index 50651f8..0000000 --- a/drivers/staging/iio/accel/accel.h +++ /dev/null @@ -1,87 +0,0 @@ - -#include "../sysfs.h" - -/* Accelerometer types of attribute */ -#define IIO_DEV_ATTR_ACCEL_OFFSET(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(accel_offset, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_ACCEL_X_OFFSET(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(accel_x_offset, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_ACCEL_Y_OFFSET(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(accel_y_offset, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_ACCEL_Z_OFFSET(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(accel_z_offset, _mode, _show, _store, _addr) - -#define IIO_CONST_ATTR_ACCEL_SCALE(_string) \ - IIO_CONST_ATTR(accel_scale, _string) - -#define IIO_DEV_ATTR_ACCEL_SCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(accel_scale, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_ACCEL_X_SCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(accel_x_scale, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_ACCEL_Y_SCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(accel_y_scale, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_ACCEL_Z_SCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(accel_z_scale, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_ACCEL_CALIBBIAS(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(accel_calibbias, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_ACCEL_X_CALIBBIAS(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(accel_x_calibbias, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_ACCEL_Y_CALIBBIAS(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(accel_y_calibbias, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_ACCEL_Z_CALIBBIAS(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(accel_z_calibbias, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_ACCEL_CALIBSCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(accel_calibscale, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_ACCEL_X_CALIBSCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(accel_x_calibscale, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_ACCEL_Y_CALIBSCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(accel_y_calibscale, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_ACCEL_Z_CALIBSCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(accel_z_calibscale, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_ACCEL(_show, _addr) \ - IIO_DEVICE_ATTR(accel_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_ACCEL_X(_show, _addr) \ - IIO_DEVICE_ATTR(accel_x_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_ACCEL_Y(_show, _addr) \ - IIO_DEVICE_ATTR(accel_y_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_ACCEL_Z(_show, _addr) \ - IIO_DEVICE_ATTR(accel_z_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_ACCEL_XY(_show, _addr) \ - IIO_DEVICE_ATTR(accel_xy, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_ACCEL_PEAK(_show, _addr) \ - IIO_DEVICE_ATTR(accel_peak, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_ACCEL_XPEAK(_show, _addr) \ - IIO_DEVICE_ATTR(accel_xpeak, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_ACCEL_YPEAK(_show, _addr) \ - IIO_DEVICE_ATTR(accel_ypeak, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_ACCEL_ZPEAK(_show, _addr) \ - IIO_DEVICE_ATTR(accel_zpeak, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_ACCEL_XYPEAK(_show, _addr) \ - IIO_DEVICE_ATTR(accel_xypeak, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_ACCEL_XYZPEAK(_show, _addr) \ - IIO_DEVICE_ATTR(accel_xyzpeak, S_IRUGO, _show, NULL, _addr) diff --git a/drivers/staging/iio/accel/adis16201.h b/drivers/staging/iio/accel/adis16201.h index dac5540..72750f7 100644 --- a/drivers/staging/iio/accel/adis16201.h +++ b/drivers/staging/iio/accel/adis16201.h @@ -89,7 +89,7 @@ enum adis16201_scan { ADIS16201_SCAN_INCLI_Y, }; -#ifdef CONFIG_IIO_RING_BUFFER +#ifdef CONFIG_IIO_BUFFER void adis16201_remove_trigger(struct iio_dev *indio_dev); int adis16201_probe_trigger(struct iio_dev *indio_dev); @@ -100,7 +100,7 @@ ssize_t adis16201_read_data_from_ring(struct device *dev, int adis16201_configure_ring(struct iio_dev *indio_dev); void adis16201_unconfigure_ring(struct iio_dev *indio_dev); -#else /* CONFIG_IIO_RING_BUFFER */ +#else /* CONFIG_IIO_BUFFER */ static inline void adis16201_remove_trigger(struct iio_dev *indio_dev) { @@ -137,5 +137,5 @@ static inline void adis16201_uninitialize_ring(struct iio_ring_buffer *ring) { } -#endif /* CONFIG_IIO_RING_BUFFER */ +#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 2fd01ae..1c5dad5 100644 --- a/drivers/staging/iio/accel/adis16201_core.c +++ b/drivers/staging/iio/accel/adis16201_core.c @@ -13,14 +13,11 @@ #include <linux/spi/spi.h> #include <linux/slab.h> #include <linux/sysfs.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" - -#include "accel.h" -#include "inclinometer.h" -#include "../adc/adc.h" +#include "../buffer_generic.h" #include "adis16201.h" @@ -328,7 +325,7 @@ static int adis16201_read_raw(struct iio_dev *indio_dev, case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): case (1 << IIO_CHAN_INFO_SCALE_SHARED): switch (chan->type) { - case IIO_IN: + case IIO_VOLTAGE: *val = 0; if (chan->channel == 0) *val2 = 1220; @@ -410,7 +407,7 @@ static int adis16201_write_raw(struct iio_dev *indio_dev, } static struct iio_chan_spec adis16201_channels[] = { - IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0, (1 << IIO_CHAN_INFO_SCALE_SEPARATE), in_supply, ADIS16201_SCAN_SUPPLY, IIO_ST('u', 12, 16, 0), 0), @@ -429,7 +426,7 @@ static struct iio_chan_spec adis16201_channels[] = { (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), accel_y, ADIS16201_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, (1 << IIO_CHAN_INFO_SCALE_SEPARATE), in_aux, ADIS16201_SCAN_AUX_ADC, IIO_ST('u', 12, 16, 0), 0), @@ -466,7 +463,7 @@ static const struct iio_info adis16201_info = { static int __devinit adis16201_probe(struct spi_device *spi) { - int ret, regdone = 0; + int ret; struct adis16201_state *st; struct iio_dev *indio_dev; @@ -495,14 +492,9 @@ static int __devinit adis16201_probe(struct spi_device *spi) if (ret) goto error_free_dev; - ret = iio_device_register(indio_dev); - if (ret) - goto error_unreg_ring_funcs; - regdone = 1; - - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - adis16201_channels, - ARRAY_SIZE(adis16201_channels)); + 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; @@ -518,19 +510,20 @@ static int __devinit adis16201_probe(struct spi_device *spi) ret = adis16201_initial_setup(indio_dev); if (ret) goto error_remove_trigger; + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto error_remove_trigger; return 0; error_remove_trigger: adis16201_remove_trigger(indio_dev); error_uninitialize_ring: - iio_ring_buffer_unregister(indio_dev->ring); + iio_buffer_unregister(indio_dev); error_unreg_ring_funcs: adis16201_unconfigure_ring(indio_dev); error_free_dev: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ret; } @@ -539,10 +532,11 @@ static int adis16201_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); - adis16201_remove_trigger(indio_dev); - iio_ring_buffer_unregister(indio_dev->ring); 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); return 0; } diff --git a/drivers/staging/iio/accel/adis16201_ring.c b/drivers/staging/iio/accel/adis16201_ring.c index 66e708d..dbd8832 100644 --- a/drivers/staging/iio/accel/adis16201_ring.c +++ b/drivers/staging/iio/accel/adis16201_ring.c @@ -1,17 +1,12 @@ #include <linux/interrupt.h> -#include <linux/irq.h> #include <linux/mutex.h> -#include <linux/device.h> #include <linux/kernel.h> #include <linux/spi/spi.h> #include <linux/slab.h> -#include <linux/sysfs.h> #include "../iio.h" -#include "../sysfs.h" #include "../ring_sw.h" -#include "accel.h" -#include "../trigger.h" +#include "../trigger_consumer.h" #include "adis16201.h" @@ -38,10 +33,12 @@ static int adis16201_read_ring_data(struct iio_dev *indio_dev, u8 *rx) xfers[i].cs_change = 1; xfers[i].len = 2; xfers[i].delay_usecs = 20; - xfers[i].tx_buf = st->tx + 2 * i; - st->tx[2 * i] = ADIS16201_READ_REG(ADIS16201_SUPPLY_OUT + - 2 * i); - st->tx[2 * i + 1] = 0; + if (i < ADIS16201_OUTPUTS) { + xfers[i].tx_buf = st->tx + 2 * i; + st->tx[2 * i] = ADIS16201_READ_REG(ADIS16201_SUPPLY_OUT + + 2 * i); + st->tx[2 * i + 1] = 0; + } if (i >= 1) xfers[i].rx_buf = rx + 2 * (i - 1); spi_message_add_tail(&xfers[i], &msg); @@ -62,9 +59,9 @@ static int adis16201_read_ring_data(struct iio_dev *indio_dev, u8 *rx) static irqreturn_t adis16201_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->private_data; + struct iio_dev *indio_dev = pf->indio_dev; struct adis16201_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; int i = 0; s16 *data; @@ -97,26 +94,26 @@ static irqreturn_t adis16201_trigger_handler(int irq, void *p) void adis16201_unconfigure_ring(struct iio_dev *indio_dev) { iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); } -static const struct iio_ring_setup_ops adis16201_ring_setup_ops = { - .preenable = &iio_sw_ring_preenable, - .postenable = &iio_triggered_ring_postenable, - .predisable = &iio_triggered_ring_predisable, +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_ring_buffer *ring; + struct iio_buffer *ring; ring = iio_sw_rb_allocate(indio_dev); if (!ring) { ret = -ENOMEM; return ret; } - indio_dev->ring = ring; + indio_dev->buffer = ring; /* Effectively select the ring buffer implementation */ ring->bpe = 2; ring->scan_timestamp = true; @@ -124,15 +121,6 @@ int adis16201_configure_ring(struct iio_dev *indio_dev) ring->setup_ops = &adis16201_ring_setup_ops; ring->owner = THIS_MODULE; - /* Set default scan mode */ - iio_scan_mask_set(ring, ADIS16201_SCAN_SUPPLY); - iio_scan_mask_set(ring, ADIS16201_SCAN_ACC_X); - iio_scan_mask_set(ring, ADIS16201_SCAN_ACC_Y); - iio_scan_mask_set(ring, ADIS16201_SCAN_AUX_ADC); - iio_scan_mask_set(ring, ADIS16201_SCAN_TEMP); - iio_scan_mask_set(ring, ADIS16201_SCAN_INCLI_X); - iio_scan_mask_set(ring, ADIS16201_SCAN_INCLI_Y); - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &adis16201_trigger_handler, IRQF_ONESHOT, @@ -144,9 +132,9 @@ int adis16201_configure_ring(struct iio_dev *indio_dev) goto error_iio_sw_rb_free; } - indio_dev->modes |= INDIO_RING_TRIGGERED; + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; return 0; error_iio_sw_rb_free: - iio_sw_rb_free(indio_dev->ring); + 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 index 3a95c08..f448258 100644 --- a/drivers/staging/iio/accel/adis16201_trigger.c +++ b/drivers/staging/iio/accel/adis16201_trigger.c @@ -1,13 +1,8 @@ #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/mutex.h> -#include <linux/device.h> #include <linux/kernel.h> -#include <linux/sysfs.h> #include <linux/spi/spi.h> #include "../iio.h" -#include "../sysfs.h" #include "../trigger.h" #include "adis16201.h" @@ -23,6 +18,11 @@ static int adis16201_data_rdy_trigger_set_state(struct iio_trigger *trig, return adis16201_set_irq(indio_dev, state); } +static const struct iio_trigger_ops adis16201_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = &adis16201_data_rdy_trigger_set_state, +}; + int adis16201_probe_trigger(struct iio_dev *indio_dev) { int ret; @@ -41,9 +41,8 @@ int adis16201_probe_trigger(struct iio_dev *indio_dev) if (ret) goto error_free_trig; st->trig->dev.parent = &st->us->dev; - st->trig->owner = THIS_MODULE; + st->trig->ops = &adis16201_trigger_ops; st->trig->private_data = indio_dev; - st->trig->set_trigger_state = &adis16201_data_rdy_trigger_set_state; ret = iio_trigger_register(st->trig); /* select default trigger */ diff --git a/drivers/staging/iio/accel/adis16203.h b/drivers/staging/iio/accel/adis16203.h index 4071bc0..3f96ad3 100644 --- a/drivers/staging/iio/accel/adis16203.h +++ b/drivers/staging/iio/accel/adis16203.h @@ -82,7 +82,7 @@ enum adis16203_scan { ADIS16203_SCAN_INCLI_Y, }; -#ifdef CONFIG_IIO_RING_BUFFER +#ifdef CONFIG_IIO_BUFFER void adis16203_remove_trigger(struct iio_dev *indio_dev); int adis16203_probe_trigger(struct iio_dev *indio_dev); @@ -93,7 +93,7 @@ ssize_t adis16203_read_data_from_ring(struct device *dev, int adis16203_configure_ring(struct iio_dev *indio_dev); void adis16203_unconfigure_ring(struct iio_dev *indio_dev); -#else /* CONFIG_IIO_RING_BUFFER */ +#else /* CONFIG_IIO_BUFFER */ static inline void adis16203_remove_trigger(struct iio_dev *indio_dev) { @@ -121,5 +121,5 @@ static inline void adis16203_unconfigure_ring(struct iio_dev *indio_dev) { } -#endif /* CONFIG_IIO_RING_BUFFER */ +#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 cf5d15d..8a33374 100644 --- a/drivers/staging/iio/accel/adis16203_core.c +++ b/drivers/staging/iio/accel/adis16203_core.c @@ -13,13 +13,11 @@ #include <linux/spi/spi.h> #include <linux/slab.h> #include <linux/sysfs.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "accel.h" -#include "inclinometer.h" -#include "../ring_generic.h" -#include "../adc/adc.h" +#include "../buffer_generic.h" #include "adis16203.h" @@ -334,7 +332,7 @@ static int adis16203_read_raw(struct iio_dev *indio_dev, case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): case (1 << IIO_CHAN_INFO_SCALE_SHARED): switch (chan->type) { - case IIO_IN: + case IIO_VOLTAGE: *val = 0; if (chan->channel == 0) *val2 = 1220; @@ -375,11 +373,11 @@ static int adis16203_read_raw(struct iio_dev *indio_dev, } static struct iio_chan_spec adis16203_channels[] = { - IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0, (1 << IIO_CHAN_INFO_SCALE_SEPARATE), in_supply, ADIS16203_SCAN_SUPPLY, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, (1 << IIO_CHAN_INFO_SCALE_SEPARATE), in_aux, ADIS16203_SCAN_AUX_ADC, IIO_ST('u', 12, 16, 0), 0), @@ -421,7 +419,7 @@ static const struct iio_info adis16203_info = { static int __devinit adis16203_probe(struct spi_device *spi) { - int ret, regdone = 0; + int ret; struct iio_dev *indio_dev; struct adis16203_state *st; @@ -448,14 +446,9 @@ static int __devinit adis16203_probe(struct spi_device *spi) if (ret) goto error_free_dev; - ret = iio_device_register(indio_dev); - if (ret) - goto error_unreg_ring_funcs; - regdone = 1; - - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - adis16203_channels, - ARRAY_SIZE(adis16203_channels)); + 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; @@ -471,19 +464,21 @@ static int __devinit adis16203_probe(struct spi_device *spi) ret = adis16203_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: adis16203_remove_trigger(indio_dev); error_uninitialize_ring: - iio_ring_buffer_unregister(indio_dev->ring); + iio_buffer_unregister(indio_dev); error_unreg_ring_funcs: adis16203_unconfigure_ring(indio_dev); error_free_dev: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ret; } @@ -492,10 +487,11 @@ static int adis16203_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); - adis16203_remove_trigger(indio_dev); - iio_ring_buffer_unregister(indio_dev->ring); 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); return 0; } diff --git a/drivers/staging/iio/accel/adis16203_ring.c b/drivers/staging/iio/accel/adis16203_ring.c index d2c07c5..838d301 100644 --- a/drivers/staging/iio/accel/adis16203_ring.c +++ b/drivers/staging/iio/accel/adis16203_ring.c @@ -1,20 +1,12 @@ #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/workqueue.h> #include <linux/mutex.h> -#include <linux/device.h> #include <linux/kernel.h> #include <linux/spi/spi.h> #include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/list.h> #include "../iio.h" -#include "../sysfs.h" #include "../ring_sw.h" -#include "accel.h" -#include "../trigger.h" +#include "../trigger_consumer.h" #include "adis16203.h" /** @@ -67,9 +59,9 @@ static int adis16203_read_ring_data(struct device *dev, u8 *rx) static irqreturn_t adis16203_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->private_data; + struct iio_dev *indio_dev = pf->indio_dev; struct adis16203_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; int i = 0; s16 *data; @@ -104,26 +96,26 @@ static irqreturn_t adis16203_trigger_handler(int irq, void *p) void adis16203_unconfigure_ring(struct iio_dev *indio_dev) { iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); } -static const struct iio_ring_setup_ops adis16203_ring_setup_ops = { - .preenable = &iio_sw_ring_preenable, - .postenable = &iio_triggered_ring_postenable, - .predisable = &iio_triggered_ring_predisable, +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_ring_buffer *ring; + struct iio_buffer *ring; ring = iio_sw_rb_allocate(indio_dev); if (!ring) { ret = -ENOMEM; return ret; } - indio_dev->ring = ring; + indio_dev->buffer = ring; /* Effectively select the ring buffer implementation */ ring->bpe = 2; ring->scan_timestamp = true; @@ -131,13 +123,6 @@ int adis16203_configure_ring(struct iio_dev *indio_dev) ring->setup_ops = &adis16203_ring_setup_ops; ring->owner = THIS_MODULE; - /* Set default scan mode */ - iio_scan_mask_set(ring, ADIS16203_SCAN_SUPPLY); - iio_scan_mask_set(ring, ADIS16203_SCAN_TEMP); - iio_scan_mask_set(ring, ADIS16203_SCAN_AUX_ADC); - iio_scan_mask_set(ring, ADIS16203_SCAN_INCLI_X); - iio_scan_mask_set(ring, ADIS16203_SCAN_INCLI_Y); - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &adis16203_trigger_handler, IRQF_ONESHOT, @@ -149,10 +134,10 @@ int adis16203_configure_ring(struct iio_dev *indio_dev) goto error_iio_sw_rb_free; } - indio_dev->modes |= INDIO_RING_TRIGGERED; + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; return 0; error_iio_sw_rb_free: - iio_sw_rb_free(indio_dev->ring); + 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 index 3caf3e8..50165f9 100644 --- a/drivers/staging/iio/accel/adis16203_trigger.c +++ b/drivers/staging/iio/accel/adis16203_trigger.c @@ -1,14 +1,8 @@ #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/mutex.h> -#include <linux/device.h> #include <linux/kernel.h> -#include <linux/sysfs.h> -#include <linux/list.h> #include <linux/spi/spi.h> #include "../iio.h" -#include "../sysfs.h" #include "../trigger.h" #include "adis16203.h" @@ -24,6 +18,11 @@ static int adis16203_data_rdy_trigger_set_state(struct iio_trigger *trig, return adis16203_set_irq(indio_dev, state); } +static const struct iio_trigger_ops adis16203_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = &adis16203_data_rdy_trigger_set_state, +}; + int adis16203_probe_trigger(struct iio_dev *indio_dev) { int ret; @@ -44,9 +43,8 @@ int adis16203_probe_trigger(struct iio_dev *indio_dev) goto error_free_trig; st->trig->dev.parent = &st->us->dev; - st->trig->owner = THIS_MODULE; + st->trig->ops = &adis16203_trigger_ops; st->trig->private_data = indio_dev; - st->trig->set_trigger_state = &adis16203_data_rdy_trigger_set_state; ret = iio_trigger_register(st->trig); /* select default trigger */ diff --git a/drivers/staging/iio/accel/adis16204.h b/drivers/staging/iio/accel/adis16204.h index 3bb0490..7cf4e91 100644 --- a/drivers/staging/iio/accel/adis16204.h +++ b/drivers/staging/iio/accel/adis16204.h @@ -90,7 +90,7 @@ enum adis16204_scan { ADIS16204_SCAN_TEMP, }; -#ifdef CONFIG_IIO_RING_BUFFER +#ifdef CONFIG_IIO_BUFFER void adis16204_remove_trigger(struct iio_dev *indio_dev); int adis16204_probe_trigger(struct iio_dev *indio_dev); @@ -101,7 +101,7 @@ ssize_t adis16204_read_data_from_ring(struct device *dev, int adis16204_configure_ring(struct iio_dev *indio_dev); void adis16204_unconfigure_ring(struct iio_dev *indio_dev); -#else /* CONFIG_IIO_RING_BUFFER */ +#else /* CONFIG_IIO_BUFFER */ static inline void adis16204_remove_trigger(struct iio_dev *indio_dev) { @@ -129,5 +129,5 @@ static inline void adis16204_unconfigure_ring(struct iio_dev *indio_dev) { } -#endif /* CONFIG_IIO_RING_BUFFER */ +#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 3e2b626..644ac8e 100644 --- a/drivers/staging/iio/accel/adis16204_core.c +++ b/drivers/staging/iio/accel/adis16204_core.c @@ -8,7 +8,6 @@ #include <linux/interrupt.h> #include <linux/irq.h> -#include <linux/gpio.h> #include <linux/delay.h> #include <linux/mutex.h> #include <linux/device.h> @@ -17,12 +16,11 @@ #include <linux/slab.h> #include <linux/sysfs.h> #include <linux/list.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" -#include "accel.h" -#include "../adc/adc.h" +#include "../buffer_generic.h" #include "adis16204.h" @@ -299,15 +297,18 @@ static int adis16204_initial_setup(struct iio_dev *indio_dev) err_ret: return ret; } + +/* Unique to this driver currently */ +#define IIO_DEV_ATTR_ACCEL_XY(_show, _addr) \ + IIO_DEVICE_ATTR(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_XPEAK(adis16204_read_14bit_signed, - ADIS16204_X_PEAK_OUT); -static IIO_DEV_ATTR_ACCEL_YPEAK(adis16204_read_14bit_signed, - ADIS16204_Y_PEAK_OUT); static IIO_DEV_ATTR_ACCEL_XYPEAK(adis16204_read_14bit_signed, ADIS16204_XY_PEAK_OUT); -static IIO_CONST_ATTR(accel_xy_scale, "0.017125"); +static IIO_CONST_ATTR(in_accel_xy_scale, "0.017125"); static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16204_write_reset, 0); @@ -319,13 +320,16 @@ enum adis16204_channel { accel_y, }; -static u8 adis16204_addresses[5][2] = { +static u8 adis16204_addresses[5][3] = { [in_supply] = { ADIS16204_SUPPLY_OUT }, [in_aux] = { ADIS16204_AUX_ADC }, [temp] = { ADIS16204_TEMP_OUT }, - [accel_x] = { ADIS16204_XACCL_OUT, ADIS16204_XACCL_NULL }, - [accel_y] = { ADIS16204_XACCL_OUT, ADIS16204_YACCL_NULL }, + [accel_x] = { ADIS16204_XACCL_OUT, ADIS16204_XACCL_NULL, + ADIS16204_X_PEAK_OUT }, + [accel_y] = { ADIS16204_XACCL_OUT, ADIS16204_YACCL_NULL, + ADIS16204_Y_PEAK_OUT }, }; + static int adis16204_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, @@ -335,6 +339,7 @@ static int adis16204_read_raw(struct iio_dev *indio_dev, int bits; u8 addr; s16 val16; + int addrind; switch (mask) { case 0: @@ -363,7 +368,7 @@ static int adis16204_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): switch (chan->type) { - case IIO_IN: + case IIO_VOLTAGE: *val = 0; if (chan->channel == 0) *val2 = 1220; @@ -389,15 +394,16 @@ static int adis16204_read_raw(struct iio_dev *indio_dev, *val = 25; return IIO_VAL_INT; case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): - switch (chan->type) { - case IIO_ACCEL: + case (1 << IIO_CHAN_INFO_PEAK_SEPARATE): + if (mask == (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE)) { bits = 12; - break; - default: - return -EINVAL; - }; + addrind = 1; + } else { /* PEAK_SEPARATE */ + bits = 14; + addrind = 2; + } mutex_lock(&indio_dev->mlock); - addr = adis16204_addresses[chan->address][1]; + addr = adis16204_addresses[chan->address][addrind]; ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16); if (ret) { mutex_unlock(&indio_dev->mlock); @@ -438,11 +444,11 @@ static int adis16204_write_raw(struct iio_dev *indio_dev, } static struct iio_chan_spec adis16204_channels[] = { - IIO_CHAN(IIO_IN, 0, 0, 0, "supply", 0, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 0, 0, "supply", 0, 0, (1 << IIO_CHAN_INFO_SCALE_SEPARATE), in_supply, ADIS16204_SCAN_SUPPLY, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, (1 << IIO_CHAN_INFO_SCALE_SEPARATE), in_aux, ADIS16204_SCAN_AUX_ADC, IIO_ST('u', 12, 16, 0), 0), @@ -453,23 +459,24 @@ static struct iio_chan_spec adis16204_channels[] = { IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, (1 << IIO_CHAN_INFO_SCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), + (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_PEAK_SEPARATE), accel_x, ADIS16204_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0), IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, (1 << IIO_CHAN_INFO_SCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), + (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_PEAK_SEPARATE), accel_y, ADIS16204_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0), IIO_CHAN_SOFT_TIMESTAMP(5), }; + static struct attribute *adis16204_attributes[] = { &iio_dev_attr_reset.dev_attr.attr, - &iio_dev_attr_accel_xy.dev_attr.attr, - &iio_dev_attr_accel_xpeak.dev_attr.attr, - &iio_dev_attr_accel_ypeak.dev_attr.attr, - &iio_dev_attr_accel_xypeak.dev_attr.attr, - &iio_const_attr_accel_xy_scale.dev_attr.attr, + &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 }; @@ -486,7 +493,7 @@ static const struct iio_info adis16204_info = { static int __devinit adis16204_probe(struct spi_device *spi) { - int ret, regdone = 0; + int ret; struct adis16204_state *st; struct iio_dev *indio_dev; @@ -513,14 +520,9 @@ static int __devinit adis16204_probe(struct spi_device *spi) if (ret) goto error_free_dev; - ret = iio_device_register(indio_dev); - if (ret) - goto error_unreg_ring_funcs; - regdone = 1; - - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - adis16204_channels, - ARRAY_SIZE(adis16204_channels)); + 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; @@ -536,19 +538,20 @@ static int __devinit adis16204_probe(struct spi_device *spi) ret = adis16204_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: adis16204_remove_trigger(indio_dev); error_uninitialize_ring: - iio_ring_buffer_unregister(indio_dev->ring); + iio_buffer_unregister(indio_dev); error_unreg_ring_funcs: adis16204_unconfigure_ring(indio_dev); error_free_dev: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ret; } @@ -557,10 +560,11 @@ static int adis16204_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); - adis16204_remove_trigger(indio_dev); - iio_ring_buffer_unregister(indio_dev->ring); 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); return 0; } diff --git a/drivers/staging/iio/accel/adis16204_ring.c b/drivers/staging/iio/accel/adis16204_ring.c index 852df06..08551bb 100644 --- a/drivers/staging/iio/accel/adis16204_ring.c +++ b/drivers/staging/iio/accel/adis16204_ring.c @@ -1,20 +1,12 @@ #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/workqueue.h> #include <linux/mutex.h> -#include <linux/device.h> #include <linux/kernel.h> #include <linux/spi/spi.h> #include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/list.h> #include "../iio.h" -#include "../sysfs.h" #include "../ring_sw.h" -#include "accel.h" -#include "../trigger.h" +#include "../trigger_consumer.h" #include "adis16204.h" /** @@ -65,9 +57,9 @@ static int adis16204_read_ring_data(struct device *dev, u8 *rx) static irqreturn_t adis16204_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->private_data; + struct iio_dev *indio_dev = pf->indio_dev; struct adis16204_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; int i = 0; s16 *data; size_t datasize = ring->access->get_bytes_per_datum(ring); @@ -99,26 +91,26 @@ static irqreturn_t adis16204_trigger_handler(int irq, void *p) void adis16204_unconfigure_ring(struct iio_dev *indio_dev) { iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); } -static const struct iio_ring_setup_ops adis16204_ring_setup_ops = { - .preenable = &iio_sw_ring_preenable, - .postenable = &iio_triggered_ring_postenable, - .predisable = &iio_triggered_ring_predisable, +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_ring_buffer *ring; + struct iio_buffer *ring; ring = iio_sw_rb_allocate(indio_dev); if (!ring) { ret = -ENOMEM; return ret; } - indio_dev->ring = ring; + indio_dev->buffer = ring; /* Effectively select the ring buffer implementation */ ring->access = &ring_sw_access_funcs; ring->bpe = 2; @@ -126,13 +118,6 @@ int adis16204_configure_ring(struct iio_dev *indio_dev) ring->setup_ops = &adis16204_ring_setup_ops; ring->owner = THIS_MODULE; - /* Set default scan mode */ - iio_scan_mask_set(ring, ADIS16204_SCAN_SUPPLY); - iio_scan_mask_set(ring, ADIS16204_SCAN_ACC_X); - iio_scan_mask_set(ring, ADIS16204_SCAN_ACC_Y); - iio_scan_mask_set(ring, ADIS16204_SCAN_AUX_ADC); - iio_scan_mask_set(ring, ADIS16204_SCAN_TEMP); - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &adis16204_trigger_handler, IRQF_ONESHOT, @@ -145,10 +130,10 @@ int adis16204_configure_ring(struct iio_dev *indio_dev) goto error_iio_sw_rb_free; } - indio_dev->modes |= INDIO_RING_TRIGGERED; + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; return 0; error_iio_sw_rb_free: - iio_sw_rb_free(indio_dev->ring); + 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 index 01f73b9..55b661c 100644 --- a/drivers/staging/iio/accel/adis16204_trigger.c +++ b/drivers/staging/iio/accel/adis16204_trigger.c @@ -1,14 +1,8 @@ #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/mutex.h> -#include <linux/device.h> #include <linux/kernel.h> -#include <linux/sysfs.h> -#include <linux/list.h> #include <linux/spi/spi.h> #include "../iio.h" -#include "../sysfs.h" #include "../trigger.h" #include "adis16204.h" @@ -24,6 +18,11 @@ static int adis16204_data_rdy_trigger_set_state(struct iio_trigger *trig, return adis16204_set_irq(indio_dev, state); } +static const struct iio_trigger_ops adis16204_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = &adis16204_data_rdy_trigger_set_state, +}; + int adis16204_probe_trigger(struct iio_dev *indio_dev) { int ret; @@ -44,9 +43,8 @@ int adis16204_probe_trigger(struct iio_dev *indio_dev) goto error_free_trig; st->trig->dev.parent = &st->us->dev; - st->trig->owner = THIS_MODULE; + st->trig->ops = &adis16204_trigger_ops; st->trig->private_data = indio_dev; - st->trig->set_trigger_state = &adis16204_data_rdy_trigger_set_state; ret = iio_trigger_register(st->trig); /* select default trigger */ diff --git a/drivers/staging/iio/accel/adis16209.h b/drivers/staging/iio/accel/adis16209.h index c8b7b00..3c88b86 100644 --- a/drivers/staging/iio/accel/adis16209.h +++ b/drivers/staging/iio/accel/adis16209.h @@ -128,7 +128,7 @@ 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_RING_BUFFER +#ifdef CONFIG_IIO_BUFFER void adis16209_remove_trigger(struct iio_dev *indio_dev); int adis16209_probe_trigger(struct iio_dev *indio_dev); @@ -140,7 +140,7 @@ ssize_t adis16209_read_data_from_ring(struct device *dev, int adis16209_configure_ring(struct iio_dev *indio_dev); void adis16209_unconfigure_ring(struct iio_dev *indio_dev); -#else /* CONFIG_IIO_RING_BUFFER */ +#else /* CONFIG_IIO_BUFFER */ static inline void adis16209_remove_trigger(struct iio_dev *indio_dev) { @@ -168,5 +168,5 @@ static inline void adis16209_unconfigure_ring(struct iio_dev *indio_dev) { } -#endif /* CONFIG_IIO_RING_BUFFER */ +#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 bec1fa8..0a8571b 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -14,13 +14,11 @@ #include <linux/slab.h> #include <linux/sysfs.h> #include <linux/list.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" -#include "accel.h" -#include "inclinometer.h" -#include "../adc/adc.h" +#include "../buffer_generic.h" #include "adis16209.h" @@ -360,7 +358,7 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): case (1 << IIO_CHAN_INFO_SCALE_SHARED): switch (chan->type) { - case IIO_IN: + case IIO_VOLTAGE: *val = 0; if (chan->channel == 0) *val2 = 305180; @@ -411,7 +409,7 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, } static struct iio_chan_spec adis16209_channels[] = { - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, (1 << IIO_CHAN_INFO_SCALE_SEPARATE), in_supply, ADIS16209_SCAN_SUPPLY, IIO_ST('u', 14, 16, 0), 0), @@ -430,15 +428,15 @@ static struct iio_chan_spec adis16209_channels[] = { (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), accel_y, ADIS16209_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, (1 << IIO_CHAN_INFO_SCALE_SEPARATE), in_aux, ADIS16209_SCAN_AUX_ADC, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_INCLI, 0, 1, 0, NULL, 0, IIO_MOD_X, + IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X, (1 << IIO_CHAN_INFO_SCALE_SHARED), incli_x, ADIS16209_SCAN_INCLI_X, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_INCLI, 0, 1, 0, NULL, 0, IIO_MOD_Y, + IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y, (1 << IIO_CHAN_INFO_SCALE_SHARED), incli_y, ADIS16209_SCAN_INCLI_Y, IIO_ST('s', 14, 16, 0), 0), @@ -469,7 +467,7 @@ static const struct iio_info adis16209_info = { static int __devinit adis16209_probe(struct spi_device *spi) { - int ret, regdone = 0; + int ret; struct adis16209_state *st; struct iio_dev *indio_dev; @@ -496,14 +494,9 @@ static int __devinit adis16209_probe(struct spi_device *spi) if (ret) goto error_free_dev; - ret = iio_device_register(indio_dev); - if (ret) - goto error_unreg_ring_funcs; - regdone = 1; - - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - adis16209_channels, - ARRAY_SIZE(adis16209_channels)); + 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; @@ -519,19 +512,20 @@ static int __devinit adis16209_probe(struct spi_device *spi) ret = adis16209_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: adis16209_remove_trigger(indio_dev); error_uninitialize_ring: - iio_ring_buffer_unregister(indio_dev->ring); + iio_buffer_unregister(indio_dev); error_unreg_ring_funcs: adis16209_unconfigure_ring(indio_dev); error_free_dev: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ret; } @@ -542,10 +536,11 @@ static int adis16209_remove(struct spi_device *spi) flush_scheduled_work(); - adis16209_remove_trigger(indio_dev); - iio_ring_buffer_unregister(indio_dev->ring); 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); return 0; } diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c index 45017d3..bb66364 100644 --- a/drivers/staging/iio/accel/adis16209_ring.c +++ b/drivers/staging/iio/accel/adis16209_ring.c @@ -1,20 +1,12 @@ #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/workqueue.h> #include <linux/mutex.h> -#include <linux/device.h> #include <linux/kernel.h> #include <linux/spi/spi.h> #include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/list.h> #include "../iio.h" -#include "../sysfs.h" #include "../ring_sw.h" -#include "accel.h" -#include "../trigger.h" +#include "../trigger_consumer.h" #include "adis16209.h" /** @@ -65,9 +57,9 @@ static int adis16209_read_ring_data(struct device *dev, u8 *rx) static irqreturn_t adis16209_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->private_data; + struct iio_dev *indio_dev = pf->indio_dev; struct adis16209_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; int i = 0; s16 *data; @@ -99,26 +91,26 @@ static irqreturn_t adis16209_trigger_handler(int irq, void *p) void adis16209_unconfigure_ring(struct iio_dev *indio_dev) { iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); } -static const struct iio_ring_setup_ops adis16209_ring_setup_ops = { - .preenable = &iio_sw_ring_preenable, - .postenable = &iio_triggered_ring_postenable, - .predisable = &iio_triggered_ring_predisable, +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_ring_buffer *ring; + struct iio_buffer *ring; ring = iio_sw_rb_allocate(indio_dev); if (!ring) { ret = -ENOMEM; return ret; } - indio_dev->ring = ring; + indio_dev->buffer = ring; /* Effectively select the ring buffer implementation */ ring->access = &ring_sw_access_funcs; ring->bpe = 2; @@ -126,16 +118,6 @@ int adis16209_configure_ring(struct iio_dev *indio_dev) ring->setup_ops = &adis16209_ring_setup_ops; ring->owner = THIS_MODULE; - /* Set default scan mode */ - iio_scan_mask_set(ring, ADIS16209_SCAN_SUPPLY); - iio_scan_mask_set(ring, ADIS16209_SCAN_ACC_X); - iio_scan_mask_set(ring, ADIS16209_SCAN_ACC_Y); - iio_scan_mask_set(ring, ADIS16209_SCAN_AUX_ADC); - iio_scan_mask_set(ring, ADIS16209_SCAN_TEMP); - iio_scan_mask_set(ring, ADIS16209_SCAN_INCLI_X); - iio_scan_mask_set(ring, ADIS16209_SCAN_INCLI_Y); - iio_scan_mask_set(ring, ADIS16209_SCAN_ROT); - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &adis16209_trigger_handler, IRQF_ONESHOT, @@ -148,10 +130,10 @@ int adis16209_configure_ring(struct iio_dev *indio_dev) goto error_iio_sw_rb_free; } - indio_dev->modes |= INDIO_RING_TRIGGERED; + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; return 0; error_iio_sw_rb_free: - iio_sw_rb_free(indio_dev->ring); + 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 index 6df7b47..8df8a97 100644 --- a/drivers/staging/iio/accel/adis16209_trigger.c +++ b/drivers/staging/iio/accel/adis16209_trigger.c @@ -1,14 +1,8 @@ #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/mutex.h> -#include <linux/device.h> #include <linux/kernel.h> -#include <linux/sysfs.h> -#include <linux/list.h> #include <linux/spi/spi.h> #include "../iio.h" -#include "../sysfs.h" #include "../trigger.h" #include "adis16209.h" @@ -33,6 +27,11 @@ static int adis16209_data_rdy_trigger_set_state(struct iio_trigger *trig, return adis16209_set_irq(indio_dev, state); } +static const struct iio_trigger_ops adis16209_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = &adis16209_data_rdy_trigger_set_state, +}; + int adis16209_probe_trigger(struct iio_dev *indio_dev) { int ret; @@ -52,9 +51,8 @@ int adis16209_probe_trigger(struct iio_dev *indio_dev) if (ret) goto error_free_trig; st->trig->dev.parent = &st->us->dev; - st->trig->owner = THIS_MODULE; + st->trig->ops = &adis16209_trigger_ops; st->trig->private_data = indio_dev; - st->trig->set_trigger_state = &adis16209_data_rdy_trigger_set_state; ret = iio_trigger_register(st->trig); /* select default trigger */ diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index bf9ba07..6d4503d 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -6,9 +6,6 @@ * Licensed under the GPL-2 or later. */ -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/gpio.h> #include <linux/delay.h> #include <linux/mutex.h> #include <linux/device.h> @@ -16,12 +13,10 @@ #include <linux/spi/spi.h> #include <linux/slab.h> #include <linux/sysfs.h> -#include <linux/list.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "accel.h" -#include "../adc/adc.h" #include "adis16220.h" @@ -29,16 +24,15 @@ /** * adis16220_spi_write_reg_8() - write single byte to a register - * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @indio_dev: iio device associated with child of actual device * @reg_address: the address of the register to be written * @val: the value to write **/ -static int adis16220_spi_write_reg_8(struct device *dev, +static int adis16220_spi_write_reg_8(struct iio_dev *indio_dev, u8 reg_address, u8 val) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adis16220_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -53,18 +47,17 @@ static int adis16220_spi_write_reg_8(struct device *dev, /** * adis16220_spi_write_reg_16() - write 2 bytes to a pair of registers - * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @indio_dev: iio device associated with child of actual device * @reg_address: the address of the lower of the two registers. Second register * is assumed to have address one greater. * @val: value to be written **/ -static int adis16220_spi_write_reg_16(struct device *dev, +static int adis16220_spi_write_reg_16(struct iio_dev *indio_dev, u8 lower_reg_address, u16 value) { int ret; struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adis16220_state *st = iio_priv(indio_dev); struct spi_transfer xfers[] = { { @@ -77,7 +70,6 @@ static int adis16220_spi_write_reg_16(struct device *dev, .tx_buf = st->tx + 2, .bits_per_word = 8, .len = 2, - .cs_change = 1, .delay_usecs = 35, }, }; @@ -99,17 +91,16 @@ static int adis16220_spi_write_reg_16(struct device *dev, /** * adis16220_spi_read_reg_16() - read 2 bytes from a 16-bit register - * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @indio_dev: iio device associated with child of actual device * @reg_address: the address of the lower of the two registers. Second register * is assumed to have address one greater. * @val: somewhere to pass back the value read **/ -static int adis16220_spi_read_reg_16(struct device *dev, - u8 lower_reg_address, - u16 *val) +static int adis16220_spi_read_reg_16(struct iio_dev *indio_dev, + u8 lower_reg_address, + u16 *val) { struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adis16220_state *st = iio_priv(indio_dev); int ret; struct spi_transfer xfers[] = { @@ -149,52 +140,23 @@ error_ret: return ret; } -static ssize_t adis16220_spi_read_signed(struct device *dev, - struct device_attribute *attr, - char *buf, - unsigned bits) -{ - int ret; - s16 val = 0; - unsigned shift = 16 - bits; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = adis16220_spi_read_reg_16(dev, this_attr->address, (u16 *)&val); - if (ret) - return ret; - - val = ((s16)(val << shift) >> shift); - return sprintf(buf, "%d\n", val); -} - -static ssize_t adis16220_read_12bit_unsigned(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u16 val = 0; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = adis16220_spi_read_reg_16(dev, this_attr->address, &val); - if (ret) - return ret; - - return sprintf(buf, "%u\n", val & 0x0FFF); -} - static ssize_t adis16220_read_16bit(struct device *dev, struct device_attribute *attr, char *buf) { + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev *indio_dev = dev_get_drvdata(dev); ssize_t ret; + s16 val = 0; /* Take the iio_dev status lock */ mutex_lock(&indio_dev->mlock); - ret = adis16220_spi_read_signed(dev, attr, buf, 16); + ret = adis16220_spi_read_reg_16(indio_dev, this_attr->address, + (u16 *)&val); mutex_unlock(&indio_dev->mlock); - - return ret; + if (ret) + return ret; + return sprintf(buf, "%d\n", val); } static ssize_t adis16220_write_16bit(struct device *dev, @@ -202,6 +164,7 @@ static ssize_t adis16220_write_16bit(struct device *dev, const char *buf, size_t len) { + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; long val; @@ -209,34 +172,34 @@ static ssize_t adis16220_write_16bit(struct device *dev, ret = strict_strtol(buf, 10, &val); if (ret) goto error_ret; - ret = adis16220_spi_write_reg_16(dev, this_attr->address, val); + ret = adis16220_spi_write_reg_16(indio_dev, this_attr->address, val); error_ret: return ret ? ret : len; } -static int adis16220_capture(struct device *dev) +static int adis16220_capture(struct iio_dev *indio_dev) { int ret; - ret = adis16220_spi_write_reg_16(dev, + ret = adis16220_spi_write_reg_16(indio_dev, ADIS16220_GLOB_CMD, 0xBF08); /* initiates a manual data capture */ if (ret) - dev_err(dev, "problem beginning capture"); + dev_err(&indio_dev->dev, "problem beginning capture"); msleep(10); /* delay for capture to finish */ return ret; } -static int adis16220_reset(struct device *dev) +static int adis16220_reset(struct iio_dev *indio_dev) { int ret; - ret = adis16220_spi_write_reg_8(dev, + ret = adis16220_spi_write_reg_8(indio_dev, ADIS16220_GLOB_CMD, ADIS16220_GLOB_CMD_SW_RESET); if (ret) - dev_err(dev, "problem resetting device"); + dev_err(&indio_dev->dev, "problem resetting device"); return ret; } @@ -245,72 +208,84 @@ static ssize_t adis16220_write_reset(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - if (len < 1) - return -1; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return adis16220_reset(dev) == 0 ? len : -EIO; - } - return -1; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + bool val; + int ret; + + ret = strtobool(buf, &val); + if (ret) + return ret; + if (!val) + return -EINVAL; + + ret = adis16220_reset(indio_dev); + if (ret) + return ret; + return len; } static ssize_t adis16220_write_capture(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - if (len < 1) - return -1; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return adis16220_capture(dev) == 0 ? len : -EIO; - } - return -1; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + bool val; + int ret; + + ret = strtobool(buf, &val); + if (ret) + return ret; + if (!val) + return -EINVAL; + ret = adis16220_capture(indio_dev); + if (ret) + return ret; + + return len; } -static int adis16220_check_status(struct device *dev) +static int adis16220_check_status(struct iio_dev *indio_dev) { u16 status; int ret; - ret = adis16220_spi_read_reg_16(dev, ADIS16220_DIAG_STAT, &status); + ret = adis16220_spi_read_reg_16(indio_dev, ADIS16220_DIAG_STAT, + &status); if (ret < 0) { - dev_err(dev, "Reading status failed\n"); + dev_err(&indio_dev->dev, "Reading status failed\n"); goto error_ret; } ret = status & 0x7F; if (status & ADIS16220_DIAG_STAT_VIOLATION) - dev_err(dev, "Capture period violation/interruption\n"); + dev_err(&indio_dev->dev, + "Capture period violation/interruption\n"); if (status & ADIS16220_DIAG_STAT_SPI_FAIL) - dev_err(dev, "SPI failure\n"); + dev_err(&indio_dev->dev, "SPI failure\n"); if (status & ADIS16220_DIAG_STAT_FLASH_UPT) - dev_err(dev, "Flash update failed\n"); + dev_err(&indio_dev->dev, "Flash update failed\n"); if (status & ADIS16220_DIAG_STAT_POWER_HIGH) - dev_err(dev, "Power supply above 3.625V\n"); + dev_err(&indio_dev->dev, "Power supply above 3.625V\n"); if (status & ADIS16220_DIAG_STAT_POWER_LOW) - dev_err(dev, "Power supply below 3.15V\n"); + dev_err(&indio_dev->dev, "Power supply below 3.15V\n"); error_ret: return ret; } -static int adis16220_self_test(struct device *dev) +static int adis16220_self_test(struct iio_dev *indio_dev) { int ret; - ret = adis16220_spi_write_reg_16(dev, + ret = adis16220_spi_write_reg_16(indio_dev, ADIS16220_MSC_CTRL, ADIS16220_MSC_CTRL_SELF_TEST_EN); if (ret) { - dev_err(dev, "problem starting self test"); + dev_err(&indio_dev->dev, "problem starting self test"); goto err_ret; } - adis16220_check_status(dev); + adis16220_check_status(indio_dev); err_ret: return ret; @@ -319,24 +294,23 @@ err_ret: static int adis16220_initial_setup(struct iio_dev *indio_dev) { int ret; - struct device *dev = &indio_dev->dev; /* Do self test */ - ret = adis16220_self_test(dev); + ret = adis16220_self_test(indio_dev); if (ret) { - dev_err(dev, "self test failure"); + dev_err(&indio_dev->dev, "self test failure"); goto err_ret; } /* Read status register to check the result */ - ret = adis16220_check_status(dev); + ret = adis16220_check_status(indio_dev); if (ret) { - adis16220_reset(dev); - dev_err(dev, "device not playing ball -> reset"); + adis16220_reset(indio_dev); + dev_err(&indio_dev->dev, "device not playing ball -> reset"); msleep(ADIS16220_STARTUP_DELAY); - ret = adis16220_check_status(dev); + ret = adis16220_check_status(indio_dev); if (ret) { - dev_err(dev, "giving up"); + dev_err(&indio_dev->dev, "giving up"); goto err_ret; } } @@ -381,7 +355,7 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev, count = ADIS16220_CAPTURE_SIZE - off; /* write the begin position of capture buffer */ - ret = adis16220_spi_write_reg_16(&indio_dev->dev, + ret = adis16220_spi_write_reg_16(indio_dev, ADIS16220_CAPT_PNTR, off > 1); if (ret) @@ -480,24 +454,6 @@ static struct bin_attribute adc2_bin = { .size = ADIS16220_CAPTURE_SIZE, }; -static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16220_read_12bit_unsigned, - ADIS16220_CAPT_SUPPLY); -static IIO_CONST_ATTR_IN_NAMED_SCALE(0, supply, "0.0012207"); -static IIO_DEV_ATTR_ACCEL(adis16220_read_16bit, ADIS16220_CAPT_BUFA); -static IIO_DEVICE_ATTR(accel_peak_raw, S_IRUGO, adis16220_read_16bit, - NULL, ADIS16220_CAPT_PEAKA); -static IIO_DEV_ATTR_ACCEL_OFFSET(S_IWUSR | S_IRUGO, - adis16220_read_16bit, - adis16220_write_16bit, - ADIS16220_ACCL_NULL); -static IIO_CONST_ATTR_ACCEL_SCALE("0.18704223545"); -static IIO_DEV_ATTR_TEMP_RAW(adis16220_read_12bit_unsigned); -static IIO_CONST_ATTR_TEMP_OFFSET("25"); -static IIO_CONST_ATTR_TEMP_SCALE("-0.47"); - -static IIO_DEV_ATTR_IN_RAW(1, adis16220_read_16bit, ADIS16220_CAPT_BUF1); -static IIO_DEV_ATTR_IN_RAW(2, adis16220_read_16bit, ADIS16220_CAPT_BUF2); - static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16220_write_reset, 0); @@ -514,21 +470,142 @@ static IIO_DEV_ATTR_CAPTURE_COUNT(S_IWUSR | S_IRUGO, adis16220_write_16bit, ADIS16220_CAPT_PNTR); -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100200"); +enum adis16220_channel { + in_supply, in_1, in_2, accel, temp +}; + +struct adis16220_address_spec { + u8 addr; + u8 bits; + bool sign; +}; + +/* Address / bits / signed */ +static const struct adis16220_address_spec adis16220_addresses[][3] = { + [in_supply] = { { ADIS16220_CAPT_SUPPLY, 12, 0 }, }, + [in_1] = { { ADIS16220_CAPT_BUF1, 16, 1 }, + { ADIS16220_AIN1_NULL, 16, 1 }, + { ADIS16220_CAPT_PEAK1, 16, 1 }, }, + [in_2] = { { ADIS16220_CAPT_BUF2, 16, 1 }, + { ADIS16220_AIN2_NULL, 16, 1 }, + { ADIS16220_CAPT_PEAK2, 16, 1 }, }, + [accel] = { { ADIS16220_CAPT_BUFA, 16, 1 }, + { ADIS16220_ACCL_NULL, 16, 1 }, + { ADIS16220_CAPT_PEAKA, 16, 1 }, }, + [temp] = { { ADIS16220_CAPT_TEMP, 12, 0 }, } +}; + +static int adis16220_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, + long mask) +{ + int ret = -EINVAL; + int addrind = 0; + u16 uval; + s16 sval; + u8 bits; + + switch (mask) { + case 0: + addrind = 0; + break; + case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + if (chan->type == IIO_TEMP) { + *val = 25; + return IIO_VAL_INT; + } + addrind = 1; + break; + case (1 << IIO_CHAN_INFO_PEAK_SEPARATE): + addrind = 2; + break; + case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + *val = 0; + switch (chan->type) { + case IIO_TEMP: + *val2 = -470000; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_ACCEL: + *val2 = 1887042; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_VOLTAGE: + if (chan->channel == 0) + *val2 = 0012221; + else /* Should really be dependent on VDD */ + *val2 = 305; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + default: + return -EINVAL; + } + if (adis16220_addresses[chan->address][addrind].sign) { + ret = adis16220_spi_read_reg_16(indio_dev, + adis16220_addresses[chan + ->address] + [addrind].addr, + &sval); + if (ret) + return ret; + bits = adis16220_addresses[chan->address][addrind].bits; + sval &= (1 << bits) - 1; + sval = (s16)(sval << (16 - bits)) >> (16 - bits); + *val = sval; + return IIO_VAL_INT; + } else { + ret = adis16220_spi_read_reg_16(indio_dev, + adis16220_addresses[chan + ->address] + [addrind].addr, + &uval); + if (ret) + return ret; + bits = adis16220_addresses[chan->address][addrind].bits; + uval &= (1 << bits) - 1; + *val = uval; + return IIO_VAL_INT; + } +} + +static const struct iio_chan_spec adis16220_channels[] = { + { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .extend_name = "supply", + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .address = in_supply, + }, { + .type = IIO_ACCEL, + .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SEPARATE) | + (1 << IIO_CHAN_INFO_PEAK_SEPARATE), + .address = accel, + }, { + .type = IIO_TEMP, + .indexed = 1, + .channel = 0, + .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .address = temp, + }, { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 1, + .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .address = in_1, + }, { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 2, + .address = in_2, + } +}; static struct attribute *adis16220_attributes[] = { - &iio_dev_attr_in0_supply_raw.dev_attr.attr, - &iio_const_attr_in0_supply_scale.dev_attr.attr, - &iio_dev_attr_accel_raw.dev_attr.attr, - &iio_dev_attr_accel_offset.dev_attr.attr, - &iio_dev_attr_accel_peak_raw.dev_attr.attr, - &iio_const_attr_accel_scale.dev_attr.attr, - &iio_dev_attr_temp_raw.dev_attr.attr, - &iio_dev_attr_in1_raw.dev_attr.attr, - &iio_dev_attr_in2_raw.dev_attr.attr, - &iio_const_attr_temp_offset.dev_attr.attr, - &iio_const_attr_temp_scale.dev_attr.attr, - &iio_const_attr_sampling_frequency_available.dev_attr.attr, &iio_dev_attr_reset.dev_attr.attr, &iio_dev_attr_capture.dev_attr.attr, &iio_dev_attr_capture_count.dev_attr.attr, @@ -542,10 +619,12 @@ static const struct attribute_group adis16220_attribute_group = { static const struct iio_info adis16220_info = { .attrs = &adis16220_attribute_group, .driver_module = THIS_MODULE, + .read_raw = &adis16220_read_raw, }; + static int __devinit adis16220_probe(struct spi_device *spi) { - int ret, regdone = 0; + int ret; struct adis16220_state *st; struct iio_dev *indio_dev; @@ -567,15 +646,16 @@ static int __devinit adis16220_probe(struct spi_device *spi) indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16220_info; indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = adis16220_channels; + indio_dev->num_channels = ARRAY_SIZE(adis16220_channels); ret = iio_device_register(indio_dev); if (ret) goto error_free_dev; - regdone = 1; ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &accel_bin); if (ret) - goto error_free_dev; + goto error_unregister_dev; ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &adc1_bin); if (ret) @@ -597,11 +677,10 @@ 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: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ret; } @@ -616,6 +695,7 @@ static int adis16220_remove(struct spi_device *spi) 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; } diff --git a/drivers/staging/iio/accel/adis16240.h b/drivers/staging/iio/accel/adis16240.h index f1dd047..3fabcc0 100644 --- a/drivers/staging/iio/accel/adis16240.h +++ b/drivers/staging/iio/accel/adis16240.h @@ -152,7 +152,7 @@ int adis16240_set_irq(struct iio_dev *indio_dev, bool enable); #define ADIS16240_SCAN_AUX_ADC 4 #define ADIS16240_SCAN_TEMP 5 -#ifdef CONFIG_IIO_RING_BUFFER +#ifdef CONFIG_IIO_BUFFER void adis16240_remove_trigger(struct iio_dev *indio_dev); int adis16240_probe_trigger(struct iio_dev *indio_dev); @@ -164,7 +164,7 @@ ssize_t adis16240_read_data_from_ring(struct device *dev, int adis16240_configure_ring(struct iio_dev *indio_dev); void adis16240_unconfigure_ring(struct iio_dev *indio_dev); -#else /* CONFIG_IIO_RING_BUFFER */ +#else /* CONFIG_IIO_BUFFER */ static inline void adis16240_remove_trigger(struct iio_dev *indio_dev) { @@ -192,5 +192,5 @@ static inline void adis16240_unconfigure_ring(struct iio_dev *indio_dev) { } -#endif /* CONFIG_IIO_RING_BUFFER */ +#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 aee8b69..b8be292 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -17,12 +17,11 @@ #include <linux/slab.h> #include <linux/sysfs.h> #include <linux/list.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" -#include "accel.h" -#include "../adc/adc.h" +#include "../buffer_generic.h" #include "adis16240.h" @@ -326,7 +325,7 @@ err_ret: return ret; } -static IIO_DEVICE_ATTR(accel_xyz_squared_peak_raw, S_IRUGO, +static IIO_DEVICE_ATTR(in_accel_xyz_squared_peak_raw, S_IRUGO, adis16240_read_12bit_signed, NULL, ADIS16240_XYZPEAK_OUT); @@ -393,7 +392,7 @@ static int adis16240_read_raw(struct iio_dev *indio_dev, case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): case (1 << IIO_CHAN_INFO_SCALE_SHARED): switch (chan->type) { - case IIO_IN: + case IIO_VOLTAGE: *val = 0; if (chan->channel == 0) *val2 = 4880; @@ -470,11 +469,11 @@ static int adis16240_write_raw(struct iio_dev *indio_dev, } static struct iio_chan_spec adis16240_channels[] = { - IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0, (1 << IIO_CHAN_INFO_SCALE_SEPARATE), in_supply, ADIS16240_SCAN_SUPPLY, IIO_ST('u', 10, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, 0, in_aux, ADIS16240_SCAN_AUX_ADC, IIO_ST('u', 10, 16, 0), 0), @@ -501,7 +500,7 @@ static struct iio_chan_spec adis16240_channels[] = { }; static struct attribute *adis16240_attributes[] = { - &iio_dev_attr_accel_xyz_squared_peak_raw.dev_attr.attr, + &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 @@ -520,7 +519,7 @@ static const struct iio_info adis16240_info = { static int __devinit adis16240_probe(struct spi_device *spi) { - int ret, regdone = 0; + int ret; struct adis16240_state *st; struct iio_dev *indio_dev; @@ -548,14 +547,9 @@ static int __devinit adis16240_probe(struct spi_device *spi) if (ret) goto error_free_dev; - ret = iio_device_register(indio_dev); - if (ret) - goto error_unreg_ring_funcs; - regdone = 1; - - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - adis16240_channels, - ARRAY_SIZE(adis16240_channels)); + 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; @@ -571,19 +565,19 @@ static int __devinit adis16240_probe(struct spi_device *spi) ret = adis16240_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: adis16240_remove_trigger(indio_dev); error_uninitialize_ring: - iio_ring_buffer_unregister(indio_dev->ring); + iio_buffer_unregister(indio_dev); error_unreg_ring_funcs: adis16240_unconfigure_ring(indio_dev); error_free_dev: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ret; } @@ -595,10 +589,11 @@ static int adis16240_remove(struct spi_device *spi) flush_scheduled_work(); - adis16240_remove_trigger(indio_dev); - iio_ring_buffer_unregister(indio_dev->ring); 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); return 0; } diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c index c812a34..34f1e7e 100644 --- a/drivers/staging/iio/accel/adis16240_ring.c +++ b/drivers/staging/iio/accel/adis16240_ring.c @@ -1,20 +1,12 @@ #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/workqueue.h> #include <linux/mutex.h> -#include <linux/device.h> #include <linux/kernel.h> #include <linux/spi/spi.h> #include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/list.h> #include "../iio.h" -#include "../sysfs.h" #include "../ring_sw.h" -#include "accel.h" -#include "../trigger.h" +#include "../trigger_consumer.h" #include "adis16240.h" /** @@ -62,9 +54,9 @@ static int adis16240_read_ring_data(struct device *dev, u8 *rx) static irqreturn_t adis16240_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->private_data; + struct iio_dev *indio_dev = pf->indio_dev; struct adis16240_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; int i = 0; s16 *data; @@ -96,26 +88,26 @@ static irqreturn_t adis16240_trigger_handler(int irq, void *p) void adis16240_unconfigure_ring(struct iio_dev *indio_dev) { iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); } -static const struct iio_ring_setup_ops adis16240_ring_setup_ops = { - .preenable = &iio_sw_ring_preenable, - .postenable = &iio_triggered_ring_postenable, - .predisable = &iio_triggered_ring_predisable, +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_ring_buffer *ring; + struct iio_buffer *ring; ring = iio_sw_rb_allocate(indio_dev); if (!ring) { ret = -ENOMEM; return ret; } - indio_dev->ring = ring; + indio_dev->buffer = ring; /* Effectively select the ring buffer implementation */ ring->access = &ring_sw_access_funcs; ring->bpe = 2; @@ -123,14 +115,6 @@ int adis16240_configure_ring(struct iio_dev *indio_dev) ring->setup_ops = &adis16240_ring_setup_ops; ring->owner = THIS_MODULE; - /* Set default scan mode */ - iio_scan_mask_set(ring, ADIS16240_SCAN_SUPPLY); - iio_scan_mask_set(ring, ADIS16240_SCAN_ACC_X); - iio_scan_mask_set(ring, ADIS16240_SCAN_ACC_Y); - iio_scan_mask_set(ring, ADIS16240_SCAN_ACC_Z); - iio_scan_mask_set(ring, ADIS16240_SCAN_AUX_ADC); - iio_scan_mask_set(ring, ADIS16240_SCAN_TEMP); - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &adis16240_trigger_handler, IRQF_ONESHOT, @@ -143,10 +127,10 @@ int adis16240_configure_ring(struct iio_dev *indio_dev) goto error_iio_sw_rb_free; } - indio_dev->modes |= INDIO_RING_TRIGGERED; + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; return 0; error_iio_sw_rb_free: - iio_sw_rb_free(indio_dev->ring); + 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 index 17135fc3..13f1d14 100644 --- a/drivers/staging/iio/accel/adis16240_trigger.c +++ b/drivers/staging/iio/accel/adis16240_trigger.c @@ -1,14 +1,8 @@ #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/mutex.h> -#include <linux/device.h> #include <linux/kernel.h> -#include <linux/sysfs.h> -#include <linux/list.h> #include <linux/spi/spi.h> #include "../iio.h" -#include "../sysfs.h" #include "../trigger.h" #include "adis16240.h" @@ -33,6 +27,11 @@ static int adis16240_data_rdy_trigger_set_state(struct iio_trigger *trig, return adis16240_set_irq(indio_dev, state); } +static const struct iio_trigger_ops adis16240_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = &adis16240_data_rdy_trigger_set_state, +}; + int adis16240_probe_trigger(struct iio_dev *indio_dev) { int ret; @@ -53,9 +52,8 @@ int adis16240_probe_trigger(struct iio_dev *indio_dev) goto error_free_trig; st->trig->dev.parent = &st->us->dev; - st->trig->owner = THIS_MODULE; + st->trig->ops = &adis16240_trigger_ops; st->trig->private_data = indio_dev; - st->trig->set_trigger_state = &adis16240_data_rdy_trigger_set_state; ret = iio_trigger_register(st->trig); /* select default trigger */ diff --git a/drivers/staging/iio/accel/inclinometer.h b/drivers/staging/iio/accel/inclinometer.h deleted file mode 100644 index faf73d7..0000000 --- a/drivers/staging/iio/accel/inclinometer.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Inclinometer related attributes - */ -#include "../sysfs.h" - -#define IIO_DEV_ATTR_INCLI_X(_show, _addr) \ - IIO_DEVICE_ATTR(incli_x_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_INCLI_Y(_show, _addr) \ - IIO_DEVICE_ATTR(incli_y_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_INCLI_Z(_show, _addr) \ - IIO_DEVICE_ATTR(incli_z_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_INCLI_X_OFFSET(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(incli_x_offset, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_INCLI_Y_OFFSET(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(incli_y_offset, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_INCLI_Z_OFFSET(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(incli_z_offset, _mode, _show, _store, _addr) - -#define IIO_CONST_ATTR_INCLI_SCALE(_string) \ - IIO_CONST_ATTR(incli_scale, _string) diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c index c8a358a..5238503 100644 --- a/drivers/staging/iio/accel/kxsd9.c +++ b/drivers/staging/iio/accel/kxsd9.c @@ -21,11 +21,10 @@ #include <linux/spi/spi.h> #include <linux/sysfs.h> #include <linux/slab.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "../adc/adc.h" -#include "accel.h" #define KXSD9_REG_X 0x00 #define KXSD9_REG_Y 0x02 @@ -34,10 +33,6 @@ #define KXSD9_REG_RESET 0x0a #define KXSD9_REG_CTRL_C 0x0c -#define KXSD9_FS_8 0x00 -#define KXSD9_FS_6 0x01 -#define KXSD9_FS_4 0x02 -#define KXSD9_FS_2 0x03 #define KXSD9_FS_MASK 0x03 #define KXSD9_REG_CTRL_B 0x0d @@ -46,13 +41,8 @@ #define KXSD9_READ(a) (0x80 | (a)) #define KXSD9_WRITE(a) (a) -#define KXSD9_SCALE_2G "0.011978" -#define KXSD9_SCALE_4G "0.023927" -#define KXSD9_SCALE_6G "0.035934" -#define KXSD9_SCALE_8G "0.047853" - #define KXSD9_STATE_RX_SIZE 2 -#define KXSD9_STATE_TX_SIZE 4 +#define KXSD9_STATE_TX_SIZE 2 /** * struct kxsd9_state - device related storage * @buf_lock: protect the rx and tx buffers. @@ -67,170 +57,70 @@ struct kxsd9_state { u8 tx[KXSD9_STATE_TX_SIZE]; }; -/* This may want to move to mili g to allow for non integer ranges */ -static ssize_t kxsd9_read_scale(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - ssize_t len = 0; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct kxsd9_state *st = iio_priv(indio_dev); - struct spi_transfer xfer = { - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .tx_buf = st->tx, - .rx_buf = st->rx, - }; - struct spi_message msg; - - mutex_lock(&st->buf_lock); - st->tx[0] = KXSD9_READ(KXSD9_REG_CTRL_C); - st->tx[1] = 0; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->us, &msg); - if (ret) - goto error_ret; - - switch (st->rx[1] & KXSD9_FS_MASK) { - case KXSD9_FS_8: - len += sprintf(buf, "%s\n", KXSD9_SCALE_8G); - break; - case KXSD9_FS_6: - len += sprintf(buf, "%s\n", KXSD9_SCALE_6G); - break; - case KXSD9_FS_4: - len += sprintf(buf, "%s\n", KXSD9_SCALE_4G); - break; - case KXSD9_FS_2: - len += sprintf(buf, "%s\n", KXSD9_SCALE_2G); - break; - } +#define KXSD9_SCALE_2G "0.011978" +#define KXSD9_SCALE_4G "0.023927" +#define KXSD9_SCALE_6G "0.035934" +#define KXSD9_SCALE_8G "0.047853" -error_ret: - mutex_unlock(&st->buf_lock); +/* reverse order */ +static const int kxsd9_micro_scales[4] = { 47853, 35934, 23927, 11978 }; - return ret ? ret : len; -} -static ssize_t kxsd9_write_scale(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) +static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro) { - - struct spi_message msg; - int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); + int ret, i; struct kxsd9_state *st = iio_priv(indio_dev); - u8 val; - struct spi_transfer xfers[] = { - { - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .tx_buf = st->tx, - .rx_buf = st->rx, - }, { - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .tx_buf = st->tx, - }, - }; - - if (!strncmp(buf, KXSD9_SCALE_8G, - strlen(buf) < strlen(KXSD9_SCALE_8G) - ? strlen(buf) : strlen(KXSD9_SCALE_8G))) - val = KXSD9_FS_8; - else if (!strncmp(buf, KXSD9_SCALE_6G, - strlen(buf) < strlen(KXSD9_SCALE_6G) - ? strlen(buf) : strlen(KXSD9_SCALE_6G))) - val = KXSD9_FS_6; - else if (!strncmp(buf, KXSD9_SCALE_4G, - strlen(buf) < strlen(KXSD9_SCALE_4G) - ? strlen(buf) : strlen(KXSD9_SCALE_4G))) - val = KXSD9_FS_4; - else if (!strncmp(buf, KXSD9_SCALE_2G, - strlen(buf) < strlen(KXSD9_SCALE_2G) - ? strlen(buf) : strlen(KXSD9_SCALE_2G))) - val = KXSD9_FS_2; - else + bool foundit = false; + + for (i = 0; i < 4; i++) + if (micro == kxsd9_micro_scales[i]) { + foundit = true; + break; + } + if (!foundit) return -EINVAL; mutex_lock(&st->buf_lock); - st->tx[0] = KXSD9_READ(KXSD9_REG_CTRL_C); - st->tx[1] = 0; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C)); if (ret) goto error_ret; st->tx[0] = KXSD9_WRITE(KXSD9_REG_CTRL_C); - st->tx[1] = (st->rx[1] & ~KXSD9_FS_MASK) | val; + st->tx[1] = (ret & ~KXSD9_FS_MASK) | i; - spi_message_init(&msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_write(st->us, st->tx, 2); error_ret: mutex_unlock(&st->buf_lock); - return ret ? ret : len; + return ret; } -static ssize_t kxsd9_read_accel(struct device *dev, - struct device_attribute *attr, - char *buf) +static int kxsd9_read(struct iio_dev *indio_dev, u8 address) { struct spi_message msg; int ret; - ssize_t len = 0; - u16 val; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct kxsd9_state *st = iio_priv(indio_dev); struct spi_transfer xfers[] = { { .bits_per_word = 8, .len = 1, - .cs_change = 0, .delay_usecs = 200, .tx_buf = st->tx, }, { .bits_per_word = 8, .len = 2, - .cs_change = 1, .rx_buf = st->rx, }, }; mutex_lock(&st->buf_lock); - st->tx[0] = KXSD9_READ(this_attr->address); + st->tx[0] = KXSD9_READ(address); spi_message_init(&msg); spi_message_add_tail(&xfers[0], &msg); spi_message_add_tail(&xfers[1], &msg); ret = spi_sync(st->us, &msg); if (ret) - goto error_ret; - val = (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0); - len = sprintf(buf, "%d\n", val); -error_ret: - mutex_unlock(&st->buf_lock); - - return ret ? ret : len; + return ret; + return (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0); } -static IIO_DEV_ATTR_ACCEL_X(kxsd9_read_accel, KXSD9_REG_X); -static IIO_DEV_ATTR_ACCEL_Y(kxsd9_read_accel, KXSD9_REG_Y); -static IIO_DEV_ATTR_ACCEL_Z(kxsd9_read_accel, KXSD9_REG_Z); -static IIO_DEV_ATTR_IN_RAW(0, kxsd9_read_accel, KXSD9_REG_AUX); - -static IIO_DEVICE_ATTR(accel_scale, - S_IRUGO | S_IWUSR, - kxsd9_read_scale, - kxsd9_write_scale, - 0); - static IIO_CONST_ATTR(accel_scale_available, KXSD9_SCALE_2G " " KXSD9_SCALE_4G " " @@ -238,48 +128,94 @@ static IIO_CONST_ATTR(accel_scale_available, KXSD9_SCALE_8G); static struct attribute *kxsd9_attributes[] = { - &iio_dev_attr_accel_x_raw.dev_attr.attr, - &iio_dev_attr_accel_y_raw.dev_attr.attr, - &iio_dev_attr_accel_z_raw.dev_attr.attr, - &iio_dev_attr_in0_raw.dev_attr.attr, - &iio_dev_attr_accel_scale.dev_attr.attr, &iio_const_attr_accel_scale_available.dev_attr.attr, NULL, }; +static int kxsd9_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + int ret = -EINVAL; + + if (mask == (1 << IIO_CHAN_INFO_SCALE_SHARED)) { + /* Check no integer component */ + if (val) + return -EINVAL; + ret = kxsd9_write_scale(indio_dev, val2); + } + + return ret; +} + +static int kxsd9_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + int ret = -EINVAL; + struct kxsd9_state *st = iio_priv(indio_dev); + + switch (mask) { + case 0: + ret = kxsd9_read(indio_dev, chan->address); + if (ret < 0) + goto error_ret; + *val = ret; + break; + case (1 << IIO_CHAN_INFO_SCALE_SHARED): + ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C)); + if (ret) + goto error_ret; + *val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK]; + ret = IIO_VAL_INT_PLUS_MICRO; + break; + }; + +error_ret: + return ret; +}; +#define KXSD9_ACCEL_CHAN(axis) \ + { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask = 1 << IIO_CHAN_INFO_SCALE_SHARED, \ + .address = KXSD9_REG_##axis, \ + } + +static struct iio_chan_spec kxsd9_channels[] = { + KXSD9_ACCEL_CHAN(X), KXSD9_ACCEL_CHAN(Y), KXSD9_ACCEL_CHAN(Z), + { + .type = IIO_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) { - struct spi_transfer xfers[2] = { - { - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .tx_buf = st->tx, - }, { - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .tx_buf = st->tx + 2, - }, - }; - struct spi_message msg; + int ret; + st->tx[0] = 0x0d; st->tx[1] = 0x40; - st->tx[2] = 0x0c; - st->tx[3] = 0x9b; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); + ret = spi_write(st->us, st->tx, 2); + if (ret) + return ret; - return spi_sync(st->us, &msg); + st->tx[0] = 0x0c; + st->tx[1] = 0x9b; + return spi_write(st->us, st->tx, 2); }; static const struct iio_info kxsd9_info = { + .read_raw = &kxsd9_read_raw, + .write_raw = &kxsd9_write_raw, .attrs = &kxsd9_attribute_group, .driver_module = THIS_MODULE, }; @@ -300,7 +236,9 @@ static int __devinit kxsd9_probe(struct spi_device *spi) st->us = spi; mutex_init(&st->buf_lock); - + indio_dev->channels = kxsd9_channels; + indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels); + indio_dev->name = spi_get_device_id(spi)->name; indio_dev->dev.parent = &spi->dev; indio_dev->info = &kxsd9_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -324,10 +262,15 @@ error_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} +}; + static struct spi_driver kxsd9_driver = { .driver = { .name = "kxsd9", @@ -335,6 +278,7 @@ static struct spi_driver kxsd9_driver = { }, .probe = kxsd9_probe, .remove = __devexit_p(kxsd9_remove), + .id_table = kxsd9_id, }; static __init int kxsd9_spi_init(void) diff --git a/drivers/staging/iio/accel/lis3l02dq.h b/drivers/staging/iio/accel/lis3l02dq.h index 18b23ac..7237a9a 100644 --- a/drivers/staging/iio/accel/lis3l02dq.h +++ b/drivers/staging/iio/accel/lis3l02dq.h @@ -174,20 +174,20 @@ int lis3l02dq_spi_write_reg_8(struct iio_dev *indio_dev, int lis3l02dq_disable_all_events(struct iio_dev *indio_dev); -#ifdef CONFIG_IIO_RING_BUFFER -/* At the moment triggers are only used for ring buffer +#ifdef CONFIG_IIO_BUFFER +/* At the moment triggers are only used for buffer * filling. This may change! */ void lis3l02dq_remove_trigger(struct iio_dev *indio_dev); int lis3l02dq_probe_trigger(struct iio_dev *indio_dev); -ssize_t lis3l02dq_read_accel_from_ring(struct iio_ring_buffer *ring, +ssize_t lis3l02dq_read_accel_from_buffer(struct iio_buffer *buffer, int index, int *val); -int lis3l02dq_configure_ring(struct iio_dev *indio_dev); -void lis3l02dq_unconfigure_ring(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 @@ -202,8 +202,8 @@ void lis3l02dq_unconfigure_ring(struct iio_dev *indio_dev); irqreturn_t lis3l02dq_data_rdy_trig_poll(int irq, void *private); #define lis3l02dq_th lis3l02dq_data_rdy_trig_poll -#else /* CONFIG_IIO_RING_BUFFER */ -#define lis3l02dq_th lis3l02dq_noring +#else /* CONFIG_IIO_BUFFER */ +#define lis3l02dq_th lis3l02dq_nobuffer static inline void lis3l02dq_remove_trigger(struct iio_dev *indio_dev) { @@ -213,19 +213,19 @@ static inline int lis3l02dq_probe_trigger(struct iio_dev *indio_dev) return 0; } static inline ssize_t -lis3l02dq_read_accel_from_ring(struct iio_ring_buffer *ring, - int index, - int *val) +lis3l02dq_read_accel_from_buffer(struct iio_buffer *buffer, + int index, + int *val) { return 0; } -static int lis3l02dq_configure_ring(struct iio_dev *indio_dev) +static int lis3l02dq_configure_buffer(struct iio_dev *indio_dev) { return 0; } -static inline void lis3l02dq_unconfigure_ring(struct iio_dev *indio_dev) +static inline void lis3l02dq_unconfigure_buffer(struct iio_dev *indio_dev) { } -#endif /* CONFIG_IIO_RING_BUFFER */ +#endif /* CONFIG_IIO_BUFFER */ #endif /* SPI_LIS3L02DQ_H_ */ diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index a29dfd2..559545a 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -21,12 +21,11 @@ #include <linux/spi/spi.h> #include <linux/slab.h> #include <linux/sysfs.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" - -#include "accel.h" +#include "../buffer_generic.h" #include "lis3l02dq.h" @@ -35,8 +34,8 @@ * This means that use cannot be made of spi_write etc. */ /* direct copy of the irq_default_primary_handler */ -#ifndef CONFIG_IIO_RING_BUFFER -static irqreturn_t lis3l02dq_noring(int irq, void *private) +#ifndef CONFIG_IIO_BUFFER +static irqreturn_t lis3l02dq_nobuffer(int irq, void *private) { return IRQ_WAKE_THREAD; } @@ -201,14 +200,14 @@ static u8 lis3l02dq_axis_map[3][3] = { }; static int lis3l02dq_read_thresh(struct iio_dev *indio_dev, - int e, + u64 e, int *val) { return lis3l02dq_read_reg_s16(indio_dev, LIS3L02DQ_REG_THS_L_ADDR, val); } static int lis3l02dq_write_thresh(struct iio_dev *indio_dev, - int event_code, + u64 event_code, int val) { u16 value = val; @@ -260,10 +259,11 @@ static int lis3l02dq_read_raw(struct iio_dev *indio_dev, case 0: /* Take the iio_dev status lock */ mutex_lock(&indio_dev->mlock); - if (indio_dev->currentmode == INDIO_RING_TRIGGERED) - ret = lis3l02dq_read_accel_from_ring(indio_dev->ring, - chan->scan_index, - val); + if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) + ret = lis3l02dq_read_accel_from_buffer(indio_dev-> + buffer, + chan->scan_index, + val); else { reg = lis3l02dq_axis_map [LIS3L02DQ_ACCEL][chan->address]; @@ -453,55 +453,55 @@ static irqreturn_t lis3l02dq_event_handler(int irq, void *private) &t); if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_HIGH) - iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, - IIO_EV_MOD_Z, + IIO_MOD_Z, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), timestamp); if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_LOW) - iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, - IIO_EV_MOD_Z, + IIO_MOD_Z, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), timestamp); if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_HIGH) - iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, - IIO_EV_MOD_Y, + IIO_MOD_Y, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), timestamp); if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_LOW) - iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, - IIO_EV_MOD_Y, + IIO_MOD_Y, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), timestamp); if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_HIGH) - iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, - IIO_EV_MOD_X, + IIO_MOD_X, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), timestamp); if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_LOW) - iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, - IIO_EV_MOD_X, + IIO_MOD_X, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), timestamp); @@ -535,7 +535,7 @@ static struct iio_chan_spec lis3l02dq_channels[] = { static ssize_t lis3l02dq_read_event_config(struct iio_dev *indio_dev, - int event_code) + u64 event_code) { u8 val; @@ -587,7 +587,7 @@ error_ret: } static int lis3l02dq_write_event_config(struct iio_dev *indio_dev, - int event_code, + u64 event_code, int state) { int ret = 0; @@ -652,7 +652,6 @@ static const struct attribute_group lis3l02dq_attribute_group = { }; static const struct iio_info lis3l02dq_info = { - .num_interrupt_lines = 1, .read_raw = &lis3l02dq_read_raw, .write_raw = &lis3l02dq_write_raw, .read_event_value = &lis3l02dq_read_thresh, @@ -665,7 +664,7 @@ static const struct iio_info lis3l02dq_info = { static int __devinit lis3l02dq_probe(struct spi_device *spi) { - int ret, regdone = 0; + int ret; struct lis3l02dq_state *st; struct iio_dev *indio_dev; @@ -688,21 +687,16 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi) indio_dev->modes = INDIO_DIRECT_MODE; - ret = lis3l02dq_configure_ring(indio_dev); + ret = lis3l02dq_configure_buffer(indio_dev); if (ret) goto error_free_dev; - ret = iio_device_register(indio_dev); - if (ret) - goto error_unreg_ring_funcs; - regdone = 1; - - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - lis3l02dq_channels, - ARRAY_SIZE(lis3l02dq_channels)); + ret = iio_buffer_register(indio_dev, + lis3l02dq_channels, + ARRAY_SIZE(lis3l02dq_channels)); if (ret) { - printk(KERN_ERR "failed to initialize the ring\n"); - goto error_unreg_ring_funcs; + printk(KERN_ERR "failed to initialize the buffer\n"); + goto error_unreg_buffer_funcs; } if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) { @@ -713,7 +707,7 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi) "lis3l02dq", indio_dev); if (ret) - goto error_uninitialize_ring; + goto error_uninitialize_buffer; ret = lis3l02dq_probe_trigger(indio_dev); if (ret) @@ -724,23 +718,25 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi) ret = lis3l02dq_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_RING_TRIGGERED) + if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) lis3l02dq_remove_trigger(indio_dev); error_free_interrupt: if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) free_irq(st->us->irq, indio_dev); -error_uninitialize_ring: - iio_ring_buffer_unregister(indio_dev->ring); -error_unreg_ring_funcs: - lis3l02dq_unconfigure_ring(indio_dev); +error_uninitialize_buffer: + iio_buffer_unregister(indio_dev); +error_unreg_buffer_funcs: + lis3l02dq_unconfigure_buffer(indio_dev); error_free_dev: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ret; } @@ -778,6 +774,8 @@ static int lis3l02dq_remove(struct spi_device *spi) 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; @@ -790,12 +788,10 @@ static int lis3l02dq_remove(struct spi_device *spi) free_irq(st->us->irq, indio_dev); lis3l02dq_remove_trigger(indio_dev); - iio_ring_buffer_unregister(indio_dev->ring); - lis3l02dq_unconfigure_ring(indio_dev); - iio_device_unregister(indio_dev); - - return 0; + iio_buffer_unregister(indio_dev); + lis3l02dq_unconfigure_buffer(indio_dev); + iio_free_device(indio_dev); err_ret: return ret; } diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index 8d5c8ac..5c542dd 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -1,19 +1,15 @@ #include <linux/interrupt.h> -#include <linux/irq.h> #include <linux/gpio.h> #include <linux/mutex.h> -#include <linux/device.h> #include <linux/kernel.h> #include <linux/spi/spi.h> -#include <linux/sysfs.h> #include <linux/slab.h> #include "../iio.h" -#include "../sysfs.h" #include "../ring_sw.h" #include "../kfifo_buf.h" -#include "accel.h" #include "../trigger.h" +#include "../trigger_consumer.h" #include "lis3l02dq.h" /** @@ -42,31 +38,32 @@ irqreturn_t lis3l02dq_data_rdy_trig_poll(int irq, void *private) } /** - * lis3l02dq_read_accel_from_ring() individual acceleration read from ring + * lis3l02dq_read_accel_from_buffer() individual acceleration read from buffer **/ -ssize_t lis3l02dq_read_accel_from_ring(struct iio_ring_buffer *ring, - int index, - int *val) +ssize_t lis3l02dq_read_accel_from_buffer(struct iio_buffer *buffer, + int index, + int *val) { int ret; s16 *data; - if (!iio_scan_mask_query(ring, index)) + if (!iio_scan_mask_query(buffer, index)) return -EINVAL; - if (!ring->access->read_last) + if (!buffer->access->read_last) return -EBUSY; - data = kmalloc(ring->access->get_bytes_per_datum(ring), + data = kmalloc(buffer->access->get_bytes_per_datum(buffer), GFP_KERNEL); if (data == NULL) return -ENOMEM; - ret = ring->access->read_last(ring, (u8 *)data); + ret = buffer->access->read_last(buffer, (u8 *)data); if (ret) goto error_free_data; - *val = data[bitmap_weight(&ring->scan_mask, index)]; + *val = data[bitmap_weight(buffer->scan_mask, index)]; error_free_data: + kfree(data); return ret; @@ -89,13 +86,13 @@ static const u8 read_all_tx_array[] = { **/ static int lis3l02dq_read_all(struct iio_dev *indio_dev, u8 *rx_array) { - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *buffer = indio_dev->buffer; struct lis3l02dq_state *st = iio_priv(indio_dev); struct spi_transfer *xfers; struct spi_message msg; int ret, i, j = 0; - xfers = kzalloc((ring->scan_count) * 2 + xfers = kzalloc((buffer->scan_count) * 2 * sizeof(*xfers), GFP_KERNEL); if (!xfers) return -ENOMEM; @@ -103,7 +100,7 @@ static int lis3l02dq_read_all(struct iio_dev *indio_dev, u8 *rx_array) mutex_lock(&st->buf_lock); for (i = 0; i < ARRAY_SIZE(read_all_tx_array)/4; i++) - if (ring->scan_mask & (1 << i)) { + if (test_bit(i, buffer->scan_mask)) { /* lower byte */ xfers[j].tx_buf = st->tx + 2*j; st->tx[2*j] = read_all_tx_array[i*4]; @@ -131,7 +128,7 @@ static int lis3l02dq_read_all(struct iio_dev *indio_dev, u8 *rx_array) * values in alternate bytes */ spi_message_init(&msg); - for (j = 0; j < ring->scan_count * 2; j++) + for (j = 0; j < buffer->scan_count * 2; j++) spi_message_add_tail(&xfers[j], &msg); ret = spi_sync(st->us, &msg); @@ -141,20 +138,20 @@ static int lis3l02dq_read_all(struct iio_dev *indio_dev, u8 *rx_array) return ret; } -static int lis3l02dq_get_ring_element(struct iio_dev *indio_dev, +static int lis3l02dq_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) { int ret, i; u8 *rx_array ; s16 *data = (s16 *)buf; - rx_array = kzalloc(4 * (indio_dev->ring->scan_count), GFP_KERNEL); + rx_array = kzalloc(4 * (indio_dev->buffer->scan_count), GFP_KERNEL); if (rx_array == NULL) return -ENOMEM; ret = lis3l02dq_read_all(indio_dev, rx_array); if (ret < 0) return ret; - for (i = 0; i < indio_dev->ring->scan_count; i++) + for (i = 0; i < indio_dev->buffer->scan_count; i++) data[i] = combine_8_to_16(rx_array[i*4+1], rx_array[i*4+3]); kfree(rx_array); @@ -165,27 +162,27 @@ static int lis3l02dq_get_ring_element(struct iio_dev *indio_dev, static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->private_data; - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_dev *indio_dev = pf->indio_dev; + struct iio_buffer *buffer = indio_dev->buffer; int len = 0; - size_t datasize = ring->access->get_bytes_per_datum(ring); + size_t datasize = buffer->access->get_bytes_per_datum(buffer); char *data = kmalloc(datasize, GFP_KERNEL); if (data == NULL) { dev_err(indio_dev->dev.parent, - "memory alloc failed in ring bh"); + "memory alloc failed in buffer bh"); return -ENOMEM; } - if (ring->scan_count) - len = lis3l02dq_get_ring_element(indio_dev, data); + if (buffer->scan_count) + len = lis3l02dq_get_buffer_element(indio_dev, data); /* Guaranteed to be aligned with 8 byte boundary */ - if (ring->scan_timestamp) + if (buffer->scan_timestamp) *(s64 *)(((phys_addr_t)data + len + sizeof(s64) - 1) & ~(sizeof(s64) - 1)) = pf->timestamp; - ring->access->store_to(ring, (u8 *)data, pf->timestamp); + buffer->access->store_to(buffer, (u8 *)data, pf->timestamp); iio_trigger_notify_done(indio_dev->trig); kfree(data); @@ -258,7 +255,7 @@ error_ret: * * If disabling the interrupt also does a final read to ensure it is clear. * This is only important in some cases where the scan enable elements are - * switched before the ring is reenabled. + * switched before the buffer is reenabled. **/ static int lis3l02dq_data_rdy_trigger_set_state(struct iio_trigger *trig, bool state) @@ -306,6 +303,12 @@ static int lis3l02dq_trig_try_reen(struct iio_trigger *trig) return 0; } +static const struct iio_trigger_ops lis3l02dq_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = &lis3l02dq_data_rdy_trigger_set_state, + .try_reenable = &lis3l02dq_trig_try_reen, +}; + int lis3l02dq_probe_trigger(struct iio_dev *indio_dev) { int ret; @@ -318,10 +321,8 @@ int lis3l02dq_probe_trigger(struct iio_dev *indio_dev) } st->trig->dev.parent = &st->us->dev; - st->trig->owner = THIS_MODULE; + st->trig->ops = &lis3l02dq_trigger_ops; st->trig->private_data = indio_dev; - st->trig->set_trigger_state = &lis3l02dq_data_rdy_trigger_set_state; - st->trig->try_reenable = &lis3l02dq_trig_try_reen; ret = iio_trigger_register(st->trig); if (ret) goto error_free_trig; @@ -342,13 +343,13 @@ void lis3l02dq_remove_trigger(struct iio_dev *indio_dev) iio_free_trigger(st->trig); } -void lis3l02dq_unconfigure_ring(struct iio_dev *indio_dev) +void lis3l02dq_unconfigure_buffer(struct iio_dev *indio_dev) { iio_dealloc_pollfunc(indio_dev->pollfunc); - lis3l02dq_free_buf(indio_dev->ring); + lis3l02dq_free_buf(indio_dev->buffer); } -static int lis3l02dq_ring_postenable(struct iio_dev *indio_dev) +static int lis3l02dq_buffer_postenable(struct iio_dev *indio_dev) { /* Disable unwanted channels otherwise the interrupt will not clear */ u8 t; @@ -361,17 +362,17 @@ static int lis3l02dq_ring_postenable(struct iio_dev *indio_dev) if (ret) goto error_ret; - if (iio_scan_mask_query(indio_dev->ring, 0)) { + if (iio_scan_mask_query(indio_dev->buffer, 0)) { t |= LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE; oneenabled = true; } else t &= ~LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE; - if (iio_scan_mask_query(indio_dev->ring, 1)) { + if (iio_scan_mask_query(indio_dev->buffer, 1)) { t |= LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE; oneenabled = true; } else t &= ~LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE; - if (iio_scan_mask_query(indio_dev->ring, 2)) { + if (iio_scan_mask_query(indio_dev->buffer, 2)) { t |= LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE; oneenabled = true; } else @@ -385,18 +386,18 @@ static int lis3l02dq_ring_postenable(struct iio_dev *indio_dev) if (ret) goto error_ret; - return iio_triggered_ring_postenable(indio_dev); + return iio_triggered_buffer_postenable(indio_dev); error_ret: return ret; } /* Turn all channels on again */ -static int lis3l02dq_ring_predisable(struct iio_dev *indio_dev) +static int lis3l02dq_buffer_predisable(struct iio_dev *indio_dev) { u8 t; int ret; - ret = iio_triggered_ring_predisable(indio_dev); + ret = iio_triggered_buffer_predisable(indio_dev); if (ret) goto error_ret; @@ -417,34 +418,29 @@ error_ret: return ret; } -static const struct iio_ring_setup_ops lis3l02dq_ring_setup_ops = { - .preenable = &iio_sw_ring_preenable, - .postenable = &lis3l02dq_ring_postenable, - .predisable = &lis3l02dq_ring_predisable, +static const struct iio_buffer_setup_ops lis3l02dq_buffer_setup_ops = { + .preenable = &iio_sw_buffer_preenable, + .postenable = &lis3l02dq_buffer_postenable, + .predisable = &lis3l02dq_buffer_predisable, }; -int lis3l02dq_configure_ring(struct iio_dev *indio_dev) +int lis3l02dq_configure_buffer(struct iio_dev *indio_dev) { int ret; - struct iio_ring_buffer *ring; + struct iio_buffer *buffer; - ring = lis3l02dq_alloc_buf(indio_dev); - if (!ring) + buffer = lis3l02dq_alloc_buf(indio_dev); + if (!buffer) return -ENOMEM; - indio_dev->ring = ring; - /* Effectively select the ring buffer implementation */ - indio_dev->ring->access = &lis3l02dq_access_funcs; - ring->bpe = 2; - - ring->scan_timestamp = true; - ring->setup_ops = &lis3l02dq_ring_setup_ops; - ring->owner = THIS_MODULE; + indio_dev->buffer = buffer; + /* Effectively select the buffer implementation */ + indio_dev->buffer->access = &lis3l02dq_access_funcs; + buffer->bpe = 2; - /* Set default scan mode */ - iio_scan_mask_set(ring, 0); - iio_scan_mask_set(ring, 1); - iio_scan_mask_set(ring, 2); + buffer->scan_timestamp = true; + buffer->setup_ops = &lis3l02dq_buffer_setup_ops; + buffer->owner = THIS_MODULE; /* Functions are NULL as we set handler below */ indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, @@ -459,10 +455,10 @@ int lis3l02dq_configure_ring(struct iio_dev *indio_dev) goto error_iio_sw_rb_free; } - indio_dev->modes |= INDIO_RING_TRIGGERED; + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; return 0; error_iio_sw_rb_free: - lis3l02dq_free_buf(indio_dev->ring); + lis3l02dq_free_buf(indio_dev->buffer); return ret; } diff --git a/drivers/staging/iio/accel/sca3000.h b/drivers/staging/iio/accel/sca3000.h index 1e396ce..ad38dd9 100644 --- a/drivers/staging/iio/accel/sca3000.h +++ b/drivers/staging/iio/accel/sca3000.h @@ -221,7 +221,7 @@ int sca3000_read_data_short(struct sca3000_state *st, **/ int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val); -#ifdef CONFIG_IIO_RING_BUFFER +#ifdef CONFIG_IIO_BUFFER /** * sca3000_register_ring_funcs() setup the ring state change functions **/ @@ -248,7 +248,7 @@ void sca3000_unconfigure_ring(struct iio_dev *indio_dev); * sca3000_ring_int_process() handles ring related event pushing and escalation * @val: the event code **/ -void sca3000_ring_int_process(u8 val, struct iio_ring_buffer *ring); +void sca3000_ring_int_process(u8 val, struct iio_buffer *ring); #else static inline void sca3000_register_ring_funcs(struct iio_dev *indio_dev) diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index 603f5bc..a44a705 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -11,18 +11,17 @@ */ #include <linux/interrupt.h> -#include <linux/gpio.h> #include <linux/fs.h> #include <linux/device.h> #include <linux/slab.h> #include <linux/kernel.h> #include <linux/spi/spi.h> #include <linux/sysfs.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" +#include "../buffer_generic.h" -#include "accel.h" #include "sca3000.h" enum sca3000_variant { @@ -268,8 +267,8 @@ static ssize_t sca3000_show_rev(struct device *dev, char *buf) { int len = 0, ret; - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct sca3000_state *st = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct sca3000_state *st = iio_priv(indio_dev); mutex_lock(&st->lock); ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_REVID, 1); @@ -296,8 +295,8 @@ sca3000_show_available_measurement_modes(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct sca3000_state *st = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct sca3000_state *st = iio_priv(indio_dev); int len = 0; len += sprintf(buf + len, "0 - normal mode"); @@ -328,8 +327,8 @@ sca3000_show_measurement_mode(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct sca3000_state *st = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct sca3000_state *st = iio_priv(indio_dev); int len = 0, ret; mutex_lock(&st->lock); @@ -379,8 +378,8 @@ sca3000_store_measurement_mode(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct sca3000_state *st = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct sca3000_state *st = iio_priv(indio_dev); int ret; int mask = 0x03; long val; @@ -422,7 +421,7 @@ static IIO_DEVICE_ATTR(measurement_mode, S_IRUGO | S_IWUSR, /* More standard attributes */ -static IIO_DEV_ATTR_REV(sca3000_show_rev); +static IIO_DEVICE_ATTR(revision, S_IRUGO, sca3000_show_rev, NULL, 0); #define SCA3000_INFO_MASK \ (1 << IIO_CHAN_INFO_SCALE_SHARED) @@ -695,7 +694,7 @@ 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, - int e, + u64 e, int *val) { int ret, i; @@ -723,8 +722,8 @@ static int sca3000_read_thresh(struct iio_dev *indio_dev, * sca3000_write_thresh() control of threshold **/ static int sca3000_write_thresh(struct iio_dev *indio_dev, - int e, - int val) + u64 e, + int val) { struct sca3000_state *st = iio_priv(indio_dev); int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e); @@ -771,9 +770,9 @@ static struct attribute *sca3000_attributes_with_temp[] = { &iio_dev_attr_sampling_frequency_available.dev_attr.attr, &iio_dev_attr_sampling_frequency.dev_attr.attr, /* Only present if temp sensor is */ - &iio_dev_attr_temp_raw.dev_attr.attr, - &iio_const_attr_temp_offset.dev_attr.attr, - &iio_const_attr_temp_scale.dev_attr.attr, + &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, }; @@ -812,40 +811,40 @@ static irqreturn_t sca3000_event_handler(int irq, void *private) if (ret) goto done; - sca3000_ring_int_process(val, indio_dev->ring); + sca3000_ring_int_process(val, indio_dev->buffer); if (val & SCA3000_INT_STATUS_FREE_FALL) - iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, - IIO_EV_MOD_X_AND_Y_AND_Z, + IIO_MOD_X_AND_Y_AND_Z, IIO_EV_TYPE_MAG, IIO_EV_DIR_FALLING), last_timestamp); if (val & SCA3000_INT_STATUS_Y_TRIGGER) - iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, - IIO_EV_MOD_Y, + IIO_MOD_Y, IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING), last_timestamp); if (val & SCA3000_INT_STATUS_X_TRIGGER) - iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, - IIO_EV_MOD_X, + IIO_MOD_X, IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING), last_timestamp); if (val & SCA3000_INT_STATUS_Z_TRIGGER) - iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, - IIO_EV_MOD_Z, + IIO_MOD_Z, IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING), last_timestamp); @@ -858,7 +857,7 @@ done: * sca3000_read_event_config() what events are enabled **/ static int sca3000_read_event_config(struct iio_dev *indio_dev, - int e) + u64 e) { struct sca3000_state *st = iio_priv(indio_dev); int ret; @@ -961,7 +960,7 @@ error_ret: * this mode is disabled. Currently normal mode is assumed. **/ static int sca3000_write_event_config(struct iio_dev *indio_dev, - int e, + u64 e, int state) { struct sca3000_state *st = iio_priv(indio_dev); @@ -1018,14 +1017,14 @@ exit_point: /* Free fall detector related event attribute */ static IIO_DEVICE_ATTR_NAMED(accel_xayaz_mag_falling_en, - accel_x&y&z_mag_falling_en, + in_accel_x&y&z_mag_falling_en, S_IRUGO | S_IWUSR, sca3000_query_free_fall_mode, sca3000_set_free_fall_mode, 0); static IIO_CONST_ATTR_NAMED(accel_xayaz_mag_falling_period, - accel_x&y&z_mag_falling_period, + in_accel_x&y&z_mag_falling_period, "0.226"); static struct attribute *sca3000_event_attributes[] = { @@ -1036,6 +1035,7 @@ static struct attribute *sca3000_event_attributes[] = { static struct attribute_group sca3000_event_attribute_group = { .attrs = sca3000_event_attributes, + .name = "events", }; /** @@ -1102,7 +1102,6 @@ error_ret: static const struct iio_info sca3000_info = { .attrs = &sca3000_attribute_group, .read_raw = &sca3000_read_raw, - .num_interrupt_lines = 1, .event_attrs = &sca3000_event_attribute_group, .read_event_value = &sca3000_read_thresh, .write_event_value = &sca3000_write_thresh, @@ -1123,7 +1122,7 @@ static const struct iio_info sca3000_info_with_temp = { static int __devinit sca3000_probe(struct spi_device *spi) { - int ret, regdone = 0; + int ret; struct sca3000_state *st; struct iio_dev *indio_dev; @@ -1155,13 +1154,19 @@ static int __devinit sca3000_probe(struct spi_device *spi) ret = iio_device_register(indio_dev); if (ret < 0) goto error_free_dev; - regdone = 1; - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - sca3000_channels, - ARRAY_SIZE(sca3000_channels)); + + ret = iio_buffer_register(indio_dev, + sca3000_channels, + ARRAY_SIZE(sca3000_channels)); if (ret < 0) goto error_unregister_dev; - if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) { + if (indio_dev->buffer) { + iio_scan_mask_set(indio_dev->buffer, 0); + iio_scan_mask_set(indio_dev->buffer, 1); + iio_scan_mask_set(indio_dev->buffer, 2); + } + + if (spi->irq) { ret = request_threaded_irq(spi->irq, NULL, &sca3000_event_handler, @@ -1178,16 +1183,14 @@ static int __devinit sca3000_probe(struct spi_device *spi) return 0; error_free_irq: - if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) + if (spi->irq) free_irq(spi->irq, indio_dev); error_unregister_ring: - iio_ring_buffer_unregister(indio_dev->ring); + iio_buffer_unregister(indio_dev); error_unregister_dev: + iio_device_unregister(indio_dev); error_free_dev: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ret; @@ -1220,11 +1223,12 @@ static int sca3000_remove(struct spi_device *spi) ret = sca3000_stop_all_interrupts(st); if (ret) return ret; - if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) + if (spi->irq) free_irq(spi->irq, indio_dev); - iio_ring_buffer_unregister(indio_dev->ring); - sca3000_unconfigure_ring(indio_dev); iio_device_unregister(indio_dev); + iio_buffer_unregister(indio_dev); + sca3000_unconfigure_ring(indio_dev); + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index a704c75..4a9a01d 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -10,9 +10,7 @@ */ #include <linux/interrupt.h> -#include <linux/gpio.h> #include <linux/fs.h> -#include <linux/device.h> #include <linux/slab.h> #include <linux/kernel.h> #include <linux/spi/spi.h> @@ -22,9 +20,8 @@ #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" +#include "../buffer_generic.h" #include "../ring_hw.h" -#include "accel.h" #include "sca3000.h" /* RFC / future work @@ -84,10 +81,10 @@ error_ret: * can only be inferred approximately from ring buffer events such as 50% full * and knowledge of when buffer was last emptied. This is left to userspace. **/ -static int sca3000_read_first_n_hw_rb(struct iio_ring_buffer *r, +static int sca3000_read_first_n_hw_rb(struct iio_buffer *r, size_t count, char __user *buf) { - struct iio_hw_ring_buffer *hw_ring = iio_to_hw_ring_buf(r); + struct iio_hw_buffer *hw_ring = iio_to_hw_buf(r); struct iio_dev *indio_dev = hw_ring->private; struct sca3000_state *st = iio_priv(indio_dev); u8 *rx; @@ -137,25 +134,20 @@ error_ret: } /* This is only valid with all 3 elements enabled */ -static int sca3000_ring_get_length(struct iio_ring_buffer *r) +static int sca3000_ring_get_length(struct iio_buffer *r) { return 64; } /* only valid if resolution is kept at 11bits */ -static int sca3000_ring_get_bytes_per_datum(struct iio_ring_buffer *r) +static int sca3000_ring_get_bytes_per_datum(struct iio_buffer *r) { return 6; } -static void sca3000_ring_release(struct device *dev) -{ - struct iio_ring_buffer *r = to_iio_ring_buffer(dev); - kfree(iio_to_hw_ring_buf(r)); -} -static IIO_RING_ENABLE_ATTR; -static IIO_RING_BYTES_PER_DATUM_ATTR; -static IIO_RING_LENGTH_ATTR; +static IIO_BUFFER_ENABLE_ATTR; +static IIO_BUFFER_BYTES_PER_DATUM_ATTR; +static IIO_BUFFER_LENGTH_ATTR; /** * sca3000_query_ring_int() is the hardware ring status interrupt enabled @@ -166,7 +158,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_ring_buffer *ring = dev_get_drvdata(dev); + struct iio_buffer *ring = dev_get_drvdata(dev); struct iio_dev *indio_dev = ring->indio_dev; struct sca3000_state *st = iio_priv(indio_dev); @@ -188,7 +180,7 @@ static ssize_t sca3000_set_ring_int(struct device *dev, const char *buf, size_t len) { - struct iio_ring_buffer *ring = dev_get_drvdata(dev); + struct iio_buffer *ring = dev_get_drvdata(dev); struct iio_dev *indio_dev = ring->indio_dev; struct sca3000_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); @@ -226,86 +218,18 @@ static IIO_DEVICE_ATTR(75_percent, S_IRUGO | S_IWUSR, sca3000_set_ring_int, SCA3000_INT_MASK_RING_THREE_QUARTER); - -/** - * sca3000_show_ring_bpse() -sysfs function to query bits per sample from ring - * @dev: ring buffer device - * @attr: this device attribute - * @buf: buffer to write to - **/ -static ssize_t sca3000_show_ring_bpse(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int len = 0, ret; - struct iio_ring_buffer *ring = dev_get_drvdata(dev); - struct iio_dev *indio_dev = ring->indio_dev; - struct sca3000_state *st = iio_priv(indio_dev); - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); - if (ret) - goto error_ret; - if (st->rx[0] & SCA3000_RING_BUF_8BIT) - len = sprintf(buf, "s8/8\n"); - else - len = sprintf(buf, "s11/16\n"); -error_ret: - mutex_unlock(&st->lock); - - return ret ? ret : len; -} - -/** - * sca3000_store_ring_bpse() - bits per scan element - * @dev: ring buffer device - * @attr: attribute called from - * @buf: input from userspace - * @len: length of input - **/ -static ssize_t sca3000_store_ring_bpse(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_ring_buffer *ring = dev_get_drvdata(dev); - struct iio_dev *indio_dev = ring->indio_dev; - struct sca3000_state *st = iio_priv(indio_dev); - int ret; - - mutex_lock(&st->lock); - - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); - if (ret) - goto error_ret; - if (sysfs_streq(buf, "s8/8")) { - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, - st->rx[0] | SCA3000_RING_BUF_8BIT); - st->bpse = 8; - } else if (sysfs_streq(buf, "s11/16")) { - ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, - st->rx[0] & ~SCA3000_RING_BUF_8BIT); - st->bpse = 11; - } else - ret = -EINVAL; -error_ret: - mutex_unlock(&st->lock); - - return ret ? ret : len; -} - static ssize_t sca3000_show_buffer_scale(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_ring_buffer *ring = dev_get_drvdata(dev); + struct iio_buffer *ring = dev_get_drvdata(dev); struct iio_dev *indio_dev = ring->indio_dev; struct sca3000_state *st = iio_priv(indio_dev); return sprintf(buf, "0.%06d\n", 4*st->info->scale); } -static IIO_DEVICE_ATTR(accel_scale, +static IIO_DEVICE_ATTR(in_accel_scale, S_IRUGO, sca3000_show_buffer_scale, NULL, @@ -323,28 +247,19 @@ static struct attribute *sca3000_ring_attributes[] = { &dev_attr_enable.attr, &iio_dev_attr_50_percent.dev_attr.attr, &iio_dev_attr_75_percent.dev_attr.attr, - &iio_dev_attr_accel_scale.dev_attr.attr, + &iio_dev_attr_in_accel_scale.dev_attr.attr, NULL, }; static struct attribute_group sca3000_ring_attr = { .attrs = sca3000_ring_attributes, + .name = "buffer", }; -static const struct attribute_group *sca3000_ring_attr_groups[] = { - &sca3000_ring_attr, - NULL -}; - -static struct device_type sca3000_ring_type = { - .release = sca3000_ring_release, - .groups = sca3000_ring_attr_groups, -}; - -static struct iio_ring_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) +static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) { - struct iio_ring_buffer *buf; - struct iio_hw_ring_buffer *ring; + struct iio_buffer *buf; + struct iio_hw_buffer *ring; ring = kzalloc(sizeof *ring, GFP_KERNEL); if (!ring) @@ -353,21 +268,18 @@ static struct iio_ring_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) ring->private = indio_dev; buf = &ring->buf; buf->stufftoread = 0; - iio_ring_buffer_init(buf, indio_dev); - buf->dev.type = &sca3000_ring_type; - buf->dev.parent = &indio_dev->dev; - dev_set_drvdata(&buf->dev, (void *)buf); + buf->attrs = &sca3000_ring_attr; + iio_buffer_init(buf, indio_dev); return buf; } -static inline void sca3000_rb_free(struct iio_ring_buffer *r) +static inline void sca3000_rb_free(struct iio_buffer *r) { - if (r) - iio_put_ring_buffer(r); + kfree(iio_to_hw_buf(r)); } -static const struct iio_ring_access_funcs sca3000_ring_access_funcs = { +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, @@ -375,23 +287,19 @@ static const struct iio_ring_access_funcs sca3000_ring_access_funcs = { int sca3000_configure_ring(struct iio_dev *indio_dev) { - indio_dev->ring = sca3000_rb_allocate(indio_dev); - if (indio_dev->ring == NULL) + indio_dev->buffer = sca3000_rb_allocate(indio_dev); + if (indio_dev->buffer == NULL) return -ENOMEM; - indio_dev->modes |= INDIO_RING_HARDWARE_BUFFER; - - indio_dev->ring->access = &sca3000_ring_access_funcs; + indio_dev->modes |= INDIO_BUFFER_HARDWARE; - iio_scan_mask_set(indio_dev->ring, 0); - iio_scan_mask_set(indio_dev->ring, 1); - iio_scan_mask_set(indio_dev->ring, 2); + indio_dev->buffer->access = &sca3000_ring_access_funcs; return 0; } void sca3000_unconfigure_ring(struct iio_dev *indio_dev) { - sca3000_rb_free(indio_dev->ring); + sca3000_rb_free(indio_dev->buffer); } static inline @@ -435,14 +343,14 @@ static int sca3000_hw_ring_postdisable(struct iio_dev *indio_dev) return __sca3000_hw_ring_state_set(indio_dev, 0); } -static const struct iio_ring_setup_ops sca3000_ring_setup_ops = { +static const struct iio_buffer_setup_ops sca3000_ring_setup_ops = { .preenable = &sca3000_hw_ring_preenable, .postdisable = &sca3000_hw_ring_postdisable, }; void sca3000_register_ring_funcs(struct iio_dev *indio_dev) { - indio_dev->ring->setup_ops = &sca3000_ring_setup_ops; + indio_dev->buffer->setup_ops = &sca3000_ring_setup_ops; } /** @@ -451,7 +359,7 @@ void sca3000_register_ring_funcs(struct iio_dev *indio_dev) * This is only split from the main interrupt handler so as to * reduce the amount of code if the ring buffer is not enabled. **/ -void sca3000_ring_int_process(u8 val, struct iio_ring_buffer *ring) +void sca3000_ring_int_process(u8 val, struct iio_buffer *ring) { if (val & (SCA3000_INT_STATUS_THREE_QUARTERS | SCA3000_INT_STATUS_HALF)) { diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index b39f2e1..d9decea 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -1,28 +1,14 @@ # # ADC drivers # -comment "Analog to digital convertors" - -config AD7150 - tristate "Analog Devices ad7150/1/6 capacitive sensor driver" - depends on I2C - help - Say yes here to build support for Analog Devices capacitive sensors. - (ad7150, ad7151, ad7156) Provides direct access via sysfs. - -config AD7152 - tristate "Analog Devices ad7152/3 capacitive sensor driver" - depends on I2C - help - Say yes here to build support for Analog Devices capacitive sensors. - (ad7152, ad7153) Provides direct access via sysfs. +menu "Analog to digital converters" config AD7291 - tristate "Analog Devices AD7291 temperature sensor driver" + tristate "Analog Devices AD7291 ADC driver" depends on I2C help Say yes here to build support for Analog Devices AD7291 - temperature sensors. + 8 Channel ADC with temperature sensor. config AD7298 tristate "Analog Devices AD7298 ADC driver" @@ -34,22 +20,15 @@ config AD7298 To compile this driver as a module, choose M here: the module will be called ad7298. -config AD7314 - tristate "Analog Devices AD7314 temperature sensor driver" - depends on SPI - help - Say yes here to build support for Analog Devices AD7314 - temperature sensors. - config AD7606 tristate "Analog Devices AD7606 ADC driver" depends on GPIOLIB - select IIO_RING_BUFFER + select IIO_BUFFER select IIO_TRIGGER select IIO_SW_RING help Say yes here to build support for Analog Devices: - ad7606, ad7606-6, ad7606-4 analog to digital convertors (ADC). + ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC). To compile this driver as a module, choose M here: the module will be called ad7606. @@ -72,18 +51,18 @@ config AD7606_IFACE_SPI config AD799X tristate "Analog Devices AD799x ADC driver" depends on I2C - select IIO_TRIGGER if IIO_RING_BUFFER + 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 convertors (ADC). Provides direct access + 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_RING_BUFFER + select IIO_BUFFER select IIO_SW_RING help Say yes here to include ring buffer support in the AD799X @@ -92,13 +71,13 @@ config AD799X_RING_BUFFER config AD7476 tristate "Analog Devices AD7475/6/7/8 AD7466/7/8 and AD7495 ADC driver" depends on SPI - select IIO_RING_BUFFER + select IIO_BUFFER select IIO_SW_RING select IIO_TRIGGER help Say yes here to build support for Analog Devices AD7475, AD7476, AD7477, AD7478, AD7466, AD7467, AD7468, AD7495 - SPI analog to digital convertors (ADC). + 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 @@ -107,12 +86,12 @@ config AD7476 config AD7887 tristate "Analog Devices AD7887 ADC driver" depends on SPI - select IIO_RING_BUFFER + 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 convertor (ADC). + 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 @@ -124,7 +103,7 @@ config AD7780 depends on GPIOLIB help Say yes here to build support for Analog Devices - AD7780 and AD7781 SPI analog to digital convertors (ADC). + 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 @@ -133,40 +112,38 @@ config AD7780 config AD7793 tristate "Analog Devices AD7792 AD7793 ADC driver" depends on SPI - select IIO_RING_BUFFER + 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 convertors (ADC). + 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 AD7745 - tristate "Analog Devices AD7745, AD7746 AD7747 capacitive sensor driver" - depends on I2C - help - Say yes here to build support for Analog Devices capacitive sensors. - (AD7745, AD7746, AD7747) Provides direct access via sysfs. - - To compile this driver as a module, choose M here: the - module will be called ad7745. - config AD7816 tristate "Analog Devices AD7816/7/8 temperature sensor and ADC driver" depends on SPI + depends on GENERIC_GPIO help Say yes here to build support for Analog Devices AD7816/7/8 temperature sensors and ADC. -config ADT75 - tristate "Analog Devices ADT75 temperature sensor driver" - depends on I2C +config AD7192 + tristate "Analog Devices AD7190 AD7192 AD7195 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 ADT75 - temperature sensors. + Say yes here to build support for Analog Devices AD7190, + AD7192 or AD7195 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 ad7192. config ADT7310 tristate "Analog Devices ADT7310 temperature sensor driver" @@ -182,14 +159,24 @@ config ADT7410 Say yes here to build support for Analog Devices ADT7410 temperature sensors. +config AD7280 + tristate "Analog Devices AD7280A Lithium Ion Battery Monitoring System" + depends on SPI + help + Say yes here to build support for Analog Devices AD7280A + Lithium Ion Battery Monitoring System. + + To compile this driver as a module, choose M here: the + module will be called ad7280a + config MAX1363 tristate "Maxim max1363 ADC driver" depends on I2C - select IIO_TRIGGER if IIO_RING_BUFFER + select IIO_TRIGGER if IIO_BUFFER select MAX1363_RING_BUFFER help Say yes here to build support for many Maxim i2c analog to digital - convertors (ADC). (max1361, max1362, max1363, max1364, max1036, + 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, @@ -200,8 +187,10 @@ config MAX1363 config MAX1363_RING_BUFFER bool "Maxim max1363: use ring buffer" depends on MAX1363 - select IIO_RING_BUFFER + select IIO_BUFFER select IIO_SW_RING help Say yes here to include ring buffer support in the MAX1363 ADC driver. + +endmenu diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile index f020351..ceee7f3 100644 --- a/drivers/staging/iio/adc/Makefile +++ b/drivers/staging/iio/adc/Makefile @@ -8,7 +8,7 @@ max1363-y += max1363_ring.o obj-$(CONFIG_MAX1363) += max1363.o ad7606-y := ad7606_core.o -ad7606-$(CONFIG_IIO_RING_BUFFER) += ad7606_ring.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 @@ -18,25 +18,22 @@ ad799x-$(CONFIG_AD799X_RING_BUFFER) += ad799x_ring.o obj-$(CONFIG_AD799X) += ad799x.o ad7476-y := ad7476_core.o -ad7476-$(CONFIG_IIO_RING_BUFFER) += ad7476_ring.o +ad7476-$(CONFIG_IIO_BUFFER) += ad7476_ring.o obj-$(CONFIG_AD7476) += ad7476.o ad7887-y := ad7887_core.o -ad7887-$(CONFIG_IIO_RING_BUFFER) += ad7887_ring.o +ad7887-$(CONFIG_IIO_BUFFER) += ad7887_ring.o obj-$(CONFIG_AD7887) += ad7887.o ad7298-y := ad7298_core.o -ad7298-$(CONFIG_IIO_RING_BUFFER) += ad7298_ring.o +ad7298-$(CONFIG_IIO_BUFFER) += ad7298_ring.o obj-$(CONFIG_AD7298) += ad7298.o -obj-$(CONFIG_AD7150) += ad7150.o -obj-$(CONFIG_AD7152) += ad7152.o obj-$(CONFIG_AD7291) += ad7291.o -obj-$(CONFIG_AD7314) += ad7314.o -obj-$(CONFIG_AD7745) += ad7745.o obj-$(CONFIG_AD7780) += ad7780.o obj-$(CONFIG_AD7793) += ad7793.o obj-$(CONFIG_AD7816) += ad7816.o -obj-$(CONFIG_ADT75) += adt75.o +obj-$(CONFIG_AD7192) += ad7192.o obj-$(CONFIG_ADT7310) += adt7310.o obj-$(CONFIG_ADT7410) += adt7410.o +obj-$(CONFIG_AD7280) += ad7280a.o diff --git a/drivers/staging/iio/adc/ad7150.c b/drivers/staging/iio/adc/ad7150.c deleted file mode 100644 index 04017ef..0000000 --- a/drivers/staging/iio/adc/ad7150.c +++ /dev/null @@ -1,812 +0,0 @@ -/* - * AD7150 capacitive sensor driver supporting AD7150/1/6 - * - * 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/i2c.h> - -#include "../iio.h" -#include "../sysfs.h" - -/* - * AD7150 registers definition - */ - -#define AD7150_STATUS 0 -#define AD7150_STATUS_OUT1 (1 << 3) -#define AD7150_STATUS_OUT2 (1 << 5) -#define AD7150_CH1_DATA_HIGH 1 -#define AD7150_CH1_DATA_LOW 2 -#define AD7150_CH2_DATA_HIGH 3 -#define AD7150_CH2_DATA_LOW 4 -#define AD7150_CH1_AVG_HIGH 5 -#define AD7150_CH1_AVG_LOW 6 -#define AD7150_CH2_AVG_HIGH 7 -#define AD7150_CH2_AVG_LOW 8 -#define AD7150_CH1_SENSITIVITY 9 -#define AD7150_CH1_THR_HOLD_H 9 -#define AD7150_CH1_TIMEOUT 10 -#define AD7150_CH1_THR_HOLD_L 10 -#define AD7150_CH1_SETUP 11 -#define AD7150_CH2_SENSITIVITY 12 -#define AD7150_CH2_THR_HOLD_H 12 -#define AD7150_CH2_TIMEOUT 13 -#define AD7150_CH2_THR_HOLD_L 13 -#define AD7150_CH2_SETUP 14 -#define AD7150_CFG 15 -#define AD7150_CFG_FIX (1 << 7) -#define AD7150_PD_TIMER 16 -#define AD7150_CH1_CAPDAC 17 -#define AD7150_CH2_CAPDAC 18 -#define AD7150_SN3 19 -#define AD7150_SN2 20 -#define AD7150_SN1 21 -#define AD7150_SN0 22 -#define AD7150_ID 23 - -#define AD7150_MAX_CONV_MODE 4 - -/* - * struct ad7150_chip_info - chip specifc information - */ - -struct ad7150_chip_info { - struct i2c_client *client; - bool inter; - u16 ch1_threshold; /* Ch1 Threshold (in fixed threshold mode) */ - u8 ch1_sensitivity; /* Ch1 Sensitivity (in adaptive threshold mode) */ - u8 ch1_timeout; /* Ch1 Timeout (in adaptive threshold mode) */ - u8 ch1_setup; - u16 ch2_threshold; /* Ch2 Threshold (in fixed threshold mode) */ - u8 ch2_sensitivity; /* Ch1 Sensitivity (in adaptive threshold mode) */ - u8 ch2_timeout; /* Ch1 Timeout (in adaptive threshold mode) */ - u8 ch2_setup; - u8 powerdown_timer; - char threshold_mode[10]; /* adaptive/fixed threshold mode */ - int old_state; - char *conversion_mode; -}; - -struct ad7150_conversion_mode { - char *name; - u8 reg_cfg; -}; - -static struct ad7150_conversion_mode -ad7150_conv_mode_table[AD7150_MAX_CONV_MODE] = { - { "idle", 0 }, - { "continuous-conversion", 1 }, - { "single-conversion", 2 }, - { "power-down", 3 }, -}; - -/* - * ad7150 register access by I2C - */ - -static int ad7150_i2c_read(struct ad7150_chip_info *chip, u8 reg, u8 *data, int len) -{ - struct i2c_client *client = chip->client; - int ret = 0; - - ret = i2c_master_send(client, ®, 1); - if (ret < 0) { - dev_err(&client->dev, "I2C write error\n"); - return ret; - } - - ret = i2c_master_recv(client, data, len); - if (ret < 0) { - dev_err(&client->dev, "I2C read error\n"); - return ret; - } - - return ret; -} - -static int ad7150_i2c_write(struct ad7150_chip_info *chip, u8 reg, u8 data) -{ - struct i2c_client *client = chip->client; - int ret = 0; - - u8 tx[2] = { - reg, - data, - }; - - ret = i2c_master_send(client, tx, 2); - if (ret < 0) - dev_err(&client->dev, "I2C write error\n"); - - return ret; -} - -/* - * sysfs nodes - */ - -#define IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(_show) \ - IIO_DEVICE_ATTR(available_conversion_modes, S_IRUGO, _show, NULL, 0) -#define IIO_DEV_ATTR_CONVERSION_MODE(_mode, _show, _store) \ - IIO_DEVICE_ATTR(conversion_mode, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_AVAIL_THRESHOLD_MODES(_show) \ - IIO_DEVICE_ATTR(available_threshold_modes, S_IRUGO, _show, NULL, 0) -#define IIO_DEV_ATTR_THRESHOLD_MODE(_mode, _show, _store) \ - IIO_DEVICE_ATTR(threshold_mode, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CH1_THRESHOLD(_mode, _show, _store) \ - IIO_DEVICE_ATTR(ch1_threshold, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CH2_THRESHOLD(_mode, _show, _store) \ - IIO_DEVICE_ATTR(ch2_threshold, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CH1_SENSITIVITY(_mode, _show, _store) \ - IIO_DEVICE_ATTR(ch1_sensitivity, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CH2_SENSITIVITY(_mode, _show, _store) \ - IIO_DEVICE_ATTR(ch2_sensitivity, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CH1_TIMEOUT(_mode, _show, _store) \ - IIO_DEVICE_ATTR(ch1_timeout, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CH2_TIMEOUT(_mode, _show, _store) \ - IIO_DEVICE_ATTR(ch2_timeout, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CH1_VALUE(_show) \ - IIO_DEVICE_ATTR(ch1_value, S_IRUGO, _show, NULL, 0) -#define IIO_DEV_ATTR_CH2_VALUE(_show) \ - IIO_DEVICE_ATTR(ch2_value, S_IRUGO, _show, NULL, 0) -#define IIO_DEV_ATTR_CH1_SETUP(_mode, _show, _store) \ - IIO_DEVICE_ATTR(ch1_setup, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CH2_SETUP(_mode, _show, _store) \ - IIO_DEVICE_ATTR(ch2_setup, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_POWERDOWN_TIMER(_mode, _show, _store) \ - IIO_DEVICE_ATTR(powerdown_timer, _mode, _show, _store, 0) - -static ssize_t ad7150_show_conversion_modes(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int i; - int len = 0; - - for (i = 0; i < AD7150_MAX_CONV_MODE; i++) - len += sprintf(buf + len, "%s\n", ad7150_conv_mode_table[i].name); - - return len; -} - -static IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(ad7150_show_conversion_modes); - -static ssize_t ad7150_show_conversion_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%s\n", chip->conversion_mode); -} - -static ssize_t ad7150_store_conversion_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - u8 cfg; - int i; - - ad7150_i2c_read(chip, AD7150_CFG, &cfg, 1); - - for (i = 0; i < AD7150_MAX_CONV_MODE; i++) { - if (strncmp(buf, ad7150_conv_mode_table[i].name, - strlen(ad7150_conv_mode_table[i].name) - 1) == 0) { - chip->conversion_mode = ad7150_conv_mode_table[i].name; - cfg |= 0x18 | ad7150_conv_mode_table[i].reg_cfg; - ad7150_i2c_write(chip, AD7150_CFG, cfg); - return len; - } - } - - dev_err(dev, "not supported conversion mode\n"); - - return -EINVAL; -} - -static IIO_DEV_ATTR_CONVERSION_MODE(S_IRUGO | S_IWUSR, - ad7150_show_conversion_mode, - ad7150_store_conversion_mode); - -static ssize_t ad7150_show_threshold_modes(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "adaptive\nfixed\n"); -} - -static IIO_DEV_ATTR_AVAIL_THRESHOLD_MODES(ad7150_show_threshold_modes); - -static ssize_t ad7150_show_ch1_value(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - u8 data[2]; - - ad7150_i2c_read(chip, AD7150_CH1_DATA_HIGH, data, 2); - return sprintf(buf, "%d\n", ((int) data[0] << 8) | data[1]); -} - -static IIO_DEV_ATTR_CH1_VALUE(ad7150_show_ch1_value); - -static ssize_t ad7150_show_ch2_value(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - u8 data[2]; - - ad7150_i2c_read(chip, AD7150_CH2_DATA_HIGH, data, 2); - return sprintf(buf, "%d\n", ((int) data[0] << 8) | data[1]); -} - -static IIO_DEV_ATTR_CH2_VALUE(ad7150_show_ch2_value); - -static ssize_t ad7150_show_threshold_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%s\n", chip->threshold_mode); -} - -static ssize_t ad7150_store_threshold_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - u8 cfg; - - ad7150_i2c_read(chip, AD7150_CFG, &cfg, 1); - - if (strncmp(buf, "fixed", 5) == 0) { - strcpy(chip->threshold_mode, "fixed"); - cfg |= AD7150_CFG_FIX; - ad7150_i2c_write(chip, AD7150_CFG, cfg); - - return len; - } else if (strncmp(buf, "adaptive", 8) == 0) { - strcpy(chip->threshold_mode, "adaptive"); - cfg &= ~AD7150_CFG_FIX; - ad7150_i2c_write(chip, AD7150_CFG, cfg); - - return len; - } - - dev_err(dev, "not supported threshold mode\n"); - return -EINVAL; -} - -static IIO_DEV_ATTR_THRESHOLD_MODE(S_IRUGO | S_IWUSR, - ad7150_show_threshold_mode, - ad7150_store_threshold_mode); - -static ssize_t ad7150_show_ch1_threshold(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%d\n", chip->ch1_threshold); -} - -static ssize_t ad7150_store_ch1_threshold(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x10000)) { - ad7150_i2c_write(chip, AD7150_CH1_THR_HOLD_H, data >> 8); - ad7150_i2c_write(chip, AD7150_CH1_THR_HOLD_L, data); - chip->ch1_threshold = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_CH1_THRESHOLD(S_IRUGO | S_IWUSR, - ad7150_show_ch1_threshold, - ad7150_store_ch1_threshold); - -static ssize_t ad7150_show_ch2_threshold(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%d\n", chip->ch2_threshold); -} - -static ssize_t ad7150_store_ch2_threshold(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x10000)) { - ad7150_i2c_write(chip, AD7150_CH2_THR_HOLD_H, data >> 8); - ad7150_i2c_write(chip, AD7150_CH2_THR_HOLD_L, data); - chip->ch2_threshold = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_CH2_THRESHOLD(S_IRUGO | S_IWUSR, - ad7150_show_ch2_threshold, - ad7150_store_ch2_threshold); - -static ssize_t ad7150_show_ch1_sensitivity(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%d\n", chip->ch1_sensitivity); -} - -static ssize_t ad7150_store_ch1_sensitivity(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x100)) { - ad7150_i2c_write(chip, AD7150_CH1_SENSITIVITY, data); - chip->ch1_sensitivity = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_CH1_SENSITIVITY(S_IRUGO | S_IWUSR, - ad7150_show_ch1_sensitivity, - ad7150_store_ch1_sensitivity); - -static ssize_t ad7150_show_ch2_sensitivity(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%d\n", chip->ch2_sensitivity); -} - -static ssize_t ad7150_store_ch2_sensitivity(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x100)) { - ad7150_i2c_write(chip, AD7150_CH2_SENSITIVITY, data); - chip->ch2_sensitivity = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_CH2_SENSITIVITY(S_IRUGO | S_IWUSR, - ad7150_show_ch2_sensitivity, - ad7150_store_ch2_sensitivity); - -static ssize_t ad7150_show_ch1_timeout(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%d\n", chip->ch1_timeout); -} - -static ssize_t ad7150_store_ch1_timeout(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x100)) { - ad7150_i2c_write(chip, AD7150_CH1_TIMEOUT, data); - chip->ch1_timeout = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_CH1_TIMEOUT(S_IRUGO | S_IWUSR, - ad7150_show_ch1_timeout, - ad7150_store_ch1_timeout); - -static ssize_t ad7150_show_ch2_timeout(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%d\n", chip->ch2_timeout); -} - -static ssize_t ad7150_store_ch2_timeout(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x100)) { - ad7150_i2c_write(chip, AD7150_CH2_TIMEOUT, data); - chip->ch2_timeout = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_CH2_TIMEOUT(S_IRUGO | S_IWUSR, - ad7150_show_ch2_timeout, - ad7150_store_ch2_timeout); - -static ssize_t ad7150_show_ch1_setup(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "0x%02x\n", chip->ch1_setup); -} - -static ssize_t ad7150_store_ch1_setup(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x100)) { - ad7150_i2c_write(chip, AD7150_CH1_SETUP, data); - chip->ch1_setup = data; - return len; - } - - - return -EINVAL; -} - -static IIO_DEV_ATTR_CH1_SETUP(S_IRUGO | S_IWUSR, - ad7150_show_ch1_setup, - ad7150_store_ch1_setup); - -static ssize_t ad7150_show_ch2_setup(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "0x%02x\n", chip->ch2_setup); -} - -static ssize_t ad7150_store_ch2_setup(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x100)) { - ad7150_i2c_write(chip, AD7150_CH2_SETUP, data); - chip->ch2_setup = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_CH2_SETUP(S_IRUGO | S_IWUSR, - ad7150_show_ch2_setup, - ad7150_store_ch2_setup); - -static ssize_t ad7150_show_powerdown_timer(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "0x%02x\n", chip->powerdown_timer); -} - -static ssize_t ad7150_store_powerdown_timer(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7150_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x40)) { - chip->powerdown_timer = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_POWERDOWN_TIMER(S_IRUGO | S_IWUSR, - ad7150_show_powerdown_timer, - ad7150_store_powerdown_timer); - -static struct attribute *ad7150_attributes[] = { - &iio_dev_attr_available_threshold_modes.dev_attr.attr, - &iio_dev_attr_threshold_mode.dev_attr.attr, - &iio_dev_attr_ch1_threshold.dev_attr.attr, - &iio_dev_attr_ch2_threshold.dev_attr.attr, - &iio_dev_attr_ch1_timeout.dev_attr.attr, - &iio_dev_attr_ch2_timeout.dev_attr.attr, - &iio_dev_attr_ch1_setup.dev_attr.attr, - &iio_dev_attr_ch2_setup.dev_attr.attr, - &iio_dev_attr_ch1_sensitivity.dev_attr.attr, - &iio_dev_attr_ch2_sensitivity.dev_attr.attr, - &iio_dev_attr_powerdown_timer.dev_attr.attr, - &iio_dev_attr_ch1_value.dev_attr.attr, - &iio_dev_attr_ch2_value.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad7150_attribute_group = { - .attrs = ad7150_attributes, -}; - -/* - * threshold events - */ - -static irqreturn_t ad7150_event_handler(int irq, void *private) -{ - struct iio_dev *indio_dev = private; - struct ad7150_chip_info *chip = iio_priv(indio_dev); - u8 int_status; - s64 timestamp = iio_get_time_ns(); - - ad7150_i2c_read(chip, AD7150_STATUS, &int_status, 1); - - if ((int_status & AD7150_STATUS_OUT1) && !(chip->old_state & AD7150_STATUS_OUT1)) - iio_push_event(indio_dev, 0, - IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, - 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - timestamp); - else if ((!(int_status & AD7150_STATUS_OUT1)) && (chip->old_state & AD7150_STATUS_OUT1)) - iio_push_event(indio_dev, 0, - IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, - 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING), - timestamp); - - if ((int_status & AD7150_STATUS_OUT2) && !(chip->old_state & AD7150_STATUS_OUT2)) - iio_push_event(indio_dev, 0, - IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, - 1, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - timestamp); - else if ((!(int_status & AD7150_STATUS_OUT2)) && (chip->old_state & AD7150_STATUS_OUT2)) - iio_push_event(indio_dev, 0, - IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, - 1, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING), - timestamp); - return IRQ_HANDLED; -} - -static IIO_CONST_ATTR(ch1_high_en, "1"); -static IIO_CONST_ATTR(ch2_high_en, "1"); -static IIO_CONST_ATTR(ch1_low_en, "1"); -static IIO_CONST_ATTR(ch2_low_en, "1"); - -static struct attribute *ad7150_event_attributes[] = { - &iio_const_attr_ch1_high_en.dev_attr.attr, - &iio_const_attr_ch2_high_en.dev_attr.attr, - &iio_const_attr_ch1_low_en.dev_attr.attr, - &iio_const_attr_ch2_low_en.dev_attr.attr, - NULL, -}; - -static struct attribute_group ad7150_event_attribute_group = { - .attrs = ad7150_event_attributes, -}; - -static const struct iio_info ad7150_info = { - .attrs = &ad7150_attribute_group, - .num_interrupt_lines = 1, - .event_attrs = &ad7150_event_attribute_group, - .driver_module = THIS_MODULE, -}; -/* - * device probe and remove - */ - -static int __devinit ad7150_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int ret = 0, regdone = 0; - 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; - } - chip = iio_priv(indio_dev); - /* this is only used for device removal purposes */ - i2c_set_clientdata(client, indio_dev); - - chip->client = client; - - /* Establish that the iio_dev is a child of the i2c device */ - indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; - - indio_dev->info = &ad7150_info; - - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - regdone = 1; - - if (client->irq) { - ret = request_threaded_irq(client->irq, - NULL, - &ad7150_event_handler, - IRQF_TRIGGER_RISING | - IRQF_TRIGGER_FALLING, - "ad7150", - indio_dev); - if (ret) - goto error_free_dev; - } - - dev_err(&client->dev, "%s capacitive sensor registered, irq: %d\n", id->name, client->irq); - - return 0; - -error_free_dev: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); -error_ret: - return ret; -} - -static int __devexit ad7150_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - - if (client->irq) - free_irq(client->irq, indio_dev); - iio_device_unregister(indio_dev); - - return 0; -} - -static const struct i2c_device_id ad7150_id[] = { - { "ad7150", 0 }, - { "ad7151", 0 }, - { "ad7156", 0 }, - {} -}; - -MODULE_DEVICE_TABLE(i2c, ad7150_id); - -static struct i2c_driver ad7150_driver = { - .driver = { - .name = "ad7150", - }, - .probe = ad7150_probe, - .remove = __devexit_p(ad7150_remove), - .id_table = ad7150_id, -}; - -static __init int ad7150_init(void) -{ - return i2c_add_driver(&ad7150_driver); -} - -static __exit void ad7150_exit(void) -{ - i2c_del_driver(&ad7150_driver); -} - -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_DESCRIPTION("Analog Devices ad7150/1/6 capacitive sensor driver"); -MODULE_LICENSE("GPL v2"); - -module_init(ad7150_init); -module_exit(ad7150_exit); diff --git a/drivers/staging/iio/adc/ad7152.c b/drivers/staging/iio/adc/ad7152.c deleted file mode 100644 index 21f5f38..0000000 --- a/drivers/staging/iio/adc/ad7152.c +++ /dev/null @@ -1,586 +0,0 @@ -/* - * AD7152 capacitive sensor driver supporting AD7152/3 - * - * 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/i2c.h> - -#include "../iio.h" -#include "../sysfs.h" - -/* - * AD7152 registers definition - */ - -#define AD7152_STATUS 0 -#define AD7152_STATUS_RDY1 (1 << 0) -#define AD7152_STATUS_RDY2 (1 << 1) -#define AD7152_CH1_DATA_HIGH 1 -#define AD7152_CH1_DATA_LOW 2 -#define AD7152_CH2_DATA_HIGH 3 -#define AD7152_CH2_DATA_LOW 4 -#define AD7152_CH1_OFFS_HIGH 5 -#define AD7152_CH1_OFFS_LOW 6 -#define AD7152_CH2_OFFS_HIGH 7 -#define AD7152_CH2_OFFS_LOW 8 -#define AD7152_CH1_GAIN_HIGH 9 -#define AD7152_CH1_GAIN_LOW 10 -#define AD7152_CH1_SETUP 11 -#define AD7152_CH2_GAIN_HIGH 12 -#define AD7152_CH2_GAIN_LOW 13 -#define AD7152_CH2_SETUP 14 -#define AD7152_CFG 15 -#define AD7152_RESEVERD 16 -#define AD7152_CAPDAC_POS 17 -#define AD7152_CAPDAC_NEG 18 -#define AD7152_CFG2 26 - -#define AD7152_MAX_CONV_MODE 6 - -/* - * struct ad7152_chip_info - chip specifc information - */ - -struct ad7152_chip_info { - struct i2c_client *client; - u16 ch1_offset; /* Channel 1 offset calibration coefficient */ - u16 ch1_gain; /* Channel 1 gain coefficient */ - u8 ch1_setup; - u16 ch2_offset; /* Channel 2 offset calibration coefficient */ - u16 ch2_gain; /* Channel 1 gain coefficient */ - u8 ch2_setup; - u8 filter_rate_setup; /* Capacitive channel digital filter setup; conversion time/update rate setup per channel */ - char *conversion_mode; -}; - -struct ad7152_conversion_mode { - char *name; - u8 reg_cfg; -}; - -static struct ad7152_conversion_mode -ad7152_conv_mode_table[AD7152_MAX_CONV_MODE] = { - { "idle", 0 }, - { "continuous-conversion", 1 }, - { "single-conversion", 2 }, - { "power-down", 3 }, - { "offset-calibration", 5 }, - { "gain-calibration", 6 }, -}; - -/* - * ad7152 register access by I2C - */ - -static int ad7152_i2c_read(struct ad7152_chip_info *chip, u8 reg, u8 *data, int len) -{ - struct i2c_client *client = chip->client; - int ret; - - ret = i2c_master_send(client, ®, 1); - if (ret < 0) { - dev_err(&client->dev, "I2C write error\n"); - return ret; - } - - ret = i2c_master_recv(client, data, len); - if (ret < 0) { - dev_err(&client->dev, "I2C read error\n"); - } - - return ret; -} - -static int ad7152_i2c_write(struct ad7152_chip_info *chip, u8 reg, u8 data) -{ - struct i2c_client *client = chip->client; - int ret; - - u8 tx[2] = { - reg, - data, - }; - - ret = i2c_master_send(client, tx, 2); - if (ret < 0) - dev_err(&client->dev, "I2C write error\n"); - - return ret; -} - -/* - * sysfs nodes - */ - -#define IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(_show) \ - IIO_DEVICE_ATTR(available_conversion_modes, S_IRUGO, _show, NULL, 0) -#define IIO_DEV_ATTR_CONVERSION_MODE(_mode, _show, _store) \ - IIO_DEVICE_ATTR(conversion_mode, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CH1_OFFSET(_mode, _show, _store) \ - IIO_DEVICE_ATTR(ch1_offset, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CH2_OFFSET(_mode, _show, _store) \ - IIO_DEVICE_ATTR(ch2_offset, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CH1_GAIN(_mode, _show, _store) \ - IIO_DEVICE_ATTR(ch1_gain, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CH2_GAIN(_mode, _show, _store) \ - IIO_DEVICE_ATTR(ch2_gain, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CH1_VALUE(_show) \ - IIO_DEVICE_ATTR(ch1_value, S_IRUGO, _show, NULL, 0) -#define IIO_DEV_ATTR_CH2_VALUE(_show) \ - IIO_DEVICE_ATTR(ch2_value, S_IRUGO, _show, NULL, 0) -#define IIO_DEV_ATTR_CH1_SETUP(_mode, _show, _store) \ - IIO_DEVICE_ATTR(ch1_setup, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CH2_SETUP(_mode, _show, _store) \ - IIO_DEVICE_ATTR(ch2_setup, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_FILTER_RATE_SETUP(_mode, _show, _store) \ - IIO_DEVICE_ATTR(filter_rate_setup, _mode, _show, _store, 0) - -static ssize_t ad7152_show_conversion_modes(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int i; - int len = 0; - - for (i = 0; i < AD7152_MAX_CONV_MODE; i++) - len += sprintf(buf + len, "%s ", ad7152_conv_mode_table[i].name); - - len += sprintf(buf + len, "\n"); - - return len; -} - -static IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(ad7152_show_conversion_modes); - -static ssize_t ad7152_show_ch1_value(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - u8 data[2]; - - ad7152_i2c_read(chip, AD7152_CH1_DATA_HIGH, data, 2); - return sprintf(buf, "%d\n", ((int)data[0] << 8) | data[1]); -} - -static IIO_DEV_ATTR_CH1_VALUE(ad7152_show_ch1_value); - -static ssize_t ad7152_show_ch2_value(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - u8 data[2]; - - ad7152_i2c_read(chip, AD7152_CH2_DATA_HIGH, data, 2); - return sprintf(buf, "%d\n", ((int)data[0] << 8) | data[1]); -} - -static IIO_DEV_ATTR_CH2_VALUE(ad7152_show_ch2_value); - -static ssize_t ad7152_show_conversion_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%s\n", chip->conversion_mode); -} - -static ssize_t ad7152_store_conversion_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - u8 cfg; - int i; - - ad7152_i2c_read(chip, AD7152_CFG, &cfg, 1); - - for (i = 0; i < AD7152_MAX_CONV_MODE; i++) - if (strncmp(buf, ad7152_conv_mode_table[i].name, - strlen(ad7152_conv_mode_table[i].name) - 1) == 0) { - chip->conversion_mode = ad7152_conv_mode_table[i].name; - cfg |= 0x18 | ad7152_conv_mode_table[i].reg_cfg; - ad7152_i2c_write(chip, AD7152_CFG, cfg); - return len; - } - - dev_err(dev, "not supported conversion mode\n"); - - return -EINVAL; -} - -static IIO_DEV_ATTR_CONVERSION_MODE(S_IRUGO | S_IWUSR, - ad7152_show_conversion_mode, - ad7152_store_conversion_mode); - -static ssize_t ad7152_show_ch1_offset(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%d\n", chip->ch1_offset); -} - -static ssize_t ad7152_store_ch1_offset(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x10000)) { - ad7152_i2c_write(chip, AD7152_CH1_OFFS_HIGH, data >> 8); - ad7152_i2c_write(chip, AD7152_CH1_OFFS_LOW, data); - chip->ch1_offset = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_CH1_OFFSET(S_IRUGO | S_IWUSR, - ad7152_show_ch1_offset, - ad7152_store_ch1_offset); - -static ssize_t ad7152_show_ch2_offset(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%d\n", chip->ch2_offset); -} - -static ssize_t ad7152_store_ch2_offset(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x10000)) { - ad7152_i2c_write(chip, AD7152_CH2_OFFS_HIGH, data >> 8); - ad7152_i2c_write(chip, AD7152_CH2_OFFS_LOW, data); - chip->ch2_offset = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_CH2_OFFSET(S_IRUGO | S_IWUSR, - ad7152_show_ch2_offset, - ad7152_store_ch2_offset); - -static ssize_t ad7152_show_ch1_gain(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%d\n", chip->ch1_gain); -} - -static ssize_t ad7152_store_ch1_gain(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x10000)) { - ad7152_i2c_write(chip, AD7152_CH1_GAIN_HIGH, data >> 8); - ad7152_i2c_write(chip, AD7152_CH1_GAIN_LOW, data); - chip->ch1_gain = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_CH1_GAIN(S_IRUGO | S_IWUSR, - ad7152_show_ch1_gain, - ad7152_store_ch1_gain); - -static ssize_t ad7152_show_ch2_gain(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%d\n", chip->ch2_gain); -} - -static ssize_t ad7152_store_ch2_gain(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x10000)) { - ad7152_i2c_write(chip, AD7152_CH2_GAIN_HIGH, data >> 8); - ad7152_i2c_write(chip, AD7152_CH2_GAIN_LOW, data); - chip->ch2_gain = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_CH2_GAIN(S_IRUGO | S_IWUSR, - ad7152_show_ch2_gain, - ad7152_store_ch2_gain); - -static ssize_t ad7152_show_ch1_setup(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "0x%02x\n", chip->ch1_setup); -} - -static ssize_t ad7152_store_ch1_setup(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x100)) { - ad7152_i2c_write(chip, AD7152_CH1_SETUP, data); - chip->ch1_setup = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_CH1_SETUP(S_IRUGO | S_IWUSR, - ad7152_show_ch1_setup, - ad7152_store_ch1_setup); - -static ssize_t ad7152_show_ch2_setup(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "0x%02x\n", chip->ch2_setup); -} - -static ssize_t ad7152_store_ch2_setup(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x100)) { - ad7152_i2c_write(chip, AD7152_CH2_SETUP, data); - chip->ch2_setup = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_CH2_SETUP(S_IRUGO | S_IWUSR, - ad7152_show_ch2_setup, - ad7152_store_ch2_setup); - -static ssize_t ad7152_show_filter_rate_setup(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "0x%02x\n", chip->filter_rate_setup); -} - -static ssize_t ad7152_store_filter_rate_setup(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7152_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x100)) { - ad7152_i2c_write(chip, AD7152_CFG2, data); - chip->filter_rate_setup = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_FILTER_RATE_SETUP(S_IRUGO | S_IWUSR, - ad7152_show_filter_rate_setup, - ad7152_store_filter_rate_setup); - -static struct attribute *ad7152_attributes[] = { - &iio_dev_attr_available_conversion_modes.dev_attr.attr, - &iio_dev_attr_conversion_mode.dev_attr.attr, - &iio_dev_attr_ch1_gain.dev_attr.attr, - &iio_dev_attr_ch2_gain.dev_attr.attr, - &iio_dev_attr_ch1_offset.dev_attr.attr, - &iio_dev_attr_ch2_offset.dev_attr.attr, - &iio_dev_attr_ch1_value.dev_attr.attr, - &iio_dev_attr_ch2_value.dev_attr.attr, - &iio_dev_attr_ch1_setup.dev_attr.attr, - &iio_dev_attr_ch2_setup.dev_attr.attr, - &iio_dev_attr_filter_rate_setup.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad7152_attribute_group = { - .attrs = ad7152_attributes, -}; - -static const struct iio_info ad7152_info = { - .attrs = &ad7152_attribute_group, - .driver_module = THIS_MODULE, -}; -/* - * device probe and remove - */ - -static int __devinit 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; - } - chip = iio_priv(indio_dev); - /* this is only used for device removal purposes */ - i2c_set_clientdata(client, indio_dev); - - chip->client = client; - - /* Echipabilish that the iio_dev is a child of the i2c device */ - indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; - indio_dev->info = &ad7152_info; - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - - 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) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - - iio_device_unregister(indio_dev); - - return 0; -} - -static const struct i2c_device_id ad7152_id[] = { - { "ad7152", 0 }, - { "ad7153", 0 }, - {} -}; - -MODULE_DEVICE_TABLE(i2c, ad7152_id); - -static struct i2c_driver ad7152_driver = { - .driver = { - .name = "ad7152", - }, - .probe = ad7152_probe, - .remove = __devexit_p(ad7152_remove), - .id_table = ad7152_id, -}; - -static __init int ad7152_init(void) -{ - return i2c_add_driver(&ad7152_driver); -} - -static __exit void ad7152_exit(void) -{ - i2c_del_driver(&ad7152_driver); -} - -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_DESCRIPTION("Analog Devices ad7152/3 capacitive sensor driver"); -MODULE_LICENSE("GPL v2"); - -module_init(ad7152_init); -module_exit(ad7152_exit); diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c new file mode 100644 index 0000000..31c376b --- /dev/null +++ b/drivers/staging/iio/adc/ad7192.c @@ -0,0 +1,1179 @@ +/* + * AD7190 AD7192 AD7195 SPI ADC driver + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include <linux/interrupt.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/sysfs.h> +#include <linux/spi/spi.h> +#include <linux/regulator/consumer.h> +#include <linux/err.h> +#include <linux/sched.h> +#include <linux/delay.h> + +#include "../iio.h" +#include "../sysfs.h" +#include "../buffer_generic.h" +#include "../ring_sw.h" +#include "../trigger.h" +#include "../trigger_consumer.h" + +#include "ad7192.h" + +/* Registers */ +#define AD7192_REG_COMM 0 /* Communications Register (WO, 8-bit) */ +#define AD7192_REG_STAT 0 /* Status Register (RO, 8-bit) */ +#define AD7192_REG_MODE 1 /* Mode Register (RW, 24-bit */ +#define AD7192_REG_CONF 2 /* Configuration Register (RW, 24-bit) */ +#define AD7192_REG_DATA 3 /* Data Register (RO, 24/32-bit) */ +#define AD7192_REG_ID 4 /* ID Register (RO, 8-bit) */ +#define AD7192_REG_GPOCON 5 /* GPOCON Register (RO, 8-bit) */ +#define AD7192_REG_OFFSET 6 /* Offset Register (RW, 16-bit + * (AD7792)/24-bit (AD7192)) */ +#define AD7192_REG_FULLSALE 7 /* Full-Scale Register + * (RW, 16-bit (AD7792)/24-bit (AD7192)) */ + +/* Communications Register Bit Designations (AD7192_REG_COMM) */ +#define AD7192_COMM_WEN (1 << 7) /* Write Enable */ +#define AD7192_COMM_WRITE (0 << 6) /* Write Operation */ +#define AD7192_COMM_READ (1 << 6) /* Read Operation */ +#define AD7192_COMM_ADDR(x) (((x) & 0x7) << 3) /* Register Address */ +#define AD7192_COMM_CREAD (1 << 2) /* Continuous Read of Data Register */ + +/* Status Register Bit Designations (AD7192_REG_STAT) */ +#define AD7192_STAT_RDY (1 << 7) /* Ready */ +#define AD7192_STAT_ERR (1 << 6) /* Error (Overrange, Underrange) */ +#define AD7192_STAT_NOREF (1 << 5) /* Error no external reference */ +#define AD7192_STAT_PARITY (1 << 4) /* Parity */ +#define AD7192_STAT_CH3 (1 << 2) /* Channel 3 */ +#define AD7192_STAT_CH2 (1 << 1) /* Channel 2 */ +#define AD7192_STAT_CH1 (1 << 0) /* Channel 1 */ + +/* Mode Register Bit Designations (AD7192_REG_MODE) */ +#define AD7192_MODE_SEL(x) (((x) & 0x7) << 21) /* Operation Mode Select */ +#define AD7192_MODE_DAT_STA (1 << 20) /* Status Register transmission */ +#define AD7192_MODE_CLKSRC(x) (((x) & 0x3) << 18) /* Clock Source Select */ +#define AD7192_MODE_SINC3 (1 << 15) /* SINC3 Filter Select */ +#define AD7192_MODE_ACX (1 << 14) /* AC excitation enable(AD7195 only)*/ +#define AD7192_MODE_ENPAR (1 << 13) /* Parity Enable */ +#define AD7192_MODE_CLKDIV (1 << 12) /* Clock divide by 2 (AD7190/2 only)*/ +#define AD7192_MODE_SCYCLE (1 << 11) /* Single cycle conversion */ +#define AD7192_MODE_REJ60 (1 << 10) /* 50/60Hz notch filter */ +#define AD7192_MODE_RATE(x) ((x) & 0x3FF) /* Filter Update Rate Select */ + +/* Mode Register: AD7192_MODE_SEL options */ +#define AD7192_MODE_CONT 0 /* Continuous Conversion Mode */ +#define AD7192_MODE_SINGLE 1 /* Single Conversion Mode */ +#define AD7192_MODE_IDLE 2 /* Idle Mode */ +#define AD7192_MODE_PWRDN 3 /* Power-Down Mode */ +#define AD7192_MODE_CAL_INT_ZERO 4 /* Internal Zero-Scale Calibration */ +#define AD7192_MODE_CAL_INT_FULL 5 /* Internal Full-Scale Calibration */ +#define AD7192_MODE_CAL_SYS_ZERO 6 /* System Zero-Scale Calibration */ +#define AD7192_MODE_CAL_SYS_FULL 7 /* System Full-Scale Calibration */ + +/* Mode Register: AD7192_MODE_CLKSRC options */ +#define AD7192_CLK_EXT_MCLK1_2 0 /* External 4.92 MHz Clock connected + * from MCLK1 to MCLK2 */ +#define AD7192_CLK_EXT_MCLK2 1 /* External Clock applied to MCLK2 */ +#define AD7192_CLK_INT 2 /* Internal 4.92 MHz Clock not + * available at the MCLK2 pin */ +#define AD7192_CLK_INT_CO 3 /* Internal 4.92 MHz Clock available + * at the MCLK2 pin */ + + +/* Configuration Register Bit Designations (AD7192_REG_CONF) */ + +#define AD7192_CONF_CHOP (1 << 23) /* CHOP enable */ +#define AD7192_CONF_REFSEL (1 << 20) /* REFIN1/REFIN2 Reference Select */ +#define AD7192_CONF_CHAN(x) (((x) & 0xFF) << 8) /* Channel select */ +#define AD7192_CONF_BURN (1 << 7) /* Burnout current enable */ +#define AD7192_CONF_REFDET (1 << 6) /* Reference detect enable */ +#define AD7192_CONF_BUF (1 << 4) /* Buffered Mode Enable */ +#define AD7192_CONF_UNIPOLAR (1 << 3) /* Unipolar/Bipolar Enable */ +#define AD7192_CONF_GAIN(x) ((x) & 0x7) /* Gain Select */ + +#define AD7192_CH_AIN1P_AIN2M 0 /* AIN1(+) - AIN2(-) */ +#define AD7192_CH_AIN3P_AIN4M 1 /* AIN3(+) - AIN4(-) */ +#define AD7192_CH_TEMP 2 /* Temp Sensor */ +#define AD7192_CH_AIN2P_AIN2M 3 /* AIN2(+) - AIN2(-) */ +#define AD7192_CH_AIN1 4 /* AIN1 - AINCOM */ +#define AD7192_CH_AIN2 5 /* AIN2 - AINCOM */ +#define AD7192_CH_AIN3 6 /* AIN3 - AINCOM */ +#define AD7192_CH_AIN4 7 /* AIN4 - AINCOM */ + +/* ID Register Bit Designations (AD7192_REG_ID) */ +#define ID_AD7190 0x4 +#define ID_AD7192 0x0 +#define ID_AD7195 0x6 +#define AD7192_ID_MASK 0x0F + +/* GPOCON Register Bit Designations (AD7192_REG_GPOCON) */ +#define AD7192_GPOCON_BPDSW (1 << 6) /* Bridge power-down switch enable */ +#define AD7192_GPOCON_GP32EN (1 << 5) /* Digital Output P3 and P2 enable */ +#define AD7192_GPOCON_GP10EN (1 << 4) /* Digital Output P1 and P0 enable */ +#define AD7192_GPOCON_P3DAT (1 << 3) /* P3 state */ +#define AD7192_GPOCON_P2DAT (1 << 2) /* P2 state */ +#define AD7192_GPOCON_P1DAT (1 << 1) /* P1 state */ +#define AD7192_GPOCON_P0DAT (1 << 0) /* P0 state */ + +#define AD7192_INT_FREQ_MHz 4915200 + +/* NOTE: + * The AD7190/2/5 features a dual use data out ready DOUT/RDY output. + * In order to avoid contentions on the SPI bus, it's therefore necessary + * to use spi bus locking. + * + * The DOUT/RDY output must also be wired to an interrupt capable GPIO. + */ + +struct ad7192_state { + struct spi_device *spi; + struct iio_trigger *trig; + struct regulator *reg; + struct ad7192_platform_data *pdata; + wait_queue_head_t wq_data_avail; + bool done; + bool irq_dis; + u16 int_vref_mv; + u32 mclk; + u32 f_order; + u32 mode; + u32 conf; + u32 scale_avail[8][2]; + 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; +}; + +static int __ad7192_write_reg(struct ad7192_state *st, bool locked, + bool cs_change, unsigned char reg, + unsigned size, unsigned val) +{ + u8 *data = st->data; + struct spi_transfer t = { + .tx_buf = data, + .len = size + 1, + .cs_change = cs_change, + }; + struct spi_message m; + + data[0] = AD7192_COMM_WRITE | AD7192_COMM_ADDR(reg); + + switch (size) { + case 3: + data[1] = val >> 16; + data[2] = val >> 8; + data[3] = val; + break; + case 2: + data[1] = val >> 8; + data[2] = val; + break; + case 1: + data[1] = val; + break; + default: + return -EINVAL; + } + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + + if (locked) + return spi_sync_locked(st->spi, &m); + else + return spi_sync(st->spi, &m); +} + +static int ad7192_write_reg(struct ad7192_state *st, + unsigned reg, unsigned size, unsigned val) +{ + return __ad7192_write_reg(st, false, false, reg, size, val); +} + +static int __ad7192_read_reg(struct ad7192_state *st, bool locked, + bool cs_change, unsigned char reg, + int *val, unsigned size) +{ + u8 *data = st->data; + int ret; + struct spi_transfer t[] = { + { + .tx_buf = data, + .len = 1, + }, { + .rx_buf = data, + .len = size, + .cs_change = cs_change, + }, + }; + struct spi_message m; + + data[0] = AD7192_COMM_READ | AD7192_COMM_ADDR(reg); + + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + spi_message_add_tail(&t[1], &m); + + if (locked) + ret = spi_sync_locked(st->spi, &m); + else + ret = spi_sync(st->spi, &m); + + if (ret < 0) + return ret; + + switch (size) { + case 3: + *val = data[0] << 16 | data[1] << 8 | data[2]; + break; + case 2: + *val = data[0] << 8 | data[1]; + break; + case 1: + *val = data[0]; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ad7192_read_reg(struct ad7192_state *st, + unsigned reg, int *val, unsigned size) +{ + return __ad7192_read_reg(st, 0, 0, reg, val, size); +} + +static int ad7192_read(struct ad7192_state *st, unsigned ch, + unsigned len, int *val) +{ + int ret; + st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) | + AD7192_CONF_CHAN(1 << ch); + st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | + AD7192_MODE_SEL(AD7192_MODE_SINGLE); + + ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf); + + spi_bus_lock(st->spi->master); + st->done = false; + + ret = __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, st->mode); + if (ret < 0) + goto out; + + st->irq_dis = false; + enable_irq(st->spi->irq); + wait_event_interruptible(st->wq_data_avail, st->done); + + ret = __ad7192_read_reg(st, 1, 0, AD7192_REG_DATA, val, len); +out: + spi_bus_unlock(st->spi->master); + + return ret; +} + +static int ad7192_calibrate(struct ad7192_state *st, unsigned mode, unsigned ch) +{ + int ret; + + st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) | + AD7192_CONF_CHAN(1 << ch); + st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | AD7192_MODE_SEL(mode); + + ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf); + + spi_bus_lock(st->spi->master); + st->done = false; + + ret = __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, + (st->devid != ID_AD7195) ? + st->mode | AD7192_MODE_CLKDIV : + st->mode); + if (ret < 0) + goto out; + + st->irq_dis = false; + enable_irq(st->spi->irq); + wait_event_interruptible(st->wq_data_avail, st->done); + + st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | + AD7192_MODE_SEL(AD7192_MODE_IDLE); + + ret = __ad7192_write_reg(st, 1, 0, AD7192_REG_MODE, 3, st->mode); +out: + spi_bus_unlock(st->spi->master); + + return ret; +} + +static const u8 ad7192_calib_arr[8][2] = { + {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN1}, + {AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN1}, + {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN2}, + {AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN2}, + {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN3}, + {AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN3}, + {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN4}, + {AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN4} +}; + +static int ad7192_calibrate_all(struct ad7192_state *st) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(ad7192_calib_arr); i++) { + ret = ad7192_calibrate(st, ad7192_calib_arr[i][0], + ad7192_calib_arr[i][1]); + if (ret) + goto out; + } + + return 0; +out: + dev_err(&st->spi->dev, "Calibration failed\n"); + return ret; +} + +static int ad7192_setup(struct ad7192_state *st) +{ + struct iio_dev *indio_dev = spi_get_drvdata(st->spi); + struct ad7192_platform_data *pdata = st->pdata; + unsigned long long scale_uv; + int i, ret, id; + u8 ones[6]; + + /* reset the serial interface */ + memset(&ones, 0xFF, 6); + ret = spi_write(st->spi, &ones, 6); + if (ret < 0) + goto out; + msleep(1); /* Wait for at least 500us */ + + /* write/read test for device presence */ + ret = ad7192_read_reg(st, AD7192_REG_ID, &id, 1); + if (ret) + goto out; + + id &= AD7192_ID_MASK; + + if (id != st->devid) + dev_warn(&st->spi->dev, "device ID query failed (0x%X)\n", id); + + switch (pdata->clock_source_sel) { + case AD7192_CLK_EXT_MCLK1_2: + case AD7192_CLK_EXT_MCLK2: + st->mclk = AD7192_INT_FREQ_MHz; + break; + case AD7192_CLK_INT: + case AD7192_CLK_INT_CO: + if (pdata->ext_clk_Hz) + st->mclk = pdata->ext_clk_Hz; + else + st->mclk = AD7192_INT_FREQ_MHz; + break; + default: + ret = -EINVAL; + goto out; + } + + st->mode = AD7192_MODE_SEL(AD7192_MODE_IDLE) | + AD7192_MODE_CLKSRC(pdata->clock_source_sel) | + AD7192_MODE_RATE(480); + + st->conf = AD7192_CONF_GAIN(0); + + if (pdata->rej60_en) + st->mode |= AD7192_MODE_REJ60; + + if (pdata->sinc3_en) + st->mode |= AD7192_MODE_SINC3; + + if (pdata->refin2_en && (st->devid != ID_AD7195)) + st->conf |= AD7192_CONF_REFSEL; + + if (pdata->chop_en) { + st->conf |= AD7192_CONF_CHOP; + if (pdata->sinc3_en) + st->f_order = 3; /* SINC 3rd order */ + else + st->f_order = 4; /* SINC 4th order */ + } else { + st->f_order = 1; + } + + if (pdata->buf_en) + st->conf |= AD7192_CONF_BUF; + + if (pdata->unipolar_en) + st->conf |= AD7192_CONF_UNIPOLAR; + + if (pdata->burnout_curr_en) + st->conf |= AD7192_CONF_BURN; + + ret = ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode); + if (ret) + goto out; + + ret = ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf); + if (ret) + goto out; + + ret = ad7192_calibrate_all(st); + if (ret) + goto out; + + /* Populate available ADC input ranges */ + for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) { + scale_uv = ((u64)st->int_vref_mv * 100000000) + >> (indio_dev->channels[0].scan_type.realbits - + ((st->conf & AD7192_CONF_UNIPOLAR) ? 0 : 1)); + scale_uv >>= i; + + st->scale_avail[i][1] = do_div(scale_uv, 100000000) * 10; + st->scale_avail[i][0] = scale_uv; + } + + return 0; +out: + dev_err(&st->spi->dev, "setup failed\n"); + return ret; +} + +static int ad7192_scan_from_ring(struct ad7192_state *st, unsigned ch, int *val) +{ + struct iio_buffer *ring = iio_priv_to_dev(st)->buffer; + int ret; + s64 dat64[2]; + u32 *dat32 = (u32 *)dat64; + + if (!(test_bit(ch, ring->scan_mask))) + return -EBUSY; + + ret = ring->access->read_last(ring, (u8 *) &dat64); + if (ret) + return ret; + + *val = *dat32; + + return 0; +} + +static int ad7192_ring_preenable(struct iio_dev *indio_dev) +{ + struct ad7192_state *st = iio_priv(indio_dev); + struct iio_buffer *ring = indio_dev->buffer; + size_t d_size; + unsigned channel; + + if (!ring->scan_count) + return -EINVAL; + + channel = find_first_bit(ring->scan_mask, indio_dev->masklength); + + d_size = ring->scan_count * + indio_dev->channels[0].scan_type.storagebits / 8; + + if (ring->scan_timestamp) { + d_size += sizeof(s64); + + if (d_size % sizeof(s64)) + d_size += sizeof(s64) - (d_size % sizeof(s64)); + } + + if (indio_dev->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 (ring->scan_count) + __ad7192_read_reg(st, 1, 1, AD7192_REG_DATA, + dat32, + indio_dev->channels[0].scan_type.realbits/8); + + /* Guaranteed to be aligned with 8 byte boundary */ + if (ring->scan_timestamp) + dat64[1] = pf->timestamp; + + ring->access->store_to(ring, (u8 *)dat64, pf->timestamp); + + iio_trigger_notify_done(indio_dev->trig); + st->irq_dis = false; + enable_irq(st->spi->irq); + + return IRQ_HANDLED; +} + +static const struct iio_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->buffer->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: + 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 int ad7192_probe_trigger(struct iio_dev *indio_dev) +{ + struct ad7192_state *st = iio_priv(indio_dev); + int ret; + + st->trig = iio_allocate_trigger("%s-dev%d", + spi_get_device_id(st->spi)->name, + indio_dev->id); + if (st->trig == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + ret = request_irq(st->spi->irq, + ad7192_data_rdy_trig_poll, + IRQF_TRIGGER_LOW, + spi_get_device_id(st->spi)->name, + indio_dev); + if (ret) + goto error_free_trig; + + disable_irq_nosync(st->spi->irq); + st->irq_dis = true; + st->trig->dev.parent = &st->spi->dev; + st->trig->owner = THIS_MODULE; + st->trig->private_data = indio_dev; + + ret = iio_trigger_register(st->trig); + + /* select default trigger */ + indio_dev->trig = st->trig; + if (ret) + goto error_free_irq; + + return 0; + +error_free_irq: + free_irq(st->spi->irq, indio_dev); +error_free_trig: + iio_free_trigger(st->trig); +error_ret: + return ret; +} + +static void ad7192_remove_trigger(struct iio_dev *indio_dev) +{ + struct ad7192_state *st = iio_priv(indio_dev); + + iio_trigger_unregister(st->trig); + free_irq(st->spi->irq, indio_dev); + iio_free_trigger(st->trig); +} + +static ssize_t ad7192_read_frequency(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7192_state *st = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", st->mclk / + (st->f_order * 1024 * AD7192_MODE_RATE(st->mode))); +} + +static ssize_t ad7192_write_frequency(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7192_state *st = iio_priv(indio_dev); + unsigned long lval; + int div, ret; + + ret = strict_strtoul(buf, 10, &lval); + if (ret) + return ret; + + mutex_lock(&indio_dev->mlock); + if (iio_buffer_enabled(indio_dev)) { + mutex_unlock(&indio_dev->mlock); + return -EBUSY; + } + + div = st->mclk / (lval * st->f_order * 1024); + if (div < 1 || div > 1023) { + ret = -EINVAL; + goto out; + } + + st->mode &= ~AD7192_MODE_RATE(-1); + st->mode |= AD7192_MODE_RATE(div); + ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode); + +out: + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, + ad7192_read_frequency, + ad7192_write_frequency); + + +static ssize_t ad7192_show_scale_available(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7192_state *st = iio_priv(indio_dev); + int i, len = 0; + + for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) + len += sprintf(buf + len, "%d.%09u ", st->scale_avail[i][0], + st->scale_avail[i][1]); + + len += sprintf(buf + len, "\n"); + + return len; +} + +static IIO_DEVICE_ATTR_NAMED(in_v_m_v_scale_available, + in_voltage-voltage_scale_available, + S_IRUGO, ad7192_show_scale_available, NULL, 0); + +static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO, + ad7192_show_scale_available, NULL, 0); + +static ssize_t ad7192_show_ac_excitation(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7192_state *st = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", !!(st->mode & AD7192_MODE_ACX)); +} + +static ssize_t ad7192_show_bridge_switch(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7192_state *st = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", !!(st->gpocon & AD7192_GPOCON_BPDSW)); +} + +static ssize_t ad7192_set(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7192_state *st = iio_priv(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + bool val; + + ret = strtobool(buf, &val); + if (ret < 0) + return ret; + + mutex_lock(&indio_dev->mlock); + if (iio_buffer_enabled(indio_dev)) { + mutex_unlock(&indio_dev->mlock); + return -EBUSY; + } + + switch (this_attr->address) { + case AD7192_REG_GPOCON: + if (val) + st->gpocon |= AD7192_GPOCON_BPDSW; + else + st->gpocon &= ~AD7192_GPOCON_BPDSW; + + ad7192_write_reg(st, AD7192_REG_GPOCON, 1, st->gpocon); + break; + case AD7192_REG_MODE: + if (val) + st->mode |= AD7192_MODE_ACX; + else + st->mode &= ~AD7192_MODE_ACX; + + ad7192_write_reg(st, AD7192_REG_GPOCON, 3, st->mode); + break; + default: + ret = -EINVAL; + } + + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static IIO_DEVICE_ATTR(bridge_switch_en, S_IRUGO | S_IWUSR, + ad7192_show_bridge_switch, ad7192_set, + AD7192_REG_GPOCON); + +static IIO_DEVICE_ATTR(ac_excitation_en, S_IRUGO | S_IWUSR, + ad7192_show_ac_excitation, ad7192_set, + AD7192_REG_MODE); + +static struct attribute *ad7192_attributes[] = { + &iio_dev_attr_sampling_frequency.dev_attr.attr, + &iio_dev_attr_in_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, + &iio_dev_attr_ac_excitation_en.dev_attr.attr, + NULL +}; + +static mode_t ad7192_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7192_state *st = iio_priv(indio_dev); + + mode_t mode = attr->mode; + + if ((st->devid != ID_AD7195) && + (attr == &iio_dev_attr_ac_excitation_en.dev_attr.attr)) + mode = 0; + + return mode; +} + +static const struct attribute_group ad7192_attribute_group = { + .attrs = ad7192_attributes, + .is_visible = ad7192_attr_is_visible, +}; + +static int ad7192_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad7192_state *st = iio_priv(indio_dev); + int ret, smpl = 0; + bool unipolar = !!(st->conf & AD7192_CONF_UNIPOLAR); + + switch (m) { + case 0: + mutex_lock(&indio_dev->mlock); + if (iio_buffer_enabled(indio_dev)) + ret = ad7192_scan_from_ring(st, + chan->scan_index, &smpl); + else + ret = ad7192_read(st, chan->address, + chan->scan_type.realbits / 8, &smpl); + mutex_unlock(&indio_dev->mlock); + + if (ret < 0) + return ret; + + *val = (smpl >> chan->scan_type.shift) & + ((1 << (chan->scan_type.realbits)) - 1); + + switch (chan->type) { + case IIO_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 (1 << IIO_CHAN_INFO_SCALE_SHARED): + mutex_lock(&indio_dev->mlock); + *val = st->scale_avail[AD7192_CONF_GAIN(st->conf)][0]; + *val2 = st->scale_avail[AD7192_CONF_GAIN(st->conf)][1]; + mutex_unlock(&indio_dev->mlock); + + return IIO_VAL_INT_PLUS_NANO; + + case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + *val = 1000; + + return IIO_VAL_INT; + } + + return -EINVAL; +} + +static int ad7192_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad7192_state *st = iio_priv(indio_dev); + int ret, i; + unsigned int tmp; + + mutex_lock(&indio_dev->mlock); + if (iio_buffer_enabled(indio_dev)) { + mutex_unlock(&indio_dev->mlock); + return -EBUSY; + } + + switch (mask) { + case (1 << IIO_CHAN_INFO_SCALE_SHARED): + ret = -EINVAL; + for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) + if (val2 == st->scale_avail[i][1]) { + tmp = st->conf; + st->conf &= ~AD7192_CONF_GAIN(-1); + st->conf |= AD7192_CONF_GAIN(i); + + if (tmp != st->conf) { + ad7192_write_reg(st, AD7192_REG_CONF, + 3, st->conf); + ad7192_calibrate_all(st); + } + ret = 0; + } + + default: + ret = -EINVAL; + } + + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int ad7192_validate_trigger(struct iio_dev *indio_dev, + struct iio_trigger *trig) +{ + if (indio_dev->trig != trig) + return -EINVAL; + + return 0; +} + +static int ad7192_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask) +{ + return IIO_VAL_INT_PLUS_NANO; +} + +static const struct iio_info ad7192_info = { + .read_raw = &ad7192_read_raw, + .write_raw = &ad7192_write_raw, + .write_raw_get_fmt = &ad7192_write_raw_get_fmt, + .attrs = &ad7192_attribute_group, + .validate_trigger = ad7192_validate_trigger, + .driver_module = THIS_MODULE, +}; + +#define AD7192_CHAN_DIFF(_chan, _chan2, _name, _address, _si) \ + { .type = IIO_VOLTAGE, \ + .differential = 1, \ + .indexed = 1, \ + .extend_name = _name, \ + .channel = _chan, \ + .channel2 = _chan2, \ + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \ + .address = _address, \ + .scan_index = _si, \ + .scan_type = IIO_ST('s', 24, 32, 0)} + +#define AD7192_CHAN(_chan, _address, _si) \ + { .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = _chan, \ + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \ + .address = _address, \ + .scan_index = _si, \ + .scan_type = IIO_ST('s', 24, 32, 0)} + +#define AD7192_CHAN_TEMP(_chan, _address, _si) \ + { .type = IIO_TEMP, \ + .indexed = 1, \ + .channel = _chan, \ + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \ + .address = _address, \ + .scan_index = _si, \ + .scan_type = IIO_ST('s', 24, 32, 0)} + +static struct iio_chan_spec ad7192_channels[] = { + AD7192_CHAN_DIFF(1, 2, NULL, AD7192_CH_AIN1P_AIN2M, 0), + AD7192_CHAN_DIFF(3, 4, NULL, AD7192_CH_AIN3P_AIN4M, 1), + AD7192_CHAN_TEMP(0, AD7192_CH_TEMP, 2), + AD7192_CHAN_DIFF(2, 2, "shorted", AD7192_CH_AIN2P_AIN2M, 3), + AD7192_CHAN(1, AD7192_CH_AIN1, 4), + AD7192_CHAN(2, AD7192_CH_AIN2, 5), + AD7192_CHAN(3, AD7192_CH_AIN3, 6), + AD7192_CHAN(4, AD7192_CH_AIN4, 7), + IIO_CHAN_SOFT_TIMESTAMP(8), +}; + +static int __devinit ad7192_probe(struct spi_device *spi) +{ + struct ad7192_platform_data *pdata = spi->dev.platform_data; + struct ad7192_state *st; + struct iio_dev *indio_dev; + int ret, i , voltage_uv = 0; + + if (!pdata) { + dev_err(&spi->dev, "no platform data?\n"); + return -ENODEV; + } + + if (!spi->irq) { + dev_err(&spi->dev, "no IRQ?\n"); + return -ENODEV; + } + + indio_dev = iio_allocate_device(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + + st->reg = regulator_get(&spi->dev, "vcc"); + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) + goto error_put_reg; + + voltage_uv = regulator_get_voltage(st->reg); + } + + st->pdata = pdata; + + if (pdata && pdata->vref_mv) + st->int_vref_mv = pdata->vref_mv; + else if (voltage_uv) + st->int_vref_mv = voltage_uv / 1000; + else + dev_warn(&spi->dev, "reference voltage undefined\n"); + + spi_set_drvdata(spi, indio_dev); + st->spi = spi; + st->devid = spi_get_device_id(spi)->driver_data; + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ad7192_channels; + indio_dev->num_channels = ARRAY_SIZE(ad7192_channels); + indio_dev->available_scan_masks = st->available_scan_masks; + indio_dev->info = &ad7192_info; + + for (i = 0; i < indio_dev->num_channels; i++) + st->available_scan_masks[i] = (1 << i) | (1 << + indio_dev->channels[indio_dev->num_channels - 1]. + scan_index); + + init_waitqueue_head(&st->wq_data_avail); + + ret = ad7192_register_ring_funcs_and_init(indio_dev); + if (ret) + goto error_disable_reg; + + ret = ad7192_probe_trigger(indio_dev); + if (ret) + goto error_ring_cleanup; + + ret = iio_buffer_register(indio_dev, + indio_dev->channels, + indio_dev->num_channels); + 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; + 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); +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 ad7192_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(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); + + if (!IS_ERR(st->reg)) { + regulator_disable(st->reg); + regulator_put(st->reg); + } + + return 0; +} + +static const struct spi_device_id ad7192_id[] = { + {"ad7190", ID_AD7190}, + {"ad7192", ID_AD7192}, + {"ad7195", ID_AD7195}, + {} +}; + +static struct spi_driver ad7192_driver = { + .driver = { + .name = "ad7192", + .owner = THIS_MODULE, + }, + .probe = ad7192_probe, + .remove = __devexit_p(ad7192_remove), + .id_table = ad7192_id, +}; + +static int __init ad7192_init(void) +{ + return spi_register_driver(&ad7192_driver); +} +module_init(ad7192_init); + +static void __exit ad7192_exit(void) +{ + spi_unregister_driver(&ad7192_driver); +} +module_exit(ad7192_exit); + +MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); +MODULE_DESCRIPTION("Analog Devices AD7190, AD7192, AD7195 ADC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/ad7192.h b/drivers/staging/iio/adc/ad7192.h new file mode 100644 index 0000000..a0a5b61 --- /dev/null +++ b/drivers/staging/iio/adc/ad7192.h @@ -0,0 +1,47 @@ +/* + * AD7190 AD7192 AD7195 SPI ADC driver + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ +#ifndef IIO_ADC_AD7192_H_ +#define IIO_ADC_AD7192_H_ + +/* + * TODO: struct ad7192_platform_data needs to go into include/linux/iio + */ + +/** + * struct ad7192_platform_data - platform/board specific information + * @vref_mv: the external reference voltage in millivolt + * @clock_source_sel: [0..3] + * 0 External 4.92 MHz clock connected from MCLK1 to MCLK2 + * 1 External Clock applied to MCLK2 + * 2 Internal 4.92 MHz Clock not available at the MCLK2 pin + * 3 Internal 4.92 MHz Clock available at the MCLK2 pin + * @ext_clk_Hz: the external clock frequency in Hz, if not set + * the driver uses the internal clock (16.776 MHz) + * @refin2_en: REFIN1/REFIN2 Reference Select (AD7190/2 only) + * @rej60_en: 50/60Hz notch filter enable + * @sinc3_en: SINC3 filter enable (default SINC4) + * @chop_en: CHOP mode enable + * @buf_en: buffered input mode enable + * @unipolar_en: unipolar mode enable + * @burnout_curr_en: constant current generators on AIN(+|-) enable + */ + +struct ad7192_platform_data { + u16 vref_mv; + u8 clock_source_sel; + u32 ext_clk_Hz; + bool refin2_en; + bool rej60_en; + bool sinc3_en; + bool chop_en; + bool buf_en; + bool unipolar_en; + bool burnout_curr_en; +}; + +#endif /* IIO_ADC_AD7192_H_ */ diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c new file mode 100644 index 0000000..372d059 --- /dev/null +++ b/drivers/staging/iio/adc/ad7280a.c @@ -0,0 +1,997 @@ +/* + * AD7280A Lithium Ion Battery Monitoring System + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/sysfs.h> +#include <linux/spi/spi.h> +#include <linux/err.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/module.h> + +#include "../iio.h" +#include "../sysfs.h" + +#include "ad7280a.h" + +/* Registers */ +#define AD7280A_CELL_VOLTAGE_1 0x0 /* D11 to D0, Read only */ +#define AD7280A_CELL_VOLTAGE_2 0x1 /* D11 to D0, Read only */ +#define AD7280A_CELL_VOLTAGE_3 0x2 /* D11 to D0, Read only */ +#define AD7280A_CELL_VOLTAGE_4 0x3 /* D11 to D0, Read only */ +#define AD7280A_CELL_VOLTAGE_5 0x4 /* D11 to D0, Read only */ +#define AD7280A_CELL_VOLTAGE_6 0x5 /* D11 to D0, Read only */ +#define AD7280A_AUX_ADC_1 0x6 /* D11 to D0, Read only */ +#define AD7280A_AUX_ADC_2 0x7 /* D11 to D0, Read only */ +#define AD7280A_AUX_ADC_3 0x8 /* D11 to D0, Read only */ +#define AD7280A_AUX_ADC_4 0x9 /* D11 to D0, Read only */ +#define AD7280A_AUX_ADC_5 0xA /* D11 to D0, Read only */ +#define AD7280A_AUX_ADC_6 0xB /* D11 to D0, Read only */ +#define AD7280A_SELF_TEST 0xC /* D11 to D0, Read only */ +#define AD7280A_CONTROL_HB 0xD /* D15 to D8, Read/write */ +#define AD7280A_CONTROL_LB 0xE /* D7 to D0, Read/write */ +#define AD7280A_CELL_OVERVOLTAGE 0xF /* D7 to D0, Read/write */ +#define AD7280A_CELL_UNDERVOLTAGE 0x10 /* D7 to D0, Read/write */ +#define AD7280A_AUX_ADC_OVERVOLTAGE 0x11 /* D7 to D0, Read/write */ +#define AD7280A_AUX_ADC_UNDERVOLTAGE 0x12 /* D7 to D0, Read/write */ +#define AD7280A_ALERT 0x13 /* D7 to D0, Read/write */ +#define AD7280A_CELL_BALANCE 0x14 /* D7 to D0, Read/write */ +#define AD7280A_CB1_TIMER 0x15 /* D7 to D0, Read/write */ +#define AD7280A_CB2_TIMER 0x16 /* D7 to D0, Read/write */ +#define AD7280A_CB3_TIMER 0x17 /* D7 to D0, Read/write */ +#define AD7280A_CB4_TIMER 0x18 /* D7 to D0, Read/write */ +#define AD7280A_CB5_TIMER 0x19 /* D7 to D0, Read/write */ +#define AD7280A_CB6_TIMER 0x1A /* D7 to D0, Read/write */ +#define AD7280A_PD_TIMER 0x1B /* D7 to D0, Read/write */ +#define AD7280A_READ 0x1C /* D7 to D0, Read/write */ +#define AD7280A_CNVST_CONTROL 0x1D /* D7 to D0, Read/write */ + +/* Bits and Masks */ +#define AD7280A_CTRL_HB_CONV_INPUT_ALL (0 << 6) +#define AD7280A_CTRL_HB_CONV_INPUT_6CELL_AUX1_3_4 (1 << 6) +#define AD7280A_CTRL_HB_CONV_INPUT_6CELL (2 << 6) +#define AD7280A_CTRL_HB_CONV_INPUT_SELF_TEST (3 << 6) +#define AD7280A_CTRL_HB_CONV_RES_READ_ALL (0 << 4) +#define AD7280A_CTRL_HB_CONV_RES_READ_6CELL_AUX1_3_4 (1 << 4) +#define AD7280A_CTRL_HB_CONV_RES_READ_6CELL (2 << 4) +#define AD7280A_CTRL_HB_CONV_RES_READ_NO (3 << 4) +#define AD7280A_CTRL_HB_CONV_START_CNVST (0 << 3) +#define AD7280A_CTRL_HB_CONV_START_CS (1 << 3) +#define AD7280A_CTRL_HB_CONV_AVG_DIS (0 << 1) +#define AD7280A_CTRL_HB_CONV_AVG_2 (1 << 1) +#define AD7280A_CTRL_HB_CONV_AVG_4 (2 << 1) +#define AD7280A_CTRL_HB_CONV_AVG_8 (3 << 1) +#define AD7280A_CTRL_HB_CONV_AVG(x) ((x) << 1) +#define AD7280A_CTRL_HB_PWRDN_SW (1 << 0) + +#define AD7280A_CTRL_LB_SWRST (1 << 7) +#define AD7280A_CTRL_LB_ACQ_TIME_400ns (0 << 5) +#define AD7280A_CTRL_LB_ACQ_TIME_800ns (1 << 5) +#define AD7280A_CTRL_LB_ACQ_TIME_1200ns (2 << 5) +#define AD7280A_CTRL_LB_ACQ_TIME_1600ns (3 << 5) +#define AD7280A_CTRL_LB_ACQ_TIME(x) ((x) << 5) +#define AD7280A_CTRL_LB_MUST_SET (1 << 4) +#define AD7280A_CTRL_LB_THERMISTOR_EN (1 << 3) +#define AD7280A_CTRL_LB_LOCK_DEV_ADDR (1 << 2) +#define AD7280A_CTRL_LB_INC_DEV_ADDR (1 << 1) +#define AD7280A_CTRL_LB_DAISY_CHAIN_RB_EN (1 << 0) + +#define AD7280A_ALERT_GEN_STATIC_HIGH (1 << 6) +#define AD7280A_ALERT_RELAY_SIG_CHAIN_DOWN (3 << 6) + +#define AD7280A_ALL_CELLS (0xAD << 16) + +#define AD7280A_MAX_SPI_CLK_Hz 700000 /* < 1MHz */ +#define AD7280A_MAX_CHAIN 8 +#define AD7280A_CELLS_PER_DEV 6 +#define AD7280A_BITS 12 +#define AD7280A_NUM_CH (AD7280A_AUX_ADC_6 - \ + AD7280A_CELL_VOLTAGE_1 + 1) + +#define AD7280A_DEVADDR_MASTER 0 +#define AD7280A_DEVADDR_ALL 0x1F +/* 5-bit device address is sent LSB first */ +#define AD7280A_DEVADDR(addr) (((addr & 0x1) << 4) | ((addr & 0x2) << 3) | \ + (addr & 0x4) | ((addr & 0x8) >> 3) | \ + ((addr & 0x10) >> 4)) + +/* During a read a valid write is mandatory. + * So writing to the highest available address (Address 0x1F) + * and setting the address all parts bit to 0 is recommended + * So the TXVAL is AD7280A_DEVADDR_ALL + CRC + */ +#define AD7280A_READ_TXVAL 0xF800030A + +/* + * AD7280 CRC + * + * P(x) = x^8 + x^5 + x^3 + x^2 + x^1 + x^0 = 0b100101111 => 0x2F + */ +#define POLYNOM 0x2F +#define POLYNOM_ORDER 8 +#define HIGHBIT 1 << (POLYNOM_ORDER - 1); + +struct ad7280_state { + struct spi_device *spi; + struct iio_chan_spec *channels; + struct iio_dev_attr *iio_attr; + int slave_num; + int scan_cnt; + int readback_delay_us; + unsigned char crc_tab[256]; + unsigned char ctrl_hb; + unsigned char ctrl_lb; + unsigned char cell_threshhigh; + unsigned char cell_threshlow; + unsigned char aux_threshhigh; + unsigned char aux_threshlow; + unsigned char cb_mask[AD7280A_MAX_CHAIN]; +}; + +static void ad7280_crc8_build_table(unsigned char *crc_tab) +{ + unsigned char bit, crc; + int cnt, i; + + for (cnt = 0; cnt < 256; cnt++) { + crc = cnt; + for (i = 0; i < 8; i++) { + bit = crc & HIGHBIT; + crc <<= 1; + if (bit) + crc ^= POLYNOM; + } + crc_tab[cnt] = crc; + } +} + +static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned val) +{ + unsigned char crc; + + crc = crc_tab[val >> 16 & 0xFF]; + crc = crc_tab[crc ^ (val >> 8 & 0xFF)]; + + return crc ^ (val & 0xFF); +} + +static int ad7280_check_crc(struct ad7280_state *st, unsigned val) +{ + unsigned char crc = ad7280_calc_crc8(st->crc_tab, val >> 10); + + if (crc != ((val >> 2) & 0xFF)) + return -EIO; + + return 0; +} + +/* After initiating a conversion sequence we need to wait until the + * conversion is done. The delay is typically in the range of 15..30 us + * however depending an the number of devices in the daisy chain and the + * number of averages taken, conversion delays and acquisition time options + * it may take up to 250us, in this case we better sleep instead of busy + * wait. + */ + +static void ad7280_delay(struct ad7280_state *st) +{ + if (st->readback_delay_us < 50) + udelay(st->readback_delay_us); + else + msleep(1); +} + +static int __ad7280_read32(struct spi_device *spi, unsigned *val) +{ + unsigned rx_buf, tx_buf = cpu_to_be32(AD7280A_READ_TXVAL); + int ret; + + struct spi_transfer t = { + .tx_buf = &tx_buf, + .rx_buf = &rx_buf, + .len = 4, + }; + struct spi_message m; + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + + ret = spi_sync(spi, &m); + if (ret) + return ret; + + *val = be32_to_cpu(rx_buf); + + return 0; +} + +static int ad7280_write(struct ad7280_state *st, unsigned devaddr, + unsigned addr, bool all, unsigned val) +{ + unsigned reg = (devaddr << 27 | addr << 21 | + (val & 0xFF) << 13 | all << 12); + + reg |= ad7280_calc_crc8(st->crc_tab, reg >> 11) << 3 | 0x2; + reg = cpu_to_be32(reg); + + return spi_write(st->spi, ®, 4); +} + +static int ad7280_read(struct ad7280_state *st, unsigned devaddr, + unsigned addr) +{ + int ret; + unsigned tmp; + + /* turns off the read operation on all parts */ + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1, + AD7280A_CTRL_HB_CONV_INPUT_ALL | + AD7280A_CTRL_HB_CONV_RES_READ_NO | + st->ctrl_hb); + if (ret) + return ret; + + /* turns on the read operation on the addressed part */ + ret = ad7280_write(st, devaddr, AD7280A_CONTROL_HB, 0, + AD7280A_CTRL_HB_CONV_INPUT_ALL | + AD7280A_CTRL_HB_CONV_RES_READ_ALL | + st->ctrl_hb); + if (ret) + return ret; + + /* Set register address on the part to be read from */ + ret = ad7280_write(st, devaddr, AD7280A_READ, 0, addr << 2); + if (ret) + return ret; + + __ad7280_read32(st->spi, &tmp); + + if (ad7280_check_crc(st, tmp)) + return -EIO; + + if (((tmp >> 27) != devaddr) || (((tmp >> 21) & 0x3F) != addr)) + return -EFAULT; + + return (tmp >> 13) & 0xFF; +} + +static int ad7280_read_channel(struct ad7280_state *st, unsigned devaddr, + unsigned addr) +{ + int ret; + unsigned tmp; + + ret = ad7280_write(st, devaddr, AD7280A_READ, 0, addr << 2); + if (ret) + return ret; + + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1, + AD7280A_CTRL_HB_CONV_INPUT_ALL | + AD7280A_CTRL_HB_CONV_RES_READ_NO | + st->ctrl_hb); + if (ret) + return ret; + + ret = ad7280_write(st, devaddr, AD7280A_CONTROL_HB, 0, + AD7280A_CTRL_HB_CONV_INPUT_ALL | + AD7280A_CTRL_HB_CONV_RES_READ_ALL | + AD7280A_CTRL_HB_CONV_START_CS | + st->ctrl_hb); + if (ret) + return ret; + + ad7280_delay(st); + + __ad7280_read32(st->spi, &tmp); + + if (ad7280_check_crc(st, tmp)) + return -EIO; + + if (((tmp >> 27) != devaddr) || (((tmp >> 23) & 0xF) != addr)) + return -EFAULT; + + return (tmp >> 11) & 0xFFF; +} + +static int ad7280_read_all_channels(struct ad7280_state *st, unsigned cnt, + unsigned *array) +{ + int i, ret; + unsigned tmp, sum = 0; + + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ, 1, + AD7280A_CELL_VOLTAGE_1 << 2); + if (ret) + return ret; + + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1, + AD7280A_CTRL_HB_CONV_INPUT_ALL | + AD7280A_CTRL_HB_CONV_RES_READ_ALL | + AD7280A_CTRL_HB_CONV_START_CS | + st->ctrl_hb); + if (ret) + return ret; + + ad7280_delay(st); + + for (i = 0; i < cnt; i++) { + __ad7280_read32(st->spi, &tmp); + + if (ad7280_check_crc(st, tmp)) + return -EIO; + + if (array) + array[i] = tmp; + /* only sum cell voltages */ + if (((tmp >> 23) & 0xF) <= AD7280A_CELL_VOLTAGE_6) + sum += ((tmp >> 11) & 0xFFF); + } + + return sum; +} + +static int ad7280_chain_setup(struct ad7280_state *st) +{ + unsigned val, n; + int ret; + + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_LB, 1, + AD7280A_CTRL_LB_DAISY_CHAIN_RB_EN | + AD7280A_CTRL_LB_LOCK_DEV_ADDR | + AD7280A_CTRL_LB_MUST_SET | + AD7280A_CTRL_LB_SWRST | + st->ctrl_lb); + if (ret) + return ret; + + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_LB, 1, + AD7280A_CTRL_LB_DAISY_CHAIN_RB_EN | + AD7280A_CTRL_LB_LOCK_DEV_ADDR | + AD7280A_CTRL_LB_MUST_SET | + st->ctrl_lb); + if (ret) + return ret; + + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ, 1, + AD7280A_CONTROL_LB << 2); + if (ret) + return ret; + + for (n = 0; n <= AD7280A_MAX_CHAIN; n++) { + __ad7280_read32(st->spi, &val); + if (val == 0) + return n - 1; + + if (ad7280_check_crc(st, val)) + return -EIO; + + if (n != AD7280A_DEVADDR(val >> 27)) + return -EIO; + } + + return -EFAULT; +} + +static ssize_t ad7280_show_balance_sw(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7280_state *st = iio_priv(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + return sprintf(buf, "%d\n", + !!(st->cb_mask[this_attr->address >> 8] & + (1 << ((this_attr->address & 0xFF) + 2)))); +} + +static ssize_t ad7280_store_balance_sw(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7280_state *st = iio_priv(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + bool readin; + int ret; + unsigned devaddr, ch; + + ret = strtobool(buf, &readin); + if (ret) + return ret; + + devaddr = this_attr->address >> 8; + ch = this_attr->address & 0xFF; + + mutex_lock(&indio_dev->mlock); + if (readin) + st->cb_mask[devaddr] |= 1 << (ch + 2); + else + st->cb_mask[devaddr] &= ~(1 << (ch + 2)); + + ret = ad7280_write(st, devaddr, AD7280A_CELL_BALANCE, + 0, st->cb_mask[devaddr]); + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +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 ad7280_state *st = iio_priv(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + unsigned msecs; + + mutex_lock(&indio_dev->mlock); + ret = ad7280_read(st, this_attr->address >> 8, + this_attr->address & 0xFF); + mutex_unlock(&indio_dev->mlock); + + if (ret < 0) + return ret; + + msecs = (ret >> 3) * 71500; + + return sprintf(buf, "%d\n", msecs); +} + +static ssize_t ad7280_store_balance_timer(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(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_strtoul(buf, 10, &val); + if (ret) + return ret; + + val /= 71500; + + if (val > 31) + return -EINVAL; + + mutex_lock(&indio_dev->mlock); + ret = ad7280_write(st, this_attr->address >> 8, + this_attr->address & 0xFF, + 0, (val & 0x1F) << 3); + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static struct attribute *ad7280_attributes[AD7280A_MAX_CHAIN * + AD7280A_CELLS_PER_DEV * 2 + 1]; + +static struct attribute_group ad7280_attrs_group = { + .attrs = ad7280_attributes, +}; + +static int ad7280_channel_init(struct ad7280_state *st) +{ + int dev, ch, cnt; + + st->channels = kzalloc(sizeof(*st->channels) * + ((st->slave_num + 1) * 12 + 2), GFP_KERNEL); + if (st->channels == NULL) + return -ENOMEM; + + for (dev = 0, cnt = 0; dev <= st->slave_num; dev++) + for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_AUX_ADC_6; ch++, + cnt++) { + if (ch < AD7280A_AUX_ADC_1) { + st->channels[cnt].type = IIO_VOLTAGE; + st->channels[cnt].differential = 1; + st->channels[cnt].channel = (dev * 6) + ch; + st->channels[cnt].channel2 = + st->channels[cnt].channel + 1; + } else { + st->channels[cnt].type = IIO_TEMP; + st->channels[cnt].channel = (dev * 6) + ch - 6; + } + st->channels[cnt].indexed = 1; + st->channels[cnt].info_mask = + (1 << IIO_CHAN_INFO_SCALE_SHARED); + st->channels[cnt].address = + AD7280A_DEVADDR(dev) << 8 | ch; + st->channels[cnt].scan_index = cnt; + st->channels[cnt].scan_type.sign = 'u'; + st->channels[cnt].scan_type.realbits = 12; + st->channels[cnt].scan_type.storagebits = 32; + st->channels[cnt].scan_type.shift = 0; + } + + st->channels[cnt].type = IIO_VOLTAGE; + st->channels[cnt].differential = 1; + st->channels[cnt].channel = 0; + st->channels[cnt].channel2 = dev * 6; + st->channels[cnt].address = AD7280A_ALL_CELLS; + st->channels[cnt].indexed = 1; + st->channels[cnt].info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED); + st->channels[cnt].scan_index = cnt; + st->channels[cnt].scan_type.sign = 'u'; + st->channels[cnt].scan_type.realbits = 32; + st->channels[cnt].scan_type.storagebits = 32; + st->channels[cnt].scan_type.shift = 0; + cnt++; + st->channels[cnt].type = IIO_TIMESTAMP; + st->channels[cnt].channel = -1; + st->channels[cnt].scan_index = cnt; + st->channels[cnt].scan_type.sign = 's'; + st->channels[cnt].scan_type.realbits = 64; + st->channels[cnt].scan_type.storagebits = 64; + st->channels[cnt].scan_type.shift = 0; + + return cnt + 1; +} + +static int ad7280_attr_init(struct ad7280_state *st) +{ + int dev, ch, cnt; + + st->iio_attr = kzalloc(sizeof(*st->iio_attr) * (st->slave_num + 1) * + AD7280A_CELLS_PER_DEV * 2, GFP_KERNEL); + if (st->iio_attr == NULL) + return -ENOMEM; + + for (dev = 0, cnt = 0; dev <= st->slave_num; dev++) + for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_CELL_VOLTAGE_6; + ch++, cnt++) { + st->iio_attr[cnt].address = + AD7280A_DEVADDR(dev) << 8 | ch; + st->iio_attr[cnt].dev_attr.attr.mode = + S_IWUSR | S_IRUGO; + st->iio_attr[cnt].dev_attr.show = + ad7280_show_balance_sw; + st->iio_attr[cnt].dev_attr.store = + ad7280_store_balance_sw; + st->iio_attr[cnt].dev_attr.attr.name = + kasprintf(GFP_KERNEL, + "in%d-in%d_balance_switch_en", + (dev * AD7280A_CELLS_PER_DEV) + ch, + (dev * AD7280A_CELLS_PER_DEV) + ch + 1); + ad7280_attributes[cnt] = + &st->iio_attr[cnt].dev_attr.attr; + cnt++; + st->iio_attr[cnt].address = + AD7280A_DEVADDR(dev) << 8 | + (AD7280A_CB1_TIMER + ch); + st->iio_attr[cnt].dev_attr.attr.mode = + S_IWUSR | S_IRUGO; + st->iio_attr[cnt].dev_attr.show = + ad7280_show_balance_timer; + st->iio_attr[cnt].dev_attr.store = + ad7280_store_balance_timer; + st->iio_attr[cnt].dev_attr.attr.name = + kasprintf(GFP_KERNEL, "in%d-in%d_balance_timer", + (dev * AD7280A_CELLS_PER_DEV) + ch, + (dev * AD7280A_CELLS_PER_DEV) + ch + 1); + ad7280_attributes[cnt] = + &st->iio_attr[cnt].dev_attr.attr; + } + + ad7280_attributes[cnt] = NULL; + + return 0; +} + +static ssize_t ad7280_read_channel_config(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7280_state *st = iio_priv(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + unsigned val; + + switch (this_attr->address) { + case AD7280A_CELL_OVERVOLTAGE: + val = 1000 + (st->cell_threshhigh * 1568) / 100; + break; + case AD7280A_CELL_UNDERVOLTAGE: + val = 1000 + (st->cell_threshlow * 1568) / 100; + break; + case AD7280A_AUX_ADC_OVERVOLTAGE: + val = (st->aux_threshhigh * 196) / 10; + break; + case AD7280A_AUX_ADC_UNDERVOLTAGE: + val = (st->aux_threshlow * 196) / 10; + break; + default: + return -EINVAL; + } + + return sprintf(buf, "%d\n", val); +} + +static ssize_t ad7280_write_channel_config(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(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); + if (ret) + return ret; + + switch (this_attr->address) { + case AD7280A_CELL_OVERVOLTAGE: + case AD7280A_CELL_UNDERVOLTAGE: + val = ((val - 1000) * 100) / 1568; /* LSB 15.68mV */ + break; + case AD7280A_AUX_ADC_OVERVOLTAGE: + case AD7280A_AUX_ADC_UNDERVOLTAGE: + val = (val * 10) / 196; /* LSB 19.6mV */ + break; + default: + return -EFAULT; + } + + val = clamp(val, 0L, 0xFFL); + + mutex_lock(&indio_dev->mlock); + switch (this_attr->address) { + case AD7280A_CELL_OVERVOLTAGE: + st->cell_threshhigh = val; + break; + case AD7280A_CELL_UNDERVOLTAGE: + st->cell_threshlow = val; + break; + case AD7280A_AUX_ADC_OVERVOLTAGE: + st->aux_threshhigh = val; + break; + case AD7280A_AUX_ADC_UNDERVOLTAGE: + st->aux_threshlow = val; + break; + } + + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, + this_attr->address, 1, val); + + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static irqreturn_t ad7280_event_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct ad7280_state *st = iio_priv(indio_dev); + unsigned *channels; + int i, ret; + + channels = kzalloc(sizeof(*channels) * st->scan_cnt, GFP_KERNEL); + if (channels == NULL) + return IRQ_HANDLED; + + ret = ad7280_read_all_channels(st, st->scan_cnt, channels); + if (ret < 0) + return IRQ_HANDLED; + + for (i = 0; i < st->scan_cnt; i++) { + if (((channels[i] >> 23) & 0xF) <= AD7280A_CELL_VOLTAGE_6) { + if (((channels[i] >> 11) & 0xFFF) >= + st->cell_threshhigh) + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_VOLTAGE, + 1, + 0, + IIO_EV_DIR_RISING, + IIO_EV_TYPE_THRESH, + 0, 0, 0), + iio_get_time_ns()); + else if (((channels[i] >> 11) & 0xFFF) <= + st->cell_threshlow) + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_VOLTAGE, + 1, + 0, + IIO_EV_DIR_FALLING, + IIO_EV_TYPE_THRESH, + 0, 0, 0), + iio_get_time_ns()); + } else { + if (((channels[i] >> 11) & 0xFFF) >= st->aux_threshhigh) + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_TEMP, + 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + iio_get_time_ns()); + else if (((channels[i] >> 11) & 0xFFF) <= + st->aux_threshlow) + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_TEMP, + 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + iio_get_time_ns()); + } + } + + kfree(channels); + + return IRQ_HANDLED; +} + +static IIO_DEVICE_ATTR_NAMED(in_thresh_low_value, + in_voltage-voltage_thresh_low_value, + S_IRUGO | S_IWUSR, + ad7280_read_channel_config, + ad7280_write_channel_config, + AD7280A_CELL_UNDERVOLTAGE); + +static IIO_DEVICE_ATTR_NAMED(in_thresh_high_value, + in_voltage-voltage_thresh_high_value, + S_IRUGO | S_IWUSR, + ad7280_read_channel_config, + ad7280_write_channel_config, + AD7280A_CELL_OVERVOLTAGE); + +static IIO_DEVICE_ATTR(in_temp_thresh_low_value, + S_IRUGO | S_IWUSR, + ad7280_read_channel_config, + ad7280_write_channel_config, + AD7280A_AUX_ADC_UNDERVOLTAGE); + +static IIO_DEVICE_ATTR(in_temp_thresh_high_value, + S_IRUGO | S_IWUSR, + ad7280_read_channel_config, + ad7280_write_channel_config, + AD7280A_AUX_ADC_OVERVOLTAGE); + + +static struct attribute *ad7280_event_attributes[] = { + &iio_dev_attr_in_thresh_low_value.dev_attr.attr, + &iio_dev_attr_in_thresh_high_value.dev_attr.attr, + &iio_dev_attr_in_temp_thresh_low_value.dev_attr.attr, + &iio_dev_attr_in_temp_thresh_high_value.dev_attr.attr, + NULL, +}; + +static struct attribute_group ad7280_event_attrs_group = { + .attrs = ad7280_event_attributes, +}; + +static int ad7280_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad7280_state *st = iio_priv(indio_dev); + unsigned int scale_uv; + int ret; + + switch (m) { + case 0: + mutex_lock(&indio_dev->mlock); + if (chan->address == AD7280A_ALL_CELLS) + ret = ad7280_read_all_channels(st, st->scan_cnt, NULL); + else + ret = ad7280_read_channel(st, chan->address >> 8, + chan->address & 0xFF); + mutex_unlock(&indio_dev->mlock); + + if (ret < 0) + return ret; + + *val = ret; + + return IIO_VAL_INT; + case (1 << IIO_CHAN_INFO_SCALE_SHARED): + if ((chan->address & 0xFF) <= AD7280A_CELL_VOLTAGE_6) + scale_uv = (4000 * 1000) >> AD7280A_BITS; + else + scale_uv = (5000 * 1000) >> AD7280A_BITS; + + *val = scale_uv / 1000; + *val2 = (scale_uv % 1000) * 1000; + return IIO_VAL_INT_PLUS_MICRO; + } + return -EINVAL; +} + +static const struct iio_info ad7280_info = { + .read_raw = &ad7280_read_raw, + .event_attrs = &ad7280_event_attrs_group, + .attrs = &ad7280_attrs_group, + .driver_module = THIS_MODULE, +}; + +static const struct ad7280_platform_data ad7793_default_pdata = { + .acquisition_time = AD7280A_ACQ_TIME_400ns, + .conversion_averaging = AD7280A_CONV_AVG_DIS, + .thermistor_term_en = true, +}; + +static int __devinit ad7280_probe(struct spi_device *spi) +{ + const struct ad7280_platform_data *pdata = spi->dev.platform_data; + struct ad7280_state *st; + int ret; + const unsigned short tACQ_ns[4] = {465, 1010, 1460, 1890}; + const unsigned short nAVG[4] = {1, 2, 4, 8}; + struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); + + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + st->spi = spi; + + if (!pdata) + pdata = &ad7793_default_pdata; + + ad7280_crc8_build_table(st->crc_tab); + + st->spi->max_speed_hz = AD7280A_MAX_SPI_CLK_Hz; + st->spi->mode = SPI_MODE_1; + spi_setup(st->spi); + + st->ctrl_lb = AD7280A_CTRL_LB_ACQ_TIME(pdata->acquisition_time & 0x3); + st->ctrl_hb = AD7280A_CTRL_HB_CONV_AVG(pdata->conversion_averaging + & 0x3) | (pdata->thermistor_term_en ? + AD7280A_CTRL_LB_THERMISTOR_EN : 0); + + ret = ad7280_chain_setup(st); + if (ret < 0) + goto error_free_device; + + st->slave_num = ret; + st->scan_cnt = (st->slave_num + 1) * AD7280A_NUM_CH; + st->cell_threshhigh = 0xFF; + st->aux_threshhigh = 0xFF; + + /* + * Total Conversion Time = ((tACQ + tCONV) * + * (Number of Conversions per Part)) − + * tACQ + ((N - 1) * tDELAY) + * + * Readback Delay = Total Conversion Time + tWAIT + */ + + st->readback_delay_us = + ((tACQ_ns[pdata->acquisition_time & 0x3] + 695) * + (AD7280A_NUM_CH * nAVG[pdata->conversion_averaging & 0x3])) + - tACQ_ns[pdata->acquisition_time & 0x3] + + st->slave_num * 250; + + /* Convert to usecs */ + st->readback_delay_us = DIV_ROUND_UP(st->readback_delay_us, 1000); + st->readback_delay_us += 5; /* Add tWAIT */ + + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->dev.parent = &spi->dev; + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = ad7280_channel_init(st); + if (ret < 0) + goto error_free_device; + + indio_dev->num_channels = ret; + indio_dev->channels = st->channels; + indio_dev->info = &ad7280_info; + + ret = ad7280_attr_init(st); + if (ret < 0) + goto error_free_channels; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_free_attr; + + if (spi->irq > 0) { + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, + AD7280A_ALERT, 1, + AD7280A_ALERT_RELAY_SIG_CHAIN_DOWN); + if (ret) + goto error_unregister; + + ret = ad7280_write(st, AD7280A_DEVADDR(st->slave_num), + AD7280A_ALERT, 0, + AD7280A_ALERT_GEN_STATIC_HIGH | + (pdata->chain_last_alert_ignore & 0xF)); + if (ret) + goto error_unregister; + + ret = request_threaded_irq(spi->irq, + NULL, + ad7280_event_handler, + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, + indio_dev->name, + indio_dev); + if (ret) + goto error_unregister; + } + + return 0; +error_unregister: + iio_device_unregister(indio_dev); + +error_free_attr: + kfree(st->iio_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) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad7280_state *st = iio_priv(indio_dev); + + if (spi->irq > 0) + free_irq(spi->irq, indio_dev); + iio_device_unregister(indio_dev); + + ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1, + AD7280A_CTRL_HB_PWRDN_SW | st->ctrl_hb); + + kfree(st->channels); + kfree(st->iio_attr); + iio_free_device(indio_dev); + + return 0; +} + +static const struct spi_device_id ad7280_id[] = { + {"ad7280a", 0}, + {} +}; + +static struct spi_driver ad7280_driver = { + .driver = { + .name = "ad7280", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = ad7280_probe, + .remove = __devexit_p(ad7280_remove), + .id_table = ad7280_id, +}; + +static int __init ad7280_init(void) +{ + return spi_register_driver(&ad7280_driver); +} +module_init(ad7280_init); + +static void __exit ad7280_exit(void) +{ + spi_unregister_driver(&ad7280_driver); +} +module_exit(ad7280_exit); + +MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); +MODULE_DESCRIPTION("Analog Devices AD7280A"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/ad7280a.h b/drivers/staging/iio/adc/ad7280a.h new file mode 100644 index 0000000..20400b0 --- /dev/null +++ b/drivers/staging/iio/adc/ad7280a.h @@ -0,0 +1,38 @@ +/* + * AD7280A Lithium Ion Battery Monitoring System + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#ifndef IIO_ADC_AD7280_H_ +#define IIO_ADC_AD7280_H_ + +/* + * TODO: struct ad7280_platform_data needs to go into include/linux/iio + */ + +#define AD7280A_ACQ_TIME_400ns 0 +#define AD7280A_ACQ_TIME_800ns 1 +#define AD7280A_ACQ_TIME_1200ns 2 +#define AD7280A_ACQ_TIME_1600ns 3 + +#define AD7280A_CONV_AVG_DIS 0 +#define AD7280A_CONV_AVG_2 1 +#define AD7280A_CONV_AVG_4 2 +#define AD7280A_CONV_AVG_8 3 + +#define AD7280A_ALERT_REMOVE_VIN5 (1 << 2) +#define AD7280A_ALERT_REMOVE_VIN4_VIN5 (2 << 2) +#define AD7280A_ALERT_REMOVE_AUX5 (1 << 0) +#define AD7280A_ALERT_REMOVE_AUX4_AUX5 (2 << 0) + +struct ad7280_platform_data { + unsigned acquisition_time; + unsigned conversion_averaging; + unsigned chain_last_alert_ignore; + bool thermistor_term_en; +}; + +#endif /* IIO_ADC_AD7280_H_ */ diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c index 96cbb17..10e79e8 100644 --- a/drivers/staging/iio/adc/ad7291.c +++ b/drivers/staging/iio/adc/ad7291.c @@ -1,83 +1,110 @@ /* - * AD7291 digital temperature sensor driver supporting AD7291 + * AD7291 8-Channel, I2C, 12-Bit SAR ADC with Temperature Sensor * - * Copyright 2010 Analog Devices Inc. + * Copyright 2010-2011 Analog Devices Inc. * * Licensed under the GPL-2 or later. */ #include <linux/interrupt.h> -#include <linux/gpio.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 <linux/mutex.h> +#include <linux/regulator/consumer.h> +#include <linux/err.h> #include "../iio.h" #include "../sysfs.h" /* + * Simplified handling + * + * If no events enabled - single polled channel read + * If event enabled direct reads disable unless channel + * is in the read mask. + * + * The noise-delayed bit as per datasheet suggestion is always enabled. + * + */ + +/* * AD7291 registers definition */ -#define AD7291_COMMAND 0 -#define AD7291_VOLTAGE 1 -#define AD7291_T_SENSE 2 -#define AD7291_T_AVERAGE 3 -#define AD7291_VOLTAGE_LIMIT_BASE 4 -#define AD7291_VOLTAGE_LIMIT_COUNT 8 -#define AD7291_T_SENSE_HIGH 0x1c -#define AD7291_T_SENSE_LOW 0x1d -#define AD7291_T_SENSE_HYST 0x1e -#define AD7291_VOLTAGE_ALERT_STATUS 0x1f +#define AD7291_COMMAND 0x00 +#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_VOLTAGE_ALERT_STATUS 0x1F #define AD7291_T_ALERT_STATUS 0x20 +#define AD7291_VOLTAGE_LIMIT_COUNT 8 + + /* * AD7291 command */ -#define AD7291_AUTOCYCLE 0x1 -#define AD7291_RESET 0x2 -#define AD7291_ALART_CLEAR 0x4 -#define AD7291_ALART_POLARITY 0x8 -#define AD7291_EXT_REF 0x10 -#define AD7291_NOISE_DELAY 0x20 -#define AD7291_T_SENSE_MASK 0x40 -#define AD7291_VOLTAGE_MASK 0xff00 +#define AD7291_AUTOCYCLE (1 << 0) +#define AD7291_RESET (1 << 1) +#define AD7291_ALERT_CLEAR (1 << 2) +#define AD7291_ALERT_POLARITY (1 << 3) +#define AD7291_EXT_REF (1 << 4) +#define AD7291_NOISE_DELAY (1 << 5) +#define AD7291_T_SENSE_MASK (1 << 7) +#define AD7291_VOLTAGE_MASK 0xFF00 #define AD7291_VOLTAGE_OFFSET 0x8 /* * AD7291 value masks */ -#define AD7291_CHANNEL_MASK 0xf000 -#define AD7291_VALUE_MASK 0xfff +#define AD7291_CHANNEL_MASK 0xF000 +#define AD7291_BITS 12 +#define AD7291_VALUE_MASK 0xFFF #define AD7291_T_VALUE_SIGN 0x400 #define AD7291_T_VALUE_FLOAT_OFFSET 2 #define AD7291_T_VALUE_FLOAT_MASK 0x2 -/* - * struct ad7291_chip_info - chip specifc information - */ +#define AD7291_BITS 12 struct ad7291_chip_info { - struct i2c_client *client; - u16 command; - u8 channels; /* Active voltage channels */ + 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; }; -/* - * struct ad7291_chip_info - chip specifc information - */ - -struct ad7291_limit_regs { - u16 data_high; - u16 data_low; - u16 hysteresis; -}; - -/* - * ad7291 register access by I2C - */ static int ad7291_i2c_read(struct ad7291_chip_info *chip, u8 reg, u16 *data) { struct i2c_client *client = chip->client; @@ -96,352 +123,25 @@ static int ad7291_i2c_read(struct ad7291_chip_info *chip, u8 reg, u16 *data) static int ad7291_i2c_write(struct ad7291_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; -} - -/* Returns negative errno, or else the number of words read. */ -static int ad7291_i2c_read_data(struct ad7291_chip_info *chip, u8 reg, u16 *data) -{ - struct i2c_client *client = chip->client; - u8 commands[4]; - int ret = 0; - int i, count; - - if (reg == AD7291_T_SENSE || reg == AD7291_T_AVERAGE) - count = 2; - else if (reg == AD7291_VOLTAGE) { - if (!chip->channels) { - dev_err(&client->dev, "No voltage channel is selected.\n"); - return -EINVAL; - } - count = 2 + chip->channels * 2; - } else { - dev_err(&client->dev, "I2C wrong data register\n"); - return -EINVAL; - } - - commands[0] = 0; - commands[1] = (chip->command >> 8) & 0xff; - commands[2] = chip->command & 0xff; - commands[3] = reg; - - ret = i2c_master_send(client, commands, 4); - if (ret < 0) { - dev_err(&client->dev, "I2C master send error\n"); - return ret; - } - - ret = i2c_master_recv(client, (u8 *)data, count); - if (ret < 0) { - dev_err(&client->dev, "I2C master receive error\n"); - return ret; - } - ret >>= 2; - - for (i = 0; i < ret; i++) - data[i] = swab16(data[i]); - - return ret; -} - -static ssize_t ad7291_show_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7291_chip_info *chip = iio_priv(dev_info); - - if (chip->command & AD7291_AUTOCYCLE) - return sprintf(buf, "autocycle\n"); - else - return sprintf(buf, "command\n"); + return i2c_smbus_write_word_data(chip->client, reg, swab16(data)); } -static ssize_t ad7291_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 ad7291_chip_info *chip = iio_priv(dev_info); - u16 command; - int ret; - - command = chip->command & (~AD7291_AUTOCYCLE); - if (strcmp(buf, "autocycle")) - command |= AD7291_AUTOCYCLE; - - ret = ad7291_i2c_write(chip, AD7291_COMMAND, command); - if (ret) - return -EIO; - - chip->command = command; - - return ret; -} - -static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, - ad7291_show_mode, - ad7291_store_mode, - 0); - -static ssize_t ad7291_show_available_modes(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "command\nautocycle\n"); -} - -static IIO_DEVICE_ATTR(available_modes, S_IRUGO, ad7291_show_available_modes, NULL, 0); - static ssize_t ad7291_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 ad7291_chip_info *chip = iio_priv(dev_info); - u16 command; - int ret; - - command = chip->command | AD7291_RESET; - - ret = ad7291_i2c_write(chip, AD7291_COMMAND, command); - if (ret) - return -EIO; - - return ret; -} - -static IIO_DEVICE_ATTR(reset, S_IWUSR, - NULL, - ad7291_store_reset, - 0); - -static ssize_t ad7291_show_ext_ref(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7291_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%d\n", !!(chip->command & AD7291_EXT_REF)); -} - -static ssize_t ad7291_store_ext_ref(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7291_chip_info *chip = iio_priv(dev_info); - u16 command; - int ret; - - command = chip->command & (~AD7291_EXT_REF); - if (strcmp(buf, "1")) - command |= AD7291_EXT_REF; - - ret = ad7291_i2c_write(chip, AD7291_COMMAND, command); - if (ret) - return -EIO; - - chip->command = command; - - return ret; -} - -static IIO_DEVICE_ATTR(ext_ref, S_IRUGO | S_IWUSR, - ad7291_show_ext_ref, - ad7291_store_ext_ref, - 0); - -static ssize_t ad7291_show_noise_delay(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7291_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%d\n", !!(chip->command & AD7291_NOISE_DELAY)); -} - -static ssize_t ad7291_store_noise_delay(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7291_chip_info *chip = iio_priv(dev_info); - u16 command; - int ret; - - command = chip->command & (~AD7291_NOISE_DELAY); - if (strcmp(buf, "1")) - command |= AD7291_NOISE_DELAY; - - ret = ad7291_i2c_write(chip, AD7291_COMMAND, command); - if (ret) - return -EIO; - - chip->command = command; - - return ret; -} - -static IIO_DEVICE_ATTR(noise_delay, S_IRUGO | S_IWUSR, - ad7291_show_noise_delay, - ad7291_store_noise_delay, - 0); - -static ssize_t ad7291_show_t_sense(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7291_chip_info *chip = iio_priv(dev_info); - u16 data; - char sign = ' '; - int ret; - - ret = ad7291_i2c_read_data(chip, AD7291_T_SENSE, &data); - if (ret) - return -EIO; - - if (data & AD7291_T_VALUE_SIGN) { - /* convert supplement to positive value */ - data = (AD7291_T_VALUE_SIGN << 1) - data; - sign = '-'; - } - - return sprintf(buf, "%c%d.%.2d\n", sign, - (data >> AD7291_T_VALUE_FLOAT_OFFSET), - (data & AD7291_T_VALUE_FLOAT_MASK) * 25); -} - -static IIO_DEVICE_ATTR(t_sense, S_IRUGO, ad7291_show_t_sense, NULL, 0); - -static ssize_t ad7291_show_t_average(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7291_chip_info *chip = iio_priv(dev_info); - u16 data; - char sign = ' '; - int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = iio_priv(indio_dev); - ret = ad7291_i2c_read_data(chip, AD7291_T_AVERAGE, &data); - if (ret) - return -EIO; - - if (data & AD7291_T_VALUE_SIGN) { - /* convert supplement to positive value */ - data = (AD7291_T_VALUE_SIGN << 1) - data; - sign = '-'; - } - - return sprintf(buf, "%c%d.%.2d\n", sign, - (data >> AD7291_T_VALUE_FLOAT_OFFSET), - (data & AD7291_T_VALUE_FLOAT_MASK) * 25); + return ad7291_i2c_write(chip, AD7291_COMMAND, + chip->command | AD7291_RESET); } -static IIO_DEVICE_ATTR(t_average, S_IRUGO, ad7291_show_t_average, NULL, 0); - -static ssize_t ad7291_show_voltage(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7291_chip_info *chip = iio_priv(dev_info); - u16 data[AD7291_VOLTAGE_LIMIT_COUNT]; - int i, size, ret; - - ret = ad7291_i2c_read_data(chip, AD7291_VOLTAGE, data); - if (ret) - return -EIO; - - for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT; i++) { - if (chip->command & (AD7291_T_SENSE_MASK << i)) { - ret = sprintf(buf, "channel[%d]=%d\n", i, - data[i] & AD7291_VALUE_MASK); - if (ret < 0) - break; - buf += ret; - size += ret; - } - } - - return size; -} - -static IIO_DEVICE_ATTR(voltage, S_IRUGO, ad7291_show_voltage, NULL, 0); - -static ssize_t ad7291_show_channel_mask(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7291_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "0x%x\n", (chip->command & AD7291_VOLTAGE_MASK) >> - AD7291_VOLTAGE_OFFSET); -} - -static ssize_t ad7291_store_channel_mask(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7291_chip_info *chip = iio_priv(dev_info); - u16 command; - unsigned long data; - int i, ret; - - ret = strict_strtoul(buf, 16, &data); - if (ret || data > 0xff) - return -EINVAL; - - command = chip->command & (~AD7291_VOLTAGE_MASK); - command |= data << AD7291_VOLTAGE_OFFSET; - - ret = ad7291_i2c_write(chip, AD7291_COMMAND, command); - if (ret) - return -EIO; - - chip->command = command; - - for (i = 0, chip->channels = 0; i < AD7291_VOLTAGE_LIMIT_COUNT; i++) { - if (chip->command & (AD7291_T_SENSE_MASK << i)) - chip->channels++; - } - - return ret; -} - -static IIO_DEVICE_ATTR(channel_mask, S_IRUGO | S_IWUSR, - ad7291_show_channel_mask, - ad7291_store_channel_mask, - 0); +static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, ad7291_store_reset, 0); static struct attribute *ad7291_attributes[] = { - &iio_dev_attr_available_modes.dev_attr.attr, - &iio_dev_attr_mode.dev_attr.attr, &iio_dev_attr_reset.dev_attr.attr, - &iio_dev_attr_ext_ref.dev_attr.attr, - &iio_dev_attr_noise_delay.dev_attr.attr, - &iio_dev_attr_t_sense.dev_attr.attr, - &iio_dev_attr_t_average.dev_attr.attr, - &iio_dev_attr_voltage.dev_attr.attr, - &iio_dev_attr_channel_mask.dev_attr.attr, NULL, }; @@ -449,10 +149,6 @@ static const struct attribute_group ad7291_attribute_group = { .attrs = ad7291_attributes, }; -/* - * temperature bound events - */ - static irqreturn_t ad7291_event_handler(int irq, void *private) { struct iio_dev *indio_dev = private; @@ -471,35 +167,22 @@ static irqreturn_t ad7291_event_handler(int irq, void *private) if (!(t_status || v_status)) return IRQ_HANDLED; - command = chip->command | AD7291_ALART_CLEAR; + command = chip->command | AD7291_ALERT_CLEAR; ad7291_i2c_write(chip, AD7291_COMMAND, command); - command = chip->command & ~AD7291_ALART_CLEAR; + command = chip->command & ~AD7291_ALERT_CLEAR; ad7291_i2c_write(chip, AD7291_COMMAND, command); - if (t_status & (1 << 0)) - iio_push_event(indio_dev, 0, + /* For now treat t_sense and t_sense_average the same */ + if ((t_status & (1 << 0)) || (t_status & (1 << 2))) + iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), timestamp); - if (t_status & (1 << 1)) - iio_push_event(indio_dev, 0, - IIO_UNMOD_EVENT_CODE(IIO_TEMP, - 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - timestamp); - if (t_status & (1 << 2)) - iio_push_event(indio_dev, 0, - IIO_UNMOD_EVENT_CODE(IIO_TEMP, - 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING), - timestamp); - if (t_status & (1 << 3)) - iio_push_event(indio_dev, 0, + if ((t_status & (1 << 1)) || (t_status & (1 << 3))) + iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, IIO_EV_TYPE_THRESH, @@ -508,15 +191,15 @@ static irqreturn_t ad7291_event_handler(int irq, void *private) for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT*2; i += 2) { if (v_status & (1 << i)) - iio_push_event(indio_dev, 0, - IIO_UNMOD_EVENT_CODE(IIO_IN, + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i/2, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), timestamp); if (v_status & (1 << (i + 1))) - iio_push_event(indio_dev, 0, - IIO_UNMOD_EVENT_CODE(IIO_IN, + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i/2, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), @@ -526,251 +209,352 @@ static irqreturn_t ad7291_event_handler(int irq, void *private) return IRQ_HANDLED; } -static inline ssize_t ad7291_show_t_bound(struct device *dev, +static inline ssize_t ad7291_show_hyst(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7291_chip_info *chip = iio_priv(dev_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; - char sign = ' '; int ret; ret = ad7291_i2c_read(chip, this_attr->address, &data); - if (ret) - return -EIO; - - data &= AD7291_VALUE_MASK; - if (data & AD7291_T_VALUE_SIGN) { - /* convert supplement to positive value */ - data = (AD7291_T_VALUE_SIGN << 1) - data; - sign = '-'; - } + if (ret < 0) + return ret; - return sprintf(buf, "%c%d.%.2d\n", sign, - data >> AD7291_T_VALUE_FLOAT_OFFSET, - (data & AD7291_T_VALUE_FLOAT_MASK) * 25); + return sprintf(buf, "%d\n", data & AD7291_VALUE_MASK); } -static inline ssize_t ad7291_set_t_bound(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) +static inline ssize_t ad7291_set_hyst(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7291_chip_info *chip = iio_priv(dev_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); - long tmp1, tmp2; u16 data; - char *pos; int ret; - pos = strchr(buf, '.'); + ret = kstrtou16(buf, 10, &data); - ret = strict_strtol(buf, 10, &tmp1); - - if (ret || tmp1 > 127 || tmp1 < -128) + if (ret < 0) + return ret; + if (data > AD7291_VALUE_MASK) return -EINVAL; - if (pos) { - len = strlen(pos); - if (len > AD7291_T_VALUE_FLOAT_OFFSET) - len = AD7291_T_VALUE_FLOAT_OFFSET; - pos[len] = 0; - ret = strict_strtol(pos, 10, &tmp2); - - if (!ret) - tmp2 = (tmp2 / 25) * 25; - } - - if (tmp1 < 0) - data = (u16)(-tmp1); - else - data = (u16)tmp1; - data = (data << AD7291_T_VALUE_FLOAT_OFFSET) | - (tmp2 & AD7291_T_VALUE_FLOAT_MASK); - if (tmp1 < 0) - /* convert positive value to supplyment */ - data = (AD7291_T_VALUE_SIGN << 1) - data; - ret = ad7291_i2c_write(chip, this_attr->address, data); - if (ret) - return -EIO; + if (ret < 0) + return ret; - return ret; + return len; } -static inline ssize_t ad7291_show_v_bound(struct device *dev, - struct device_attribute *attr, - u8 bound_reg, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7291_chip_info *chip = iio_priv(dev_info); - u16 data; - int ret; +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); - if (bound_reg < AD7291_VOLTAGE_LIMIT_BASE || - bound_reg >= AD7291_VOLTAGE_LIMIT_BASE + - AD7291_VOLTAGE_LIMIT_COUNT) - return -EINVAL; +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, +}; - ret = ad7291_i2c_read(chip, bound_reg, &data); - if (ret) - return -EIO; +/* 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 }, +}; - data &= AD7291_VALUE_MASK; +static int ad7291_read_event_value(struct iio_dev *indio_dev, + u64 event_code, + int *val) +{ + struct ad7291_chip_info *chip = iio_priv(indio_dev); - return sprintf(buf, "%d\n", data); + 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, reg, &uval); + if (ret < 0) + return ret; + *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)]; + + 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; + }; } -static inline ssize_t ad7291_set_v_bound(struct device *dev, - struct device_attribute *attr, - u8 bound_reg, - const char *buf, - size_t len) +static int ad7291_write_event_value(struct iio_dev *indio_dev, + u64 event_code, + int val) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7291_chip_info *chip = iio_priv(dev_info); - unsigned long value; - u16 data; - int ret; + struct ad7291_chip_info *chip = iio_priv(indio_dev); + u8 reg; + s16 signval; - if (bound_reg < AD7291_VOLTAGE_LIMIT_BASE || - bound_reg >= AD7291_VOLTAGE_LIMIT_BASE + - AD7291_VOLTAGE_LIMIT_COUNT) + switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { + case 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: + 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; + }; +} - ret = strict_strtoul(buf, 10, &value); - - if (ret || value >= 4096) +static int ad7291_read_event_config(struct iio_dev *indio_dev, + u64 event_code) +{ + 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)) { + case IIO_VOLTAGE: + if (chip->c_mask & + (1 << (15 - IIO_EVENT_CODE_EXTRACT_NUM(event_code)))) + return 1; + else + return 0; + case IIO_TEMP: + /* always on */ + return 1; + default: return -EINVAL; + } - data = (u16)value; - ret = ad7291_i2c_write(chip, bound_reg, data); - if (ret) - return -EIO; +} +static int ad7291_write_event_config(struct iio_dev *indio_dev, + u64 event_code, + int state) +{ + int ret = 0; + struct ad7291_chip_info *chip = iio_priv(indio_dev); + u16 regval; + + mutex_lock(&chip->state_lock); + regval = chip->command; + /* + * To be enabled the channel must simply be on. If any are enabled + * use continuous sampling mode. + * Possible to disable temp as well but that makes single read tricky. + */ + + switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) { + 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))); + else + break; + + regval &= ~AD7291_AUTOCYCLE; + regval |= chip->c_mask; + if (chip->c_mask) /* Enable autocycle? */ + regval |= AD7291_AUTOCYCLE; + + ret = ad7291_i2c_write(chip, AD7291_COMMAND, regval); + if (ret < 0) + goto error_ret; + + chip->command = regval; + break; + default: + ret = -EINVAL; + } + +error_ret: + mutex_unlock(&chip->state_lock); return ret; } -static IIO_DEVICE_ATTR(t_sense_high_value, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, - AD7291_T_SENSE_HIGH); -static IIO_DEVICE_ATTR(t_sense_low_value, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, - AD7291_T_SENSE_LOW); -static IIO_DEVICE_ATTR(t_sense_hyst_value, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, - AD7291_T_SENSE_HYST); -static IIO_DEVICE_ATTR(v0_high, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x04); -static IIO_DEVICE_ATTR(v0_low, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x05); -static IIO_DEVICE_ATTR(v0_hyst, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x06); -static IIO_DEVICE_ATTR(v1_high, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x07); -static IIO_DEVICE_ATTR(v1_low, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x08); -static IIO_DEVICE_ATTR(v1_hyst, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x09); -static IIO_DEVICE_ATTR(v2_high, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x0A); -static IIO_DEVICE_ATTR(v2_low, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x0B); -static IIO_DEVICE_ATTR(v2_hyst, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x0C); -static IIO_DEVICE_ATTR(v3_high, - S_IRUGO | S_IWUSR, - /* Datasheet suggests this one and this one only - has the registers in different order */ - ad7291_show_t_bound, ad7291_set_t_bound, 0x0E); -static IIO_DEVICE_ATTR(v3_low, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x0D); -static IIO_DEVICE_ATTR(v3_hyst, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x0F); -static IIO_DEVICE_ATTR(v4_high, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x10); -static IIO_DEVICE_ATTR(v4_low, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x11); -static IIO_DEVICE_ATTR(v4_hyst, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x12); -static IIO_DEVICE_ATTR(v5_high, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x13); -static IIO_DEVICE_ATTR(v5_low, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x14); -static IIO_DEVICE_ATTR(v5_hyst, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x15); -static IIO_DEVICE_ATTR(v6_high, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x16); -static IIO_DEVICE_ATTR(v6_low, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x17); -static IIO_DEVICE_ATTR(v6_hyst, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x18); -static IIO_DEVICE_ATTR(v7_high, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x19); -static IIO_DEVICE_ATTR(v7_low, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x1A); -static IIO_DEVICE_ATTR(v7_hyst, - S_IRUGO | S_IWUSR, - ad7291_show_t_bound, ad7291_set_t_bound, 0x1B); +static int ad7291_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + int ret; + struct ad7291_chip_info *chip = iio_priv(indio_dev); + unsigned int scale_uv; + u16 regval; + s16 signval; + + switch (mask) { + case 0: + switch (chan->type) { + case IIO_VOLTAGE: + mutex_lock(&chip->state_lock); + /* If in autocycle mode drop through */ + if (chip->command & AD7291_AUTOCYCLE) { + mutex_unlock(&chip->state_lock); + return -EBUSY; + } + /* Enable this channel alone */ + regval = chip->command & (~AD7291_VOLTAGE_MASK); + regval |= 1 << (15 - chan->channel); + ret = ad7291_i2c_write(chip, AD7291_COMMAND, regval); + if (ret < 0) { + mutex_unlock(&chip->state_lock); + return ret; + } + /* Read voltage */ + ret = i2c_smbus_read_word_data(chip->client, + AD7291_VOLTAGE); + if (ret < 0) { + mutex_unlock(&chip->state_lock); + return ret; + } + *val = swab16((u16)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, + AD7291_T_SENSE); + if (ret < 0) + return ret; + signval = (s16)((swab16((u16)ret) & + AD7291_VALUE_MASK) << 4) >> 4; + *val = signval; + return IIO_VAL_INT; + default: + return -EINVAL; + } + case (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE): + ret = i2c_smbus_read_word_data(chip->client, + AD7291_T_AVERAGE); + if (ret < 0) + return ret; + signval = (s16)((swab16((u16)ret) & + AD7291_VALUE_MASK) << 4) >> 4; + *val = signval; + return IIO_VAL_INT; + case (1 << IIO_CHAN_INFO_SCALE_SHARED): + scale_uv = (chip->int_vref_mv * 1000) >> AD7291_BITS; + *val = scale_uv / 1000; + *val2 = (scale_uv % 1000) * 1000; + return IIO_VAL_INT_PLUS_MICRO; + case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + /* + * One LSB of the ADC corresponds to 0.25 deg C. + * The temperature reading is in 12-bit twos complement format + */ + *val = 250; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} -static struct attribute *ad7291_event_attributes[] = { - &iio_dev_attr_t_sense_high_value.dev_attr.attr, - &iio_dev_attr_t_sense_low_value.dev_attr.attr, - &iio_dev_attr_t_sense_hyst_value.dev_attr.attr, - &iio_dev_attr_v0_high.dev_attr.attr, - &iio_dev_attr_v0_low.dev_attr.attr, - &iio_dev_attr_v0_hyst.dev_attr.attr, - &iio_dev_attr_v1_high.dev_attr.attr, - &iio_dev_attr_v1_low.dev_attr.attr, - &iio_dev_attr_v1_hyst.dev_attr.attr, - &iio_dev_attr_v2_high.dev_attr.attr, - &iio_dev_attr_v2_low.dev_attr.attr, - &iio_dev_attr_v2_hyst.dev_attr.attr, - &iio_dev_attr_v3_high.dev_attr.attr, - &iio_dev_attr_v3_low.dev_attr.attr, - &iio_dev_attr_v3_hyst.dev_attr.attr, - &iio_dev_attr_v4_high.dev_attr.attr, - &iio_dev_attr_v4_low.dev_attr.attr, - &iio_dev_attr_v4_hyst.dev_attr.attr, - &iio_dev_attr_v5_high.dev_attr.attr, - &iio_dev_attr_v5_low.dev_attr.attr, - &iio_dev_attr_v5_hyst.dev_attr.attr, - &iio_dev_attr_v6_high.dev_attr.attr, - &iio_dev_attr_v6_low.dev_attr.attr, - &iio_dev_attr_v6_hyst.dev_attr.attr, - &iio_dev_attr_v7_high.dev_attr.attr, - &iio_dev_attr_v7_low.dev_attr.attr, - &iio_dev_attr_v7_hyst.dev_attr.attr, - NULL, +#define AD7291_VOLTAGE_CHAN(_chan) \ +{ \ + .type = IIO_VOLTAGE, \ + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \ + .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) \ +} + +static const struct iio_chan_spec ad7291_channels[] = { + AD7291_VOLTAGE_CHAN(0), + AD7291_VOLTAGE_CHAN(1), + AD7291_VOLTAGE_CHAN(2), + AD7291_VOLTAGE_CHAN(3), + AD7291_VOLTAGE_CHAN(4), + AD7291_VOLTAGE_CHAN(5), + AD7291_VOLTAGE_CHAN(6), + AD7291_VOLTAGE_CHAN(7), + { + .type = IIO_TEMP, + .info_mask = (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .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) + } }; static struct attribute_group ad7291_event_attribute_group = { @@ -779,20 +563,20 @@ static struct attribute_group ad7291_event_attribute_group = { static const struct iio_info ad7291_info = { .attrs = &ad7291_attribute_group, - .num_interrupt_lines = 1, + .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, }; -/* - * device probe and remove - */ - static int __devinit ad7291_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct ad7291_chip_info *chip; struct iio_dev *indio_dev; - int ret = 0; + int ret = 0, voltage_uv = 0; indio_dev = iio_allocate_device(sizeof(*chip)); if (indio_dev == NULL) { @@ -800,20 +584,51 @@ static int __devinit ad7291_probe(struct i2c_client *client, goto error_ret; } chip = iio_priv(indio_dev); + + chip->reg = regulator_get(&client->dev, "vcc"); + if (!IS_ERR(chip->reg)) { + ret = regulator_enable(chip->reg); + if (ret) + goto error_put_reg; + voltage_uv = regulator_get_voltage(chip->reg); + } + + mutex_init(&chip->state_lock); /* this is only used for device removal purposes */ i2c_set_clientdata(client, indio_dev); chip->client = client; - chip->command = AD7291_NOISE_DELAY | AD7291_T_SENSE_MASK; + + chip->command = AD7291_NOISE_DELAY | + 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; + chip->command |= AD7291_EXT_REF; + } else { + chip->int_vref_mv = 2500; /* Build-in ref */ + } indio_dev->name = id->name; + indio_dev->channels = ad7291_channels; + indio_dev->num_channels = ARRAY_SIZE(ad7291_channels); + indio_dev->dev.parent = &client->dev; indio_dev->info = &ad7291_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; + ret = ad7291_i2c_write(chip, AD7291_COMMAND, AD7291_RESET); + if (ret) { + ret = -EIO; + goto error_disable_reg; + } + + ret = ad7291_i2c_write(chip, AD7291_COMMAND, chip->command); + if (ret) { + ret = -EIO; + goto error_disable_reg; + } if (client->irq > 0) { ret = request_threaded_irq(client->irq, @@ -823,28 +638,28 @@ static int __devinit ad7291_probe(struct i2c_client *client, id->name, indio_dev); if (ret) - goto error_unreg_dev; - - /* set irq polarity low level */ - chip->command |= AD7291_ALART_POLARITY; + goto error_disable_reg; } - ret = ad7291_i2c_write(chip, AD7291_COMMAND, chip->command); - if (ret) { - ret = -EIO; + ret = iio_device_register(indio_dev); + if (ret) goto error_unreg_irq; - } - dev_info(&client->dev, "%s temperature sensor registered.\n", + dev_info(&client->dev, "%s ADC registered.\n", id->name); return 0; error_unreg_irq: - free_irq(client->irq, indio_dev); -error_unreg_dev: - iio_device_unregister(indio_dev); -error_free_dev: + if (client->irq) + free_irq(client->irq, indio_dev); +error_disable_reg: + if (!IS_ERR(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; @@ -853,10 +668,18 @@ error_ret: static int __devexit ad7291_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct ad7291_chip_info *chip = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); if (client->irq) free_irq(client->irq, indio_dev); - iio_device_unregister(indio_dev); + + if (!IS_ERR(chip->reg)) { + regulator_disable(chip->reg); + regulator_put(chip->reg); + } + iio_free_device(indio_dev); return 0; @@ -871,7 +694,7 @@ MODULE_DEVICE_TABLE(i2c, ad7291_id); static struct i2c_driver ad7291_driver = { .driver = { - .name = "ad7291", + .name = KBUILD_MODNAME, }, .probe = ad7291_probe, .remove = __devexit_p(ad7291_remove), @@ -889,8 +712,7 @@ static __exit void ad7291_exit(void) } MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>"); -MODULE_DESCRIPTION("Analog Devices AD7291 digital" - " temperature sensor driver"); +MODULE_DESCRIPTION("Analog Devices AD7291 ADC driver"); MODULE_LICENSE("GPL v2"); module_init(ad7291_init); diff --git a/drivers/staging/iio/adc/ad7298.h b/drivers/staging/iio/adc/ad7298.h index 628f5ad..9ddf5cf 100644 --- a/drivers/staging/iio/adc/ad7298.h +++ b/drivers/staging/iio/adc/ad7298.h @@ -53,11 +53,11 @@ struct ad7298_state { unsigned short tx_buf[2]; }; -#ifdef CONFIG_IIO_RING_BUFFER +#ifdef CONFIG_IIO_BUFFER int ad7298_scan_from_ring(struct iio_dev *indio_dev, long ch); int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev); void ad7298_ring_cleanup(struct iio_dev *indio_dev); -#else /* CONFIG_IIO_RING_BUFFER */ +#else /* CONFIG_IIO_BUFFER */ static inline int ad7298_scan_from_ring(struct iio_dev *indio_dev, long ch) { return 0; @@ -72,5 +72,5 @@ ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev) static inline void ad7298_ring_cleanup(struct iio_dev *indio_dev) { } -#endif /* CONFIG_IIO_RING_BUFFER */ +#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 index b8e4ae2..c1de73a 100644 --- a/drivers/staging/iio/adc/ad7298_core.c +++ b/drivers/staging/iio/adc/ad7298_core.c @@ -14,11 +14,11 @@ #include <linux/regulator/consumer.h> #include <linux/err.h> #include <linux/delay.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" -#include "adc.h" +#include "../buffer_generic.h" #include "ad7298.h" @@ -26,28 +26,28 @@ static struct iio_chan_spec ad7298_channels[] = { IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, (1 << IIO_CHAN_INFO_SCALE_SEPARATE), 9, AD7298_CH_TEMP, IIO_ST('s', 32, 32, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 0, 0, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 1, 1, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 2, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 2, 2, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 3, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 3, 3, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 4, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 4, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 4, 4, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 5, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 5, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 5, 5, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 6, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 6, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 6, 6, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 7, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 7, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 7, 7, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN_SOFT_TIMESTAMP(8), @@ -109,24 +109,24 @@ static int ad7298_scan_temp(struct ad7298_state *st, int *val) return 0; } -static int ad7298_read_raw(struct iio_dev *dev_info, +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(dev_info); + struct ad7298_state *st = iio_priv(indio_dev); unsigned int scale_uv; switch (m) { case 0: - mutex_lock(&dev_info->mlock); - if (iio_ring_enabled(dev_info)) { + mutex_lock(&indio_dev->mlock); + if (iio_buffer_enabled(indio_dev)) { if (chan->address == AD7298_CH_TEMP) ret = -ENODEV; else - ret = ad7298_scan_from_ring(dev_info, + ret = ad7298_scan_from_ring(indio_dev, chan->address); } else { if (chan->address == AD7298_CH_TEMP) @@ -134,7 +134,7 @@ static int ad7298_read_raw(struct iio_dev *dev_info, else ret = ad7298_scan_direct(st, chan->address); } - mutex_unlock(&dev_info->mlock); + mutex_unlock(&indio_dev->mlock); if (ret < 0) return ret; @@ -165,7 +165,7 @@ static int __devinit ad7298_probe(struct spi_device *spi) { struct ad7298_platform_data *pdata = spi->dev.platform_data; struct ad7298_state *st; - int ret, regdone = 0; + int ret; struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); if (indio_dev == NULL) @@ -218,19 +218,19 @@ static int __devinit ad7298_probe(struct spi_device *spi) if (ret) goto error_disable_reg; - ret = iio_device_register(indio_dev); - if (ret) - goto error_disable_reg; - regdone = 1; - - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - &ad7298_channels[1], /* skip temp0 */ - ARRAY_SIZE(ad7298_channels) - 1); + 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: @@ -239,11 +239,7 @@ error_disable_reg: error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); return ret; } @@ -253,14 +249,14 @@ 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_ring_buffer_unregister(indio_dev->ring); - ad7298_ring_cleanup(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_device_unregister(indio_dev); + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c index a04c033..47630d5 100644 --- a/drivers/staging/iio/adc/ad7298_ring.c +++ b/drivers/staging/iio/adc/ad7298_ring.c @@ -7,27 +7,24 @@ */ #include <linux/interrupt.h> -#include <linux/device.h> #include <linux/kernel.h> #include <linux/slab.h> -#include <linux/sysfs.h> #include <linux/spi/spi.h> #include "../iio.h" -#include "../ring_generic.h" +#include "../buffer_generic.h" #include "../ring_sw.h" -#include "../trigger.h" -#include "../sysfs.h" +#include "../trigger_consumer.h" #include "ad7298.h" -int ad7298_scan_from_ring(struct iio_dev *dev_info, long ch) +int ad7298_scan_from_ring(struct iio_dev *indio_dev, long ch) { - struct iio_ring_buffer *ring = dev_info->ring; + struct iio_buffer *ring = indio_dev->buffer; int ret; u16 *ring_data; - if (!(ring->scan_mask & (1 << ch))) { + if (!(test_bit(ch, ring->scan_mask))) { ret = -EBUSY; goto error_ret; } @@ -60,7 +57,7 @@ error_ret: static int ad7298_ring_preenable(struct iio_dev *indio_dev) { struct ad7298_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; size_t d_size; int i, m; unsigned short command; @@ -82,7 +79,7 @@ static int ad7298_ring_preenable(struct iio_dev *indio_dev) command = AD7298_WRITE | st->ext_ref; for (i = 0, m = AD7298_CH(0); i < AD7298_MAX_CHAN; i++, m >>= 1) - if (ring->scan_mask & (1 << i)) + if (test_bit(i, ring->scan_mask)) command |= m; st->tx_buf[0] = cpu_to_be16(command); @@ -120,9 +117,9 @@ static int ad7298_ring_preenable(struct iio_dev *indio_dev) static irqreturn_t ad7298_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->private_data; + struct iio_dev *indio_dev = pf->indio_dev; struct ad7298_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; s64 time_ns; __u16 buf[16]; int b_sent, i; @@ -140,29 +137,29 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p) for (i = 0; i < ring->scan_count; i++) buf[i] = be16_to_cpu(st->rx_buf[i]); - indio_dev->ring->access->store_to(ring, (u8 *)buf, time_ns); + 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_ring_setup_ops ad7298_ring_setup_ops = { +static const struct iio_buffer_setup_ops ad7298_ring_setup_ops = { .preenable = &ad7298_ring_preenable, - .postenable = &iio_triggered_ring_postenable, - .predisable = &iio_triggered_ring_predisable, + .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->ring = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->ring) { + 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->ring->access = &ring_sw_access_funcs; + indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(NULL, &ad7298_trigger_handler, @@ -177,26 +174,21 @@ int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev) } /* Ring buffer functions - here trigger setup related */ - indio_dev->ring->setup_ops = &ad7298_ring_setup_ops; - indio_dev->ring->scan_timestamp = true; + indio_dev->buffer->setup_ops = &ad7298_ring_setup_ops; + indio_dev->buffer->scan_timestamp = true; /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_RING_TRIGGERED; + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; return 0; error_deallocate_sw_rb: - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); error_ret: return ret; } void ad7298_ring_cleanup(struct iio_dev *indio_dev) { - if (indio_dev->trig) { - iio_put_trigger(indio_dev->trig); - iio_trigger_dettach_poll_func(indio_dev->trig, - indio_dev->pollfunc); - } iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); } diff --git a/drivers/staging/iio/adc/ad7314.c b/drivers/staging/iio/adc/ad7314.c deleted file mode 100644 index 9070d9c..0000000 --- a/drivers/staging/iio/adc/ad7314.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * AD7314 digital temperature sensor driver for AD7314, ADT7301 and ADT7302 - * - * 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 "../iio.h" -#include "../sysfs.h" - -/* - * AD7314 power mode - */ -#define AD7314_PD 0x2000 - -/* - * AD7314 temperature masks - */ -#define AD7314_TEMP_SIGN 0x200 -#define AD7314_TEMP_MASK 0x7FE0 -#define AD7314_TEMP_OFFSET 5 -#define AD7314_TEMP_FLOAT_OFFSET 2 -#define AD7314_TEMP_FLOAT_MASK 0x3 - -/* - * ADT7301 and ADT7302 temperature masks - */ -#define ADT7301_TEMP_SIGN 0x2000 -#define ADT7301_TEMP_MASK 0x2FFF -#define ADT7301_TEMP_FLOAT_OFFSET 5 -#define ADT7301_TEMP_FLOAT_MASK 0x1F - -/* - * struct ad7314_chip_info - chip specifc information - */ - -struct ad7314_chip_info { - struct spi_device *spi_dev; - s64 last_timestamp; - u8 mode; -}; - -/* - * ad7314 register access by SPI - */ - -static int ad7314_spi_read(struct ad7314_chip_info *chip, u16 *data) -{ - struct spi_device *spi_dev = chip->spi_dev; - int ret = 0; - u16 value; - - ret = spi_read(spi_dev, (u8 *)&value, sizeof(value)); - if (ret < 0) { - dev_err(&spi_dev->dev, "SPI read error\n"); - return ret; - } - - *data = be16_to_cpu((u16)value); - - return ret; -} - -static int ad7314_spi_write(struct ad7314_chip_info *chip, u16 data) -{ - struct spi_device *spi_dev = chip->spi_dev; - int ret = 0; - u16 value = cpu_to_be16(data); - - ret = spi_write(spi_dev, (u8 *)&value, sizeof(value)); - if (ret < 0) - dev_err(&spi_dev->dev, "SPI write error\n"); - - return ret; -} - -static ssize_t ad7314_show_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7314_chip_info *chip = iio_priv(dev_info); - - if (chip->mode) - return sprintf(buf, "power-save\n"); - else - return sprintf(buf, "full\n"); -} - -static ssize_t ad7314_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 ad7314_chip_info *chip = iio_priv(dev_info); - u16 mode = 0; - int ret; - - if (!strcmp(buf, "full")) - mode = AD7314_PD; - - ret = ad7314_spi_write(chip, mode); - if (ret) - return -EIO; - - chip->mode = mode; - - return len; -} - -static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, - ad7314_show_mode, - ad7314_store_mode, - 0); - -static ssize_t ad7314_show_available_modes(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "full\npower-save\n"); -} - -static IIO_DEVICE_ATTR(available_modes, S_IRUGO, ad7314_show_available_modes, NULL, 0); - -static ssize_t ad7314_show_temperature(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7314_chip_info *chip = iio_priv(dev_info); - u16 data; - char sign = ' '; - int ret; - - if (chip->mode) { - ret = ad7314_spi_write(chip, 0); - if (ret) - return -EIO; - } - - ret = ad7314_spi_read(chip, &data); - if (ret) - return -EIO; - - if (chip->mode) - ad7314_spi_write(chip, chip->mode); - - if (strcmp(dev_info->name, "ad7314")) { - data = (data & AD7314_TEMP_MASK) >> - AD7314_TEMP_OFFSET; - if (data & AD7314_TEMP_SIGN) { - data = (AD7314_TEMP_SIGN << 1) - data; - sign = '-'; - } - - return sprintf(buf, "%c%d.%.2d\n", sign, - data >> AD7314_TEMP_FLOAT_OFFSET, - (data & AD7314_TEMP_FLOAT_MASK) * 25); - } else { - data &= ADT7301_TEMP_MASK; - if (data & ADT7301_TEMP_SIGN) { - data = (ADT7301_TEMP_SIGN << 1) - data; - sign = '-'; - } - - return sprintf(buf, "%c%d.%.5d\n", sign, - data >> ADT7301_TEMP_FLOAT_OFFSET, - (data & ADT7301_TEMP_FLOAT_MASK) * 3125); - } -} - -static IIO_DEVICE_ATTR(temperature, S_IRUGO, ad7314_show_temperature, NULL, 0); - -static struct attribute *ad7314_attributes[] = { - &iio_dev_attr_available_modes.dev_attr.attr, - &iio_dev_attr_mode.dev_attr.attr, - &iio_dev_attr_temperature.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad7314_attribute_group = { - .attrs = ad7314_attributes, -}; - -static const struct iio_info ad7314_info = { - .attrs = &ad7314_attribute_group, - .driver_module = THIS_MODULE, -}; -/* - * device probe and remove - */ - -static int __devinit ad7314_probe(struct spi_device *spi_dev) -{ - struct ad7314_chip_info *chip; - struct iio_dev *indio_dev; - int ret = 0; - - 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, chip); - - chip->spi_dev = spi_dev; - - indio_dev->name = spi_get_device_id(spi_dev)->name; - indio_dev->dev.parent = &spi_dev->dev; - indio_dev->info = &ad7314_info; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - - dev_info(&spi_dev->dev, "%s temperature sensor registered.\n", - indio_dev->name); - - return 0; -error_free_dev: - iio_free_device(indio_dev); -error_ret: - return ret; -} - -static int __devexit ad7314_remove(struct spi_device *spi_dev) -{ - struct iio_dev *indio_dev = dev_get_drvdata(&spi_dev->dev); - - dev_set_drvdata(&spi_dev->dev, NULL); - iio_device_unregister(indio_dev); - iio_free_device(indio_dev); - - return 0; -} - -static const struct spi_device_id ad7314_id[] = { - { "adt7301", 0 }, - { "adt7302", 0 }, - { "ad7314", 0 }, - {} -}; - -static struct spi_driver ad7314_driver = { - .driver = { - .name = "ad7314", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = ad7314_probe, - .remove = __devexit_p(ad7314_remove), - .id_table = ad7314_id, -}; - -static __init int ad7314_init(void) -{ - return spi_register_driver(&ad7314_driver); -} - -static __exit void ad7314_exit(void) -{ - spi_unregister_driver(&ad7314_driver); -} - -MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>"); -MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital" - " temperature sensor driver"); -MODULE_LICENSE("GPL v2"); - -module_init(ad7314_init); -module_exit(ad7314_exit); diff --git a/drivers/staging/iio/adc/ad7476.h b/drivers/staging/iio/adc/ad7476.h index 0d44976..6014292 100644 --- a/drivers/staging/iio/adc/ad7476.h +++ b/drivers/staging/iio/adc/ad7476.h @@ -49,11 +49,11 @@ enum ad7476_supported_device_ids { ID_AD7495 }; -#ifdef CONFIG_IIO_RING_BUFFER +#ifdef CONFIG_IIO_BUFFER int ad7476_scan_from_ring(struct iio_dev *indio_dev); int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev); void ad7476_ring_cleanup(struct iio_dev *indio_dev); -#else /* CONFIG_IIO_RING_BUFFER */ +#else /* CONFIG_IIO_BUFFER */ static inline int ad7476_scan_from_ring(struct iio_dev *indio_dev) { return 0; @@ -68,5 +68,5 @@ ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev) static inline void ad7476_ring_cleanup(struct iio_dev *indio_dev) { } -#endif /* CONFIG_IIO_RING_BUFFER */ +#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 index c210898..fd79fac 100644 --- a/drivers/staging/iio/adc/ad7476_core.c +++ b/drivers/staging/iio/adc/ad7476_core.c @@ -13,11 +13,11 @@ #include <linux/spi/spi.h> #include <linux/regulator/consumer.h> #include <linux/err.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" -#include "adc.h" +#include "../buffer_generic.h" #include "ad7476.h" @@ -32,24 +32,24 @@ static int ad7476_scan_direct(struct ad7476_state *st) return (st->data[0] << 8) | st->data[1]; } -static int ad7476_read_raw(struct iio_dev *dev_info, +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(dev_info); + struct ad7476_state *st = iio_priv(indio_dev); unsigned int scale_uv; switch (m) { case 0: - mutex_lock(&dev_info->mlock); - if (iio_ring_enabled(dev_info)) - ret = ad7476_scan_from_ring(dev_info); + mutex_lock(&indio_dev->mlock); + if (iio_buffer_enabled(indio_dev)) + ret = ad7476_scan_from_ring(indio_dev); else ret = ad7476_scan_direct(st); - mutex_unlock(&dev_info->mlock); + mutex_unlock(&indio_dev->mlock); if (ret < 0) return ret; @@ -68,49 +68,49 @@ static int ad7476_read_raw(struct iio_dev *dev_info, static const struct ad7476_chip_info ad7476_chip_info_tbl[] = { [ID_AD7466] = { - .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, + .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 0, 0, IIO_ST('u', 12, 16, 0), 0), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, [ID_AD7467] = { - .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, + .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 0, 0, IIO_ST('u', 10, 16, 2), 0), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, [ID_AD7468] = { - .channel[0] = IIO_CHAN(IIO_IN, 0, 1 , 0, NULL, 0, 0, + .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1 , 0, NULL, 0, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 0, 0, IIO_ST('u', 8, 16, 4), 0), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, [ID_AD7475] = { - .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, + .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 0, 0, IIO_ST('u', 12, 16, 0), 0), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, [ID_AD7476] = { - .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, + .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 0, 0, IIO_ST('u', 12, 16, 0), 0), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, [ID_AD7477] = { - .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, + .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 0, 0, IIO_ST('u', 10, 16, 2), 0), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, [ID_AD7478] = { - .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, + .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 0, 0, IIO_ST('u', 8, 16, 4), 0), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, [ID_AD7495] = { - .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, + .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 0, 0, IIO_ST('u', 12, 16, 0), 0), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), @@ -129,8 +129,6 @@ static int __devinit ad7476_probe(struct spi_device *spi) struct ad7476_state *st; struct iio_dev *indio_dev; int ret, voltage_uv = 0; - bool reg_done = false; - struct regulator *reg; indio_dev = iio_allocate_device(sizeof(*st)); if (indio_dev == NULL) { @@ -138,15 +136,14 @@ static int __devinit ad7476_probe(struct spi_device *spi) goto error_ret; } st = iio_priv(indio_dev); - reg = regulator_get(&spi->dev, "vcc"); - if (!IS_ERR(reg)) { - ret = regulator_enable(reg); + 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(reg); + voltage_uv = regulator_get_voltage(st->reg); } - st->reg = reg; st->chip_info = &ad7476_chip_info_tbl[spi_get_device_id(spi)->driver_data]; @@ -182,28 +179,29 @@ static int __devinit ad7476_probe(struct spi_device *spi) if (ret) goto error_disable_reg; - ret = iio_device_register(indio_dev); + ret = iio_buffer_register(indio_dev, + st->chip_info->channel, + ARRAY_SIZE(st->chip_info->channel)); if (ret) - goto error_disable_reg; + goto error_cleanup_ring; - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - st->chip_info->channel, - ARRAY_SIZE(st->chip_info->channel)); + ret = iio_device_register(indio_dev); if (ret) - goto error_cleanup_ring; + goto error_ring_unregister; return 0; +error_ring_unregister: + iio_buffer_unregister(indio_dev); error_cleanup_ring: ad7476_ring_cleanup(indio_dev); - iio_device_unregister(indio_dev); error_disable_reg: - if (!IS_ERR(reg)) + if (!IS_ERR(st->reg)) regulator_disable(st->reg); error_put_reg: - if (!IS_ERR(reg)) - regulator_put(reg); - if (!reg_done) - iio_free_device(indio_dev); + if (!IS_ERR(st->reg)) + regulator_put(st->reg); + iio_free_device(indio_dev); + error_ret: return ret; } @@ -212,16 +210,15 @@ 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); - /* copy needed as st will have been freed */ - struct regulator *reg = st->reg; - iio_ring_buffer_unregister(indio_dev->ring); - ad7476_ring_cleanup(indio_dev); iio_device_unregister(indio_dev); - if (!IS_ERR(reg)) { - regulator_disable(reg); - regulator_put(reg); + 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; } diff --git a/drivers/staging/iio/adc/ad7476_ring.c b/drivers/staging/iio/adc/ad7476_ring.c index a92fc5a..e82c1a4 100644 --- a/drivers/staging/iio/adc/ad7476_ring.c +++ b/drivers/staging/iio/adc/ad7476_ring.c @@ -11,20 +11,18 @@ #include <linux/device.h> #include <linux/kernel.h> #include <linux/slab.h> -#include <linux/sysfs.h> #include <linux/spi/spi.h> #include "../iio.h" -#include "../ring_generic.h" +#include "../buffer_generic.h" #include "../ring_sw.h" -#include "../trigger.h" -#include "../sysfs.h" +#include "../trigger_consumer.h" #include "ad7476.h" int ad7476_scan_from_ring(struct iio_dev *indio_dev) { - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; int ret; u8 *ring_data; @@ -56,7 +54,7 @@ error_ret: static int ad7476_ring_preenable(struct iio_dev *indio_dev) { struct ad7476_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; st->d_size = ring->scan_count * st->chip_info->channel[0].scan_type.storagebits / 8; @@ -68,9 +66,9 @@ static int ad7476_ring_preenable(struct iio_dev *indio_dev) st->d_size += sizeof(s64) - (st->d_size % sizeof(s64)); } - if (indio_dev->ring->access->set_bytes_per_datum) - indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring, - st->d_size); + 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; } @@ -78,7 +76,7 @@ static int ad7476_ring_preenable(struct iio_dev *indio_dev) static irqreturn_t ad7476_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->private_data; + struct iio_dev *indio_dev = pf->indio_dev; struct ad7476_state *st = iio_priv(indio_dev); s64 time_ns; __u8 *rxbuf; @@ -95,11 +93,11 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p) time_ns = iio_get_time_ns(); - if (indio_dev->ring->scan_timestamp) + if (indio_dev->buffer->scan_timestamp) memcpy(rxbuf + st->d_size - sizeof(s64), &time_ns, sizeof(time_ns)); - indio_dev->ring->access->store_to(indio_dev->ring, rxbuf, time_ns); + indio_dev->buffer->access->store_to(indio_dev->buffer, rxbuf, time_ns); done: iio_trigger_notify_done(indio_dev->trig); kfree(rxbuf); @@ -107,10 +105,10 @@ done: return IRQ_HANDLED; } -static const struct iio_ring_setup_ops ad7476_ring_setup_ops = { +static const struct iio_buffer_setup_ops ad7476_ring_setup_ops = { .preenable = &ad7476_ring_preenable, - .postenable = &iio_triggered_ring_postenable, - .predisable = &iio_triggered_ring_predisable, + .postenable = &iio_triggered_buffer_postenable, + .predisable = &iio_triggered_buffer_predisable, }; int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev) @@ -118,13 +116,13 @@ 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->ring = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->ring) { + 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->ring->access = &ring_sw_access_funcs; + indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(NULL, &ad7476_trigger_handler, @@ -139,27 +137,21 @@ int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev) } /* Ring buffer functions - here trigger setup related */ - indio_dev->ring->setup_ops = &ad7476_ring_setup_ops; - indio_dev->ring->scan_timestamp = true; + indio_dev->buffer->setup_ops = &ad7476_ring_setup_ops; + indio_dev->buffer->scan_timestamp = true; /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_RING_TRIGGERED; + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; return 0; error_deallocate_sw_rb: - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); error_ret: return ret; } void ad7476_ring_cleanup(struct iio_dev *indio_dev) { - /* ensure that the trigger has been detached */ - if (indio_dev->trig) { - iio_put_trigger(indio_dev->trig); - iio_trigger_dettach_poll_func(indio_dev->trig, - indio_dev->pollfunc); - } iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); } diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h index b8b3d8e..35018c3 100644 --- a/drivers/staging/iio/adc/ad7606.h +++ b/drivers/staging/iio/adc/ad7606.h @@ -50,8 +50,6 @@ struct ad7606_platform_data { struct ad7606_chip_info { const char *name; - u8 bits; - char sign; u16 int_vref_mv; struct iio_chan_spec *channels; unsigned num_channels; @@ -68,18 +66,10 @@ struct ad7606_state { struct regulator *reg; struct work_struct poll_work; wait_queue_head_t wq_data_avail; - size_t d_size; const struct ad7606_bus_ops *bops; - int irq; - unsigned id; unsigned range; unsigned oversampling; bool done; - bool have_frstdata; - bool have_os; - bool have_stby; - bool have_reset; - bool have_range; void __iomem *base_address; /* @@ -100,7 +90,7 @@ void ad7606_resume(struct iio_dev *indio_dev); struct iio_dev *ad7606_probe(struct device *dev, int irq, void __iomem *base_address, unsigned id, const struct ad7606_bus_ops *bops); -int ad7606_remove(struct iio_dev *indio_dev); +int ad7606_remove(struct iio_dev *indio_dev, int irq); int ad7606_reset(struct ad7606_state *st); enum ad7606_supported_device_ids { diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index 459371a..54423ab 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -16,17 +16,17 @@ #include <linux/gpio.h> #include <linux/delay.h> #include <linux/sched.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" -#include "adc.h" +#include "../buffer_generic.h" #include "ad7606.h" int ad7606_reset(struct ad7606_state *st) { - if (st->have_reset) { + if (gpio_is_valid(st->pdata->gpio_reset)) { gpio_set_value(st->pdata->gpio_reset, 1); ndelay(100); /* t_reset >= 100ns */ gpio_set_value(st->pdata->gpio_reset, 0); @@ -48,7 +48,7 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned ch) if (ret) goto error_ret; - if (st->have_frstdata) { + if (gpio_is_valid(st->pdata->gpio_frstdata)) { ret = st->bops->read_block(st->dev, 1, st->data); if (ret) goto error_ret; @@ -90,7 +90,7 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, switch (m) { case 0: mutex_lock(&indio_dev->mlock); - if (iio_ring_enabled(indio_dev)) + if (iio_buffer_enabled(indio_dev)) ret = ad7606_scan_from_ring(indio_dev, chan->address); else ret = ad7606_scan_direct(indio_dev, chan->address); @@ -140,9 +140,9 @@ static ssize_t ad7606_store_range(struct device *dev, return count; } -static IIO_DEVICE_ATTR(range, S_IRUGO | S_IWUSR, \ +static IIO_DEVICE_ATTR(in_voltage_range, S_IRUGO | S_IWUSR, \ ad7606_show_range, ad7606_store_range, 0); -static IIO_CONST_ATTR(range_available, "5000 10000"); +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) @@ -198,8 +198,8 @@ static IIO_DEVICE_ATTR(oversampling_ratio, S_IRUGO | S_IWUSR, static IIO_CONST_ATTR(oversampling_ratio_available, "0 2 4 8 16 32 64"); static struct attribute *ad7606_attributes[] = { - &iio_dev_attr_range.dev_attr.attr, - &iio_const_attr_range_available.dev_attr.attr, + &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, &iio_const_attr_oversampling_ratio_available.dev_attr.attr, NULL, @@ -214,15 +214,18 @@ static mode_t ad7606_attr_is_visible(struct kobject *kobj, mode_t mode = attr->mode; - if (!st->have_os && - (attr == &iio_dev_attr_oversampling_ratio.dev_attr.attr || - attr == - &iio_const_attr_oversampling_ratio_available.dev_attr.attr)) + 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; - else if (!st->have_range && - (attr == &iio_dev_attr_range.dev_attr.attr || - attr == &iio_const_attr_range_available.dev_attr.attr)) - mode = 0; return mode; } @@ -232,69 +235,43 @@ static const struct attribute_group ad7606_attribute_group = { .is_visible = ad7606_attr_is_visible, }; +#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 struct iio_chan_spec ad7606_8_channels[] = { - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 0, 0, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 1, 1, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 2, 2, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 3, 3, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 4, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 4, 4, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 5, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 5, 5, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 6, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 6, 6, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 7, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 7, 7, IIO_ST('s', 16, 16, 0), 0), + AD7606_CHANNEL(0), + AD7606_CHANNEL(1), + AD7606_CHANNEL(2), + AD7606_CHANNEL(3), + AD7606_CHANNEL(4), + AD7606_CHANNEL(5), + AD7606_CHANNEL(6), + AD7606_CHANNEL(7), IIO_CHAN_SOFT_TIMESTAMP(8), }; static struct iio_chan_spec ad7606_6_channels[] = { - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 0, 0, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 1, 1, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 2, 2, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 3, 3, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 4, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 4, 4, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 5, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 5, 5, IIO_ST('s', 16, 16, 0), 0), + AD7606_CHANNEL(0), + AD7606_CHANNEL(1), + AD7606_CHANNEL(2), + AD7606_CHANNEL(3), + AD7606_CHANNEL(4), + AD7606_CHANNEL(5), IIO_CHAN_SOFT_TIMESTAMP(6), }; static struct iio_chan_spec ad7606_4_channels[] = { - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 0, 0, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 1, 1, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 2, 2, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 3, 3, IIO_ST('s', 16, 16, 0), 0), + AD7606_CHANNEL(0), + AD7606_CHANNEL(1), + AD7606_CHANNEL(2), + AD7606_CHANNEL(3), IIO_CHAN_SOFT_TIMESTAMP(4), }; @@ -346,64 +323,96 @@ static int ad7606_request_gpios(struct ad7606_state *st) }; int ret; - ret = gpio_request_one(st->pdata->gpio_convst, GPIOF_OUT_INIT_LOW, - "AD7606_CONVST"); - if (ret) { - dev_err(st->dev, "failed to request GPIO CONVST\n"); - return ret; + if (gpio_is_valid(st->pdata->gpio_convst)) { + ret = gpio_request_one(st->pdata->gpio_convst, + GPIOF_OUT_INIT_LOW, + "AD7606_CONVST"); + if (ret) { + dev_err(st->dev, "failed to request GPIO CONVST\n"); + goto error_ret; + } + } else { + ret = -EIO; + goto error_ret; } - ret = gpio_request_array(gpio_array, ARRAY_SIZE(gpio_array)); - if (!ret) { - st->have_os = true; + if (gpio_is_valid(st->pdata->gpio_os0) && + gpio_is_valid(st->pdata->gpio_os1) && + gpio_is_valid(st->pdata->gpio_os2)) { + ret = gpio_request_array(gpio_array, ARRAY_SIZE(gpio_array)); + if (ret < 0) + goto error_free_convst; } - ret = gpio_request_one(st->pdata->gpio_reset, GPIOF_OUT_INIT_LOW, - "AD7606_RESET"); - if (!ret) - st->have_reset = true; - - ret = gpio_request_one(st->pdata->gpio_range, GPIOF_DIR_OUT | - ((st->range == 10000) ? GPIOF_INIT_HIGH : - GPIOF_INIT_LOW), "AD7606_RANGE"); - if (!ret) - st->have_range = true; + if (gpio_is_valid(st->pdata->gpio_reset)) { + ret = gpio_request_one(st->pdata->gpio_reset, + GPIOF_OUT_INIT_LOW, + "AD7606_RESET"); + if (ret < 0) + goto error_free_os; + } - ret = gpio_request_one(st->pdata->gpio_stby, GPIOF_OUT_INIT_HIGH, - "AD7606_STBY"); - if (!ret) - st->have_stby = true; + if (gpio_is_valid(st->pdata->gpio_range)) { + ret = gpio_request_one(st->pdata->gpio_range, GPIOF_DIR_OUT | + ((st->range == 10000) ? GPIOF_INIT_HIGH : + GPIOF_INIT_LOW), "AD7606_RANGE"); + if (ret < 0) + goto error_free_reset; + } + if (gpio_is_valid(st->pdata->gpio_stby)) { + ret = gpio_request_one(st->pdata->gpio_stby, + GPIOF_OUT_INIT_HIGH, + "AD7606_STBY"); + if (ret < 0) + goto error_free_range; + } if (gpio_is_valid(st->pdata->gpio_frstdata)) { ret = gpio_request_one(st->pdata->gpio_frstdata, GPIOF_IN, "AD7606_FRSTDATA"); - if (!ret) - st->have_frstdata = true; + if (ret < 0) + goto error_free_stby; } return 0; + +error_free_stby: + if (gpio_is_valid(st->pdata->gpio_stby)) + gpio_free(st->pdata->gpio_stby); +error_free_range: + if (gpio_is_valid(st->pdata->gpio_range)) + gpio_free(st->pdata->gpio_range); +error_free_reset: + if (gpio_is_valid(st->pdata->gpio_reset)) + gpio_free(st->pdata->gpio_reset); +error_free_os: + if (gpio_is_valid(st->pdata->gpio_os0) && + gpio_is_valid(st->pdata->gpio_os1) && + gpio_is_valid(st->pdata->gpio_os2)) + gpio_free_array(gpio_array, ARRAY_SIZE(gpio_array)); +error_free_convst: + gpio_free(st->pdata->gpio_convst); +error_ret: + return ret; } static void ad7606_free_gpios(struct ad7606_state *st) { - if (st->have_range) - gpio_free(st->pdata->gpio_range); - - if (st->have_stby) + if (gpio_is_valid(st->pdata->gpio_frstdata)) + gpio_free(st->pdata->gpio_frstdata); + if (gpio_is_valid(st->pdata->gpio_stby)) gpio_free(st->pdata->gpio_stby); - - if (st->have_os) { - gpio_free(st->pdata->gpio_os0); - gpio_free(st->pdata->gpio_os1); + if (gpio_is_valid(st->pdata->gpio_range)) + gpio_free(st->pdata->gpio_range); + if (gpio_is_valid(st->pdata->gpio_reset)) + gpio_free(st->pdata->gpio_reset); + if (gpio_is_valid(st->pdata->gpio_os0) && + gpio_is_valid(st->pdata->gpio_os1) && + gpio_is_valid(st->pdata->gpio_os2)) { gpio_free(st->pdata->gpio_os2); + gpio_free(st->pdata->gpio_os1); + gpio_free(st->pdata->gpio_os0); } - - if (st->have_reset) - gpio_free(st->pdata->gpio_reset); - - if (st->have_frstdata) - gpio_free(st->pdata->gpio_frstdata); - gpio_free(st->pdata->gpio_convst); } @@ -415,7 +424,7 @@ static irqreturn_t ad7606_interrupt(int irq, void *dev_id) struct iio_dev *indio_dev = dev_id; struct ad7606_state *st = iio_priv(indio_dev); - if (iio_ring_enabled(indio_dev)) { + if (iio_buffer_enabled(indio_dev)) { if (!work_pending(&st->poll_work)) schedule_work(&st->poll_work); } else { @@ -439,7 +448,7 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, { struct ad7606_platform_data *pdata = dev->platform_data; struct ad7606_state *st; - int ret, regdone = 0; + int ret; struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); if (indio_dev == NULL) { @@ -450,8 +459,6 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, st = iio_priv(indio_dev); st->dev = dev; - st->id = id; - st->irq = irq; st->bops = bops; st->base_address = base_address; st->range = pdata->default_range == 10000 ? 10000 : 5000; @@ -492,7 +499,7 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, if (ret) dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); - ret = request_irq(st->irq, ad7606_interrupt, + ret = request_irq(irq, ad7606_interrupt, IRQF_TRIGGER_FALLING, st->chip_info->name, indio_dev); if (ret) goto error_free_gpios; @@ -501,24 +508,24 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, if (ret) goto error_free_irq; - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_irq; - regdone = 1; - - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - indio_dev->channels, - indio_dev->num_channels); + 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: - free_irq(st->irq, indio_dev); + free_irq(irq, indio_dev); error_free_gpios: ad7606_free_gpios(st); @@ -529,29 +536,27 @@ error_disable_reg: error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ERR_PTR(ret); } -int ad7606_remove(struct iio_dev *indio_dev) +int ad7606_remove(struct iio_dev *indio_dev, int irq) { struct ad7606_state *st = iio_priv(indio_dev); - iio_ring_buffer_unregister(indio_dev->ring); + iio_device_unregister(indio_dev); + iio_buffer_unregister(indio_dev); ad7606_ring_cleanup(indio_dev); - free_irq(st->irq, indio_dev); + free_irq(irq, indio_dev); if (!IS_ERR(st->reg)) { regulator_disable(st->reg); regulator_put(st->reg); } ad7606_free_gpios(st); - iio_device_unregister(indio_dev); + iio_free_device(indio_dev); return 0; } @@ -560,8 +565,8 @@ void ad7606_suspend(struct iio_dev *indio_dev) { struct ad7606_state *st = iio_priv(indio_dev); - if (st->have_stby) { - if (st->have_range) + if (gpio_is_valid(st->pdata->gpio_stby)) { + if (gpio_is_valid(st->pdata->gpio_range)) gpio_set_value(st->pdata->gpio_range, 1); gpio_set_value(st->pdata->gpio_stby, 0); } @@ -571,8 +576,8 @@ void ad7606_resume(struct iio_dev *indio_dev) { struct ad7606_state *st = iio_priv(indio_dev); - if (st->have_stby) { - if (st->have_range) + if (gpio_is_valid(st->pdata->gpio_stby)) { + if (gpio_is_valid(st->pdata->gpio_range)) gpio_set_value(st->pdata->gpio_range, st->range == 10000); diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c index d21218d..688632e 100644 --- a/drivers/staging/iio/adc/ad7606_par.c +++ b/drivers/staging/iio/adc/ad7606_par.c @@ -106,7 +106,7 @@ static int __devexit ad7606_par_remove(struct platform_device *pdev) struct resource *res; struct ad7606_state *st = iio_priv(indio_dev); - ad7606_remove(indio_dev); + ad7606_remove(indio_dev, platform_get_irq(pdev, 0)); iounmap(st->base_address); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c index a199bf4..20927fd 100644 --- a/drivers/staging/iio/adc/ad7606_ring.c +++ b/drivers/staging/iio/adc/ad7606_ring.c @@ -10,19 +10,17 @@ #include <linux/device.h> #include <linux/kernel.h> #include <linux/slab.h> -#include <linux/sysfs.h> #include "../iio.h" -#include "../ring_generic.h" +#include "../buffer_generic.h" #include "../ring_sw.h" -#include "../trigger.h" -#include "../sysfs.h" +#include "../trigger_consumer.h" #include "ad7606.h" int ad7606_scan_from_ring(struct iio_dev *indio_dev, unsigned ch) { - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; int ret; u16 *ring_data; @@ -45,45 +43,13 @@ error_ret: } /** - * ad7606_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 ad7606_ring_preenable(struct iio_dev *indio_dev) -{ - struct ad7606_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; - size_t d_size; - - d_size = st->chip_info->num_channels * - st->chip_info->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 (ring->access->set_bytes_per_datum) - ring->access->set_bytes_per_datum(ring, d_size); - - st->d_size = d_size; - - return 0; -} - -/** * ad7606_trigger_handler_th() th/bh of trigger launched polling to ring buffer * **/ static irqreturn_t ad7606_trigger_handler_th_bh(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->private_data; - struct ad7606_state *st = iio_priv(indio_dev); + struct ad7606_state *st = iio_priv(pf->indio_dev); gpio_set_value(st->pdata->gpio_convst, 1); @@ -104,16 +70,17 @@ 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_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; s64 time_ns; __u8 *buf; int ret; - buf = kzalloc(st->d_size, GFP_KERNEL); + buf = kzalloc(ring->access->get_bytes_per_datum(ring), + GFP_KERNEL); if (buf == NULL) return; - if (st->have_frstdata) { + if (gpio_is_valid(st->pdata->gpio_frstdata)) { ret = st->bops->read_block(st->dev, 1, buf); if (ret) goto done; @@ -140,20 +107,20 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s) time_ns = iio_get_time_ns(); if (ring->scan_timestamp) - memcpy(buf + st->d_size - sizeof(s64), - &time_ns, sizeof(time_ns)); + *((s64 *)(buf + ring->access->get_bytes_per_datum(ring) - + sizeof(s64))) = time_ns; - ring->access->store_to(indio_dev->ring, buf, time_ns); + ring->access->store_to(indio_dev->buffer, buf, time_ns); done: gpio_set_value(st->pdata->gpio_convst, 0); iio_trigger_notify_done(indio_dev->trig); kfree(buf); } -static const struct iio_ring_setup_ops ad7606_ring_setup_ops = { - .preenable = &ad7606_ring_preenable, - .postenable = &iio_triggered_ring_postenable, - .predisable = &iio_triggered_ring_predisable, +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) @@ -161,14 +128,16 @@ int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev) struct ad7606_state *st = iio_priv(indio_dev); int ret; - indio_dev->ring = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->ring) { + 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->ring->access = &ring_sw_access_funcs; + indio_dev->buffer->access = &ring_sw_access_funcs; + indio_dev->buffer->bpe = + st->chip_info->channels[0].scan_type.storagebits / 8; indio_dev->pollfunc = iio_alloc_pollfunc(&ad7606_trigger_handler_th_bh, &ad7606_trigger_handler_th_bh, 0, @@ -183,28 +152,23 @@ int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev) /* Ring buffer functions - here trigger setup related */ - indio_dev->ring->setup_ops = &ad7606_ring_setup_ops; - indio_dev->ring->scan_timestamp = true ; + indio_dev->buffer->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_RING_TRIGGERED; + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; return 0; error_deallocate_sw_rb: - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); error_ret: return ret; } void ad7606_ring_cleanup(struct iio_dev *indio_dev) { - if (indio_dev->trig) { - iio_put_trigger(indio_dev->trig); - iio_trigger_dettach_poll_func(indio_dev->trig, - indio_dev->pollfunc); - } iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); } diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c index 0769c80..aede1ba 100644 --- a/drivers/staging/iio/adc/ad7606_spi.c +++ b/drivers/staging/iio/adc/ad7606_spi.c @@ -59,7 +59,7 @@ static int __devexit ad7606_spi_remove(struct spi_device *spi) { struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev); - return ad7606_remove(indio_dev); + return ad7606_remove(indio_dev, spi->irq); } #ifdef CONFIG_PM diff --git a/drivers/staging/iio/adc/ad7745.c b/drivers/staging/iio/adc/ad7745.c deleted file mode 100644 index 4c13f26..0000000 --- a/drivers/staging/iio/adc/ad7745.c +++ /dev/null @@ -1,674 +0,0 @@ -/* - * AD774X capacitive sensor driver supporting AD7745/6/7 - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/interrupt.h> -#include <linux/gpio.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 "../iio.h" -#include "../sysfs.h" - -/* - * AD774X registers definition - */ - -#define AD774X_STATUS 0 -#define AD774X_STATUS_RDY (1 << 2) -#define AD774X_STATUS_RDYVT (1 << 1) -#define AD774X_STATUS_RDYCAP (1 << 0) -#define AD774X_CAP_DATA_HIGH 1 -#define AD774X_CAP_DATA_MID 2 -#define AD774X_CAP_DATA_LOW 3 -#define AD774X_VT_DATA_HIGH 4 -#define AD774X_VT_DATA_MID 5 -#define AD774X_VT_DATA_LOW 6 -#define AD774X_CAP_SETUP 7 -#define AD774X_VT_SETUP 8 -#define AD774X_EXEC_SETUP 9 -#define AD774X_CFG 10 -#define AD774X_CAPDACA 11 -#define AD774X_CAPDACB 12 -#define AD774X_CAPDAC_EN (1 << 7) -#define AD774X_CAP_OFFH 13 -#define AD774X_CAP_OFFL 14 -#define AD774X_CAP_GAINH 15 -#define AD774X_CAP_GAINL 16 -#define AD774X_VOLT_GAINH 17 -#define AD774X_VOLT_GAINL 18 - -#define AD774X_MAX_CONV_MODE 6 - -/* - * struct ad774x_chip_info - chip specifc information - */ - -struct ad774x_chip_info { - struct i2c_client *client; - bool inter; - u16 cap_offs; /* Capacitive offset */ - u16 cap_gain; /* Capacitive gain calibration */ - u16 volt_gain; /* Voltage gain calibration */ - u8 cap_setup; - u8 vt_setup; - u8 exec_setup; - - char *conversion_mode; -}; - -struct ad774x_conversion_mode { - char *name; - u8 reg_cfg; -}; - -static struct ad774x_conversion_mode -ad774x_conv_mode_table[AD774X_MAX_CONV_MODE] = { - { "idle", 0 }, - { "continuous-conversion", 1 }, - { "single-conversion", 2 }, - { "power-down", 3 }, - { "offset-calibration", 5 }, - { "gain-calibration", 6 }, -}; - -/* - * ad774x register access by I2C - */ - -static int ad774x_i2c_read(struct ad774x_chip_info *chip, u8 reg, u8 *data, int len) -{ - struct i2c_client *client = chip->client; - int ret; - - ret = i2c_master_send(client, ®, 1); - if (ret < 0) { - dev_err(&client->dev, "I2C write error\n"); - return ret; - } - - ret = i2c_master_recv(client, data, len); - if (ret < 0) { - dev_err(&client->dev, "I2C read error\n"); - return ret; - } - - return ret; -} - -static int ad774x_i2c_write(struct ad774x_chip_info *chip, u8 reg, u8 data) -{ - struct i2c_client *client = chip->client; - int ret; - - u8 tx[2] = { - reg, - data, - }; - - ret = i2c_master_send(client, tx, 2); - if (ret < 0) - dev_err(&client->dev, "I2C write error\n"); - - return ret; -} - -/* - * sysfs nodes - */ - -#define IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(_show) \ - IIO_DEVICE_ATTR(available_conversion_modes, S_IRUGO, _show, NULL, 0) -#define IIO_DEV_ATTR_CONVERSION_MODE(_mode, _show, _store) \ - IIO_DEVICE_ATTR(conversion_mode, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CAP_SETUP(_mode, _show, _store) \ - IIO_DEVICE_ATTR(cap_setup, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_VT_SETUP(_mode, _show, _store) \ - IIO_DEVICE_ATTR(in0_setup, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_EXEC_SETUP(_mode, _show, _store) \ - IIO_DEVICE_ATTR(exec_setup, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_VOLT_GAIN(_mode, _show, _store) \ - IIO_DEVICE_ATTR(in0_gain, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CAP_OFFS(_mode, _show, _store) \ - IIO_DEVICE_ATTR(cap_offs, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CAP_GAIN(_mode, _show, _store) \ - IIO_DEVICE_ATTR(cap_gain, _mode, _show, _store, 0) -#define IIO_DEV_ATTR_CAP_DATA(_show) \ - IIO_DEVICE_ATTR(cap0_raw, S_IRUGO, _show, NULL, 0) -#define IIO_DEV_ATTR_VT_DATA(_show) \ - IIO_DEVICE_ATTR(in0_raw, S_IRUGO, _show, NULL, 0) - -static ssize_t ad774x_show_conversion_modes(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int i; - int len = 0; - - for (i = 0; i < AD774X_MAX_CONV_MODE; i++) - len += sprintf(buf + len, "%s ", ad774x_conv_mode_table[i].name); - - len += sprintf(buf + len, "\n"); - - return len; -} - -static IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(ad774x_show_conversion_modes); - -static ssize_t ad774x_show_conversion_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%s\n", chip->conversion_mode); -} - -static ssize_t ad774x_store_conversion_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - u8 cfg; - int i; - - ad774x_i2c_read(chip, AD774X_CFG, &cfg, 1); - - for (i = 0; i < AD774X_MAX_CONV_MODE; i++) { - if (strncmp(buf, ad774x_conv_mode_table[i].name, - strlen(ad774x_conv_mode_table[i].name) - 1) == 0) { - chip->conversion_mode = ad774x_conv_mode_table[i].name; - cfg |= 0x18 | ad774x_conv_mode_table[i].reg_cfg; - ad774x_i2c_write(chip, AD774X_CFG, cfg); - return len; - } - } - - dev_err(dev, "not supported conversion mode\n"); - - return -EINVAL; -} - -static IIO_DEV_ATTR_CONVERSION_MODE(S_IRUGO | S_IWUSR, - ad774x_show_conversion_mode, - ad774x_store_conversion_mode); - -static ssize_t ad774x_show_dac_value(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - u8 data; - - ad774x_i2c_read(chip, this_attr->address, &data, 1); - - return sprintf(buf, "%02x\n", data & 0x7F); -} - -static ssize_t ad774x_store_dac_value(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if (!ret) { - ad774x_i2c_write(chip, this_attr->address, - (data ? AD774X_CAPDAC_EN : 0) | (data & 0x7F)); - return len; - } - - return -EINVAL; -} - -static IIO_DEVICE_ATTR(capdac0_raw, S_IRUGO | S_IWUSR, - ad774x_show_dac_value, - ad774x_store_dac_value, - AD774X_CAPDACA); - -static IIO_DEVICE_ATTR(capdac1_raw, S_IRUGO | S_IWUSR, - ad774x_show_dac_value, - ad774x_store_dac_value, - AD774X_CAPDACB); - -static ssize_t ad774x_show_cap_setup(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "0x%02x\n", chip->cap_setup); -} - -static ssize_t ad774x_store_cap_setup(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x100)) { - ad774x_i2c_write(chip, AD774X_CAP_SETUP, data); - chip->cap_setup = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_CAP_SETUP(S_IRUGO | S_IWUSR, - ad774x_show_cap_setup, - ad774x_store_cap_setup); - -static ssize_t ad774x_show_vt_setup(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "0x%02x\n", chip->vt_setup); -} - -static ssize_t ad774x_store_vt_setup(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x100)) { - ad774x_i2c_write(chip, AD774X_VT_SETUP, data); - chip->vt_setup = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_VT_SETUP(S_IRUGO | S_IWUSR, - ad774x_show_vt_setup, - ad774x_store_vt_setup); - -static ssize_t ad774x_show_exec_setup(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "0x%02x\n", chip->exec_setup); -} - -static ssize_t ad774x_store_exec_setup(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x100)) { - ad774x_i2c_write(chip, AD774X_EXEC_SETUP, data); - chip->exec_setup = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_EXEC_SETUP(S_IRUGO | S_IWUSR, - ad774x_show_exec_setup, - ad774x_store_exec_setup); - -static ssize_t ad774x_show_volt_gain(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%d\n", chip->volt_gain); -} - -static ssize_t ad774x_store_volt_gain(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x10000)) { - ad774x_i2c_write(chip, AD774X_VOLT_GAINH, data >> 8); - ad774x_i2c_write(chip, AD774X_VOLT_GAINL, data); - chip->volt_gain = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_VOLT_GAIN(S_IRUGO | S_IWUSR, - ad774x_show_volt_gain, - ad774x_store_volt_gain); - -static ssize_t ad774x_show_cap_data(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - unsigned long data; - char tmp[3]; - - ad774x_i2c_read(chip, AD774X_CAP_DATA_HIGH, tmp, 3); - data = ((int)tmp[0] << 16) | ((int)tmp[1] << 8) | (int)tmp[2]; - - return sprintf(buf, "%ld\n", data); -} - -static IIO_DEV_ATTR_CAP_DATA(ad774x_show_cap_data); - -static ssize_t ad774x_show_vt_data(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - unsigned long data; - char tmp[3]; - - ad774x_i2c_read(chip, AD774X_VT_DATA_HIGH, tmp, 3); - data = ((int)tmp[0] << 16) | ((int)tmp[1] << 8) | (int)tmp[2]; - - return sprintf(buf, "%ld\n", data); -} - -static IIO_DEV_ATTR_VT_DATA(ad774x_show_vt_data); - -static ssize_t ad774x_show_cap_offs(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%d\n", chip->cap_offs); -} - -static ssize_t ad774x_store_cap_offs(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x10000)) { - ad774x_i2c_write(chip, AD774X_CAP_OFFH, data >> 8); - ad774x_i2c_write(chip, AD774X_CAP_OFFL, data); - chip->cap_offs = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_CAP_OFFS(S_IRUGO | S_IWUSR, - ad774x_show_cap_offs, - ad774x_store_cap_offs); - -static ssize_t ad774x_show_cap_gain(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - - return sprintf(buf, "%d\n", chip->cap_gain); -} - -static ssize_t ad774x_store_cap_gain(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad774x_chip_info *chip = iio_priv(dev_info); - unsigned long data; - int ret; - - ret = strict_strtoul(buf, 10, &data); - - if ((!ret) && (data < 0x10000)) { - ad774x_i2c_write(chip, AD774X_CAP_GAINH, data >> 8); - ad774x_i2c_write(chip, AD774X_CAP_GAINL, data); - chip->cap_gain = data; - return len; - } - - return -EINVAL; -} - -static IIO_DEV_ATTR_CAP_GAIN(S_IRUGO | S_IWUSR, - ad774x_show_cap_gain, - ad774x_store_cap_gain); - -static struct attribute *ad774x_attributes[] = { - &iio_dev_attr_available_conversion_modes.dev_attr.attr, - &iio_dev_attr_conversion_mode.dev_attr.attr, - &iio_dev_attr_cap_setup.dev_attr.attr, - &iio_dev_attr_in0_setup.dev_attr.attr, - &iio_dev_attr_exec_setup.dev_attr.attr, - &iio_dev_attr_cap_offs.dev_attr.attr, - &iio_dev_attr_cap_gain.dev_attr.attr, - &iio_dev_attr_in0_gain.dev_attr.attr, - &iio_dev_attr_in0_raw.dev_attr.attr, - &iio_dev_attr_cap0_raw.dev_attr.attr, - &iio_dev_attr_capdac0_raw.dev_attr.attr, - &iio_dev_attr_capdac1_raw.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad774x_attribute_group = { - .attrs = ad774x_attributes, -}; - -/* - * data ready events - */ - -#define IIO_EVENT_CODE_CAP_RDY 0 -#define IIO_EVENT_CODE_VT_RDY 1 - -#define IIO_EVENT_ATTR_CAP_RDY_SH(_evlist, _show, _store, _mask) \ - IIO_EVENT_ATTR_SH(cap_rdy, _evlist, _show, _store, _mask) - -#define IIO_EVENT_ATTR_VT_RDY_SH(_evlist, _show, _store, _mask) \ - IIO_EVENT_ATTR_SH(vt_rdy, _evlist, _show, _store, _mask) - -static irqreturn_t ad774x_event_handler(int irq, void *private) -{ - struct iio_dev *indio_dev = private; - struct ad774x_chip_info *chip = iio_priv(indio_dev); - u8 int_status; - - ad774x_i2c_read(chip, AD774X_STATUS, &int_status, 1); - - if (int_status & AD774X_STATUS_RDYCAP) - iio_push_event(indio_dev, 0, - IIO_EVENT_CODE_CAP_RDY, - iio_get_time_ns()); - - if (int_status & AD774X_STATUS_RDYVT) - iio_push_event(indio_dev, 0, - IIO_EVENT_CODE_VT_RDY, - iio_get_time_ns()); - - return IRQ_HANDLED; -} - -static IIO_CONST_ATTR(cap_rdy_en, "1"); -static IIO_CONST_ATTR(vt_rdy_en, "1"); - -static struct attribute *ad774x_event_attributes[] = { - &iio_const_attr_cap_rdy_en.dev_attr.attr, - &iio_const_attr_vt_rdy_en.dev_attr.attr, - NULL, -}; - -static struct attribute_group ad774x_event_attribute_group = { - .attrs = ad774x_event_attributes, -}; - -static const struct iio_info ad774x_info = { - .attrs = &ad774x_event_attribute_group, - .event_attrs = &ad774x_event_attribute_group, - .num_interrupt_lines = 1, - .driver_module = THIS_MODULE, -}; -/* - * device probe and remove - */ - -static int __devinit ad774x_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int ret = 0, regdone = 0; - struct ad774x_chip_info *chip; - struct iio_dev *indio_dev; - - 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; - - /* Establish that the iio_dev is a child of the i2c device */ - indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; - indio_dev->info = &ad774x_info; - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - regdone = 1; - - if (client->irq) { - ret = request_threaded_irq(client->irq, - NULL, - &ad774x_event_handler, - IRQF_TRIGGER_FALLING, - "ad774x", - indio_dev); - if (ret) - goto error_free_dev; - } - - dev_err(&client->dev, "%s capacitive sensor registered, irq: %d\n", id->name, client->irq); - - return 0; - -error_free_dev: - if (regdone) - free_irq(client->irq, indio_dev); - else - iio_free_device(indio_dev); -error_ret: - return ret; -} - -static int __devexit ad774x_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - - if (client->irq) - free_irq(client->irq, indio_dev); - iio_device_unregister(indio_dev); - - return 0; -} - -static const struct i2c_device_id ad774x_id[] = { - { "ad7745", 0 }, - { "ad7746", 0 }, - { "ad7747", 0 }, - {} -}; - -MODULE_DEVICE_TABLE(i2c, ad774x_id); - -static struct i2c_driver ad774x_driver = { - .driver = { - .name = "ad774x", - }, - .probe = ad774x_probe, - .remove = __devexit_p(ad774x_remove), - .id_table = ad774x_id, -}; - -static __init int ad774x_init(void) -{ - return i2c_add_driver(&ad774x_driver); -} - -static __exit void ad774x_exit(void) -{ - i2c_del_driver(&ad774x_driver); -} - -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_DESCRIPTION("Analog Devices ad7745/6/7 capacitive sensor driver"); -MODULE_LICENSE("GPL v2"); - -module_init(ad774x_init); -module_exit(ad774x_exit); diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c index e0c7b6c..7a579a1 100644 --- a/drivers/staging/iio/adc/ad7780.c +++ b/drivers/staging/iio/adc/ad7780.c @@ -16,11 +16,10 @@ #include <linux/err.h> #include <linux/sched.h> #include <linux/gpio.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" -#include "adc.h" #include "ad7780.h" @@ -127,12 +126,12 @@ static int ad7780_read_raw(struct iio_dev *indio_dev, static const struct ad7780_chip_info ad7780_chip_info_tbl[] = { [ID_AD7780] = { - .channel = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, + .channel = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 0, 0, IIO_ST('s', 24, 32, 8), 0), }, [ID_AD7781] = { - .channel = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, + .channel = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), 0, 0, IIO_ST('s', 20, 32, 12), 0), }, @@ -256,13 +255,14 @@ static int ad7780_remove(struct spi_device *spi) struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad7780_state *st = iio_priv(indio_dev); + iio_device_unregister(indio_dev); free_irq(spi->irq, st); gpio_free(st->pdata->gpio_pdrst); if (!IS_ERR(st->reg)) { regulator_disable(st->reg); regulator_put(st->reg); } - iio_device_unregister(indio_dev); + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index 90f6c03..a831b92 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -19,10 +19,10 @@ #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" +#include "../buffer_generic.h" #include "../ring_sw.h" #include "../trigger.h" -#include "adc.h" +#include "../trigger_consumer.h" #include "ad7793.h" @@ -51,7 +51,8 @@ struct ad7793_state { u16 mode; u16 conf; u32 scale_avail[8][2]; - u32 available_scan_masks[7]; + /* 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. @@ -316,12 +317,12 @@ out: static int ad7793_scan_from_ring(struct ad7793_state *st, unsigned ch, int *val) { - struct iio_ring_buffer *ring = iio_priv_to_dev(st)->ring; + struct iio_buffer *ring = iio_priv_to_dev(st)->buffer; int ret; s64 dat64[2]; u32 *dat32 = (u32 *)dat64; - if (!(ring->scan_mask & (1 << ch))) + if (!(test_bit(ch, ring->scan_mask))) return -EBUSY; ret = ring->access->read_last(ring, (u8 *) &dat64); @@ -336,14 +337,15 @@ static int ad7793_scan_from_ring(struct ad7793_state *st, unsigned ch, int *val) static int ad7793_ring_preenable(struct iio_dev *indio_dev) { struct ad7793_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; size_t d_size; unsigned channel; if (!ring->scan_count) return -EINVAL; - channel = __ffs(ring->scan_mask); + channel = find_first_bit(ring->scan_mask, + indio_dev->masklength); d_size = ring->scan_count * indio_dev->channels[0].scan_type.storagebits / 8; @@ -355,9 +357,9 @@ static int ad7793_ring_preenable(struct iio_dev *indio_dev) d_size += sizeof(s64) - (d_size % sizeof(s64)); } - if (indio_dev->ring->access->set_bytes_per_datum) - indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring, - d_size); + 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); @@ -402,8 +404,8 @@ static int ad7793_ring_postdisable(struct iio_dev *indio_dev) static irqreturn_t ad7793_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->private_data; - struct iio_ring_buffer *ring = indio_dev->ring; + 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; @@ -426,10 +428,10 @@ static irqreturn_t ad7793_trigger_handler(int irq, void *p) return IRQ_HANDLED; } -static const struct iio_ring_setup_ops ad7793_ring_setup_ops = { +static const struct iio_buffer_setup_ops ad7793_ring_setup_ops = { .preenable = &ad7793_ring_preenable, - .postenable = &iio_triggered_ring_postenable, - .predisable = &iio_triggered_ring_predisable, + .postenable = &iio_triggered_buffer_postenable, + .predisable = &iio_triggered_buffer_predisable, .postdisable = &ad7793_ring_postdisable, }; @@ -437,13 +439,13 @@ static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev) { int ret; - indio_dev->ring = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->ring) { + 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->ring->access = &ring_sw_access_funcs; + indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &ad7793_trigger_handler, IRQF_ONESHOT, @@ -456,28 +458,22 @@ static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev) } /* Ring buffer functions - here trigger setup related */ - indio_dev->ring->setup_ops = &ad7793_ring_setup_ops; + indio_dev->buffer->setup_ops = &ad7793_ring_setup_ops; /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_RING_TRIGGERED; + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; return 0; error_deallocate_sw_rb: - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); error_ret: return ret; } static void ad7793_ring_cleanup(struct iio_dev *indio_dev) { - /* ensure that the trigger has been detached */ - if (indio_dev->trig) { - iio_put_trigger(indio_dev->trig); - iio_trigger_dettach_poll_func(indio_dev->trig, - indio_dev->pollfunc); - } iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); } /** @@ -574,7 +570,7 @@ static ssize_t ad7793_write_frequency(struct device *dev, int i, ret; mutex_lock(&indio_dev->mlock); - if (iio_ring_enabled(indio_dev)) { + if (iio_buffer_enabled(indio_dev)) { mutex_unlock(&indio_dev->mlock); return -EBUSY; } @@ -651,7 +647,7 @@ static int ad7793_read_raw(struct iio_dev *indio_dev, switch (m) { case 0: mutex_lock(&indio_dev->mlock); - if (iio_ring_enabled(indio_dev)) + if (iio_buffer_enabled(indio_dev)) ret = ad7793_scan_from_ring(st, chan->scan_index, &smpl); else @@ -678,7 +674,7 @@ static int ad7793_read_raw(struct iio_dev *indio_dev, case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): switch (chan->type) { - case IIO_IN: + case IIO_VOLTAGE: /* 1170mV / 2^23 * 6 */ scale_uv = (1170ULL * 100000000ULL * 6ULL) >> (chan->scan_type.realbits - @@ -713,7 +709,7 @@ static int ad7793_write_raw(struct iio_dev *indio_dev, unsigned int tmp; mutex_lock(&indio_dev->mlock); - if (iio_ring_enabled(indio_dev)) { + if (iio_buffer_enabled(indio_dev)) { mutex_unlock(&indio_dev->mlock); return -EBUSY; } @@ -771,57 +767,137 @@ static const struct iio_info ad7793_info = { static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { [ID_AD7793] = { - .channel[0] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD7793_CH_AIN1P_AIN1M, - 0, IIO_ST('s', 24, 32, 0), 0), - .channel[1] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 1, 1, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD7793_CH_AIN2P_AIN2M, - 1, IIO_ST('s', 24, 32, 0), 0), - .channel[2] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 2, 2, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD7793_CH_AIN3P_AIN3M, - 2, IIO_ST('s', 24, 32, 0), 0), - .channel[3] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, "shorted", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD7793_CH_AIN1M_AIN1M, - 3, IIO_ST('s', 24, 32, 0), 0), - .channel[4] = IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - AD7793_CH_TEMP, - 4, IIO_ST('s', 24, 32, 0), 0), - .channel[5] = IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 4, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - AD7793_CH_AVDD_MONITOR, - 5, IIO_ST('s', 24, 32, 0), 0), + .channel[0] = { + .type = IIO_VOLTAGE, + .differential = 1, + .indexed = 1, + .channel = 0, + .channel2 = 0, + .address = AD7793_CH_AIN1P_AIN1M, + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .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 = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .scan_index = 5, + .scan_type = IIO_ST('s', 24, 32, 0), + }, .channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6), }, [ID_AD7792] = { - .channel[0] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD7793_CH_AIN1P_AIN1M, - 0, IIO_ST('s', 16, 32, 0), 0), - .channel[1] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 1, 1, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD7793_CH_AIN2P_AIN2M, - 1, IIO_ST('s', 16, 32, 0), 0), - .channel[2] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 2, 2, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD7793_CH_AIN3P_AIN3M, - 2, IIO_ST('s', 16, 32, 0), 0), - .channel[3] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, "shorted", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD7793_CH_AIN1M_AIN1M, - 3, IIO_ST('s', 16, 32, 0), 0), - .channel[4] = IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - AD7793_CH_TEMP, - 4, IIO_ST('s', 16, 32, 0), 0), - .channel[5] = IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 4, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - AD7793_CH_AVDD_MONITOR, - 5, IIO_ST('s', 16, 32, 0), 0), + .channel[0] = { + .type = IIO_VOLTAGE, + .differential = 1, + .indexed = 1, + .channel = 0, + .channel2 = 0, + .address = AD7793_CH_AIN1P_AIN1M, + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .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 = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .scan_index = 5, + .scan_type = IIO_ST('s', 16, 32, 0), + }, .channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6), }, }; @@ -831,7 +907,7 @@ 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, regdone = 0; + int ret, i, voltage_uv = 0; if (!pdata) { dev_err(&spi->dev, "no platform data?\n"); @@ -881,10 +957,12 @@ static int __devinit ad7793_probe(struct spi_device *spi) indio_dev->num_channels = 7; indio_dev->info = &ad7793_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); + 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); @@ -892,18 +970,13 @@ static int __devinit ad7793_probe(struct spi_device *spi) if (ret) goto error_disable_reg; - ret = iio_device_register(indio_dev); - if (ret) - goto error_unreg_ring; - regdone = 1; - ret = ad7793_probe_trigger(indio_dev); if (ret) goto error_unreg_ring; - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - indio_dev->channels, - indio_dev->num_channels); + ret = iio_buffer_register(indio_dev, + indio_dev->channels, + indio_dev->num_channels); if (ret) goto error_remove_trigger; @@ -911,10 +984,14 @@ static int __devinit ad7793_probe(struct spi_device *spi) if (ret) goto error_uninitialize_ring; + ret = iio_device_register(indio_dev); + if (ret) + goto error_uninitialize_ring; + return 0; error_uninitialize_ring: - iio_ring_buffer_unregister(indio_dev->ring); + iio_buffer_unregister(indio_dev); error_remove_trigger: ad7793_remove_trigger(indio_dev); error_unreg_ring: @@ -926,10 +1003,7 @@ error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); return ret; } @@ -939,7 +1013,8 @@ 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_ring_buffer_unregister(indio_dev->ring); + iio_device_unregister(indio_dev); + iio_buffer_unregister(indio_dev); ad7793_remove_trigger(indio_dev); ad7793_ring_cleanup(indio_dev); @@ -948,7 +1023,7 @@ static int ad7793_remove(struct spi_device *spi) regulator_put(st->reg); } - iio_device_unregister(indio_dev); + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c index 0c84217..bdb9049 100644 --- a/drivers/staging/iio/adc/ad7816.c +++ b/drivers/staging/iio/adc/ad7816.c @@ -14,6 +14,7 @@ #include <linux/sysfs.h> #include <linux/list.h> #include <linux/spi/spi.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -111,8 +112,8 @@ static ssize_t ad7816_show_mode(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7816_chip_info *chip = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7816_chip_info *chip = iio_priv(indio_dev); if (chip->mode) return sprintf(buf, "power-save\n"); @@ -125,8 +126,8 @@ static ssize_t ad7816_store_mode(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7816_chip_info *chip = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7816_chip_info *chip = iio_priv(indio_dev); if (strcmp(buf, "full")) { gpio_set_value(chip->rdwr_pin, 1); @@ -157,8 +158,8 @@ static ssize_t ad7816_show_channel(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7816_chip_info *chip = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7816_chip_info *chip = iio_priv(indio_dev); return sprintf(buf, "%d\n", chip->channel_id); } @@ -168,8 +169,8 @@ static ssize_t ad7816_store_channel(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7816_chip_info *chip = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7816_chip_info *chip = iio_priv(indio_dev); unsigned long data; int ret; @@ -179,13 +180,13 @@ static ssize_t ad7816_store_channel(struct device *dev, if (data > AD7816_CS_MAX && data != AD7816_CS_MASK) { dev_err(&chip->spi_dev->dev, "Invalid channel id %lu for %s.\n", - data, dev_info->name); + data, indio_dev->name); return -EINVAL; - } else if (strcmp(dev_info->name, "ad7818") == 0 && data > 1) { + } else if (strcmp(indio_dev->name, "ad7818") == 0 && data > 1) { dev_err(&chip->spi_dev->dev, "Invalid channel id %lu for ad7818.\n", data); return -EINVAL; - } else if (strcmp(dev_info->name, "ad7816") == 0 && data > 0) { + } else if (strcmp(indio_dev->name, "ad7816") == 0 && data > 0) { dev_err(&chip->spi_dev->dev, "Invalid channel id %lu for ad7816.\n", data); return -EINVAL; @@ -206,8 +207,8 @@ static ssize_t ad7816_show_value(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7816_chip_info *chip = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7816_chip_info *chip = iio_priv(indio_dev); u16 data; s8 value; int ret; @@ -246,16 +247,14 @@ static const struct attribute_group ad7816_attribute_group = { * temperature bound events */ -#define IIO_EVENT_CODE_AD7816_OTI IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_TEMP, \ +#define IIO_EVENT_CODE_AD7816_OTI IIO_UNMOD_EVENT_CODE(IIO_TEMP, \ 0, \ IIO_EV_TYPE_THRESH, \ IIO_EV_DIR_FALLING) static irqreturn_t ad7816_event_handler(int irq, void *private) { - iio_push_event(private, 0, - IIO_EVENT_CODE_AD7816_OTI, - iio_get_time_ns()); + iio_push_event(private, IIO_EVENT_CODE_AD7816_OTI, iio_get_time_ns()); return IRQ_HANDLED; } @@ -263,8 +262,8 @@ static ssize_t ad7816_show_oti(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7816_chip_info *chip = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7816_chip_info *chip = iio_priv(indio_dev); int value; if (chip->channel_id > AD7816_CS_MAX) { @@ -284,8 +283,8 @@ static inline ssize_t ad7816_set_oti(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7816_chip_info *chip = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7816_chip_info *chip = iio_priv(indio_dev); long value; u8 data; int ret; @@ -328,11 +327,11 @@ static struct attribute *ad7816_event_attributes[] = { static struct attribute_group ad7816_event_attribute_group = { .attrs = ad7816_event_attributes, + .name = "events", }; static const struct iio_info ad7816_info = { .attrs = &ad7816_attribute_group, - .num_interrupt_lines = 1, .event_attrs = &ad7816_event_attribute_group, .driver_module = THIS_MODULE, }; @@ -397,10 +396,6 @@ static int __devinit ad7816_probe(struct spi_device *spi_dev) indio_dev->info = &ad7816_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_gpio; - if (spi_dev->irq) { /* Only low trigger is supported in ad7816/7/8 */ ret = request_threaded_irq(spi_dev->irq, @@ -410,16 +405,19 @@ static int __devinit ad7816_probe(struct spi_device *spi_dev) indio_dev->name, indio_dev); if (ret) - goto error_unreg_dev; + goto error_free_gpio; } + ret = iio_device_register(indio_dev); + if (ret) + goto error_free_irq; + dev_info(&spi_dev->dev, "%s temperature sensor and ADC registered.\n", indio_dev->name); return 0; - -error_unreg_dev: - iio_device_unregister(indio_dev); +error_free_irq: + free_irq(spi_dev->irq, indio_dev); error_free_gpio: gpio_free(chip->busy_pin); error_free_gpio_convert: @@ -437,13 +435,13 @@ 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_device_unregister(indio_dev); iio_free_device(indio_dev); return 0; diff --git a/drivers/staging/iio/adc/ad7887.h b/drivers/staging/iio/adc/ad7887.h index 837046c..3452d18 100644 --- a/drivers/staging/iio/adc/ad7887.h +++ b/drivers/staging/iio/adc/ad7887.h @@ -82,12 +82,12 @@ enum ad7887_supported_device_ids { ID_AD7887 }; -#ifdef CONFIG_IIO_RING_BUFFER -int ad7887_scan_from_ring(struct ad7887_state *st, long mask); +#ifdef CONFIG_IIO_BUFFER +int ad7887_scan_from_ring(struct ad7887_state *st, int channum); int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev); void ad7887_ring_cleanup(struct iio_dev *indio_dev); -#else /* CONFIG_IIO_RING_BUFFER */ -static inline int ad7887_scan_from_ring(struct ad7887_state *st, long mask) +#else /* CONFIG_IIO_BUFFER */ +static inline int ad7887_scan_from_ring(struct ad7887_state *st, int channum) { return 0; } @@ -101,5 +101,5 @@ ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev) static inline void ad7887_ring_cleanup(struct iio_dev *indio_dev) { } -#endif /* CONFIG_IIO_RING_BUFFER */ +#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 index 3d9121e..609dcd5 100644 --- a/drivers/staging/iio/adc/ad7887_core.c +++ b/drivers/staging/iio/adc/ad7887_core.c @@ -13,11 +13,12 @@ #include <linux/spi/spi.h> #include <linux/regulator/consumer.h> #include <linux/err.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" -#include "adc.h" +#include "../buffer_generic.h" + #include "ad7887.h" @@ -30,24 +31,24 @@ static int ad7887_scan_direct(struct ad7887_state *st, unsigned ch) return (st->data[(ch * 2)] << 8) | st->data[(ch * 2) + 1]; } -static int ad7887_read_raw(struct iio_dev *dev_info, +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(dev_info); + struct ad7887_state *st = iio_priv(indio_dev); unsigned int scale_uv; switch (m) { case 0: - mutex_lock(&dev_info->mlock); - if (iio_ring_enabled(dev_info)) + mutex_lock(&indio_dev->mlock); + if (iio_buffer_enabled(indio_dev)) ret = ad7887_scan_from_ring(st, 1 << chan->address); else ret = ad7887_scan_direct(st, chan->address); - mutex_unlock(&dev_info->mlock); + mutex_unlock(&indio_dev->mlock); if (ret < 0) return ret; @@ -70,14 +71,24 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = { * More devices added in future */ [ID_AD7887] = { - .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 1, 1, IIO_ST('u', 12, 16, 0), 0), - - .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 0, 0, IIO_ST('u', 12, 16, 0), 0), - + .channel[0] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 1, + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .address = 1, + .scan_index = 1, + .scan_type = IIO_ST('u', 12, 16, 0), + }, + .channel[1] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .address = 0, + .scan_index = 0, + .scan_type = IIO_ST('u', 12, 16, 0), + }, .channel[2] = IIO_CHAN_SOFT_TIMESTAMP(2), .int_vref_mv = 2500, }, @@ -92,7 +103,7 @@ 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, regdone = 0; + int ret, voltage_uv = 0; struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); if (indio_dev == NULL) @@ -188,18 +199,19 @@ static int __devinit ad7887_probe(struct spi_device *spi) if (ret) goto error_disable_reg; - ret = iio_device_register(indio_dev); + ret = iio_buffer_register(indio_dev, + indio_dev->channels, + indio_dev->num_channels); if (ret) - goto error_disable_reg; - regdone = 1; + goto error_cleanup_ring; - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - indio_dev->channels, - indio_dev->num_channels); + ret = iio_device_register(indio_dev); if (ret) - goto error_cleanup_ring; - return 0; + 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: @@ -208,10 +220,7 @@ error_disable_reg: error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); return ret; } @@ -221,13 +230,14 @@ 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_ring_buffer_unregister(indio_dev->ring); + 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_device_unregister(indio_dev); + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c index 0ac7c0b..cb74cad 100644 --- a/drivers/staging/iio/adc/ad7887_ring.c +++ b/drivers/staging/iio/adc/ad7887_ring.c @@ -8,27 +8,24 @@ */ #include <linux/interrupt.h> -#include <linux/device.h> #include <linux/kernel.h> #include <linux/slab.h> -#include <linux/sysfs.h> #include <linux/spi/spi.h> #include "../iio.h" -#include "../ring_generic.h" +#include "../buffer_generic.h" #include "../ring_sw.h" -#include "../trigger.h" -#include "../sysfs.h" +#include "../trigger_consumer.h" #include "ad7887.h" -int ad7887_scan_from_ring(struct ad7887_state *st, long mask) +int ad7887_scan_from_ring(struct ad7887_state *st, int channum) { - struct iio_ring_buffer *ring = iio_priv_to_dev(st)->ring; + struct iio_buffer *ring = iio_priv_to_dev(st)->buffer; int count = 0, ret; u16 *ring_data; - if (!(ring->scan_mask & mask)) { + if (!(test_bit(channum, ring->scan_mask))) { ret = -EBUSY; goto error_ret; } @@ -44,7 +41,8 @@ int ad7887_scan_from_ring(struct ad7887_state *st, long mask) goto error_free_ring_data; /* for single channel scan the result is stored with zero offset */ - if ((ring->scan_mask == ((1 << 1) | (1 << 0))) && (mask == (1 << 1))) + if ((test_bit(1, ring->scan_mask) || test_bit(0, ring->scan_mask)) && + (channum == 1)) count = 1; ret = be16_to_cpu(ring_data[count]); @@ -65,7 +63,7 @@ error_ret: static int ad7887_ring_preenable(struct iio_dev *indio_dev) { struct ad7887_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; st->d_size = ring->scan_count * st->chip_info->channel[0].scan_type.storagebits / 8; @@ -77,11 +75,12 @@ static int ad7887_ring_preenable(struct iio_dev *indio_dev) st->d_size += sizeof(s64) - (st->d_size % sizeof(s64)); } - if (indio_dev->ring->access->set_bytes_per_datum) - indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring, - st->d_size); + if (indio_dev->buffer->access->set_bytes_per_datum) + indio_dev->buffer->access-> + set_bytes_per_datum(indio_dev->buffer, st->d_size); - switch (ring->scan_mask) { + /* We know this is a single long so can 'cheat' */ + switch (*ring->scan_mask) { case (1 << 0): st->ring_msg = &st->msg[AD7887_CH0]; break; @@ -115,9 +114,9 @@ static int ad7887_ring_postdisable(struct iio_dev *indio_dev) static irqreturn_t ad7887_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->private_data; + struct iio_dev *indio_dev = pf->indio_dev; struct ad7887_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; s64 time_ns; __u8 *buf; int b_sent; @@ -140,7 +139,7 @@ static irqreturn_t ad7887_trigger_handler(int irq, void *p) memcpy(buf + st->d_size - sizeof(s64), &time_ns, sizeof(time_ns)); - indio_dev->ring->access->store_to(indio_dev->ring, buf, time_ns); + indio_dev->buffer->access->store_to(indio_dev->buffer, buf, time_ns); done: kfree(buf); iio_trigger_notify_done(indio_dev->trig); @@ -148,10 +147,10 @@ done: return IRQ_HANDLED; } -static const struct iio_ring_setup_ops ad7887_ring_setup_ops = { +static const struct iio_buffer_setup_ops ad7887_ring_setup_ops = { .preenable = &ad7887_ring_preenable, - .postenable = &iio_triggered_ring_postenable, - .predisable = &iio_triggered_ring_predisable, + .postenable = &iio_triggered_buffer_postenable, + .predisable = &iio_triggered_buffer_predisable, .postdisable = &ad7887_ring_postdisable, }; @@ -159,13 +158,13 @@ int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev) { int ret; - indio_dev->ring = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->ring) { + 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->ring->access = &ring_sw_access_funcs; + indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &ad7887_trigger_handler, IRQF_ONESHOT, @@ -177,26 +176,20 @@ int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev) goto error_deallocate_sw_rb; } /* Ring buffer functions - here trigger setup related */ - indio_dev->ring->setup_ops = &ad7887_ring_setup_ops; + indio_dev->buffer->setup_ops = &ad7887_ring_setup_ops; /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_RING_TRIGGERED; + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; return 0; error_deallocate_sw_rb: - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); error_ret: return ret; } void ad7887_ring_cleanup(struct iio_dev *indio_dev) { - /* ensure that the trigger has been detached */ - if (indio_dev->trig) { - iio_put_trigger(indio_dev->trig); - iio_trigger_dettach_poll_func(indio_dev->trig, - indio_dev->pollfunc); - } iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); } diff --git a/drivers/staging/iio/adc/ad799x.h b/drivers/staging/iio/adc/ad799x.h index 0dc9b4c..eda01d5 100644 --- a/drivers/staging/iio/adc/ad799x.h +++ b/drivers/staging/iio/adc/ad799x.h @@ -124,11 +124,11 @@ struct ad799x_platform_data { int ad7997_8_set_scan_mode(struct ad799x_state *st, unsigned mask); #ifdef CONFIG_AD799X_RING_BUFFER -int ad799x_single_channel_from_ring(struct ad799x_state *st, long mask); +int ad799x_single_channel_from_ring(struct iio_dev *indio_dev, int channum); int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev); void ad799x_ring_cleanup(struct iio_dev *indio_dev); #else /* CONFIG_AD799X_RING_BUFFER */ -int ad799x_single_channel_from_ring(struct ad799x_state *st, long mask) +int ad799x_single_channel_from_ring(struct iio_dev *indio_dev, int channum) { return -EINVAL; } diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index 92cfe2e..ee6cd79 100644 --- a/drivers/staging/iio/adc/ad799x_core.c +++ b/drivers/staging/iio/adc/ad799x_core.c @@ -31,12 +31,12 @@ #include <linux/slab.h> #include <linux/types.h> #include <linux/err.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" +#include "../buffer_generic.h" -#include "../ring_generic.h" -#include "adc.h" #include "ad799x.h" /* @@ -136,49 +136,56 @@ static int ad799x_scan_direct(struct ad799x_state *st, unsigned ch) return rxbuf; } -static int ad799x_read_raw(struct iio_dev *dev_info, +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(dev_info); + struct ad799x_state *st = iio_priv(indio_dev); unsigned int scale_uv; switch (m) { case 0: - mutex_lock(&dev_info->mlock); - if (iio_ring_enabled(dev_info)) - ret = ad799x_single_channel_from_ring(st, - 1 << chan->address); + mutex_lock(&indio_dev->mlock); + if (iio_buffer_enabled(indio_dev)) + ret = ad799x_single_channel_from_ring(indio_dev, + chan->scan_index); else - ret = ad799x_scan_direct(st, chan->address); - mutex_unlock(&dev_info->mlock); + ret = ad799x_scan_direct(st, chan->scan_index); + 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); + *val = (ret >> chan->scan_type.shift) & + RES_MASK(chan->scan_type.realbits); return IIO_VAL_INT; case (1 << IIO_CHAN_INFO_SCALE_SHARED): - scale_uv = (st->int_vref_mv * 1000) - >> st->chip_info->channel[0].scan_type.realbits; + 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 *dev_info = dev_get_drvdata(dev); - struct ad799x_state *st = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad799x_state *st = iio_priv(indio_dev); - int ret, len = 0; + int ret; u8 val; ret = ad799x_i2c_read8(st, AD7998_CYCLE_TMR_REG, &val); if (ret) @@ -186,33 +193,7 @@ static ssize_t ad799x_read_frequency(struct device *dev, val &= AD7998_CYC_MASK; - switch (val) { - case AD7998_CYC_DIS: - len = sprintf(buf, "0\n"); - break; - case AD7998_CYC_TCONF_32: - len = sprintf(buf, "15625\n"); - break; - case AD7998_CYC_TCONF_64: - len = sprintf(buf, "7812\n"); - break; - case AD7998_CYC_TCONF_128: - len = sprintf(buf, "3906\n"); - break; - case AD7998_CYC_TCONF_256: - len = sprintf(buf, "1953\n"); - break; - case AD7998_CYC_TCONF_512: - len = sprintf(buf, "976\n"); - break; - case AD7998_CYC_TCONF_1024: - len = sprintf(buf, "488\n"); - break; - case AD7998_CYC_TCONF_2048: - len = sprintf(buf, "244\n"); - break; - } - return len; + return sprintf(buf, "%u\n", ad7998_frequencies[val]); } static ssize_t ad799x_write_frequency(struct device *dev, @@ -220,68 +201,101 @@ static ssize_t ad799x_write_frequency(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad799x_state *st = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad799x_state *st = iio_priv(indio_dev); long val; - int ret; + int ret, i; u8 t; ret = strict_strtol(buf, 10, &val); if (ret) return ret; - mutex_lock(&dev_info->mlock); + 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; - switch (val) { - case 15625: - t |= AD7998_CYC_TCONF_32; - break; - case 7812: - t |= AD7998_CYC_TCONF_64; - break; - case 3906: - t |= AD7998_CYC_TCONF_128; - break; - case 1953: - t |= AD7998_CYC_TCONF_256; - break; - case 976: - t |= AD7998_CYC_TCONF_512; - break; - case 488: - t |= AD7998_CYC_TCONF_1024; - break; - case 244: - t |= AD7998_CYC_TCONF_2048; - break; - case 0: - t |= AD7998_CYC_DIS; - break; - default: + 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(&dev_info->mlock); + 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 *dev_info = dev_get_drvdata(dev); - struct ad799x_state *st = iio_priv(dev_info); + 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; @@ -298,8 +312,8 @@ static ssize_t ad799x_write_channel_config(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad799x_state *st = iio_priv(dev_info); + 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; @@ -309,9 +323,9 @@ static ssize_t ad799x_write_channel_config(struct device *dev, if (ret) return ret; - mutex_lock(&dev_info->mlock); + mutex_lock(&indio_dev->mlock); ret = ad799x_i2c_write16(st, this_attr->address, val); - mutex_unlock(&dev_info->mlock); + mutex_unlock(&indio_dev->mlock); return ret ? ret : len; } @@ -334,83 +348,41 @@ static irqreturn_t ad799x_event_handler(int irq, void *private) for (i = 0; i < 8; i++) { if (status & (1 << i)) - iio_push_event(indio_dev, 0, + iio_push_event(indio_dev, i & 0x1 ? - IIO_EVENT_CODE_IN_HIGH_THRESH(i >> 1) : - IIO_EVENT_CODE_IN_LOW_THRESH(i >> 1), + 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(in0_thresh_low_value, - S_IRUGO | S_IWUSR, - ad799x_read_channel_config, - ad799x_write_channel_config, - AD7998_DATALOW_CH1_REG); - -static IIO_DEVICE_ATTR(in0_thresh_high_value, - S_IRUGO | S_IWUSR, - ad799x_read_channel_config, - ad799x_write_channel_config, - AD7998_DATAHIGH_CH1_REG); - -static IIO_DEVICE_ATTR(in0_thresh_both_hyst_raw, +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(in1_thresh_low_value, - S_IRUGO | S_IWUSR, - ad799x_read_channel_config, - ad799x_write_channel_config, - AD7998_DATALOW_CH2_REG); - -static IIO_DEVICE_ATTR(in1_thresh_high_value, - S_IRUGO | S_IWUSR, - ad799x_read_channel_config, - ad799x_write_channel_config, - AD7998_DATAHIGH_CH2_REG); - -static IIO_DEVICE_ATTR(in1_thresh_both_hyst_raw, +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(in2_thresh_low_value, - S_IRUGO | S_IWUSR, - ad799x_read_channel_config, - ad799x_write_channel_config, - AD7998_DATALOW_CH3_REG); - -static IIO_DEVICE_ATTR(in2_thresh_high_value, - S_IRUGO | S_IWUSR, - ad799x_read_channel_config, - ad799x_write_channel_config, - AD7998_DATAHIGH_CH3_REG); - -static IIO_DEVICE_ATTR(in2_thresh_both_hyst_raw, +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(in3_thresh_low_value, - S_IRUGO | S_IWUSR, - ad799x_read_channel_config, - ad799x_write_channel_config, - AD7998_DATALOW_CH4_REG); - -static IIO_DEVICE_ATTR(in3_thresh_high_value, - S_IRUGO | S_IWUSR, - ad799x_read_channel_config, - ad799x_write_channel_config, - AD7998_DATAHIGH_CH4_REG); - -static IIO_DEVICE_ATTR(in3_thresh_both_hyst_raw, +static IIO_DEVICE_ATTR(in_voltage3_thresh_both_hyst_raw, S_IRUGO | S_IWUSR, ad799x_read_channel_config, ad799x_write_channel_config, @@ -422,18 +394,10 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("15625 7812 3906 1953 976 488 244 0"); static struct attribute *ad7993_4_7_8_event_attributes[] = { - &iio_dev_attr_in0_thresh_low_value.dev_attr.attr, - &iio_dev_attr_in0_thresh_high_value.dev_attr.attr, - &iio_dev_attr_in0_thresh_both_hyst_raw.dev_attr.attr, - &iio_dev_attr_in1_thresh_low_value.dev_attr.attr, - &iio_dev_attr_in1_thresh_high_value.dev_attr.attr, - &iio_dev_attr_in1_thresh_both_hyst_raw.dev_attr.attr, - &iio_dev_attr_in2_thresh_low_value.dev_attr.attr, - &iio_dev_attr_in2_thresh_high_value.dev_attr.attr, - &iio_dev_attr_in2_thresh_both_hyst_raw.dev_attr.attr, - &iio_dev_attr_in3_thresh_low_value.dev_attr.attr, - &iio_dev_attr_in3_thresh_high_value.dev_attr.attr, - &iio_dev_attr_in3_thresh_both_hyst_raw.dev_attr.attr, + &iio_dev_attr_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, @@ -441,15 +405,12 @@ static struct attribute *ad7993_4_7_8_event_attributes[] = { 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_in0_thresh_low_value.dev_attr.attr, - &iio_dev_attr_in0_thresh_high_value.dev_attr.attr, - &iio_dev_attr_in0_thresh_both_hyst_raw.dev_attr.attr, - &iio_dev_attr_in1_thresh_low_value.dev_attr.attr, - &iio_dev_attr_in1_thresh_high_value.dev_attr.attr, - &iio_dev_attr_in1_thresh_both_hyst_raw.dev_attr.attr, + &iio_dev_attr_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, @@ -457,6 +418,7 @@ static struct attribute *ad7992_event_attributes[] = { static struct attribute_group ad7992_event_attrs_group = { .attrs = ad7992_event_attributes, + .name = "events", }; static const struct iio_info ad7991_info = { @@ -466,181 +428,374 @@ static const struct iio_info ad7991_info = { static const struct iio_info ad7992_info = { .read_raw = &ad799x_read_raw, - .num_interrupt_lines = 1, .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, - .num_interrupt_lines = 1, .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] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 0, 0, IIO_ST('u', 12, 16, 0), 0), - .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 1, 1, IIO_ST('u', 12, 16, 0), 0), - .channel[2] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 2, 2, IIO_ST('u', 12, 16, 0), 0), - .channel[3] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 3, 3, IIO_ST('u', 12, 16, 0), 0), - .channel[4] = IIO_CHAN_SOFT_TIMESTAMP(4), + .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] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 0, 0, IIO_ST('u', 10, 16, 0), 0), - .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 1, 1, IIO_ST('u', 10, 16, 0), 0), - .channel[2] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 2, 2, IIO_ST('u', 10, 16, 0), 0), - .channel[3] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 3, 3, IIO_ST('u', 10, 16, 0), 0), - .channel[4] = IIO_CHAN_SOFT_TIMESTAMP(4), + .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] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 0, 0, IIO_ST('u', 10, 16, 0), 0), - .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 1, 1, IIO_ST('u', 10, 16, 0), 0), - .channel[2] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 2, 2, IIO_ST('u', 10, 16, 0), 0), - .channel[3] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 3, 3, IIO_ST('u', 10, 16, 0), 0), - .channel[4] = IIO_CHAN_SOFT_TIMESTAMP(4), + .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] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 0, 0, IIO_ST('u', 12, 16, 0), 0), - .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 1, 1, IIO_ST('u', 12, 16, 0), 0), - .channel[2] = IIO_CHAN_SOFT_TIMESTAMP(2), + .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] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 0, 0, IIO_ST('u', 10, 16, 0), 0), - .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 1, 1, IIO_ST('u', 10, 16, 0), 0), - .channel[2] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 2, 2, IIO_ST('u', 10, 16, 0), 0), - .channel[3] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 3, 3, IIO_ST('u', 10, 16, 0), 0), - .channel[4] = IIO_CHAN_SOFT_TIMESTAMP(4), + .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] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 0, 0, IIO_ST('u', 12, 16, 0), 0), - .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 1, 1, IIO_ST('u', 12, 16, 0), 0), - .channel[2] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 2, 2, IIO_ST('u', 12, 16, 0), 0), - .channel[3] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 3, 3, IIO_ST('u', 12, 16, 0), 0), - .channel[4] = IIO_CHAN_SOFT_TIMESTAMP(4), + .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] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 0, 0, IIO_ST('u', 10, 16, 0), 0), - .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 1, 1, IIO_ST('u', 10, 16, 0), 0), - .channel[2] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 2, 2, IIO_ST('u', 10, 16, 0), 0), - .channel[3] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 3, 3, IIO_ST('u', 10, 16, 0), 0), - .channel[4] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 4, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 4, 4, IIO_ST('u', 10, 16, 0), 0), - .channel[5] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 5, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 5, 5, IIO_ST('u', 10, 16, 0), 0), - .channel[6] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 6, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 6, 6, IIO_ST('u', 10, 16, 0), 0), - .channel[7] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 7, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 7, 7, IIO_ST('u', 10, 16, 0), 0), - .channel[8] = IIO_CHAN_SOFT_TIMESTAMP(8), + .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] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 0, 0, IIO_ST('u', 12, 16, 0), 0), - .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 1, 1, IIO_ST('u', 12, 16, 0), 0), - .channel[2] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 2, 2, IIO_ST('u', 12, 16, 0), 0), - .channel[3] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 3, 3, IIO_ST('u', 12, 16, 0), 0), - .channel[4] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 4, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 4, 4, IIO_ST('u', 12, 16, 0), 0), - .channel[5] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 5, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 5, 5, IIO_ST('u', 12, 16, 0), 0), - .channel[6] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 6, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 6, 6, IIO_ST('u', 12, 16, 0), 0), - .channel[7] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 7, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 7, 7, IIO_ST('u', 12, 16, 0), 0), - .channel[8] = IIO_CHAN_SOFT_TIMESTAMP(8), + .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, @@ -651,7 +806,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = { static int __devinit ad799x_probe(struct i2c_client *client, const struct i2c_device_id *id) { - int ret, regdone = 0; + 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)); @@ -685,7 +840,6 @@ static int __devinit ad799x_probe(struct i2c_client *client, indio_dev->dev.parent = &client->dev; indio_dev->name = id->name; indio_dev->info = st->chip_info->info; - indio_dev->name = id->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->chip_info->channel; @@ -695,14 +849,9 @@ static int __devinit ad799x_probe(struct i2c_client *client, if (ret) goto error_disable_reg; - ret = iio_device_register(indio_dev); - if (ret) - goto error_cleanup_ring; - regdone = 1; - - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - indio_dev->channels, - indio_dev->num_channels); + ret = iio_buffer_register(indio_dev, + indio_dev->channels, + indio_dev->num_channels); if (ret) goto error_cleanup_ring; @@ -717,9 +866,14 @@ static int __devinit ad799x_probe(struct i2c_client *client, 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: @@ -728,10 +882,7 @@ error_disable_reg: error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); return ret; } @@ -741,16 +892,17 @@ 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_ring_buffer_unregister(indio_dev->ring); + iio_buffer_unregister(indio_dev); ad799x_ring_cleanup(indio_dev); if (!IS_ERR(st->reg)) { regulator_disable(st->reg); regulator_put(st->reg); } - iio_device_unregister(indio_dev); + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c index 0376a82..e3f4698 100644 --- a/drivers/staging/iio/adc/ad799x_ring.c +++ b/drivers/staging/iio/adc/ad799x_ring.c @@ -10,29 +10,26 @@ */ #include <linux/interrupt.h> -#include <linux/device.h> #include <linux/slab.h> #include <linux/kernel.h> -#include <linux/sysfs.h> #include <linux/list.h> #include <linux/i2c.h> #include <linux/bitops.h> #include "../iio.h" -#include "../ring_generic.h" +#include "../buffer_generic.h" #include "../ring_sw.h" -#include "../trigger.h" -#include "../sysfs.h" +#include "../trigger_consumer.h" #include "ad799x.h" -int ad799x_single_channel_from_ring(struct ad799x_state *st, long mask) +int ad799x_single_channel_from_ring(struct iio_dev *indio_dev, int channum) { - struct iio_ring_buffer *ring = iio_priv_to_dev(st)->ring; + struct iio_buffer *ring = indio_dev->buffer; int count = 0, ret; u16 *ring_data; - if (!(ring->scan_mask & mask)) { + if (!(test_bit(channum, ring->scan_mask))) { ret = -EBUSY; goto error_ret; } @@ -47,13 +44,7 @@ int ad799x_single_channel_from_ring(struct ad799x_state *st, long mask) if (ret) goto error_free_ring_data; /* Need a count of channels prior to this one */ - mask >>= 1; - while (mask) { - if (mask & ring->scan_mask) - count++; - mask >>= 1; - } - + count = bitmap_weight(ring->scan_mask, channum); ret = be16_to_cpu(ring_data[count]); error_free_ring_data: @@ -71,7 +62,7 @@ error_ret: **/ static int ad799x_ring_preenable(struct iio_dev *indio_dev) { - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; struct ad799x_state *st = iio_priv(indio_dev); /* @@ -80,7 +71,7 @@ static int ad799x_ring_preenable(struct iio_dev *indio_dev) */ if (st->id == ad7997 || st->id == ad7998) - ad7997_8_set_scan_mode(st, ring->scan_mask); + ad7997_8_set_scan_mode(st, *ring->scan_mask); st->d_size = ring->scan_count * 2; @@ -91,9 +82,9 @@ static int ad799x_ring_preenable(struct iio_dev *indio_dev) st->d_size += sizeof(s64) - (st->d_size % sizeof(s64)); } - if (indio_dev->ring->access->set_bytes_per_datum) - indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring, - st->d_size); + 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; } @@ -108,9 +99,9 @@ static int ad799x_ring_preenable(struct iio_dev *indio_dev) static irqreturn_t ad799x_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->private_data; + struct iio_dev *indio_dev = pf->indio_dev; struct ad799x_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; s64 time_ns; __u8 *rxbuf; int b_sent; @@ -124,12 +115,12 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p) case ad7991: case ad7995: case ad7999: - cmd = st->config | (ring->scan_mask << AD799X_CHANNEL_SHIFT); + cmd = st->config | (*ring->scan_mask << AD799X_CHANNEL_SHIFT); break; case ad7992: case ad7993: case ad7994: - cmd = (ring->scan_mask << AD799X_CHANNEL_SHIFT) | + cmd = (*ring->scan_mask << AD799X_CHANNEL_SHIFT) | AD7998_CONV_RES_REG; break; case ad7997: @@ -151,7 +142,7 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p) memcpy(rxbuf + st->d_size - sizeof(s64), &time_ns, sizeof(time_ns)); - ring->access->store_to(indio_dev->ring, rxbuf, time_ns); + ring->access->store_to(indio_dev->buffer, rxbuf, time_ns); done: kfree(rxbuf); if (b_sent < 0) @@ -162,23 +153,23 @@ out: return IRQ_HANDLED; } -static const struct iio_ring_setup_ops ad799x_buf_setup_ops = { +static const struct iio_buffer_setup_ops ad799x_buf_setup_ops = { .preenable = &ad799x_ring_preenable, - .postenable = &iio_triggered_ring_postenable, - .predisable = &iio_triggered_ring_predisable, + .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->ring = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->ring) { + 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->ring->access = &ring_sw_access_funcs; + indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(NULL, &ad799x_trigger_handler, IRQF_ONESHOT, @@ -192,27 +183,21 @@ int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev) } /* Ring buffer functions - here trigger setup related */ - indio_dev->ring->setup_ops = &ad799x_buf_setup_ops; - indio_dev->ring->scan_timestamp = true; + indio_dev->buffer->setup_ops = &ad799x_buf_setup_ops; + indio_dev->buffer->scan_timestamp = true; /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_RING_TRIGGERED; + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; return 0; error_deallocate_sw_rb: - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); error_ret: return ret; } void ad799x_ring_cleanup(struct iio_dev *indio_dev) { - /* ensure that the trigger has been detached */ - if (indio_dev->trig) { - iio_put_trigger(indio_dev->trig); - iio_trigger_dettach_poll_func(indio_dev->trig, - indio_dev->pollfunc); - } iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); } diff --git a/drivers/staging/iio/adc/adc.h b/drivers/staging/iio/adc/adc.h deleted file mode 100644 index 40c5949..0000000 --- a/drivers/staging/iio/adc/adc.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * adc.h - sysfs attributes associated with ADCs - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * Copyright (c) 2008 Jonathan Cameron <jic23@cam.ac.uk> - * - */ - -/* Deprecated */ -#define IIO_DEV_ATTR_ADC(_num, _show, _addr) \ - IIO_DEVICE_ATTR(adc_##_num, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_IN_RAW(_num, _show, _addr) \ - IIO_DEVICE_ATTR(in##_num##_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_IN_NAMED_RAW(_num, _name, _show, _addr) \ - IIO_DEVICE_ATTR(in##_num##_##_name##_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_IN_DIFF_RAW(_nump, _numn, _show, _addr) \ - IIO_DEVICE_ATTR_NAMED(in##_nump##min##_numn##_raw, \ - in##_nump-in##_numn##_raw, \ - S_IRUGO, \ - _show, \ - NULL, \ - _addr) - - -#define IIO_CONST_ATTR_IN_NAMED_OFFSET(_num, _name, _string) \ - IIO_CONST_ATTR(in##_num##_##_name##_offset, _string) - -#define IIO_CONST_ATTR_IN_NAMED_SCALE(_num, _name, _string) \ - IIO_CONST_ATTR(in##_num##_##_name##_scale, _string) - -#define IIO_EVENT_CODE_IN_HIGH_THRESH(a) \ - IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, a, IIO_EV_TYPE_THRESH, \ - IIO_EV_DIR_RISING) -#define IIO_EVENT_CODE_IN_LOW_THRESH(a) \ - IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, a, IIO_EV_TYPE_THRESH, \ - IIO_EV_DIR_FALLING) diff --git a/drivers/staging/iio/adc/adt7310.c b/drivers/staging/iio/adc/adt7310.c index 1a41b80..c9e0be3 100644 --- a/drivers/staging/iio/adc/adt7310.c +++ b/drivers/staging/iio/adc/adt7310.c @@ -13,6 +13,7 @@ #include <linux/sysfs.h> #include <linux/list.h> #include <linux/spi/spi.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -399,19 +400,19 @@ static irqreturn_t adt7310_event_handler(int irq, void *private) return ret; if (status & ADT7310_STAT_T_HIGH) - iio_push_event(indio_dev, 0, + 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, 0, + 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, 0, + iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), @@ -740,14 +741,15 @@ static struct attribute *adt7310_event_ct_attributes[] = { 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, - .num_interrupt_lines = ADT7310_IRQS, .event_attrs = adt7310_event_attribute_group, .driver_module = THIS_MODULE, }; @@ -780,10 +782,6 @@ static int __devinit adt7310_probe(struct spi_device *spi_dev) indio_dev->info = &adt7310_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - /* CT critcal temperature event. line 0 */ if (spi_dev->irq) { if (adt7310_platform_data[2]) @@ -797,7 +795,7 @@ static int __devinit adt7310_probe(struct spi_device *spi_dev) indio_dev->name, indio_dev); if (ret) - goto error_unreg_dev; + goto error_free_dev; } /* INT bound temperature alarm event. line 1 */ @@ -834,6 +832,10 @@ static int __devinit adt7310_probe(struct spi_device *spi_dev) } } + 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); @@ -843,8 +845,6 @@ error_unreg_int_irq: free_irq(adt7310_platform_data[0], indio_dev); error_unreg_ct_irq: free_irq(spi_dev->irq, indio_dev); -error_unreg_dev: - iio_device_unregister(indio_dev); error_free_dev: iio_free_device(indio_dev); error_ret: @@ -856,12 +856,12 @@ 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_device_unregister(indio_dev); iio_free_device(indio_dev); return 0; diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c index 76aa063..a289e42 100644 --- a/drivers/staging/iio/adc/adt7410.c +++ b/drivers/staging/iio/adc/adt7410.c @@ -13,6 +13,7 @@ #include <linux/sysfs.h> #include <linux/list.h> #include <linux/i2c.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -365,19 +366,19 @@ static irqreturn_t adt7410_event_handler(int irq, void *private) return IRQ_HANDLED; if (status & ADT7410_STAT_T_HIGH) - iio_push_event(indio_dev, 0, + 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, 0, + 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, 0, + iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), @@ -707,14 +708,15 @@ static struct attribute *adt7410_event_ct_attributes[] = { 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, - .num_interrupt_lines = ADT7410_IRQS, .event_attrs = adt7410_event_attribute_group, .driver_module = THIS_MODULE, }; @@ -747,10 +749,6 @@ static int __devinit adt7410_probe(struct i2c_client *client, indio_dev->info = &adt7410_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - /* CT critcal temperature event. line 0 */ if (client->irq) { ret = request_threaded_irq(client->irq, @@ -760,7 +758,7 @@ static int __devinit adt7410_probe(struct i2c_client *client, id->name, indio_dev); if (ret) - goto error_unreg_dev; + goto error_free_dev; } /* INT bound temperature alarm event. line 1 */ @@ -797,6 +795,9 @@ static int __devinit adt7410_probe(struct i2c_client *client, 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); @@ -807,8 +808,6 @@ error_unreg_int_irq: free_irq(adt7410_platform_data[0], indio_dev); error_unreg_ct_irq: free_irq(client->irq, indio_dev); -error_unreg_dev: - iio_device_unregister(indio_dev); error_free_dev: iio_free_device(indio_dev); error_ret: @@ -820,11 +819,12 @@ 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_device_unregister(indio_dev); + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/adt75.c b/drivers/staging/iio/adc/adt75.c deleted file mode 100644 index 38f141d..0000000 --- a/drivers/staging/iio/adc/adt75.c +++ /dev/null @@ -1,657 +0,0 @@ -/* - * ADT75 digital temperature sensor driver supporting ADT75 - * - * 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/i2c.h> - -#include "../iio.h" -#include "../sysfs.h" - -/* - * ADT75 registers definition - */ - -#define ADT75_TEMPERATURE 0 -#define ADT75_CONFIG 1 -#define ADT75_T_HYST 2 -#define ADT75_T_OS 3 -#define ADT75_ONESHOT 4 - -/* - * ADT75 config - */ -#define ADT75_PD 0x1 -#define ADT75_OS_INT 0x2 -#define ADT75_OS_POLARITY 0x4 -#define ADT75_FAULT_QUEUE_MASK 0x18 -#define ADT75_FAULT_QUEUE_OFFSET 3 -#define ADT75_SMBUS_ALART 0x8 - -/* - * ADT75 masks - */ -#define ADT75_VALUE_SIGN 0x800 -#define ADT75_VALUE_OFFSET 4 -#define ADT75_VALUE_FLOAT_OFFSET 4 -#define ADT75_VALUE_FLOAT_MASK 0xF - - -/* - * struct adt75_chip_info - chip specifc information - */ - -struct adt75_chip_info { - struct i2c_client *client; - u8 config; -}; - -/* - * adt75 register access by I2C - */ - -static int adt75_i2c_read(struct iio_dev *dev_info, u8 reg, u8 *data) -{ - struct adt75_chip_info *chip = iio_priv(dev_info); - struct i2c_client *client = chip->client; - int ret = 0, len; - - ret = i2c_smbus_write_byte(client, reg); - if (ret < 0) { - dev_err(&client->dev, "I2C read register address error\n"); - return ret; - } - - if (reg == ADT75_CONFIG || reg == ADT75_ONESHOT) - len = 1; - else - len = 2; - - ret = i2c_master_recv(client, data, len); - if (ret < 0) { - dev_err(&client->dev, "I2C read error\n"); - return ret; - } - - return ret; -} - -static int adt75_i2c_write(struct iio_dev *dev_info, u8 reg, u8 data) -{ - struct adt75_chip_info *chip = iio_priv(dev_info); - struct i2c_client *client = chip->client; - int ret = 0; - - if (reg == ADT75_CONFIG || reg == ADT75_ONESHOT) - ret = i2c_smbus_write_byte_data(client, reg, data); - else - ret = i2c_smbus_write_word_data(client, reg, data); - - if (ret < 0) - dev_err(&client->dev, "I2C write error\n"); - - return ret; -} - -static ssize_t adt75_show_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct adt75_chip_info *chip = iio_priv(dev_get_drvdata(dev)); - - if (chip->config & ADT75_PD) - return sprintf(buf, "power-save\n"); - else - return sprintf(buf, "full\n"); -} - -static ssize_t adt75_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 adt75_chip_info *chip = iio_priv(dev_info); - int ret; - u8 config; - - ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config); - if (ret) - return -EIO; - - config = chip->config & ~ADT75_PD; - if (!strcmp(buf, "full")) - config |= ADT75_PD; - - ret = adt75_i2c_write(dev_info, ADT75_CONFIG, config); - if (ret) - return -EIO; - - chip->config = config; - - return ret; -} - -static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, - adt75_show_mode, - adt75_store_mode, - 0); - -static ssize_t adt75_show_available_modes(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "full\npower-down\n"); -} - -static IIO_DEVICE_ATTR(available_modes, S_IRUGO, adt75_show_available_modes, NULL, 0); - -static ssize_t adt75_show_oneshot(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct adt75_chip_info *chip = iio_priv(dev_get_drvdata(dev)); - - return sprintf(buf, "%d\n", !!(chip->config & ADT75_ONESHOT)); -} - -static ssize_t adt75_store_oneshot(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt75_chip_info *chip = iio_priv(dev_info); - unsigned long data = 0; - int ret; - u8 config; - - ret = strict_strtoul(buf, 10, &data); - if (ret) - return -EINVAL; - - - ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config); - if (ret) - return -EIO; - - config = chip->config & ~ADT75_ONESHOT; - if (data) - config |= ADT75_ONESHOT; - - ret = adt75_i2c_write(dev_info, ADT75_CONFIG, config); - if (ret) - return -EIO; - - chip->config = config; - - return ret; -} - -static IIO_DEVICE_ATTR(oneshot, S_IRUGO | S_IWUSR, - adt75_show_oneshot, - adt75_store_oneshot, - 0); - -static ssize_t adt75_show_value(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt75_chip_info *chip = iio_priv(dev_info); - u16 data; - char sign = ' '; - int ret; - - if (chip->config & ADT75_PD) { - dev_err(dev, "Can't read value in power-down mode.\n"); - return -EIO; - } - - if (chip->config & ADT75_ONESHOT) { - /* write to active converter */ - ret = i2c_smbus_write_byte(chip->client, ADT75_ONESHOT); - if (ret) - return -EIO; - } - - ret = adt75_i2c_read(dev_info, ADT75_TEMPERATURE, (u8 *)&data); - if (ret) - return -EIO; - - data = swab16(data) >> ADT75_VALUE_OFFSET; - if (data & ADT75_VALUE_SIGN) { - /* convert supplement to positive value */ - data = (ADT75_VALUE_SIGN << 1) - data; - sign = '-'; - } - - return sprintf(buf, "%c%d.%.4d\n", sign, - (data >> ADT75_VALUE_FLOAT_OFFSET), - (data & ADT75_VALUE_FLOAT_MASK) * 625); -} - -static IIO_DEVICE_ATTR(value, S_IRUGO, adt75_show_value, NULL, 0); - -static struct attribute *adt75_attributes[] = { - &iio_dev_attr_available_modes.dev_attr.attr, - &iio_dev_attr_mode.dev_attr.attr, - &iio_dev_attr_oneshot.dev_attr.attr, - &iio_dev_attr_value.dev_attr.attr, - NULL, -}; - -static const struct attribute_group adt75_attribute_group = { - .attrs = adt75_attributes, -}; - -/* - * temperature bound events - */ - -#define IIO_EVENT_CODE_ADT75_OTI IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_TEMP, \ - 0, \ - IIO_EV_TYPE_THRESH, \ - IIO_EV_DIR_FALLING) - -static irqreturn_t adt75_event_handler(int irq, void *private) -{ - iio_push_event(private, 0, - IIO_EVENT_CODE_ADT75_OTI, - iio_get_time_ns()); - - return IRQ_HANDLED; -} - -static ssize_t adt75_show_oti_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt75_chip_info *chip = iio_priv(dev_info); - int ret; - - /* retrive ALART status */ - ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config); - if (ret) - return -EIO; - - if (chip->config & ADT75_OS_INT) - return sprintf(buf, "interrupt\n"); - else - return sprintf(buf, "comparator\n"); -} - -static ssize_t adt75_set_oti_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt75_chip_info *chip = iio_priv(dev_info); - int ret; - u8 config; - - /* retrive ALART status */ - ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config); - if (ret) - return -EIO; - - config = chip->config & ~ADT75_OS_INT; - if (strcmp(buf, "comparator") != 0) - config |= ADT75_OS_INT; - - ret = adt75_i2c_write(dev_info, ADT75_CONFIG, config); - if (ret) - return -EIO; - - chip->config = config; - - return ret; -} - -static ssize_t adt75_show_available_oti_modes(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "comparator\ninterrupt\n"); -} - -static ssize_t adt75_show_smbus_alart(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt75_chip_info *chip = iio_priv(dev_info); - int ret; - - /* retrive ALART status */ - ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config); - if (ret) - return -EIO; - - return sprintf(buf, "%d\n", !!(chip->config & ADT75_SMBUS_ALART)); -} - -static ssize_t adt75_set_smbus_alart(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt75_chip_info *chip = iio_priv(dev_info); - unsigned long data = 0; - int ret; - u8 config; - - ret = strict_strtoul(buf, 10, &data); - if (ret) - return -EINVAL; - - /* retrive ALART status */ - ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config); - if (ret) - return -EIO; - - config = chip->config & ~ADT75_SMBUS_ALART; - if (data) - config |= ADT75_SMBUS_ALART; - - ret = adt75_i2c_write(dev_info, ADT75_CONFIG, config); - if (ret) - return -EIO; - - chip->config = config; - - return ret; -} - -static ssize_t adt75_show_fault_queue(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct adt75_chip_info *chip = iio_priv(dev_info); - int ret; - - /* retrive ALART status */ - ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config); - if (ret) - return -EIO; - - return sprintf(buf, "%d\n", (chip->config & ADT75_FAULT_QUEUE_MASK) >> - ADT75_FAULT_QUEUE_OFFSET); -} - -static ssize_t adt75_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 adt75_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; - - /* retrive ALART status */ - ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config); - if (ret) - return -EIO; - - config = chip->config & ~ADT75_FAULT_QUEUE_MASK; - config |= (data << ADT75_FAULT_QUEUE_OFFSET); - ret = adt75_i2c_write(dev_info, ADT75_CONFIG, config); - if (ret) - return -EIO; - - chip->config = config; - - return ret; -} -static inline ssize_t adt75_show_t_bound(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *dev_info = dev_get_drvdata(dev); - u16 data; - char sign = ' '; - int ret; - - ret = adt75_i2c_read(dev_info, this_attr->address, (u8 *)&data); - if (ret) - return -EIO; - - data = swab16(data) >> ADT75_VALUE_OFFSET; - if (data & ADT75_VALUE_SIGN) { - /* convert supplement to positive value */ - data = (ADT75_VALUE_SIGN << 1) - data; - sign = '-'; - } - - return sprintf(buf, "%c%d.%.4d\n", sign, - (data >> ADT75_VALUE_FLOAT_OFFSET), - (data & ADT75_VALUE_FLOAT_MASK) * 625); -} - -static inline ssize_t adt75_set_t_bound(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 *dev_info = dev_get_drvdata(dev); - 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 (len > ADT75_VALUE_FLOAT_OFFSET) - len = ADT75_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; - data = (data << ADT75_VALUE_FLOAT_OFFSET) | (tmp2 & ADT75_VALUE_FLOAT_MASK); - if (tmp1 < 0) - /* convert positive value to supplyment */ - data = (ADT75_VALUE_SIGN << 1) - data; - data <<= ADT75_VALUE_OFFSET; - data = swab16(data); - - ret = adt75_i2c_write(dev_info, this_attr->address, (u8)data); - if (ret) - return -EIO; - - return ret; -} - - -static IIO_DEVICE_ATTR(oti_mode, - S_IRUGO | S_IWUSR, - adt75_show_oti_mode, adt75_set_oti_mode, 0); -static IIO_DEVICE_ATTR(available_oti_modes, - S_IRUGO, - adt75_show_available_oti_modes, NULL, 0); -static IIO_DEVICE_ATTR(smbus_alart, - S_IRUGO | S_IWUSR, - adt75_show_smbus_alart, adt75_set_smbus_alart, 0); -static IIO_DEVICE_ATTR(fault_queue, - S_IRUGO | S_IWUSR, - adt75_show_fault_queue, adt75_set_fault_queue, 0); -static IIO_DEVICE_ATTR(t_os_value, - S_IRUGO | S_IWUSR, - adt75_show_t_bound, adt75_set_t_bound, - ADT75_T_OS); -static IIO_DEVICE_ATTR(t_hyst_value, - S_IRUGO | S_IWUSR, - adt75_show_t_bound, adt75_set_t_bound, - ADT75_T_HYST); - -static struct attribute *adt75_event_attributes[] = { - &iio_dev_attr_oti_mode.dev_attr.attr, - &iio_dev_attr_available_oti_modes.dev_attr.attr, - &iio_dev_attr_smbus_alart.dev_attr.attr, - &iio_dev_attr_fault_queue.dev_attr.attr, - &iio_dev_attr_t_os_value.dev_attr.attr, - &iio_dev_attr_t_hyst_value.dev_attr.attr, - NULL, -}; - -static struct attribute_group adt75_event_attribute_group = { - .attrs = adt75_event_attributes, -}; - -static const struct iio_info adt75_info = { - .attrs = &adt75_attribute_group, - .num_interrupt_lines = 1, - .event_attrs = &adt75_event_attribute_group, - .driver_module = THIS_MODULE, -}; - -/* - * device probe and remove - */ - -static int __devinit adt75_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adt75_chip_info *chip; - struct iio_dev *indio_dev; - int ret = 0; - - 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 = &adt75_info; - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - - if (client->irq > 0) { - ret = request_threaded_irq(client->irq, - NULL, - &adt75_event_handler, - IRQF_TRIGGER_LOW, - indio_dev->name, - indio_dev); - if (ret) - goto error_unreg_dev; - - ret = adt75_i2c_read(indio_dev, ADT75_CONFIG, &chip->config); - if (ret) { - ret = -EIO; - goto error_unreg_irq; - } - - /* set irq polarity low level */ - chip->config &= ~ADT75_OS_POLARITY; - - ret = adt75_i2c_write(indio_dev, ADT75_CONFIG, chip->config); - if (ret) { - ret = -EIO; - goto error_unreg_irq; - } - } - - dev_info(&client->dev, "%s temperature sensor registered.\n", - indio_dev->name); - - return 0; -error_unreg_irq: - free_irq(client->irq, indio_dev); -error_unreg_dev: - iio_device_unregister(indio_dev); -error_free_dev: - iio_free_device(indio_dev); -error_ret: - return ret; -} - -static int __devexit adt75_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - - if (client->irq) - free_irq(client->irq, indio_dev); - iio_device_unregister(indio_dev); - iio_free_device(indio_dev); - - return 0; -} - -static const struct i2c_device_id adt75_id[] = { - { "adt75", 0 }, - {} -}; - -MODULE_DEVICE_TABLE(i2c, adt75_id); - -static struct i2c_driver adt75_driver = { - .driver = { - .name = "adt75", - }, - .probe = adt75_probe, - .remove = __devexit_p(adt75_remove), - .id_table = adt75_id, -}; - -static __init int adt75_init(void) -{ - return i2c_add_driver(&adt75_driver); -} - -static __exit void adt75_exit(void) -{ - i2c_del_driver(&adt75_driver); -} - -MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>"); -MODULE_DESCRIPTION("Analog Devices ADT75 digital" - " temperature sensor driver"); -MODULE_LICENSE("GPL v2"); - -module_init(adt75_init); -module_exit(adt75_exit); diff --git a/drivers/staging/iio/adc/max1363.h b/drivers/staging/iio/adc/max1363.h index 360bfc5..cbcb08a 100644 --- a/drivers/staging/iio/adc/max1363.h +++ b/drivers/staging/iio/adc/max1363.h @@ -57,6 +57,7 @@ #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 @@ -64,7 +65,7 @@ */ struct max1363_mode { int8_t conf; - long modemask; + DECLARE_BITMAP(modemask, MAX1363_MAX_CHANNELS); }; /* This must be maintained along side the max1363_mode_table in max1363_core */ @@ -145,13 +146,14 @@ struct max1363_state { }; const struct max1363_mode -*max1363_match_mode(u32 mask, const struct max1363_chip_info *ci); +*max1363_match_mode(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_single_channel_from_ring(long mask, struct max1363_state *st); +int max1363_single_channel_from_ring(const long *mask, + struct max1363_state *st); int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev); void max1363_ring_cleanup(struct iio_dev *indio_dev); diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c index 72b0917..eb699ad 100644 --- a/drivers/staging/iio/adc/max1363_core.c +++ b/drivers/staging/iio/adc/max1363_core.c @@ -30,26 +30,26 @@ #include <linux/regulator/consumer.h> #include <linux/slab.h> #include <linux/err.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" +#include "../buffer_generic.h" -#include "../ring_generic.h" -#include "adc.h" #include "max1363.h" #define MAX1363_MODE_SINGLE(_num, _mask) { \ .conf = MAX1363_CHANNEL_SEL(_num) \ | MAX1363_CONFIG_SCAN_SINGLE_1 \ | MAX1363_CONFIG_SE, \ - .modemask = _mask, \ + .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 = _mask, \ + .modemask[0] = _mask, \ } /* note not available for max1363 hence naming */ @@ -57,14 +57,14 @@ .conf = MAX1363_CHANNEL_SEL(_num) \ | MAX1236_SCAN_MID_TO_CHANNEL \ | MAX1363_CONFIG_SE, \ - .modemask = _mask \ + .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 = _mask \ + .modemask[0] = _mask \ } /* Can't think how to automate naming so specify for now */ @@ -72,7 +72,7 @@ .conf = MAX1363_CHANNEL_SEL(_num) \ | MAX1363_CONFIG_SCAN_TO_CS \ | MAX1363_CONFIG_DE, \ - .modemask = _mask \ + .modemask[0] = _mask \ } /* note only available for max1363 hence naming */ @@ -80,7 +80,7 @@ .conf = MAX1363_CHANNEL_SEL(_num) \ | MAX1236_SCAN_MID_TO_CHANNEL \ | MAX1363_CONFIG_SE, \ - .modemask = _mask \ + .modemask[0] = _mask \ } static const struct max1363_mode max1363_mode_table[] = { @@ -147,13 +147,15 @@ static const struct max1363_mode max1363_mode_table[] = { }; const struct max1363_mode -*max1363_match_mode(u32 mask, const struct max1363_chip_info *ci) +*max1363_match_mode(unsigned long *mask, const struct max1363_chip_info *ci) { int i; if (mask) for (i = 0; i < ci->num_modes; i++) - if (!((~max1363_mode_table[ci->mode_list[i]].modemask) & - mask)) + 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; } @@ -187,7 +189,7 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev, int ret = 0; s32 data; char rxbuf[2]; - long mask; + const unsigned long *mask; struct max1363_state *st = iio_priv(indio_dev); struct i2c_client *client = st->client; @@ -203,7 +205,7 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev, } /* If ring buffer capture is occurring, query the buffer */ - if (iio_ring_enabled(indio_dev)) { + if (iio_buffer_enabled(indio_dev)) { mask = max1363_mode_table[chan->address].modemask; data = max1363_single_channel_from_ring(mask, st); if (data < 0) { @@ -255,7 +257,7 @@ static int max1363_read_raw(struct iio_dev *indio_dev, switch (m) { case 0: ret = max1363_read_single_chan(indio_dev, chan, val, m); - if (ret) + if (ret < 0) return ret; return IIO_VAL_INT; case (1 << IIO_CHAN_INFO_SCALE_SHARED): @@ -287,72 +289,52 @@ static const enum max1363_modes max1363_mode_list[] = { (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) \ | IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)) #define MAX1363_INFO_MASK (1 << IIO_CHAN_INFO_SCALE_SHARED) +#define MAX1363_CHAN_U(num, addr, si, bits, evmask) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = num, \ + .address = addr, \ + .info_mask = MAX1363_INFO_MASK, \ + .scan_type = IIO_ST('u', bits, (bits > 8) ? 16 : 8, 0), \ + .scan_index = si, \ + .event_mask = evmask, \ + } -static struct iio_chan_spec max1363_channels[] = { - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, MAX1363_INFO_MASK, - _s0, 0, IIO_ST('u', 12, 16, 0), MAX1363_EV_M), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, MAX1363_INFO_MASK, - _s1, 1, IIO_ST('u', 12, 16, 0), MAX1363_EV_M), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, MAX1363_INFO_MASK, - _s2, 2, IIO_ST('u', 12, 16, 0), MAX1363_EV_M), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, MAX1363_INFO_MASK, - _s3, 3, IIO_ST('u', 12, 16, 0), MAX1363_EV_M), - IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 0, 1, MAX1363_INFO_MASK, - d0m1, 4, IIO_ST('s', 12, 16, 0), MAX1363_EV_M), - IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 2, 3, MAX1363_INFO_MASK, - d2m3, 5, IIO_ST('s', 12, 16, 0), MAX1363_EV_M), - IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 1, 0, MAX1363_INFO_MASK, - d1m0, 6, IIO_ST('s', 12, 16, 0), MAX1363_EV_M), - IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 3, 2, MAX1363_INFO_MASK, - d3m2, 7, IIO_ST('s', 12, 16, 0), MAX1363_EV_M), - IIO_CHAN_SOFT_TIMESTAMP(8) -}; - -static struct iio_chan_spec max1361_channels[] = { - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, MAX1363_INFO_MASK, - _s0, 0, IIO_ST('u', 10, 16, 0), MAX1363_EV_M), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, MAX1363_INFO_MASK, - _s1, 1, IIO_ST('u', 10, 16, 0), MAX1363_EV_M), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, MAX1363_INFO_MASK, - _s2, 2, IIO_ST('u', 10, 16, 0), MAX1363_EV_M), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, MAX1363_INFO_MASK, - _s3, 3, IIO_ST('u', 10, 16, 0), MAX1363_EV_M), - IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 0, 1, MAX1363_INFO_MASK, - d0m1, 4, IIO_ST('s', 10, 16, 0), MAX1363_EV_M), - IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 2, 3, MAX1363_INFO_MASK, - d2m3, 5, IIO_ST('s', 10, 16, 0), MAX1363_EV_M), - IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 1, 0, MAX1363_INFO_MASK, - d1m0, 6, IIO_ST('s', 10, 16, 0), MAX1363_EV_M), - IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 3, 2, MAX1363_INFO_MASK, - d3m2, 7, IIO_ST('s', 10, 16, 0), MAX1363_EV_M), - IIO_CHAN_SOFT_TIMESTAMP(8) -}; - -#define MAX1363_CHAN_U(num, address, scan_index, bits) \ - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, num, 0, MAX1363_INFO_MASK, \ - address, scan_index, IIO_ST('u', bits, \ - (bits == 8) ? 8 : 16, 0), 0) /* bipolar channel */ -#define MAX1363_CHAN_B(num, num2, address, scan_index, bits) \ - IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, num, num2, MAX1363_INFO_MASK,\ - address, scan_index, IIO_ST('s', bits, \ - (bits == 8) ? 8 : 16, 0), 0) - -#define MAX1363_4X_CHANS(bits) { \ - MAX1363_CHAN_U(0, _s0, 0, bits), \ - MAX1363_CHAN_U(1, _s1, 1, bits), \ - MAX1363_CHAN_U(2, _s2, 2, bits), \ - MAX1363_CHAN_U(3, _s3, 3, bits), \ - MAX1363_CHAN_B(0, 1, d0m1, 4, bits), \ - MAX1363_CHAN_B(2, 3, d2m3, 5, bits), \ - MAX1363_CHAN_B(1, 0, d1m0, 6, bits), \ - MAX1363_CHAN_B(3, 2, d3m2, 7, bits), \ - IIO_CHAN_SOFT_TIMESTAMP(8) \ +#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, \ + .scan_type = IIO_ST('u', bits, (bits > 8) ? 16 : 8, 0), \ + .scan_index = si, \ + .event_mask = evmask, \ } -static struct iio_chan_spec max1036_channels[] = MAX1363_4X_CHANS(8); -static struct iio_chan_spec max1136_channels[] = MAX1363_4X_CHANS(10); -static struct iio_chan_spec max1236_channels[] = MAX1363_4X_CHANS(12); +#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[] = { @@ -377,30 +359,30 @@ static const enum max1363_modes max1238_mode_list[] = { }; #define MAX1363_12X_CHANS(bits) { \ - MAX1363_CHAN_U(0, _s0, 0, bits), \ - MAX1363_CHAN_U(1, _s1, 1, bits), \ - MAX1363_CHAN_U(2, _s2, 2, bits), \ - MAX1363_CHAN_U(3, _s3, 3, bits), \ - MAX1363_CHAN_U(4, _s4, 4, bits), \ - MAX1363_CHAN_U(5, _s5, 5, bits), \ - MAX1363_CHAN_U(6, _s6, 6, bits), \ - MAX1363_CHAN_U(7, _s7, 7, bits), \ - MAX1363_CHAN_U(8, _s8, 8, bits), \ - MAX1363_CHAN_U(9, _s9, 9, bits), \ - MAX1363_CHAN_U(10, _s10, 10, bits), \ - MAX1363_CHAN_U(11, _s11, 11, bits), \ - MAX1363_CHAN_B(0, 1, d0m1, 12, bits), \ - MAX1363_CHAN_B(2, 3, d2m3, 13, bits), \ - MAX1363_CHAN_B(4, 5, d4m5, 14, bits), \ - MAX1363_CHAN_B(6, 7, d6m7, 15, bits), \ - MAX1363_CHAN_B(8, 9, d8m9, 16, bits), \ - MAX1363_CHAN_B(10, 11, d10m11, 17, bits), \ - MAX1363_CHAN_B(1, 0, d1m0, 18, bits), \ - MAX1363_CHAN_B(3, 2, d3m2, 19, bits), \ - MAX1363_CHAN_B(5, 4, d5m4, 20, bits), \ - MAX1363_CHAN_B(7, 6, d7m6, 21, bits), \ - MAX1363_CHAN_B(9, 8, d9m8, 22, bits), \ - MAX1363_CHAN_B(11, 10, d11m10, 23, bits), \ + 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); @@ -425,25 +407,25 @@ static const enum max1363_modes max11608_mode_list[] = { d1m0to3m2, d1m0to5m4, d1m0to7m6, }; -#define MAX1363_8X_CHANS(bits) { \ - MAX1363_CHAN_U(0, _s0, 0, bits), \ - MAX1363_CHAN_U(1, _s1, 1, bits), \ - MAX1363_CHAN_U(2, _s2, 2, bits), \ - MAX1363_CHAN_U(3, _s3, 3, bits), \ - MAX1363_CHAN_U(4, _s4, 4, bits), \ - MAX1363_CHAN_U(5, _s5, 5, bits), \ - MAX1363_CHAN_U(6, _s6, 6, bits), \ - MAX1363_CHAN_U(7, _s7, 7, bits), \ - MAX1363_CHAN_B(0, 1, d0m1, 8, bits), \ - MAX1363_CHAN_B(2, 3, d2m3, 9, bits), \ - MAX1363_CHAN_B(4, 5, d4m5, 10, bits), \ - MAX1363_CHAN_B(6, 7, d6m7, 11, bits), \ - MAX1363_CHAN_B(1, 0, d1m0, 12, bits), \ - MAX1363_CHAN_B(3, 2, d3m2, 13, bits), \ - MAX1363_CHAN_B(5, 4, d5m4, 14, bits), \ - MAX1363_CHAN_B(7, 6, d7m6, 15, bits), \ - IIO_CHAN_SOFT_TIMESTAMP(16) \ - } +#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); @@ -453,10 +435,10 @@ static const enum max1363_modes max11644_mode_list[] = { }; #define MAX1363_2X_CHANS(bits) { \ - MAX1363_CHAN_U(0, _s0, 0, bits), \ - MAX1363_CHAN_U(1, _s1, 1, bits), \ - MAX1363_CHAN_B(0, 1, d0m1, 2, bits), \ - MAX1363_CHAN_B(1, 0, d1m0, 3, bits), \ + 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) \ } @@ -551,7 +533,7 @@ 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, - int event_code, + u64 event_code, int *val) { struct max1363_state *st = iio_priv(indio_dev); @@ -563,7 +545,7 @@ static int max1363_read_thresh(struct iio_dev *indio_dev, } static int max1363_write_thresh(struct iio_dev *indio_dev, - int event_code, + u64 event_code, int val) { struct max1363_state *st = iio_priv(indio_dev); @@ -591,11 +573,23 @@ static int max1363_write_thresh(struct iio_dev *indio_dev, return 0; } -static const int max1363_event_codes[] = { - IIO_EVENT_CODE_IN_LOW_THRESH(3), IIO_EVENT_CODE_IN_HIGH_THRESH(3), - IIO_EVENT_CODE_IN_LOW_THRESH(2), IIO_EVENT_CODE_IN_HIGH_THRESH(2), - IIO_EVENT_CODE_IN_LOW_THRESH(1), IIO_EVENT_CODE_IN_HIGH_THRESH(1), - IIO_EVENT_CODE_IN_LOW_THRESH(0), IIO_EVENT_CODE_IN_HIGH_THRESH(0) +static 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) @@ -611,15 +605,14 @@ static irqreturn_t max1363_event_handler(int irq, void *private) i2c_master_recv(st->client, &rx, 1); mask = rx; for_each_set_bit(loc, &mask, 8) - iio_push_event(indio_dev, 0, max1363_event_codes[loc], - timestamp); + 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, - int event_code) + u64 event_code) { struct max1363_state *st = iio_priv(indio_dev); @@ -641,7 +634,7 @@ static int max1363_monitor_mode_update(struct max1363_state *st, int enabled) int ret, i = 3, j; unsigned long numelements; int len; - long modemask; + const long *modemask; if (!enabled) { /* transition to ring capture is not currently supported */ @@ -669,7 +662,7 @@ static int max1363_monitor_mode_update(struct max1363_state *st, int enabled) st->configbyte |= max1363_mode_table[d1m0to3m2].conf; modemask = max1363_mode_table[d1m0to3m2].modemask; } - numelements = hweight_long(modemask); + numelements = bitmap_weight(modemask, MAX1363_MAX_CHANNELS); len = 3 * numelements + 3; tx_buf = kmalloc(len, GFP_KERNEL); if (!tx_buf) { @@ -685,7 +678,7 @@ static int max1363_monitor_mode_update(struct max1363_state *st, int enabled) * setup to match what we need. */ for (j = 0; j < 8; j++) - if (modemask & (1 << 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; @@ -771,7 +764,7 @@ error_ret: } static int max1363_write_event_config(struct iio_dev *indio_dev, - int event_code, + u64 event_code, int state) { int ret = 0; @@ -823,6 +816,7 @@ static struct attribute *max1363_event_attributes[] = { static struct attribute_group max1363_event_attribute_group = { .attrs = max1363_event_attributes, + .name = "events", }; #define MAX1363_EVENT_FUNCS \ @@ -840,7 +834,6 @@ static const struct iio_info max1363_info = { .write_event_config = &max1363_write_event_config, .read_raw = &max1363_read_raw, .driver_module = THIS_MODULE, - .num_interrupt_lines = 1, .event_attrs = &max1363_event_attribute_group, }; @@ -1249,7 +1242,7 @@ static int max1363_initial_setup(struct max1363_state *st) static int __devinit max1363_probe(struct i2c_client *client, const struct i2c_device_id *id) { - int ret, i, regdone = 0; + int ret, i; struct max1363_state *st; struct iio_dev *indio_dev; struct regulator *reg; @@ -1278,7 +1271,7 @@ static int __devinit max1363_probe(struct i2c_client *client, st->client = client; indio_dev->available_scan_masks - = kzalloc(sizeof(*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; @@ -1286,15 +1279,19 @@ static int __devinit max1363_probe(struct i2c_client *client, } for (i = 0; i < st->chip_info->num_modes; i++) - indio_dev->available_scan_masks[i] = - max1363_mode_table[st->chip_info->mode_list[i]] - .modemask; + 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; @@ -1303,13 +1300,9 @@ static int __devinit max1363_probe(struct i2c_client *client, if (ret) goto error_free_available_scan_masks; - ret = iio_device_register(indio_dev); - if (ret) - goto error_cleanup_ring; - regdone = 1; - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - st->chip_info->channels, - st->chip_info->num_channels); + ret = iio_buffer_register(indio_dev, + st->chip_info->channels, + st->chip_info->num_channels); if (ret) goto error_cleanup_ring; @@ -1325,19 +1318,21 @@ static int __devinit max1363_probe(struct i2c_client *client, goto error_uninit_ring; } - return 0; + 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_ring_buffer_unregister(indio_dev->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: - if (!regdone) - iio_free_device(indio_dev); - else - iio_device_unregister(indio_dev); + iio_free_device(indio_dev); error_disable_reg: regulator_disable(reg); error_put_reg: @@ -1352,16 +1347,17 @@ static int max1363_remove(struct i2c_client *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_ring_buffer_unregister(indio_dev->ring); + 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_device_unregister(indio_dev); + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c index f43befd..df6893e 100644 --- a/drivers/staging/iio/adc/max1363_ring.c +++ b/drivers/staging/iio/adc/max1363_ring.c @@ -9,28 +9,26 @@ */ #include <linux/interrupt.h> -#include <linux/device.h> #include <linux/slab.h> #include <linux/kernel.h> -#include <linux/sysfs.h> -#include <linux/list.h> #include <linux/i2c.h> #include <linux/bitops.h> #include "../iio.h" -#include "../ring_generic.h" +#include "../buffer_generic.h" #include "../ring_sw.h" -#include "../trigger.h" -#include "../sysfs.h" +#include "../trigger_consumer.h" #include "max1363.h" -int max1363_single_channel_from_ring(long mask, struct max1363_state *st) +int max1363_single_channel_from_ring(const long *mask, struct max1363_state *st) { - struct iio_ring_buffer *ring = iio_priv_to_dev(st)->ring; - int count = 0, ret; + struct iio_buffer *ring = iio_priv_to_dev(st)->buffer; + int count = 0, ret, index; u8 *ring_data; - if (!(st->current_mode->modemask & mask)) { + index = find_first_bit(mask, MAX1363_MAX_CHANNELS); + + if (!(test_bit(index, st->current_mode->modemask))) { ret = -EBUSY; goto error_ret; } @@ -45,12 +43,8 @@ int max1363_single_channel_from_ring(long mask, struct max1363_state *st) if (ret) goto error_free_ring_data; /* Need a count of channels prior to this one */ - mask >>= 1; - while (mask) { - if (mask & st->current_mode->modemask) - count++; - mask >>= 1; - } + + count = bitmap_weight(mask, index - 1); if (st->chip_info->bits != 8) ret = ((int)(ring_data[count*2 + 0] & 0x0F) << 8) + (int)(ring_data[count*2 + 1]); @@ -74,7 +68,7 @@ error_ret: static int max1363_ring_preenable(struct iio_dev *indio_dev) { struct max1363_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; size_t d_size = 0; unsigned long numvals; @@ -89,7 +83,8 @@ static int max1363_ring_preenable(struct iio_dev *indio_dev) max1363_set_scan_mode(st); - numvals = hweight_long(st->current_mode->modemask); + numvals = bitmap_weight(st->current_mode->modemask, + indio_dev->masklength); if (ring->access->set_bytes_per_datum) { if (ring->scan_timestamp) d_size += sizeof(s64); @@ -108,13 +103,14 @@ static int max1363_ring_preenable(struct iio_dev *indio_dev) static irqreturn_t max1363_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->private_data; + struct iio_dev *indio_dev = pf->indio_dev; struct max1363_state *st = iio_priv(indio_dev); s64 time_ns; __u8 *rxbuf; int b_sent; size_t d_size; - unsigned long numvals = hweight_long(st->current_mode->modemask); + 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) @@ -145,7 +141,7 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p) memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns)); - indio_dev->ring->access->store_to(indio_dev->ring, rxbuf, time_ns); + indio_dev->buffer->access->store_to(indio_dev->buffer, rxbuf, time_ns); done: iio_trigger_notify_done(indio_dev->trig); kfree(rxbuf); @@ -153,10 +149,10 @@ done: return IRQ_HANDLED; } -static const struct iio_ring_setup_ops max1363_ring_setup_ops = { - .postenable = &iio_triggered_ring_postenable, +static const struct iio_buffer_setup_ops max1363_ring_setup_ops = { + .postenable = &iio_triggered_buffer_postenable, .preenable = &max1363_ring_preenable, - .predisable = &iio_triggered_ring_predisable, + .predisable = &iio_triggered_buffer_predisable, }; int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) @@ -164,8 +160,8 @@ 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->ring = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->ring) { + indio_dev->buffer = iio_sw_rb_allocate(indio_dev); + if (!indio_dev->buffer) { ret = -ENOMEM; goto error_ret; } @@ -181,17 +177,17 @@ int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) goto error_deallocate_sw_rb; } /* Effectively select the ring buffer implementation */ - indio_dev->ring->access = &ring_sw_access_funcs; + indio_dev->buffer->access = &ring_sw_access_funcs; /* Ring buffer functions - here trigger setup related */ - indio_dev->ring->setup_ops = &max1363_ring_setup_ops; + indio_dev->buffer->setup_ops = &max1363_ring_setup_ops; /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_RING_TRIGGERED; + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; return 0; error_deallocate_sw_rb: - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); error_ret: return ret; } @@ -199,11 +195,6 @@ error_ret: void max1363_ring_cleanup(struct iio_dev *indio_dev) { /* ensure that the trigger has been detached */ - if (indio_dev->trig) { - iio_put_trigger(indio_dev->trig); - iio_trigger_dettach_poll_func(indio_dev->trig, - indio_dev->pollfunc); - } iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); } diff --git a/drivers/staging/iio/addac/Kconfig b/drivers/staging/iio/addac/Kconfig index 9847baf..698a897 100644 --- a/drivers/staging/iio/addac/Kconfig +++ b/drivers/staging/iio/addac/Kconfig @@ -1,10 +1,11 @@ # # ADDAC drivers # -comment "Analog digital bi-direction convertors" +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 help Say yes here to build support for Analog Devices ADT7316, ADT7317, ADT7318 and ADT7516, ADT7517, ADT7519 temperature sensors, ADC and DAC. @@ -23,3 +24,5 @@ config ADT7316_I2C help Say yes here to build I2C bus support for Analog Devices ADT7316/7/8 and ADT7516/7/9. + +endmenu diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c index 1c86cf1..07d718e 100644 --- a/drivers/staging/iio/addac/adt7316-i2c.c +++ b/drivers/staging/iio/addac/adt7316-i2c.c @@ -11,6 +11,7 @@ #include <linux/kernel.h> #include <linux/i2c.h> #include <linux/interrupt.h> +#include <linux/module.h> #include "adt7316.h" diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index 637316f..8df2470 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -17,6 +17,7 @@ #include <linux/list.h> #include <linux/i2c.h> #include <linux/rtc.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -203,7 +204,7 @@ struct adt7316_chip_info { #define ADT7316_TEMP_INT_MASK 0x1F #define ADT7516_AIN_INT_MASK 0xE0 #define ADT7316_TEMP_AIN_INT_MASK \ - (ADT7316_TEMP_INT_MASK | ADT7316_TEMP_INT_MASK) + (ADT7316_TEMP_INT_MASK) /* * struct adt7316_chip_info - chip specifc information @@ -1776,44 +1777,44 @@ static irqreturn_t adt7316_event_handler(int irq, void *private) time = iio_get_time_ns(); if (stat1 & (1 << 0)) - iio_push_event(indio_dev, 0, + iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), time); if (stat1 & (1 << 1)) - iio_push_event(indio_dev, 0, + iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), time); if (stat1 & (1 << 2)) - iio_push_event(indio_dev, 0, + iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_TEMP, 1, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), time); if (stat1 & (1 << 3)) - iio_push_event(indio_dev, 0, + iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_TEMP, 1, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), time); if (stat1 & (1 << 5)) - iio_push_event(indio_dev, 0, - IIO_UNMOD_EVENT_CODE(IIO_IN, 1, + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 1, IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER), time); if (stat1 & (1 << 6)) - iio_push_event(indio_dev, 0, - IIO_UNMOD_EVENT_CODE(IIO_IN, 2, + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 2, IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER), time); if (stat1 & (1 << 7)) - iio_push_event(indio_dev, 0, - IIO_UNMOD_EVENT_CODE(IIO_IN, 3, + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 3, IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER), time); @@ -1821,8 +1822,8 @@ static irqreturn_t adt7316_event_handler(int irq, void *private) ret = chip->bus.read(chip->bus.client, ADT7316_INT_STAT2, &stat2); if (!ret) { if (stat2 & ADT7316_INT_MASK2_VDD) - iio_push_event(indio_dev, 0, - IIO_UNMOD_EVENT_CODE(IIO_IN, + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), @@ -2063,6 +2064,7 @@ static struct attribute *adt7316_event_attributes[] = { static struct attribute_group adt7316_event_attribute_group = { .attrs = adt7316_event_attributes, + .name = "events", }; static struct attribute *adt7516_event_attributes[] = { @@ -2083,6 +2085,7 @@ static struct attribute *adt7516_event_attributes[] = { static struct attribute_group adt7516_event_attribute_group = { .attrs = adt7516_event_attributes, + .name = "events", }; #ifdef CONFIG_PM @@ -2107,14 +2110,12 @@ EXPORT_SYMBOL(adt7316_enable); static const struct iio_info adt7316_info = { .attrs = &adt7316_attribute_group, - .num_interrupt_lines = 1, .event_attrs = &adt7316_event_attribute_group, .driver_module = THIS_MODULE, }; static const struct iio_info adt7516_info = { .attrs = &adt7516_attribute_group, - .num_interrupt_lines = 1, .event_attrs = &adt7516_event_attribute_group, .driver_module = THIS_MODULE, }; @@ -2166,10 +2167,6 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus, indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - if (chip->bus.irq > 0) { if (adt7316_platform_data[0]) chip->bus.irq_flags = adt7316_platform_data[0]; @@ -2181,7 +2178,7 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus, indio_dev->name, indio_dev); if (ret) - goto error_unreg_dev; + goto error_free_dev; if (chip->bus.irq_flags & IRQF_TRIGGER_HIGH) chip->config1 |= ADT7316_INT_POLARITY; @@ -2199,6 +2196,10 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus, goto error_unreg_irq; } + ret = iio_device_register(indio_dev); + if (ret) + goto error_unreg_irq; + dev_info(dev, "%s temperature sensor, ADC and DAC registered.\n", indio_dev->name); @@ -2206,8 +2207,6 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus, error_unreg_irq: free_irq(chip->bus.irq, indio_dev); -error_unreg_dev: - iio_device_unregister(indio_dev); error_free_dev: iio_free_device(indio_dev); error_ret: @@ -2220,10 +2219,9 @@ 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); - dev_set_drvdata(dev, NULL); + iio_device_unregister(indio_dev); if (chip->bus.irq) free_irq(chip->bus.irq, indio_dev); - iio_device_unregister(indio_dev); iio_free_device(indio_dev); return 0; diff --git a/drivers/staging/iio/buffer_generic.h b/drivers/staging/iio/buffer_generic.h new file mode 100644 index 0000000..9e8f010 --- /dev/null +++ b/drivers/staging/iio/buffer_generic.h @@ -0,0 +1,228 @@ +/* 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" +#include "chrdev.h" + +#ifdef CONFIG_IIO_BUFFER + +struct iio_buffer; + +/** + * struct iio_buffer_access_funcs - access functions for buffers. + * @mark_in_use: reference counting, typically to prevent module removal + * @unmark_in_use: reduce reference count when no longer using buffer + * @store_to: actually store stuff to the buffer + * @read_last: get the last element stored + * @read_first_n: try to get a specified number of elements (must exist) + * @mark_param_change: notify buffer that some relevant parameter has changed + * Often this means the underlying storage may need to + * change. + * @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 + * @is_enabled: query if buffer is currently being used + * @enable: enable the 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 { + void (*mark_in_use)(struct iio_buffer *buffer); + void (*unmark_in_use)(struct iio_buffer *buffer); + + int (*store_to)(struct iio_buffer *buffer, u8 *data, s64 timestamp); + int (*read_last)(struct iio_buffer *buffer, u8 *data); + int (*read_first_n)(struct iio_buffer *buffer, + size_t n, + char __user *buf); + + int (*mark_param_change)(struct iio_buffer *buffer); + 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); + + int (*is_enabled)(struct iio_buffer *buffer); + int (*enable)(struct iio_buffer *buffer); +}; + +/** + * 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_buffer - general buffer structure + * @indio_dev: industrial I/O device structure + * @owner: module that owns the buffer (for ref counting) + * @length: [DEVICE] number of datums in buffer + * @bytes_per_datum: [DEVICE] size of individual datum including timestamp + * @bpe: [DEVICE] size of individual channel value + * @scan_el_attrs: [DRIVER] control of scan elements if that scan mode + * control method is used + * @scan_count: [INTERN] the number of elements in the current scan mode + * @scan_mask: [INTERN] bitmask used in masking scan mode elements + * @scan_timestamp: [INTERN] does the scan mode include a timestamp + * @access: [DRIVER] buffer access functions associated with the + * implementation. + * @flags: [INTERN] file ops related flags including busy flag. + **/ +struct iio_buffer { + struct iio_dev *indio_dev; + struct module *owner; + int length; + int bytes_per_datum; + int bpe; + struct attribute_group *scan_el_attrs; + int scan_count; + long *scan_mask; + bool scan_timestamp; + const struct iio_buffer_access_funcs *access; + const struct iio_buffer_setup_ops *setup_ops; + struct list_head scan_el_dev_attr_list; + struct attribute_group scan_el_group; + wait_queue_head_t pollq; + bool stufftoread; + unsigned long flags; + const struct attribute_group *attrs; +}; + +/** + * iio_buffer_init() - Initialize the buffer structure + * @buffer: buffer to be initialized + * @indio_dev: the iio device the buffer is assocated with + **/ +void iio_buffer_init(struct iio_buffer *buffer, + struct iio_dev *indio_dev); + +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_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_buffer *buffer, int bit); + +#define to_iio_buffer(d) \ + container_of(d, struct iio_buffer, 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_read_bytes_per_datum() - attr for number of bytes in whole datum + **/ +ssize_t iio_buffer_read_bytes_per_datum(struct device *dev, + struct device_attribute *attr, + char *buf); +/** + * 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_BYTES_PER_DATUM_ATTR \ + DEVICE_ATTR(bytes_per_datum, S_IRUGO | S_IWUSR, \ + iio_buffer_read_bytes_per_datum, NULL) + +#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/Kconfig b/drivers/staging/iio/cdc/Kconfig new file mode 100644 index 0000000..80211df --- /dev/null +++ b/drivers/staging/iio/cdc/Kconfig @@ -0,0 +1,36 @@ +# +# CDC drivers +# +menu "Capacitance to digital converters" + +config AD7150 + tristate "Analog Devices ad7150/1/6 capacitive sensor driver" + depends on I2C + help + Say yes here to build support for Analog Devices capacitive sensors. + (ad7150, ad7151, ad7156) Provides direct access via sysfs. + + To compile this driver as a module, choose M here: the + module will be called ad7150. + +config AD7152 + tristate "Analog Devices ad7152/3 capacitive sensor driver" + depends on I2C + help + Say yes here to build support for Analog Devices capacitive sensors. + (ad7152, ad7153) Provides direct access via sysfs. + + To compile this driver as a module, choose M here: the + module will be called ad7152. + +config AD7746 + tristate "Analog Devices AD7745, AD7746 AD7747 capacitive sensor driver" + depends on I2C + help + Say yes here to build support for Analog Devices capacitive sensors. + (AD7745, AD7746, AD7747) Provides direct access via sysfs. + + To compile this driver as a module, choose M here: the + module will be called ad7746. + +endmenu diff --git a/drivers/staging/iio/cdc/Makefile b/drivers/staging/iio/cdc/Makefile new file mode 100644 index 0000000..a5fbabf --- /dev/null +++ b/drivers/staging/iio/cdc/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for industrial I/O DAC drivers +# + +obj-$(CONFIG_AD7150) += ad7150.o +obj-$(CONFIG_AD7152) += ad7152.o +obj-$(CONFIG_AD7746) += ad7746.o diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c new file mode 100644 index 0000000..a761ca9 --- /dev/null +++ b/drivers/staging/iio/cdc/ad7150.c @@ -0,0 +1,676 @@ +/* + * AD7150 capacitive sensor driver supporting AD7150/1/6 + * + * Copyright 2010-2011 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/i2c.h> +#include <linux/module.h> + +#include "../iio.h" +#include "../sysfs.h" + +/* + * AD7150 registers definition + */ + +#define AD7150_STATUS 0 +#define AD7150_STATUS_OUT1 (1 << 3) +#define AD7150_STATUS_OUT2 (1 << 5) +#define AD7150_CH1_DATA_HIGH 1 +#define AD7150_CH2_DATA_HIGH 3 +#define AD7150_CH1_AVG_HIGH 5 +#define AD7150_CH2_AVG_HIGH 7 +#define AD7150_CH1_SENSITIVITY 9 +#define AD7150_CH1_THR_HOLD_H 9 +#define AD7150_CH1_TIMEOUT 10 +#define AD7150_CH1_SETUP 11 +#define AD7150_CH2_SENSITIVITY 12 +#define AD7150_CH2_THR_HOLD_H 12 +#define AD7150_CH2_TIMEOUT 13 +#define AD7150_CH2_SETUP 14 +#define AD7150_CFG 15 +#define AD7150_CFG_FIX (1 << 7) +#define AD7150_PD_TIMER 16 +#define AD7150_CH1_CAPDAC 17 +#define AD7150_CH2_CAPDAC 18 +#define AD7150_SN3 19 +#define AD7150_SN2 20 +#define AD7150_SN1 21 +#define AD7150_SN0 22 +#define AD7150_ID 23 + +/** + * struct ad7150_chip_info - instance specific chip data + * @client: i2c client for this device + * @current_event: device always has one type of event enabled. + * This element stores the event code of the current one. + * @threshold: thresholds for simple capacitance value events + * @thresh_sensitivity: threshold for simple capacitance offset + * from 'average' value. + * @mag_sensitity: threshold for magnitude of capacitance offset from + * from 'average' value. + * @thresh_timeout: a timeout, in samples from the moment an + * adaptive threshold event occurs to when the average + * value jumps to current value. + * @mag_timeout: a timeout, in sample from the moment an + * adaptive magnitude event occurs to when the average + * value jumps to the current value. + * @old_state: store state from previous event, allowing confirmation + * of new condition. + * @conversion_mode: the current conversion mode. + * @state_lock: ensure consistent state of this structure wrt the + * hardware. + */ +struct ad7150_chip_info { + struct i2c_client *client; + u64 current_event; + u16 threshold[2][2]; + u8 thresh_sensitivity[2][2]; + u8 mag_sensitivity[2][2]; + u8 thresh_timeout[2][2]; + u8 mag_timeout[2][2]; + int old_state; + char *conversion_mode; + struct mutex state_lock; +}; + +/* + * sysfs nodes + */ + +static const u8 ad7150_addresses[][6] = { + { AD7150_CH1_DATA_HIGH, AD7150_CH1_AVG_HIGH, + AD7150_CH1_SETUP, AD7150_CH1_THR_HOLD_H, + AD7150_CH1_SENSITIVITY, AD7150_CH1_TIMEOUT }, + { AD7150_CH2_DATA_HIGH, AD7150_CH2_AVG_HIGH, + AD7150_CH2_SETUP, AD7150_CH2_THR_HOLD_H, + AD7150_CH2_SENSITIVITY, AD7150_CH2_TIMEOUT }, +}; + +static int ad7150_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + int ret; + struct ad7150_chip_info *chip = iio_priv(indio_dev); + + switch (mask) { + case 0: + ret = i2c_smbus_read_word_data(chip->client, + ad7150_addresses[chan->channel][0]); + if (ret < 0) + return ret; + *val = swab16(ret); + return IIO_VAL_INT; + case (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE): + ret = i2c_smbus_read_word_data(chip->client, + ad7150_addresses[chan->channel][1]); + if (ret < 0) + return ret; + *val = swab16(ret); + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int ad7150_read_event_config(struct iio_dev *indio_dev, u64 event_code) +{ + 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) + return ret; + + threshtype = (ret >> 5) & 0x03; + adaptive = !!(ret & 0x80); + + switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) { + case IIO_EV_TYPE_MAG_ADAPTIVE: + if (rising) + return adaptive && (threshtype == 0x1); + else + return adaptive && (threshtype == 0x0); + case IIO_EV_TYPE_THRESH_ADAPTIVE: + if (rising) + return adaptive && (threshtype == 0x3); + else + return adaptive && (threshtype == 0x2); + + case IIO_EV_TYPE_THRESH: + if (rising) + return !adaptive && (threshtype == 0x1); + else + return !adaptive && (threshtype == 0x0); + }; + return -EINVAL; +} + +/* lock should be held */ +static int ad7150_write_event_params(struct iio_dev *indio_dev, u64 event_code) +{ + 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); + + if (event_code != chip->current_event) + return 0; + + switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) { + /* Note completely different from the adaptive versions */ + case IIO_EV_TYPE_THRESH: + value = chip->threshold[rising][chan]; + ret = i2c_smbus_write_word_data(chip->client, + ad7150_addresses[chan][3], + swab16(value)); + if (ret < 0) + return ret; + return 0; + case IIO_EV_TYPE_MAG_ADAPTIVE: + sens = chip->mag_sensitivity[rising][chan]; + timeout = chip->mag_timeout[rising][chan]; + break; + case IIO_EV_TYPE_THRESH_ADAPTIVE: + sens = chip->thresh_sensitivity[rising][chan]; + timeout = chip->thresh_timeout[rising][chan]; + break; + default: + return -EINVAL; + }; + ret = i2c_smbus_write_byte_data(chip->client, + ad7150_addresses[chan][4], + sens); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(chip->client, + ad7150_addresses[chan][5], + timeout); + if (ret < 0) + return ret; + + return 0; +} + +static int ad7150_write_event_config(struct iio_dev *indio_dev, + u64 event_code, 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); + + /* Something must always be turned on */ + if (state == 0) + return -EINVAL; + + if (event_code == chip->current_event) + return 0; + mutex_lock(&chip->state_lock); + ret = i2c_smbus_read_byte_data(chip->client, AD7150_CFG); + if (ret < 0) + goto error_ret; + + cfg = ret & ~((0x03 << 5) | (0x1 << 7)); + + switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) { + case IIO_EV_TYPE_MAG_ADAPTIVE: + adaptive = 1; + if (rising) + thresh_type = 0x1; + else + thresh_type = 0x0; + break; + case IIO_EV_TYPE_THRESH_ADAPTIVE: + adaptive = 1; + if (rising) + thresh_type = 0x3; + else + thresh_type = 0x2; + break; + case IIO_EV_TYPE_THRESH: + adaptive = 0; + if (rising) + thresh_type = 0x1; + else + thresh_type = 0x0; + break; + default: + ret = -EINVAL; + goto error_ret; + }; + + cfg |= (!adaptive << 7) | (thresh_type << 5); + + ret = i2c_smbus_write_byte_data(chip->client, AD7150_CFG, cfg); + if (ret < 0) + goto error_ret; + + chip->current_event = event_code; + + /* update control attributes */ + ret = ad7150_write_event_params(indio_dev, event_code); +error_ret: + mutex_unlock(&chip->state_lock); + + return 0; +} + +static int ad7150_read_event_value(struct iio_dev *indio_dev, + u64 event_code, + int *val) +{ + 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); + + /* Complex register sharing going on here */ + switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) { + case IIO_EV_TYPE_MAG_ADAPTIVE: + *val = chip->mag_sensitivity[rising][chan]; + return 0; + + case IIO_EV_TYPE_THRESH_ADAPTIVE: + *val = chip->thresh_sensitivity[rising][chan]; + return 0; + + case IIO_EV_TYPE_THRESH: + *val = chip->threshold[rising][chan]; + return 0; + + default: + return -EINVAL; + }; +} + +static int ad7150_write_event_value(struct iio_dev *indio_dev, + u64 event_code, + int val) +{ + 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); + + mutex_lock(&chip->state_lock); + switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) { + case IIO_EV_TYPE_MAG_ADAPTIVE: + chip->mag_sensitivity[rising][chan] = val; + break; + case IIO_EV_TYPE_THRESH_ADAPTIVE: + chip->thresh_sensitivity[rising][chan] = val; + break; + case IIO_EV_TYPE_THRESH: + chip->threshold[rising][chan] = val; + break; + default: + ret = -EINVAL; + goto error_ret; + }; + + /* write back if active */ + ret = ad7150_write_event_params(indio_dev, event_code); + +error_ret: + mutex_unlock(&chip->state_lock); + return ret; +} + +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 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 rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(this_attr->address) + == IIO_EV_DIR_RISING); + + switch (IIO_EVENT_CODE_EXTRACT_TYPE(this_attr->address)) { + case IIO_EV_TYPE_MAG_ADAPTIVE: + value = chip->mag_timeout[rising][chan]; + break; + case IIO_EV_TYPE_THRESH_ADAPTIVE: + value = chip->thresh_timeout[rising][chan]; + break; + default: + return -EINVAL; + }; + + return sprintf(buf, "%d\n", value); +} + +static ssize_t ad7150_store_timeout(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(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); + u8 data; + int ret; + + ret = kstrtou8(buf, 10, &data); + if (ret < 0) + return ret; + + mutex_lock(&chip->state_lock); + switch (IIO_EVENT_CODE_EXTRACT_TYPE(this_attr->address)) { + case IIO_EV_TYPE_MAG_ADAPTIVE: + chip->mag_timeout[rising][chan] = data; + break; + case IIO_EV_TYPE_THRESH_ADAPTIVE: + chip->thresh_timeout[rising][chan] = data; + break; + default: + ret = -EINVAL; + goto error_ret; + }; + + ret = ad7150_write_event_params(indio_dev, this_attr->address); +error_ret: + mutex_unlock(&chip->state_lock); + + if (ret < 0) + return ret; + + return len; +} + +#define AD7150_TIMEOUT(chan, type, dir, ev_type, ev_dir) \ + IIO_DEVICE_ATTR(in_capacitance##chan##_##type##_##dir##_timeout, \ + S_IRUGO | S_IWUSR, \ + &ad7150_show_timeout, \ + &ad7150_store_timeout, \ + IIO_UNMOD_EVENT_CODE(IIO_CAPACITANCE, \ + chan, \ + IIO_EV_TYPE_##ev_type, \ + IIO_EV_DIR_##ev_dir)) +static AD7150_TIMEOUT(0, mag_adaptive, rising, MAG_ADAPTIVE, RISING); +static AD7150_TIMEOUT(0, mag_adaptive, falling, MAG_ADAPTIVE, FALLING); +static AD7150_TIMEOUT(1, mag_adaptive, rising, MAG_ADAPTIVE, RISING); +static AD7150_TIMEOUT(1, mag_adaptive, falling, MAG_ADAPTIVE, FALLING); +static AD7150_TIMEOUT(0, thresh_adaptive, rising, THRESH_ADAPTIVE, RISING); +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_chan_spec ad7150_channels[] = { + { + .type = IIO_CAPACITANCE, + .indexed = 1, + .channel = 0, + .info_mask = (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE), + .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) + }, { + .type = IIO_CAPACITANCE, + .indexed = 1, + .channel = 1, + .info_mask = (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE), + .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) + }, +}; + +/* + * threshold events + */ + +static irqreturn_t ad7150_event_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct ad7150_chip_info *chip = iio_priv(indio_dev); + u8 int_status; + s64 timestamp = iio_get_time_ns(); + int ret; + + ret = i2c_smbus_read_byte_data(chip->client, AD7150_STATUS); + if (ret < 0) + return IRQ_HANDLED; + + int_status = ret; + + if ((int_status & AD7150_STATUS_OUT1) && + !(chip->old_state & AD7150_STATUS_OUT1)) + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_CAPACITANCE, + 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + timestamp); + else if ((!(int_status & AD7150_STATUS_OUT1)) && + (chip->old_state & AD7150_STATUS_OUT1)) + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_CAPACITANCE, + 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + timestamp); + + if ((int_status & AD7150_STATUS_OUT2) && + !(chip->old_state & AD7150_STATUS_OUT2)) + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_CAPACITANCE, + 1, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + timestamp); + else if ((!(int_status & AD7150_STATUS_OUT2)) && + (chip->old_state & AD7150_STATUS_OUT2)) + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_CAPACITANCE, + 1, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + timestamp); + /* store the status to avoid repushing same events */ + chip->old_state = int_status; + + return IRQ_HANDLED; +} + +/* Timeouts not currently handled by core */ +static struct attribute *ad7150_event_attributes[] = { + &iio_dev_attr_in_capacitance0_mag_adaptive_rising_timeout + .dev_attr.attr, + &iio_dev_attr_in_capacitance0_mag_adaptive_falling_timeout + .dev_attr.attr, + &iio_dev_attr_in_capacitance1_mag_adaptive_rising_timeout + .dev_attr.attr, + &iio_dev_attr_in_capacitance1_mag_adaptive_falling_timeout + .dev_attr.attr, + &iio_dev_attr_in_capacitance0_thresh_adaptive_rising_timeout + .dev_attr.attr, + &iio_dev_attr_in_capacitance0_thresh_adaptive_falling_timeout + .dev_attr.attr, + &iio_dev_attr_in_capacitance1_thresh_adaptive_rising_timeout + .dev_attr.attr, + &iio_dev_attr_in_capacitance1_thresh_adaptive_falling_timeout + .dev_attr.attr, + NULL, +}; + +static struct attribute_group ad7150_event_attribute_group = { + .attrs = ad7150_event_attributes, + .name = "events", +}; + +static const struct iio_info ad7150_info = { + .event_attrs = &ad7150_event_attribute_group, + .driver_module = THIS_MODULE, + .read_raw = &ad7150_read_raw, + .read_event_config = &ad7150_read_event_config, + .write_event_config = &ad7150_write_event_config, + .read_event_value = &ad7150_read_event_value, + .write_event_value = &ad7150_write_event_value, +}; + +/* + * device probe and remove + */ + +static int __devinit 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; + } + chip = iio_priv(indio_dev); + mutex_init(&chip->state_lock); + /* this is only used for device removal purposes */ + i2c_set_clientdata(client, indio_dev); + + chip->client = client; + + indio_dev->name = id->name; + indio_dev->channels = ad7150_channels; + indio_dev->num_channels = ARRAY_SIZE(ad7150_channels); + /* Establish that the iio_dev is a child of the i2c device */ + indio_dev->dev.parent = &client->dev; + + indio_dev->info = &ad7150_info; + + indio_dev->modes = INDIO_DIRECT_MODE; + + if (client->irq) { + ret = request_threaded_irq(client->irq, + NULL, + &ad7150_event_handler, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, + "ad7150_irq1", + indio_dev); + if (ret) + goto error_free_dev; + } + + if (client->dev.platform_data) { + ret = request_threaded_irq(*(unsigned int *) + client->dev.platform_data, + NULL, + &ad7150_event_handler, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, + "ad7150_irq2", + indio_dev); + if (ret) + goto error_free_irq; + } + + ret = iio_device_register(indio_dev); + if (ret) + goto error_free_irq2; + + 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) +{ + 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; +} + +static const struct i2c_device_id ad7150_id[] = { + { "ad7150", 0 }, + { "ad7151", 0 }, + { "ad7156", 0 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, ad7150_id); + +static struct i2c_driver ad7150_driver = { + .driver = { + .name = "ad7150", + }, + .probe = ad7150_probe, + .remove = __devexit_p(ad7150_remove), + .id_table = ad7150_id, +}; + +static __init int ad7150_init(void) +{ + return i2c_add_driver(&ad7150_driver); +} + +static __exit void ad7150_exit(void) +{ + i2c_del_driver(&ad7150_driver); +} + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices AD7150/1/6 capacitive sensor driver"); +MODULE_LICENSE("GPL v2"); + +module_init(ad7150_init); +module_exit(ad7150_exit); diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c new file mode 100644 index 0000000..662584d --- /dev/null +++ b/drivers/staging/iio/cdc/ad7152.c @@ -0,0 +1,559 @@ +/* + * AD7152 capacitive sensor driver supporting AD7152/3 + * + * Copyright 2010-2011a 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/i2c.h> +#include <linux/module.h> +#include <linux/delay.h> + +#include "../iio.h" +#include "../sysfs.h" + +/* + * TODO: Check compliance of calibbias with abi (units) + */ +/* + * AD7152 registers definition + */ + +#define AD7152_REG_STATUS 0 +#define AD7152_REG_CH1_DATA_HIGH 1 +#define AD7152_REG_CH2_DATA_HIGH 3 +#define AD7152_REG_CH1_OFFS_HIGH 5 +#define AD7152_REG_CH2_OFFS_HIGH 7 +#define AD7152_REG_CH1_GAIN_HIGH 9 +#define AD7152_REG_CH1_SETUP 11 +#define AD7152_REG_CH2_GAIN_HIGH 12 +#define AD7152_REG_CH2_SETUP 14 +#define AD7152_REG_CFG 15 +#define AD7152_REG_RESEVERD 16 +#define AD7152_REG_CAPDAC_POS 17 +#define AD7152_REG_CAPDAC_NEG 18 +#define AD7152_REG_CFG2 26 + +/* Status Register Bit Designations (AD7152_REG_STATUS) */ +#define AD7152_STATUS_RDY1 (1 << 0) +#define AD7152_STATUS_RDY2 (1 << 1) +#define AD7152_STATUS_C1C2 (1 << 2) +#define AD7152_STATUS_PWDN (1 << 7) + +/* Setup Register Bit Designations (AD7152_REG_CHx_SETUP) */ +#define AD7152_SETUP_CAPDIFF (1 << 5) +#define AD7152_SETUP_RANGE_2pF (0 << 6) +#define AD7152_SETUP_RANGE_0_5pF (1 << 6) +#define AD7152_SETUP_RANGE_1pF (2 << 6) +#define AD7152_SETUP_RANGE_4pF (3 << 6) +#define AD7152_SETUP_RANGE(x) ((x) << 6) + +/* Config Register Bit Designations (AD7152_REG_CFG) */ +#define AD7152_CONF_CH2EN (1 << 3) +#define AD7152_CONF_CH1EN (1 << 4) +#define AD7152_CONF_MODE_IDLE (0 << 0) +#define AD7152_CONF_MODE_CONT_CONV (1 << 0) +#define AD7152_CONF_MODE_SINGLE_CONV (2 << 0) +#define AD7152_CONF_MODE_OFFS_CAL (5 << 0) +#define AD7152_CONF_MODE_GAIN_CAL (6 << 0) + +/* Capdac Register Bit Designations (AD7152_REG_CAPDAC_XXX) */ +#define AD7152_CAPDAC_DACEN (1 << 7) +#define AD7152_CAPDAC_DACP(x) ((x) & 0x1F) + +/* CFG2 Register Bit Designations (AD7152_REG_CFG2) */ +#define AD7152_CFG2_OSR(x) (((x) & 0x3) << 4) + +enum { + AD7152_DATA, + AD7152_OFFS, + AD7152_GAIN, + AD7152_SETUP +}; + +/* + * struct ad7152_chip_info - chip specifc information + */ + +struct ad7152_chip_info { + struct i2c_client *client; + /* + * Capacitive channel digital filter setup; + * conversion time/update rate setup per channel + */ + u8 filter_rate_setup; + u8 setup[2]; +}; + +static inline ssize_t ad7152_start_calib(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len, + u8 regval) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = iio_priv(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + bool doit; + int ret, timeout = 10; + + ret = strtobool(buf, &doit); + if (ret < 0) + return ret; + + if (!doit) + return 0; + + if (this_attr->address == 0) + regval |= AD7152_CONF_CH1EN; + else + regval |= AD7152_CONF_CH2EN; + + mutex_lock(&indio_dev->mlock); + ret = i2c_smbus_write_byte_data(chip->client, AD7152_REG_CFG, regval); + if (ret < 0) { + mutex_unlock(&indio_dev->mlock); + return ret; + } + + do { + mdelay(20); + ret = i2c_smbus_read_byte_data(chip->client, AD7152_REG_CFG); + if (ret < 0) { + mutex_unlock(&indio_dev->mlock); + return ret; + } + } while ((ret == regval) && timeout--); + + mutex_unlock(&indio_dev->mlock); + return len; +} +static ssize_t ad7152_start_offset_calib(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return ad7152_start_calib(dev, attr, buf, len, + AD7152_CONF_MODE_OFFS_CAL); +} +static ssize_t ad7152_start_gain_calib(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return ad7152_start_calib(dev, attr, buf, len, + AD7152_CONF_MODE_GAIN_CAL); +} + +static IIO_DEVICE_ATTR(in_capacitance0_calibbias_calibration, + S_IWUSR, NULL, ad7152_start_offset_calib, 0); +static IIO_DEVICE_ATTR(in_capacitance1_calibbias_calibration, + S_IWUSR, NULL, ad7152_start_offset_calib, 1); +static IIO_DEVICE_ATTR(in_capacitance0_calibscale_calibration, + S_IWUSR, NULL, ad7152_start_gain_calib, 0); +static IIO_DEVICE_ATTR(in_capacitance1_calibscale_calibration, + S_IWUSR, NULL, ad7152_start_gain_calib, 1); + +/* Values are Update Rate (Hz), Conversion Time (ms) + 1*/ +static const unsigned char ad7152_filter_rate_table[][2] = { + {200, 5 + 1}, {50, 20 + 1}, {20, 50 + 1}, {17, 60 + 1}, +}; + +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 ad7152_chip_info *chip = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", + ad7152_filter_rate_table[chip->filter_rate_setup][0]); +} + +static ssize_t ad7152_store_filter_rate_setup(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = iio_priv(indio_dev); + u8 data; + int ret, i; + + ret = kstrtou8(buf, 10, &data); + if (ret < 0) + return ret; + + for (i = 0; i < ARRAY_SIZE(ad7152_filter_rate_table); i++) + if (data >= ad7152_filter_rate_table[i][0]) + break; + + if (i >= ARRAY_SIZE(ad7152_filter_rate_table)) + i = ARRAY_SIZE(ad7152_filter_rate_table) - 1; + + mutex_lock(&indio_dev->mlock); + ret = i2c_smbus_write_byte_data(chip->client, + AD7152_REG_CFG2, AD7152_CFG2_OSR(i)); + if (ret < 0) { + mutex_unlock(&indio_dev->mlock); + return ret; + } + + chip->filter_rate_setup = i; + mutex_unlock(&indio_dev->mlock); + + return len; +} + +static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR, + ad7152_show_filter_rate_setup, + ad7152_store_filter_rate_setup); + +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("200 50 20 17"); + +static IIO_CONST_ATTR(in_capacitance_scale_available, + "0.000061050 0.000030525 0.000015263 0.000007631"); + +static struct attribute *ad7152_attributes[] = { + &iio_dev_attr_sampling_frequency.dev_attr.attr, + &iio_dev_attr_in_capacitance0_calibbias_calibration.dev_attr.attr, + &iio_dev_attr_in_capacitance1_calibbias_calibration.dev_attr.attr, + &iio_dev_attr_in_capacitance0_calibscale_calibration.dev_attr.attr, + &iio_dev_attr_in_capacitance1_calibscale_calibration.dev_attr.attr, + &iio_const_attr_in_capacitance_scale_available.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7152_attribute_group = { + .attrs = ad7152_attributes, +}; + +static const u8 ad7152_addresses[][4] = { + { AD7152_REG_CH1_DATA_HIGH, AD7152_REG_CH1_OFFS_HIGH, + AD7152_REG_CH1_GAIN_HIGH, AD7152_REG_CH1_SETUP }, + { AD7152_REG_CH2_DATA_HIGH, AD7152_REG_CH2_OFFS_HIGH, + AD7152_REG_CH2_GAIN_HIGH, AD7152_REG_CH2_SETUP }, +}; + +/* Values are nano relative to pf base. */ +static const int ad7152_scale_table[] = { + 30525, 7631, 15263, 61050 +}; + +static int ad7152_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad7152_chip_info *chip = iio_priv(indio_dev); + int ret, i; + + mutex_lock(&indio_dev->mlock); + + switch (mask) { + case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + if (val != 1) { + ret = -EINVAL; + goto out; + } + + val = (val2 * 1024) / 15625; + + ret = i2c_smbus_write_word_data(chip->client, + ad7152_addresses[chan->channel][AD7152_GAIN], + swab16(val)); + if (ret < 0) + goto out; + + ret = 0; + break; + + case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + if ((val < 0) | (val > 0xFFFF)) { + ret = -EINVAL; + goto out; + } + ret = i2c_smbus_write_word_data(chip->client, + ad7152_addresses[chan->channel][AD7152_OFFS], + swab16(val)); + if (ret < 0) + goto out; + + ret = 0; + break; + case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + if (val != 0) { + ret = -EINVAL; + goto out; + } + for (i = 0; i < ARRAY_SIZE(ad7152_scale_table); i++) + if (val2 == ad7152_scale_table[i]) + break; + + chip->setup[chan->channel] &= ~AD7152_SETUP_RANGE_4pF; + chip->setup[chan->channel] |= AD7152_SETUP_RANGE(i); + + ret = i2c_smbus_write_byte_data(chip->client, + ad7152_addresses[chan->channel][AD7152_SETUP], + chip->setup[chan->channel]); + if (ret < 0) + goto out; + + ret = 0; + break; + default: + ret = -EINVAL; + } + +out: + mutex_unlock(&indio_dev->mlock); + return ret; +} +static int ad7152_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, + long mask) +{ + struct ad7152_chip_info *chip = iio_priv(indio_dev); + int ret; + u8 regval = 0; + + mutex_lock(&indio_dev->mlock); + + switch (mask) { + case 0: + /* First set whether in differential mode */ + + regval = chip->setup[chan->channel]; + + if (chan->differential) + chip->setup[chan->channel] |= AD7152_SETUP_CAPDIFF; + else + chip->setup[chan->channel] &= ~AD7152_SETUP_CAPDIFF; + + if (regval != chip->setup[chan->channel]) { + ret = i2c_smbus_write_byte_data(chip->client, + ad7152_addresses[chan->channel][AD7152_SETUP], + chip->setup[chan->channel]); + if (ret < 0) + goto out; + } + /* Make sure the channel is enabled */ + if (chan->channel == 0) + regval = AD7152_CONF_CH1EN; + else + regval = AD7152_CONF_CH2EN; + + /* Trigger a single read */ + regval |= AD7152_CONF_MODE_SINGLE_CONV; + ret = i2c_smbus_write_byte_data(chip->client, AD7152_REG_CFG, + regval); + if (ret < 0) + goto out; + + msleep(ad7152_filter_rate_table[chip->filter_rate_setup][1]); + /* Now read the actual register */ + ret = i2c_smbus_read_word_data(chip->client, + ad7152_addresses[chan->channel][AD7152_DATA]); + if (ret < 0) + goto out; + *val = swab16(ret); + + if (chan->differential) + *val -= 0x8000; + + ret = IIO_VAL_INT; + break; + case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + + ret = i2c_smbus_read_word_data(chip->client, + ad7152_addresses[chan->channel][AD7152_GAIN]); + if (ret < 0) + goto out; + /* 1 + gain_val / 2^16 */ + *val = 1; + *val2 = (15625 * swab16(ret)) / 1024; + + ret = IIO_VAL_INT_PLUS_MICRO; + break; + case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + ret = i2c_smbus_read_word_data(chip->client, + ad7152_addresses[chan->channel][AD7152_OFFS]); + if (ret < 0) + goto out; + *val = swab16(ret); + + ret = IIO_VAL_INT; + break; + case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + ret = i2c_smbus_read_byte_data(chip->client, + ad7152_addresses[chan->channel][AD7152_SETUP]); + if (ret < 0) + goto out; + *val = 0; + *val2 = ad7152_scale_table[ret >> 6]; + + ret = IIO_VAL_INT_PLUS_NANO; + break; + default: + ret = -EINVAL; + }; +out: + mutex_unlock(&indio_dev->mlock); + return ret; +} + +static int ad7152_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask) +{ + switch (mask) { + case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + return IIO_VAL_INT_PLUS_NANO; + default: + return IIO_VAL_INT_PLUS_MICRO; + } +} + +static const struct iio_info ad7152_info = { + .attrs = &ad7152_attribute_group, + .read_raw = &ad7152_read_raw, + .write_raw = &ad7152_write_raw, + .write_raw_get_fmt = &ad7152_write_raw_get_fmt, + .driver_module = THIS_MODULE, +}; + +static const struct iio_chan_spec ad7152_channels[] = { + { + .type = IIO_CAPACITANCE, + .indexed = 1, + .channel = 0, + .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | + (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + }, { + .type = IIO_CAPACITANCE, + .differential = 1, + .indexed = 1, + .channel = 0, + .channel2 = 2, + .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | + (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + }, { + .type = IIO_CAPACITANCE, + .indexed = 1, + .channel = 1, + .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | + (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + }, { + .type = IIO_CAPACITANCE, + .differential = 1, + .indexed = 1, + .channel = 1, + .channel2 = 3, + .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | + (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + } +}; +/* + * device probe and remove + */ + +static int __devinit 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; + } + chip = iio_priv(indio_dev); + /* this is only used for device removal purposes */ + i2c_set_clientdata(client, indio_dev); + + chip->client = client; + + /* Establish that the iio_dev is a child of the i2c device */ + indio_dev->name = id->name; + indio_dev->dev.parent = &client->dev; + indio_dev->info = &ad7152_info; + indio_dev->channels = ad7152_channels; + if (id->driver_data == 0) + indio_dev->num_channels = ARRAY_SIZE(ad7152_channels); + else + indio_dev->num_channels = 2; + indio_dev->num_channels = ARRAY_SIZE(ad7152_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_free_dev; + + 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) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + iio_free_device(indio_dev); + + return 0; +} + +static const struct i2c_device_id ad7152_id[] = { + { "ad7152", 0 }, + { "ad7153", 1 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, ad7152_id); + +static struct i2c_driver ad7152_driver = { + .driver = { + .name = KBUILD_MODNAME, + }, + .probe = ad7152_probe, + .remove = __devexit_p(ad7152_remove), + .id_table = ad7152_id, +}; + +static __init int ad7152_init(void) +{ + return i2c_add_driver(&ad7152_driver); +} + +static __exit void ad7152_exit(void) +{ + i2c_del_driver(&ad7152_driver); +} + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices AD7152/3 capacitive sensor driver"); +MODULE_LICENSE("GPL v2"); + +module_init(ad7152_init); +module_exit(ad7152_exit); diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c new file mode 100644 index 0000000..2867943 --- /dev/null +++ b/drivers/staging/iio/cdc/ad7746.c @@ -0,0 +1,807 @@ +/* + * AD7746 capacitive sensor driver supporting AD7745, AD7746 and AD7747 + * + * 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/i2c.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/stat.h> + +#include "../iio.h" +#include "../sysfs.h" + +#include "ad7746.h" + +/* + * AD7746 Register Definition + */ + +#define AD7746_REG_STATUS 0 +#define AD7746_REG_CAP_DATA_HIGH 1 +#define AD7746_REG_CAP_DATA_MID 2 +#define AD7746_REG_CAP_DATA_LOW 3 +#define AD7746_REG_VT_DATA_HIGH 4 +#define AD7746_REG_VT_DATA_MID 5 +#define AD7746_REG_VT_DATA_LOW 6 +#define AD7746_REG_CAP_SETUP 7 +#define AD7746_REG_VT_SETUP 8 +#define AD7746_REG_EXC_SETUP 9 +#define AD7746_REG_CFG 10 +#define AD7746_REG_CAPDACA 11 +#define AD7746_REG_CAPDACB 12 +#define AD7746_REG_CAP_OFFH 13 +#define AD7746_REG_CAP_OFFL 14 +#define AD7746_REG_CAP_GAINH 15 +#define AD7746_REG_CAP_GAINL 16 +#define AD7746_REG_VOLT_GAINH 17 +#define AD7746_REG_VOLT_GAINL 18 + +/* Status Register Bit Designations (AD7746_REG_STATUS) */ +#define AD7746_STATUS_EXCERR (1 << 3) +#define AD7746_STATUS_RDY (1 << 2) +#define AD7746_STATUS_RDYVT (1 << 1) +#define AD7746_STATUS_RDYCAP (1 << 0) + +/* Capacitive Channel Setup Register Bit Designations (AD7746_REG_CAP_SETUP) */ +#define AD7746_CAPSETUP_CAPEN (1 << 7) +#define AD7746_CAPSETUP_CIN2 (1 << 6) /* AD7746 only */ +#define AD7746_CAPSETUP_CAPDIFF (1 << 5) +#define AD7746_CAPSETUP_CACHOP (1 << 0) + +/* Voltage/Temperature Setup Register Bit Designations (AD7746_REG_VT_SETUP) */ +#define AD7746_VTSETUP_VTEN (1 << 7) +#define AD7746_VTSETUP_VTMD_INT_TEMP (0 << 5) +#define AD7746_VTSETUP_VTMD_EXT_TEMP (1 << 5) +#define AD7746_VTSETUP_VTMD_VDD_MON (2 << 5) +#define AD7746_VTSETUP_VTMD_EXT_VIN (3 << 5) +#define AD7746_VTSETUP_EXTREF (1 << 4) +#define AD7746_VTSETUP_VTSHORT (1 << 1) +#define AD7746_VTSETUP_VTCHOP (1 << 0) + +/* Excitation Setup Register Bit Designations (AD7746_REG_EXC_SETUP) */ +#define AD7746_EXCSETUP_CLKCTRL (1 << 7) +#define AD7746_EXCSETUP_EXCON (1 << 6) +#define AD7746_EXCSETUP_EXCB (1 << 5) +#define AD7746_EXCSETUP_NEXCB (1 << 4) +#define AD7746_EXCSETUP_EXCA (1 << 3) +#define AD7746_EXCSETUP_NEXCA (1 << 2) +#define AD7746_EXCSETUP_EXCLVL(x) (((x) & 0x3) << 0) + +/* Config Register Bit Designations (AD7746_REG_CFG) */ +#define AD7746_CONF_VTFS(x) ((x) << 6) +#define AD7746_CONF_CAPFS(x) ((x) << 3) +#define AD7746_CONF_MODE_IDLE (0 << 0) +#define AD7746_CONF_MODE_CONT_CONV (1 << 0) +#define AD7746_CONF_MODE_SINGLE_CONV (2 << 0) +#define AD7746_CONF_MODE_PWRDN (3 << 0) +#define AD7746_CONF_MODE_OFFS_CAL (5 << 0) +#define AD7746_CONF_MODE_GAIN_CAL (6 << 0) + +/* CAPDAC Register Bit Designations (AD7746_REG_CAPDACx) */ +#define AD7746_CAPDAC_DACEN (1 << 7) +#define AD7746_CAPDAC_DACP(x) ((x) & 0x7F) + +/* + * struct ad7746_chip_info - chip specifc information + */ + +struct ad7746_chip_info { + struct i2c_client *client; + /* + * Capacitive channel digital filter setup; + * conversion time/update rate setup per channel + */ + u8 config; + u8 cap_setup; + u8 vt_setup; + u8 capdac[2][2]; + s8 capdac_set; +}; + +enum ad7746_chan { + VIN, + VIN_VDD, + TEMP_INT, + TEMP_EXT, + CIN1, + CIN1_DIFF, + CIN2, + CIN2_DIFF, +}; + +static const struct iio_chan_spec ad7746_channels[] = { + [VIN] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .address = AD7746_REG_VT_DATA_HIGH << 8 | + AD7746_VTSETUP_VTMD_EXT_VIN, + }, + [VIN_VDD] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 1, + .extend_name = "supply", + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .address = AD7746_REG_VT_DATA_HIGH << 8 | + AD7746_VTSETUP_VTMD_VDD_MON, + }, + [TEMP_INT] = { + .type = IIO_TEMP, + .indexed = 1, + .channel = 0, + .processed_val = IIO_PROCESSED, + .address = AD7746_REG_VT_DATA_HIGH << 8 | + AD7746_VTSETUP_VTMD_INT_TEMP, + }, + [TEMP_EXT] = { + .type = IIO_TEMP, + .indexed = 1, + .channel = 1, + .processed_val = IIO_PROCESSED, + .address = AD7746_REG_VT_DATA_HIGH << 8 | + AD7746_VTSETUP_VTMD_EXT_TEMP, + }, + [CIN1] = { + .type = IIO_CAPACITANCE, + .indexed = 1, + .channel = 0, + .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | + (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED) | + (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .address = AD7746_REG_CAP_DATA_HIGH << 8, + }, + [CIN1_DIFF] = { + .type = IIO_CAPACITANCE, + .differential = 1, + .indexed = 1, + .channel = 0, + .channel2 = 2, + .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | + (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED) | + (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .address = AD7746_REG_CAP_DATA_HIGH << 8 | + AD7746_CAPSETUP_CAPDIFF + }, + [CIN2] = { + .type = IIO_CAPACITANCE, + .indexed = 1, + .channel = 1, + .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | + (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED) | + (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .address = AD7746_REG_CAP_DATA_HIGH << 8 | + AD7746_CAPSETUP_CIN2, + }, + [CIN2_DIFF] = { + .type = IIO_CAPACITANCE, + .differential = 1, + .indexed = 1, + .channel = 1, + .channel2 = 3, + .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | + (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED) | + (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .address = AD7746_REG_CAP_DATA_HIGH << 8 | + AD7746_CAPSETUP_CAPDIFF | AD7746_CAPSETUP_CIN2, + } +}; + +/* Values are Update Rate (Hz), Conversion Time (ms) + 1*/ +static const unsigned char ad7746_vt_filter_rate_table[][2] = { + {50, 20 + 1}, {31, 32 + 1}, {16, 62 + 1}, {8, 122 + 1}, +}; + +static const unsigned char ad7746_cap_filter_rate_table[][2] = { + {91, 11 + 1}, {84, 12 + 1}, {50, 20 + 1}, {26, 38 + 1}, + {16, 62 + 1}, {13, 77 + 1}, {11, 92 + 1}, {9, 110 + 1}, +}; + +static int ad7746_select_channel(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + struct ad7746_chip_info *chip = iio_priv(indio_dev); + int ret, delay; + u8 vt_setup, cap_setup; + + switch (chan->type) { + case IIO_CAPACITANCE: + cap_setup = (chan->address & 0xFF) | AD7746_CAPSETUP_CAPEN; + vt_setup = chip->vt_setup & ~AD7746_VTSETUP_VTEN; + delay = ad7746_cap_filter_rate_table[(chip->config >> 3) & + 0x7][1]; + + if (chip->capdac_set != chan->channel) { + ret = i2c_smbus_write_byte_data(chip->client, + AD7746_REG_CAPDACA, + chip->capdac[chan->channel][0]); + if (ret < 0) + return ret; + ret = i2c_smbus_write_byte_data(chip->client, + AD7746_REG_CAPDACB, + chip->capdac[chan->channel][1]); + if (ret < 0) + return ret; + + chip->capdac_set = chan->channel; + } + break; + case IIO_VOLTAGE: + case IIO_TEMP: + vt_setup = (chan->address & 0xFF) | AD7746_VTSETUP_VTEN; + cap_setup = chip->cap_setup & ~AD7746_CAPSETUP_CAPEN; + delay = ad7746_cap_filter_rate_table[(chip->config >> 6) & + 0x3][1]; + break; + default: + return -EINVAL; + } + + if (chip->cap_setup != cap_setup) { + ret = i2c_smbus_write_byte_data(chip->client, + AD7746_REG_CAP_SETUP, + cap_setup); + if (ret < 0) + return ret; + + chip->cap_setup = cap_setup; + } + + if (chip->vt_setup != vt_setup) { + ret = i2c_smbus_write_byte_data(chip->client, + AD7746_REG_VT_SETUP, + vt_setup); + if (ret < 0) + return ret; + + chip->vt_setup = vt_setup; + } + + return delay; +} + +static inline ssize_t ad7746_start_calib(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len, + u8 regval) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7746_chip_info *chip = iio_priv(indio_dev); + bool doit; + int ret, timeout = 10; + + ret = strtobool(buf, &doit); + if (ret < 0) + return ret; + + if (!doit) + return 0; + + mutex_lock(&indio_dev->mlock); + regval |= chip->config; + ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_CFG, regval); + if (ret < 0) { + mutex_unlock(&indio_dev->mlock); + return ret; + } + + do { + msleep(20); + ret = i2c_smbus_read_byte_data(chip->client, AD7746_REG_CFG); + if (ret < 0) { + mutex_unlock(&indio_dev->mlock); + return ret; + } + } while ((ret == regval) && timeout--); + + mutex_unlock(&indio_dev->mlock); + + return len; +} + +static ssize_t ad7746_start_offset_calib(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + int ret = ad7746_select_channel(indio_dev, + &ad7746_channels[to_iio_dev_attr(attr)->address]); + if (ret < 0) + return ret; + + return ad7746_start_calib(dev, attr, buf, len, + AD7746_CONF_MODE_OFFS_CAL); +} + +static ssize_t ad7746_start_gain_calib(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + int ret = ad7746_select_channel(indio_dev, + &ad7746_channels[to_iio_dev_attr(attr)->address]); + if (ret < 0) + return ret; + + return ad7746_start_calib(dev, attr, buf, len, + AD7746_CONF_MODE_GAIN_CAL); +} + +static IIO_DEVICE_ATTR(in_capacitance0_calibbias_calibration, + S_IWUSR, NULL, ad7746_start_offset_calib, CIN1); +static IIO_DEVICE_ATTR(in_capacitance1_calibbias_calibration, + S_IWUSR, NULL, ad7746_start_offset_calib, CIN2); +static IIO_DEVICE_ATTR(in_capacitance0_calibscale_calibration, + S_IWUSR, NULL, ad7746_start_gain_calib, CIN1); +static IIO_DEVICE_ATTR(in_capacitance1_calibscale_calibration, + S_IWUSR, NULL, ad7746_start_gain_calib, CIN2); +static IIO_DEVICE_ATTR(in_voltage0_calibscale_calibration, + S_IWUSR, NULL, ad7746_start_gain_calib, VIN); + +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 ad7746_chip_info *chip = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", ad7746_cap_filter_rate_table[ + (chip->config >> 3) & 0x7][0]); +} + +static ssize_t ad7746_store_cap_filter_rate_setup(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7746_chip_info *chip = iio_priv(indio_dev); + u8 data; + int ret, i; + + ret = kstrtou8(buf, 10, &data); + if (ret < 0) + return ret; + + for (i = 0; i < ARRAY_SIZE(ad7746_cap_filter_rate_table); i++) + if (data >= ad7746_cap_filter_rate_table[i][0]) + break; + + if (i >= ARRAY_SIZE(ad7746_cap_filter_rate_table)) + i = ARRAY_SIZE(ad7746_cap_filter_rate_table) - 1; + + mutex_lock(&indio_dev->mlock); + chip->config &= ~AD7746_CONF_CAPFS(0x7); + chip->config |= AD7746_CONF_CAPFS(i); + mutex_unlock(&indio_dev->mlock); + + return len; +} + +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 ad7746_chip_info *chip = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", ad7746_vt_filter_rate_table[ + (chip->config >> 6) & 0x3][0]); +} + +static ssize_t ad7746_store_vt_filter_rate_setup(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7746_chip_info *chip = iio_priv(indio_dev); + u8 data; + int ret, i; + + ret = kstrtou8(buf, 10, &data); + if (ret < 0) + return ret; + + for (i = 0; i < ARRAY_SIZE(ad7746_vt_filter_rate_table); i++) + if (data >= ad7746_vt_filter_rate_table[i][0]) + break; + + if (i >= ARRAY_SIZE(ad7746_vt_filter_rate_table)) + i = ARRAY_SIZE(ad7746_vt_filter_rate_table) - 1; + + mutex_lock(&indio_dev->mlock); + chip->config &= ~AD7746_CONF_VTFS(0x3); + chip->config |= AD7746_CONF_VTFS(i); + mutex_unlock(&indio_dev->mlock); + + return len; +} + +static IIO_DEVICE_ATTR(in_capacitance_sampling_frequency, + S_IRUGO | S_IWUSR, ad7746_show_cap_filter_rate_setup, + ad7746_store_cap_filter_rate_setup, 0); + +static IIO_DEVICE_ATTR(in_voltage_sampling_frequency, + S_IRUGO | S_IWUSR, ad7746_show_vt_filter_rate_setup, + ad7746_store_vt_filter_rate_setup, 0); + +static IIO_CONST_ATTR(in_voltage_sampling_frequency_available, "50 31 16 8"); +static IIO_CONST_ATTR(in_capacitance_sampling_frequency_available, + "91 84 50 26 16 13 11 9"); + +static struct attribute *ad7746_attributes[] = { + &iio_dev_attr_in_capacitance_sampling_frequency.dev_attr.attr, + &iio_dev_attr_in_voltage_sampling_frequency.dev_attr.attr, + &iio_dev_attr_in_capacitance0_calibbias_calibration.dev_attr.attr, + &iio_dev_attr_in_capacitance0_calibscale_calibration.dev_attr.attr, + &iio_dev_attr_in_capacitance1_calibscale_calibration.dev_attr.attr, + &iio_dev_attr_in_capacitance1_calibbias_calibration.dev_attr.attr, + &iio_dev_attr_in_voltage0_calibscale_calibration.dev_attr.attr, + &iio_const_attr_in_voltage_sampling_frequency_available.dev_attr.attr, + &iio_const_attr_in_capacitance_sampling_frequency_available. + dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7746_attribute_group = { + .attrs = ad7746_attributes, +}; + +static int ad7746_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad7746_chip_info *chip = iio_priv(indio_dev); + int ret, reg; + + mutex_lock(&indio_dev->mlock); + + switch (mask) { + case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + if (val != 1) { + ret = -EINVAL; + goto out; + } + + val = (val2 * 1024) / 15625; + + switch (chan->type) { + case IIO_CAPACITANCE: + reg = AD7746_REG_CAP_GAINH; + break; + case IIO_VOLTAGE: + reg = AD7746_REG_VOLT_GAINH; + break; + default: + ret = -EINVAL; + goto out; + } + + ret = i2c_smbus_write_word_data(chip->client, reg, swab16(val)); + if (ret < 0) + goto out; + + ret = 0; + break; + case (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED): + if ((val < 0) | (val > 0xFFFF)) { + ret = -EINVAL; + goto out; + } + ret = i2c_smbus_write_word_data(chip->client, + AD7746_REG_CAP_OFFH, swab16(val)); + if (ret < 0) + goto out; + + ret = 0; + break; + case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + if ((val < 0) | (val > 43008000)) { /* 21pF */ + ret = -EINVAL; + goto out; + } + + /* CAPDAC Scale = 21pF_typ / 127 + * CIN Scale = 8.192pF / 2^24 + * Offset Scale = CAPDAC Scale / CIN Scale = 338646 + * */ + + val /= 338646; + + chip->capdac[chan->channel][chan->differential] = (val > 0 ? + AD7746_CAPDAC_DACP(val) | AD7746_CAPDAC_DACEN : 0); + + ret = i2c_smbus_write_byte_data(chip->client, + AD7746_REG_CAPDACA, + chip->capdac[chan->channel][0]); + if (ret < 0) + goto out; + ret = i2c_smbus_write_byte_data(chip->client, + AD7746_REG_CAPDACB, + chip->capdac[chan->channel][1]); + if (ret < 0) + goto out; + + chip->capdac_set = chan->channel; + + ret = 0; + break; + default: + ret = -EINVAL; + } + +out: + mutex_unlock(&indio_dev->mlock); + return ret; +} + +static int ad7746_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, + long mask) +{ + struct ad7746_chip_info *chip = iio_priv(indio_dev); + int ret, delay; + u8 regval, reg; + + union { + u32 d32; + u8 d8[4]; + } data; + + mutex_lock(&indio_dev->mlock); + + switch (mask) { + case 0: + ret = ad7746_select_channel(indio_dev, chan); + if (ret < 0) + goto out; + delay = ret; + + regval = chip->config | AD7746_CONF_MODE_SINGLE_CONV; + ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_CFG, + regval); + if (ret < 0) + goto out; + + msleep(delay); + /* Now read the actual register */ + + ret = i2c_smbus_read_i2c_block_data(chip->client, + chan->address >> 8, 3, &data.d8[1]); + + if (ret < 0) + goto out; + + *val = (be32_to_cpu(data.d32) & 0xFFFFFF) - 0x800000; + + switch (chan->type) { + case IIO_TEMP: + /* temperature in milli degrees Celsius + * T = ((*val / 2048) - 4096) * 1000 + */ + *val = (*val * 125) / 256; + break; + case IIO_VOLTAGE: + if (chan->channel == 1) /* supply_raw*/ + *val = *val * 6; + break; + default: + break; + } + + ret = IIO_VAL_INT; + break; + case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + switch (chan->type) { + case IIO_CAPACITANCE: + reg = AD7746_REG_CAP_GAINH; + break; + case IIO_VOLTAGE: + reg = AD7746_REG_VOLT_GAINH; + break; + default: + ret = -EINVAL; + goto out; + } + + ret = i2c_smbus_read_word_data(chip->client, reg); + if (ret < 0) + goto out; + /* 1 + gain_val / 2^16 */ + *val = 1; + *val2 = (15625 * swab16(ret)) / 1024; + + ret = IIO_VAL_INT_PLUS_MICRO; + break; + case (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED): + ret = i2c_smbus_read_word_data(chip->client, + AD7746_REG_CAP_OFFH); + if (ret < 0) + goto out; + *val = swab16(ret); + + ret = IIO_VAL_INT; + break; + case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + *val = AD7746_CAPDAC_DACP(chip->capdac[chan->channel] + [chan->differential]) * 338646; + + ret = IIO_VAL_INT; + break; + case (1 << IIO_CHAN_INFO_SCALE_SHARED): + switch (chan->type) { + case IIO_CAPACITANCE: + /* 8.192pf / 2^24 */ + *val2 = 488; + *val = 0; + break; + case IIO_VOLTAGE: + /* 1170mV / 2^23 */ + *val2 = 139475; + *val = 0; + break; + default: + ret = -EINVAL; + goto out; + } + + ret = IIO_VAL_INT_PLUS_NANO; + break; + default: + ret = -EINVAL; + }; +out: + mutex_unlock(&indio_dev->mlock); + return ret; +} + +static const struct iio_info ad7746_info = { + .attrs = &ad7746_attribute_group, + .read_raw = &ad7746_read_raw, + .write_raw = &ad7746_write_raw, + .driver_module = THIS_MODULE, +}; + +/* + * device probe and remove + */ + +static int __devinit ad7746_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct ad7746_platform_data *pdata = client->dev.platform_data; + struct ad7746_chip_info *chip; + struct iio_dev *indio_dev; + int ret = 0; + unsigned char regval = 0; + + 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; + chip->capdac_set = -1; + + /* Establish that the iio_dev is a child of the i2c device */ + indio_dev->name = id->name; + indio_dev->dev.parent = &client->dev; + indio_dev->info = &ad7746_info; + indio_dev->channels = ad7746_channels; + if (id->driver_data == 7746) + indio_dev->num_channels = ARRAY_SIZE(ad7746_channels); + else + indio_dev->num_channels = ARRAY_SIZE(ad7746_channels) - 2; + indio_dev->num_channels = ARRAY_SIZE(ad7746_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + + if (pdata) { + if (pdata->exca_en) { + if (pdata->exca_inv_en) + regval |= AD7746_EXCSETUP_NEXCA; + else + regval |= AD7746_EXCSETUP_EXCA; + } + + if (pdata->excb_en) { + if (pdata->excb_inv_en) + regval |= AD7746_EXCSETUP_NEXCB; + else + regval |= AD7746_EXCSETUP_EXCB; + } + + regval |= AD7746_EXCSETUP_EXCLVL(pdata->exclvl); + } else { + dev_warn(&client->dev, "No platform data? using default\n"); + regval = AD7746_EXCSETUP_EXCA | AD7746_EXCSETUP_EXCB | + AD7746_EXCSETUP_EXCLVL(3); + } + + ret = i2c_smbus_write_byte_data(chip->client, + AD7746_REG_EXC_SETUP, regval); + if (ret < 0) + goto error_free_dev; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_free_dev; + + 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) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + iio_free_device(indio_dev); + + return 0; +} + +static const struct i2c_device_id ad7746_id[] = { + { "ad7745", 7745 }, + { "ad7746", 7746 }, + { "ad7747", 7747 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, ad7746_id); + +static struct i2c_driver ad7746_driver = { + .driver = { + .name = KBUILD_MODNAME, + }, + .probe = ad7746_probe, + .remove = __devexit_p(ad7746_remove), + .id_table = ad7746_id, +}; + +static __init int ad7746_init(void) +{ + return i2c_add_driver(&ad7746_driver); +} + +static __exit void ad7746_exit(void) +{ + i2c_del_driver(&ad7746_driver); +} + +MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); +MODULE_DESCRIPTION("Analog Devices AD7746/5/7 capacitive sensor driver"); +MODULE_LICENSE("GPL v2"); + +module_init(ad7746_init); +module_exit(ad7746_exit); diff --git a/drivers/staging/iio/cdc/ad7746.h b/drivers/staging/iio/cdc/ad7746.h new file mode 100644 index 0000000..ea8572d --- /dev/null +++ b/drivers/staging/iio/cdc/ad7746.h @@ -0,0 +1,29 @@ +/* + * AD7746 capacitive sensor driver supporting AD7745, AD7746 and AD7747 + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#ifndef IIO_CDC_AD7746_H_ +#define IIO_CDC_AD7746_H_ + +/* + * TODO: struct ad7746_platform_data needs to go into include/linux/iio + */ + +#define AD7466_EXCLVL_0 0 /* +-VDD/8 */ +#define AD7466_EXCLVL_1 1 /* +-VDD/4 */ +#define AD7466_EXCLVL_2 2 /* +-VDD * 3/8 */ +#define AD7466_EXCLVL_3 3 /* +-VDD/2 */ + +struct ad7746_platform_data { + unsigned char exclvl; /*Excitation Voltage Level */ + bool exca_en; /* enables EXCA pin as the excitation output */ + bool exca_inv_en; /* enables /EXCA pin as the excitation output */ + bool excb_en; /* enables EXCB pin as the excitation output */ + bool excb_inv_en; /* enables /EXCB pin as the excitation output */ +}; + +#endif /* IIO_CDC_AD7746_H_ */ diff --git a/drivers/staging/iio/chrdev.h b/drivers/staging/iio/chrdev.h index 3e31ee6..d8e736f 100644 --- a/drivers/staging/iio/chrdev.h +++ b/drivers/staging/iio/chrdev.h @@ -9,26 +9,6 @@ #ifndef _IIO_CHRDEV_H_ #define _IIO_CHRDEV_H_ -struct iio_dev; - -/** - * struct iio_handler - Structure used to specify file operations - * for a particular chrdev - * @chrdev: character device structure - * @id: the location in the handler table - used for deallocation. - * @flags: file operations related flags including busy flag. - * @private: handler specific data used by the fileops registered with - * the chrdev. - */ -struct iio_handler { - struct cdev chrdev; - int id; - unsigned long flags; - void *private; -}; - -#define iio_cdev_to_handler(cd) \ - container_of(cd, struct iio_handler, chrdev) /** * struct iio_event_data - The actual event being pushed to userspace @@ -37,39 +17,9 @@ struct iio_handler { * the interrupt handler) */ struct iio_event_data { - int id; + u64 id; s64 timestamp; }; -/** - * 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 - * @handler: fileoperations and related control for the chrdev - * @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 - */ -struct iio_event_interface { - struct device dev; - struct iio_handler handler; - 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; -}; - +#define IIO_GET_EVENT_FD_IOCTL _IOR('i', 0x90, int) #endif diff --git a/drivers/staging/iio/dac/Kconfig b/drivers/staging/iio/dac/Kconfig index 7ddae35..fac8549 100644 --- a/drivers/staging/iio/dac/Kconfig +++ b/drivers/staging/iio/dac/Kconfig @@ -1,14 +1,35 @@ # # DAC drivers # -comment "Digital to analog convertors" +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 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 convertors (DAC). This driver uses the common SPI interface. + 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" @@ -62,3 +83,5 @@ config MAX517 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 index 7f4f2ed..07b6f5e 100644 --- a/drivers/staging/iio/dac/Makefile +++ b/drivers/staging/iio/dac/Makefile @@ -2,7 +2,9 @@ # Makefile for industrial I/O DAC drivers # +obj-$(CONFIG_AD5360) += ad5360.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_AD5791) += ad5791.o diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c new file mode 100644 index 0000000..24279f2 --- /dev/null +++ b/drivers/staging/iio/dac/ad5064.c @@ -0,0 +1,463 @@ +/* + * 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 = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \ + .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 long scale_uv; + unsigned int vref; + + switch (m) { + case 0: + *val = st->dac_cache[chan->channel]; + return IIO_VAL_INT; + case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + 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, +}; + +static __init int ad5064_spi_init(void) +{ + return spi_register_driver(&ad5064_driver); +} +module_init(ad5064_spi_init); + +static __exit void ad5064_spi_exit(void) +{ + spi_unregister_driver(&ad5064_driver); +} +module_exit(ad5064_spi_exit); + +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 new file mode 100644 index 0000000..72d0f3f --- /dev/null +++ b/drivers/staging/iio/dac/ad5360.c @@ -0,0 +1,581 @@ +/* + * 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 = (1 << IIO_CHAN_INFO_SCALE_SEPARATE) | \ + (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | \ + (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | \ + (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), \ + .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 (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + 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 (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + 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 (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + 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 long scale_uv; + unsigned int ofs_index; + 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 (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + /* 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 (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + ret = ad5360_read(indio_dev, AD5360_READBACK_OFFSET, + chan->address); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + ret = ad5360_read(indio_dev, AD5360_READBACK_GAIN, + chan->address); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + 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, +}; + +static __init int ad5360_spi_init(void) +{ + return spi_register_driver(&ad5360_driver); +} +module_init(ad5360_spi_init); + +static __exit void ad5360_spi_exit(void) +{ + spi_unregister_driver(&ad5360_driver); +} +module_exit(ad5360_spi_exit); + +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/ad5446.c b/drivers/staging/iio/dac/ad5446.c index e8a9d0b..e1c204d 100644 --- a/drivers/staging/iio/dac/ad5446.c +++ b/drivers/staging/iio/dac/ad5446.c @@ -16,6 +16,7 @@ #include <linux/spi/spi.h> #include <linux/regulator/consumer.h> #include <linux/err.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -67,8 +68,8 @@ static ssize_t ad5446_write(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad5446_state *st = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad5446_state *st = iio_priv(indio_dev); int ret; long val; @@ -81,11 +82,11 @@ static ssize_t ad5446_write(struct device *dev, goto error_ret; } - mutex_lock(&dev_info->mlock); + 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(&dev_info->mlock); + mutex_unlock(&indio_dev->mlock); error_ret: return ret ? ret : len; @@ -97,21 +98,21 @@ static ssize_t ad5446_show_scale(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad5446_state *st = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad5446_state *st = iio_priv(indio_dev); /* Corresponds to Vref / 2^(bits) */ unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits; return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); } -static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5446_show_scale, NULL, 0); +static IIO_DEVICE_ATTR(out_voltage_scale, S_IRUGO, ad5446_show_scale, NULL, 0); static ssize_t ad5446_write_powerdown_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad5446_state *st = iio_priv(dev_info); + 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; @@ -128,8 +129,8 @@ static ssize_t ad5446_write_powerdown_mode(struct device *dev, static ssize_t ad5446_read_powerdown_mode(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad5446_state *st = iio_priv(dev_info); + 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"}; @@ -140,8 +141,8 @@ static ssize_t ad5446_read_dac_powerdown(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad5446_state *st = iio_priv(dev_info); + 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); } @@ -150,8 +151,8 @@ static ssize_t ad5446_write_dac_powerdown(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad5446_state *st = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad5446_state *st = iio_priv(indio_dev); unsigned long readin; int ret; @@ -162,7 +163,7 @@ static ssize_t ad5446_write_dac_powerdown(struct device *dev, if (readin > 1) ret = -EINVAL; - mutex_lock(&dev_info->mlock); + mutex_lock(&indio_dev->mlock); st->pwr_down = readin; if (st->pwr_down) @@ -171,28 +172,28 @@ static ssize_t ad5446_write_dac_powerdown(struct device *dev, st->chip_info->store_sample(st, st->cached_val); ret = spi_sync(st->spi, &st->msg); - mutex_unlock(&dev_info->mlock); + mutex_unlock(&indio_dev->mlock); return ret ? ret : len; } -static IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO | S_IWUSR, +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_powerdown_mode_available, +static IIO_CONST_ATTR(out_voltage_powerdown_mode_available, "1kohm_to_gnd 100kohm_to_gnd three_state"); -static IIO_DEVICE_ATTR(out0_powerdown, S_IRUGO | S_IWUSR, +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_out0_raw.dev_attr.attr, - &iio_dev_attr_out_scale.dev_attr.attr, - &iio_dev_attr_out0_powerdown.dev_attr.attr, - &iio_dev_attr_out_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_powerdown_mode_available.dev_attr.attr, + &iio_dev_attr_out_voltage0_raw.dev_attr.attr, + &iio_dev_attr_out_voltage_scale.dev_attr.attr, + &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, }; @@ -200,16 +201,18 @@ static mode_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 *dev_info = dev_get_drvdata(dev); - struct ad5446_state *st = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad5446_state *st = iio_priv(indio_dev); mode_t mode = attr->mode; if (!st->chip_info->store_pwr_down && - (attr == &iio_dev_attr_out0_powerdown.dev_attr.attr || - attr == &iio_dev_attr_out_powerdown_mode.dev_attr.attr || + (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_powerdown_mode_available.dev_attr.attr)) + &iio_const_attr_out_voltage_powerdown_mode_available. + dev_attr.attr)) mode = 0; return mode; @@ -421,13 +424,14 @@ 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); - struct regulator *reg = st->reg; iio_device_unregister(indio_dev); - if (!IS_ERR(reg)) { - regulator_disable(reg); - regulator_put(reg); + if (!IS_ERR(st->reg)) { + regulator_disable(st->reg); + regulator_put(st->reg); } + iio_free_device(indio_dev); + return 0; } diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c index 1915f45..60dd640 100644 --- a/drivers/staging/iio/dac/ad5504.c +++ b/drivers/staging/iio/dac/ad5504.c @@ -7,7 +7,6 @@ */ #include <linux/interrupt.h> -#include <linux/gpio.h> #include <linux/fs.h> #include <linux/device.h> #include <linux/kernel.h> @@ -15,6 +14,7 @@ #include <linux/slab.h> #include <linux/sysfs.h> #include <linux/regulator/consumer.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -168,10 +168,10 @@ static ssize_t ad5504_show_scale(struct device *dev, return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); } -static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5504_show_scale, NULL, 0); +static IIO_DEVICE_ATTR(out_voltage_scale, S_IRUGO, ad5504_show_scale, NULL, 0); #define IIO_DEV_ATTR_OUT_RW_RAW(_num, _show, _store, _addr) \ - IIO_DEVICE_ATTR(out##_num##_raw, \ + IIO_DEVICE_ATTR(out_voltage##_num##_raw, \ S_IRUGO | S_IWUSR, _show, _store, _addr) static IIO_DEV_ATTR_OUT_RW_RAW(0, ad5504_read_dac, @@ -183,17 +183,16 @@ static IIO_DEV_ATTR_OUT_RW_RAW(2, ad5504_read_dac, static IIO_DEV_ATTR_OUT_RW_RAW(3, ad5504_read_dac, ad5504_write_dac, AD5504_ADDR_DAC3); -static IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO | +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_powerdown_mode_available, +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##_num##_powerdown, \ + 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, @@ -204,17 +203,17 @@ static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5504_read_dac_powerdown, ad5504_write_dac_powerdown, 3); static struct attribute *ad5504_attributes[] = { - &iio_dev_attr_out0_raw.dev_attr.attr, - &iio_dev_attr_out1_raw.dev_attr.attr, - &iio_dev_attr_out2_raw.dev_attr.attr, - &iio_dev_attr_out3_raw.dev_attr.attr, - &iio_dev_attr_out0_powerdown.dev_attr.attr, - &iio_dev_attr_out1_powerdown.dev_attr.attr, - &iio_dev_attr_out2_powerdown.dev_attr.attr, - &iio_dev_attr_out3_powerdown.dev_attr.attr, - &iio_dev_attr_out_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_powerdown_mode_available.dev_attr.attr, - &iio_dev_attr_out_scale.dev_attr.attr, + &iio_dev_attr_out_voltage0_raw.dev_attr.attr, + &iio_dev_attr_out_voltage1_raw.dev_attr.attr, + &iio_dev_attr_out_voltage2_raw.dev_attr.attr, + &iio_dev_attr_out_voltage3_raw.dev_attr.attr, + &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, + &iio_dev_attr_out_voltage_scale.dev_attr.attr, NULL, }; @@ -223,11 +222,11 @@ static const struct attribute_group ad5504_attribute_group = { }; static struct attribute *ad5501_attributes[] = { - &iio_dev_attr_out0_raw.dev_attr.attr, - &iio_dev_attr_out0_powerdown.dev_attr.attr, - &iio_dev_attr_out_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_powerdown_mode_available.dev_attr.attr, - &iio_dev_attr_out_scale.dev_attr.attr, + &iio_dev_attr_out_voltage0_raw.dev_attr.attr, + &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, + &iio_dev_attr_out_voltage_scale.dev_attr.attr, NULL, }; @@ -246,12 +245,13 @@ static struct attribute *ad5504_ev_attributes[] = { 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, 0, - IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_TEMP, + iio_push_event(private, + IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), @@ -262,14 +262,12 @@ static irqreturn_t ad5504_event_handler(int irq, void *private) static const struct iio_info ad5504_info = { .attrs = &ad5504_attribute_group, - .num_interrupt_lines = 1, .event_attrs = &ad5504_ev_attribute_group, .driver_module = THIS_MODULE, }; static const struct iio_info ad5501_info = { .attrs = &ad5501_attribute_group, - .num_interrupt_lines = 1, .event_attrs = &ad5504_ev_attribute_group, .driver_module = THIS_MODULE, }; @@ -282,6 +280,11 @@ static int __devinit ad5504_probe(struct spi_device *spi) 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); @@ -291,11 +294,6 @@ static int __devinit ad5504_probe(struct spi_device *spi) voltage_uv = regulator_get_voltage(reg); } - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_disable_reg; - } spi_set_drvdata(spi, indio_dev); st = iio_priv(indio_dev); if (voltage_uv) @@ -315,10 +313,6 @@ static int __devinit ad5504_probe(struct spi_device *spi) indio_dev->info = &ad5504_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - if (spi->irq) { ret = request_threaded_irq(spi->irq, NULL, @@ -327,22 +321,26 @@ static int __devinit ad5504_probe(struct spi_device *spi) spi_get_device_id(st->spi)->name, indio_dev); if (ret) - goto error_unreg_iio_device; + goto error_disable_reg; } + ret = iio_device_register(indio_dev); + if (ret) + goto error_free_irq; + return 0; -error_unreg_iio_device: - iio_device_unregister(indio_dev); -error_free_dev: - iio_free_device(indio_dev); +error_free_irq: + free_irq(spi->irq, indio_dev); error_disable_reg: if (!IS_ERR(reg)) - regulator_disable(st->reg); + regulator_disable(reg); error_put_reg: if (!IS_ERR(reg)) regulator_put(reg); + iio_free_device(indio_dev); +error_ret: return ret; } @@ -350,16 +348,16 @@ 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); - struct regulator *reg = st->reg; - if (spi->irq) - free_irq(spi->irq, indio_dev); iio_device_unregister(indio_dev); + if (spi->irq) + free_irq(spi->irq, indio_dev); - if (!IS_ERR(reg)) { - regulator_disable(reg); - regulator_put(reg); + if (!IS_ERR(st->reg)) { + regulator_disable(st->reg); + regulator_put(st->reg); } + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/staging/iio/dac/ad5624r_spi.c index a5b3776..284d879 100644 --- a/drivers/staging/iio/dac/ad5624r_spi.c +++ b/drivers/staging/iio/dac/ad5624r_spi.c @@ -7,7 +7,6 @@ */ #include <linux/interrupt.h> -#include <linux/gpio.h> #include <linux/fs.h> #include <linux/device.h> #include <linux/kernel.h> @@ -15,6 +14,7 @@ #include <linux/slab.h> #include <linux/sysfs.h> #include <linux/regulator/consumer.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -172,22 +172,22 @@ static ssize_t ad5624r_show_scale(struct device *dev, return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); } -static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5624r_show_scale, NULL, 0); +static IIO_DEVICE_ATTR(out_voltage_scale, S_IRUGO, ad5624r_show_scale, NULL, 0); static IIO_DEV_ATTR_OUT_RAW(0, ad5624r_write_dac, AD5624R_ADDR_DAC0); static IIO_DEV_ATTR_OUT_RAW(1, ad5624r_write_dac, AD5624R_ADDR_DAC1); static IIO_DEV_ATTR_OUT_RAW(2, ad5624r_write_dac, AD5624R_ADDR_DAC2); static IIO_DEV_ATTR_OUT_RAW(3, ad5624r_write_dac, AD5624R_ADDR_DAC3); -static IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO | +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_powerdown_mode_available, +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##_num##_powerdown, \ + 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, @@ -200,17 +200,17 @@ static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5624r_read_dac_powerdown, ad5624r_write_dac_powerdown, 3); static struct attribute *ad5624r_attributes[] = { - &iio_dev_attr_out0_raw.dev_attr.attr, - &iio_dev_attr_out1_raw.dev_attr.attr, - &iio_dev_attr_out2_raw.dev_attr.attr, - &iio_dev_attr_out3_raw.dev_attr.attr, - &iio_dev_attr_out0_powerdown.dev_attr.attr, - &iio_dev_attr_out1_powerdown.dev_attr.attr, - &iio_dev_attr_out2_powerdown.dev_attr.attr, - &iio_dev_attr_out3_powerdown.dev_attr.attr, - &iio_dev_attr_out_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_powerdown_mode_available.dev_attr.attr, - &iio_dev_attr_out_scale.dev_attr.attr, + &iio_dev_attr_out_voltage0_raw.dev_attr.attr, + &iio_dev_attr_out_voltage1_raw.dev_attr.attr, + &iio_dev_attr_out_voltage2_raw.dev_attr.attr, + &iio_dev_attr_out_voltage3_raw.dev_attr.attr, + &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, + &iio_dev_attr_out_voltage_scale.dev_attr.attr, NULL, }; @@ -227,24 +227,23 @@ static int __devinit ad5624r_probe(struct spi_device *spi) { struct ad5624r_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; + goto error_ret; } st = iio_priv(indio_dev); - st->reg = reg; + 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]; @@ -261,25 +260,25 @@ static int __devinit ad5624r_probe(struct spi_device *spi) indio_dev->info = &ad5624r_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - ret = ad5624r_spi_write(spi, AD5624R_CMD_INTERNAL_REFER_SETUP, 0, !!voltage_uv, 16); if (ret) - goto error_free_dev; + goto error_disable_reg; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_disable_reg; return 0; -error_free_dev: - iio_free_device(indio_dev); error_disable_reg: - if (!IS_ERR(reg)) - regulator_disable(reg); + if (!IS_ERR(st->reg)) + regulator_disable(st->reg); error_put_reg: - if (!IS_ERR(reg)) - regulator_put(reg); + if (!IS_ERR(st->reg)) + regulator_put(st->reg); + iio_free_device(indio_dev); +error_ret: return ret; } @@ -288,13 +287,13 @@ 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); - struct regulator *reg = st->reg; iio_device_unregister(indio_dev); - if (!IS_ERR(reg)) { - regulator_disable(reg); - regulator_put(reg); + if (!IS_ERR(st->reg)) { + regulator_disable(st->reg); + regulator_put(st->reg); } + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/dac/ad5686.c b/drivers/staging/iio/dac/ad5686.c index fd67cfa..48389e1 100644 --- a/drivers/staging/iio/dac/ad5686.c +++ b/drivers/staging/iio/dac/ad5686.c @@ -7,9 +7,9 @@ */ #include <linux/interrupt.h> -#include <linux/gpio.h> #include <linux/fs.h> #include <linux/device.h> +#include <linux/module.h> #include <linux/kernel.h> #include <linux/spi/spi.h> #include <linux/slab.h> @@ -25,10 +25,7 @@ #define AD5686_ADDR(x) ((x) << 16) #define AD5686_CMD(x) ((x) << 20) -#define AD5686_ADDR_DAC0 0x1 -#define AD5686_ADDR_DAC1 0x2 -#define AD5686_ADDR_DAC2 0x4 -#define AD5686_ADDR_DAC3 0x8 +#define AD5686_ADDR_DAC(chan) (0x1 << (chan)) #define AD5686_ADDR_ALL_DAC 0xF #define AD5686_CMD_NOOP 0x0 @@ -96,63 +93,35 @@ enum ad5686_supported_device_ids { ID_AD5685, ID_AD5686, }; - +#define AD5868_CHANNEL(chan, bits, shift) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = chan, \ + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \ + .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] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD5686_ADDR_DAC0, - 0, IIO_ST('u', 12, 16, 4), 0), - .channel[1] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD5686_ADDR_DAC1, - 1, IIO_ST('u', 12, 16, 4), 0), - .channel[2] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD5686_ADDR_DAC2, - 2, IIO_ST('u', 12, 16, 4), 0), - .channel[3] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 3, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD5686_ADDR_DAC3, - 3, IIO_ST('u', 12, 16, 4), 0), + .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] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD5686_ADDR_DAC0, - 0, IIO_ST('u', 14, 16, 2), 0), - .channel[1] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD5686_ADDR_DAC1, - 1, IIO_ST('u', 14, 16, 2), 0), - .channel[2] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD5686_ADDR_DAC2, - 2, IIO_ST('u', 14, 16, 2), 0), - .channel[3] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 3, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD5686_ADDR_DAC3, - 3, IIO_ST('u', 14, 16, 2), 0), + .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] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD5686_ADDR_DAC0, - 0, IIO_ST('u', 16, 16, 0), 0), - .channel[1] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD5686_ADDR_DAC1, - 1, IIO_ST('u', 16, 16, 0), 0), - .channel[2] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD5686_ADDR_DAC2, - 2, IIO_ST('u', 16, 16, 0), 0), - .channel[3] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 3, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - AD5686_ADDR_DAC3, - 3, IIO_ST('u', 16, 16, 0), 0), + .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, }, }; @@ -274,11 +243,12 @@ static ssize_t ad5686_write_dac_powerdown(struct device *dev, return ret ? ret : len; } -static IIO_CONST_ATTR(out_powerdown_mode_available, +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##_num##_powerdown_mode, S_IRUGO | S_IWUSR, \ +#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) @@ -287,8 +257,9 @@ 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##_num##_powerdown, S_IRUGO | S_IWUSR, \ +#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) @@ -298,15 +269,15 @@ static IIO_DEV_ATTR_DAC_POWERDOWN(2); static IIO_DEV_ATTR_DAC_POWERDOWN(3); static struct attribute *ad5686_attributes[] = { - &iio_dev_attr_out0_powerdown.dev_attr.attr, - &iio_dev_attr_out1_powerdown.dev_attr.attr, - &iio_dev_attr_out2_powerdown.dev_attr.attr, - &iio_dev_attr_out3_powerdown.dev_attr.attr, - &iio_dev_attr_out0_powerdown_mode.dev_attr.attr, - &iio_dev_attr_out1_powerdown_mode.dev_attr.attr, - &iio_dev_attr_out2_powerdown_mode.dev_attr.attr, - &iio_dev_attr_out3_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_powerdown_mode_available.dev_attr.attr, + &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, }; @@ -356,7 +327,7 @@ static int ad5686_write_raw(struct iio_dev *indio_dev, switch (mask) { case 0: - if (val > (1 << chan->scan_type.realbits)) + if (val > (1 << chan->scan_type.realbits) || val < 0) return -EINVAL; mutex_lock(&indio_dev->mlock); @@ -420,16 +391,16 @@ static int __devinit ad5686_probe(struct spi_device *spi) indio_dev->channels = st->chip_info->channel; indio_dev->num_channels = AD5686_DAC_CHANNELS; - ret = iio_device_register(indio_dev); - if (ret) - goto error_disable_reg; - 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: @@ -439,10 +410,7 @@ error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); return ret; } @@ -451,14 +419,13 @@ 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); - struct regulator *reg = st->reg; - - if (!IS_ERR(reg)) { - regulator_disable(reg); - regulator_put(reg); - } 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; } diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c index 64770d2..6fbca8d 100644 --- a/drivers/staging/iio/dac/ad5791.c +++ b/drivers/staging/iio/dac/ad5791.c @@ -7,7 +7,6 @@ */ #include <linux/interrupt.h> -#include <linux/gpio.h> #include <linux/fs.h> #include <linux/device.h> #include <linux/kernel.h> @@ -15,6 +14,7 @@ #include <linux/slab.h> #include <linux/sysfs.h> #include <linux/regulator/consumer.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -71,48 +71,23 @@ static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val) return ret; } -static ssize_t ad5791_write_dac(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5791_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - long readin; - int ret; - - ret = strict_strtol(buf, 10, &readin); - if (ret) - return ret; - - readin += (1 << (st->chip_info->bits - 1)); - readin &= AD5791_RES_MASK(st->chip_info->bits); - readin <<= st->chip_info->left_shift; - - ret = ad5791_spi_write(st->spi, this_attr->address, readin); - return ret ? ret : len; +#define AD5791_CHAN(bits, shift) { \ + .type = IIO_VOLTAGE, \ + .output = 1, \ + .indexed = 1, \ + .address = AD5791_ADDR_DAC0, \ + .channel = 0, \ + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED) | \ + (1 << IIO_CHAN_INFO_OFFSET_SHARED), \ + .scan_type = IIO_ST('u', bits, 24, shift) \ } -static ssize_t ad5791_read_dac(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5791_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret; - int val; - - ret = ad5791_spi_read(st->spi, this_attr->address, &val); - if (ret) - return ret; - - val &= AD5791_DAC_MASK; - val >>= st->chip_info->left_shift; - val -= (1 << (st->chip_info->bits - 1)); - - return sprintf(buf, "%d\n", val); -} +static 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) @@ -183,58 +158,24 @@ static ssize_t ad5791_write_dac_powerdown(struct device *dev, return ret ? ret : len; } -static ssize_t ad5791_show_scale(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5791_state *st = iio_priv(indio_dev); - /* Corresponds to Vref / 2^(bits) */ - unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits; - - return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); -} -static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5791_show_scale, NULL, 0); - -static ssize_t ad5791_show_name(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5791_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%s\n", spi_get_device_id(st->spi)->name); -} -static IIO_DEVICE_ATTR(name, S_IRUGO, ad5791_show_name, NULL, 0); - -#define IIO_DEV_ATTR_OUT_RW_RAW(_num, _show, _store, _addr) \ - IIO_DEVICE_ATTR(out##_num##_raw, \ - S_IRUGO | S_IWUSR, _show, _store, _addr) - -static IIO_DEV_ATTR_OUT_RW_RAW(0, ad5791_read_dac, - ad5791_write_dac, AD5791_ADDR_DAC0); - -static IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO | +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_powerdown_mode_available, +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##_num##_powerdown, \ + 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_out0_raw.dev_attr.attr, - &iio_dev_attr_out0_powerdown.dev_attr.attr, - &iio_dev_attr_out_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_powerdown_mode_available.dev_attr.attr, - &iio_dev_attr_out_scale.dev_attr.attr, - &iio_dev_attr_name.dev_attr.attr, + &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, }; @@ -263,31 +204,78 @@ static int ad5780_get_lin_comp(unsigned int span) else return AD5780_LINCOMP_10_20; } - static const struct ad5791_chip_info ad5791_chip_info_tbl[] = { [ID_AD5760] = { - .bits = 16, - .left_shift = 4, .get_lin_comp = ad5780_get_lin_comp, }, [ID_AD5780] = { - .bits = 18, - .left_shift = 2, .get_lin_comp = ad5780_get_lin_comp, }, [ID_AD5781] = { - .bits = 18, - .left_shift = 2, .get_lin_comp = ad5791_get_lin_comp, }, [ID_AD5791] = { - .bits = 20, - .left_shift = 0, .get_lin_comp = ad5791_get_lin_comp, }, }; +static 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 (1 << IIO_CHAN_INFO_SCALE_SHARED): + *val = 0; + *val2 = (((u64)st->vref_mv) * 1000000ULL) >> chan->scan_type.realbits; + return IIO_VAL_INT_PLUS_MICRO; + case (1 << IIO_CHAN_INFO_OFFSET_SHARED): + 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, }; @@ -296,50 +284,52 @@ static int __devinit ad5791_probe(struct spi_device *spi) { struct ad5791_platform_data *pdata = spi->dev.platform_data; struct iio_dev *indio_dev; - struct regulator *reg_vdd, *reg_vss; struct ad5791_state *st; int ret, pos_voltage_uv = 0, neg_voltage_uv = 0; - reg_vdd = regulator_get(&spi->dev, "vdd"); - if (!IS_ERR(reg_vdd)) { - ret = regulator_enable(reg_vdd); + 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(reg_vdd); + pos_voltage_uv = regulator_get_voltage(st->reg_vdd); } - reg_vss = regulator_get(&spi->dev, "vss"); - if (!IS_ERR(reg_vss)) { - ret = regulator_enable(reg_vss); + 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(reg_vss); + neg_voltage_uv = regulator_get_voltage(st->reg_vss); } - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_disable_reg_neg; - } - st = iio_priv(indio_dev); st->pwr_down = true; st->spi = spi; - if (!IS_ERR(reg_vss) && !IS_ERR(reg_vdd)) - st->vref_mv = (pos_voltage_uv - neg_voltage_uv) / 1000; - else if (pdata) - st->vref_mv = pdata->vref_pos_mv - pdata->vref_neg_mv; - else + 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_free_dev; + goto error_disable_reg_neg; - st->chip_info = - &ad5791_chip_info_tbl[spi_get_device_id(spi)->driver_data]; + 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)) @@ -349,39 +339,37 @@ static int __devinit ad5791_probe(struct spi_device *spi) ret = ad5791_spi_write(spi, AD5791_ADDR_CTRL, st->ctrl | AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI); if (ret) - goto error_free_dev; - - st->reg_vdd = reg_vdd; - st->reg_vss = reg_vss; + 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_free_dev; + goto error_disable_reg_neg; return 0; -error_free_dev: - iio_free_device(indio_dev); - error_disable_reg_neg: - if (!IS_ERR(reg_vss)) - regulator_disable(reg_vss); + if (!IS_ERR(st->reg_vss)) + regulator_disable(st->reg_vss); error_put_reg_neg: - if (!IS_ERR(reg_vss)) - regulator_put(reg_vss); + if (!IS_ERR(st->reg_vss)) + regulator_put(st->reg_vss); - if (!IS_ERR(reg_vdd)) - regulator_disable(reg_vdd); + if (!IS_ERR(st->reg_vdd)) + regulator_disable(st->reg_vdd); error_put_reg_pos: - if (!IS_ERR(reg_vdd)) - regulator_put(reg_vdd); - + if (!IS_ERR(st->reg_vdd)) + regulator_put(st->reg_vdd); + iio_free_device(indio_dev); error_ret: + return ret; } @@ -389,20 +377,18 @@ 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); - struct regulator *reg_vdd = st->reg_vdd; - struct regulator *reg_vss = st->reg_vss; iio_device_unregister(indio_dev); - if (!IS_ERR(st->reg_vdd)) { - regulator_disable(reg_vdd); - regulator_put(reg_vdd); + regulator_disable(st->reg_vdd); + regulator_put(st->reg_vdd); } if (!IS_ERR(st->reg_vss)) { - regulator_disable(reg_vss); - regulator_put(reg_vss); + regulator_disable(st->reg_vss); + regulator_put(st->reg_vss); } + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/dac/ad5791.h b/drivers/staging/iio/dac/ad5791.h index c807f26..fd7edbd 100644 --- a/drivers/staging/iio/dac/ad5791.h +++ b/drivers/staging/iio/dac/ad5791.h @@ -68,14 +68,10 @@ struct ad5791_platform_data { /** * struct ad5791_chip_info - chip specific information - * @bits: accuracy of the DAC in bits - * @left_shift: number of bits the datum must be shifted * @get_lin_comp: function pointer to the device specific function */ struct ad5791_chip_info { - u8 bits; - u8 left_shift; int (*get_lin_comp) (unsigned int span); }; @@ -86,6 +82,7 @@ struct ad5791_chip_info { * @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 */ @@ -95,6 +92,7 @@ struct ad5791_state { 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; diff --git a/drivers/staging/iio/dac/dac.h b/drivers/staging/iio/dac/dac.h index 1d82f35..0754d71 100644 --- a/drivers/staging/iio/dac/dac.h +++ b/drivers/staging/iio/dac/dac.h @@ -3,4 +3,4 @@ */ #define IIO_DEV_ATTR_OUT_RAW(_num, _store, _addr) \ - IIO_DEVICE_ATTR(out##_num##_raw, S_IWUSR, NULL, _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 index ed5d351..adfbd20 100644 --- a/drivers/staging/iio/dac/max517.c +++ b/drivers/staging/iio/dac/max517.c @@ -26,6 +26,7 @@ #include <linux/err.h> #include "../iio.h" +#include "../sysfs.h" #include "dac.h" #include "max517.h" @@ -58,8 +59,8 @@ static ssize_t max517_set_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count, int channel) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct max517_data *data = iio_priv(dev_info); + 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; @@ -119,15 +120,16 @@ static ssize_t max517_set_value_both(struct device *dev, { return max517_set_value(dev, attr, buf, count, 3); } -static IIO_DEVICE_ATTR_NAMED(out1and2_raw, out1&2_raw, S_IWUSR, NULL, - max517_set_value_both, -1); +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 *dev_info = dev_get_drvdata(dev); - struct max517_data *data = iio_priv(dev_info); + 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; @@ -140,7 +142,8 @@ static ssize_t max517_show_scale1(struct device *dev, { return max517_show_scale(dev, attr, buf, 1); } -static IIO_DEVICE_ATTR(out1_scale, S_IRUGO, max517_show_scale1, NULL, 0); +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, @@ -148,12 +151,13 @@ static ssize_t max517_show_scale2(struct device *dev, { return max517_show_scale(dev, attr, buf, 2); } -static IIO_DEVICE_ATTR(out2_scale, S_IRUGO, max517_show_scale2, NULL, 0); +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_out1_raw.dev_attr.attr, - &iio_dev_attr_out1_scale.dev_attr.attr, + &iio_dev_attr_out_voltage1_raw.dev_attr.attr, + &iio_dev_attr_out_voltage1_scale.dev_attr.attr, NULL }; @@ -163,11 +167,11 @@ static struct attribute_group max517_attribute_group = { /* On MAX518 and MAX519 variant, we have two outputs */ static struct attribute *max518_attributes[] = { - &iio_dev_attr_out1_raw.dev_attr.attr, - &iio_dev_attr_out1_scale.dev_attr.attr, - &iio_dev_attr_out2_raw.dev_attr.attr, - &iio_dev_attr_out2_scale.dev_attr.attr, - &iio_dev_attr_out1and2_raw.dev_attr.attr, + &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 }; diff --git a/drivers/staging/iio/dds/Kconfig b/drivers/staging/iio/dds/Kconfig index e07431d..93b7141 100644 --- a/drivers/staging/iio/dds/Kconfig +++ b/drivers/staging/iio/dds/Kconfig @@ -1,7 +1,7 @@ # # Direct Digital Synthesis drivers # -comment "Direct Digital Synthesis" +menu "Direct Digital Synthesis" config AD5930 tristate "Analog Devices ad5930/5932 driver" @@ -57,3 +57,5 @@ config AD9951 help Say yes here to build support for Analog Devices DDS chip ad9951, provides direct access via sysfs. + +endmenu diff --git a/drivers/staging/iio/dds/ad5930.c b/drivers/staging/iio/dds/ad5930.c index 0b2aa4c..f5e368b 100644 --- a/drivers/staging/iio/dds/ad5930.c +++ b/drivers/staging/iio/dds/ad5930.c @@ -14,6 +14,7 @@ #include <linux/spi/spi.h> #include <linux/slab.h> #include <linux/sysfs.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -129,6 +130,7 @@ error_ret: static int __devexit ad5930_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); + iio_free_device(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/dds/ad9832.c b/drivers/staging/iio/dds/ad9832.c index 6f0efe6..9b4ff60 100644 --- a/drivers/staging/iio/dds/ad9832.c +++ b/drivers/staging/iio/dds/ad9832.c @@ -13,6 +13,7 @@ #include <linux/spi/spi.h> #include <linux/regulator/consumer.h> #include <linux/err.h> +#include <linux/module.h> #include <asm/div64.h> #include "../iio.h" @@ -76,8 +77,8 @@ static ssize_t ad9832_write(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad9832_state *st = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad9832_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; long val; @@ -86,7 +87,7 @@ static ssize_t ad9832_write(struct device *dev, if (ret) goto error_ret; - mutex_lock(&dev_info->mlock); + mutex_lock(&indio_dev->mlock); switch (this_attr->address) { case AD9832_FREQ0HM: case AD9832_FREQ1HM: @@ -147,7 +148,7 @@ static ssize_t ad9832_write(struct device *dev, default: ret = -ENODEV; } - mutex_unlock(&dev_info->mlock); + mutex_unlock(&indio_dev->mlock); error_ret: return ret ? ret : len; @@ -327,13 +328,14 @@ static int __devexit ad9832_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad9832_state *st = iio_priv(indio_dev); - struct regulator *reg = st->reg; iio_device_unregister(indio_dev); - if (!IS_ERR(reg)) { - regulator_disable(reg); - regulator_put(reg); + if (!IS_ERR(st->reg)) { + regulator_disable(st->reg); + regulator_put(st->reg); } + iio_free_device(indio_dev); + return 0; } diff --git a/drivers/staging/iio/dds/ad9834.c b/drivers/staging/iio/dds/ad9834.c index e6454d5..c468f69 100644 --- a/drivers/staging/iio/dds/ad9834.c +++ b/drivers/staging/iio/dds/ad9834.c @@ -16,6 +16,7 @@ #include <linux/spi/spi.h> #include <linux/regulator/consumer.h> #include <linux/err.h> +#include <linux/module.h> #include <asm/div64.h> #include "../iio.h" @@ -65,8 +66,8 @@ static ssize_t ad9834_write(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad9834_state *st = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad9834_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; long val; @@ -75,7 +76,7 @@ static ssize_t ad9834_write(struct device *dev, if (ret) goto error_ret; - mutex_lock(&dev_info->mlock); + mutex_lock(&indio_dev->mlock); switch (this_attr->address) { case AD9834_REG_FREQ0: case AD9834_REG_FREQ1: @@ -133,7 +134,7 @@ static ssize_t ad9834_write(struct device *dev, default: ret = -ENODEV; } - mutex_unlock(&dev_info->mlock); + mutex_unlock(&indio_dev->mlock); error_ret: return ret ? ret : len; @@ -144,13 +145,13 @@ static ssize_t ad9834_store_wavetype(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad9834_state *st = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad9834_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret = 0; bool is_ad9833_7 = (st->devid == ID_AD9833) || (st->devid == ID_AD9837); - mutex_lock(&dev_info->mlock); + mutex_lock(&indio_dev->mlock); switch (this_attr->address) { case 0: @@ -193,7 +194,7 @@ static ssize_t ad9834_store_wavetype(struct device *dev, st->data = cpu_to_be16(AD9834_REG_CMD | st->control); ret = spi_sync(st->spi, &st->msg); } - mutex_unlock(&dev_info->mlock); + mutex_unlock(&indio_dev->mlock); return ret ? ret : len; } @@ -202,8 +203,8 @@ static ssize_t ad9834_show_out0_wavetype_available(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad9834_state *st = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad9834_state *st = iio_priv(indio_dev); char *str; if ((st->devid == ID_AD9833) || (st->devid == ID_AD9837)) @@ -224,8 +225,8 @@ static ssize_t ad9834_show_out1_wavetype_available(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad9834_state *st = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad9834_state *st = iio_priv(indio_dev); char *str; if (st->control & AD9834_MODE) @@ -284,8 +285,8 @@ static mode_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 *dev_info = dev_get_drvdata(dev); - struct ad9834_state *st = iio_priv(dev_info); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad9834_state *st = iio_priv(indio_dev); mode_t mode = attr->mode; @@ -416,13 +417,13 @@ static int __devexit ad9834_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad9834_state *st = iio_priv(indio_dev); - struct regulator *reg = st->reg; iio_device_unregister(indio_dev); - if (!IS_ERR(reg)) { - regulator_disable(reg); - regulator_put(reg); + if (!IS_ERR(st->reg)) { + regulator_disable(st->reg); + regulator_put(st->reg); } + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/dds/ad9850.c b/drivers/staging/iio/dds/ad9850.c index d7c9d05..a14771b 100644 --- a/drivers/staging/iio/dds/ad9850.c +++ b/drivers/staging/iio/dds/ad9850.c @@ -14,6 +14,7 @@ #include <linux/spi/spi.h> #include <linux/slab.h> #include <linux/sysfs.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -115,6 +116,7 @@ error_ret: static int __devexit ad9850_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); + iio_free_device(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/dds/ad9852.c b/drivers/staging/iio/dds/ad9852.c index 0184585..cfceaa6 100644 --- a/drivers/staging/iio/dds/ad9852.c +++ b/drivers/staging/iio/dds/ad9852.c @@ -14,6 +14,7 @@ #include <linux/spi/spi.h> #include <linux/slab.h> #include <linux/sysfs.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -217,7 +218,6 @@ static struct attribute *ad9852_attributes[] = { }; static const struct attribute_group ad9852_attribute_group = { - .name = DRV_NAME, .attrs = ad9852_attributes, }; @@ -267,6 +267,7 @@ error_ret: static int __devexit ad9852_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); + iio_free_device(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/dds/ad9910.c b/drivers/staging/iio/dds/ad9910.c index 0fa217f..da83d2b 100644 --- a/drivers/staging/iio/dds/ad9910.c +++ b/drivers/staging/iio/dds/ad9910.c @@ -14,6 +14,7 @@ #include <linux/spi/spi.h> #include <linux/slab.h> #include <linux/sysfs.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -352,7 +353,6 @@ static struct attribute *ad9910_attributes[] = { }; static const struct attribute_group ad9910_attribute_group = { - .name = DRV_NAME, .attrs = ad9910_attributes, }; @@ -400,6 +400,7 @@ error_ret: static int __devexit ad9910_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); + iio_free_device(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/dds/ad9951.c b/drivers/staging/iio/dds/ad9951.c index d361d1f..20c1825 100644 --- a/drivers/staging/iio/dds/ad9951.c +++ b/drivers/staging/iio/dds/ad9951.c @@ -14,6 +14,7 @@ #include <linux/spi/spi.h> #include <linux/slab.h> #include <linux/sysfs.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -161,7 +162,6 @@ static struct attribute *ad9951_attributes[] = { }; static const struct attribute_group ad9951_attribute_group = { - .name = DRV_NAME, .attrs = ad9951_attributes, }; @@ -211,6 +211,7 @@ error_ret: static int __devexit ad9951_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); + iio_free_device(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/gyro/Kconfig b/drivers/staging/iio/gyro/Kconfig index ae2e7d3..22aea5b 100644 --- a/drivers/staging/iio/gyro/Kconfig +++ b/drivers/staging/iio/gyro/Kconfig @@ -1,7 +1,7 @@ # # IIO Digital Gyroscope Sensor drivers configuration # -comment "Digital gyroscope sensors" +menu "Digital gyroscope sensors" config ADIS16060 tristate "Analog Devices ADIS16060 Yaw Rate Gyroscope with SPI driver" @@ -27,8 +27,8 @@ config ADIS16130 config ADIS16260 tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver" depends on SPI - select IIO_TRIGGER if IIO_RING_BUFFER - select IIO_SW_RING if IIO_RING_BUFFER + 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. @@ -45,3 +45,5 @@ config ADXRS450 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 2212240..9ba5ec1 100644 --- a/drivers/staging/iio/gyro/Makefile +++ b/drivers/staging/iio/gyro/Makefile @@ -12,7 +12,7 @@ adis16130-y := adis16130_core.o obj-$(CONFIG_ADIS16130) += adis16130.o adis16260-y := adis16260_core.o -adis16260-$(CONFIG_IIO_RING_BUFFER) += adis16260_ring.o adis16260_trigger.o +adis16260-$(CONFIG_IIO_BUFFER) += adis16260_ring.o adis16260_trigger.o obj-$(CONFIG_ADIS16260) += adis16260.o adis16251-y := adis16251_core.o diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c index afa52d1..38cf3f4 100644 --- a/drivers/staging/iio/gyro/adis16060_core.c +++ b/drivers/staging/iio/gyro/adis16060_core.c @@ -13,12 +13,10 @@ #include <linux/spi/spi.h> #include <linux/slab.h> #include <linux/sysfs.h> - +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "gyro.h" -#include "../adc/adc.h" #define ADIS16060_GYRO 0x20 /* Measure Angular Rate (Gyro) */ #define ADIS16060_TEMP_OUT 0x10 /* Measure Temperature */ @@ -42,11 +40,9 @@ struct adis16060_state { static struct iio_dev *adis16060_iio_dev; -static int adis16060_spi_write(struct device *dev, - u8 val) +static int adis16060_spi_write(struct iio_dev *indio_dev, u8 val) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adis16060_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -57,11 +53,9 @@ static int adis16060_spi_write(struct device *dev, return ret; } -static int adis16060_spi_read(struct device *dev, - u16 *val) +static int adis16060_spi_read(struct iio_dev *indio_dev, u16 *val) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adis16060_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -82,63 +76,74 @@ static int adis16060_spi_read(struct device *dev, return ret; } -static ssize_t adis16060_read(struct device *dev, - struct device_attribute *attr, - char *buf) +static int adis16060_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, + long mask) { - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - u16 val = 0; - ssize_t ret; - - /* Take the iio_dev status lock */ - mutex_lock(&indio_dev->mlock); + u16 tval = 0; + int ret; - ret = adis16060_spi_write(dev, this_attr->address); - if (ret < 0) - goto error_ret; - ret = adis16060_spi_read(dev, &val); -error_ret: - mutex_unlock(&indio_dev->mlock); + switch (mask) { + case 0: + /* Take the iio_dev status lock */ + mutex_lock(&indio_dev->mlock); + ret = adis16060_spi_write(indio_dev, chan->address); + if (ret < 0) { + mutex_unlock(&indio_dev->mlock); + return ret; + } + ret = adis16060_spi_read(indio_dev, &tval); + mutex_unlock(&indio_dev->mlock); + *val = tval; + return IIO_VAL_INT; + case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + *val = -7; + *val2 = 461117; + return IIO_VAL_INT_PLUS_MICRO; + case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + *val = 0; + *val2 = 34000; + return IIO_VAL_INT_PLUS_MICRO; + } - if (ret == 0) - return sprintf(buf, "%d\n", val); - else - return ret; + return -EINVAL; } -static IIO_DEV_ATTR_GYRO_Z(adis16060_read, ADIS16060_GYRO); -static IIO_DEVICE_ATTR(temp_raw, S_IRUGO, adis16060_read, NULL, - ADIS16060_TEMP_OUT); -static IIO_CONST_ATTR_TEMP_SCALE("34"); /* Milli degrees C */ -static IIO_CONST_ATTR_TEMP_OFFSET("-7461.117"); /* Milli degrees C */ -static IIO_DEV_ATTR_IN_RAW(0, adis16060_read, ADIS16060_AIN1); -static IIO_DEV_ATTR_IN_RAW(1, adis16060_read, ADIS16060_AIN2); -static IIO_CONST_ATTR(name, "adis16060"); - -static struct attribute *adis16060_attributes[] = { - &iio_dev_attr_gyro_z_raw.dev_attr.attr, - &iio_dev_attr_temp_raw.dev_attr.attr, - &iio_const_attr_temp_scale.dev_attr.attr, - &iio_const_attr_temp_offset.dev_attr.attr, - &iio_dev_attr_in0_raw.dev_attr.attr, - &iio_dev_attr_in1_raw.dev_attr.attr, - &iio_const_attr_name.dev_attr.attr, - NULL -}; - -static const struct attribute_group adis16060_attribute_group = { - .attrs = adis16060_attributes, -}; - static const struct iio_info adis16060_info = { - .attrs = &adis16060_attribute_group, + .read_raw = &adis16060_read_raw, .driver_module = THIS_MODULE, }; +static const struct iio_chan_spec adis16060_channels[] = { + { + .type = IIO_ANGL_VEL, + .modified = 1, + .channel2 = IIO_MOD_Z, + .address = ADIS16060_GYRO, + }, { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .address = ADIS16060_AIN1, + }, { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 1, + .address = ADIS16060_AIN2, + }, { + .type = IIO_TEMP, + .indexed = 1, + .channel = 0, + .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .address = ADIS16060_TEMP_OUT, + } +}; + static int __devinit adis16060_r_probe(struct spi_device *spi) { - int ret, regdone = 0; + int ret; struct adis16060_state *st; struct iio_dev *indio_dev; @@ -154,23 +159,22 @@ static int __devinit adis16060_r_probe(struct spi_device *spi) st->us_r = spi; mutex_init(&st->buf_lock); + indio_dev->name = spi->dev.driver->name; indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16060_info; indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = adis16060_channels; + indio_dev->num_channels = ARRAY_SIZE(adis16060_channels); ret = iio_device_register(indio_dev); if (ret) goto error_free_dev; - regdone = 1; adis16060_iio_dev = indio_dev; return 0; error_free_dev: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ret; } @@ -179,6 +183,7 @@ error_ret: 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; } diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c index ad2db4d..5d7a906 100644 --- a/drivers/staging/iio/gyro/adis16080_core.c +++ b/drivers/staging/iio/gyro/adis16080_core.c @@ -5,7 +5,6 @@ * * Licensed under the GPL-2 or later. */ -#include <linux/gpio.h> #include <linux/delay.h> #include <linux/mutex.h> #include <linux/device.h> @@ -13,11 +12,10 @@ #include <linux/spi/spi.h> #include <linux/slab.h> #include <linux/sysfs.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "gyro.h" -#include "../adc/adc.h" #define ADIS16080_DIN_GYRO (0 << 10) /* Gyroscope output */ #define ADIS16080_DIN_TEMP (1 << 10) /* Temperature output */ @@ -44,11 +42,10 @@ struct adis16080_state { u8 buf[2] ____cacheline_aligned; }; -static int adis16080_spi_write(struct device *dev, +static int adis16080_spi_write(struct iio_dev *indio_dev, u16 val) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adis16080_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -61,11 +58,10 @@ static int adis16080_spi_write(struct device *dev, return ret; } -static int adis16080_spi_read(struct device *dev, - u16 *val) +static int adis16080_spi_read(struct iio_dev *indio_dev, + u16 *val) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adis16080_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -79,56 +75,68 @@ static int adis16080_spi_read(struct device *dev, return ret; } -static ssize_t adis16080_read(struct device *dev, - struct device_attribute *attr, - char *buf) +static int adis16080_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) { - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - u16 val = 0; - ssize_t ret; - + int ret = -EINVAL; + u16 ut; /* Take the iio_dev status lock */ + mutex_lock(&indio_dev->mlock); - ret = adis16080_spi_write(dev, - this_attr->address | ADIS16080_DIN_WRITE); - if (ret < 0) - goto error_ret; - ret = adis16080_spi_read(dev, &val); -error_ret: + switch (mask) { + case 0: + ret = adis16080_spi_write(indio_dev, + chan->address | + ADIS16080_DIN_WRITE); + if (ret < 0) + break; + ret = adis16080_spi_read(indio_dev, &ut); + if (ret < 0) + break; + *val = ut; + ret = IIO_VAL_INT; + break; + } mutex_unlock(&indio_dev->mlock); - if (ret == 0) - return sprintf(buf, "%d\n", val); - else - return ret; + return ret; } -static IIO_DEV_ATTR_GYRO_Z(adis16080_read, ADIS16080_DIN_GYRO); -static IIO_DEVICE_ATTR(temp_raw, S_IRUGO, adis16080_read, NULL, - ADIS16080_DIN_TEMP); -static IIO_DEV_ATTR_IN_RAW(0, adis16080_read, ADIS16080_DIN_AIN1); -static IIO_DEV_ATTR_IN_RAW(1, adis16080_read, ADIS16080_DIN_AIN2); - -static struct attribute *adis16080_attributes[] = { - &iio_dev_attr_gyro_z_raw.dev_attr.attr, - &iio_dev_attr_temp_raw.dev_attr.attr, - &iio_dev_attr_in0_raw.dev_attr.attr, - &iio_dev_attr_in1_raw.dev_attr.attr, - NULL -}; -static const struct attribute_group adis16080_attribute_group = { - .attrs = adis16080_attributes, +static const struct iio_chan_spec adis16080_channels[] = { + { + .type = IIO_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 = { - .attrs = &adis16080_attribute_group, + .read_raw = &adis16080_read_raw, .driver_module = THIS_MODULE, }; static int __devinit adis16080_probe(struct spi_device *spi) { - int ret, regdone = 0; + int ret; struct adis16080_state *st; struct iio_dev *indio_dev; @@ -147,6 +155,8 @@ static int __devinit adis16080_probe(struct spi_device *spi) mutex_init(&st->buf_lock); indio_dev->name = spi->dev.driver->name; + indio_dev->channels = adis16080_channels; + indio_dev->num_channels = ARRAY_SIZE(adis16080_channels); indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16080_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -154,15 +164,10 @@ static int __devinit adis16080_probe(struct spi_device *spi) ret = iio_device_register(indio_dev); if (ret) goto error_free_dev; - regdone = 1; - return 0; error_free_dev: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ret; } @@ -171,6 +176,7 @@ error_ret: static int adis16080_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); + iio_free_device(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/gyro/adis16130_core.c b/drivers/staging/iio/gyro/adis16130_core.c index c80e908..749240d 100644 --- a/drivers/staging/iio/gyro/adis16130_core.c +++ b/drivers/staging/iio/gyro/adis16130_core.c @@ -14,11 +14,10 @@ #include <linux/slab.h> #include <linux/sysfs.h> #include <linux/list.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "gyro.h" -#include "../adc/adc.h" #define ADIS16130_CON 0x0 #define ADIS16130_CON_RD (1 << 6) @@ -41,140 +40,77 @@ /** * struct adis16130_state - device instance specific data * @us: actual spi_device to write data - * @mode: 24 bits (1) or 16 bits (0) * @buf_lock: mutex to protect tx and rx * @buf: unified tx/rx buffer **/ struct adis16130_state { struct spi_device *us; - u32 mode; struct mutex buf_lock; u8 buf[4] ____cacheline_aligned; }; -static int adis16130_spi_write(struct device *dev, u8 reg_addr, - u8 val) +static int adis16130_spi_read(struct iio_dev *indio_dev, u8 reg_addr, u32 *val) { int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16130_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - st->buf[0] = reg_addr; - st->buf[1] = val; - - ret = spi_write(st->us, st->buf, 2); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int adis16130_spi_read(struct device *dev, u8 reg_addr, - u32 *val) -{ - int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adis16130_state *st = iio_priv(indio_dev); + struct spi_message msg; + struct spi_transfer xfer = { + .tx_buf = st->buf, + .rx_buf = st->buf, + .len = 4, + }; mutex_lock(&st->buf_lock); st->buf[0] = ADIS16130_CON_RD | reg_addr; - if (st->mode) - ret = spi_read(st->us, st->buf, 4); - else - ret = spi_read(st->us, st->buf, 3); - - if (ret == 0) { - if (st->mode) - *val = (st->buf[1] << 16) | - (st->buf[2] << 8) | - st->buf[3]; - else - *val = (st->buf[1] << 8) | st->buf[2]; - } + st->buf[1] = st->buf[2] = st->buf[3] = 0; + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->us, &msg); + ret = spi_read(st->us, st->buf, 4); + + if (ret == 0) + *val = (st->buf[1] << 16) | (st->buf[2] << 8) | st->buf[3]; mutex_unlock(&st->buf_lock); return ret; } -static ssize_t adis16130_val_read(struct device *dev, - struct device_attribute *attr, - char *buf) +static int adis16130_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, + long mask) { - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - u32 val; - ssize_t ret; + int ret; + u32 temp; /* Take the iio_dev status lock */ mutex_lock(&indio_dev->mlock); - ret = adis16130_spi_read(dev, this_attr->address, &val); + ret = adis16130_spi_read(indio_dev, chan->address, &temp); mutex_unlock(&indio_dev->mlock); - - if (ret == 0) - return sprintf(buf, "%d\n", val); - else + if (ret) return ret; + *val = temp; + return IIO_VAL_INT; } -static ssize_t adis16130_bitsmode_read(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16130_state *st = iio_priv(indio_dev); - - if (st->mode == 1) - return sprintf(buf, "s24\n"); - else - return sprintf(buf, "s16\n"); -} - -static ssize_t adis16130_bitsmode_write(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - int ret; - u8 val; - - if (sysfs_streq(buf, "s16")) - val = 0; - else if (sysfs_streq(buf, "s24")) - val = 1; - else - return -EINVAL; - - ret = adis16130_spi_write(dev, ADIS16130_MODE, val); - - return ret ? ret : len; -} -static IIO_DEVICE_ATTR(temp_raw, S_IRUGO, adis16130_val_read, NULL, - ADIS16130_TEMPDATA); - -static IIO_DEV_ATTR_GYRO_Z(adis16130_val_read, ADIS16130_RATEDATA); - -static IIO_DEVICE_ATTR(gyro_z_type, S_IWUSR | S_IRUGO, adis16130_bitsmode_read, - adis16130_bitsmode_write, - ADIS16130_MODE); - -static IIO_CONST_ATTR(gyro_z_type_available, "s16 s24"); - -static struct attribute *adis16130_attributes[] = { - &iio_dev_attr_temp_raw.dev_attr.attr, - &iio_dev_attr_gyro_z_raw.dev_attr.attr, - &iio_dev_attr_gyro_z_type.dev_attr.attr, - &iio_const_attr_gyro_z_type_available.dev_attr.attr, - NULL -}; - -static const struct attribute_group adis16130_attribute_group = { - .attrs = adis16130_attributes, +static const struct iio_chan_spec adis16130_channels[] = { + { + .type = IIO_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 = { - .attrs = &adis16130_attribute_group, + .read_raw = &adis16130_read_raw, .driver_module = THIS_MODULE, }; @@ -196,10 +132,11 @@ static int __devinit adis16130_probe(struct spi_device *spi) st->us = spi; mutex_init(&st->buf_lock); indio_dev->name = spi->dev.driver->name; + indio_dev->channels = adis16130_channels; + indio_dev->num_channels = ARRAY_SIZE(adis16130_channels); indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16130_info; indio_dev->modes = INDIO_DIRECT_MODE; - st->mode = 1; ret = iio_device_register(indio_dev); if (ret) @@ -218,6 +155,7 @@ error_ret: static int adis16130_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); + iio_free_device(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/gyro/adis16260.h b/drivers/staging/iio/gyro/adis16260.h index 969b624..4c4b251 100644 --- a/drivers/staging/iio/gyro/adis16260.h +++ b/drivers/staging/iio/gyro/adis16260.h @@ -112,7 +112,7 @@ int adis16260_set_irq(struct iio_dev *indio_dev, bool enable); #define ADIS16260_SCAN_TEMP 3 #define ADIS16260_SCAN_ANGL 4 -#ifdef CONFIG_IIO_RING_BUFFER +#ifdef CONFIG_IIO_BUFFER void adis16260_remove_trigger(struct iio_dev *indio_dev); int adis16260_probe_trigger(struct iio_dev *indio_dev); @@ -124,7 +124,7 @@ ssize_t adis16260_read_data_from_ring(struct device *dev, int adis16260_configure_ring(struct iio_dev *indio_dev); void adis16260_unconfigure_ring(struct iio_dev *indio_dev); -#else /* CONFIG_IIO_RING_BUFFER */ +#else /* CONFIG_IIO_BUFFER */ static inline void adis16260_remove_trigger(struct iio_dev *indio_dev) { @@ -152,5 +152,5 @@ static inline void adis16260_unconfigure_ring(struct iio_dev *indio_dev) { } -#endif /* CONFIG_IIO_RING_BUFFER */ +#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 index f2d43cf..aaa3967 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -8,7 +8,6 @@ #include <linux/interrupt.h> #include <linux/irq.h> -#include <linux/gpio.h> #include <linux/delay.h> #include <linux/mutex.h> #include <linux/device.h> @@ -17,12 +16,11 @@ #include <linux/slab.h> #include <linux/sysfs.h> #include <linux/list.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" -#include "../adc/adc.h" -#include "gyro.h" +#include "../buffer_generic.h" #include "adis16260.h" @@ -391,7 +389,7 @@ enum adis16260_channel { }; #define ADIS16260_GYRO_CHANNEL_SET(axis, mod) \ struct iio_chan_spec adis16260_channels_##axis[] = { \ - IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, mod, \ + IIO_CHAN(IIO_ANGL_VEL, 1, 0, 0, NULL, 0, mod, \ (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | \ (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | \ (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \ @@ -406,11 +404,11 @@ enum adis16260_channel { (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \ temp, ADIS16260_SCAN_TEMP, \ IIO_ST('u', 12, 16, 0), 0), \ - IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0, \ + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0, \ (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \ in_supply, ADIS16260_SCAN_SUPPLY, \ IIO_ST('u', 12, 16, 0), 0), \ - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, \ + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, \ (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \ in_aux, ADIS16260_SCAN_AUX_ADC, \ IIO_ST('u', 12, 16, 0), 0), \ @@ -469,14 +467,14 @@ static int adis16260_read_raw(struct iio_dev *indio_dev, case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): case (1 << IIO_CHAN_INFO_SCALE_SHARED): switch (chan->type) { - case IIO_GYRO: + 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_IN: + case IIO_VOLTAGE: *val = 0; if (chan->channel == 0) *val2 = 18315; @@ -496,7 +494,7 @@ static int adis16260_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): switch (chan->type) { - case IIO_GYRO: + case IIO_ANGL_VEL: bits = 12; break; default: @@ -516,7 +514,7 @@ static int adis16260_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): switch (chan->type) { - case IIO_GYRO: + case IIO_ANGL_VEL: bits = 12; break; default: @@ -578,7 +576,7 @@ static const struct iio_info adis16260_info = { static int __devinit adis16260_probe(struct spi_device *spi) { - int ret, regdone = 0; + int ret; struct adis16260_platform_data *pd = spi->dev.platform_data; struct adis16260_state *st; struct iio_dev *indio_dev; @@ -626,18 +624,21 @@ static int __devinit adis16260_probe(struct spi_device *spi) if (ret) goto error_free_dev; - ret = iio_device_register(indio_dev); - if (ret) - goto error_unreg_ring_funcs; - regdone = 1; - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - indio_dev->channels, - ARRAY_SIZE(adis16260_channels_x)); + 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->buffer, ADIS16260_SCAN_SUPPLY); + iio_scan_mask_set(indio_dev->buffer, ADIS16260_SCAN_GYRO); + iio_scan_mask_set(indio_dev->buffer, ADIS16260_SCAN_AUX_ADC); + iio_scan_mask_set(indio_dev->buffer, ADIS16260_SCAN_TEMP); + iio_scan_mask_set(indio_dev->buffer, ADIS16260_SCAN_ANGL); + } if (spi->irq) { ret = adis16260_probe_trigger(indio_dev); if (ret) @@ -648,19 +649,20 @@ static int __devinit adis16260_probe(struct spi_device *spi) 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_ring_buffer_unregister(indio_dev->ring); + iio_buffer_unregister(indio_dev); error_unreg_ring_funcs: adis16260_unconfigure_ring(indio_dev); error_free_dev: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ret; } @@ -670,6 +672,8 @@ 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; @@ -677,9 +681,9 @@ static int adis16260_remove(struct spi_device *spi) flush_scheduled_work(); adis16260_remove_trigger(indio_dev); - iio_ring_buffer_unregister(indio_dev->ring); - iio_device_unregister(indio_dev); + iio_buffer_unregister(indio_dev); adis16260_unconfigure_ring(indio_dev); + iio_free_device(indio_dev); err_ret: return ret; diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c index a4df8b3..679c151 100644 --- a/drivers/staging/iio/gyro/adis16260_ring.c +++ b/drivers/staging/iio/gyro/adis16260_ring.c @@ -1,20 +1,12 @@ #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/workqueue.h> #include <linux/mutex.h> -#include <linux/device.h> #include <linux/kernel.h> #include <linux/spi/spi.h> #include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/list.h> #include "../iio.h" -#include "../sysfs.h" #include "../ring_sw.h" -#include "../accel/accel.h" -#include "../trigger.h" +#include "../trigger_consumer.h" #include "adis16260.h" /** @@ -68,9 +60,9 @@ static int adis16260_read_ring_data(struct device *dev, u8 *rx) static irqreturn_t adis16260_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->private_data; + struct iio_dev *indio_dev = pf->indio_dev; struct adis16260_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; int i = 0; s16 *data; size_t datasize = ring->access->get_bytes_per_datum(ring); @@ -101,26 +93,26 @@ static irqreturn_t adis16260_trigger_handler(int irq, void *p) void adis16260_unconfigure_ring(struct iio_dev *indio_dev) { iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); } -static const struct iio_ring_setup_ops adis16260_ring_setup_ops = { - .preenable = &iio_sw_ring_preenable, - .postenable = &iio_triggered_ring_postenable, - .predisable = &iio_triggered_ring_predisable, +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_ring_buffer *ring; + struct iio_buffer *ring; ring = iio_sw_rb_allocate(indio_dev); if (!ring) { ret = -ENOMEM; return ret; } - indio_dev->ring = ring; + indio_dev->buffer = ring; /* Effectively select the ring buffer implementation */ ring->access = &ring_sw_access_funcs; ring->bpe = 2; @@ -128,13 +120,6 @@ int adis16260_configure_ring(struct iio_dev *indio_dev) ring->setup_ops = &adis16260_ring_setup_ops; ring->owner = THIS_MODULE; - /* Set default scan mode */ - iio_scan_mask_set(ring, ADIS16260_SCAN_SUPPLY); - iio_scan_mask_set(ring, ADIS16260_SCAN_GYRO); - iio_scan_mask_set(ring, ADIS16260_SCAN_AUX_ADC); - iio_scan_mask_set(ring, ADIS16260_SCAN_TEMP); - iio_scan_mask_set(ring, ADIS16260_SCAN_ANGL); - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &adis16260_trigger_handler, IRQF_ONESHOT, @@ -146,10 +131,10 @@ int adis16260_configure_ring(struct iio_dev *indio_dev) goto error_iio_sw_rb_free; } - indio_dev->modes |= INDIO_RING_TRIGGERED; + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; return 0; error_iio_sw_rb_free: - iio_sw_rb_free(indio_dev->ring); + 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 index 01094d0..2f2b216 100644 --- a/drivers/staging/iio/gyro/adis16260_trigger.c +++ b/drivers/staging/iio/gyro/adis16260_trigger.c @@ -1,14 +1,8 @@ #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/mutex.h> -#include <linux/device.h> #include <linux/kernel.h> -#include <linux/sysfs.h> -#include <linux/list.h> #include <linux/spi/spi.h> #include "../iio.h" -#include "../sysfs.h" #include "../trigger.h" #include "adis16260.h" @@ -24,6 +18,11 @@ static int adis16260_data_rdy_trigger_set_state(struct iio_trigger *trig, return adis16260_set_irq(indio_dev, state); } +static const struct iio_trigger_ops adis16260_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = &adis16260_data_rdy_trigger_set_state, +}; + int adis16260_probe_trigger(struct iio_dev *indio_dev) { int ret; @@ -46,9 +45,8 @@ int adis16260_probe_trigger(struct iio_dev *indio_dev) goto error_free_trig; st->trig->dev.parent = &st->us->dev; - st->trig->owner = THIS_MODULE; + st->trig->ops = &adis16260_trigger_ops; st->trig->private_data = indio_dev; - st->trig->set_trigger_state = &adis16260_data_rdy_trigger_set_state; ret = iio_trigger_register(st->trig); /* select default trigger */ diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c index 7502a26..3c3ef79 100644 --- a/drivers/staging/iio/gyro/adxrs450_core.c +++ b/drivers/staging/iio/gyro/adxrs450_core.c @@ -8,7 +8,6 @@ #include <linux/interrupt.h> #include <linux/irq.h> -#include <linux/gpio.h> #include <linux/delay.h> #include <linux/mutex.h> #include <linux/device.h> @@ -17,11 +16,10 @@ #include <linux/slab.h> #include <linux/sysfs.h> #include <linux/list.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "gyro.h" -#include "../adc/adc.h" #include "adxrs450.h" @@ -32,26 +30,12 @@ * Second register's address is reg_address + 1. * @val: somewhere to pass back the value read **/ -static int adxrs450_spi_read_reg_16(struct device *dev, - u8 reg_address, - u16 *val) +static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, + u8 reg_address, + u16 *val) { - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adxrs450_state *st = iio_priv(indio_dev); int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 4, - .cs_change = 1, - }, { - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 4, - }, - }; mutex_lock(&st->buf_lock); st->tx[0] = ADXRS450_READ_DATA | (reg_address >> 7); @@ -62,10 +46,13 @@ static int adxrs450_spi_read_reg_16(struct device *dev, if (!(hweight32(be32_to_cpu(*(u32 *)st->tx)) & 1)) st->tx[3] |= ADXRS450_P; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_write(st->us, st->tx, 4); + if (ret) { + dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n", + reg_address); + goto error_ret; + } + ret = spi_read(st->us, st->rx, 4); if (ret) { dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n", reg_address); @@ -86,20 +73,12 @@ error_ret: * Second register's address is reg_address + 1. * @val: value to be written. **/ -static int adxrs450_spi_write_reg_16(struct device *dev, - u8 reg_address, - u16 val) +static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev, + u8 reg_address, + u16 val) { - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adxrs450_state *st = iio_priv(indio_dev); int ret; - struct spi_transfer xfers = { - .tx_buf = st->tx, - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 4, - }; mutex_lock(&st->buf_lock); st->tx[0] = ADXRS450_WRITE_DATA | reg_address >> 7; @@ -108,14 +87,12 @@ static int adxrs450_spi_write_reg_16(struct device *dev, st->tx[3] = val << 1; if (!(hweight32(be32_to_cpu(*(u32 *)st->tx)) & 1)) - st->tx[3] |= ADXRS450_P; + st->tx[3] |= ADXRS450_P; - spi_message_init(&msg); - spi_message_add_tail(&xfers, &msg); - ret = spi_sync(st->us, &msg); + ret = spi_write(st->us, st->tx, 4); if (ret) dev_err(&st->us->dev, "problem while writing 16 bit register 0x%02x\n", - reg_address); + reg_address); msleep(1); /* enforce sequential transfer delay 0.1ms */ mutex_unlock(&st->buf_lock); return ret; @@ -126,24 +103,10 @@ static int adxrs450_spi_write_reg_16(struct device *dev, * @dev: device associated with child of actual iio_dev * @val: somewhere to pass back the value read **/ -static int adxrs450_spi_sensor_data(struct device *dev, s16 *val) +static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) { - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adxrs450_state *st = iio_priv(indio_dev); int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 4, - .cs_change = 1, - }, { - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 4, - }, - }; mutex_lock(&st->buf_lock); st->tx[0] = ADXRS450_SENSOR_DATA; @@ -151,10 +114,13 @@ static int adxrs450_spi_sensor_data(struct device *dev, s16 *val) st->tx[2] = 0; st->tx[3] = 0; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_write(st->us, st->tx, 4); + if (ret) { + dev_err(&st->us->dev, "Problem while reading sensor data\n"); + goto error_ret; + } + + ret = spi_read(st->us, st->rx, 4); if (ret) { dev_err(&st->us->dev, "Problem while reading sensor data\n"); goto error_ret; @@ -206,73 +172,12 @@ error_ret: return ret; } -static ssize_t adxrs450_read_temp(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u16 t; - ret = adxrs450_spi_read_reg_16(dev, - ADXRS450_TEMP1, - &t); - if (ret) - return ret; - return sprintf(buf, "%d\n", t >> 7); -} - -static ssize_t adxrs450_read_quad(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - s16 t; - ret = adxrs450_spi_read_reg_16(dev, - ADXRS450_QUAD1, - &t); - if (ret) - return ret; - return sprintf(buf, "%d\n", t); -} - -static ssize_t adxrs450_write_dnc(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - int ret; - long val; - - ret = strict_strtol(buf, 10, &val); - if (ret) - goto error_ret; - ret = adxrs450_spi_write_reg_16(dev, - ADXRS450_DNC1, - val & 0x3FF); -error_ret: - return ret ? ret : len; -} - -static ssize_t adxrs450_read_sensor_data(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - s16 t; - - ret = adxrs450_spi_sensor_data(dev, &t); - if (ret) - return ret; - - return sprintf(buf, "%d\n", t); -} - /* Recommended Startup Sequence by spec */ static int adxrs450_initial_setup(struct iio_dev *indio_dev) { u32 t; u16 data; int ret; - struct device *dev = &indio_dev->dev; struct adxrs450_state *st = iio_priv(indio_dev); msleep(ADXRS450_STARTUP_DELAY*2); @@ -305,23 +210,23 @@ static int adxrs450_initial_setup(struct iio_dev *indio_dev) return -EIO; } - ret = adxrs450_spi_read_reg_16(dev, ADXRS450_FAULT1, &data); + ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_FAULT1, &data); if (ret) return ret; if (data & 0x0fff) { dev_err(&st->us->dev, "The device is not in normal status!\n"); return -EINVAL; } - ret = adxrs450_spi_read_reg_16(dev, ADXRS450_PID1, &data); + ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_PID1, &data); if (ret) return ret; dev_info(&st->us->dev, "The Part ID is 0x%x\n", data); - ret = adxrs450_spi_read_reg_16(dev, ADXRS450_SNL, &data); + ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_SNL, &data); if (ret) return ret; t = data; - ret = adxrs450_spi_read_reg_16(dev, ADXRS450_SNH, &data); + ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_SNH, &data); if (ret) return ret; t |= data << 16; @@ -330,34 +235,96 @@ static int adxrs450_initial_setup(struct iio_dev *indio_dev) return 0; } -static IIO_DEV_ATTR_GYRO_Z(adxrs450_read_sensor_data, 0); -static IIO_DEV_ATTR_TEMP_RAW(adxrs450_read_temp); -static IIO_DEV_ATTR_GYRO_Z_QUADRATURE_CORRECTION(adxrs450_read_quad, 0); -static IIO_DEV_ATTR_GYRO_Z_CALIBBIAS(S_IWUSR, - NULL, adxrs450_write_dnc, 0); -static IIO_CONST_ATTR(name, "adxrs450"); - -static struct attribute *adxrs450_attributes[] = { - &iio_dev_attr_gyro_z_raw.dev_attr.attr, - &iio_dev_attr_temp_raw.dev_attr.attr, - &iio_dev_attr_gyro_z_quadrature_correction_raw.dev_attr.attr, - &iio_dev_attr_gyro_z_calibbias.dev_attr.attr, - &iio_const_attr_name.dev_attr.attr, - NULL -}; +static int adxrs450_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + int ret; + switch (mask) { + case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + ret = adxrs450_spi_write_reg_16(indio_dev, + ADXRS450_DNC1, + val & 0x3FF); + break; + default: + ret = -EINVAL; + break; + } + return ret; +} -static const struct attribute_group adxrs450_attribute_group = { - .attrs = adxrs450_attributes, +static int adxrs450_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + int ret; + s16 t; + u16 ut; + switch (mask) { + case 0: + switch (chan->type) { + case IIO_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, &ut); + if (ret) + break; + *val = ut; + ret = IIO_VAL_INT; + break; + default: + ret = -EINVAL; + break; + } + break; + case (1 << IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE): + ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t); + if (ret) + break; + *val = t; + ret = IIO_VAL_INT; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static const struct iio_chan_spec adxrs450_channels[] = { + { + .type = IIO_ANGL_VEL, + .modified = 1, + .channel2 = IIO_MOD_Z, + .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE) + }, { + .type = IIO_TEMP, + .indexed = 1, + .channel = 0, + } }; static const struct iio_info adxrs450_info = { - .attrs = &adxrs450_attribute_group, .driver_module = THIS_MODULE, + .read_raw = &adxrs450_read_raw, + .write_raw = &adxrs450_write_raw, }; static int __devinit adxrs450_probe(struct spi_device *spi) { - int ret, regdone = 0; + int ret; struct adxrs450_state *st; struct iio_dev *indio_dev; @@ -376,24 +343,23 @@ static int __devinit adxrs450_probe(struct spi_device *spi) indio_dev->dev.parent = &spi->dev; indio_dev->info = &adxrs450_info; indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = adxrs450_channels; + indio_dev->num_channels = ARRAY_SIZE(adxrs450_channels); + indio_dev->name = spi->dev.driver->name; ret = iio_device_register(indio_dev); if (ret) goto error_free_dev; - regdone = 1; /* 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: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ret; @@ -402,6 +368,7 @@ error_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; } diff --git a/drivers/staging/iio/gyro/gyro.h b/drivers/staging/iio/gyro/gyro.h deleted file mode 100644 index b5495613..0000000 --- a/drivers/staging/iio/gyro/gyro.h +++ /dev/null @@ -1,85 +0,0 @@ - -#include "../sysfs.h" - -/* Gyroscope types of attribute */ - -#define IIO_CONST_ATTR_GYRO_OFFSET(_string) \ - IIO_CONST_ATTR(gyro_offset, _string) - -#define IIO_DEV_ATTR_GYRO_OFFSET(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(gyro_offset, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_GYRO_X_OFFSET(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(gyro_x_offset, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_GYRO_Y_OFFSET(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(gyro_y_offset, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_GYRO_Z_OFFSET(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(gyro_z_offset, _mode, _show, _store, _addr) - -#define IIO_CONST_ATTR_GYRO_SCALE(_string) \ - IIO_CONST_ATTR(gyro_scale, _string) - -#define IIO_DEV_ATTR_GYRO_SCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(gyro_scale, S_IRUGO, _show, _store, _addr) - -#define IIO_DEV_ATTR_GYRO_X_SCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(gyro_x_scale, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_GYRO_Y_SCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(gyro_y_scale, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_GYRO_Z_SCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(gyro_z_scale, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_GYRO_CALIBBIAS(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(gyro_calibbias, S_IRUGO, _show, _store, _addr) - -#define IIO_DEV_ATTR_GYRO_X_CALIBBIAS(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(gyro_x_calibbias, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_GYRO_Y_CALIBBIAS(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(gyro_y_calibbias, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_GYRO_Z_CALIBBIAS(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(gyro_z_calibbias, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_GYRO_CALIBSCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(gyro_calibscale, S_IRUGO, _show, _store, _addr) - -#define IIO_DEV_ATTR_GYRO_X_CALIBSCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(gyro_x_calibscale, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_GYRO_Y_CALIBSCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(gyro_y_calibscale, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_GYRO_Z_CALIBSCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(gyro_z_calibscale, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_GYRO_Z_QUADRATURE_CORRECTION(_show, _addr) \ - IIO_DEVICE_ATTR(gyro_z_quadrature_correction_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_GYRO(_show, _addr) \ - IIO_DEVICE_ATTR(gyro_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_GYRO_X(_show, _addr) \ - IIO_DEVICE_ATTR(gyro_x_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_GYRO_Y(_show, _addr) \ - IIO_DEVICE_ATTR(gyro_y_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_GYRO_Z(_show, _addr) \ - IIO_DEVICE_ATTR(gyro_z_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_ANGL(_show, _addr) \ - IIO_DEVICE_ATTR(angl_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_ANGL_X(_show, _addr) \ - IIO_DEVICE_ATTR(angl_x_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_ANGL_Y(_show, _addr) \ - IIO_DEVICE_ATTR(angl_y_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_ANGL_Z(_show, _addr) \ - IIO_DEVICE_ATTR(angl_z_raw, S_IRUGO, _show, NULL, _addr) diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h index 7a6ce4d..f3d88cd 100644 --- a/drivers/staging/iio/iio.h +++ b/drivers/staging/iio/iio.h @@ -1,3 +1,4 @@ + /* The industrial I/O core * * Copyright (c) 2008 Jonathan Cameron @@ -12,9 +13,6 @@ #include <linux/device.h> #include <linux/cdev.h> -#include <linux/irq.h> -#include "sysfs.h" -#include "chrdev.h" /* IIO TODO LIST */ /* @@ -22,20 +20,18 @@ * Currently assumes nano seconds. */ -/* Event interface flags */ -#define IIO_BUSY_BIT_POS 1 +enum iio_data_type { + IIO_RAW, + IIO_PROCESSED, +}; -/* naughty temporary hack to match these against the event version - - need to flattern these together */ enum iio_chan_type { /* real channel types */ - IIO_IN, - IIO_OUT, + IIO_VOLTAGE, IIO_CURRENT, IIO_POWER, IIO_ACCEL, - IIO_IN_DIFF, - IIO_GYRO, + IIO_ANGL_VEL, IIO_MAGN, IIO_LIGHT, IIO_INTENSITY, @@ -45,21 +41,25 @@ enum iio_chan_type { IIO_ROT, IIO_ANGL, IIO_TIMESTAMP, + IIO_CAPACITANCE, }; -#define IIO_MOD_X 0 -#define IIO_MOD_LIGHT_BOTH 0 -#define IIO_MOD_Y 1 -#define IIO_MOD_LIGHT_IR 1 -#define IIO_MOD_Z 2 -#define IIO_MOD_X_AND_Y 3 -#define IIO_MOD_X_ANX_Z 4 -#define IIO_MOD_Y_AND_Z 5 -#define IIO_MOD_X_AND_Y_AND_Z 6 -#define IIO_MOD_X_OR_Y 7 -#define IIO_MOD_X_OR_Z 8 -#define IIO_MOD_Y_OR_Z 9 -#define IIO_MOD_X_OR_Y_OR_Z 10 +enum iio_modifier { + IIO_NO_MOD, + IIO_MOD_X, + IIO_MOD_Y, + IIO_MOD_Z, + IIO_MOD_X_AND_Y, + IIO_MOD_X_ANX_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, +}; /* Could add the raw attributes as well - allowing buffer only devices */ enum iio_chan_info_enum { @@ -75,6 +75,16 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_PEAK_SEPARATE, IIO_CHAN_INFO_PEAK_SCALE_SHARED, IIO_CHAN_INFO_PEAK_SCALE_SEPARATE, + IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED, + IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE, + IIO_CHAN_INFO_AVERAGE_RAW_SHARED, + IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE, +}; + +enum iio_endian { + IIO_CPU, + IIO_BE, + IIO_LE, }; /** @@ -92,6 +102,7 @@ enum iio_chan_info_enum { * 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. @@ -108,6 +119,7 @@ enum iio_chan_info_enum { * 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; @@ -120,33 +132,26 @@ struct iio_chan_spec { u8 realbits; u8 storagebits; u8 shift; + enum iio_endian endianness; } scan_type; - const long info_mask; - const long event_mask; - const char *extend_name; + long info_mask; + long event_mask; + char *extend_name; unsigned processed_val:1; unsigned modified:1; unsigned indexed:1; + unsigned output:1; + unsigned differential:1; }; -/* Meant for internal use only */ -void __iio_device_attr_deinit(struct device_attribute *dev_attr); -int __iio_device_attr_init(struct device_attribute *dev_attr, - const char *postfix, - struct iio_chan_spec const *chan, - ssize_t (*readfunc)(struct device *dev, - struct device_attribute *attr, - char *buf), - ssize_t (*writefunc)(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len), - bool generic); + #define IIO_ST(si, rb, sb, sh) \ { .sign = si, .realbits = rb, .storagebits = sb, .shift = sh } -#define IIO_CHAN(_type, _mod, _indexed, _proc, _name, _chan, _chan2, \ +/* 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, \ @@ -163,20 +168,6 @@ int __iio_device_attr_init(struct device_attribute *dev_attr, { .type = IIO_TIMESTAMP, .channel = -1, \ .scan_index = _si, .scan_type = IIO_ST('s', 64, 64, 0) } -int __iio_add_chan_devattr(const char *postfix, - const char *group, - struct iio_chan_spec const *chan, - ssize_t (*func)(struct device *dev, - struct device_attribute *attr, - char *buf), - ssize_t (*writefunc)(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len), - int mask, - bool generic, - struct device *dev, - struct list_head *attr_list); /** * iio_get_time_ns() - utility function to get a time stamp for events etc **/ @@ -194,10 +185,11 @@ static inline s64 iio_get_time_ns(void) /* Device operating modes */ #define INDIO_DIRECT_MODE 0x01 -#define INDIO_RING_TRIGGERED 0x02 -#define INDIO_RING_HARDWARE_BUFFER 0x08 +#define INDIO_BUFFER_TRIGGERED 0x02 +#define INDIO_BUFFER_HARDWARE 0x08 -#define INDIO_ALL_RING_MODES (INDIO_RING_TRIGGERED | INDIO_RING_HARDWARE_BUFFER) +#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. */ @@ -206,12 +198,12 @@ static inline s64 iio_get_time_ns(void) #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 - * @num_interrupt_lines:number of physical interrupt lines from device * @event_attrs: event control attributes * @attrs: general purpose device attributes * @read_raw: function to request a value from the device. @@ -235,7 +227,6 @@ struct iio_trigger; /* forward declaration */ **/ struct iio_info { struct module *driver_module; - int num_interrupt_lines; struct attribute_group *event_attrs; const struct attribute_group *attrs; @@ -256,17 +247,17 @@ struct iio_info { long mask); int (*read_event_config)(struct iio_dev *indio_dev, - int event_code); + u64 event_code); int (*write_event_config)(struct iio_dev *indio_dev, - int event_code, + u64 event_code, int state); int (*read_event_value)(struct iio_dev *indio_dev, - int event_code, + u64 event_code, int *val); int (*write_event_value)(struct iio_dev *indio_dev, - int event_code, + u64 event_code, int val); int (*validate_trigger)(struct iio_dev *indio_dev, struct iio_trigger *trig); @@ -276,110 +267,92 @@ struct iio_info { /** * struct iio_dev - industrial I/O device * @id: [INTERN] used to identify device internally - * @dev_data: [DRIVER] device specific data * @modes: [DRIVER] operating modes supported by device * @currentmode: [DRIVER] current operating mode * @dev: [DRIVER] device structure, should be assigned a parent * and owner - * @event_interfaces: [INTERN] event chrdevs associated with interrupt lines - * @ring: [DRIVER] any ring buffer present + * @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 - * @trig: [INTERN] current device trigger (ring buffer modes) + * @masklength: [INTERN] the length of the mask established from + * channels + * @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. + * 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 **/ struct iio_dev { int id; - void *dev_data; + int modes; int currentmode; struct device dev; - struct iio_event_interface *event_interfaces; + struct iio_event_interface *event_interface; - struct iio_ring_buffer *ring; + struct iio_buffer *buffer; struct mutex mlock; - u32 *available_scan_masks; + unsigned long *available_scan_masks; + unsigned masklength; struct iio_trigger *trig; struct iio_poll_func *pollfunc; - struct iio_chan_spec const *channels; - int num_channels; - - struct list_head channel_attr_list; - const char *name; - const struct iio_info *info; + 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; + struct cdev chrdev; +#define IIO_MAX_GROUPS 6 + const struct attribute_group *groups[IIO_MAX_GROUPS + 1]; + int groupcounter; }; /** * iio_device_register() - register a device with the IIO subsystem - * @dev_info: Device structure filled by the device driver + * @indio_dev: Device structure filled by the device driver **/ -int iio_device_register(struct iio_dev *dev_info); +int iio_device_register(struct iio_dev *indio_dev); /** * iio_device_unregister() - unregister a device from the IIO subsystem - * @dev_info: Device structure representing the device. + * @indio_dev: Device structure representing the device. **/ -void iio_device_unregister(struct iio_dev *dev_info); +void iio_device_unregister(struct iio_dev *indio_dev); /** * iio_push_event() - try to add event to the list for userspace reading - * @dev_info: IIO device structure - * @ev_line: Which event line (hardware interrupt) + * @indio_dev: IIO device structure * @ev_code: What event * @timestamp: When the event occurred **/ -int iio_push_event(struct iio_dev *dev_info, - int ev_line, - int ev_code, - s64 timestamp); - -/* Used to distinguish between bipolar and unipolar scan elemenents. - * Whilst this may seem obvious, we may well want to change the representation - * in the future!*/ -#define IIO_SIGNED(a) -(a) -#define IIO_UNSIGNED(a) (a) - -extern dev_t iio_devt; +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 *dev) +static inline void iio_put_device(struct iio_dev *indio_dev) { - if (dev) - put_device(&dev->dev); + if (indio_dev) + put_device(&indio_dev->dev); }; -/** - * to_iio_dev() - get iio_dev for which we have the struct device - * @d: the struct device - **/ -static inline struct iio_dev *to_iio_dev(struct device *d) -{ - return container_of(d, struct iio_dev, dev); -}; - -/** - * iio_dev_get_devdata() - helper function gets device specific data - * @d: the iio_dev associated with the device - **/ -static inline void *iio_dev_get_devdata(struct iio_dev *d) -{ - return d->dev_data; -} - - /* Can we make this smaller? */ #define IIO_ALIGN L1_CACHE_BYTES /** @@ -388,9 +361,9 @@ static inline void *iio_dev_get_devdata(struct iio_dev *d) **/ struct iio_dev *iio_allocate_device(int sizeof_priv); -static inline void *iio_priv(const struct iio_dev *dev) +static inline void *iio_priv(const struct iio_dev *indio_dev) { - return (char *)dev + ALIGN(sizeof(struct iio_dev), IIO_ALIGN); + return (char *)indio_dev + ALIGN(sizeof(struct iio_dev), IIO_ALIGN); } static inline struct iio_dev *iio_priv_to_dev(void *priv) @@ -403,37 +376,16 @@ static inline struct iio_dev *iio_priv_to_dev(void *priv) * 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 *dev); - -/** - * iio_put() - internal module reference count reduce - **/ -void iio_put(void); +void iio_free_device(struct iio_dev *indio_dev); /** - * iio_get() - internal module reference count increase + * iio_buffer_enabled() - helper function to test if the buffer is enabled + * @indio_dev: IIO device info structure for device **/ -void iio_get(void); - -/** - * iio_device_get_chrdev_minor() - get an unused minor number - **/ -int iio_device_get_chrdev_minor(void); -void iio_device_free_chrdev_minor(int val); - -/** - * iio_ring_enabled() - helper function to test if any form of ring is enabled - * @dev_info: IIO device info structure for device - **/ -static inline bool iio_ring_enabled(struct iio_dev *dev_info) +static inline bool iio_buffer_enabled(struct iio_dev *indio_dev) { - return dev_info->currentmode - & (INDIO_RING_TRIGGERED - | INDIO_RING_HARDWARE_BUFFER); + return indio_dev->currentmode + & (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE); }; -struct ida; - -int iio_get_new_ida_val(struct ida *this_ida); -void iio_free_ida_val(struct ida *this_ida, int id); #endif /* _INDUSTRIAL_IO_H_ */ diff --git a/drivers/staging/iio/iio_core.h b/drivers/staging/iio/iio_core.h new file mode 100644 index 0000000..36159e0 --- /dev/null +++ b/drivers/staging/iio/iio_core.h @@ -0,0 +1,63 @@ +/* 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; + +int iio_chrdev_buffer_open(struct iio_dev *indio_dev); +void iio_chrdev_buffer_release(struct iio_dev *indio_dev); + +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 + +static inline int iio_chrdev_buffer_open(struct iio_dev *indio_dev) +{ + return -EINVAL; +} + +static inline void iio_chrdev_buffer_release(struct iio_dev *indio_dev) +{} + +#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 new file mode 100644 index 0000000..523c288 --- /dev/null +++ b/drivers/staging/iio/iio_core_trigger.h @@ -0,0 +1,47 @@ + +/* 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 + **/ + +int 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 new file mode 100644 index 0000000..da657d1 --- /dev/null +++ b/drivers/staging/iio/iio_dummy_evgen.c @@ -0,0 +1,217 @@ +/** + * Copyright (c) 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. + * + * Companion module to the iio simple dummy example driver. + * The purpose of this is to generate 'fake' event interrupts thus + * allowing that driver's code to be as close as possible to that of + * a normal driver talking to hardware. The approach used here + * is not intended to be general and just happens to work for this + * particular use case. + */ + +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/mutex.h> +#include <linux/module.h> +#include <linux/sysfs.h> + +#include "iio_dummy_evgen.h" +#include "iio.h" +#include "sysfs.h" + +/* Fiddly bit of faking and irq without hardware */ +#define IIO_EVENTGEN_NO 10 +/** + * struct iio_dummy_evgen - evgen state + * @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 + * @lock: protect the evgen state + */ +struct iio_dummy_eventgen { + struct irq_chip chip; + int base; + bool enabled[IIO_EVENTGEN_NO]; + bool inuse[IIO_EVENTGEN_NO]; + struct mutex lock; +}; + +/* We can only ever have one instance of this 'device' */ +static struct iio_dummy_eventgen *iio_evgen; +static const char *iio_evgen_name = "iio_dummy_evgen"; + +static void iio_dummy_event_irqmask(struct irq_data *d) +{ + struct irq_chip *chip = irq_data_get_irq_chip(d); + struct iio_dummy_eventgen *evgen = + container_of(chip, struct iio_dummy_eventgen, chip); + + evgen->enabled[d->irq - evgen->base] = false; +} + +static void iio_dummy_event_irqunmask(struct irq_data *d) +{ + struct irq_chip *chip = irq_data_get_irq_chip(d); + struct iio_dummy_eventgen *evgen = + container_of(chip, struct iio_dummy_eventgen, chip); + + evgen->enabled[d->irq - evgen->base] = true; +} + +static int iio_dummy_evgen_create(void) +{ + int ret, i; + + iio_evgen = kzalloc(sizeof(*iio_evgen), GFP_KERNEL); + if (iio_evgen == NULL) + return -ENOMEM; + + iio_evgen->base = irq_alloc_descs(-1, 0, IIO_EVENTGEN_NO, 0); + if (iio_evgen->base < 0) { + ret = iio_evgen->base; + kfree(iio_evgen); + return ret; + } + iio_evgen->chip.name = iio_evgen_name; + iio_evgen->chip.irq_mask = &iio_dummy_event_irqmask; + iio_evgen->chip.irq_unmask = &iio_dummy_event_irqunmask; + for (i = 0; i < IIO_EVENTGEN_NO; i++) { + irq_set_chip(iio_evgen->base + i, &iio_evgen->chip); + irq_set_handler(iio_evgen->base + i, &handle_simple_irq); + irq_modify_status(iio_evgen->base + i, + IRQ_NOREQUEST | IRQ_NOAUTOEN, + IRQ_NOPROBE); + } + mutex_init(&iio_evgen->lock); + return 0; +} + +/** + * iio_dummy_evgen_get_irq() - get an evgen provided irq for a device + * + * This function will give a free allocated irq to a client device. + * That irq can then be caused to 'fire' by using the associated sysfs file. + */ +int iio_dummy_evgen_get_irq(void) +{ + int i, ret = 0; + mutex_lock(&iio_evgen->lock); + for (i = 0; i < IIO_EVENTGEN_NO; i++) + if (iio_evgen->inuse[i] == false) { + ret = iio_evgen->base + i; + iio_evgen->inuse[i] = true; + break; + } + mutex_unlock(&iio_evgen->lock); + if (i == IIO_EVENTGEN_NO) + return -ENOMEM; + return ret; +} +EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_irq); + +/** + * iio_dummy_evgen_release_irq() - give the irq back. + * @irq: irq being returned to the pool + * + * Used by client driver instances to give the irqs back when they disconnect + */ +int iio_dummy_evgen_release_irq(int irq) +{ + mutex_lock(&iio_evgen->lock); + iio_evgen->inuse[irq - iio_evgen->base] = false; + mutex_unlock(&iio_evgen->lock); + + return 0; +} +EXPORT_SYMBOL_GPL(iio_dummy_evgen_release_irq); + +static void iio_dummy_evgen_free(void) +{ + irq_free_descs(iio_evgen->base, IIO_EVENTGEN_NO); + kfree(iio_evgen); +} + +static void iio_evgen_release(struct device *dev) +{ + iio_dummy_evgen_free(); +} + +static ssize_t iio_evgen_poke(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + if (iio_evgen->enabled[this_attr->address]) + handle_nested_irq(iio_evgen->base + this_attr->address); + + return len; +} + +static IIO_DEVICE_ATTR(poke_ev0, S_IWUSR, NULL, &iio_evgen_poke, 0); +static IIO_DEVICE_ATTR(poke_ev1, S_IWUSR, NULL, &iio_evgen_poke, 1); +static IIO_DEVICE_ATTR(poke_ev2, S_IWUSR, NULL, &iio_evgen_poke, 2); +static IIO_DEVICE_ATTR(poke_ev3, S_IWUSR, NULL, &iio_evgen_poke, 3); +static IIO_DEVICE_ATTR(poke_ev4, S_IWUSR, NULL, &iio_evgen_poke, 4); +static IIO_DEVICE_ATTR(poke_ev5, S_IWUSR, NULL, &iio_evgen_poke, 5); +static IIO_DEVICE_ATTR(poke_ev6, S_IWUSR, NULL, &iio_evgen_poke, 6); +static IIO_DEVICE_ATTR(poke_ev7, S_IWUSR, NULL, &iio_evgen_poke, 7); +static IIO_DEVICE_ATTR(poke_ev8, S_IWUSR, NULL, &iio_evgen_poke, 8); +static IIO_DEVICE_ATTR(poke_ev9, S_IWUSR, NULL, &iio_evgen_poke, 9); + +static struct attribute *iio_evgen_attrs[] = { + &iio_dev_attr_poke_ev0.dev_attr.attr, + &iio_dev_attr_poke_ev1.dev_attr.attr, + &iio_dev_attr_poke_ev2.dev_attr.attr, + &iio_dev_attr_poke_ev3.dev_attr.attr, + &iio_dev_attr_poke_ev4.dev_attr.attr, + &iio_dev_attr_poke_ev5.dev_attr.attr, + &iio_dev_attr_poke_ev6.dev_attr.attr, + &iio_dev_attr_poke_ev7.dev_attr.attr, + &iio_dev_attr_poke_ev8.dev_attr.attr, + &iio_dev_attr_poke_ev9.dev_attr.attr, + NULL, +}; + +static const struct attribute_group iio_evgen_group = { + .attrs = iio_evgen_attrs, +}; + +static const struct attribute_group *iio_evgen_groups[] = { + &iio_evgen_group, + NULL +}; + +static struct device iio_evgen_dev = { + .bus = &iio_bus_type, + .groups = iio_evgen_groups, + .release = &iio_evgen_release, +}; +static __init int iio_dummy_evgen_init(void) +{ + int ret = iio_dummy_evgen_create(); + if (ret < 0) + return ret; + device_initialize(&iio_evgen_dev); + dev_set_name(&iio_evgen_dev, "iio_evgen"); + return device_add(&iio_evgen_dev); +} +module_init(iio_dummy_evgen_init); + +static __exit void iio_dummy_evgen_exit(void) +{ + device_unregister(&iio_evgen_dev); +} +module_exit(iio_dummy_evgen_exit); + +MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); +MODULE_DESCRIPTION("IIO dummy driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/iio_dummy_evgen.h b/drivers/staging/iio/iio_dummy_evgen.h new file mode 100644 index 0000000..d8845e2 --- /dev/null +++ b/drivers/staging/iio/iio_dummy_evgen.h @@ -0,0 +1,2 @@ +int iio_dummy_evgen_get_irq(void); +int iio_dummy_evgen_release_irq(int irq); diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c new file mode 100644 index 0000000..af0c992 --- /dev/null +++ b/drivers/staging/iio/iio_simple_dummy.c @@ -0,0 +1,545 @@ +/** + * Copyright (c) 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. + * + * A reference industrial I/O driver to illustrate the functionality available. + * + * There are numerous real drivers to illustrate the finer points. + * The purpose of this driver is to provide a driver with far more comments + * and explanatory notes than any 'real' driver would have. + * Anyone starting out writing an IIO driver should first make sure they + * understand all of this driver except those bits specifically marked + * as being present to allow us to 'fake' the presence of hardware. + */ +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/moduleparam.h> + +#include "iio.h" +#include "sysfs.h" +#include "buffer_generic.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 + * dummy devices are registered. + */ +static unsigned instances = 1; +module_param(instances, int, 0); + +/* Pointer array used to fake bus elements */ +static struct iio_dev **iio_dummy_devs; + +/* Fake a name for the part number, usually obtained from the id table */ +static const char *iio_dummy_part_number = "iio_dummy_part_no"; + +/** + * struct iio_dummy_accel_calibscale - realworld to register mapping + * @val: first value in read_raw - here integer part. + * @val2: second value in read_raw etc - here micro part. + * @regval: register value - magic device specific numbers. + */ +struct iio_dummy_accel_calibscale { + int val; + int val2; + int regval; /* what would be written to hardware */ +}; + +static const struct iio_dummy_accel_calibscale dummy_scales[] = { + { 0, 100, 0x8 }, /* 0.000100 */ + { 0, 133, 0x7 }, /* 0.000133 */ + { 733, 13, 0x9 }, /* 733.00013 */ +}; + +/* + * 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[] = { + /* indexed ADC channel in_voltage0_raw etc */ + { + .type = IIO_VOLTAGE, + /* Channel has a numeric index of 0 */ + .indexed = 1, + .channel = 0, + /* What other information is available? */ + .info_mask = + /* + * in_voltage0_offset + * Offset for userspace to apply prior to scale + * when converting to standard units (microvolts) + */ + (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | + /* + * in_voltage0_scale + * Multipler for userspace to apply post offset + * when converting to standard units (microvolts) + */ + (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + /* The ordering of elements in the buffer via an enum */ + .scan_index = voltage0, + .scan_type = { /* Description of storage in buffer */ + .sign = 'u', /* unsigned */ + .realbits = 13, /* 13 bits */ + .storagebits = 16, /* 16 bits used for storage */ + .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), +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ + }, + /* Differential ADC channel in_voltage1-voltage2_raw etc*/ + { + .type = IIO_VOLTAGE, + .differential = 1, + /* + * Indexing for differential channels uses channel + * for the positive part, channel2 for the negative. + */ + .indexed = 1, + .channel = 1, + .channel2 = 2, + .info_mask = + /* + * in_voltage-voltage_scale + * Shared version of scale - shared by differential + * input channels of type IIO_VOLTAGE. + */ + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .scan_index = diffvoltage1m2, + .scan_type = { /* Description of storage in buffer */ + .sign = 's', /* signed */ + .realbits = 12, /* 12 bits */ + .storagebits = 16, /* 16 bits used for storage */ + .shift = 0, /* zero shift */ + }, + }, + /* Differential ADC channel in_voltage3-voltage4_raw etc*/ + { + .type = IIO_VOLTAGE, + .differential = 1, + .indexed = 1, + .channel = 3, + .channel2 = 4, + .info_mask = + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .scan_index = diffvoltage3m4, + .scan_type = { + .sign = 's', + .realbits = 11, + .storagebits = 16, + .shift = 0, + }, + }, + /* + * 'modified' (i.e. axis specified) acceleration channel + * in_accel_z_raw + */ + { + .type = IIO_ACCEL, + .modified = 1, + /* Channel 2 is use for modifiers */ + .channel2 = IIO_MOD_X, + .info_mask = + /* + * Internal bias correction value. Applied + * by the hardware or driver prior to userspace + * seeing the readings. Typically part of hardware + * calibration. + */ + (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), + .scan_index = accelx, + .scan_type = { /* Description of storage in buffer */ + .sign = 's', /* signed */ + .realbits = 16, /* 12 bits */ + .storagebits = 16, /* 16 bits used for storage */ + .shift = 0, /* zero shift */ + }, + }, + /* + * Convenience macro for timestamps. 4 is the index in + * the buffer. + */ + IIO_CHAN_SOFT_TIMESTAMP(4), + /* DAC channel out_voltage0_raw */ + { + .type = IIO_VOLTAGE, + .output = 1, + .indexed = 1, + .channel = 0, + }, +}; + +/** + * iio_dummy_read_raw() - data read 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. + */ +static int iio_dummy_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + struct iio_dummy_state *st = iio_priv(indio_dev); + int ret = -EINVAL; + + mutex_lock(&st->lock); + switch (mask) { + case 0: /* magic value - channel value read */ + switch (chan->type) { + case IIO_VOLTAGE: + if (chan->output) { + /* Set integer part to cached value */ + *val = st->dac_val; + ret = IIO_VAL_INT; + } else if (chan->differential) { + if (chan->channel == 1) + *val = st->differential_adc_val[0]; + else + *val = st->differential_adc_val[1]; + ret = IIO_VAL_INT; + } else { + *val = st->single_ended_adc_val; + ret = IIO_VAL_INT; + } + break; + case IIO_ACCEL: + *val = st->accel_val; + ret = IIO_VAL_INT; + break; + default: + break; + } + break; + case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + /* only single ended adc -> 7 */ + *val = 7; + ret = IIO_VAL_INT; + break; + case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + /* only single ended adc -> 0.001333 */ + *val = 0; + *val2 = 1333; + ret = IIO_VAL_INT_PLUS_MICRO; + break; + case (1 << IIO_CHAN_INFO_SCALE_SHARED): + /* all differential adc channels -> 0.000001344 */ + *val = 0; + *val2 = 1344; + ret = IIO_VAL_INT_PLUS_NANO; + break; + case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + /* only the acceleration axis - read from cache */ + *val = st->accel_calibbias; + ret = IIO_VAL_INT; + break; + case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + *val = st->accel_calibscale->val; + *val2 = st->accel_calibscale->val2; + ret = IIO_VAL_INT_PLUS_MICRO; + break; + default: + break; + } + mutex_unlock(&st->lock); + return ret; +} + +/** + * 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. + * + * 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 + * in struct iio_info is provided by the driver. + */ +static int iio_dummy_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + int i; + int ret = 0; + struct iio_dummy_state *st = iio_priv(indio_dev); + + switch (mask) { + case 0: + if (chan->output == 0) + return -EINVAL; + + /* Locking not required as writing single value */ + mutex_lock(&st->lock); + st->dac_val = val; + mutex_unlock(&st->lock); + return 0; + case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + mutex_lock(&st->lock); + /* Compare against table - hard matching here */ + for (i = 0; i < ARRAY_SIZE(dummy_scales); i++) + if (val == dummy_scales[i].val && + val2 == dummy_scales[i].val2) + break; + if (i == ARRAY_SIZE(dummy_scales)) + ret = -EINVAL; + else + st->accel_calibscale = &dummy_scales[i]; + mutex_unlock(&st->lock); + return ret; + default: + return -EINVAL; + } +} + +/* + * Device type specific information. + */ +static const struct iio_info iio_dummy_info = { + .driver_module = THIS_MODULE, + .read_raw = &iio_dummy_read_raw, + .write_raw = &iio_dummy_write_raw, +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS + .read_event_config = &iio_simple_dummy_read_event_config, + .write_event_config = &iio_simple_dummy_write_event_config, + .read_event_value = &iio_simple_dummy_read_event_value, + .write_event_value = &iio_simple_dummy_write_event_value, +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ +}; + +/** + * iio_dummy_init_device() - device instance specific init + * @indio_dev: the iio device structure + * + * Most drivers have one of these to set up default values, + * reset the device to known state etc. + */ +static int iio_dummy_init_device(struct iio_dev *indio_dev) +{ + struct iio_dummy_state *st = iio_priv(indio_dev); + + st->dac_val = 0; + st->single_ended_adc_val = 73; + st->differential_adc_val[0] = 33; + st->differential_adc_val[1] = -34; + st->accel_val = 34; + st->accel_calibbias = -7; + st->accel_calibscale = &dummy_scales[0]; + + return 0; +} + +/** + * iio_dummy_probe() - device instance probe + * @index: an id number for this instance. + * + * Arguments are bus type specific. + * I2C: iio_dummy_probe(struct i2c_client *client, + * const struct i2c_device_id *id) + * SPI: iio_dummy_probe(struct spi_device *spi) + */ +static int __devinit iio_dummy_probe(int index) +{ + int ret; + struct iio_dev *indio_dev; + struct iio_dummy_state *st; + + /* + * Allocate an IIO device. + * + * This structure contains all generic state + * information about the device instance. + * It also has a region (accessed by iio_priv() + * for chip specific state information. + */ + indio_dev = iio_allocate_device(sizeof(*st)); + if (indio_dev == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + st = iio_priv(indio_dev); + mutex_init(&st->lock); + + iio_dummy_init_device(indio_dev); + /* + * With hardware: Set the parent device. + * indio_dev->dev.parent = &spi->dev; + * indio_dev->dev.parent = &client->dev; + */ + + /* + * Make the iio_dev struct available to remove function. + * Bus equivalents + * i2c_set_clientdata(client, indio_dev); + * spi_set_drvdata(spi, indio_dev); + */ + iio_dummy_devs[index] = indio_dev; + + + /* + * Set the device name. + * + * This is typically a part number and obtained from the module + * id table. + * e.g. for i2c and spi: + * indio_dev->name = id->name; + * indio_dev->name = spi_get_device_id(spi)->name; + */ + indio_dev->name = iio_dummy_part_number; + + /* Provide description of available channels */ + indio_dev->channels = iio_dummy_channels; + indio_dev->num_channels = ARRAY_SIZE(iio_dummy_channels); + + /* + * Provide device type specific interface functions and + * constant data. + */ + indio_dev->info = &iio_dummy_info; + + /* Specify that device provides sysfs type interfaces */ + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_simple_dummy_events_register(indio_dev); + 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. + */ + ret = iio_buffer_register(indio_dev, iio_dummy_channels, 5); + if (ret < 0) + goto error_unconfigure_buffer; + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto error_unregister_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); +error_ret: + return ret; +} + +/** + * iio_dummy_remove() - device instance removal function + * @index: device index. + * + * Parameters follow those of iio_dummy_probe for buses. + */ +static int iio_dummy_remove(int index) +{ + int ret; + /* + * Get a pointer to the device instance iio_dev structure + * from the bus subsystem. E.g. + * struct iio_dev *indio_dev = i2c_get_clientdata(client); + * struct iio_dev *indio_dev = spi_get_drvdata(spi); + */ + struct iio_dev *indio_dev = iio_dummy_devs[index]; + + + /* Unregister the device */ + iio_device_unregister(indio_dev); + + /* 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); + if (ret) + goto error_ret; + + /* Free all structures */ + iio_free_device(indio_dev); + +error_ret: + return ret; +} + +/** + * iio_dummy_init() - device driver registration + * + * Varies depending on bus type of the device. As there is no device + * here, call probe directly. For information on device registration + * i2c: + * Documentation/i2c/writing-clients + * spi: + * Documentation/spi/spi-summary + */ +static __init int iio_dummy_init(void) +{ + int i, ret; + if (instances > 10) { + instances = 1; + return -EINVAL; + } + /* Fake a bus */ + iio_dummy_devs = kzalloc(sizeof(*iio_dummy_devs)*instances, GFP_KERNEL); + /* Here we have no actual device so call probe */ + for (i = 0; i < instances; i++) { + ret = iio_dummy_probe(i); + if (ret < 0) + return ret; + } + return 0; +} +module_init(iio_dummy_init); + +/** + * iio_dummy_exit() - device driver removal + * + * Varies depending on bus type of the device. + * As there is no device here, call remove directly. + */ +static __exit void iio_dummy_exit(void) +{ + int i; + for (i = 0; i < instances; i++) + iio_dummy_remove(i); + kfree(iio_dummy_devs); +} +module_exit(iio_dummy_exit); + +MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); +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 new file mode 100644 index 0000000..53975d9 --- /dev/null +++ b/drivers/staging/iio/iio_simple_dummy.h @@ -0,0 +1,108 @@ +/** + * Copyright (c) 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. + * + * Join together the various functionality of iio_simple_dummy driver + */ + +#include <linux/kernel.h> + +struct iio_dummy_accel_calibscale; + +/** + * struct iio_dummy_state - device instance specific state. + * @dac_val: cache for dac value + * @single_ended_adc_val: cache for single ended adc value + * @differential_adc_val: cache for differential adc value + * @accel_val: cache for acceleration value + * @accel_calibbias: cache for acceleration calibbias + * @accel_calibscale: cache for acceleration calibscale + * @lock: lock to ensure state is consistent + * @event_irq: irq number for event line (faked) + * @event_val: cache for event theshold value + * @event_en: cache of whether event is enabled + */ +struct iio_dummy_state { + int dac_val; + int single_ended_adc_val; + int differential_adc_val[2]; + int accel_val; + int accel_calibbias; + const struct iio_dummy_accel_calibscale *accel_calibscale; + struct mutex lock; +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS + int event_irq; + int event_val; + bool event_en; +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ +}; + +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS + +struct iio_dev; + +int iio_simple_dummy_read_event_config(struct iio_dev *indio_dev, + u64 event_code); + +int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, + u64 event_code, + int state); + +int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev, + u64 event_code, + int *val); + +int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev, + u64 event_code, + int val); + +int iio_simple_dummy_events_register(struct iio_dev *indio_dev); +int iio_simple_dummy_events_unregister(struct iio_dev *indio_dev); + +#else /* Stubs for when events are disabled at compile time */ + +static inline int +iio_simple_dummy_events_register(struct iio_dev *indio_dev) +{ + return 0; +}; + +static inline int +iio_simple_dummy_events_unregister(struct iio_dev *indio_dev) +{ + return 0; +}; + +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS*/ + +/** + * enum iio_simple_dummy_scan_elements - scan index enum + * @voltage0: the single ended voltage channel + * @diffvoltage1m2: first differential channel + * @diffvoltage3m4: second differenial channel + * @accelx: acceleration channel + * + * Enum provides convenient numbering for the scan index. + */ +enum iio_simple_dummy_scan_elements { + voltage0, + diffvoltage1m2, + diffvoltage3m4, + accelx, +}; + +#ifdef CONFIG_IIO_SIMPLE_DUMMY_BUFFER +int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev); +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) +{ + return 0; +}; +static inline +void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev) +{}; +#endif /* CONFIG_IIO_SIMPLE_DUMMY_BUFFER */ diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c new file mode 100644 index 0000000..f0b36d2 --- /dev/null +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -0,0 +1,206 @@ +/** + * Copyright (c) 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. + * + * Buffer handling elements of industrial I/O reference driver. + * Uses the kfifo buffer. + * + * To test without hardware use the sysfs trigger. + */ + +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/bitmap.h> + +#include "iio.h" +#include "trigger_consumer.h" +#include "kfifo_buf.h" + +#include "iio_simple_dummy.h" + +/* Some fake data */ + +static const s16 fakedata[] = { + [voltage0] = 7, + [diffvoltage1m2] = -33, + [diffvoltage3m4] = -2, + [accelx] = 344, +}; +/** + * iio_simple_dummy_trigger_h() - the trigger handler function + * @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, + * 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. + */ +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); + if (data == NULL) + return -ENOMEM; + + if (buffer->scan_count) { + /* + * Three common options here: + * hardware scans: certain combinations of channels make + * 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 + * 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 + * in the constant table fakedata. + */ + int i, j; + for (i = 0, j = 0; i < buffer->scan_count; i++) { + j = find_next_bit(buffer->scan_mask, + indio_dev->masklength, j + 1); + /* random access read form 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); + + kfree(data); + + /* + * Tell the core we are done with this trigger and ready for the + * next one. + */ + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +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 + * trigger. + */ + .postenable = &iio_triggered_buffer_postenable, + /* + * iio_triggered_buffer_predisable: + * Generic function that simple detaches the pollfunc from the trigger. + * Replace this to put hardware state back again after the trigger is + * detached but before userspace knows we have disabled the ring. + */ + .predisable = &iio_triggered_buffer_predisable, +}; + +int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) +{ + int ret; + struct iio_buffer *buffer; + + /* Allocate a buffer to use - here a kfifo */ + buffer = iio_kfifo_allocate(indio_dev); + if (buffer == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + indio_dev->buffer = buffer; + /* Tell the core how to access the buffer */ + buffer->access = &kfifo_access_funcs; + + /* Number of bytes per element */ + buffer->bpe = 2; + /* Enable timestamps by default */ + buffer->scan_timestamp = true; + + /* + * Tell the core what device type specific functions should + * be run on either side of buffer capture enable / disable. + */ + buffer->setup_ops = &iio_simple_dummy_buffer_setup_ops; + buffer->owner = THIS_MODULE; + + /* + * Configure a polling function. + * When a trigger event with this polling function connected + * occurs, this function is run. Typically this grabs data + * from the device. + * + * NULL for the top 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. + * + * IRQF_ONESHOT ensures irqs are masked such that only one instance + * of the handler can run at a time. + * + * "iio_simple_dummy_consumer%d" formatting string for the irq 'name' + * as seen under /proc/interrupts. Remaining parameters as per printk. + */ + indio_dev->pollfunc = iio_alloc_pollfunc(NULL, + &iio_simple_dummy_trigger_h, + IRQF_ONESHOT, + indio_dev, + "iio_simple_dummy_consumer%d", + indio_dev->id); + + if (indio_dev->pollfunc == NULL) { + ret = -ENOMEM; + goto error_free_buffer; + } + + /* + * Notify the core that this device is capable of buffered capture + * driven by a trigger. + */ + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; + return 0; + +error_free_buffer: + iio_kfifo_free(indio_dev->buffer); +error_ret: + return ret; + +} + +/** + * iio_simple_dummy_unconfigure_buffer() - release buffer resources + * @indo_dev: device instance state + */ +void iio_simple_dummy_unconfigure_buffer(struct iio_dev *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 new file mode 100644 index 0000000..9f00cff --- /dev/null +++ b/drivers/staging/iio/iio_simple_dummy_events.c @@ -0,0 +1,190 @@ +/** + * Copyright (c) 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. + * + * Event handling elements of industrial I/O reference driver. + */ +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/irq.h> + +#include "iio.h" +#include "sysfs.h" +#include "iio_simple_dummy.h" + +/* Evgen 'fakes' interrupt events for this example */ +#include "iio_dummy_evgen.h" + +/** + * iio_simple_dummy_read_event_config() - is event enabled? + * @indio_dev: the device instance data + * @event_code: event code of the event 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) +{ + struct iio_dummy_state *st = iio_priv(indio_dev); + + return st->event_en; +} + +/** + * 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 + * @state: whether to enable or disable the device. + * + * This function would normally set the relevant registers on the devices + * so that it generates the specified event. Here it just sets up a cached + * value. + */ +int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, + u64 event_code, + int state) +{ + struct iio_dummy_state *st = iio_priv(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)) { + case IIO_VOLTAGE: + switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) { + case IIO_EV_TYPE_THRESH: + if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == + IIO_EV_DIR_RISING) + st->event_en = state; + else + return -EINVAL; + break; + default: + return -EINVAL; + } + default: + return -EINVAL; + } + + return 0; +} + +/** + * 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 + * @val: value for the event code. + * + * Many devices provide a large set of events of which only a subset may + * be enabled at a time, with value registers whose meaning changes depending + * on the event enabled. This often means that the driver must cache the values + * associated with each possible events so that the right value is in place when + * the enabled event is changed. + */ +int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev, + u64 event_code, + int *val) +{ + struct iio_dummy_state *st = iio_priv(indio_dev); + + *val = st->event_val; + + return 0; +} + +/** + * 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 + * @val: the value to be set. + */ +int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev, + u64 event_code, + int val) +{ + struct iio_dummy_state *st = iio_priv(indio_dev); + + st->event_val = val; + + return 0; +} + +/** + * iio_simple_dummy_event_handler() - identify and pass on event + * @irq: irq of event line + * @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. + * Here only one event occurs so we push that directly on with locally + * grabbed timestamp. + */ +static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0, + IIO_EV_DIR_RISING, + IIO_EV_TYPE_THRESH, 0, 0, 0), + iio_get_time_ns()); + return IRQ_HANDLED; +} + +/** + * iio_simple_dummy_events_register() - setup interrupt handling for events + * @indio_dev: device instance data + * + * This function requests the threaded interrupt to handle the events. + * Normally the irq is a hardware interrupt and the number comes + * from board configuration files. Here we get it from a companion + * module that fakes the interrupt for us. Note that module in + * no way forms part of this example. Just assume that events magically + * appear via the provided interrupt. + */ +int iio_simple_dummy_events_register(struct iio_dev *indio_dev) +{ + struct iio_dummy_state *st = iio_priv(indio_dev); + int ret; + + /* Fire up event source - normally not present */ + st->event_irq = iio_dummy_evgen_get_irq(); + if (st->event_irq < 0) { + ret = st->event_irq; + goto error_ret; + } + ret = request_threaded_irq(st->event_irq, + NULL, + &iio_simple_dummy_event_handler, + IRQF_ONESHOT, + "iio_simple_event", + indio_dev); + if (ret < 0) + goto error_free_evgen; + return 0; + +error_free_evgen: + iio_dummy_evgen_release_irq(st->event_irq); +error_ret: + return ret; +} + +/** + * iio_simple_dummy_events_unregister() - tidy up interrupt handling on remove + * @indio_dev: device instance data + */ +int iio_simple_dummy_events_unregister(struct iio_dev *indio_dev) +{ + struct iio_dummy_state *st = iio_priv(indio_dev); + + free_irq(st->event_irq, indio_dev); + /* Not part of normal driver */ + iio_dummy_evgen_release_irq(st->event_irq); + + return 0; +} diff --git a/drivers/staging/iio/impedance-analyzer/Kconfig b/drivers/staging/iio/impedance-analyzer/Kconfig new file mode 100644 index 0000000..ad0ff76 --- /dev/null +++ b/drivers/staging/iio/impedance-analyzer/Kconfig @@ -0,0 +1,18 @@ +# +# Impedance Converter, Network Analyzer drivers +# +menu "Network Analyzer, Impedance Converters" + +config AD5933 + tristate "Analog Devices AD5933, AD5934 driver" + depends on I2C + select IIO_BUFFER + select IIO_SW_RING + help + Say yes here to build support for Analog Devices Impedance Converter, + Network Analyzer, AD5933/4, provides direct access via sysfs. + + To compile this driver as a module, choose M here: the + module will be called ad5933. + +endmenu diff --git a/drivers/staging/iio/impedance-analyzer/Makefile b/drivers/staging/iio/impedance-analyzer/Makefile new file mode 100644 index 0000000..7604d78 --- /dev/null +++ b/drivers/staging/iio/impedance-analyzer/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for Impedance Converter, Network Analyzer drivers +# + +obj-$(CONFIG_AD5933) += ad5933.o diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c new file mode 100644 index 0000000..1086e0b --- /dev/null +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -0,0 +1,814 @@ +/* + * AD5933 AD5934 Impedance Converter, Network Analyzer + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include <linux/interrupt.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/sysfs.h> +#include <linux/i2c.h> +#include <linux/regulator/consumer.h> +#include <linux/slab.h> +#include <linux/types.h> +#include <linux/err.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <asm/div64.h> + +#include "../iio.h" +#include "../sysfs.h" +#include "../buffer_generic.h" +#include "../ring_sw.h" + +#include "ad5933.h" + +/* AD5933/AD5934 Registers */ +#define AD5933_REG_CONTROL_HB 0x80 /* R/W, 2 bytes */ +#define AD5933_REG_CONTROL_LB 0x81 /* R/W, 2 bytes */ +#define AD5933_REG_FREQ_START 0x82 /* R/W, 3 bytes */ +#define AD5933_REG_FREQ_INC 0x85 /* R/W, 3 bytes */ +#define AD5933_REG_INC_NUM 0x88 /* R/W, 2 bytes, 9 bit */ +#define AD5933_REG_SETTLING_CYCLES 0x8A /* R/W, 2 bytes */ +#define AD5933_REG_STATUS 0x8F /* R, 1 byte */ +#define AD5933_REG_TEMP_DATA 0x92 /* R, 2 bytes*/ +#define AD5933_REG_REAL_DATA 0x94 /* R, 2 bytes*/ +#define AD5933_REG_IMAG_DATA 0x96 /* R, 2 bytes*/ + +/* AD5933_REG_CONTROL_HB Bits */ +#define AD5933_CTRL_INIT_START_FREQ (0x1 << 4) +#define AD5933_CTRL_START_SWEEP (0x2 << 4) +#define AD5933_CTRL_INC_FREQ (0x3 << 4) +#define AD5933_CTRL_REPEAT_FREQ (0x4 << 4) +#define AD5933_CTRL_MEASURE_TEMP (0x9 << 4) +#define AD5933_CTRL_POWER_DOWN (0xA << 4) +#define AD5933_CTRL_STANDBY (0xB << 4) + +#define AD5933_CTRL_RANGE_2000mVpp (0x0 << 1) +#define AD5933_CTRL_RANGE_200mVpp (0x1 << 1) +#define AD5933_CTRL_RANGE_400mVpp (0x2 << 1) +#define AD5933_CTRL_RANGE_1000mVpp (0x3 << 1) +#define AD5933_CTRL_RANGE(x) ((x) << 1) + +#define AD5933_CTRL_PGA_GAIN_1 (0x1 << 0) +#define AD5933_CTRL_PGA_GAIN_5 (0x0 << 0) + +/* AD5933_REG_CONTROL_LB Bits */ +#define AD5933_CTRL_RESET (0x1 << 4) +#define AD5933_CTRL_INT_SYSCLK (0x0 << 3) +#define AD5933_CTRL_EXT_SYSCLK (0x1 << 3) + +/* AD5933_REG_STATUS Bits */ +#define AD5933_STAT_TEMP_VALID (0x1 << 0) +#define AD5933_STAT_DATA_VALID (0x1 << 1) +#define AD5933_STAT_SWEEP_DONE (0x1 << 2) + +/* I2C Block Commands */ +#define AD5933_I2C_BLOCK_WRITE 0xA0 +#define AD5933_I2C_BLOCK_READ 0xA1 +#define AD5933_I2C_ADDR_POINTER 0xB0 + +/* Device Specs */ +#define AD5933_INT_OSC_FREQ_Hz 16776000 +#define AD5933_MAX_OUTPUT_FREQ_Hz 100000 +#define AD5933_MAX_RETRIES 100 + +#define AD5933_OUT_RANGE 1 +#define AD5933_OUT_RANGE_AVAIL 2 +#define AD5933_OUT_SETTLING_CYCLES 3 +#define AD5933_IN_PGA_GAIN 4 +#define AD5933_IN_PGA_GAIN_AVAIL 5 +#define AD5933_FREQ_POINTS 6 + +#define AD5933_POLL_TIME_ms 10 +#define AD5933_INIT_EXCITATION_TIME_ms 100 + +struct ad5933_state { + struct i2c_client *client; + struct regulator *reg; + struct ad5933_platform_data *pdata; + struct delayed_work work; + unsigned long mclk_hz; + unsigned char ctrl_hb; + unsigned char ctrl_lb; + unsigned range_avail[4]; + unsigned short vref_mv; + unsigned short settling_cycles; + unsigned short freq_points; + unsigned freq_start; + unsigned freq_inc; + unsigned state; + unsigned poll_time_jiffies; +}; + +static struct ad5933_platform_data ad5933_default_pdata = { + .vref_mv = 3300, +}; + +static struct iio_chan_spec ad5933_channels[] = { + IIO_CHAN(IIO_TEMP, 0, 1, 1, NULL, 0, 0, 0, + 0, AD5933_REG_TEMP_DATA, IIO_ST('s', 14, 16, 0), 0), + /* Ring Channels */ + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "real_raw", 0, 0, + (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + AD5933_REG_REAL_DATA, 0, IIO_ST('s', 16, 16, 0), 0), + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "imag_raw", 0, 0, + (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + AD5933_REG_IMAG_DATA, 1, IIO_ST('s', 16, 16, 0), 0), +}; + +static int ad5933_i2c_write(struct i2c_client *client, + u8 reg, u8 len, u8 *data) +{ + int ret; + + while (len--) { + ret = i2c_smbus_write_byte_data(client, reg++, *data++); + if (ret < 0) { + dev_err(&client->dev, "I2C write error\n"); + return ret; + } + } + return 0; +} + +static int ad5933_i2c_read(struct i2c_client *client, + u8 reg, u8 len, u8 *data) +{ + int ret; + + while (len--) { + ret = i2c_smbus_read_byte_data(client, reg++); + if (ret < 0) { + dev_err(&client->dev, "I2C read error\n"); + return ret; + } + *data++ = ret; + } + return 0; +} + +static int ad5933_cmd(struct ad5933_state *st, unsigned char cmd) +{ + unsigned char dat = st->ctrl_hb | cmd; + + return ad5933_i2c_write(st->client, + AD5933_REG_CONTROL_HB, 1, &dat); +} + +static int ad5933_reset(struct ad5933_state *st) +{ + unsigned char dat = st->ctrl_lb | AD5933_CTRL_RESET; + return ad5933_i2c_write(st->client, + AD5933_REG_CONTROL_LB, 1, &dat); +} + +static int ad5933_wait_busy(struct ad5933_state *st, unsigned char event) +{ + unsigned char val, timeout = AD5933_MAX_RETRIES; + int ret; + + while (timeout--) { + ret = ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &val); + if (ret < 0) + return ret; + if (val & event) + return val; + cpu_relax(); + mdelay(1); + } + + return -EAGAIN; +} + +static int ad5933_set_freq(struct ad5933_state *st, + unsigned reg, unsigned long freq) +{ + unsigned long long freqreg; + union { + u32 d32; + u8 d8[4]; + } dat; + + freqreg = (u64) freq * (u64) (1 << 27); + do_div(freqreg, st->mclk_hz / 4); + + switch (reg) { + case AD5933_REG_FREQ_START: + st->freq_start = freq; + break; + case AD5933_REG_FREQ_INC: + st->freq_inc = freq; + break; + default: + return -EINVAL; + } + + dat.d32 = cpu_to_be32(freqreg); + return ad5933_i2c_write(st->client, reg, 3, &dat.d8[1]); +} + +static int ad5933_setup(struct ad5933_state *st) +{ + unsigned short dat; + int ret; + + ret = ad5933_reset(st); + if (ret < 0) + return ret; + + ret = ad5933_set_freq(st, AD5933_REG_FREQ_START, 10000); + if (ret < 0) + return ret; + + ret = ad5933_set_freq(st, AD5933_REG_FREQ_INC, 200); + if (ret < 0) + return ret; + + st->settling_cycles = 10; + dat = cpu_to_be16(st->settling_cycles); + + ret = ad5933_i2c_write(st->client, + AD5933_REG_SETTLING_CYCLES, 2, (u8 *)&dat); + if (ret < 0) + return ret; + + st->freq_points = 100; + dat = cpu_to_be16(st->freq_points); + + return ad5933_i2c_write(st->client, AD5933_REG_INC_NUM, 2, (u8 *)&dat); +} + +static void ad5933_calc_out_ranges(struct ad5933_state *st) +{ + int i; + unsigned normalized_3v3[4] = {1980, 198, 383, 970}; + + for (i = 0; i < 4; i++) + st->range_avail[i] = normalized_3v3[i] * st->vref_mv / 3300; + +} + +/* + * handles: AD5933_REG_FREQ_START and AD5933_REG_FREQ_INC + */ + +static ssize_t ad5933_show_frequency(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad5933_state *st = iio_priv(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + unsigned long long freqreg; + union { + u32 d32; + u8 d8[4]; + } dat; + + mutex_lock(&indio_dev->mlock); + ret = ad5933_i2c_read(st->client, this_attr->address, 3, &dat.d8[1]); + mutex_unlock(&indio_dev->mlock); + if (ret < 0) + return ret; + + freqreg = be32_to_cpu(dat.d32) & 0xFFFFFF; + + freqreg = (u64) freqreg * (u64) (st->mclk_hz / 4); + do_div(freqreg, 1 << 27); + + return sprintf(buf, "%d\n", (int) freqreg); +} + +static ssize_t ad5933_store_frequency(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad5933_state *st = iio_priv(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + long val; + int ret; + + ret = strict_strtoul(buf, 10, &val); + if (ret) + return ret; + + if (val > AD5933_MAX_OUTPUT_FREQ_Hz) + return -EINVAL; + + mutex_lock(&indio_dev->mlock); + ret = ad5933_set_freq(st, this_attr->address, val); + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static IIO_DEVICE_ATTR(out_voltage0_freq_start, S_IRUGO | S_IWUSR, + ad5933_show_frequency, + ad5933_store_frequency, + AD5933_REG_FREQ_START); + +static IIO_DEVICE_ATTR(out_voltage0_freq_increment, S_IRUGO | S_IWUSR, + ad5933_show_frequency, + ad5933_store_frequency, + AD5933_REG_FREQ_INC); + +static ssize_t ad5933_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(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; + + mutex_lock(&indio_dev->mlock); + switch (this_attr->address) { + case AD5933_OUT_RANGE: + len = sprintf(buf, "%d\n", + st->range_avail[(st->ctrl_hb >> 1) & 0x3]); + break; + case AD5933_OUT_RANGE_AVAIL: + len = sprintf(buf, "%d %d %d %d\n", st->range_avail[0], + st->range_avail[3], st->range_avail[2], + st->range_avail[1]); + break; + case AD5933_OUT_SETTLING_CYCLES: + len = sprintf(buf, "%d\n", st->settling_cycles); + break; + case AD5933_IN_PGA_GAIN: + len = sprintf(buf, "%s\n", + (st->ctrl_hb & AD5933_CTRL_PGA_GAIN_1) ? + "1" : "0.2"); + break; + case AD5933_IN_PGA_GAIN_AVAIL: + len = sprintf(buf, "1 0.2\n"); + break; + case AD5933_FREQ_POINTS: + len = sprintf(buf, "%d\n", st->freq_points); + break; + default: + ret = -EINVAL; + } + + mutex_unlock(&indio_dev->mlock); + return ret ? ret : len; +} + +static ssize_t ad5933_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad5933_state *st = iio_priv(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + long val; + int i, ret = 0; + unsigned short dat; + + if (this_attr->address != AD5933_IN_PGA_GAIN) { + ret = strict_strtol(buf, 10, &val); + if (ret) + return ret; + } + + mutex_lock(&indio_dev->mlock); + switch (this_attr->address) { + case AD5933_OUT_RANGE: + for (i = 0; i < 4; i++) + if (val == st->range_avail[i]) { + st->ctrl_hb &= ~AD5933_CTRL_RANGE(0x3); + st->ctrl_hb |= AD5933_CTRL_RANGE(i); + ret = ad5933_cmd(st, 0); + break; + } + ret = -EINVAL; + break; + case AD5933_IN_PGA_GAIN: + if (sysfs_streq(buf, "1")) { + st->ctrl_hb |= AD5933_CTRL_PGA_GAIN_1; + } else if (sysfs_streq(buf, "0.2")) { + st->ctrl_hb &= ~AD5933_CTRL_PGA_GAIN_1; + } else { + ret = -EINVAL; + break; + } + ret = ad5933_cmd(st, 0); + break; + case AD5933_OUT_SETTLING_CYCLES: + val = clamp(val, 0L, 0x7FFL); + st->settling_cycles = val; + + /* 2x, 4x handling, see datasheet */ + if (val > 511) + val = (val >> 1) | (1 << 9); + else if (val > 1022) + val = (val >> 2) | (3 << 9); + + dat = cpu_to_be16(val); + ret = ad5933_i2c_write(st->client, + AD5933_REG_SETTLING_CYCLES, 2, (u8 *)&dat); + break; + case AD5933_FREQ_POINTS: + val = clamp(val, 0L, 511L); + st->freq_points = val; + + dat = cpu_to_be16(val); + ret = ad5933_i2c_write(st->client, AD5933_REG_INC_NUM, 2, + (u8 *)&dat); + break; + default: + ret = -EINVAL; + } + + mutex_unlock(&indio_dev->mlock); + return ret ? ret : len; +} + +static IIO_DEVICE_ATTR(out_voltage0_scale, S_IRUGO | S_IWUSR, + ad5933_show, + ad5933_store, + AD5933_OUT_RANGE); + +static IIO_DEVICE_ATTR(out_voltage0_scale_available, S_IRUGO, + ad5933_show, + NULL, + AD5933_OUT_RANGE_AVAIL); + +static IIO_DEVICE_ATTR(in_voltage0_scale, S_IRUGO | S_IWUSR, + ad5933_show, + ad5933_store, + AD5933_IN_PGA_GAIN); + +static IIO_DEVICE_ATTR(in_voltage0_scale_available, S_IRUGO, + ad5933_show, + NULL, + AD5933_IN_PGA_GAIN_AVAIL); + +static IIO_DEVICE_ATTR(out_voltage0_freq_points, S_IRUGO | S_IWUSR, + ad5933_show, + ad5933_store, + AD5933_FREQ_POINTS); + +static IIO_DEVICE_ATTR(out_voltage0_settling_cycles, S_IRUGO | S_IWUSR, + ad5933_show, + ad5933_store, + AD5933_OUT_SETTLING_CYCLES); + +/* note: + * ideally we would handle the scale attributes via the iio_info + * (read|write)_raw methods, however this part is a untypical since we + * don't create dedicated sysfs channel attributes for out0 and in0. + */ +static struct attribute *ad5933_attributes[] = { + &iio_dev_attr_out_voltage0_scale.dev_attr.attr, + &iio_dev_attr_out_voltage0_scale_available.dev_attr.attr, + &iio_dev_attr_out_voltage0_freq_start.dev_attr.attr, + &iio_dev_attr_out_voltage0_freq_increment.dev_attr.attr, + &iio_dev_attr_out_voltage0_freq_points.dev_attr.attr, + &iio_dev_attr_out_voltage0_settling_cycles.dev_attr.attr, + &iio_dev_attr_in_voltage0_scale.dev_attr.attr, + &iio_dev_attr_in_voltage0_scale_available.dev_attr.attr, + NULL +}; + +static const struct attribute_group ad5933_attribute_group = { + .attrs = ad5933_attributes, +}; + +static int ad5933_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad5933_state *st = iio_priv(indio_dev); + unsigned short dat; + int ret = -EINVAL; + + mutex_lock(&indio_dev->mlock); + switch (m) { + case 0: + if (iio_buffer_enabled(indio_dev)) { + ret = -EBUSY; + goto out; + } + ret = ad5933_cmd(st, AD5933_CTRL_MEASURE_TEMP); + if (ret < 0) + goto out; + ret = ad5933_wait_busy(st, AD5933_STAT_TEMP_VALID); + if (ret < 0) + goto out; + + ret = ad5933_i2c_read(st->client, + AD5933_REG_TEMP_DATA, 2, + (u8 *)&dat); + if (ret < 0) + goto out; + mutex_unlock(&indio_dev->mlock); + ret = be16_to_cpu(dat); + /* Temp in Milli degrees Celsius */ + if (ret < 8192) + *val = ret * 1000 / 32; + else + *val = (ret - 16384) * 1000 / 32; + + return IIO_VAL_INT; + } + +out: + mutex_unlock(&indio_dev->mlock); + return ret; +} + +static const struct iio_info ad5933_info = { + .read_raw = &ad5933_read_raw, + .attrs = &ad5933_attribute_group, + .driver_module = THIS_MODULE, +}; + +static int ad5933_ring_preenable(struct iio_dev *indio_dev) +{ + struct ad5933_state *st = iio_priv(indio_dev); + struct iio_buffer *ring = indio_dev->buffer; + size_t d_size; + int ret; + + if (!ring->scan_count) + return -EINVAL; + + d_size = ring->scan_count * + ad5933_channels[1].scan_type.storagebits / 8; + + if (indio_dev->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; + + ret = ad5933_cmd(st, AD5933_CTRL_STANDBY); + if (ret < 0) + return ret; + + ret = ad5933_cmd(st, AD5933_CTRL_INIT_START_FREQ); + if (ret < 0) + return ret; + + st->state = AD5933_CTRL_INIT_START_FREQ; + + return 0; +} + +static int ad5933_ring_postenable(struct iio_dev *indio_dev) +{ + struct ad5933_state *st = iio_priv(indio_dev); + + /* AD5933_CTRL_INIT_START_FREQ: + * High Q complex circuits require a long time to reach steady state. + * To facilitate the measurement of such impedances, this mode allows + * the user full control of the settling time requirement before + * entering start frequency sweep mode where the impedance measurement + * takes place. In this mode the impedance is excited with the + * programmed start frequency (ad5933_ring_preenable), + * but no measurement takes place. + */ + + schedule_delayed_work(&st->work, + msecs_to_jiffies(AD5933_INIT_EXCITATION_TIME_ms)); + return 0; +} + +static int ad5933_ring_postdisable(struct iio_dev *indio_dev) +{ + struct ad5933_state *st = iio_priv(indio_dev); + + cancel_delayed_work_sync(&st->work); + return ad5933_cmd(st, AD5933_CTRL_POWER_DOWN); +} + +static const struct iio_buffer_setup_ops ad5933_ring_setup_ops = { + .preenable = &ad5933_ring_preenable, + .postenable = &ad5933_ring_postenable, + .postdisable = &ad5933_ring_postdisable, +}; + +static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev) +{ + indio_dev->buffer = iio_sw_rb_allocate(indio_dev); + if (!indio_dev->buffer) + return -ENOMEM; + + /* Effectively select the ring buffer implementation */ + indio_dev->buffer->access = &ring_sw_access_funcs; + + /* Ring buffer functions - here trigger setup related */ + indio_dev->buffer->setup_ops = &ad5933_ring_setup_ops; + + indio_dev->modes |= INDIO_BUFFER_HARDWARE; + + return 0; +} + +static void ad5933_work(struct work_struct *work) +{ + struct ad5933_state *st = container_of(work, + struct ad5933_state, work.work); + struct iio_dev *indio_dev = i2c_get_clientdata(st->client); + struct iio_buffer *ring = indio_dev->buffer; + signed short buf[2]; + unsigned char status; + + mutex_lock(&indio_dev->mlock); + if (st->state == AD5933_CTRL_INIT_START_FREQ) { + /* start sweep */ + ad5933_cmd(st, AD5933_CTRL_START_SWEEP); + st->state = AD5933_CTRL_START_SWEEP; + schedule_delayed_work(&st->work, st->poll_time_jiffies); + mutex_unlock(&indio_dev->mlock); + return; + } + + ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &status); + + if (status & AD5933_STAT_DATA_VALID) { + ad5933_i2c_read(st->client, + test_bit(1, ring->scan_mask) ? + AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA, + ring->scan_count * 2, (u8 *)buf); + + if (ring->scan_count == 2) { + buf[0] = be16_to_cpu(buf[0]); + buf[1] = be16_to_cpu(buf[1]); + } else { + buf[0] = be16_to_cpu(buf[0]); + } + /* save datum to the ring */ + ring->access->store_to(ring, (u8 *)buf, iio_get_time_ns()); + } else { + /* no data available - try again later */ + schedule_delayed_work(&st->work, st->poll_time_jiffies); + mutex_unlock(&indio_dev->mlock); + return; + } + + if (status & AD5933_STAT_SWEEP_DONE) { + /* last sample received - power down do nothing until + * the ring enable is toggled */ + ad5933_cmd(st, AD5933_CTRL_POWER_DOWN); + } else { + /* we just received a valid datum, move on to the next */ + ad5933_cmd(st, AD5933_CTRL_INC_FREQ); + schedule_delayed_work(&st->work, st->poll_time_jiffies); + } + + mutex_unlock(&indio_dev->mlock); +} + +static int __devinit ad5933_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret, voltage_uv = 0; + struct ad5933_platform_data *pdata = client->dev.platform_data; + struct ad5933_state *st; + struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + st->client = client; + + if (!pdata) + st->pdata = &ad5933_default_pdata; + else + st->pdata = pdata; + + st->reg = regulator_get(&client->dev, "vcc"); + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) + goto error_put_reg; + voltage_uv = regulator_get_voltage(st->reg); + } + + if (voltage_uv) + st->vref_mv = voltage_uv / 1000; + else + st->vref_mv = st->pdata->vref_mv; + + if (st->pdata->ext_clk_Hz) { + st->mclk_hz = st->pdata->ext_clk_Hz; + st->ctrl_lb = AD5933_CTRL_EXT_SYSCLK; + } else { + st->mclk_hz = AD5933_INT_OSC_FREQ_Hz; + st->ctrl_lb = AD5933_CTRL_INT_SYSCLK; + } + + ad5933_calc_out_ranges(st); + INIT_DELAYED_WORK(&st->work, ad5933_work); + st->poll_time_jiffies = msecs_to_jiffies(AD5933_POLL_TIME_ms); + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &ad5933_info; + indio_dev->name = id->name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ad5933_channels; + indio_dev->num_channels = 1; /* only register temp0_input */ + + ret = ad5933_register_ring_funcs_and_init(indio_dev); + if (ret) + goto error_disable_reg; + + /* skip temp0_input, register in0_(real|imag)_raw */ + ret = iio_buffer_register(indio_dev, &ad5933_channels[1], 2); + if (ret) + goto error_unreg_ring; + + /* enable both REAL and IMAG channels by default */ + iio_scan_mask_set(indio_dev->buffer, 0); + iio_scan_mask_set(indio_dev->buffer, 1); + + ret = ad5933_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_unreg_ring: + iio_sw_rb_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) +{ + 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)) { + regulator_disable(st->reg); + regulator_put(st->reg); + } + iio_free_device(indio_dev); + + return 0; +} + +static const struct i2c_device_id ad5933_id[] = { + { "ad5933", 0 }, + { "ad5934", 0 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, ad5933_id); + +static struct i2c_driver ad5933_driver = { + .driver = { + .name = "ad5933", + }, + .probe = ad5933_probe, + .remove = __devexit_p(ad5933_remove), + .id_table = ad5933_id, +}; + +static __init int ad5933_init(void) +{ + return i2c_add_driver(&ad5933_driver); +} +module_init(ad5933_init); + +static __exit void ad5933_exit(void) +{ + i2c_del_driver(&ad5933_driver); +} +module_exit(ad5933_exit); + +MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); +MODULE_DESCRIPTION("Analog Devices AD5933 Impedance Conv. Network Analyzer"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.h b/drivers/staging/iio/impedance-analyzer/ad5933.h new file mode 100644 index 0000000..b140e42 --- /dev/null +++ b/drivers/staging/iio/impedance-analyzer/ad5933.h @@ -0,0 +1,28 @@ +/* + * AD5933 AD5934 Impedance Converter, Network Analyzer + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#ifndef IIO_ADC_AD5933_H_ +#define IIO_ADC_AD5933_H_ + +/* + * TODO: struct ad5933_platform_data needs to go into include/linux/iio + */ + +/** + * struct ad5933_platform_data - platform specific data + * @ext_clk_Hz: the external clock frequency in Hz, if not set + * the driver uses the internal clock (16.776 MHz) + * @vref_mv: the external reference voltage in millivolt + */ + +struct ad5933_platform_data { + unsigned long ext_clk_Hz; + unsigned short vref_mv; +}; + +#endif /* IIO_ADC_AD5933_H_ */ diff --git a/drivers/staging/iio/imu/Kconfig b/drivers/staging/iio/imu/Kconfig index e0e0144..2c2f47d 100644 --- a/drivers/staging/iio/imu/Kconfig +++ b/drivers/staging/iio/imu/Kconfig @@ -1,15 +1,17 @@ # # IIO imu drivers configuration # -comment "Inertial measurement units" +menu "Inertial measurement units" config ADIS16400 tristate "Analog Devices ADIS16400 and similar IMU SPI driver" depends on SPI - select IIO_SW_RING if IIO_RING_BUFFER - select IIO_TRIGGER if IIO_RING_BUFFER + select IIO_SW_RING if IIO_BUFFER + select IIO_TRIGGER if IIO_BUFFER help - Say yes here to build support for Analog Devices adis16300, adis16350, - adis16354, adis16355, adis16360, adis16362, adis16364, adis16365, - adis16400 and adis16405 triaxial inertial sensors (adis16400 series - also have magnetometers). + 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 index d46a691..3400a13 100644 --- a/drivers/staging/iio/imu/Makefile +++ b/drivers/staging/iio/imu/Makefile @@ -3,5 +3,5 @@ # adis16400-y := adis16400_core.o -adis16400-$(CONFIG_IIO_RING_BUFFER) += adis16400_ring.o adis16400_trigger.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 index 1f8f0c6..f3546ee 100644 --- a/drivers/staging/iio/imu/adis16400.h +++ b/drivers/staging/iio/imu/adis16400.h @@ -184,7 +184,7 @@ int adis16400_set_irq(struct iio_dev *indio_dev, bool enable); #define ADIS16300_SCAN_INCLI_X 12 #define ADIS16300_SCAN_INCLI_Y 13 -#ifdef CONFIG_IIO_RING_BUFFER +#ifdef CONFIG_IIO_BUFFER void adis16400_remove_trigger(struct iio_dev *indio_dev); int adis16400_probe_trigger(struct iio_dev *indio_dev); @@ -196,7 +196,7 @@ ssize_t adis16400_read_data_from_ring(struct device *dev, int adis16400_configure_ring(struct iio_dev *indio_dev); void adis16400_unconfigure_ring(struct iio_dev *indio_dev); -#else /* CONFIG_IIO_RING_BUFFER */ +#else /* CONFIG_IIO_BUFFER */ static inline void adis16400_remove_trigger(struct iio_dev *indio_dev) { @@ -224,5 +224,5 @@ static inline void adis16400_unconfigure_ring(struct iio_dev *indio_dev) { } -#endif /* CONFIG_IIO_RING_BUFFER */ +#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 index a2c3b67..d082a37 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -16,7 +16,6 @@ #include <linux/interrupt.h> #include <linux/irq.h> -#include <linux/gpio.h> #include <linux/delay.h> #include <linux/mutex.h> #include <linux/device.h> @@ -25,21 +24,16 @@ #include <linux/slab.h> #include <linux/sysfs.h> #include <linux/list.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" -#include "../accel/accel.h" -#include "../adc/adc.h" -#include "../gyro/gyro.h" -#include "../magnetometer/magnet.h" - +#include "../buffer_generic.h" #include "adis16400.h" -#define DRIVER_NAME "adis16400" - enum adis16400_chip_variant { ADIS16300, + ADIS16334, ADIS16350, ADIS16360, ADIS16362, @@ -48,19 +42,12 @@ enum adis16400_chip_variant { ADIS16400, }; -static int adis16400_check_status(struct iio_dev *indio_dev); - -/* At the moment the spi framework doesn't allow global setting of cs_change. - * It's in the likely to be added comment at the top of spi.h. - * This means that use cannot be made of spi_write etc. - */ - /** * adis16400_spi_write_reg_8() - write single byte to a register * @dev: device associated with child of actual device (iio_dev or iio_trig) * @reg_address: the address of the register to be written * @val: the value to write - **/ + */ static int adis16400_spi_write_reg_8(struct iio_dev *indio_dev, u8 reg_address, u8 val) @@ -84,7 +71,10 @@ static int adis16400_spi_write_reg_8(struct iio_dev *indio_dev, * @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) @@ -126,6 +116,9 @@ static int adis16400_spi_write_reg_16(struct iio_dev *indio_dev, * @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, @@ -150,8 +143,6 @@ static int adis16400_spi_read_reg_16(struct iio_dev *indio_dev, mutex_lock(&st->buf_lock); st->tx[0] = ADIS16400_READ_REG(lower_reg_address); st->tx[1] = 0; - st->tx[2] = 0; - st->tx[3] = 0; spi_message_init(&msg); spi_message_add_tail(&xfers[0], &msg); @@ -240,23 +231,26 @@ static ssize_t adis16400_write_reset(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + bool val; + int ret; - if (len < 1) - return -1; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return adis16400_reset(indio_dev); + ret = strtobool(buf, &val); + if (ret < 0) + return ret; + if (val) { + ret = adis16400_reset(dev_get_drvdata(dev)); + if (ret < 0) + return ret; } - return -1; + + 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; @@ -289,24 +283,6 @@ static int adis16400_stop_device(struct iio_dev *indio_dev) 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_check_status(struct iio_dev *indio_dev) { u16 status; @@ -356,11 +332,28 @@ 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 device *dev = &indio_dev->dev; struct adis16400_state *st = iio_priv(indio_dev); /* use low spi speed for init */ @@ -368,29 +361,26 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev) st->us->mode = SPI_MODE_3; spi_setup(st->us); - /* Disable IRQ */ ret = adis16400_set_irq(indio_dev, false); if (ret) { - dev_err(dev, "disable irq failed"); + dev_err(&indio_dev->dev, "disable irq failed"); goto err_ret; } - /* Do self test */ ret = adis16400_self_test(indio_dev); if (ret) { - dev_err(dev, "self test failure"); + dev_err(&indio_dev->dev, "self test failure"); goto err_ret; } - /* Read status register to check the result */ ret = adis16400_check_status(indio_dev); if (ret) { adis16400_reset(indio_dev); - dev_err(dev, "device not playing ball -> reset"); + dev_err(&indio_dev->dev, "device not playing ball -> reset"); msleep(ADIS16400_STARTUP_DELAY); ret = adis16400_check_status(indio_dev); if (ret) { - dev_err(dev, "giving up"); + dev_err(&indio_dev->dev, "giving up"); goto err_ret; } } @@ -401,10 +391,11 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev) goto err_ret; if ((prod_id & 0xF000) != st->variant->product_id) - dev_warn(dev, "incorrect id"); + dev_warn(&indio_dev->dev, "incorrect id"); - printk(KERN_INFO DRIVER_NAME ": prod_id 0x%04x at CS%d (irq %d)\n", - prod_id, st->us->chip_select, st->us->irq); + 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, @@ -414,15 +405,13 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev) spi_setup(st->us); } - err_ret: - return ret; } static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - adis16400_read_frequency, - adis16400_write_frequency); + adis16400_read_frequency, + adis16400_write_frequency); static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16400_write_reset, 0); @@ -447,23 +436,23 @@ enum adis16400_chan { }; static u8 adis16400_addresses[17][2] = { - [in_supply] = { ADIS16400_SUPPLY_OUT, 0 }, + [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, 0 }, - [magn_y] = { ADIS16400_YMAGN_OUT, 0 }, - [magn_z] = { ADIS16400_ZMAGN_OUT, 0 }, - [temp] = { ADIS16400_TEMP_OUT, 0 }, + [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, 0 }, - [incli_x] = { ADIS16300_PITCH_OUT, 0 }, - [incli_y] = { ADIS16300_ROLL_OUT, 0 } + [in1] = { ADIS16400_AUX_ADC }, + [incli_x] = { ADIS16300_PITCH_OUT }, + [incli_y] = { ADIS16300_ROLL_OUT } }; static int adis16400_write_raw(struct iio_dev *indio_dev, @@ -473,6 +462,7 @@ static int adis16400_write_raw(struct iio_dev *indio_dev, long mask) { int ret; + switch (mask) { case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): mutex_lock(&indio_dev->mlock); @@ -493,9 +483,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, long mask) { struct adis16400_state *st = iio_priv(indio_dev); - int ret; + int ret, shift; s16 val16; - int shift; switch (mask) { case 0: @@ -518,11 +507,11 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, case (1 << IIO_CHAN_INFO_SCALE_SHARED): case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): switch (chan->type) { - case IIO_GYRO: + case IIO_ANGL_VEL: *val = 0; *val2 = st->variant->gyro_scale_micro; return IIO_VAL_INT_PLUS_MICRO; - case IIO_IN: + case IIO_VOLTAGE: *val = 0; if (chan->channel == 0) *val2 = 2418; @@ -566,135 +555,371 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, } static struct iio_chan_spec adis16400_channels[] = { - IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - in_supply, ADIS16400_SCAN_SUPPLY, - IIO_ST('u', 14, 16, 0), 0), - IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_X, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - gyro_x, ADIS16400_SCAN_GYRO_X, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_Y, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - gyro_y, ADIS16400_SCAN_GYRO_Y, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_Z, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - gyro_z, ADIS16400_SCAN_GYRO_Z, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - accel_x, ADIS16400_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - accel_y, ADIS16400_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - accel_z, ADIS16400_SCAN_ACC_Z, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_MAGN, 1, 0, 0, NULL, 0, IIO_MOD_X, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - magn_x, ADIS16400_SCAN_MAGN_X, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_MAGN, 1, 0, 0, NULL, 0, IIO_MOD_Y, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - magn_y, ADIS16400_SCAN_MAGN_Y, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_MAGN, 1, 0, 0, NULL, 0, IIO_MOD_Z, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - magn_z, ADIS16400_SCAN_MAGN_Z, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - temp, ADIS16400_SCAN_TEMP, IIO_ST('s', 12, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - in1, ADIS16400_SCAN_ADC_0, IIO_ST('s', 12, 16, 0), 0), + { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .extend_name = "supply", + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .address = temp, + .scan_index = ADIS16400_SCAN_TEMP, + .scan_type = IIO_ST('s', 12, 16, 0), + }, { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 1, + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .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[] = { - IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - in_supply, ADIS16400_SCAN_SUPPLY, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_X, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - gyro_x, ADIS16400_SCAN_GYRO_X, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_Y, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - gyro_y, ADIS16400_SCAN_GYRO_Y, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_Z, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - gyro_z, ADIS16400_SCAN_GYRO_Z, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - accel_x, ADIS16400_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - accel_y, ADIS16400_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - accel_z, ADIS16400_SCAN_ACC_Z, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_TEMP, 0, 1, 0, "x", 0, 0, - (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - temp0, ADIS16350_SCAN_TEMP_X, IIO_ST('s', 12, 16, 0), 0), - IIO_CHAN(IIO_TEMP, 0, 1, 0, "y", 1, 0, - (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - temp1, ADIS16350_SCAN_TEMP_Y, IIO_ST('s', 12, 16, 0), 0), - IIO_CHAN(IIO_TEMP, 0, 1, 0, "z", 2, 0, - (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - temp2, ADIS16350_SCAN_TEMP_Z, IIO_ST('s', 12, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - in1, ADIS16350_SCAN_ADC_0, IIO_ST('s', 12, 16, 0), 0), + { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .extend_name = "supply", + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .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 = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .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 = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .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 = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .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[] = { - IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - in_supply, ADIS16400_SCAN_SUPPLY, IIO_ST('u', 12, 16, 0), 0), - IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_X, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - gyro_x, ADIS16400_SCAN_GYRO_X, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - accel_x, ADIS16400_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - accel_y, ADIS16400_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - accel_z, ADIS16400_SCAN_ACC_Z, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - temp, ADIS16400_SCAN_TEMP, IIO_ST('s', 12, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - in1, ADIS16350_SCAN_ADC_0, IIO_ST('s', 12, 16, 0), 0), - IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - incli_x, ADIS16300_SCAN_INCLI_X, IIO_ST('s', 13, 16, 0), 0), - IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - incli_y, ADIS16300_SCAN_INCLI_Y, IIO_ST('s', 13, 16, 0), 0), + { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .extend_name = "supply", + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .address = temp, + .scan_index = ADIS16400_SCAN_TEMP, + .scan_type = IIO_ST('s', 12, 16, 0), + }, { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 1, + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .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 = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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 = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | + (1 << IIO_CHAN_INFO_SCALE_SHARED), + .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, @@ -719,6 +944,16 @@ static struct adis16400_chip_info adis16400_chips[] = { (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), @@ -783,7 +1018,7 @@ static const struct iio_info adis16400_info = { static int __devinit adis16400_probe(struct spi_device *spi) { - int ret, regdone = 0; + int ret; struct adis16400_state *st; struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); if (indio_dev == NULL) { @@ -810,20 +1045,15 @@ static int __devinit adis16400_probe(struct spi_device *spi) if (ret) goto error_free_dev; - ret = iio_device_register(indio_dev); - if (ret) - goto error_unreg_ring_funcs; - regdone = 1; - - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - st->variant->channels, - st->variant->num_channels); + 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 && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) { + if (spi->irq) { ret = adis16400_probe_trigger(indio_dev); if (ret) goto error_uninitialize_ring; @@ -833,20 +1063,21 @@ static int __devinit adis16400_probe(struct spi_device *spi) 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_RING_TRIGGERED) + if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) adis16400_remove_trigger(indio_dev); error_uninitialize_ring: - iio_ring_buffer_unregister(indio_dev->ring); + iio_buffer_unregister(indio_dev); error_unreg_ring_funcs: adis16400_unconfigure_ring(indio_dev); error_free_dev: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ret; } @@ -857,14 +1088,15 @@ 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_ring_buffer_unregister(indio_dev->ring); + iio_buffer_unregister(indio_dev); adis16400_unconfigure_ring(indio_dev); - iio_device_unregister(indio_dev); + iio_free_device(indio_dev); return 0; @@ -874,6 +1106,7 @@ err_ret: static const struct spi_device_id adis16400_id[] = { {"adis16300", ADIS16300}, + {"adis16334", ADIS16334}, {"adis16350", ADIS16350}, {"adis16354", ADIS16350}, {"adis16355", ADIS16350}, diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c index 3612373..c368245 100644 --- a/drivers/staging/iio/imu/adis16400_ring.c +++ b/drivers/staging/iio/imu/adis16400_ring.c @@ -1,21 +1,13 @@ #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/workqueue.h> #include <linux/mutex.h> -#include <linux/device.h> #include <linux/kernel.h> #include <linux/spi/spi.h> #include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/list.h> #include <linux/bitops.h> #include "../iio.h" -#include "../sysfs.h" #include "../ring_sw.h" -#include "../accel/accel.h" -#include "../trigger.h" +#include "../trigger_consumer.h" #include "adis16400.h" /** @@ -87,13 +79,13 @@ static int adis16350_spi_read_all(struct device *dev, u8 *rx) int i, j = 0, ret; struct spi_transfer *xfers; - xfers = kzalloc(sizeof(*xfers)*indio_dev->ring->scan_count + 1, + xfers = kzalloc(sizeof(*xfers)*indio_dev->buffer->scan_count + 1, GFP_KERNEL); if (xfers == NULL) return -ENOMEM; for (i = 0; i < ARRAY_SIZE(read_all_tx_array); i++) - if (indio_dev->ring->scan_mask & (1 << i)) { + if (test_bit(i, indio_dev->buffer->scan_mask)) { xfers[j].tx_buf = &read_all_tx_array[i]; xfers[j].bits_per_word = 16; xfers[j].len = 2; @@ -104,7 +96,7 @@ static int adis16350_spi_read_all(struct device *dev, u8 *rx) xfers[j].len = 2; spi_message_init(&msg); - for (j = 0; j < indio_dev->ring->scan_count + 1; j++) + for (j = 0; j < indio_dev->buffer->scan_count + 1; j++) spi_message_add_tail(&xfers[j], &msg); ret = spi_sync(st->us, &msg); @@ -119,13 +111,14 @@ static int adis16350_spi_read_all(struct device *dev, u8 *rx) static irqreturn_t adis16400_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->private_data; + struct iio_dev *indio_dev = pf->indio_dev; struct adis16400_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; + 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); - unsigned long mask = ring->scan_mask; + /* Asumption that long is enough for maximum channels */ + unsigned long mask = *ring->scan_mask; data = kmalloc(datasize , GFP_KERNEL); if (data == NULL) { @@ -144,7 +137,7 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p) ret = adis16400_spi_read_burst(&indio_dev->dev, st->rx); if (ret < 0) goto err; - for (; i < indio_dev->ring->scan_count; i++) { + for (; i < indio_dev->buffer->scan_count; i++) { j = __ffs(mask); mask &= ~(1 << j); data[i] = be16_to_cpup( @@ -155,7 +148,7 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p) /* 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->ring, (u8 *) data, pf->timestamp); + ring->access->store_to(indio_dev->buffer, (u8 *) data, pf->timestamp); iio_trigger_notify_done(indio_dev->trig); @@ -170,36 +163,32 @@ err: void adis16400_unconfigure_ring(struct iio_dev *indio_dev) { iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); } -static const struct iio_ring_setup_ops adis16400_ring_setup_ops = { - .preenable = &iio_sw_ring_preenable, - .postenable = &iio_triggered_ring_postenable, - .predisable = &iio_triggered_ring_predisable, +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 adis16400_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring; + struct iio_buffer *ring; ring = iio_sw_rb_allocate(indio_dev); if (!ring) { ret = -ENOMEM; return ret; } - indio_dev->ring = ring; + indio_dev->buffer = ring; /* Effectively select the ring buffer implementation */ ring->access = &ring_sw_access_funcs; ring->bpe = 2; ring->scan_timestamp = true; ring->setup_ops = &adis16400_ring_setup_ops; ring->owner = THIS_MODULE; - /* Set default scan mode */ - ring->scan_mask = st->variant->default_scan_mask; - ring->scan_count = hweight_long(st->variant->default_scan_mask); indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &adis16400_trigger_handler, @@ -213,9 +202,9 @@ int adis16400_configure_ring(struct iio_dev *indio_dev) goto error_iio_sw_rb_free; } - indio_dev->modes |= INDIO_RING_TRIGGERED; + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; return 0; error_iio_sw_rb_free: - iio_sw_rb_free(indio_dev->ring); + 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 index c6ec41a..bf99153 100644 --- a/drivers/staging/iio/imu/adis16400_trigger.c +++ b/drivers/staging/iio/imu/adis16400_trigger.c @@ -1,14 +1,8 @@ #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/mutex.h> -#include <linux/device.h> #include <linux/kernel.h> -#include <linux/sysfs.h> -#include <linux/list.h> #include <linux/spi/spi.h> #include "../iio.h" -#include "../sysfs.h" #include "../trigger.h" #include "adis16400.h" @@ -24,13 +18,18 @@ static int adis16400_data_rdy_trigger_set_state(struct iio_trigger *trig, return adis16400_set_irq(indio_dev, state); } +static const struct iio_trigger_ops adis16400_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = &adis16400_data_rdy_trigger_set_state, +}; + int adis16400_probe_trigger(struct iio_dev *indio_dev) { int ret; struct adis16400_state *st = iio_priv(indio_dev); st->trig = iio_allocate_trigger("%s-dev%d", - spi_get_device_id(st->us)->name, + indio_dev->name, indio_dev->id); if (st->trig == NULL) { ret = -ENOMEM; @@ -45,9 +44,8 @@ int adis16400_probe_trigger(struct iio_dev *indio_dev) if (ret) goto error_free_trig; st->trig->dev.parent = &st->us->dev; - st->trig->owner = THIS_MODULE; st->trig->private_data = indio_dev; - st->trig->set_trigger_state = &adis16400_data_rdy_trigger_set_state; + st->trig->ops = &adis16400_trigger_ops; ret = iio_trigger_register(st->trig); /* select default trigger */ diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c new file mode 100644 index 0000000..6dd5d7d --- /dev/null +++ b/drivers/staging/iio/industrialio-buffer.c @@ -0,0 +1,635 @@ +/* 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/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_generic.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->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; +} + +int iio_chrdev_buffer_open(struct iio_dev *indio_dev) +{ + struct iio_buffer *rb = indio_dev->buffer; + if (!rb) + return -EINVAL; + if (rb->access->mark_in_use) + rb->access->mark_in_use(rb); + return 0; +} + +void iio_chrdev_buffer_release(struct iio_dev *indio_dev) +{ + struct iio_buffer *rb = indio_dev->buffer; + + clear_bit(IIO_BUSY_BIT_POS, &rb->flags); + if (rb->access->unmark_in_use) + rb->access->unmark_in_use(rb); +} + +void iio_buffer_init(struct iio_buffer *buffer, struct iio_dev *indio_dev) +{ + buffer->indio_dev = indio_dev; + 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 = iio_scan_mask_query(indio_dev->buffer, + to_iio_dev_attr(attr)->address); + if (ret < 0) + return ret; + return sprintf(buf, "%d\n", ret); +} + +static int iio_scan_mask_clear(struct iio_buffer *buffer, int bit) +{ + clear_bit(bit, buffer->scan_mask); + buffer->scan_count--; + return 0; +} + +static ssize_t iio_scan_el_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + int ret = 0; + bool state; + struct iio_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 (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { + ret = -EBUSY; + goto error_ret; + } + ret = iio_scan_mask_query(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(buffer, this_attr->address); + if (ret) + goto error_ret; + } + +error_ret: + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; + +} + +static ssize_t iio_scan_el_ts_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_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 (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { + 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 (indio_dev->masklength && buffer->scan_mask == NULL) { + buffer->scan_mask + = kzalloc(sizeof(*buffer->scan_mask)* + BITS_TO_LONGS(indio_dev->masklength), + 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 + = kzalloc(sizeof(buffer->scan_el_group.attrs[0])* + (attrcount + 1), + 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; + + if (buffer->access->set_length) { + buffer->access->set_length(buffer, val); + if (buffer->access->mark_param_change) + buffer->access->mark_param_change(buffer); + } + + return len; +} +EXPORT_SYMBOL(iio_buffer_write_length); + +ssize_t iio_buffer_read_bytes_per_datum(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_bytes_per_datum) + return sprintf(buf, "%d\n", + buffer->access->get_bytes_per_datum(buffer)); + + return 0; +} +EXPORT_SYMBOL(iio_buffer_read_bytes_per_datum); + +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 = !!(previous_mode & INDIO_ALL_BUFFER_MODES); + if (current_state == requested_state) { + printk(KERN_INFO "iio-buffer, current state requested again\n"); + goto done; + } + if (requested_state) { + if (buffer->setup_ops->preenable) { + ret = buffer->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; + } + } + if (buffer->access->mark_in_use) + buffer->access->mark_in_use(buffer); + /* 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; + if (buffer->access->unmark_in_use) + buffer->access->unmark_in_use(buffer); + 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 (buffer->setup_ops->postenable) { + ret = buffer->setup_ops->postenable(indio_dev); + if (ret) { + printk(KERN_INFO + "Buffer not started:" + "postenable failed\n"); + if (buffer->access->unmark_in_use) + buffer->access->unmark_in_use(buffer); + indio_dev->currentmode = previous_mode; + if (buffer->setup_ops->postdisable) + buffer->setup_ops-> + postdisable(indio_dev); + goto error_ret; + } + } + } else { + if (buffer->setup_ops->predisable) { + ret = buffer->setup_ops->predisable(indio_dev); + if (ret) + goto error_ret; + } + if (buffer->access->unmark_in_use) + buffer->access->unmark_in_use(buffer); + indio_dev->currentmode = INDIO_DIRECT_MODE; + if (buffer->setup_ops->postdisable) { + ret = buffer->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", !!(indio_dev->currentmode + & INDIO_ALL_BUFFER_MODES)); +} +EXPORT_SYMBOL(iio_buffer_show_enable); + +int iio_sw_buffer_preenable(struct iio_dev *indio_dev) +{ + struct iio_buffer *buffer = indio_dev->buffer; + size_t size; + dev_dbg(&indio_dev->dev, "%s\n", __func__); + /* Check if there are any scan elements enabled, if not fail*/ + if (!(buffer->scan_count || buffer->scan_timestamp)) + return -EINVAL; + if (buffer->scan_timestamp) + if (buffer->scan_count) + /* Timestamp (aligned to s64) and data */ + size = (((buffer->scan_count * buffer->bpe) + + sizeof(s64) - 1) + & ~(sizeof(s64) - 1)) + + sizeof(s64); + else /* Timestamp only */ + size = sizeof(s64); + else /* Data only */ + size = buffer->scan_count * buffer->bpe; + buffer->access->set_bytes_per_datum(buffer, size); + + return 0; +} +EXPORT_SYMBOL(iio_sw_buffer_preenable); + + +/* 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; +} + +/** + * 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_buffer *buffer, int bit) +{ + struct iio_dev *indio_dev = buffer->indio_dev; + 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); + buffer->scan_count++; + + kfree(trialmask); + + return 0; +}; +EXPORT_SYMBOL_GPL(iio_scan_mask_set); + +int iio_scan_mask_query(struct iio_buffer *buffer, int bit) +{ + struct iio_dev *indio_dev = buffer->indio_dev; + long *mask; + + if (bit > indio_dev->masklength) + return -EINVAL; + + if (!buffer->scan_mask) + return 0; + if (indio_dev->available_scan_masks) + mask = iio_scan_mask_match(indio_dev->available_scan_masks, + indio_dev->masklength, + buffer->scan_mask); + else + mask = buffer->scan_mask; + if (!mask) + return 0; + + return test_bit(bit, mask); +}; +EXPORT_SYMBOL_GPL(iio_scan_mask_query); diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index 19819e7..326e967 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -21,21 +21,17 @@ #include <linux/wait.h> #include <linux/cdev.h> #include <linux/slab.h> +#include <linux/anon_inodes.h> #include "iio.h" -#include "trigger_consumer.h" +#include "iio_core.h" +#include "iio_core_trigger.h" +#include "chrdev.h" +#include "sysfs.h" -#define IIO_ID_PREFIX "device" -#define IIO_ID_FORMAT IIO_ID_PREFIX "%d" - -/* IDR to assign each registered device a unique id*/ +/* IDA to assign each registered device a unique id*/ static DEFINE_IDA(iio_ida); -/* IDR to allocate character device minor numbers */ -static DEFINE_IDA(iio_chrdev_ida); -/* Lock used to protect both of the above */ -static DEFINE_SPINLOCK(iio_ida_lock); -dev_t iio_devt; -EXPORT_SYMBOL(iio_devt); +static dev_t iio_devt; #define IIO_DEV_MAX 256 struct bus_type iio_bus_type = { @@ -43,14 +39,22 @@ struct bus_type iio_bus_type = { }; EXPORT_SYMBOL(iio_bus_type); -static const char * const iio_chan_type_name_spec_shared[] = { - [IIO_IN] = "in", - [IIO_OUT] = "out", +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_IN_DIFF] = "in-in", - [IIO_GYRO] = "gyro", + [IIO_ANGL_VEL] = "anglvel", [IIO_MAGN] = "magn", [IIO_LIGHT] = "illuminance", [IIO_INTENSITY] = "intensity", @@ -60,21 +64,15 @@ static const char * const iio_chan_type_name_spec_shared[] = { [IIO_ROT] = "rot", [IIO_ANGL] = "angl", [IIO_TIMESTAMP] = "timestamp", + [IIO_CAPACITANCE] = "capacitance", }; -static const char * const iio_chan_type_name_spec_complex[] = { - [IIO_IN_DIFF] = "in%d-in%d", -}; - -static const char * const iio_modifier_names_light[] = { - [IIO_MOD_LIGHT_BOTH] = "both", - [IIO_MOD_LIGHT_IR] = "ir", -}; - -static const char * const iio_modifier_names_axial[] = { +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 */ @@ -85,21 +83,51 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_CALIBBIAS_SHARED/2] = "calibbias", [IIO_CHAN_INFO_PEAK_SHARED/2] = "peak_raw", [IIO_CHAN_INFO_PEAK_SCALE_SHARED/2] = "peak_scale", + [IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED/2] + = "quadrature_correction_raw", + [IIO_CHAN_INFO_AVERAGE_RAW_SHARED/2] = "mean_raw", }; -int iio_push_event(struct iio_dev *dev_info, - int ev_line, - int ev_code, - s64 timestamp) +/** + * 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 - = &dev_info->event_interfaces[ev_line]; + 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->handler.flags)) { + 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; @@ -125,7 +153,6 @@ error_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, @@ -135,7 +162,6 @@ ssize_t iio_read_const_attr(struct device *dev, } EXPORT_SYMBOL(iio_read_const_attr); - static ssize_t iio_event_chrdev_read(struct file *filep, char __user *buf, size_t count, @@ -187,12 +213,11 @@ error_ret: static int iio_event_chrdev_release(struct inode *inode, struct file *filep) { - struct iio_handler *hand = iio_cdev_to_handler(inode->i_cdev); - struct iio_event_interface *ev_int = hand->private; + 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->handler.flags); + 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 @@ -202,23 +227,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep) list_del(&el->list); kfree(el); } - mutex_unlock(&ev_int->event_list_lock); - - return 0; -} - -static int iio_event_chrdev_open(struct inode *inode, struct file *filep) -{ - struct iio_handler *hand = iio_cdev_to_handler(inode->i_cdev); - struct iio_event_interface *ev_int = hand->private; - - mutex_lock(&ev_int->event_list_lock); - if (test_and_set_bit(IIO_BUSY_BIT_POS, &hand->flags)) { - fops_put(filep->f_op); - mutex_unlock(&ev_int->event_list_lock); - return -EBUSY; - } - filep->private_data = hand->private; + ev_int->current_events = 0; mutex_unlock(&ev_int->event_list_lock); return 0; @@ -227,124 +236,25 @@ static int iio_event_chrdev_open(struct inode *inode, struct file *filep) static const struct file_operations iio_event_chrdev_fileops = { .read = iio_event_chrdev_read, .release = iio_event_chrdev_release, - .open = iio_event_chrdev_open, .owner = THIS_MODULE, .llseek = noop_llseek, }; -static void iio_event_dev_release(struct device *dev) +static int iio_event_getfd(struct iio_dev *indio_dev) { - struct iio_event_interface *ev_int - = container_of(dev, struct iio_event_interface, dev); - cdev_del(&ev_int->handler.chrdev); - iio_device_free_chrdev_minor(MINOR(dev->devt)); -}; - -static struct device_type iio_event_type = { - .release = iio_event_dev_release, -}; - -int iio_device_get_chrdev_minor(void) -{ - int ret, val; - -ida_again: - if (unlikely(ida_pre_get(&iio_chrdev_ida, GFP_KERNEL) == 0)) - return -ENOMEM; - spin_lock(&iio_ida_lock); - ret = ida_get_new(&iio_chrdev_ida, &val); - spin_unlock(&iio_ida_lock); - if (unlikely(ret == -EAGAIN)) - goto ida_again; - else if (unlikely(ret)) - return ret; - if (val > IIO_DEV_MAX) - return -ENOMEM; - return val; -} - -void iio_device_free_chrdev_minor(int val) -{ - spin_lock(&iio_ida_lock); - ida_remove(&iio_chrdev_ida, val); - spin_unlock(&iio_ida_lock); -} + if (indio_dev->event_interface == NULL) + return -ENODEV; -static int iio_setup_ev_int(struct iio_event_interface *ev_int, - const char *dev_name, - int index, - struct module *owner, - struct device *dev) -{ - int ret, minor; - - ev_int->dev.bus = &iio_bus_type; - ev_int->dev.parent = dev; - ev_int->dev.type = &iio_event_type; - device_initialize(&ev_int->dev); - - minor = iio_device_get_chrdev_minor(); - if (minor < 0) { - ret = minor; - goto error_device_put; + mutex_lock(&indio_dev->event_interface->event_list_lock); + if (test_and_set_bit(IIO_BUSY_BIT_POS, + &indio_dev->event_interface->flags)) { + mutex_unlock(&indio_dev->event_interface->event_list_lock); + return -EBUSY; } - ev_int->dev.devt = MKDEV(MAJOR(iio_devt), minor); - dev_set_name(&ev_int->dev, "%s:event%d", dev_name, index); - - ret = device_add(&ev_int->dev); - if (ret) - goto error_free_minor; - - cdev_init(&ev_int->handler.chrdev, &iio_event_chrdev_fileops); - ev_int->handler.chrdev.owner = owner; - - 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); - ev_int->handler.private = ev_int; - ev_int->handler.flags = 0; - - ret = cdev_add(&ev_int->handler.chrdev, ev_int->dev.devt, 1); - if (ret) - goto error_unreg_device; - - return 0; - -error_unreg_device: - device_unregister(&ev_int->dev); -error_free_minor: - iio_device_free_chrdev_minor(minor); -error_device_put: - put_device(&ev_int->dev); - - return ret; -} - -static void iio_free_ev_int(struct iio_event_interface *ev_int) -{ - device_unregister(&ev_int->dev); - put_device(&ev_int->dev); -} - -static int __init iio_dev_init(void) -{ - int err; - - err = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio"); - if (err < 0) - printk(KERN_ERR "%s: failed to allocate char dev region\n", - __FILE__); - - return err; -} - -static void __exit iio_dev_exit(void) -{ - if (iio_devt) - unregister_chrdev_region(iio_devt, IIO_DEV_MAX); + mutex_unlock(&indio_dev->event_interface->event_list_lock); + return anon_inode_getfd("iio:event", + &iio_event_chrdev_fileops, + indio_dev->event_interface, O_RDONLY); } static int __init iio_init(void) @@ -360,9 +270,12 @@ static int __init iio_init(void) goto error_nothing; } - ret = iio_dev_init(); - if (ret < 0) + ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio"); + if (ret < 0) { + printk(KERN_ERR "%s: failed to allocate char dev region\n", + __FILE__); goto error_unregister_bus_type; + } return 0; @@ -374,7 +287,8 @@ error_nothing: static void __exit iio_exit(void) { - iio_dev_exit(); + if (iio_devt) + unregister_chrdev_region(iio_devt, IIO_DEV_MAX); bus_unregister(&iio_bus_type); } @@ -476,54 +390,7 @@ static ssize_t iio_write_channel_info(struct device *dev, return len; } -static int __iio_build_postfix(struct iio_chan_spec const *chan, - bool generic, - const char *postfix, - char **result) -{ - char *all_post; - /* 3 options - generic, extend_name, modified - if generic, extend_name - * and modified cannot apply.*/ - - if (generic || (!chan->modified && !chan->extend_name)) { - all_post = kasprintf(GFP_KERNEL, "%s", postfix); - } else if (chan->modified) { - const char *intermediate; - switch (chan->type) { - case IIO_INTENSITY: - intermediate - = iio_modifier_names_light[chan->channel2]; - break; - case IIO_ACCEL: - case IIO_GYRO: - case IIO_MAGN: - case IIO_INCLI: - case IIO_ROT: - case IIO_ANGL: - intermediate - = iio_modifier_names_axial[chan->channel2]; - break; - default: - return -EINVAL; - } - if (chan->extend_name) - all_post = kasprintf(GFP_KERNEL, "%s_%s_%s", - intermediate, - chan->extend_name, - postfix); - else - all_post = kasprintf(GFP_KERNEL, "%s_%s", - intermediate, - postfix); - } else - all_post = kasprintf(GFP_KERNEL, "%s_%s", chan->extend_name, - postfix); - if (all_post == NULL) - return -ENOMEM; - *result = all_post; - return 0; -} - +static int __iio_device_attr_init(struct device_attribute *dev_attr, const char *postfix, struct iio_chan_spec const *chan, @@ -539,28 +406,77 @@ int __iio_device_attr_init(struct device_attribute *dev_attr, int ret; char *name_format, *full_postfix; sysfs_attr_init(&dev_attr->attr); - ret = __iio_build_postfix(chan, generic, postfix, &full_postfix); - if (ret) - goto error_ret; - /* Special case for types that uses both channel numbers in naming */ - if (chan->type == IIO_IN_DIFF && !generic) - name_format - = kasprintf(GFP_KERNEL, "%s_%s", - iio_chan_type_name_spec_complex[chan->type], - full_postfix); - else if (generic || !chan->indexed) - name_format - = kasprintf(GFP_KERNEL, "%s_%s", - iio_chan_type_name_spec_shared[chan->type], - full_postfix); - else - name_format - = kasprintf(GFP_KERNEL, "%s%d_%s", - iio_chan_type_name_spec_shared[chan->type], - chan->channel, - full_postfix); + /* Build up postfix of <extend_name>_<modifier>_postfix */ + if (chan->modified) { + 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; @@ -596,13 +512,12 @@ error_ret: return ret; } -void __iio_device_attr_deinit(struct device_attribute *dev_attr) +static void __iio_device_attr_deinit(struct device_attribute *dev_attr) { kfree(dev_attr->attr.name); } int __iio_add_chan_devattr(const char *postfix, - const char *group, struct iio_chan_spec const *chan, ssize_t (*readfunc)(struct device *dev, struct device_attribute *attr, @@ -611,7 +526,7 @@ int __iio_add_chan_devattr(const char *postfix, struct device_attribute *attr, const char *buf, size_t len), - int mask, + u64 mask, bool generic, struct device *dev, struct list_head *attr_list) @@ -640,12 +555,6 @@ int __iio_add_chan_devattr(const char *postfix, ret = -EBUSY; goto error_device_attr_deinit; } - - ret = sysfs_add_file_to_group(&dev->kobj, - &iio_attr->dev_attr.attr, group); - if (ret < 0) - goto error_device_attr_deinit; - list_add(&iio_attr->l, attr_list); return 0; @@ -658,59 +567,52 @@ error_ret: return ret; } -static int iio_device_add_channel_sysfs(struct iio_dev *dev_info, +static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, struct iio_chan_spec const *chan) { - int ret, i; - + int ret, i, attrcount = 0; if (chan->channel < 0) return 0; - if (chan->processed_val) - ret = __iio_add_chan_devattr("input", NULL, chan, - &iio_read_channel_info, - NULL, - 0, - 0, - &dev_info->dev, - &dev_info->channel_attr_list); - else - ret = __iio_add_chan_devattr("raw", NULL, chan, - &iio_read_channel_info, - (chan->type == IIO_OUT ? - &iio_write_channel_info : NULL), - 0, - 0, - &dev_info->dev, - &dev_info->channel_attr_list); + + 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], - NULL, chan, + chan, &iio_read_channel_info, &iio_write_channel_info, (1 << i), !(i%2), - &dev_info->dev, - &dev_info->channel_attr_list); + &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 *dev_info, +static void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev, struct iio_dev_attr *p) { - sysfs_remove_file_from_group(&dev_info->dev.kobj, - &p->dev_attr.attr, NULL); kfree(p->dev_attr.attr.name); kfree(p); } @@ -725,107 +627,91 @@ static ssize_t iio_show_dev_name(struct device *dev, static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL); -static int iio_device_register_sysfs(struct iio_dev *dev_info) +static int iio_device_register_sysfs(struct iio_dev *indio_dev) { - int i, ret = 0; + int i, ret = 0, attrcount, attrn, attrcount_orig = 0; struct iio_dev_attr *p, *n; + struct attribute **attr; - if (dev_info->info->attrs) { - ret = sysfs_create_group(&dev_info->dev.kobj, - dev_info->info->attrs); - if (ret) { - dev_err(dev_info->dev.parent, - "Failed to register sysfs hooks\n"); - goto error_ret; - } + /* 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(&dev_info->channel_attr_list); - if (dev_info->channels) - for (i = 0; i < dev_info->num_channels; i++) { - ret = iio_device_add_channel_sysfs(dev_info, - &dev_info + 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 (dev_info->name) { - ret = sysfs_add_file_to_group(&dev_info->dev.kobj, - &dev_attr_name.attr, - NULL); - if (ret) - goto error_clear_attrs; + + if (indio_dev->name) + attrcount++; + + indio_dev->chan_attr_group.attrs + = kzalloc(sizeof(indio_dev->chan_attr_group.attrs[0])* + (attrcount + 1), + 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, - &dev_info->channel_attr_list, l) { + &indio_dev->channel_attr_list, l) { list_del(&p->l); - iio_device_remove_and_free_read_attr(dev_info, p); + iio_device_remove_and_free_read_attr(indio_dev, p); } - if (dev_info->info->attrs) - sysfs_remove_group(&dev_info->dev.kobj, dev_info->info->attrs); -error_ret: - return ret; + return ret; } -static void iio_device_unregister_sysfs(struct iio_dev *dev_info) +static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) { struct iio_dev_attr *p, *n; - if (dev_info->name) - sysfs_remove_file_from_group(&dev_info->dev.kobj, - &dev_attr_name.attr, - NULL); - list_for_each_entry_safe(p, n, &dev_info->channel_attr_list, l) { + + list_for_each_entry_safe(p, n, &indio_dev->channel_attr_list, l) { list_del(&p->l); - iio_device_remove_and_free_read_attr(dev_info, p); + iio_device_remove_and_free_read_attr(indio_dev, p); } - - if (dev_info->info->attrs) - sysfs_remove_group(&dev_info->dev.kobj, dev_info->info->attrs); -} - -/* Return a negative errno on failure */ -int iio_get_new_ida_val(struct ida *this_ida) -{ - int ret; - int val; - -ida_again: - if (unlikely(ida_pre_get(this_ida, GFP_KERNEL) == 0)) - return -ENOMEM; - - spin_lock(&iio_ida_lock); - ret = ida_get_new(this_ida, &val); - spin_unlock(&iio_ida_lock); - if (unlikely(ret == -EAGAIN)) - goto ida_again; - else if (unlikely(ret)) - return ret; - - return val; + kfree(indio_dev->chan_attr_group.attrs); } -EXPORT_SYMBOL(iio_get_new_ida_val); - -void iio_free_ida_val(struct ida *this_ida, int id) -{ - spin_lock(&iio_ida_lock); - ida_remove(this_ida, id); - spin_unlock(&iio_ida_lock); -} -EXPORT_SYMBOL(iio_free_ida_val); static const char * const iio_ev_type_text[] = { [IIO_EV_TYPE_THRESH] = "thresh", [IIO_EV_TYPE_MAG] = "mag", - [IIO_EV_TYPE_ROC] = "roc" + [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[] = { @@ -907,230 +793,214 @@ static ssize_t iio_ev_value_store(struct device *dev, return len; } -static int iio_device_add_event_sysfs(struct iio_dev *dev_info, +static int iio_device_add_event_sysfs(struct iio_dev *indio_dev, struct iio_chan_spec const *chan) { - - int ret = 0, i, mask; + 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_TYPE_MAX], - iio_ev_dir_text[i%IIO_EV_TYPE_MAX]); + 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; } - switch (chan->type) { - /* Switch this to a table at some point */ - case IIO_IN: - mask = IIO_UNMOD_EVENT_CODE(chan->type, chan->channel, - i/IIO_EV_TYPE_MAX, - i%IIO_EV_TYPE_MAX); - break; - case IIO_ACCEL: + if (chan->modified) mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel, - i/IIO_EV_TYPE_MAX, - i%IIO_EV_TYPE_MAX); - break; - case IIO_IN_DIFF: - mask = IIO_MOD_EVENT_CODE(chan->type, chan->channel, - chan->channel2, - i/IIO_EV_TYPE_MAX, - i%IIO_EV_TYPE_MAX); - break; - default: - printk(KERN_INFO "currently unhandled type of event\n"); - } + 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, - NULL, chan, &iio_ev_state_show, iio_ev_state_store, mask, - /*HACK. - limits us to one - event interface - fix by - extending the bitmask - but - how far*/ 0, - &dev_info->event_interfaces[0].dev, - &dev_info->event_interfaces[0]. + &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_TYPE_MAX], - iio_ev_dir_text[i%IIO_EV_TYPE_MAX]); + 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, NULL, chan, + ret = __iio_add_chan_devattr(postfix, chan, iio_ev_value_show, iio_ev_value_store, mask, 0, - &dev_info->event_interfaces[0] - .dev, - &dev_info->event_interfaces[0] - .dev_attr_list); + &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_all_event_sysfs(struct iio_dev *dev_info, - const char *groupname, - int num) +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, - &dev_info->event_interfaces[num]. + &indio_dev->event_interface-> dev_attr_list, l) { - sysfs_remove_file_from_group(&dev_info - ->event_interfaces[num].dev.kobj, - &p->dev_attr.attr, - groupname); kfree(p->dev_attr.attr.name); kfree(p); } } -static inline int __iio_add_event_config_attrs(struct iio_dev *dev_info, int i) +static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev) { - int j; - int ret; - INIT_LIST_HEAD(&dev_info->event_interfaces[0].dev_attr_list); + int j, ret, attrcount = 0; + + INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list); /* Dynically created from the channels array */ - if (dev_info->channels) { - for (j = 0; j < dev_info->num_channels; j++) { - ret = iio_device_add_event_sysfs(dev_info, - &dev_info - ->channels[j]); - if (ret) - goto error_clear_attrs; - } + 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 0; + return attrcount; error_clear_attrs: - __iio_remove_all_event_sysfs(dev_info, NULL, i); + __iio_remove_event_config_attrs(indio_dev); return ret; } -static inline int __iio_remove_event_config_attrs(struct iio_dev *dev_info, - int i) +static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev) { - __iio_remove_all_event_sysfs(dev_info, NULL, i); - return 0; + 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 int iio_device_register_eventset(struct iio_dev *dev_info) +static const char *iio_event_group_name = "events"; +static int iio_device_register_eventset(struct iio_dev *indio_dev) { - int ret = 0, i, j; + struct iio_dev_attr *p; + int ret = 0, attrcount_orig = 0, attrcount, attrn; + struct attribute **attr; - if (dev_info->info->num_interrupt_lines == 0) + if (!(indio_dev->info->event_attrs || + iio_check_for_dynamic_events(indio_dev))) return 0; - dev_info->event_interfaces = - kzalloc(sizeof(struct iio_event_interface) - *dev_info->info->num_interrupt_lines, - GFP_KERNEL); - if (dev_info->event_interfaces == NULL) { + indio_dev->event_interface = + kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL); + if (indio_dev->event_interface == NULL) { ret = -ENOMEM; goto error_ret; } - for (i = 0; i < dev_info->info->num_interrupt_lines; i++) { - ret = iio_setup_ev_int(&dev_info->event_interfaces[i], - dev_name(&dev_info->dev), - i, - dev_info->info->driver_module, - &dev_info->dev); - if (ret) { - dev_err(&dev_info->dev, - "Could not get chrdev interface\n"); - goto error_free_setup_ev_ints; - } - - dev_set_drvdata(&dev_info->event_interfaces[i].dev, - (void *)dev_info); - - if (dev_info->info->event_attrs != NULL) - ret = sysfs_create_group(&dev_info - ->event_interfaces[i] - .dev.kobj, - &dev_info->info - ->event_attrs[i]); - - if (ret) { - dev_err(&dev_info->dev, - "Failed to register sysfs for event attrs"); - goto error_remove_sysfs_interfaces; - } + 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; } - for (i = 0; i < dev_info->info->num_interrupt_lines; i++) { - ret = __iio_add_event_config_attrs(dev_info, i); - if (ret) - goto error_unregister_config_attrs; + indio_dev->event_interface->group.name = iio_event_group_name; + indio_dev->event_interface->group.attrs = + kzalloc(sizeof(indio_dev->event_interface->group.attrs[0]) + *(attrcount + 1), + 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_unregister_config_attrs: - for (j = 0; j < i; j++) - __iio_remove_event_config_attrs(dev_info, i); - i = dev_info->info->num_interrupt_lines - 1; -error_remove_sysfs_interfaces: - for (j = 0; j < i; j++) - if (dev_info->info->event_attrs != NULL) - sysfs_remove_group(&dev_info - ->event_interfaces[j].dev.kobj, - &dev_info->info->event_attrs[j]); -error_free_setup_ev_ints: - for (j = 0; j < i; j++) - iio_free_ev_int(&dev_info->event_interfaces[j]); - kfree(dev_info->event_interfaces); +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 *dev_info) +static void iio_device_unregister_eventset(struct iio_dev *indio_dev) { - int i; - - if (dev_info->info->num_interrupt_lines == 0) + if (indio_dev->event_interface == NULL) return; - for (i = 0; i < dev_info->info->num_interrupt_lines; i++) { - __iio_remove_event_config_attrs(dev_info, i); - if (dev_info->info->event_attrs != NULL) - sysfs_remove_group(&dev_info - ->event_interfaces[i].dev.kobj, - &dev_info->info->event_attrs[i]); - } - - for (i = 0; i < dev_info->info->num_interrupt_lines; i++) - iio_free_ev_int(&dev_info->event_interfaces[i]); - kfree(dev_info->event_interfaces); + __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) { - iio_put(); - kfree(to_iio_dev(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 = { @@ -1154,12 +1024,21 @@ struct iio_dev *iio_allocate_device(int sizeof_priv) 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); - iio_get(); + + 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; @@ -1168,75 +1047,111 @@ EXPORT_SYMBOL(iio_allocate_device); void iio_free_device(struct iio_dev *dev) { - if (dev) - iio_put_device(dev); + if (dev) { + ida_simple_remove(&iio_ida, dev->id); + kfree(dev); + } } EXPORT_SYMBOL(iio_free_device); -int iio_device_register(struct iio_dev *dev_info) +/** + * iio_chrdev_open() - chrdev file open for buffer access and ioctls + **/ +static int iio_chrdev_open(struct inode *inode, struct file *filp) { - int ret; + struct iio_dev *indio_dev = container_of(inode->i_cdev, + struct iio_dev, chrdev); + filp->private_data = indio_dev; - dev_info->id = iio_get_new_ida_val(&iio_ida); - if (dev_info->id < 0) { - ret = dev_info->id; - dev_err(&dev_info->dev, "Failed to get id\n"); - goto error_ret; + return iio_chrdev_buffer_open(indio_dev); +} + +/** + * iio_chrdev_release() - chrdev file close buffer access and ioctls + **/ +static int iio_chrdev_release(struct inode *inode, struct file *filp) +{ + iio_chrdev_buffer_release(container_of(inode->i_cdev, + struct iio_dev, chrdev)); + 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; } - dev_set_name(&dev_info->dev, "device%d", dev_info->id); + return -EINVAL; +} - ret = device_add(&dev_info->dev); - if (ret) - goto error_free_ida; - ret = iio_device_register_sysfs(dev_info); +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(dev_info->dev.parent, + dev_err(indio_dev->dev.parent, "Failed to register sysfs interfaces\n"); - goto error_del_device; + goto error_ret; } - ret = iio_device_register_eventset(dev_info); + ret = iio_device_register_eventset(indio_dev); if (ret) { - dev_err(dev_info->dev.parent, + dev_err(indio_dev->dev.parent, "Failed to register event set\n"); goto error_free_sysfs; } - if (dev_info->modes & INDIO_RING_TRIGGERED) - iio_device_register_trigger_consumer(dev_info); + 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_free_sysfs: - iio_device_unregister_sysfs(dev_info); error_del_device: - device_del(&dev_info->dev); -error_free_ida: - iio_free_ida_val(&iio_ida, dev_info->id); + 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 *dev_info) +void iio_device_unregister(struct iio_dev *indio_dev) { - if (dev_info->modes & INDIO_RING_TRIGGERED) - iio_device_unregister_trigger_consumer(dev_info); - iio_device_unregister_eventset(dev_info); - iio_device_unregister_sysfs(dev_info); - iio_free_ida_val(&iio_ida, dev_info->id); - device_unregister(&dev_info->dev); + device_unregister(&indio_dev->dev); } EXPORT_SYMBOL(iio_device_unregister); - -void iio_put(void) -{ - module_put(THIS_MODULE); -} - -void iio_get(void) -{ - __module_get(THIS_MODULE); -} - subsys_initcall(iio_init); module_exit(iio_exit); diff --git a/drivers/staging/iio/industrialio-ring.c b/drivers/staging/iio/industrialio-ring.c deleted file mode 100644 index 843eb82..0000000 --- a/drivers/staging/iio/industrialio-ring.c +++ /dev/null @@ -1,596 +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 ring allocation / resizing. - * - * - * Things to look at here. - * - Better memory allocation techniques? - * - Alternative access techniques? - */ -#include <linux/kernel.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 "ring_generic.h" - -/** - * iio_ring_open() - chrdev file open for ring buffer access - * - * This function relies on all ring buffer implementations having an - * iio_ring_buffer as their first element. - **/ -static int iio_ring_open(struct inode *inode, struct file *filp) -{ - struct iio_handler *hand - = container_of(inode->i_cdev, struct iio_handler, chrdev); - struct iio_ring_buffer *rb = hand->private; - - filp->private_data = hand->private; - if (rb->access->mark_in_use) - rb->access->mark_in_use(rb); - - return 0; -} - -/** - * iio_ring_release() - chrdev file close ring buffer access - * - * This function relies on all ring buffer implementations having an - * iio_ring_buffer as their first element. - **/ -static int iio_ring_release(struct inode *inode, struct file *filp) -{ - struct cdev *cd = inode->i_cdev; - struct iio_handler *hand = iio_cdev_to_handler(cd); - struct iio_ring_buffer *rb = hand->private; - - clear_bit(IIO_BUSY_BIT_POS, &rb->access_handler.flags); - if (rb->access->unmark_in_use) - rb->access->unmark_in_use(rb); - - return 0; -} - -/** - * iio_ring_read_first_n_outer() - chrdev read for ring buffer access - * - * This function relies on all ring buffer implementations having an - * iio_ring _bufer as their first element. - **/ -static ssize_t iio_ring_read_first_n_outer(struct file *filp, char __user *buf, - size_t n, loff_t *f_ps) -{ - struct iio_ring_buffer *rb = filp->private_data; - - if (!rb->access->read_first_n) - return -EINVAL; - return rb->access->read_first_n(rb, n, buf); -} - -/** - * iio_ring_poll() - poll the ring to find out if it has data - */ -static unsigned int iio_ring_poll(struct file *filp, - struct poll_table_struct *wait) -{ - struct iio_ring_buffer *rb = filp->private_data; - - poll_wait(filp, &rb->pollq, wait); - if (rb->stufftoread) - return POLLIN | POLLRDNORM; - /* need a way of knowing if there may be enough data... */ - return 0; -} - -static const struct file_operations iio_ring_fileops = { - .read = iio_ring_read_first_n_outer, - .release = iio_ring_release, - .open = iio_ring_open, - .poll = iio_ring_poll, - .owner = THIS_MODULE, - .llseek = noop_llseek, -}; - -void iio_ring_access_release(struct device *dev) -{ - struct iio_ring_buffer *buf - = container_of(dev, struct iio_ring_buffer, dev); - cdev_del(&buf->access_handler.chrdev); - iio_device_free_chrdev_minor(MINOR(dev->devt)); -} -EXPORT_SYMBOL(iio_ring_access_release); - -static inline int -__iio_request_ring_buffer_chrdev(struct iio_ring_buffer *buf, - struct module *owner, - int id) -{ - int ret; - - buf->access_handler.flags = 0; - buf->dev.bus = &iio_bus_type; - device_initialize(&buf->dev); - - ret = iio_device_get_chrdev_minor(); - if (ret < 0) - goto error_device_put; - - buf->dev.devt = MKDEV(MAJOR(iio_devt), ret); - dev_set_name(&buf->dev, "%s:buffer%d", - dev_name(buf->dev.parent), - id); - ret = device_add(&buf->dev); - if (ret < 0) { - printk(KERN_ERR "failed to add the ring dev\n"); - goto error_device_put; - } - cdev_init(&buf->access_handler.chrdev, &iio_ring_fileops); - buf->access_handler.chrdev.owner = owner; - ret = cdev_add(&buf->access_handler.chrdev, buf->dev.devt, 1); - if (ret) { - printk(KERN_ERR "failed to allocate ring chrdev\n"); - goto error_device_unregister; - } - return 0; - -error_device_unregister: - device_unregister(&buf->dev); -error_device_put: - put_device(&buf->dev); - - return ret; -} - -static void __iio_free_ring_buffer_chrdev(struct iio_ring_buffer *buf) -{ - device_unregister(&buf->dev); -} - -void iio_ring_buffer_init(struct iio_ring_buffer *ring, - struct iio_dev *dev_info) -{ - ring->indio_dev = dev_info; - ring->access_handler.private = ring; - init_waitqueue_head(&ring->pollq); -} -EXPORT_SYMBOL(iio_ring_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); - return sprintf(buf, "%c%d/%d>>%u\n", - this_attr->c->scan_type.sign, - this_attr->c->scan_type.realbits, - this_attr->c->scan_type.storagebits, - this_attr->c->scan_type.shift); -} - -static ssize_t iio_scan_el_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - struct iio_ring_buffer *ring = dev_get_drvdata(dev); - - ret = iio_scan_mask_query(ring, to_iio_dev_attr(attr)->address); - if (ret < 0) - return ret; - return sprintf(buf, "%d\n", ret); -} - -static int iio_scan_mask_clear(struct iio_ring_buffer *ring, int bit) -{ - if (bit > IIO_MAX_SCAN_LENGTH) - return -EINVAL; - ring->scan_mask &= ~(1 << bit); - ring->scan_count--; - return 0; -} - -static ssize_t iio_scan_el_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - int ret = 0; - bool state; - struct iio_ring_buffer *ring = dev_get_drvdata(dev); - struct iio_dev *indio_dev = ring->indio_dev; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - state = !(buf[0] == '0'); - mutex_lock(&indio_dev->mlock); - if (indio_dev->currentmode == INDIO_RING_TRIGGERED) { - ret = -EBUSY; - goto error_ret; - } - ret = iio_scan_mask_query(ring, this_attr->address); - if (ret < 0) - goto error_ret; - if (!state && ret) { - ret = iio_scan_mask_clear(ring, this_attr->address); - if (ret) - goto error_ret; - } else if (state && !ret) { - ret = iio_scan_mask_set(ring, this_attr->address); - if (ret) - goto error_ret; - } - -error_ret: - mutex_unlock(&indio_dev->mlock); - - return ret ? ret : len; - -} - -static ssize_t iio_scan_el_ts_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_ring_buffer *ring = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", ring->scan_timestamp); -} - -static ssize_t iio_scan_el_ts_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - int ret = 0; - struct iio_ring_buffer *ring = dev_get_drvdata(dev); - struct iio_dev *indio_dev = ring->indio_dev; - bool state; - state = !(buf[0] == '0'); - mutex_lock(&indio_dev->mlock); - if (indio_dev->currentmode == INDIO_RING_TRIGGERED) { - ret = -EBUSY; - goto error_ret; - } - ring->scan_timestamp = state; -error_ret: - mutex_unlock(&indio_dev->mlock); - - return ret ? ret : len; -} - -static int iio_ring_add_channel_sysfs(struct iio_ring_buffer *ring, - const struct iio_chan_spec *chan) -{ - int ret; - - ret = __iio_add_chan_devattr("index", "scan_elements", - chan, - &iio_show_scan_index, - NULL, - 0, - 0, - &ring->dev, - &ring->scan_el_dev_attr_list); - if (ret) - goto error_ret; - - ret = __iio_add_chan_devattr("type", "scan_elements", - chan, - &iio_show_fixed_type, - NULL, - 0, - 0, - &ring->dev, - &ring->scan_el_dev_attr_list); - if (ret) - goto error_ret; - - if (chan->type != IIO_TIMESTAMP) - ret = __iio_add_chan_devattr("en", "scan_elements", - chan, - &iio_scan_el_show, - &iio_scan_el_store, - chan->scan_index, - 0, - &ring->dev, - &ring->scan_el_dev_attr_list); - else - ret = __iio_add_chan_devattr("en", "scan_elements", - chan, - &iio_scan_el_ts_show, - &iio_scan_el_ts_store, - chan->scan_index, - 0, - &ring->dev, - &ring->scan_el_dev_attr_list); -error_ret: - return ret; -} - -static void iio_ring_remove_and_free_scan_dev_attr(struct iio_ring_buffer *ring, - struct iio_dev_attr *p) -{ - sysfs_remove_file_from_group(&ring->dev.kobj, - &p->dev_attr.attr, "scan_elements"); - kfree(p->dev_attr.attr.name); - kfree(p); -} - -static struct attribute *iio_scan_el_dummy_attrs[] = { - NULL -}; - -static struct attribute_group iio_scan_el_dummy_group = { - .name = "scan_elements", - .attrs = iio_scan_el_dummy_attrs -}; - -static void __iio_ring_attr_cleanup(struct iio_ring_buffer *ring) -{ - struct iio_dev_attr *p, *n; - int anydynamic = !list_empty(&ring->scan_el_dev_attr_list); - list_for_each_entry_safe(p, n, - &ring->scan_el_dev_attr_list, l) - iio_ring_remove_and_free_scan_dev_attr(ring, p); - - if (ring->scan_el_attrs) - sysfs_remove_group(&ring->dev.kobj, - ring->scan_el_attrs); - else if (anydynamic) - sysfs_remove_group(&ring->dev.kobj, - &iio_scan_el_dummy_group); -} - -int iio_ring_buffer_register_ex(struct iio_ring_buffer *ring, int id, - const struct iio_chan_spec *channels, - int num_channels) -{ - int ret, i; - - ret = __iio_request_ring_buffer_chrdev(ring, ring->owner, id); - if (ret) - goto error_ret; - - if (ring->scan_el_attrs) { - ret = sysfs_create_group(&ring->dev.kobj, - ring->scan_el_attrs); - if (ret) { - dev_err(&ring->dev, - "Failed to add sysfs scan elements\n"); - goto error_free_ring_buffer_chrdev; - } - } else if (channels) { - ret = sysfs_create_group(&ring->dev.kobj, - &iio_scan_el_dummy_group); - if (ret) - goto error_free_ring_buffer_chrdev; - } - - INIT_LIST_HEAD(&ring->scan_el_dev_attr_list); - if (channels) { - /* new magic */ - for (i = 0; i < num_channels; i++) { - ret = iio_ring_add_channel_sysfs(ring, &channels[i]); - if (ret < 0) - goto error_cleanup_dynamic; - } - } - - return 0; -error_cleanup_dynamic: - __iio_ring_attr_cleanup(ring); -error_free_ring_buffer_chrdev: - __iio_free_ring_buffer_chrdev(ring); -error_ret: - return ret; -} -EXPORT_SYMBOL(iio_ring_buffer_register_ex); - -void iio_ring_buffer_unregister(struct iio_ring_buffer *ring) -{ - __iio_ring_attr_cleanup(ring); - __iio_free_ring_buffer_chrdev(ring); -} -EXPORT_SYMBOL(iio_ring_buffer_unregister); - -ssize_t iio_read_ring_length(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_ring_buffer *ring = dev_get_drvdata(dev); - - if (ring->access->get_length) - return sprintf(buf, "%d\n", - ring->access->get_length(ring)); - - return 0; -} -EXPORT_SYMBOL(iio_read_ring_length); - -ssize_t iio_write_ring_length(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - int ret; - ulong val; - struct iio_ring_buffer *ring = dev_get_drvdata(dev); - - ret = strict_strtoul(buf, 10, &val); - if (ret) - return ret; - - if (ring->access->get_length) - if (val == ring->access->get_length(ring)) - return len; - - if (ring->access->set_length) { - ring->access->set_length(ring, val); - if (ring->access->mark_param_change) - ring->access->mark_param_change(ring); - } - - return len; -} -EXPORT_SYMBOL(iio_write_ring_length); - -ssize_t iio_read_ring_bytes_per_datum(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_ring_buffer *ring = dev_get_drvdata(dev); - - if (ring->access->get_bytes_per_datum) - return sprintf(buf, "%d\n", - ring->access->get_bytes_per_datum(ring)); - - return 0; -} -EXPORT_SYMBOL(iio_read_ring_bytes_per_datum); - -ssize_t iio_store_ring_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_ring_buffer *ring = dev_get_drvdata(dev); - struct iio_dev *dev_info = ring->indio_dev; - - mutex_lock(&dev_info->mlock); - previous_mode = dev_info->currentmode; - requested_state = !(buf[0] == '0'); - current_state = !!(previous_mode & INDIO_ALL_RING_MODES); - if (current_state == requested_state) { - printk(KERN_INFO "iio-ring, current state requested again\n"); - goto done; - } - if (requested_state) { - if (ring->setup_ops->preenable) { - ret = ring->setup_ops->preenable(dev_info); - if (ret) { - printk(KERN_ERR - "Buffer not started:" - "ring preenable failed\n"); - goto error_ret; - } - } - if (ring->access->request_update) { - ret = ring->access->request_update(ring); - if (ret) { - printk(KERN_INFO - "Buffer not started:" - "ring parameter update failed\n"); - goto error_ret; - } - } - if (ring->access->mark_in_use) - ring->access->mark_in_use(ring); - /* Definitely possible for devices to support both of these.*/ - if (dev_info->modes & INDIO_RING_TRIGGERED) { - if (!dev_info->trig) { - printk(KERN_INFO - "Buffer not started: no trigger\n"); - ret = -EINVAL; - if (ring->access->unmark_in_use) - ring->access->unmark_in_use(ring); - goto error_ret; - } - dev_info->currentmode = INDIO_RING_TRIGGERED; - } else if (dev_info->modes & INDIO_RING_HARDWARE_BUFFER) - dev_info->currentmode = INDIO_RING_HARDWARE_BUFFER; - else { /* should never be reached */ - ret = -EINVAL; - goto error_ret; - } - - if (ring->setup_ops->postenable) { - ret = ring->setup_ops->postenable(dev_info); - if (ret) { - printk(KERN_INFO - "Buffer not started:" - "postenable failed\n"); - if (ring->access->unmark_in_use) - ring->access->unmark_in_use(ring); - dev_info->currentmode = previous_mode; - if (ring->setup_ops->postdisable) - ring->setup_ops->postdisable(dev_info); - goto error_ret; - } - } - } else { - if (ring->setup_ops->predisable) { - ret = ring->setup_ops->predisable(dev_info); - if (ret) - goto error_ret; - } - if (ring->access->unmark_in_use) - ring->access->unmark_in_use(ring); - dev_info->currentmode = INDIO_DIRECT_MODE; - if (ring->setup_ops->postdisable) { - ret = ring->setup_ops->postdisable(dev_info); - if (ret) - goto error_ret; - } - } -done: - mutex_unlock(&dev_info->mlock); - return len; - -error_ret: - mutex_unlock(&dev_info->mlock); - return ret; -} -EXPORT_SYMBOL(iio_store_ring_enable); - -ssize_t iio_show_ring_enable(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_ring_buffer *ring = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", !!(ring->indio_dev->currentmode - & INDIO_ALL_RING_MODES)); -} -EXPORT_SYMBOL(iio_show_ring_enable); - -int iio_sw_ring_preenable(struct iio_dev *indio_dev) -{ - struct iio_ring_buffer *ring = indio_dev->ring; - size_t size; - dev_dbg(&indio_dev->dev, "%s\n", __func__); - /* Check if there are any scan elements enabled, if not fail*/ - if (!(ring->scan_count || ring->scan_timestamp)) - return -EINVAL; - if (ring->scan_timestamp) - if (ring->scan_count) - /* Timestamp (aligned to s64) and data */ - size = (((ring->scan_count * ring->bpe) - + sizeof(s64) - 1) - & ~(sizeof(s64) - 1)) - + sizeof(s64); - else /* Timestamp only */ - size = sizeof(s64); - else /* Data only */ - size = ring->scan_count * ring->bpe; - ring->access->set_bytes_per_datum(ring, size); - - return 0; -} -EXPORT_SYMBOL(iio_sw_ring_preenable); diff --git a/drivers/staging/iio/industrialio-trigger.c b/drivers/staging/iio/industrialio-trigger.c index 90ca2df..2c626e0 100644 --- a/drivers/staging/iio/industrialio-trigger.c +++ b/drivers/staging/iio/industrialio-trigger.c @@ -8,7 +8,6 @@ */ #include <linux/kernel.h> -#include <linux/module.h> #include <linux/idr.h> #include <linux/err.h> #include <linux/device.h> @@ -18,6 +17,8 @@ #include "iio.h" #include "trigger.h" +#include "iio_core.h" +#include "iio_core_trigger.h" #include "trigger_consumer.h" /* RFC - Question of approach @@ -31,8 +32,7 @@ * Any other suggestions? */ -static DEFINE_IDR(iio_trigger_idr); -static DEFINE_SPINLOCK(iio_trigger_idr_lock); +static DEFINE_IDA(iio_trigger_ida); /* Single list of all available triggers */ static LIST_HEAD(iio_trigger_list); @@ -71,48 +71,15 @@ static void iio_trigger_unregister_sysfs(struct iio_trigger *trig_info) NULL); } - -/** - * iio_trigger_register_id() - get a unique id for this trigger - * @trig_info: the trigger - **/ -static int iio_trigger_register_id(struct iio_trigger *trig_info) -{ - int ret = 0; - -idr_again: - if (unlikely(idr_pre_get(&iio_trigger_idr, GFP_KERNEL) == 0)) - return -ENOMEM; - - spin_lock(&iio_trigger_idr_lock); - ret = idr_get_new(&iio_trigger_idr, NULL, &trig_info->id); - spin_unlock(&iio_trigger_idr_lock); - if (unlikely(ret == -EAGAIN)) - goto idr_again; - else if (likely(!ret)) - trig_info->id = trig_info->id & MAX_ID_MASK; - - return ret; -} - -/** - * iio_trigger_unregister_id() - free up unique id for use by another trigger - * @trig_info: the trigger - **/ -static void iio_trigger_unregister_id(struct iio_trigger *trig_info) -{ - spin_lock(&iio_trigger_idr_lock); - idr_remove(&iio_trigger_idr, trig_info->id); - spin_unlock(&iio_trigger_idr_lock); -} - int iio_trigger_register(struct iio_trigger *trig_info) { int ret; - ret = iio_trigger_register_id(trig_info); - if (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); @@ -135,7 +102,7 @@ int iio_trigger_register(struct iio_trigger *trig_info) error_device_del: device_del(&trig_info->dev); error_unregister_id: - iio_trigger_unregister_id(trig_info); + ida_simple_remove(&iio_trigger_ida, trig_info->id); error_ret: return ret; } @@ -148,7 +115,7 @@ void iio_trigger_unregister(struct iio_trigger *trig_info) mutex_unlock(&iio_trigger_list_lock); iio_trigger_unregister_sysfs(trig_info); - iio_trigger_unregister_id(trig_info); + ida_simple_remove(&iio_trigger_ida, trig_info->id); /* Possible issue in here */ device_unregister(&trig_info->dev); } @@ -173,13 +140,12 @@ static struct iio_trigger *iio_trigger_find_by_name(const char *name, void iio_trigger_poll(struct iio_trigger *trig, s64 time) { int i; - if (!trig->use_count) { + if (!trig->use_count) for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) if (trig->subirqs[i].enabled) { trig->use_count++; generic_handle_irq(trig->subirq_base + i); } - } } EXPORT_SYMBOL(iio_trigger_poll); @@ -206,8 +172,8 @@ EXPORT_SYMBOL(iio_trigger_poll_chained); void iio_trigger_notify_done(struct iio_trigger *trig) { trig->use_count--; - if (trig->use_count == 0 && trig->try_reenable) - if (trig->try_reenable(trig)) { + if (trig->use_count == 0 && trig->ops && trig->ops->try_reenable) + if (trig->ops->try_reenable(trig)) { /* Missed and interrupt so launch new poll now */ iio_trigger_poll(trig, 0); } @@ -215,6 +181,26 @@ void iio_trigger_notify_done(struct iio_trigger *trig) EXPORT_SYMBOL(iio_trigger_notify_done); /* Trigger Consumer related functions */ +static int iio_trigger_get_irq(struct iio_trigger *trig) +{ + int ret; + mutex_lock(&trig->pool_lock); + ret = bitmap_find_free_region(trig->pool, + CONFIG_IIO_CONSUMERS_PER_TRIGGER, + ilog2(1)); + mutex_unlock(&trig->pool_lock); + if (ret >= 0) + ret += trig->subirq_base; + + return ret; +} + +static void iio_trigger_put_irq(struct iio_trigger *trig, int irq) +{ + mutex_lock(&trig->pool_lock); + clear_bit(irq - trig->subirq_base, trig->pool); + mutex_unlock(&trig->pool_lock); +} /* Complexity in here. With certain triggers (datardy) an acknowledgement * may be needed if the pollfuncs do not include the data read for the @@ -223,44 +209,45 @@ EXPORT_SYMBOL(iio_trigger_notify_done); * the relevant function is in there may be the best option. */ /* Worth protecting against double additions?*/ -int iio_trigger_attach_poll_func(struct iio_trigger *trig, - struct iio_poll_func *pf) +static int iio_trigger_attach_poll_func(struct iio_trigger *trig, + struct iio_poll_func *pf) { int ret = 0; bool notinuse = bitmap_empty(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER); + /* Prevent the module being removed whilst attached to a trigger */ + __module_get(pf->indio_dev->info->driver_module); pf->irq = iio_trigger_get_irq(trig); ret = request_threaded_irq(pf->irq, pf->h, pf->thread, pf->type, pf->name, pf); - if (trig->set_trigger_state && notinuse) - ret = trig->set_trigger_state(trig, true); + if (trig->ops && trig->ops->set_trigger_state && notinuse) + ret = trig->ops->set_trigger_state(trig, true); return ret; } -EXPORT_SYMBOL(iio_trigger_attach_poll_func); -int iio_trigger_dettach_poll_func(struct iio_trigger *trig, - struct iio_poll_func *pf) +static int iio_trigger_dettach_poll_func(struct iio_trigger *trig, + struct iio_poll_func *pf) { int ret = 0; bool no_other_users = (bitmap_weight(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER) == 1); - if (trig->set_trigger_state && no_other_users) { - ret = trig->set_trigger_state(trig, false); + if (trig->ops && trig->ops->set_trigger_state && no_other_users) { + ret = trig->ops->set_trigger_state(trig, false); if (ret) goto error_ret; } iio_trigger_put_irq(trig, pf->irq); free_irq(pf->irq, pf); + module_put(pf->indio_dev->info->driver_module); error_ret: return ret; } -EXPORT_SYMBOL(iio_trigger_dettach_poll_func); irqreturn_t iio_pollfunc_store_time(int irq, void *p) { @@ -274,7 +261,7 @@ struct iio_poll_func *iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p), irqreturn_t (*thread)(int irq, void *p), int type, - void *private, + struct iio_dev *indio_dev, const char *fmt, ...) { @@ -294,7 +281,7 @@ struct iio_poll_func pf->h = h; pf->thread = thread; pf->type = type; - pf->private_data = private; + pf->indio_dev = indio_dev; return pf; } @@ -317,13 +304,11 @@ static ssize_t iio_trigger_read_current(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - int len = 0; - if (dev_info->trig) - len = sprintf(buf, - "%s\n", - dev_info->trig->name); - return len; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + + if (indio_dev->trig) + return sprintf(buf, "%s\n", indio_dev->trig->name); + return 0; } /** @@ -338,38 +323,38 @@ static ssize_t iio_trigger_write_current(struct device *dev, const char *buf, size_t len) { - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct iio_trigger *oldtrig = dev_info->trig; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_trigger *oldtrig = indio_dev->trig; struct iio_trigger *trig; int ret; - mutex_lock(&dev_info->mlock); - if (dev_info->currentmode == INDIO_RING_TRIGGERED) { - mutex_unlock(&dev_info->mlock); + mutex_lock(&indio_dev->mlock); + if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { + mutex_unlock(&indio_dev->mlock); return -EBUSY; } - mutex_unlock(&dev_info->mlock); + mutex_unlock(&indio_dev->mlock); trig = iio_trigger_find_by_name(buf, len); - if (trig && dev_info->info->validate_trigger) { - ret = dev_info->info->validate_trigger(dev_info, trig); + if (trig && indio_dev->info->validate_trigger) { + ret = indio_dev->info->validate_trigger(indio_dev, trig); if (ret) return ret; } - if (trig && trig->validate_device) { - ret = trig->validate_device(trig, dev_info); + if (trig && trig->ops && trig->ops->validate_device) { + ret = trig->ops->validate_device(trig, indio_dev); if (ret) return ret; } - dev_info->trig = trig; + indio_dev->trig = trig; - if (oldtrig && dev_info->trig != oldtrig) + if (oldtrig && indio_dev->trig != oldtrig) iio_put_trigger(oldtrig); - if (dev_info->trig) - iio_get_trigger(dev_info->trig); + if (indio_dev->trig) + iio_get_trigger(indio_dev->trig); return len; } @@ -409,7 +394,6 @@ static void iio_trig_release(struct device *device) } kfree(trig->name); kfree(trig); - iio_put(); } static struct device_type iio_trig_type = { @@ -476,7 +460,7 @@ struct iio_trigger *iio_allocate_trigger(const char *fmt, ...) IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE); } - iio_get(); + get_device(&trig->dev); } return trig; } @@ -489,37 +473,35 @@ void iio_free_trigger(struct iio_trigger *trig) } EXPORT_SYMBOL(iio_free_trigger); -int iio_device_register_trigger_consumer(struct iio_dev *dev_info) +int iio_device_register_trigger_consumer(struct iio_dev *indio_dev) { - int ret; - ret = sysfs_create_group(&dev_info->dev.kobj, - &iio_trigger_consumer_attr_group); - return ret; + indio_dev->groups[indio_dev->groupcounter++] = + &iio_trigger_consumer_attr_group; + + return 0; } -EXPORT_SYMBOL(iio_device_register_trigger_consumer); -int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info) +void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev) { - sysfs_remove_group(&dev_info->dev.kobj, - &iio_trigger_consumer_attr_group); - return 0; + /* Clean up and associated but not attached triggers references */ + if (indio_dev->trig) + iio_put_trigger(indio_dev->trig); } -EXPORT_SYMBOL(iio_device_unregister_trigger_consumer); -int iio_triggered_ring_postenable(struct iio_dev *indio_dev) +int iio_triggered_buffer_postenable(struct iio_dev *indio_dev) { return indio_dev->trig ? iio_trigger_attach_poll_func(indio_dev->trig, indio_dev->pollfunc) : 0; } -EXPORT_SYMBOL(iio_triggered_ring_postenable); +EXPORT_SYMBOL(iio_triggered_buffer_postenable); -int iio_triggered_ring_predisable(struct iio_dev *indio_dev) +int iio_triggered_buffer_predisable(struct iio_dev *indio_dev) { return indio_dev->trig ? iio_trigger_dettach_poll_func(indio_dev->trig, indio_dev->pollfunc) : 0; } -EXPORT_SYMBOL(iio_triggered_ring_predisable); +EXPORT_SYMBOL(iio_triggered_buffer_predisable); diff --git a/drivers/staging/iio/kfifo_buf.c b/drivers/staging/iio/kfifo_buf.c index 6002368..e8c234b 100644 --- a/drivers/staging/iio/kfifo_buf.c +++ b/drivers/staging/iio/kfifo_buf.c @@ -8,7 +8,15 @@ #include "kfifo_buf.h" -#define iio_to_kfifo(r) container_of(r, struct iio_kfifo, ring) +struct iio_kfifo { + struct iio_buffer buffer; + struct kfifo kf; + int use_count; + int update_needed; + struct mutex use_lock; +}; + +#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) @@ -16,11 +24,11 @@ static inline int __iio_allocate_kfifo(struct iio_kfifo *buf, if ((length == 0) || (bytes_per_datum == 0)) return -EINVAL; - __iio_update_ring_buffer(&buf->ring, bytes_per_datum, length); + __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_ring_buffer *r) +static int iio_request_update_kfifo(struct iio_buffer *r) { int ret = 0; struct iio_kfifo *buf = iio_to_kfifo(r); @@ -33,14 +41,14 @@ static int iio_request_update_kfifo(struct iio_ring_buffer *r) goto error_ret; } kfifo_free(&buf->kf); - ret = __iio_allocate_kfifo(buf, buf->ring.bytes_per_datum, - buf->ring.length); + ret = __iio_allocate_kfifo(buf, buf->buffer.bytes_per_datum, + buf->buffer.length); error_ret: mutex_unlock(&buf->use_lock); return ret; } -static void iio_mark_kfifo_in_use(struct iio_ring_buffer *r) +static void iio_mark_kfifo_in_use(struct iio_buffer *r) { struct iio_kfifo *buf = iio_to_kfifo(r); mutex_lock(&buf->use_lock); @@ -48,7 +56,7 @@ static void iio_mark_kfifo_in_use(struct iio_ring_buffer *r) mutex_unlock(&buf->use_lock); } -static void iio_unmark_kfifo_in_use(struct iio_ring_buffer *r) +static void iio_unmark_kfifo_in_use(struct iio_buffer *r) { struct iio_kfifo *buf = iio_to_kfifo(r); mutex_lock(&buf->use_lock); @@ -56,7 +64,7 @@ static void iio_unmark_kfifo_in_use(struct iio_ring_buffer *r) mutex_unlock(&buf->use_lock); } -static int iio_get_length_kfifo(struct iio_ring_buffer *r) +static int iio_get_length_kfifo(struct iio_buffer *r) { return r->length; } @@ -66,9 +74,9 @@ static inline void __iio_init_kfifo(struct iio_kfifo *kf) mutex_init(&kf->use_lock); } -static IIO_RING_ENABLE_ATTR; -static IIO_RING_BYTES_PER_DATUM_ATTR; -static IIO_RING_LENGTH_ATTR; +static IIO_BUFFER_ENABLE_ATTR; +static IIO_BUFFER_BYTES_PER_DATUM_ATTR; +static IIO_BUFFER_LENGTH_ATTR; static struct attribute *iio_kfifo_attributes[] = { &dev_attr_length.attr, @@ -79,27 +87,10 @@ static struct attribute *iio_kfifo_attributes[] = { static struct attribute_group iio_kfifo_attribute_group = { .attrs = iio_kfifo_attributes, + .name = "buffer", }; -static const struct attribute_group *iio_kfifo_attribute_groups[] = { - &iio_kfifo_attribute_group, - NULL -}; - -static void iio_kfifo_release(struct device *dev) -{ - struct iio_ring_buffer *r = to_iio_ring_buffer(dev); - struct iio_kfifo *kf = iio_to_kfifo(r); - kfifo_free(&kf->kf); - kfree(kf); -} - -static struct device_type iio_kfifo_type = { - .release = iio_kfifo_release, - .groups = iio_kfifo_attribute_groups, -}; - -struct iio_ring_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) +struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) { struct iio_kfifo *kf; @@ -107,22 +98,20 @@ struct iio_ring_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) if (!kf) return NULL; kf->update_needed = true; - iio_ring_buffer_init(&kf->ring, indio_dev); + iio_buffer_init(&kf->buffer, indio_dev); + kf->buffer.attrs = &iio_kfifo_attribute_group; __iio_init_kfifo(kf); - kf->ring.dev.type = &iio_kfifo_type; - kf->ring.dev.parent = &indio_dev->dev; - dev_set_drvdata(&kf->ring.dev, (void *)&(kf->ring)); - return &kf->ring; + return &kf->buffer; } EXPORT_SYMBOL(iio_kfifo_allocate); -static int iio_get_bytes_per_datum_kfifo(struct iio_ring_buffer *r) +static int iio_get_bytes_per_datum_kfifo(struct iio_buffer *r) { return r->bytes_per_datum; } -static int iio_set_bytes_per_datum_kfifo(struct iio_ring_buffer *r, size_t bpd) +static int iio_set_bytes_per_datum_kfifo(struct iio_buffer *r, size_t bpd) { if (r->bytes_per_datum != bpd) { r->bytes_per_datum = bpd; @@ -132,14 +121,14 @@ static int iio_set_bytes_per_datum_kfifo(struct iio_ring_buffer *r, size_t bpd) return 0; } -static int iio_mark_update_needed_kfifo(struct iio_ring_buffer *r) +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_length_kfifo(struct iio_ring_buffer *r, int length) +static int iio_set_length_kfifo(struct iio_buffer *r, int length) { if (r->length != length) { r->length = length; @@ -149,14 +138,13 @@ static int iio_set_length_kfifo(struct iio_ring_buffer *r, int length) return 0; } -void iio_kfifo_free(struct iio_ring_buffer *r) +void iio_kfifo_free(struct iio_buffer *r) { - if (r) - iio_put_ring_buffer(r); + kfree(iio_to_kfifo(r)); } EXPORT_SYMBOL(iio_kfifo_free); -static int iio_store_to_kfifo(struct iio_ring_buffer *r, +static int iio_store_to_kfifo(struct iio_buffer *r, u8 *data, s64 timestamp) { @@ -175,7 +163,7 @@ static int iio_store_to_kfifo(struct iio_ring_buffer *r, return 0; } -static int iio_read_first_n_kfifo(struct iio_ring_buffer *r, +static int iio_read_first_n_kfifo(struct iio_buffer *r, size_t n, char __user *buf) { int ret, copied; @@ -186,7 +174,7 @@ static int iio_read_first_n_kfifo(struct iio_ring_buffer *r, return copied; } -const struct iio_ring_access_funcs kfifo_access_funcs = { +const struct iio_buffer_access_funcs kfifo_access_funcs = { .mark_in_use = &iio_mark_kfifo_in_use, .unmark_in_use = &iio_unmark_kfifo_in_use, .store_to = &iio_store_to_kfifo, diff --git a/drivers/staging/iio/kfifo_buf.h b/drivers/staging/iio/kfifo_buf.h index aac3053..a15598b 100644 --- a/drivers/staging/iio/kfifo_buf.h +++ b/drivers/staging/iio/kfifo_buf.h @@ -1,18 +1,10 @@ #include <linux/kfifo.h> #include "iio.h" -#include "ring_generic.h" +#include "buffer_generic.h" -struct iio_kfifo { - struct iio_ring_buffer ring; - struct kfifo kf; - int use_count; - int update_needed; - struct mutex use_lock; -}; +extern const struct iio_buffer_access_funcs kfifo_access_funcs; -extern const struct iio_ring_access_funcs kfifo_access_funcs; - -struct iio_ring_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev); -void iio_kfifo_free(struct iio_ring_buffer *r); +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 1ad2d56..e7e9159 100644 --- a/drivers/staging/iio/light/Kconfig +++ b/drivers/staging/iio/light/Kconfig @@ -1,7 +1,7 @@ # # Light sensors # -comment "Light sensors" +menu "Light sensors" config SENSORS_ISL29018 tristate "ISL 29018 light and proximity sensor" @@ -30,3 +30,5 @@ config TSL2583 help Provides support for the TAOS tsl2580, tsl2581 and tsl2583 devices. Access ALS data via iio, sysfs. + +endmenu diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 426b6af..9dc9e63 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -28,7 +28,7 @@ #include <linux/delay.h> #include <linux/slab.h> #include "../iio.h" - +#include "../sysfs.h" #define CONVERSION_TIME_MS 100 #define ISL29018_REG_ADD_COMMAND1 0x00 @@ -51,7 +51,11 @@ #define ISL29018_REG_ADD_DATA_LSB 0x02 #define ISL29018_REG_ADD_DATA_MSB 0x03 -#define ISL29018_MAX_REGS ISL29018_REG_ADD_DATA_MSB +#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; @@ -66,22 +70,27 @@ struct isl29018_chip { static int isl29018_write_data(struct i2c_client *client, u8 reg, u8 val, u8 mask, u8 shift) { - u8 regval; - int ret = 0; + u8 regval = val; + int ret; struct isl29018_chip *chip = iio_priv(i2c_get_clientdata(client)); - regval = chip->reg_cache[reg]; - regval &= ~mask; - regval |= val << shift; + /* 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); - return ret; + } else { + /* don't update cache on err */ + if (reg < ISL29018_MAX_REGS) + chip->reg_cache[reg] = regval; } - chip->reg_cache[reg] = regval; - return 0; + return ret; } static int isl29018_set_range(struct i2c_client *client, unsigned long range, @@ -411,7 +420,7 @@ static const struct iio_chan_spec isl29018_channels[] = { .type = IIO_LIGHT, .indexed = 1, .channel = 0, - .processed_val = 1, + .processed_val = IIO_PROCESSED, .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), }, { .type = IIO_INTENSITY, @@ -457,6 +466,48 @@ static int isl29018_chip_init(struct i2c_client *client) memset(chip->reg_cache, 0, sizeof(chip->reg_cache)); + /* Code added per Intersil Application Note 1534: + * When VDD sinks to approximately 1.8V or below, some of + * the part's registers may change their state. When VDD + * recovers to 2.25V (or greater), the part may thus be in an + * unknown mode of operation. The user can return the part to + * a known mode of operation either by (a) setting VDD = 0V for + * 1 second or more and then powering back up with a slew rate + * of 0.5V/ms or greater, or (b) via I2C disable all ALS/PROX + * conversions, clear the test registers, and then rewrite all + * registers to the desired values. + * ... + * FOR ISL29011, ISL29018, ISL29021, ISL29023 + * 1. Write 0x00 to register 0x08 (TEST) + * 2. Write 0x00 to register 0x00 (CMD1) + * 3. Rewrite all registers to the desired values + * + * ISL29018 Data Sheet (FN6619.1, Feb 11, 2010) essentially says + * the same thing EXCEPT the data sheet asks for a 1ms delay after + * writing the CMD1 register. + */ + status = isl29018_write_data(client, ISL29018_REG_TEST, 0, + ISL29018_TEST_MASK, ISL29018_TEST_SHIFT); + if (status < 0) { + dev_err(&client->dev, "Failed to clear isl29018 TEST reg." + "(%d)\n", status); + return status; + } + + /* See Intersil AN1534 comments above. + * "Operating Mode" (COMMAND1) register is reprogrammed when + * data is read from the device. + */ + status = isl29018_write_data(client, ISL29018_REG_ADD_COMMAND1, 0, + 0xff, 0); + if (status < 0) { + dev_err(&client->dev, "Failed to clear isl29018 CMD1 reg." + "(%d)\n", status); + return status; + } + + msleep(1); /* per data sheet, page 10 */ + /* set defaults */ status = isl29018_set_range(client, chip->range, &new_range); if (status < 0) { @@ -530,6 +581,7 @@ static int __devexit isl29018_remove(struct i2c_client *client) dev_dbg(&client->dev, "%s()\n", __func__); iio_device_unregister(indio_dev); + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c index f25243b..7e984bc 100644 --- a/drivers/staging/iio/light/tsl2563.c +++ b/drivers/staging/iio/light/tsl2563.c @@ -31,13 +31,12 @@ #include <linux/sched.h> #include <linux/mutex.h> #include <linux/delay.h> -#include <linux/platform_device.h> #include <linux/pm.h> -#include <linux/hwmon.h> #include <linux/err.h> #include <linux/slab.h> #include "../iio.h" +#include "../sysfs.h" #include "tsl2563.h" /* Use this many bits for fraction part. */ @@ -519,7 +518,8 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; break; default: - return -EINVAL; + ret = -EINVAL; + goto error_ret; } error_ret: @@ -527,21 +527,31 @@ error_ret: return ret; } -#define INFO_MASK (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) -#define EVENT_MASK (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | \ - IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)) -#define IIO_CHAN_2563(type, mod, proc, chan, imask, emask) \ - IIO_CHAN(type, mod, 1, proc, NULL, chan, 0, imask, 0, 0, {}, emask) - static const struct iio_chan_spec tsl2563_channels[] = { - IIO_CHAN_2563(IIO_LIGHT, 0, 1, 0, 0, 0), - IIO_CHAN_2563(IIO_INTENSITY, 1, 0, 0, INFO_MASK, EVENT_MASK), - IIO_CHAN_2563(IIO_INTENSITY, 1, 0, 1, INFO_MASK, 0), + { + .type = IIO_LIGHT, + .indexed = 1, + .channel = 0, + }, { + .type = IIO_INTENSITY, + .modified = 1, + .channel2 = IIO_MOD_LIGHT_BOTH, + .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), + .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_BOTH, + .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), + } }; static int tsl2563_read_thresh(struct iio_dev *indio_dev, - int event_code, - int *val) + u64 event_code, + int *val) { struct tsl2563_chip *chip = iio_priv(indio_dev); @@ -559,8 +569,8 @@ static int tsl2563_read_thresh(struct iio_dev *indio_dev, return 0; } -static ssize_t tsl2563_write_thresh(struct iio_dev *indio_dev, - int event_code, +static int tsl2563_write_thresh(struct iio_dev *indio_dev, + u64 event_code, int val) { struct tsl2563_chip *chip = iio_priv(indio_dev); @@ -595,8 +605,8 @@ 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, 0, - IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_LIGHT, + iio_push_event(dev_info, + IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER), @@ -608,8 +618,8 @@ static irqreturn_t tsl2563_event_handler(int irq, void *private) } static int tsl2563_write_interrupt_config(struct iio_dev *indio_dev, - int event_code, - int state) + u64 event_code, + int state) { struct tsl2563_chip *chip = iio_priv(indio_dev); int ret = 0; @@ -650,7 +660,7 @@ out: } static int tsl2563_read_interrupt_config(struct iio_dev *indio_dev, - int event_code) + u64 event_code) { struct tsl2563_chip *chip = iio_priv(indio_dev); int ret; @@ -680,7 +690,6 @@ static const struct iio_info tsl2563_info_no_irq = { static const struct iio_info tsl2563_info = { .driver_module = THIS_MODULE, - .num_interrupt_lines = 1, .read_raw = &tsl2563_read_raw, .write_raw = &tsl2563_write_raw, .read_event_value = &tsl2563_read_thresh, @@ -697,7 +706,7 @@ static int __devinit tsl2563_probe(struct i2c_client *client, struct tsl2563_platform_data *pdata = client->dev.platform_data; int err = 0; int ret; - u8 id; + u8 id = 0; indio_dev = iio_allocate_device(sizeof(*chip)); if (!indio_dev) @@ -743,9 +752,6 @@ static int __devinit tsl2563_probe(struct i2c_client *client, indio_dev->info = &tsl2563_info; else indio_dev->info = &tsl2563_info_no_irq; - ret = iio_device_register(indio_dev); - if (ret) - goto fail1; if (client->irq) { ret = request_threaded_irq(client->irq, NULL, @@ -764,12 +770,16 @@ static int __devinit tsl2563_probe(struct i2c_client *client, /* 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_device_unregister(indio_dev); + iio_free_device(indio_dev); fail1: kfree(chip); return err; @@ -779,6 +789,8 @@ 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 */ @@ -789,7 +801,8 @@ static int tsl2563_remove(struct i2c_client *client) tsl2563_set_power(chip, 0); if (client->irq) free_irq(client->irq, indio_dev); - iio_device_unregister(indio_dev); + + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 5694610..80f77cf 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -27,6 +27,7 @@ #include <linux/mutex.h> #include <linux/unistd.h> #include <linux/slab.h> +#include <linux/module.h> #include "../iio.h" #define TSL258X_MAX_DEVICE_REGS 32 @@ -68,7 +69,7 @@ enum { TSL258X_CHIP_UNKNOWN = 0, TSL258X_CHIP_WORKING = 1, TSL258X_CHIP_SUSPENDED = 2 -} TSL258X_CHIP_WORKING_STATUS; +}; /* Per-device data */ struct taos_als_info { @@ -87,7 +88,6 @@ struct taos_settings { struct tsl2583_chip { struct mutex als_mutex; struct i2c_client *client; - struct iio_dev *iio_dev; struct taos_als_info als_cur_info; struct taos_settings taos_settings; int als_time_scale; @@ -114,7 +114,7 @@ struct taos_lux { /* This structure is intentionally large to accommodate updates via sysfs. */ /* Sized to 11 = max 10 segments + 1 termination segment */ /* Assumption is is one and only one type of glass used */ -struct taos_lux taos_device_lux[11] = { +static struct taos_lux taos_device_lux[11] = { { 9830, 8520, 15729 }, { 12452, 10807, 23344 }, { 14746, 6383, 11705 }, @@ -159,8 +159,7 @@ static void taos_defaults(struct tsl2583_chip *chip) static int taos_i2c_read(struct i2c_client *client, u8 reg, u8 *val, unsigned int len) { - int ret; - int i; + int i, ret; for (i = 0; i < len; i++) { /* select register to write */ @@ -191,47 +190,47 @@ taos_i2c_read(struct i2c_client *client, u8 reg, u8 *val, unsigned int len) * the array are then used along with the time scale factor array values, to * calculate the lux. */ -static int taos_get_lux(struct i2c_client *client) +static int taos_get_lux(struct iio_dev *indio_dev) { u16 ch0, ch1; /* separated ch0/ch1 data from device */ u32 lux; /* raw lux calculated from device data */ u32 ratio; u8 buf[5]; struct taos_lux *p; - struct tsl2583_chip *chip = i2c_get_clientdata(client); + struct tsl2583_chip *chip = iio_priv(indio_dev); int i, ret; u32 ch0lux = 0; u32 ch1lux = 0; if (mutex_trylock(&chip->als_mutex) == 0) { - dev_info(&client->dev, "taos_get_lux device is busy\n"); + dev_info(&chip->client->dev, "taos_get_lux device is busy\n"); return chip->als_cur_info.lux; /* busy, so return LAST VALUE */ } if (chip->taos_chip_status != TSL258X_CHIP_WORKING) { /* device is not enabled */ - dev_err(&client->dev, "taos_get_lux device is not enabled\n"); + dev_err(&chip->client->dev, "taos_get_lux device is not enabled\n"); ret = -EBUSY ; goto out_unlock; } - ret = taos_i2c_read(client, (TSL258X_CMD_REG), &buf[0], 1); + ret = taos_i2c_read(chip->client, (TSL258X_CMD_REG), &buf[0], 1); if (ret < 0) { - dev_err(&client->dev, "taos_get_lux failed to read CMD_REG\n"); + dev_err(&chip->client->dev, "taos_get_lux failed to read CMD_REG\n"); goto out_unlock; } /* is data new & valid */ if (!(buf[0] & TSL258X_STA_ADC_INTR)) { - dev_err(&client->dev, "taos_get_lux data not valid\n"); + dev_err(&chip->client->dev, "taos_get_lux data not valid\n"); ret = chip->als_cur_info.lux; /* return LAST VALUE */ goto out_unlock; } for (i = 0; i < 4; i++) { int reg = TSL258X_CMD_REG | (TSL258X_ALS_CHAN0LO + i); - ret = taos_i2c_read(client, reg, &buf[i], 1); + ret = taos_i2c_read(chip->client, reg, &buf[i], 1); if (ret < 0) { - dev_err(&client->dev, "taos_get_lux failed to read" + dev_err(&chip->client->dev, "taos_get_lux failed to read" " register %x\n", reg); goto out_unlock; } @@ -239,11 +238,12 @@ static int taos_get_lux(struct i2c_client *client) /* clear status, really interrupt status (interrupts are off), but * we use the bit anyway - don't forget 0x80 - this is a command*/ - ret = i2c_smbus_write_byte(client, - (TSL258X_CMD_REG | TSL258X_CMD_SPL_FN | TSL258X_CMD_ALS_INT_CLR)); + ret = i2c_smbus_write_byte(chip->client, + (TSL258X_CMD_REG | TSL258X_CMD_SPL_FN | + TSL258X_CMD_ALS_INT_CLR)); if (ret < 0) { - dev_err(&client->dev, + dev_err(&chip->client->dev, "taos_i2c_write_command failed in taos_get_lux, err = %d\n", ret); goto out_unlock; /* have no data, so return failure */ @@ -285,7 +285,7 @@ static int taos_get_lux(struct i2c_client *client) /* note: lux is 31 bit max at this point */ if (ch1lux > ch0lux) { - dev_dbg(&client->dev, "No Data - Return last value\n"); + dev_dbg(&chip->client->dev, "No Data - Return last value\n"); ret = chip->als_cur_info.lux = 0; goto out_unlock; } @@ -319,54 +319,56 @@ out_unlock: * to derive actual lux). * Return updated gain_trim value. */ -int taos_als_calibrate(struct i2c_client *client) +static int taos_als_calibrate(struct iio_dev *indio_dev) { - struct tsl2583_chip *chip = i2c_get_clientdata(client); + struct tsl2583_chip *chip = iio_priv(indio_dev); u8 reg_val; unsigned int gain_trim_val; int ret; int lux_val; - ret = i2c_smbus_write_byte(client, (TSL258X_CMD_REG | TSL258X_CNTRL)); + ret = i2c_smbus_write_byte(chip->client, + (TSL258X_CMD_REG | TSL258X_CNTRL)); if (ret < 0) { - dev_err(&client->dev, + dev_err(&chip->client->dev, "taos_als_calibrate failed to reach the CNTRL register, ret=%d\n", ret); return ret; } - reg_val = i2c_smbus_read_byte(client); + reg_val = i2c_smbus_read_byte(chip->client); if ((reg_val & (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) != (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) { - dev_err(&client->dev, + dev_err(&chip->client->dev, "taos_als_calibrate failed: device not powered on with ADC enabled\n"); return -1; } - ret = i2c_smbus_write_byte(client, (TSL258X_CMD_REG | TSL258X_CNTRL)); + ret = i2c_smbus_write_byte(chip->client, + (TSL258X_CMD_REG | TSL258X_CNTRL)); if (ret < 0) { - dev_err(&client->dev, + dev_err(&chip->client->dev, "taos_als_calibrate failed to reach the STATUS register, ret=%d\n", ret); return ret; } - reg_val = i2c_smbus_read_byte(client); + reg_val = i2c_smbus_read_byte(chip->client); if ((reg_val & TSL258X_STA_ADC_VALID) != TSL258X_STA_ADC_VALID) { - dev_err(&client->dev, + dev_err(&chip->client->dev, "taos_als_calibrate failed: STATUS - ADC not valid.\n"); return -ENODATA; } - lux_val = taos_get_lux(client); + lux_val = taos_get_lux(indio_dev); if (lux_val < 0) { - dev_err(&client->dev, "taos_als_calibrate failed to get lux\n"); + dev_err(&chip->client->dev, "taos_als_calibrate failed to get lux\n"); return lux_val; } gain_trim_val = (unsigned int) (((chip->taos_settings.als_cal_target) * chip->taos_settings.als_gain_trim) / lux_val); if ((gain_trim_val < 250) || (gain_trim_val > 4000)) { - dev_err(&client->dev, + dev_err(&chip->client->dev, "taos_als_calibrate failed: trim_val of %d is out of range\n", gain_trim_val); return -ENODATA; @@ -380,21 +382,21 @@ int taos_als_calibrate(struct i2c_client *client) * Turn the device on. * Configuration must be set before calling this function. */ -static int taos_chip_on(struct i2c_client *client) +static int taos_chip_on(struct iio_dev *indio_dev) { int i; - int ret = 0; + int ret; u8 *uP; u8 utmp; int als_count; int als_time; - struct tsl2583_chip *chip = i2c_get_clientdata(client); + struct tsl2583_chip *chip = iio_priv(indio_dev); /* and make sure we're not already on */ if (chip->taos_chip_status == TSL258X_CHIP_WORKING) { /* if forcing a register update - turn off, then on */ - dev_info(&client->dev, "device is already enabled\n"); - return -EINVAL; + dev_info(&chip->client->dev, "device is already enabled\n"); + return -EINVAL; } /* determine als integration regster */ @@ -416,20 +418,21 @@ static int taos_chip_on(struct i2c_client *client) /* TSL258x Specific power-on / adc enable sequence * Power on the device 1st. */ utmp = TSL258X_CNTL_PWR_ON; - ret = i2c_smbus_write_byte_data(client, - TSL258X_CMD_REG | TSL258X_CNTRL, utmp); + ret = i2c_smbus_write_byte_data(chip->client, + TSL258X_CMD_REG | TSL258X_CNTRL, utmp); if (ret < 0) { - dev_err(&client->dev, "taos_chip_on failed on CNTRL reg.\n"); + dev_err(&chip->client->dev, "taos_chip_on failed on CNTRL reg.\n"); return -1; } /* Use the following shadow copy for our delay before enabling ADC. * Write all the registers. */ for (i = 0, uP = chip->taos_config; i < TSL258X_REG_MAX; i++) { - ret = i2c_smbus_write_byte_data(client, TSL258X_CMD_REG + i, + ret = i2c_smbus_write_byte_data(chip->client, + TSL258X_CMD_REG + i, *uP++); if (ret < 0) { - dev_err(&client->dev, + dev_err(&chip->client->dev, "taos_chip_on failed on reg %d.\n", i); return -1; } @@ -439,10 +442,11 @@ static int taos_chip_on(struct i2c_client *client) /* NOW enable the ADC * initialize the desired mode of operation */ utmp = TSL258X_CNTL_PWR_ON | TSL258X_CNTL_ADC_ENBL; - ret = i2c_smbus_write_byte_data(client, TSL258X_CMD_REG | TSL258X_CNTRL, + ret = i2c_smbus_write_byte_data(chip->client, + TSL258X_CMD_REG | TSL258X_CNTRL, utmp); if (ret < 0) { - dev_err(&client->dev, "taos_chip_on failed on 2nd CTRL reg.\n"); + dev_err(&chip->client->dev, "taos_chip_on failed on 2nd CTRL reg.\n"); return -1; } chip->taos_chip_status = TSL258X_CHIP_WORKING; @@ -450,33 +454,26 @@ static int taos_chip_on(struct i2c_client *client) return ret; } -static int taos_chip_off(struct i2c_client *client) +static int taos_chip_off(struct iio_dev *indio_dev) { - struct tsl2583_chip *chip = i2c_get_clientdata(client); + struct tsl2583_chip *chip = iio_priv(indio_dev); int ret; /* turn device off */ chip->taos_chip_status = TSL258X_CHIP_SUSPENDED; - ret = i2c_smbus_write_byte_data(client, TSL258X_CMD_REG | TSL258X_CNTRL, + ret = i2c_smbus_write_byte_data(chip->client, + TSL258X_CMD_REG | TSL258X_CNTRL, 0x00); return ret; } /* Sysfs Interface Functions */ -static ssize_t taos_device_id(struct device *dev, -struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; - - return sprintf(buf, "%s\n", chip->client->name); -} static ssize_t taos_power_state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); return sprintf(buf, "%d\n", chip->taos_chip_status); } @@ -485,16 +482,15 @@ static ssize_t taos_power_state_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; unsigned long value; if (strict_strtoul(buf, 0, &value)) return -EINVAL; if (value == 0) - taos_chip_off(chip->client); + taos_chip_off(indio_dev); else - taos_chip_on(chip->client); + taos_chip_on(indio_dev); return len; } @@ -503,7 +499,7 @@ static ssize_t taos_gain_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); char gain[4] = {0}; switch (chip->taos_settings.als_gain) { @@ -528,7 +524,7 @@ static ssize_t taos_gain_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); unsigned long value; if (strict_strtoul(buf, 0, &value)) @@ -565,7 +561,7 @@ static ssize_t taos_als_time_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); return sprintf(buf, "%d\n", chip->taos_settings.als_time); } @@ -574,7 +570,7 @@ static ssize_t taos_als_time_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); unsigned long value; if (strict_strtoul(buf, 0, &value)) @@ -586,7 +582,7 @@ static ssize_t taos_als_time_store(struct device *dev, if (value % 50) return -EINVAL; - chip->taos_settings.als_time = value; + chip->taos_settings.als_time = value; return len; } @@ -602,7 +598,7 @@ static ssize_t taos_als_trim_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); return sprintf(buf, "%d\n", chip->taos_settings.als_gain_trim); } @@ -611,7 +607,7 @@ static ssize_t taos_als_trim_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); unsigned long value; if (strict_strtoul(buf, 0, &value)) @@ -627,7 +623,7 @@ static ssize_t taos_als_cal_target_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); return sprintf(buf, "%d\n", chip->taos_settings.als_cal_target); } @@ -636,7 +632,7 @@ static ssize_t taos_als_cal_target_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); unsigned long value; if (strict_strtoul(buf, 0, &value)) @@ -651,27 +647,26 @@ static ssize_t taos_als_cal_target_store(struct device *dev, static ssize_t taos_lux_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; - int lux; + int ret; - lux = taos_get_lux(chip->client); + ret = taos_get_lux(dev_get_drvdata(dev)); + if (ret < 0) + return ret; - return sprintf(buf, "%d\n", lux); + return sprintf(buf, "%d\n", ret); } static ssize_t taos_do_calibrate(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; unsigned long value; if (strict_strtoul(buf, 0, &value)) return -EINVAL; if (value == 1) - taos_als_calibrate(chip->client); + taos_als_calibrate(indio_dev); return len; } @@ -703,8 +698,8 @@ static ssize_t taos_luxtable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; - int value[ARRAY_SIZE(taos_device_lux)]; + struct tsl2583_chip *chip = iio_priv(indio_dev); + int value[ARRAY_SIZE(taos_device_lux)*3 + 1]; int n; get_options(buf, ARRAY_SIZE(value), value); @@ -725,18 +720,17 @@ static ssize_t taos_luxtable_store(struct device *dev, } if (chip->taos_chip_status == TSL258X_CHIP_WORKING) - taos_chip_off(chip->client); + taos_chip_off(indio_dev); /* Zero out the table */ memset(taos_device_lux, 0, sizeof(taos_device_lux)); memcpy(taos_device_lux, &value[1], (value[0] * 4)); - taos_chip_on(chip->client); + taos_chip_on(indio_dev); return len; } -static DEVICE_ATTR(name, S_IRUGO, taos_device_id, NULL); static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, taos_power_state_show, taos_power_state_store); @@ -762,7 +756,6 @@ static DEVICE_ATTR(illuminance0_lux_table, S_IRUGO | S_IWUSR, taos_luxtable_show, taos_luxtable_store); static struct attribute *sysfs_attrs_ctrl[] = { - &dev_attr_name.attr, &dev_attr_power_state.attr, &dev_attr_illuminance0_calibscale.attr, /* Gain */ &dev_attr_illuminance0_calibscale_available.attr, @@ -798,9 +791,10 @@ static const struct iio_info tsl2583_info = { static int __devinit taos_probe(struct i2c_client *clientp, const struct i2c_device_id *idp) { - int i, ret = 0; + int i, ret; unsigned char buf[TSL258X_MAX_DEVICE_REGS]; - static struct tsl2583_chip *chip; + struct tsl2583_chip *chip; + struct iio_dev *indio_dev; if (!i2c_check_functionality(clientp->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { @@ -810,12 +804,15 @@ static int __devinit taos_probe(struct i2c_client *clientp, return -EOPNOTSUPP; } - chip = kzalloc(sizeof(struct tsl2583_chip), GFP_KERNEL); - if (!chip) - return -ENOMEM; - + indio_dev = iio_allocate_device(sizeof(*chip)); + if (indio_dev == NULL) { + ret = -ENOMEM; + dev_err(&clientp->dev, "iio allocation failed\n"); + goto fail1; + } + chip = iio_priv(indio_dev); chip->client = clientp; - i2c_set_clientdata(clientp, chip); + i2c_set_clientdata(clientp, indio_dev); mutex_init(&chip->als_mutex); chip->taos_chip_status = TSL258X_CHIP_UNKNOWN; @@ -827,14 +824,14 @@ static int __devinit taos_probe(struct i2c_client *clientp, if (ret < 0) { dev_err(&clientp->dev, "i2c_smbus_write_bytes() to cmd " "reg failed in taos_probe(), err = %d\n", ret); - goto fail1; + goto fail2; } ret = i2c_smbus_read_byte(clientp); if (ret < 0) { dev_err(&clientp->dev, "i2c_smbus_read_byte from " "reg failed in taos_probe(), err = %d\n", ret); - goto fail1; + goto fail2; } buf[i] = ret; } @@ -842,58 +839,50 @@ static int __devinit taos_probe(struct i2c_client *clientp, if (!taos_tsl258x_device(buf)) { dev_info(&clientp->dev, "i2c device found but does not match " "expected id in taos_probe()\n"); - goto fail1; + goto fail2; } ret = i2c_smbus_write_byte(clientp, (TSL258X_CMD_REG | TSL258X_CNTRL)); if (ret < 0) { dev_err(&clientp->dev, "i2c_smbus_write_byte() to cmd reg " "failed in taos_probe(), err = %d\n", ret); - goto fail1; - } - - chip->iio_dev = iio_allocate_device(0); - if (!chip->iio_dev) { - ret = -ENOMEM; - dev_err(&clientp->dev, "iio allocation failed\n"); - goto fail1; + goto fail2; } - chip->iio_dev->info = &tsl2583_info; - chip->iio_dev->dev.parent = &clientp->dev; - chip->iio_dev->dev_data = (void *)(chip); - chip->iio_dev->modes = INDIO_DIRECT_MODE; - ret = iio_device_register(chip->iio_dev); + indio_dev->info = &tsl2583_info; + indio_dev->dev.parent = &clientp->dev; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->name = chip->client->name; + ret = iio_device_register(indio_dev); if (ret) { dev_err(&clientp->dev, "iio registration failed\n"); - goto fail1; + goto fail2; } /* Load up the V2 defaults (these are hard coded defaults for now) */ taos_defaults(chip); /* Make sure the chip is on */ - taos_chip_on(clientp); + taos_chip_on(indio_dev); dev_info(&clientp->dev, "Light sensor found.\n"); - return 0; - fail1: - kfree(chip); - + iio_free_device(indio_dev); +fail2: return ret; } static int taos_suspend(struct i2c_client *client, pm_message_t state) { - struct tsl2583_chip *chip = i2c_get_clientdata(client); + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct tsl2583_chip *chip = iio_priv(indio_dev); int ret = 0; mutex_lock(&chip->als_mutex); if (chip->taos_chip_status == TSL258X_CHIP_WORKING) { - ret = taos_chip_off(client); + ret = taos_chip_off(indio_dev); chip->taos_chip_status = TSL258X_CHIP_SUSPENDED; } @@ -903,13 +892,14 @@ static int taos_suspend(struct i2c_client *client, pm_message_t state) static int taos_resume(struct i2c_client *client) { - struct tsl2583_chip *chip = i2c_get_clientdata(client); + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct tsl2583_chip *chip = iio_priv(indio_dev); int ret = 0; mutex_lock(&chip->als_mutex); if (chip->taos_chip_status == TSL258X_CHIP_SUSPENDED) - ret = taos_chip_on(client); + ret = taos_chip_on(indio_dev); mutex_unlock(&chip->als_mutex); return ret; @@ -918,11 +908,9 @@ static int taos_resume(struct i2c_client *client) static int __devexit taos_remove(struct i2c_client *client) { - struct tsl2583_chip *chip = i2c_get_clientdata(client); - - iio_device_unregister(chip->iio_dev); + iio_device_unregister(i2c_get_clientdata(client)); + iio_free_device(i2c_get_clientdata(client)); - kfree(chip); return 0; } diff --git a/drivers/staging/iio/magnetometer/Kconfig b/drivers/staging/iio/magnetometer/Kconfig index 81b579d..722c4e1 100644 --- a/drivers/staging/iio/magnetometer/Kconfig +++ b/drivers/staging/iio/magnetometer/Kconfig @@ -1,11 +1,12 @@ # # Magnetometer sensors # -comment "Magnetometer sensors" +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. @@ -23,3 +24,4 @@ config SENSORS_HMC5843 To compile this driver as a module, choose M here: the module will be called hmc5843 +endmenu diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c index 33919e8..8b01712 100644 --- a/drivers/staging/iio/magnetometer/ak8975.c +++ b/drivers/staging/iio/magnetometer/ak8975.c @@ -31,8 +31,7 @@ #include <linux/gpio.h> #include "../iio.h" -#include "magnet.h" - +#include "../sysfs.h" /* * Register definitions, as well as various shifts and masks to get at the * individual fields of the registers. @@ -93,38 +92,28 @@ struct ak8975_data { struct mutex lock; u8 asa[3]; long raw_to_gauss[3]; - unsigned long mode; + bool mode; u8 reg_cache[AK8975_MAX_REGS]; int eoc_gpio; int eoc_irq; }; +static const int ak8975_index_to_reg[] = { + AK8975_REG_HXL, AK8975_REG_HYL, AK8975_REG_HZL, +}; + /* * Helper function to write to the I2C device's registers. */ static int ak8975_write_data(struct i2c_client *client, u8 reg, u8 val, u8 mask, u8 shift) { - u8 regval; - struct i2c_msg msg; - u8 w_data[2]; - int ret = 0; - struct ak8975_data *data = i2c_get_clientdata(client); + u8 regval; + int ret; - regval = data->reg_cache[reg]; - regval &= ~mask; - regval |= val << shift; - - w_data[0] = reg; - w_data[1] = regval; - - msg.addr = client->addr; - msg.flags = 0; - msg.len = 2; - msg.buf = w_data; - - ret = i2c_transfer(client->adapter, &msg, 1); + regval = (data->reg_cache[reg] & ~mask) | (val << shift); + ret = i2c_smbus_write_byte_data(client, reg, regval); if (ret < 0) { dev_err(&client->dev, "Write to device fails status %x\n", ret); return ret; @@ -140,21 +129,20 @@ static int ak8975_write_data(struct i2c_client *client, static int ak8975_read_data(struct i2c_client *client, u8 reg, u8 length, u8 *buffer) { - struct i2c_msg msg[2]; - u8 w_data[2]; int ret; - - w_data[0] = reg; - - msg[0].addr = client->addr; - msg[0].flags = I2C_M_NOSTART; /* set repeated start and write */ - msg[0].len = 1; - msg[0].buf = w_data; - - msg[1].addr = client->addr; - msg[1].flags = I2C_M_RD; - msg[1].len = length; - msg[1].buf = buffer; + struct i2c_msg msg[2] = { + { + .addr = client->addr, + .flags = I2C_M_NOSTART, + .len = 1, + .buf = ®, + }, { + .addr = client->addr, + .flags = I2C_M_RD, + .len = length, + .buf = buffer, + } + }; ret = i2c_transfer(client->adapter, msg, 2); if (ret < 0) { @@ -204,8 +192,41 @@ static int ak8975_setup(struct i2c_client *client) return ret; } - /* Precalculate scale factor for each axis and - store in the device data. */ +/* + * Precalculate scale factor (in Gauss units) for each axis and + * store in the device data. + * + * This scale factor is axis-dependent, and is derived from 3 calibration + * factors ASA(x), ASA(y), and ASA(z). + * + * These ASA values are read from the sensor device at start of day, and + * cached in the device context struct. + * + * Adjusting the flux value with the sensitivity adjustment value should be + * done via the following formula: + * + * Hadj = H * ( ( ( (ASA-128)*0.5 ) / 128 ) + 1 ) + * + * where H is the raw value, ASA is the sensitivity adjustment, and Hadj + * is the resultant adjusted value. + * + * We reduce the formula to: + * + * Hadj = H * (ASA + 128) / 256 + * + * H is in the range of -4096 to 4095. The magnetometer has a range of + * +-1229uT. To go from the raw value to uT is: + * + * HuT = H * 1229/4096, or roughly, 3/10. + * + * Since 1uT = 100 gauss, our final scale factor becomes: + * + * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100 + * Hadj = H * ((ASA + 128) * 30 / 256 + * + * Since ASA doesn't change, we cache the resultant scale factor into the + * device context in ak8975_setup(). + */ data->raw_to_gauss[0] = ((data->asa[0] + 128) * 30) >> 8; data->raw_to_gauss[1] = ((data->asa[1] + 128) * 30) >> 8; data->raw_to_gauss[2] = ((data->asa[2] + 128) * 30) >> 8; @@ -222,7 +243,7 @@ static ssize_t show_mode(struct device *dev, struct device_attribute *devattr, struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ak8975_data *data = iio_priv(indio_dev); - return sprintf(buf, "%lu\n", data->mode); + return sprintf(buf, "%u\n", data->mode); } /* @@ -235,26 +256,22 @@ static ssize_t store_mode(struct device *dev, struct device_attribute *devattr, struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ak8975_data *data = iio_priv(indio_dev); struct i2c_client *client = data->client; - unsigned long oval; + bool value; int ret; /* Convert mode string and do some basic sanity checking on it. only 0 or 1 are valid. */ - if (strict_strtoul(buf, 10, &oval)) - return -EINVAL; - - if (oval > 1) { - dev_err(dev, "mode value is not supported\n"); - return -EINVAL; - } + ret = strtobool(buf, &value); + if (ret < 0) + return ret; mutex_lock(&data->lock); /* Write the mode to the device. */ - if (data->mode != oval) { + if (data->mode != value) { ret = ak8975_write_data(client, AK8975_REG_CNTL, - (u8)oval, + (u8)value, AK8975_REG_CNTL_MODE_MASK, AK8975_REG_CNTL_MODE_SHIFT); @@ -263,7 +280,7 @@ static ssize_t store_mode(struct device *dev, struct device_attribute *devattr, mutex_unlock(&data->lock); return ret; } - data->mode = oval; + data->mode = value; } mutex_unlock(&data->lock); @@ -271,50 +288,6 @@ static ssize_t store_mode(struct device *dev, struct device_attribute *devattr, return count; } -/* - * Emits the scale factor to bring the raw value into Gauss units. - * - * This scale factor is axis-dependent, and is derived from 3 calibration - * factors ASA(x), ASA(y), and ASA(z). - * - * These ASA values are read from the sensor device at start of day, and - * cached in the device context struct. - * - * Adjusting the flux value with the sensitivity adjustment value should be - * done via the following formula: - * - * Hadj = H * ( ( ( (ASA-128)*0.5 ) / 128 ) + 1 ) - * - * where H is the raw value, ASA is the sensitivity adjustment, and Hadj - * is the resultant adjusted value. - * - * We reduce the formula to: - * - * Hadj = H * (ASA + 128) / 256 - * - * H is in the range of -4096 to 4095. The magnetometer has a range of - * +-1229uT. To go from the raw value to uT is: - * - * HuT = H * 1229/4096, or roughly, 3/10. - * - * Since 1uT = 100 gauss, our final scale factor becomes: - * - * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100 - * Hadj = H * ((ASA + 128) * 30 / 256 - * - * Since ASA doesn't change, we cache the resultant scale factor into the - * device context in ak8975_setup(). - */ -static ssize_t show_scale(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ak8975_data *data = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(devattr); - - return sprintf(buf, "%ld\n", data->raw_to_gauss[this_attr->address]); -} - static int wait_conversion_complete_gpio(struct ak8975_data *data) { struct i2c_client *client = data->client; @@ -371,13 +344,10 @@ static int wait_conversion_complete_polled(struct ak8975_data *data) /* * Emits the raw flux value for the x, y, or z axis. */ -static ssize_t show_raw(struct device *dev, struct device_attribute *devattr, - char *buf) +static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ak8975_data *data = iio_priv(indio_dev); struct i2c_client *client = data->client; - struct iio_dev_attr *this_attr = to_iio_dev_attr(devattr); u16 meas_reg; s16 raw; u8 read_status; @@ -403,7 +373,7 @@ static ssize_t show_raw(struct device *dev, struct device_attribute *devattr, } /* Wait for the conversion to complete. */ - if (data->eoc_gpio) + if (gpio_is_valid(data->eoc_gpio)) ret = wait_conversion_complete_gpio(data); else ret = wait_conversion_complete_polled(data); @@ -429,7 +399,8 @@ static ssize_t show_raw(struct device *dev, struct device_attribute *devattr, /* Read the flux value from the appropriate register (the register is specified in the iio device attributes). */ - ret = ak8975_read_data(client, this_attr->address, 2, (u8 *)&meas_reg); + ret = ak8975_read_data(client, ak8975_index_to_reg[index], + 2, (u8 *)&meas_reg); if (ret < 0) { dev_err(&client->dev, "Read axis data fails\n"); goto exit; @@ -442,30 +413,48 @@ static ssize_t show_raw(struct device *dev, struct device_attribute *devattr, /* Clamp to valid range. */ raw = clamp_t(s16, raw, -4096, 4095); - - return sprintf(buf, "%d\n", raw); + *val = raw; + return IIO_VAL_INT; exit: mutex_unlock(&data->lock); return ret; } +static int ak8975_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, + long mask) +{ + struct ak8975_data *data = iio_priv(indio_dev); + + switch (mask) { + case 0: + return ak8975_read_axis(indio_dev, chan->address, val); + case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + *val = data->raw_to_gauss[chan->address]; + return IIO_VAL_INT; + } + return -EINVAL; +} + +#define AK8975_CHANNEL(axis, index) \ + { \ + .type = IIO_MAGN, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \ + .address = index, \ + } + +static const struct iio_chan_spec ak8975_channels[] = { + AK8975_CHANNEL(X, 0), AK8975_CHANNEL(Y, 1), AK8975_CHANNEL(Z, 2), +}; + static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, show_mode, store_mode, 0); -static IIO_DEV_ATTR_MAGN_X_SCALE(S_IRUGO, show_scale, NULL, 0); -static IIO_DEV_ATTR_MAGN_Y_SCALE(S_IRUGO, show_scale, NULL, 1); -static IIO_DEV_ATTR_MAGN_Z_SCALE(S_IRUGO, show_scale, NULL, 2); -static IIO_DEV_ATTR_MAGN_X(show_raw, AK8975_REG_HXL); -static IIO_DEV_ATTR_MAGN_Y(show_raw, AK8975_REG_HYL); -static IIO_DEV_ATTR_MAGN_Z(show_raw, AK8975_REG_HZL); static struct attribute *ak8975_attr[] = { &iio_dev_attr_mode.dev_attr.attr, - &iio_dev_attr_magn_x_scale.dev_attr.attr, - &iio_dev_attr_magn_y_scale.dev_attr.attr, - &iio_dev_attr_magn_z_scale.dev_attr.attr, - &iio_dev_attr_magn_x_raw.dev_attr.attr, - &iio_dev_attr_magn_y_raw.dev_attr.attr, - &iio_dev_attr_magn_z_raw.dev_attr.attr, NULL }; @@ -475,6 +464,7 @@ static struct attribute_group ak8975_attr_group = { static const struct iio_info ak8975_info = { .attrs = &ak8975_attr_group, + .read_raw = &ak8975_read_raw, .driver_module = THIS_MODULE, }; @@ -487,11 +477,14 @@ static int ak8975_probe(struct i2c_client *client, int err; /* Grab and set up the supplied GPIO. */ - eoc_gpio = irq_to_gpio(client->irq); + 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 (eoc_gpio > 0) { + if (gpio_is_valid(eoc_gpio)) { err = gpio_request(eoc_gpio, "ak_8975"); if (err < 0) { dev_err(&client->dev, @@ -507,8 +500,7 @@ static int ak8975_probe(struct i2c_client *client, eoc_gpio, err); goto exit_gpio; } - } else - eoc_gpio = 0; /* No GPIO available */ + } /* Register with IIO */ indio_dev = iio_allocate_device(sizeof(*data)); @@ -521,7 +513,7 @@ static int ak8975_probe(struct i2c_client *client, err = ak8975_setup(client); if (err < 0) { dev_err(&client->dev, "AK8975 initialization fails\n"); - goto exit_gpio; + goto exit_free_iio; } i2c_set_clientdata(client, indio_dev); @@ -530,6 +522,8 @@ static int ak8975_probe(struct i2c_client *client, data->eoc_irq = client->irq; data->eoc_gpio = eoc_gpio; indio_dev->dev.parent = &client->dev; + indio_dev->channels = ak8975_channels; + indio_dev->num_channels = ARRAY_SIZE(ak8975_channels); indio_dev->info = &ak8975_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -542,7 +536,7 @@ static int ak8975_probe(struct i2c_client *client, exit_free_iio: iio_free_device(indio_dev); exit_gpio: - if (eoc_gpio) + if (gpio_is_valid(eoc_gpio)) gpio_free(eoc_gpio); exit: return err; @@ -552,13 +546,13 @@ 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); - int eoc_gpio = data->eoc_gpio; iio_device_unregister(indio_dev); - iio_free_device(indio_dev); - if (eoc_gpio) - gpio_free(eoc_gpio); + if (gpio_is_valid(data->eoc_gpio)) + gpio_free(data->eoc_gpio); + + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index b44c273a..fc9ee97 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -24,7 +24,6 @@ #include <linux/types.h> #include "../iio.h" #include "../sysfs.h" -#include "magnet.h" #define HMC5843_I2C_ADDRESS 0x1E @@ -62,9 +61,9 @@ /* * Device status */ -#define DATA_READY 0x01 -#define DATA_OUTPUT_LOCK 0x02 -#define VOLTAGE_REGULATOR_ENABLED 0x04 +#define DATA_READY 0x01 +#define DATA_OUTPUT_LOCK 0x02 +#define VOLTAGE_REGULATOR_ENABLED 0x04 /* * Mode register configuration @@ -89,22 +88,16 @@ /* * Device Configutration */ -#define CONF_NORMAL 0x00 +#define CONF_NORMAL 0x00 #define CONF_POSITIVE_BIAS 0x01 #define CONF_NEGATIVE_BIAS 0x02 #define CONF_NOT_USED 0x03 #define MEAS_CONF_MASK 0x03 -static const char *regval_to_scale[] = { - "0.0000006173", - "0.0000007692", - "0.0000010309", - "0.0000012821", - "0.0000018868", - "0.0000021739", - "0.0000025641", - "0.0000035714", +static int hmc5843_regval_to_nanoscale[] = { + 6173, 7692, 10309, 12821, 18868, 21739, 25641, 35714 }; + static const int regval_to_input_field_mg[] = { 700, 1000, @@ -115,7 +108,7 @@ static const int regval_to_input_field_mg[] = { 4500, 6500 }; -static const char *regval_to_samp_freq[] = { +static const char * const regval_to_samp_freq[] = { "0.5", "1", "2", @@ -150,37 +143,28 @@ static s32 hmc5843_configure(struct i2c_client *client, } /* Return the measurement value from the specified channel */ -static ssize_t hmc5843_read_measurement(struct device *dev, - struct device_attribute *attr, - char *buf) +static int hmc5843_read_measurement(struct iio_dev *indio_dev, + int address, + int *val) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct i2c_client *client = to_i2c_client(indio_dev->dev.parent); - s16 coordinate_val; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct hmc5843_data *data = iio_priv(indio_dev); s32 result; mutex_lock(&data->lock); - result = i2c_smbus_read_byte_data(client, HMC5843_STATUS_REG); while (!(result & DATA_READY)) result = i2c_smbus_read_byte_data(client, HMC5843_STATUS_REG); - result = i2c_smbus_read_word_data(client, this_attr->address); + result = i2c_smbus_read_word_data(client, address); mutex_unlock(&data->lock); if (result < 0) return -EINVAL; - coordinate_val = (s16)swab16((u16)result); - return sprintf(buf, "%d\n", coordinate_val); + *val = (s16)swab16((u16)result); + return IIO_VAL_INT; } -static IIO_DEV_ATTR_MAGN_X(hmc5843_read_measurement, - HMC5843_DATA_OUT_X_MSB_REG); -static IIO_DEV_ATTR_MAGN_Y(hmc5843_read_measurement, - HMC5843_DATA_OUT_Y_MSB_REG); -static IIO_DEV_ATTR_MAGN_Z(hmc5843_read_measurement, - HMC5843_DATA_OUT_Z_MSB_REG); + /* * From the datasheet @@ -336,7 +320,7 @@ static s32 hmc5843_set_rate(struct i2c_client *client, reg_val = (data->meas_conf) | (rate << RATE_OFFSET); if (rate >= RATE_NOT_USED) { dev_err(&client->dev, - "This data output rate is not supported \n"); + "This data output rate is not supported\n"); return -EINVAL; } return i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_A, reg_val); @@ -461,34 +445,52 @@ exit: return count; } -static IIO_DEVICE_ATTR(magn_range, +static IIO_DEVICE_ATTR(in_magn_range, S_IWUSR | S_IRUGO, show_range, set_range, HMC5843_CONFIG_REG_B); -static ssize_t show_scale(struct device *dev, - struct device_attribute *attr, - char *buf) +static int hmc5843_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, + long mask) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct hmc5843_data *data = iio_priv(indio_dev); - return strlen(strcpy(buf, regval_to_scale[data->range])); + + switch (mask) { + case 0: + return hmc5843_read_measurement(indio_dev, + chan->address, + val); + case (1 << IIO_CHAN_INFO_SCALE_SHARED): + *val = 0; + *val2 = hmc5843_regval_to_nanoscale[data->range]; + return IIO_VAL_INT_PLUS_NANO; + }; + return -EINVAL; } -static IIO_DEVICE_ATTR(magn_scale, - S_IRUGO, - show_scale, - NULL , 0); + +#define HMC5843_CHANNEL(axis, add) \ + { \ + .type = IIO_MAGN, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \ + .address = add \ + } + +static const struct iio_chan_spec hmc5843_channels[] = { + HMC5843_CHANNEL(X, HMC5843_DATA_OUT_X_MSB_REG), + HMC5843_CHANNEL(Y, HMC5843_DATA_OUT_Y_MSB_REG), + HMC5843_CHANNEL(Z, HMC5843_DATA_OUT_Z_MSB_REG), +}; static struct attribute *hmc5843_attributes[] = { &iio_dev_attr_meas_conf.dev_attr.attr, &iio_dev_attr_operating_mode.dev_attr.attr, &iio_dev_attr_sampling_frequency.dev_attr.attr, - &iio_dev_attr_magn_range.dev_attr.attr, - &iio_dev_attr_magn_scale.dev_attr.attr, - &iio_dev_attr_magn_x_raw.dev_attr.attr, - &iio_dev_attr_magn_y_raw.dev_attr.attr, - &iio_dev_attr_magn_z_raw.dev_attr.attr, + &iio_dev_attr_in_magn_range.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, NULL }; @@ -530,6 +532,7 @@ static void hmc5843_init_client(struct i2c_client *client) static const struct iio_info hmc5843_info = { .attrs = &hmc5843_group, + .read_raw = &hmc5843_read_raw, .driver_module = THIS_MODULE, }; @@ -558,6 +561,9 @@ static int hmc5843_probe(struct i2c_client *client, hmc5843_init_client(client); indio_dev->info = &hmc5843_info; + indio_dev->name = id->name; + indio_dev->channels = hmc5843_channels; + indio_dev->num_channels = ARRAY_SIZE(hmc5843_channels); indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; err = iio_device_register(indio_dev); @@ -573,9 +579,11 @@ exit: 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_device_unregister(indio_dev); + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/magnetometer/magnet.h b/drivers/staging/iio/magnetometer/magnet.h deleted file mode 100644 index 1260eb7..0000000 --- a/drivers/staging/iio/magnetometer/magnet.h +++ /dev/null @@ -1,31 +0,0 @@ - -#include "../sysfs.h" - -/* Magnetometer types of attribute */ - -#define IIO_DEV_ATTR_MAGN_X_OFFSET(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(magn_x_offset, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_MAGN_Y_OFFSET(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(magn_y_offset, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_MAGN_Z_OFFSET(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(magn_z_offset, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_MAGN_X_SCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(magn_x_scale, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_MAGN_Y_SCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(magn_y_scale, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_MAGN_Z_SCALE(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(magn_z_scale, _mode, _show, _store, _addr) - -#define IIO_DEV_ATTR_MAGN_X(_show, _addr) \ - IIO_DEVICE_ATTR(magn_x_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_MAGN_Y(_show, _addr) \ - IIO_DEVICE_ATTR(magn_y_raw, S_IRUGO, _show, NULL, _addr) - -#define IIO_DEV_ATTR_MAGN_Z(_show, _addr) \ - IIO_DEVICE_ATTR(magn_z_raw, S_IRUGO, _show, NULL, _addr) diff --git a/drivers/staging/iio/meter/Kconfig b/drivers/staging/iio/meter/Kconfig index 12e36e4..d290d27 100644 --- a/drivers/staging/iio/meter/Kconfig +++ b/drivers/staging/iio/meter/Kconfig @@ -1,7 +1,7 @@ # # IIO meter drivers configuration # -comment "Active energy metering IC" +menu "Active energy metering IC" config ADE7753 tristate "Analog Devices ADE7753/6 Single-Phase Multifunction Metering IC Driver" @@ -20,8 +20,8 @@ config ADE7754 config ADE7758 tristate "Analog Devices ADE7758 Poly Phase Multifunction Energy Metering IC Driver" depends on SPI - select IIO_TRIGGER if IIO_RING_BUFFER - select IIO_SW_RING if IIO_RING_BUFFER + select IIO_TRIGGER if IIO_BUFFER + select IIO_SW_RING if IIO_BUFFER help Say yes here to build support for Analog Devices ADE7758 Polyphase Multifunction Energy Metering IC with Per Phase Information Driver. @@ -59,3 +59,5 @@ config ADE7854_SPI To compile this driver as a module, choose M here: the module will be called ade7854-spi. + +endmenu diff --git a/drivers/staging/iio/meter/Makefile b/drivers/staging/iio/meter/Makefile index 0cc7d51..de3863d 100644 --- a/drivers/staging/iio/meter/Makefile +++ b/drivers/staging/iio/meter/Makefile @@ -6,7 +6,7 @@ obj-$(CONFIG_ADE7753) += ade7753.o obj-$(CONFIG_ADE7754) += ade7754.o ade7758-y := ade7758_core.o -ade7758-$(CONFIG_IIO_RING_BUFFER) += ade7758_ring.o ade7758_trigger.o +ade7758-$(CONFIG_IIO_BUFFER) += ade7758_ring.o ade7758_trigger.o obj-$(CONFIG_ADE7758) += ade7758.o obj-$(CONFIG_ADE7759) += ade7759.o diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c index 4d1bd42..940fef6 100644 --- a/drivers/staging/iio/meter/ade7753.c +++ b/drivers/staging/iio/meter/ade7753.c @@ -8,7 +8,6 @@ #include <linux/interrupt.h> #include <linux/irq.h> -#include <linux/gpio.h> #include <linux/delay.h> #include <linux/mutex.h> #include <linux/device.h> @@ -17,6 +16,7 @@ #include <linux/slab.h> #include <linux/sysfs.h> #include <linux/list.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -453,8 +453,8 @@ out: } static IIO_DEV_ATTR_TEMP_RAW(ade7753_read_8bit); -static IIO_CONST_ATTR(temp_offset, "-25 C"); -static IIO_CONST_ATTR(temp_scale, "0.67 C"); +static IIO_CONST_ATTR(in_temp_offset, "-25 C"); +static IIO_CONST_ATTR(in_temp_scale, "0.67 C"); static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, ade7753_read_frequency, @@ -465,9 +465,9 @@ static IIO_DEV_ATTR_RESET(ade7753_write_reset); static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500"); static struct attribute *ade7753_attributes[] = { - &iio_dev_attr_temp_raw.dev_attr.attr, - &iio_const_attr_temp_offset.dev_attr.attr, - &iio_const_attr_temp_scale.dev_attr.attr, + &iio_dev_attr_in_temp_raw.dev_attr.attr, + &iio_const_attr_in_temp_offset.dev_attr.attr, + &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, @@ -512,7 +512,7 @@ static const struct iio_info ade7753_info = { static int __devinit ade7753_probe(struct spi_device *spi) { - int ret, regdone = 0; + int ret; struct ade7753_state *st; struct iio_dev *indio_dev; @@ -534,22 +534,19 @@ static int __devinit ade7753_probe(struct spi_device *spi) indio_dev->info = &ade7753_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = iio_device_register(indio_dev); + /* Get the device into a sane initial state */ + ret = ade7753_initial_setup(indio_dev); if (ret) goto error_free_dev; - regdone = 1; - /* Get the device into a sane initial state */ - ret = ade7753_initial_setup(indio_dev); + ret = iio_device_register(indio_dev); if (ret) goto error_free_dev; + return 0; error_free_dev: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ret; @@ -561,12 +558,13 @@ static int ade7753_remove(struct spi_device *spi) int ret; struct iio_dev *indio_dev = spi_get_drvdata(spi); + iio_device_unregister(indio_dev); + ret = ade7753_stop_device(&(indio_dev->dev)); if (ret) goto err_ret; - iio_device_unregister(indio_dev); - + iio_free_device(indio_dev); err_ret: return ret; } diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c index f4f85fd..33f0d32 100644 --- a/drivers/staging/iio/meter/ade7754.c +++ b/drivers/staging/iio/meter/ade7754.c @@ -8,7 +8,6 @@ #include <linux/interrupt.h> #include <linux/irq.h> -#include <linux/gpio.h> #include <linux/delay.h> #include <linux/mutex.h> #include <linux/device.h> @@ -17,6 +16,7 @@ #include <linux/slab.h> #include <linux/sysfs.h> #include <linux/list.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -472,8 +472,8 @@ out: return ret ? ret : len; } static IIO_DEV_ATTR_TEMP_RAW(ade7754_read_8bit); -static IIO_CONST_ATTR(temp_offset, "129 C"); -static IIO_CONST_ATTR(temp_scale, "4 C"); +static IIO_CONST_ATTR(in_temp_offset, "129 C"); +static IIO_CONST_ATTR(in_temp_scale, "4 C"); static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, ade7754_read_frequency, @@ -484,9 +484,9 @@ static IIO_DEV_ATTR_RESET(ade7754_write_reset); static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26000 13000 65000 33000"); static struct attribute *ade7754_attributes[] = { - &iio_dev_attr_temp_raw.dev_attr.attr, - &iio_const_attr_temp_offset.dev_attr.attr, - &iio_const_attr_temp_scale.dev_attr.attr, + &iio_dev_attr_in_temp_raw.dev_attr.attr, + &iio_const_attr_in_temp_offset.dev_attr.attr, + &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, @@ -535,7 +535,7 @@ static const struct iio_info ade7754_info = { static int __devinit ade7754_probe(struct spi_device *spi) { - int ret, regdone = 0; + int ret; struct ade7754_state *st; struct iio_dev *indio_dev; @@ -557,22 +557,18 @@ static int __devinit ade7754_probe(struct spi_device *spi) indio_dev->info = &ade7754_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - regdone = 1; - /* Get the device into a sane initial state */ ret = ade7754_initial_setup(indio_dev); if (ret) goto error_free_dev; + ret = iio_device_register(indio_dev); + if (ret) + goto error_free_dev; + return 0; error_free_dev: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ret; @@ -584,11 +580,12 @@ 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_device_unregister(indio_dev); + iio_free_device(indio_dev); err_ret: return ret; diff --git a/drivers/staging/iio/meter/ade7758.h b/drivers/staging/iio/meter/ade7758.h index fd74e15..bdd1b05 100644 --- a/drivers/staging/iio/meter/ade7758.h +++ b/drivers/staging/iio/meter/ade7758.h @@ -122,7 +122,7 @@ struct ade7758_state { u8 *tx; u8 *rx; struct mutex buf_lock; - u32 available_scan_masks[AD7758_NUM_WAVESRC]; + unsigned long available_scan_masks[AD7758_NUM_WAVESRC]; struct iio_chan_spec *ade7758_ring_channels; struct spi_transfer ring_xfer[4]; struct spi_message ring_msg; @@ -134,7 +134,7 @@ struct ade7758_state { unsigned char tx_buf[8]; }; -#ifdef CONFIG_IIO_RING_BUFFER +#ifdef CONFIG_IIO_BUFFER /* At the moment triggers are only used for ring buffer * filling. This may change! */ @@ -150,8 +150,7 @@ ssize_t ade7758_read_data_from_ring(struct device *dev, int ade7758_configure_ring(struct iio_dev *indio_dev); void ade7758_unconfigure_ring(struct iio_dev *indio_dev); -int ade7758_initialize_ring(struct iio_ring_buffer *ring); -void ade7758_uninitialize_ring(struct iio_ring_buffer *ring); +void ade7758_uninitialize_ring(struct iio_dev *indio_dev); int ade7758_set_irq(struct device *dev, bool enable); int ade7758_spi_write_reg_8(struct device *dev, @@ -159,7 +158,7 @@ int ade7758_spi_write_reg_8(struct device *dev, int ade7758_spi_read_reg_8(struct device *dev, u8 reg_address, u8 *val); -#else /* CONFIG_IIO_RING_BUFFER */ +#else /* CONFIG_IIO_BUFFER */ static inline void ade7758_remove_trigger(struct iio_dev *indio_dev) { @@ -180,9 +179,9 @@ static inline int ade7758_initialize_ring(struct iio_ring_buffer *ring) { return 0; } -static inline void ade7758_uninitialize_ring(struct iio_ring_buffer *ring) +static inline void ade7758_uninitialize_ring(struct iio_dev *indio_dev) { } -#endif /* CONFIG_IIO_RING_BUFFER */ +#endif /* CONFIG_IIO_BUFFER */ #endif diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index 299b954..c5dafbd 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -8,7 +8,6 @@ #include <linux/interrupt.h> #include <linux/irq.h> -#include <linux/gpio.h> #include <linux/delay.h> #include <linux/mutex.h> #include <linux/device.h> @@ -17,10 +16,11 @@ #include <linux/slab.h> #include <linux/sysfs.h> #include <linux/list.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" +#include "../buffer_generic.h" #include "meter.h" #include "ade7758.h" @@ -583,8 +583,8 @@ out: } static IIO_DEV_ATTR_TEMP_RAW(ade7758_read_8bit); -static IIO_CONST_ATTR(temp_offset, "129 C"); -static IIO_CONST_ATTR(temp_scale, "4 C"); +static IIO_CONST_ATTR(in_temp_offset, "129 C"); +static IIO_CONST_ATTR(in_temp_scale, "4 C"); static IIO_DEV_ATTR_AWATTHR(ade7758_read_16bit, ADE7758_AWATTHR); @@ -614,9 +614,9 @@ static IIO_DEV_ATTR_RESET(ade7758_write_reset); static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26040 13020 6510 3255"); static struct attribute *ade7758_attributes[] = { - &iio_dev_attr_temp_raw.dev_attr.attr, - &iio_const_attr_temp_offset.dev_attr.attr, - &iio_const_attr_temp_scale.dev_attr.attr, + &iio_dev_attr_in_temp_raw.dev_attr.attr, + &iio_const_attr_in_temp_offset.dev_attr.attr, + &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, @@ -662,7 +662,7 @@ static const struct attribute_group ade7758_attribute_group = { }; static struct iio_chan_spec ade7758_channels[] = { - IIO_CHAN(IIO_IN, 0, 1, 0, "raw", 0, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "raw", 0, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), AD7758_WT(AD7758_PHASE_A, AD7758_VOLTAGE), 0, IIO_ST('s', 24, 32, 0), 0), @@ -682,7 +682,7 @@ static struct iio_chan_spec ade7758_channels[] = { (1 << IIO_CHAN_INFO_SCALE_SHARED), AD7758_WT(AD7758_PHASE_A, AD7758_REACT_PWR), 4, IIO_ST('s', 24, 32, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, "raw", 1, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "raw", 1, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), AD7758_WT(AD7758_PHASE_B, AD7758_VOLTAGE), 5, IIO_ST('s', 24, 32, 0), 0), @@ -702,7 +702,7 @@ static struct iio_chan_spec ade7758_channels[] = { (1 << IIO_CHAN_INFO_SCALE_SHARED), AD7758_WT(AD7758_PHASE_B, AD7758_REACT_PWR), 9, IIO_ST('s', 24, 32, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, "raw", 2, 0, + IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "raw", 2, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), AD7758_WT(AD7758_PHASE_C, AD7758_VOLTAGE), 10, IIO_ST('s', 24, 32, 0), 0), @@ -732,7 +732,7 @@ static const struct iio_info ade7758_info = { static int __devinit ade7758_probe(struct spi_device *spi) { - int i, ret, regdone = 0; + int i, ret; struct ade7758_state *st; struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); @@ -766,7 +766,7 @@ static int __devinit ade7758_probe(struct spi_device *spi) indio_dev->modes = INDIO_DIRECT_MODE; for (i = 0; i < AD7758_NUM_WAVESRC; i++) - st->available_scan_masks[i] = 1 << i; + set_bit(i, &st->available_scan_masks[i]); indio_dev->available_scan_masks = st->available_scan_masks; @@ -774,14 +774,9 @@ static int __devinit ade7758_probe(struct spi_device *spi) if (ret) goto error_free_tx; - ret = iio_device_register(indio_dev); - if (ret) - goto error_unreg_ring_funcs; - regdone = 1; - - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - &ade7758_channels[0], - ARRAY_SIZE(ade7758_channels)); + ret = iio_buffer_register(indio_dev, + &ade7758_channels[0], + ARRAY_SIZE(ade7758_channels)); if (ret) { dev_err(&spi->dev, "failed to initialize the ring\n"); goto error_unreg_ring_funcs; @@ -795,16 +790,20 @@ static int __devinit ade7758_probe(struct spi_device *spi) if (spi->irq) { ret = ade7758_probe_trigger(indio_dev); if (ret) - goto error_remove_trigger; + goto error_uninitialize_ring; } + ret = iio_device_register(indio_dev); + if (ret) + goto error_remove_trigger; + return 0; error_remove_trigger: - if (indio_dev->modes & INDIO_RING_TRIGGERED) + if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) ade7758_remove_trigger(indio_dev); error_uninitialize_ring: - ade7758_uninitialize_ring(indio_dev->ring); + ade7758_uninitialize_ring(indio_dev); error_unreg_ring_funcs: ade7758_unconfigure_ring(indio_dev); error_free_tx: @@ -812,10 +811,7 @@ error_free_tx: error_free_rx: kfree(st->rx); error_free_dev: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ret; } @@ -826,18 +822,19 @@ static int ade7758_remove(struct spi_device *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_remove_trigger(indio_dev); - ade7758_uninitialize_ring(indio_dev->ring); + ade7758_uninitialize_ring(indio_dev); ade7758_unconfigure_ring(indio_dev); kfree(st->tx); kfree(st->rx); - iio_device_unregister(indio_dev); - return 0; + iio_free_device(indio_dev); + err_ret: return ret; } diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c index b89b7f8..99ade65 100644 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ b/drivers/staging/iio/meter/ade7758_ring.c @@ -6,23 +6,14 @@ * Licensed under the GPL-2. */ #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/workqueue.h> -#include <linux/mutex.h> -#include <linux/device.h> #include <linux/kernel.h> #include <linux/spi/spi.h> #include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/list.h> #include <asm/unaligned.h> #include "../iio.h" -#include "../sysfs.h" #include "../ring_sw.h" -#include "../accel/accel.h" -#include "../trigger.h" +#include "../trigger_consumer.h" #include "ade7758.h" /** @@ -69,8 +60,8 @@ out: static irqreturn_t ade7758_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->private_data; - struct iio_ring_buffer *ring = indio_dev->ring; + 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; @@ -100,14 +91,14 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p) static int ade7758_ring_preenable(struct iio_dev *indio_dev) { struct ade7758_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; + struct iio_buffer *ring = indio_dev->buffer; size_t d_size; unsigned channel; if (!ring->scan_count) return -EINVAL; - channel = __ffs(ring->scan_mask); + channel = find_first_bit(ring->scan_mask, indio_dev->masklength); d_size = st->ade7758_ring_channels[channel].scan_type.storagebits / 8; @@ -118,9 +109,9 @@ static int ade7758_ring_preenable(struct iio_dev *indio_dev) d_size += sizeof(s64) - (d_size % sizeof(s64)); } - if (indio_dev->ring->access->set_bytes_per_datum) - indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring, - d_size); + 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); @@ -128,22 +119,16 @@ static int ade7758_ring_preenable(struct iio_dev *indio_dev) return 0; } -static const struct iio_ring_setup_ops ade7758_ring_setup_ops = { +static const struct iio_buffer_setup_ops ade7758_ring_setup_ops = { .preenable = &ade7758_ring_preenable, - .postenable = &iio_triggered_ring_postenable, - .predisable = &iio_triggered_ring_predisable, + .postenable = &iio_triggered_buffer_postenable, + .predisable = &iio_triggered_buffer_predisable, }; void ade7758_unconfigure_ring(struct iio_dev *indio_dev) { - /* ensure that the trigger has been detached */ - if (indio_dev->trig) { - iio_put_trigger(indio_dev->trig); - iio_trigger_dettach_poll_func(indio_dev->trig, - indio_dev->pollfunc); - } iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); } int ade7758_configure_ring(struct iio_dev *indio_dev) @@ -151,16 +136,16 @@ int ade7758_configure_ring(struct iio_dev *indio_dev) struct ade7758_state *st = iio_priv(indio_dev); int ret = 0; - indio_dev->ring = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->ring) { + indio_dev->buffer = iio_sw_rb_allocate(indio_dev); + if (!indio_dev->buffer) { ret = -ENOMEM; return ret; } /* Effectively select the ring buffer implementation */ - indio_dev->ring->access = &ring_sw_access_funcs; - indio_dev->ring->setup_ops = &ade7758_ring_setup_ops; - indio_dev->ring->owner = THIS_MODULE; + indio_dev->buffer->access = &ring_sw_access_funcs; + indio_dev->buffer->setup_ops = &ade7758_ring_setup_ops; + indio_dev->buffer->owner = THIS_MODULE; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &ade7758_trigger_handler, @@ -173,7 +158,7 @@ int ade7758_configure_ring(struct iio_dev *indio_dev) goto error_iio_sw_rb_free; } - indio_dev->modes |= INDIO_RING_TRIGGERED; + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; st->tx_buf[0] = ADE7758_READ_REG(ADE7758_RSTATUS); st->tx_buf[1] = 0; @@ -211,11 +196,11 @@ int ade7758_configure_ring(struct iio_dev *indio_dev) return 0; error_iio_sw_rb_free: - iio_sw_rb_free(indio_dev->ring); + iio_sw_rb_free(indio_dev->buffer); return ret; } -void ade7758_uninitialize_ring(struct iio_ring_buffer *ring) +void ade7758_uninitialize_ring(struct iio_dev *indio_dev) { - iio_ring_buffer_unregister(ring); + iio_buffer_unregister(indio_dev); } diff --git a/drivers/staging/iio/meter/ade7758_trigger.c b/drivers/staging/iio/meter/ade7758_trigger.c index a5c3248..392dfe3 100644 --- a/drivers/staging/iio/meter/ade7758_trigger.c +++ b/drivers/staging/iio/meter/ade7758_trigger.c @@ -7,16 +7,10 @@ */ #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/mutex.h> -#include <linux/device.h> #include <linux/kernel.h> -#include <linux/sysfs.h> -#include <linux/list.h> #include <linux/spi/spi.h> #include "../iio.h" -#include "../sysfs.h" #include "../trigger.h" #include "ade7758.h" @@ -57,6 +51,12 @@ static int ade7758_trig_try_reen(struct iio_trigger *trig) return 0; } +static const struct iio_trigger_ops ade7758_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = &ade7758_data_rdy_trigger_set_state, + .try_reenable = &ade7758_trig_try_reen, +}; + int ade7758_probe_trigger(struct iio_dev *indio_dev) { struct ade7758_state *st = iio_priv(indio_dev); @@ -79,10 +79,8 @@ int ade7758_probe_trigger(struct iio_dev *indio_dev) goto error_free_trig; st->trig->dev.parent = &st->us->dev; - st->trig->owner = THIS_MODULE; + st->trig->ops = &ade7758_trigger_ops; st->trig->private_data = indio_dev; - st->trig->set_trigger_state = &ade7758_data_rdy_trigger_set_state; - st->trig->try_reenable = &ade7758_trig_try_reen; ret = iio_trigger_register(st->trig); /* select default trigger */ diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c index a51a64c..b691f10 100644 --- a/drivers/staging/iio/meter/ade7759.c +++ b/drivers/staging/iio/meter/ade7759.c @@ -8,7 +8,6 @@ #include <linux/interrupt.h> #include <linux/irq.h> -#include <linux/gpio.h> #include <linux/delay.h> #include <linux/mutex.h> #include <linux/device.h> @@ -17,6 +16,7 @@ #include <linux/slab.h> #include <linux/sysfs.h> #include <linux/list.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -412,8 +412,8 @@ out: return ret ? ret : len; } static IIO_DEV_ATTR_TEMP_RAW(ade7759_read_8bit); -static IIO_CONST_ATTR(temp_offset, "70 C"); -static IIO_CONST_ATTR(temp_scale, "1 C"); +static IIO_CONST_ATTR(in_temp_offset, "70 C"); +static IIO_CONST_ATTR(in_temp_scale, "1 C"); static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, ade7759_read_frequency, @@ -424,9 +424,9 @@ static IIO_DEV_ATTR_RESET(ade7759_write_reset); static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500"); static struct attribute *ade7759_attributes[] = { - &iio_dev_attr_temp_raw.dev_attr.attr, - &iio_const_attr_temp_offset.dev_attr.attr, - &iio_const_attr_temp_scale.dev_attr.attr, + &iio_dev_attr_in_temp_raw.dev_attr.attr, + &iio_const_attr_in_temp_offset.dev_attr.attr, + &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, @@ -479,19 +479,17 @@ static int __devinit ade7759_probe(struct spi_device *spi) indio_dev->info = &ade7759_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = iio_device_register(indio_dev); + /* Get the device into a sane initial state */ + ret = ade7759_initial_setup(indio_dev); if (ret) goto error_free_dev; - /* Get the device into a sane initial state */ - ret = ade7759_initial_setup(indio_dev); + ret = iio_device_register(indio_dev); if (ret) - goto error_unreg_dev; - return 0; + goto error_free_dev; + return 0; -error_unreg_dev: - iio_device_unregister(indio_dev); error_free_dev: iio_free_device(indio_dev); error_ret: @@ -504,11 +502,12 @@ 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_device_unregister(indio_dev); + iio_free_device(indio_dev); err_ret: return ret; diff --git a/drivers/staging/iio/meter/ade7854-i2c.c b/drivers/staging/iio/meter/ade7854-i2c.c index dd72343..cbca3fd 100644 --- a/drivers/staging/iio/meter/ade7854-i2c.c +++ b/drivers/staging/iio/meter/ade7854-i2c.c @@ -10,6 +10,7 @@ #include <linux/kernel.h> #include <linux/i2c.h> #include <linux/slab.h> +#include <linux/module.h> #include "../iio.h" #include "ade7854.h" diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c index e0d1086..cfa23ba 100644 --- a/drivers/staging/iio/meter/ade7854-spi.c +++ b/drivers/staging/iio/meter/ade7854-spi.c @@ -10,6 +10,7 @@ #include <linux/kernel.h> #include <linux/spi/spi.h> #include <linux/slab.h> +#include <linux/module.h> #include "../iio.h" #include "ade7854.h" diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c index b82659f..49c01c5 100644 --- a/drivers/staging/iio/meter/ade7854.c +++ b/drivers/staging/iio/meter/ade7854.c @@ -8,7 +8,6 @@ #include <linux/interrupt.h> #include <linux/irq.h> -#include <linux/gpio.h> #include <linux/delay.h> #include <linux/mutex.h> #include <linux/device.h> @@ -16,6 +15,7 @@ #include <linux/slab.h> #include <linux/sysfs.h> #include <linux/list.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -582,7 +582,7 @@ error_unreg_dev: iio_device_unregister(indio_dev); error_free_dev: iio_free_device(indio_dev); -error_ret: + return ret; } EXPORT_SYMBOL(ade7854_probe); @@ -590,6 +590,7 @@ 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/resolver/Kconfig b/drivers/staging/iio/resolver/Kconfig index 6ecd79e..49f69ef 100644 --- a/drivers/staging/iio/resolver/Kconfig +++ b/drivers/staging/iio/resolver/Kconfig @@ -1,7 +1,7 @@ # # Resolver/Synchro drivers # -comment "Resolver to digital converters" +menu "Resolver to digital converters" config AD2S90 tristate "Analog Devices ad2s90 driver" @@ -10,9 +10,10 @@ config AD2S90 Say yes here to build support for Analog Devices spi resolver to digital converters, ad2s90, provides direct access via sysfs. -config AD2S120X - tristate "Analog Devices ad2s120x driver" +config AD2S1200 + tristate "Analog Devices ad2s1200/ad2s1205 driver" depends on SPI + depends on GENERIC_GPIO help Say yes here to build support for Analog Devices spi resolver to digital converters, ad2s1200 and ad2s1205, provides direct access @@ -21,7 +22,9 @@ config AD2S120X config AD2S1210 tristate "Analog Devices ad2s1210 driver" depends on SPI + depends on GENERIC_GPIO help Say yes here to build support for Analog Devices spi resolver to digital converters, ad2s1210, provides direct access via sysfs. +endmenu diff --git a/drivers/staging/iio/resolver/Makefile b/drivers/staging/iio/resolver/Makefile index 0b84a89..14375e4 100644 --- a/drivers/staging/iio/resolver/Makefile +++ b/drivers/staging/iio/resolver/Makefile @@ -3,5 +3,5 @@ # obj-$(CONFIG_AD2S90) += ad2s90.o -obj-$(CONFIG_AD2S120X) += ad2s120x.o +obj-$(CONFIG_AD2S1200) += ad2s1200.o obj-$(CONFIG_AD2S1210) += ad2s1210.o diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c new file mode 100644 index 0000000..d7ad46a --- /dev/null +++ b/drivers/staging/iio/resolver/ad2s1200.c @@ -0,0 +1,188 @@ +/* + * ad2s1200.c simple support for the ADI Resolver to Digital Converters: + * AD2S1200/1205 + * + * Copyright (c) 2010-2010 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/types.h> +#include <linux/mutex.h> +#include <linux/device.h> +#include <linux/spi/spi.h> +#include <linux/slab.h> +#include <linux/sysfs.h> +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/module.h> + +#include "../iio.h" +#include "../sysfs.h" + +#define DRV_NAME "ad2s1200" + +/* input pin sample and rdvel is controlled by driver */ +#define AD2S1200_PN 2 + +/* input clock on serial interface */ +#define AD2S1200_HZ 8192000 +/* clock period in nano second */ +#define AD2S1200_TSCLK (1000000000/AD2S1200_HZ) + +struct ad2s1200_state { + struct mutex lock; + struct spi_device *sdev; + int sample; + int rdvel; + u8 rx[2] ____cacheline_aligned; +}; + +static int ad2s1200_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + int ret = 0; + s16 vel; + struct ad2s1200_state *st = iio_priv(indio_dev); + + mutex_lock(&st->lock); + gpio_set_value(st->sample, 0); + /* delay (6 * AD2S1200_TSCLK + 20) nano seconds */ + udelay(1); + gpio_set_value(st->sample, 1); + gpio_set_value(st->rdvel, !!(chan->type == IIO_ANGL)); + ret = spi_read(st->sdev, st->rx, 2); + if (ret < 0) { + mutex_unlock(&st->lock); + return ret; + } + + switch (chan->type) { + case IIO_ANGL: + *val = (((u16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); + break; + case IIO_ANGL_VEL: + vel = (((s16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); + vel = (vel << 4) >> 4; + *val = vel; + default: + mutex_unlock(&st->lock); + return -EINVAL; + } + /* delay (2 * AD2S1200_TSCLK + 20) ns for sample pulse */ + udelay(1); + mutex_unlock(&st->lock); + return IIO_VAL_INT; +} + +static const struct iio_chan_spec ad2s1200_channels[] = { + { + .type = IIO_ANGL, + .indexed = 1, + .channel = 0, + }, { + .type = IIO_ANGL_VEL, + .indexed = 1, + .channel = 0, + } +}; + +static const struct iio_info ad2s1200_info = { + .read_raw = &ad2s1200_read_raw, + .driver_module = THIS_MODULE, +}; + +static int __devinit 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; + } + indio_dev = iio_allocate_device(sizeof(*st)); + if (indio_dev == NULL) { + ret = -ENOMEM; + goto error_ret; + } + spi_set_drvdata(spi, indio_dev); + st = iio_priv(indio_dev); + mutex_init(&st->lock); + st->sdev = spi; + st->sample = pins[0]; + st->rdvel = pins[1]; + + indio_dev->dev.parent = &spi->dev; + indio_dev->info = &ad2s1200_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ad2s1200_channels; + indio_dev->num_channels = ARRAY_SIZE(ad2s1200_channels); + indio_dev->name = spi_get_device_id(spi)->name; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_free_dev; + + 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[] = { + { "ad2s1200" }, + { "ad2s1205" }, + {} +}; + +static struct spi_driver ad2s1200_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = ad2s1200_probe, + .remove = __devexit_p(ad2s1200_remove), + .id_table = ad2s1200_id, +}; + +static __init int ad2s1200_spi_init(void) +{ + return spi_register_driver(&ad2s1200_driver); +} +module_init(ad2s1200_spi_init); + +static __exit void ad2s1200_spi_exit(void) +{ + spi_unregister_driver(&ad2s1200_driver); +} +module_exit(ad2s1200_spi_exit); + +MODULE_AUTHOR("Graff Yang <graff.yang@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices AD2S1200/1205 Resolver to Digital SPI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/resolver/ad2s120x.c b/drivers/staging/iio/resolver/ad2s120x.c deleted file mode 100644 index bed4c72..0000000 --- a/drivers/staging/iio/resolver/ad2s120x.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * ad2s120x.c simple support for the ADI Resolver to Digital Converters: AD2S1200/1205 - * - * Copyright (c) 2010-2010 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/types.h> -#include <linux/mutex.h> -#include <linux/device.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/delay.h> -#include <linux/gpio.h> - -#include "../iio.h" -#include "../sysfs.h" - -#define DRV_NAME "ad2s120x" - -/* input pin sample and rdvel is controlled by driver */ -#define AD2S120X_PN 2 - -/* input clock on serial interface */ -#define AD2S120X_HZ 8192000 -/* clock period in nano second */ -#define AD2S120X_TSCLK (1000000000/AD2S120X_HZ) - -struct ad2s120x_state { - struct mutex lock; - struct spi_device *sdev; - int sample; - int rdvel; - u8 rx[2] ____cacheline_aligned; -}; - -static ssize_t ad2s120x_show_val(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int ret = 0; - ssize_t len = 0; - u16 pos; - s16 vel; - u8 status; - struct ad2s120x_state *st = iio_priv(dev_get_drvdata(dev)); - struct iio_dev_attr *iattr = to_iio_dev_attr(attr); - - mutex_lock(&st->lock); - - gpio_set_value(st->sample, 0); - /* delay (6 * AD2S120X_TSCLK + 20) nano seconds */ - udelay(1); - gpio_set_value(st->sample, 1); - gpio_set_value(st->rdvel, iattr->address); - ret = spi_read(st->sdev, st->rx, 2); - if (ret < 0) - goto error_ret; - status = st->rx[1]; - if (iattr->address) - pos = (((u16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); - else { - vel = (st->rx[0] & 0x80) ? 0xf000 : 0; - vel |= (((s16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); - } - len = sprintf(buf, "%d %c%c%c%c ", iattr->address ? pos : vel, - (status & 0x8) ? 'P' : 'V', - (status & 0x4) ? 'd' : '_', - (status & 0x2) ? 'l' : '_', - (status & 0x1) ? '1' : '0'); -error_ret: - /* delay (2 * AD2S120X_TSCLK + 20) ns for sample pulse */ - udelay(1); - mutex_unlock(&st->lock); - - return ret ? ret : len; -} - -static IIO_DEVICE_ATTR(pos, S_IRUGO, ad2s120x_show_val, NULL, 1); -static IIO_DEVICE_ATTR(vel, S_IRUGO, ad2s120x_show_val, NULL, 0); - -static struct attribute *ad2s120x_attributes[] = { - &iio_dev_attr_pos.dev_attr.attr, - &iio_dev_attr_vel.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad2s120x_attribute_group = { - .attrs = ad2s120x_attributes, -}; - -static const struct iio_info ad2s120x_info = { - .attrs = &ad2s120x_attribute_group, - .driver_module = THIS_MODULE, -}; - -static int __devinit ad2s120x_probe(struct spi_device *spi) -{ - struct ad2s120x_state *st; - struct iio_dev *indio_dev; - int pn, ret = 0; - unsigned short *pins = spi->dev.platform_data; - - for (pn = 0; pn < AD2S120X_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; - } - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - spi_set_drvdata(spi, indio_dev); - st = iio_priv(indio_dev); - mutex_init(&st->lock); - st->sdev = spi; - st->sample = pins[0]; - st->rdvel = pins[1]; - - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &ad2s120x_info; - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - - spi->max_speed_hz = AD2S120X_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 ad2s120x_remove(struct spi_device *spi) -{ - iio_device_unregister(spi_get_drvdata(spi)); - - return 0; -} - -static struct spi_driver ad2s120x_driver = { - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - }, - .probe = ad2s120x_probe, - .remove = __devexit_p(ad2s120x_remove), -}; - -static __init int ad2s120x_spi_init(void) -{ - return spi_register_driver(&ad2s120x_driver); -} -module_init(ad2s120x_spi_init); - -static __exit void ad2s120x_spi_exit(void) -{ - spi_unregister_driver(&ad2s120x_driver); -} -module_exit(ad2s120x_spi_exit); - -MODULE_AUTHOR("Graff Yang <graff.yang@gmail.com>"); -MODULE_DESCRIPTION("Analog Devices AD2S1200/1205 Resolver to Digital SPI driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c index ecaf7bb..6401a62 100644 --- a/drivers/staging/iio/resolver/ad2s1210.c +++ b/drivers/staging/iio/resolver/ad2s1210.c @@ -16,6 +16,7 @@ #include <linux/sysfs.h> #include <linux/delay.h> #include <linux/gpio.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" @@ -194,47 +195,6 @@ static inline int ad2s1210_soft_reset(struct ad2s1210_state *st) return ad2s1210_config_write(st, 0x0); } - -/* return the OLD DATA since last spi bus write */ -static ssize_t ad2s1210_show_raw(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); - int ret = 0; - - mutex_lock(&st->lock); - if (st->old_data) { - ret = sprintf(buf, "0x%x\n", st->rx[0]); - st->old_data = false; - } - mutex_unlock(&st->lock); - - return ret; -} - -static ssize_t ad2s1210_store_raw(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; - unsigned char data; - int ret; - - ret = strict_strtoul(buf, 16, &udata); - if (ret) - return -EINVAL; - - data = udata & 0xff; - mutex_lock(&st->lock); - ret = ad2s1210_config_write(st, data); - mutex_unlock(&st->lock); - - return ret < 0 ? ret : len; -} - static ssize_t ad2s1210_store_softreset(struct device *dev, struct device_attribute *attr, const char *buf, @@ -513,75 +473,72 @@ error_ret: return ret < 0 ? ret : len; } -static ssize_t ad2s1210_show_pos(struct device *dev, - struct device_attribute *attr, - char *buf) +static int ad2s1210_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) { + struct ad2s1210_state *st = iio_priv(indio_dev); + bool negative; int ret = 0; - ssize_t len = 0; u16 pos; - struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); - - mutex_lock(&st->lock); - gpio_set_value(st->pdata->sample, 0); - /* delay (6 * tck + 20) nano seconds */ - udelay(1); - - ad2s1210_set_mode(MOD_POS, st); - ret = spi_read(st->sdev, st->rx, 2); - if (ret) - goto error_ret; - pos = be16_to_cpup((u16 *)st->rx); - if (st->hysteresis) - pos >>= 16 - st->resolution; - len = sprintf(buf, "%d\n", pos); -error_ret: - gpio_set_value(st->pdata->sample, 1); - /* delay (2 * tck + 20) nano seconds */ - udelay(1); - mutex_unlock(&st->lock); - - return ret < 0 ? ret : len; -} - -static ssize_t ad2s1210_show_vel(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - unsigned short negative; - int ret = 0; - ssize_t len = 0; s16 vel; - struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); mutex_lock(&st->lock); gpio_set_value(st->pdata->sample, 0); /* delay (6 * tck + 20) nano seconds */ udelay(1); - ad2s1210_set_mode(MOD_VEL, st); + switch (chan->type) { + case IIO_ANGL: + ad2s1210_set_mode(MOD_POS, st); + break; + case IIO_ANGL_VEL: + ad2s1210_set_mode(MOD_VEL, st); + break; + default: + ret = -EINVAL; + break; + } + if (ret < 0) + goto error_ret; ret = spi_read(st->sdev, st->rx, 2); - if (ret) + if (ret < 0) goto error_ret; - negative = st->rx[0] & 0x80; - vel = be16_to_cpup((s16 *)st->rx); - vel >>= 16 - st->resolution; - if (vel & 0x8000) { - negative = (0xffff >> st->resolution) << st->resolution; - vel |= negative; + + switch (chan->type) { + case IIO_ANGL: + pos = be16_to_cpup((u16 *)st->rx); + if (st->hysteresis) + pos >>= 16 - st->resolution; + *val = pos; + ret = IIO_VAL_INT; + break; + case IIO_ANGL_VEL: + negative = st->rx[0] & 0x80; + vel = be16_to_cpup((s16 *)st->rx); + vel >>= 16 - st->resolution; + if (vel & 0x8000) { + negative = (0xffff >> st->resolution) << st->resolution; + vel |= negative; + } + *val = vel; + ret = IIO_VAL_INT; + break; + default: + mutex_unlock(&st->lock); + return -EINVAL; } - len = sprintf(buf, "%d\n", vel); + error_ret: gpio_set_value(st->pdata->sample, 1); /* delay (2 * tck + 20) nano seconds */ udelay(1); mutex_unlock(&st->lock); - - return ret < 0 ? ret : len; + return ret; } -static IIO_DEVICE_ATTR(raw_io, S_IRUGO | S_IWUSR, - ad2s1210_show_raw, ad2s1210_store_raw, 0); static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, ad2s1210_store_softreset, 0); static IIO_DEVICE_ATTR(fclkin, S_IRUGO | S_IWUSR, @@ -594,8 +551,7 @@ static IIO_DEVICE_ATTR(bits, S_IRUGO | S_IWUSR, ad2s1210_show_resolution, ad2s1210_store_resolution, 0); static IIO_DEVICE_ATTR(fault, S_IRUGO | S_IWUSR, ad2s1210_show_fault, ad2s1210_clear_fault, 0); -static IIO_DEVICE_ATTR(pos, S_IRUGO, ad2s1210_show_pos, NULL, 0); -static IIO_DEVICE_ATTR(vel, S_IRUGO, ad2s1210_show_vel, NULL, 0); + static IIO_DEVICE_ATTR(los_thrd, S_IRUGO | S_IWUSR, ad2s1210_show_reg, ad2s1210_store_reg, AD2S1210_REG_LOS_THRD); @@ -618,16 +574,26 @@ static IIO_DEVICE_ATTR(lot_low_thrd, S_IRUGO | S_IWUSR, ad2s1210_show_reg, ad2s1210_store_reg, AD2S1210_REG_LOT_LOW_THRD); + +static struct iio_chan_spec ad2s1210_channels[] = { + { + .type = IIO_ANGL, + .indexed = 1, + .channel = 0, + }, { + .type = IIO_ANGL_VEL, + .indexed = 1, + .channel = 0, + } +}; + static struct attribute *ad2s1210_attributes[] = { - &iio_dev_attr_raw_io.dev_attr.attr, &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, &iio_dev_attr_bits.dev_attr.attr, &iio_dev_attr_fault.dev_attr.attr, - &iio_dev_attr_pos.dev_attr.attr, - &iio_dev_attr_vel.dev_attr.attr, &iio_dev_attr_los_thrd.dev_attr.attr, &iio_dev_attr_dos_ovr_thrd.dev_attr.attr, &iio_dev_attr_dos_mis_thrd.dev_attr.attr, @@ -639,7 +605,6 @@ static struct attribute *ad2s1210_attributes[] = { }; static const struct attribute_group ad2s1210_attribute_group = { - .name = DRV_NAME, .attrs = ad2s1210_attributes, }; @@ -681,51 +646,37 @@ error_ret: } static const struct iio_info ad2s1210_info = { + .read_raw = &ad2s1210_read_raw, .attrs = &ad2s1210_attribute_group, .driver_module = THIS_MODULE, }; static int ad2s1210_setup_gpios(struct ad2s1210_state *st) { - int ret; unsigned long flags = st->pdata->gpioin ? GPIOF_DIR_IN : GPIOF_DIR_OUT; + struct gpio ad2s1210_gpios[] = { + { st->pdata->sample, GPIOF_DIR_IN, "sample" }, + { st->pdata->a[0], flags, "a0" }, + { st->pdata->a[1], flags, "a1" }, + { st->pdata->res[0], flags, "res0" }, + { st->pdata->res[0], flags, "res1" }, + }; - ret = gpio_request_one(st->pdata->sample, GPIOF_DIR_IN, "sample"); - if (ret < 0) - goto error_ret; - ret = gpio_request_one(st->pdata->a[0], flags, "a0"); - if (ret < 0) - goto error_free_sample; - ret = gpio_request_one(st->pdata->a[1], flags, "a1"); - if (ret < 0) - goto error_free_a0; - ret = gpio_request_one(st->pdata->res[1], flags, "res0"); - if (ret < 0) - goto error_free_a1; - ret = gpio_request_one(st->pdata->res[1], flags, "res1"); - if (ret < 0) - goto error_free_res0; - - return 0; -error_free_res0: - gpio_free(st->pdata->res[0]); -error_free_a1: - gpio_free(st->pdata->a[1]); -error_free_a0: - gpio_free(st->pdata->a[0]); -error_free_sample: - gpio_free(st->pdata->sample); -error_ret: - return ret; + return gpio_request_array(ad2s1210_gpios, ARRAY_SIZE(ad2s1210_gpios)); } static void ad2s1210_free_gpios(struct ad2s1210_state *st) { - gpio_free(st->pdata->res[1]); - gpio_free(st->pdata->res[0]); - gpio_free(st->pdata->a[1]); - gpio_free(st->pdata->a[0]); - gpio_free(st->pdata->sample); + unsigned long flags = st->pdata->gpioin ? GPIOF_DIR_IN : GPIOF_DIR_OUT; + struct gpio ad2s1210_gpios[] = { + { st->pdata->sample, GPIOF_DIR_IN, "sample" }, + { st->pdata->a[0], flags, "a0" }, + { st->pdata->a[1], flags, "a1" }, + { st->pdata->res[0], flags, "res0" }, + { st->pdata->res[0], flags, "res1" }, + }; + + gpio_free_array(ad2s1210_gpios, ARRAY_SIZE(ad2s1210_gpios)); } static int __devinit ad2s1210_probe(struct spi_device *spi) @@ -760,6 +711,9 @@ static int __devinit ad2s1210_probe(struct spi_device *spi) indio_dev->dev.parent = &spi->dev; indio_dev->info = &ad2s1210_info; indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ad2s1210_channels; + indio_dev->num_channels = ARRAY_SIZE(ad2s1210_channels); + indio_dev->name = spi_get_device_id(spi)->name; ret = iio_device_register(indio_dev); if (ret) @@ -783,13 +737,19 @@ error_ret: static int __devexit ad2s1210_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad2s1210_state *st = iio_priv(indio_dev); + iio_device_unregister(indio_dev); - ad2s1210_free_gpios(st); + ad2s1210_free_gpios(iio_priv(indio_dev)); + iio_free_device(indio_dev); return 0; } +static const struct spi_device_id ad2s1210_id[] = { + { "ad2s1210" }, + {} +}; + static struct spi_driver ad2s1210_driver = { .driver = { .name = DRV_NAME, @@ -797,6 +757,7 @@ static struct spi_driver ad2s1210_driver = { }, .probe = ad2s1210_probe, .remove = __devexit_p(ad2s1210_remove), + .id_table = ad2s1210_id, }; static __init int ad2s1210_spi_init(void) diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c index 166e241..a9200d9 100644 --- a/drivers/staging/iio/resolver/ad2s90.c +++ b/drivers/staging/iio/resolver/ad2s90.c @@ -14,59 +14,49 @@ #include <linux/spi/spi.h> #include <linux/slab.h> #include <linux/sysfs.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#define DRV_NAME "ad2s90" - struct ad2s90_state { struct mutex lock; - struct iio_dev *idev; struct spi_device *sdev; u8 rx[2] ____cacheline_aligned; }; -static ssize_t ad2s90_show_angular(struct device *dev, - struct device_attribute *attr, char *buf) +static int ad2s90_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) { int ret; - ssize_t len = 0; - u16 val; - struct ad2s90_state *st = iio_priv(dev_get_drvdata(dev)); + struct ad2s90_state *st = iio_priv(indio_dev); mutex_lock(&st->lock); ret = spi_read(st->sdev, st->rx, 2); if (ret) goto error_ret; - val = (((u16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); - len = sprintf(buf, "%d\n", val); + *val = (((u16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); + error_ret: mutex_unlock(&st->lock); - return ret ? ret : len; + return IIO_VAL_INT; } -#define IIO_DEV_ATTR_SIMPLE_RESOLVER(_show) \ - IIO_DEVICE_ATTR(angular, S_IRUGO, _show, NULL, 0) - -static IIO_DEV_ATTR_SIMPLE_RESOLVER(ad2s90_show_angular); - -static struct attribute *ad2s90_attributes[] = { - &iio_dev_attr_angular.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad2s90_attribute_group = { - .name = DRV_NAME, - .attrs = ad2s90_attributes, -}; - static const struct iio_info ad2s90_info = { - .attrs = &ad2s90_attribute_group, + .read_raw = &ad2s90_read_raw, .driver_module = THIS_MODULE, }; +static const struct iio_chan_spec ad2s90_chan = { + .type = IIO_ANGL, + .indexed = 1, + .channel = 0, +}; + static int __devinit ad2s90_probe(struct spi_device *spi) { struct iio_dev *indio_dev; @@ -86,8 +76,11 @@ static int __devinit ad2s90_probe(struct spi_device *spi) indio_dev->dev.parent = &spi->dev; indio_dev->info = &ad2s90_info; indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = &ad2s90_chan; + indio_dev->num_channels = 1; + indio_dev->name = spi_get_device_id(spi)->name; - ret = iio_device_register(st->idev); + ret = iio_device_register(indio_dev); if (ret) goto error_free_dev; @@ -99,7 +92,7 @@ static int __devinit ad2s90_probe(struct spi_device *spi) return 0; error_free_dev: - iio_free_device(st->idev); + iio_free_device(indio_dev); error_ret: return ret; } @@ -107,17 +100,24 @@ error_ret: static int __devexit ad2s90_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 ad2s90_id[] = { + { "ad2s90" }, + {} +}; + static struct spi_driver ad2s90_driver = { .driver = { - .name = DRV_NAME, + .name = "ad2s90", .owner = THIS_MODULE, }, .probe = ad2s90_probe, .remove = __devexit_p(ad2s90_remove), + .id_table = ad2s90_id, }; static __init int ad2s90_spi_init(void) diff --git a/drivers/staging/iio/ring_generic.h b/drivers/staging/iio/ring_generic.h deleted file mode 100644 index 3f26f71..0000000 --- a/drivers/staging/iio/ring_generic.h +++ /dev/null @@ -1,288 +0,0 @@ -/* The industrial I/O core - generic ring 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_RING_GENERIC_H_ -#define _IIO_RING_GENERIC_H_ -#include "iio.h" - -#ifdef CONFIG_IIO_RING_BUFFER - -struct iio_ring_buffer; - -/** - * struct iio_ring_access_funcs - access functions for ring buffers. - * @mark_in_use: reference counting, typically to prevent module removal - * @unmark_in_use: reduce reference count when no longer using ring buffer - * @store_to: actually store stuff to the ring buffer - * @read_last: get the last element stored - * @read_first_n: try to get a specified number of elements (must exist) - * @mark_param_change: notify ring that some relevant parameter has changed - * Often this means the underlying storage may need to - * change. - * @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 ring - * @set_length: set number of datums in ring - * @is_enabled: query if ring is currently being used - * @enable: enable the ring - * - * The purpose of this structure is to make the ring buffer element - * modular as event for a given driver, different usecases may require - * different ring designs (space efficiency vs speed for example). - * - * It is worth noting that a given ring implementation may only support a small - * proportion of these functions. The core code 'should' cope fine with any of - * them not existing. - **/ -struct iio_ring_access_funcs { - void (*mark_in_use)(struct iio_ring_buffer *ring); - void (*unmark_in_use)(struct iio_ring_buffer *ring); - - int (*store_to)(struct iio_ring_buffer *ring, u8 *data, s64 timestamp); - int (*read_last)(struct iio_ring_buffer *ring, u8 *data); - int (*read_first_n)(struct iio_ring_buffer *ring, - size_t n, - char __user *buf); - - int (*mark_param_change)(struct iio_ring_buffer *ring); - int (*request_update)(struct iio_ring_buffer *ring); - - int (*get_bytes_per_datum)(struct iio_ring_buffer *ring); - int (*set_bytes_per_datum)(struct iio_ring_buffer *ring, size_t bpd); - int (*get_length)(struct iio_ring_buffer *ring); - int (*set_length)(struct iio_ring_buffer *ring, int length); - - int (*is_enabled)(struct iio_ring_buffer *ring); - int (*enable)(struct iio_ring_buffer *ring); -}; - -struct iio_ring_setup_ops { - int (*preenable)(struct iio_dev *); - int (*postenable)(struct iio_dev *); - int (*predisable)(struct iio_dev *); - int (*postdisable)(struct iio_dev *); -}; - -/** - * struct iio_ring_buffer - general ring buffer structure - * @dev: ring buffer device struct - * @indio_dev: industrial I/O device structure - * @owner: module that owns the ring buffer (for ref counting) - * @length: [DEVICE] number of datums in ring - * @bytes_per_datum: [DEVICE] size of individual datum including timestamp - * @bpe: [DEVICE] size of individual channel value - * @scan_el_attrs: [DRIVER] control of scan elements if that scan mode - * control method is used - * @scan_count: [INTERN] the number of elements in the current scan mode - * @scan_mask: [INTERN] bitmask used in masking scan mode elements - * @scan_timestamp: [INTERN] does the scan mode include a timestamp - * @access_handler: [INTERN] chrdev access handling - * @access: [DRIVER] ring access functions associated with the - * implementation. - * @preenable: [DRIVER] function to run prior to marking ring enabled - * @postenable: [DRIVER] function to run after marking ring enabled - * @predisable: [DRIVER] function to run prior to marking ring disabled - * @postdisable: [DRIVER] function to run after marking ring disabled - **/ -struct iio_ring_buffer { - struct device dev; - struct iio_dev *indio_dev; - struct module *owner; - int length; - int bytes_per_datum; - int bpe; - struct attribute_group *scan_el_attrs; - int scan_count; - unsigned long scan_mask; - bool scan_timestamp; - struct iio_handler access_handler; - const struct iio_ring_access_funcs *access; - const struct iio_ring_setup_ops *setup_ops; - struct list_head scan_el_dev_attr_list; - - wait_queue_head_t pollq; - bool stufftoread; -}; - -/** - * iio_ring_buffer_init() - Initialize the buffer structure - * @ring: buffer to be initialized - * @dev_info: the iio device the buffer is assocated with - **/ -void iio_ring_buffer_init(struct iio_ring_buffer *ring, - struct iio_dev *dev_info); - -/** - * __iio_update_ring_buffer() - update common elements of ring buffers - * @ring: ring buffer that is the event source - * @bytes_per_datum: size of individual datum including timestamp - * @length: number of datums in ring - **/ -static inline void __iio_update_ring_buffer(struct iio_ring_buffer *ring, - int bytes_per_datum, int length) -{ - ring->bytes_per_datum = bytes_per_datum; - ring->length = length; -} - -/* - * These are mainly provided to allow for a change of implementation if a device - * has a large number of scan elements - */ -#define IIO_MAX_SCAN_LENGTH 31 - -/* note 0 used as error indicator as it doesn't make sense. */ -static inline u32 iio_scan_mask_match(u32 *av_masks, u32 mask) -{ - while (*av_masks) { - if (!(~*av_masks & mask)) - return *av_masks; - av_masks++; - } - return 0; -} - -static inline int iio_scan_mask_query(struct iio_ring_buffer *ring, int bit) -{ - struct iio_dev *dev_info = ring->indio_dev; - u32 mask; - - if (bit > IIO_MAX_SCAN_LENGTH) - return -EINVAL; - - if (!ring->scan_mask) - return 0; - - if (dev_info->available_scan_masks) - mask = iio_scan_mask_match(dev_info->available_scan_masks, - ring->scan_mask); - else - mask = ring->scan_mask; - - if (!mask) - return -EINVAL; - - return !!(mask & (1 << bit)); -}; - -/** - * iio_scan_mask_set() - set particular bit in the scan mask - * @ring: the ring buffer whose scan mask we are interested in - * @bit: the bit to be set. - **/ -static inline int iio_scan_mask_set(struct iio_ring_buffer *ring, int bit) -{ - struct iio_dev *dev_info = ring->indio_dev; - u32 mask; - u32 trialmask = ring->scan_mask | (1 << bit); - - if (bit > IIO_MAX_SCAN_LENGTH) - return -EINVAL; - if (dev_info->available_scan_masks) { - mask = iio_scan_mask_match(dev_info->available_scan_masks, - trialmask); - if (!mask) - return -EINVAL; - } - ring->scan_mask = trialmask; - ring->scan_count++; - - return 0; -}; - -/** - * iio_put_ring_buffer() - notify done with buffer - * @ring: the buffer we are done with. - **/ -static inline void iio_put_ring_buffer(struct iio_ring_buffer *ring) -{ - put_device(&ring->dev); -}; - -#define to_iio_ring_buffer(d) \ - container_of(d, struct iio_ring_buffer, dev) - -/** - * iio_ring_buffer_register_ex() - register the buffer with IIO core - * @ring: the buffer to be registered - * @id: the id of the buffer (typically 0) - **/ -int iio_ring_buffer_register_ex(struct iio_ring_buffer *ring, int id, - const struct iio_chan_spec *channels, - int num_channels); - -void iio_ring_access_release(struct device *dev); - -/** - * iio_ring_buffer_unregister() - unregister the buffer from IIO core - * @ring: the buffer to be unregistered - **/ -void iio_ring_buffer_unregister(struct iio_ring_buffer *ring); - -/** - * iio_read_ring_length() - attr func to get number of datums in the buffer - **/ -ssize_t iio_read_ring_length(struct device *dev, - struct device_attribute *attr, - char *buf); -/** - * iio_write_ring_length() - attr func to set number of datums in the buffer - **/ -ssize_t iio_write_ring_length(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len); -/** - * iio_read_ring_bytes_per_datum() - attr for number of bytes in whole datum - **/ -ssize_t iio_read_ring_bytes_per_datum(struct device *dev, - struct device_attribute *attr, - char *buf); -/** - * iio_store_ring_enable() - attr to turn the buffer on - **/ -ssize_t iio_store_ring_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len); -/** - * iio_show_ring_enable() - attr to see if the buffer is on - **/ -ssize_t iio_show_ring_enable(struct device *dev, - struct device_attribute *attr, - char *buf); -#define IIO_RING_LENGTH_ATTR DEVICE_ATTR(length, S_IRUGO | S_IWUSR, \ - iio_read_ring_length, \ - iio_write_ring_length) -#define IIO_RING_BYTES_PER_DATUM_ATTR DEVICE_ATTR(bytes_per_datum, S_IRUGO | S_IWUSR, \ - iio_read_ring_bytes_per_datum, NULL) -#define IIO_RING_ENABLE_ATTR DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, \ - iio_show_ring_enable, \ - iio_store_ring_enable) - -int iio_sw_ring_preenable(struct iio_dev *indio_dev); - -#else /* CONFIG_IIO_RING_BUFFER */ - -static inline int iio_ring_buffer_register_ex(struct iio_ring_buffer *ring, - int id, - struct iio_chan_spec *channels, - int num_channels) -{ - return 0; -} - -static inline void iio_ring_buffer_unregister(struct iio_ring_buffer *ring) -{}; - -#endif /* CONFIG_IIO_RING_BUFFER */ - -#endif /* _IIO_RING_GENERIC_H_ */ diff --git a/drivers/staging/iio/ring_hw.h b/drivers/staging/iio/ring_hw.h index bb8cfd2..cad8a2e 100644 --- a/drivers/staging/iio/ring_hw.h +++ b/drivers/staging/iio/ring_hw.h @@ -14,9 +14,9 @@ * @buf: generic ring buffer elements * @private: device specific data */ -struct iio_hw_ring_buffer { - struct iio_ring_buffer buf; +struct iio_hw_buffer { + struct iio_buffer buf; void *private; }; -#define iio_to_hw_ring_buf(r) container_of(r, struct iio_hw_ring_buffer, buf) +#define iio_to_hw_buf(r) container_of(r, struct iio_hw_buffer, buf) diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c index feb84e2..66a34ad 100644 --- a/drivers/staging/iio/ring_sw.c +++ b/drivers/staging/iio/ring_sw.c @@ -30,10 +30,10 @@ * @use_lock: lock to prevent change in size when in use * * Note that the first element of all ring buffers must be a - * struct iio_ring_buffer. + * struct iio_buffer. **/ struct iio_sw_ring_buffer { - struct iio_ring_buffer buf; + struct iio_buffer buf; unsigned char *data; unsigned char *read_p; unsigned char *write_p; @@ -52,7 +52,7 @@ static inline int __iio_allocate_sw_ring_buffer(struct iio_sw_ring_buffer *ring, { if ((length == 0) || (bytes_per_datum == 0)) return -EINVAL; - __iio_update_ring_buffer(&ring->buf, bytes_per_datum, length); + __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; @@ -71,7 +71,7 @@ static inline void __iio_free_sw_ring_buffer(struct iio_sw_ring_buffer *ring) kfree(ring->data); } -static void iio_mark_sw_rb_in_use(struct iio_ring_buffer *r) +static void iio_mark_sw_rb_in_use(struct iio_buffer *r) { struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); spin_lock(&ring->use_lock); @@ -79,7 +79,7 @@ static void iio_mark_sw_rb_in_use(struct iio_ring_buffer *r) spin_unlock(&ring->use_lock); } -static void iio_unmark_sw_rb_in_use(struct iio_ring_buffer *r) +static void iio_unmark_sw_rb_in_use(struct iio_buffer *r) { struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); spin_lock(&ring->use_lock); @@ -166,7 +166,7 @@ static int iio_store_to_sw_ring(struct iio_sw_ring_buffer *ring, return ret; } -static int iio_read_first_n_sw_rb(struct iio_ring_buffer *r, +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); @@ -297,7 +297,7 @@ error_ret: return ret; } -static int iio_store_to_sw_rb(struct iio_ring_buffer *r, +static int iio_store_to_sw_rb(struct iio_buffer *r, u8 *data, s64 timestamp) { @@ -327,13 +327,13 @@ again: return 0; } -static int iio_read_last_from_sw_rb(struct iio_ring_buffer *r, +static int iio_read_last_from_sw_rb(struct iio_buffer *r, unsigned char *data) { return iio_read_last_from_sw_ring(iio_to_sw_ring(r), data); } -static int iio_request_update_sw_rb(struct iio_ring_buffer *r) +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); @@ -354,13 +354,13 @@ error_ret: return ret; } -static int iio_get_bytes_per_datum_sw_rb(struct iio_ring_buffer *r) +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_set_bytes_per_datum_sw_rb(struct iio_ring_buffer *r, size_t bpd) +static int iio_set_bytes_per_datum_sw_rb(struct iio_buffer *r, size_t bpd) { if (r->bytes_per_datum != bpd) { r->bytes_per_datum = bpd; @@ -370,12 +370,12 @@ static int iio_set_bytes_per_datum_sw_rb(struct iio_ring_buffer *r, size_t bpd) return 0; } -static int iio_get_length_sw_rb(struct iio_ring_buffer *r) +static int iio_get_length_sw_rb(struct iio_buffer *r) { return r->length; } -static int iio_set_length_sw_rb(struct iio_ring_buffer *r, int length) +static int iio_set_length_sw_rb(struct iio_buffer *r, int length) { if (r->length != length) { r->length = length; @@ -385,23 +385,16 @@ static int iio_set_length_sw_rb(struct iio_ring_buffer *r, int length) return 0; } -static int iio_mark_update_needed_sw_rb(struct iio_ring_buffer *r) +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 void iio_sw_rb_release(struct device *dev) -{ - struct iio_ring_buffer *r = to_iio_ring_buffer(dev); - iio_ring_access_release(&r->dev); - kfree(iio_to_sw_ring(r)); -} - -static IIO_RING_ENABLE_ATTR; -static IIO_RING_BYTES_PER_DATUM_ATTR; -static IIO_RING_LENGTH_ATTR; +static IIO_BUFFER_ENABLE_ATTR; +static IIO_BUFFER_BYTES_PER_DATUM_ATTR; +static IIO_BUFFER_LENGTH_ATTR; /* Standard set of ring buffer attributes */ static struct attribute *iio_ring_attributes[] = { @@ -413,21 +406,12 @@ static struct attribute *iio_ring_attributes[] = { static struct attribute_group iio_ring_attribute_group = { .attrs = iio_ring_attributes, + .name = "buffer", }; -static const struct attribute_group *iio_ring_attribute_groups[] = { - &iio_ring_attribute_group, - NULL -}; - -static struct device_type iio_sw_ring_type = { - .release = iio_sw_rb_release, - .groups = iio_ring_attribute_groups, -}; - -struct iio_ring_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev) +struct iio_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev) { - struct iio_ring_buffer *buf; + struct iio_buffer *buf; struct iio_sw_ring_buffer *ring; ring = kzalloc(sizeof *ring, GFP_KERNEL); @@ -435,24 +419,21 @@ struct iio_ring_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev) return NULL; ring->update_needed = true; buf = &ring->buf; - iio_ring_buffer_init(buf, indio_dev); + iio_buffer_init(buf, indio_dev); __iio_init_sw_ring_buffer(ring); - buf->dev.type = &iio_sw_ring_type; - buf->dev.parent = &indio_dev->dev; - dev_set_drvdata(&buf->dev, (void *)buf); + buf->attrs = &iio_ring_attribute_group; return buf; } EXPORT_SYMBOL(iio_sw_rb_allocate); -void iio_sw_rb_free(struct iio_ring_buffer *r) +void iio_sw_rb_free(struct iio_buffer *r) { - if (r) - iio_put_ring_buffer(r); + kfree(iio_to_sw_ring(r)); } EXPORT_SYMBOL(iio_sw_rb_free); -const struct iio_ring_access_funcs ring_sw_access_funcs = { +const struct iio_buffer_access_funcs ring_sw_access_funcs = { .mark_in_use = &iio_mark_sw_rb_in_use, .unmark_in_use = &iio_unmark_sw_rb_in_use, .store_to = &iio_store_to_sw_rb, diff --git a/drivers/staging/iio/ring_sw.h b/drivers/staging/iio/ring_sw.h index 1527163..a3e1578 100644 --- a/drivers/staging/iio/ring_sw.h +++ b/drivers/staging/iio/ring_sw.h @@ -23,13 +23,13 @@ #ifndef _IIO_RING_SW_H_ #define _IIO_RING_SW_H_ -#include "ring_generic.h" +#include "buffer_generic.h" /** * ring_sw_access_funcs - access functions for a software ring buffer **/ -extern const struct iio_ring_access_funcs ring_sw_access_funcs; +extern const struct iio_buffer_access_funcs ring_sw_access_funcs; -struct iio_ring_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev); -void iio_sw_rb_free(struct iio_ring_buffer *ring); +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 index dd79b58..868952b 100644 --- a/drivers/staging/iio/sysfs.h +++ b/drivers/staging/iio/sysfs.h @@ -12,19 +12,17 @@ #ifndef _INDUSTRIAL_IO_SYSFS_H_ #define _INDUSTRIAL_IO_SYSFS_H_ -#include "iio.h" +struct iio_chan_spec; /** * struct iio_dev_attr - iio specific device attribute * @dev_attr: underlying device attribute * @address: associated register address - * @val2: secondary attribute value * @l: list head for maintaining list of dynamically created attrs. */ struct iio_dev_attr { struct device_attribute dev_attr; - int address; - int val2; + u64 address; struct list_head l; struct iio_chan_spec const *c; }; @@ -64,10 +62,6 @@ struct iio_const_attr { struct iio_dev_attr iio_dev_attr_##_vname \ = IIO_ATTR(_name, _mode, _show, _store, _addr) -#define IIO_DEVICE_ATTR_2(_name, _mode, _show, _store, _addr, _val2) \ - struct iio_dev_attr iio_dev_attr_##_name \ - = IIO_ATTR_2(_name, _mode, _show, _store, _addr, _val2) - #define IIO_CONST_ATTR(_name, _string) \ struct iio_const_attr iio_const_attr_##_name \ = { .string = _string, \ @@ -77,17 +71,8 @@ struct iio_const_attr { struct iio_const_attr iio_const_attr_##_vname \ = { .string = _string, \ .dev_attr = __ATTR(_name, S_IRUGO, iio_read_const_attr, NULL)} -/* Generic attributes of onetype or another */ - -/** - * IIO_DEV_ATTR_REV - revision number for the device - * @_show: output method for the attribute - * - * Very much device dependent. - **/ -#define IIO_DEV_ATTR_REV(_show) \ - IIO_DEVICE_ATTR(revision, S_IRUGO, _show, NULL, 0) +/* Generic attributes of onetype or another */ /** * IIO_DEV_ATTR_RESET: resets the device **/ @@ -95,13 +80,6 @@ struct iio_const_attr { IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, _store, 0) /** - * IIO_CONST_ATTR_NAME - constant identifier - * @_string: the name - **/ -#define IIO_CONST_ATTR_NAME(_string) \ - IIO_CONST_ATTR(name, _string) - -/** * IIO_DEV_ATTR_SAMP_FREQ - sets any internal clock frequency * @_mode: sysfs file mode/permissions * @_show: output method for the attribute @@ -111,15 +89,11 @@ struct iio_const_attr { IIO_DEVICE_ATTR(sampling_frequency, _mode, _show, _store, 0) /** - * IIO_DEV_ATTR_AVAIL_SAMP_FREQ - list available sampling frequencies + * IIO_DEV_ATTR_SAMP_FREQ_AVAIL - list available sampling frequencies * @_show: output method for the attribute * * May be mode dependent on some devices **/ -/* Deprecated */ -#define IIO_DEV_ATTR_AVAIL_SAMP_FREQ(_show) \ - IIO_DEVICE_ATTR(available_sampling_frequency, S_IRUGO, _show, NULL, 0) - #define IIO_DEV_ATTR_SAMP_FREQ_AVAIL(_show) \ IIO_DEVICE_ATTR(sampling_frequency_available, S_IRUGO, _show, NULL, 0) /** @@ -131,92 +105,56 @@ struct iio_const_attr { #define IIO_CONST_ATTR_SAMP_FREQ_AVAIL(_string) \ IIO_CONST_ATTR(sampling_frequency_available, _string) -/** - * IIO_DEV_ATTR_SW_RING_ENABLE - enable software ring buffer - * @_show: output method for the attribute - * @_store: input method for the attribute - * - * Success may be dependent on attachment of trigger previously. - **/ -#define IIO_DEV_ATTR_SW_RING_ENABLE(_show, _store) \ - IIO_DEVICE_ATTR(sw_ring_enable, S_IRUGO | S_IWUSR, _show, _store, 0) - -/** - * IIO_DEV_ATTR_HW_RING_ENABLE - enable hardware ring buffer - * @_show: output method for the attribute - * @_store: input method for the attribute - * - * This is a different attribute from the software one as one can envision - * schemes where a combination of the two may be used. - **/ -#define IIO_DEV_ATTR_HW_RING_ENABLE(_show, _store) \ - IIO_DEVICE_ATTR(hw_ring_enable, S_IRUGO | S_IWUSR, _show, _store, 0) - #define IIO_DEV_ATTR_TEMP_RAW(_show) \ - IIO_DEVICE_ATTR(temp_raw, S_IRUGO, _show, NULL, 0) + IIO_DEVICE_ATTR(in_temp_raw, S_IRUGO, _show, NULL, 0) #define IIO_CONST_ATTR_TEMP_OFFSET(_string) \ - IIO_CONST_ATTR(temp_offset, _string) + IIO_CONST_ATTR(in_temp_offset, _string) #define IIO_CONST_ATTR_TEMP_SCALE(_string) \ - IIO_CONST_ATTR(temp_scale, _string) - -/* must match our channel defs */ -#define IIO_EV_CLASS_IN IIO_IN -#define IIO_EV_CLASS_IN_DIFF IIO_IN_DIFF -#define IIO_EV_CLASS_ACCEL IIO_ACCEL -#define IIO_EV_CLASS_GYRO IIO_GYRO -#define IIO_EV_CLASS_MAGN IIO_MAGN -#define IIO_EV_CLASS_LIGHT IIO_LIGHT -#define IIO_EV_CLASS_PROXIMITY IIO_PROXIMITY -#define IIO_EV_CLASS_TEMP IIO_TEMP - -#define IIO_EV_MOD_X IIO_MOD_X -#define IIO_EV_MOD_Y IIO_MOD_Y -#define IIO_EV_MOD_Z IIO_MOD_Z -#define IIO_EV_MOD_X_AND_Y IIO_MOD_X_AND_Y -#define IIO_EV_MOD_X_ANX_Z IIO_MOD_X_AND_Z -#define IIO_EV_MOD_Y_AND_Z IIO_MOD_Y_AND_Z -#define IIO_EV_MOD_X_AND_Y_AND_Z IIO_MOD_X_AND_Y_AND_Z -#define IIO_EV_MOD_X_OR_Y IIO_MOD_X_OR_Y -#define IIO_EV_MOD_X_OR_Z IIO_MOD_X_OR_Z -#define IIO_EV_MOD_Y_OR_Z IIO_MOD_Y_OR_Z -#define IIO_EV_MOD_X_OR_Y_OR_Z IIO_MOD_X_OR_Y_OR_Z - -#define IIO_EV_TYPE_THRESH 0 -#define IIO_EV_TYPE_MAG 1 -#define IIO_EV_TYPE_ROC 2 - -#define IIO_EV_DIR_EITHER 0 -#define IIO_EV_DIR_RISING 1 -#define IIO_EV_DIR_FALLING 2 - -#define IIO_EV_TYPE_MAX 8 -#define IIO_EV_BIT(type, direction) \ - (1 << (type*IIO_EV_TYPE_MAX + direction)) + IIO_CONST_ATTR(in_temp_scale, _string) + +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, +}; -#define IIO_EVENT_CODE(channelclass, orient_bit, number, \ - modifier, type, direction) \ - (channelclass | (orient_bit << 8) | ((number) << 9) | \ - ((modifier) << 13) | ((type) << 16) | ((direction) << 24)) +enum iio_event_direction { + IIO_EV_DIR_EITHER, + IIO_EV_DIR_RISING, + IIO_EV_DIR_FALLING, +}; + +#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) | (chan2 << 16) | chan1 | chan) + +#define IIO_EV_DIR_MAX 4 +#define IIO_EV_BIT(type, direction) \ + (1 << (type*IIO_EV_DIR_MAX + direction)) #define IIO_MOD_EVENT_CODE(channelclass, number, modifier, \ type, direction) \ - IIO_EVENT_CODE(channelclass, 1, number, modifier, type, direction) + IIO_EVENT_CODE(channelclass, 0, modifier, direction, type, number, 0, 0) #define IIO_UNMOD_EVENT_CODE(channelclass, number, type, direction) \ - IIO_EVENT_CODE(channelclass, 0, number, 0, type, direction) + IIO_EVENT_CODE(channelclass, 0, 0, direction, type, number, 0, 0) +#define IIO_EVENT_CODE_EXTRACT_TYPE(mask) ((mask >> 56) & 0xFF) -#define IIO_BUFFER_EVENT_CODE(code) \ - (IIO_EV_CLASS_BUFFER | (code << 8)) +#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0xCF) -#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 24) & 0xf) +#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) ((mask >> 9) & 0x0f) +#define IIO_EVENT_CODE_EXTRACT_NUM(mask) (mask & 0xFFFF) -#define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 13) & 0x7) +#define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 40) & 0xFF) #endif /* _INDUSTRIAL_IO_SYSFS_H_ */ diff --git a/drivers/staging/iio/trigger.h b/drivers/staging/iio/trigger.h index e0b58ed..598fcb3 100644 --- a/drivers/staging/iio/trigger.h +++ b/drivers/staging/iio/trigger.h @@ -7,6 +7,7 @@ * the Free Software Foundation. */ #include <linux/irq.h> +#include <linux/module.h> #ifndef _IIO_TRIGGER_H_ #define _IIO_TRIGGER_H_ @@ -16,6 +17,27 @@ struct iio_subirq { }; /** + * struct iio_trigger_ops - operations structure for an iio_trigger. + * @owner: used to monitor usage count of the trigger. + * @set_trigger_state: switch on/off the trigger on demand + * @try_reenable: function to reenable the trigger when the + * use count is zero (may be NULL) + * @validate_device: function to validate the device when the + * current trigger gets changed. + * + * This is typically static const within a driver and shared by + * instances of a given device. + **/ +struct iio_trigger_ops { + struct module *owner; + int (*set_trigger_state)(struct iio_trigger *trig, bool state); + int (*try_reenable)(struct iio_trigger *trig); + int (*validate_device)(struct iio_trigger *trig, + struct iio_dev *indio_dev); +}; + + +/** * struct iio_trigger - industrial I/O trigger device * * @id: [INTERN] unique id number @@ -26,11 +48,6 @@ struct iio_subirq { * @alloc_list: [DRIVER] used for driver specific trigger list * @owner: [DRIVER] used to monitor usage count of the trigger. * @use_count: use count for the trigger - * @set_trigger_state: [DRIVER] switch on/off the trigger on demand - * @try_reenable: function to reenable the trigger when the - * use count is zero (may be NULL) - * @validate_device: function to validate the device when the - * current trigger gets changed. * @subirq_chip: [INTERN] associate 'virtual' irq chip. * @subirq_base: [INTERN] base number for irqs provided by trigger. * @subirqs: [INTERN] information about the 'child' irqs. @@ -38,6 +55,7 @@ struct iio_subirq { * @pool_lock: [INTERN] protection of the irq pool. **/ struct iio_trigger { + const struct iio_trigger_ops *ops; int id; const char *name; struct device dev; @@ -48,11 +66,6 @@ struct iio_trigger { struct module *owner; int use_count; - int (*set_trigger_state)(struct iio_trigger *trig, bool state); - int (*try_reenable)(struct iio_trigger *trig); - int (*validate_device)(struct iio_trigger *trig, - struct iio_dev *indio_dev); - struct irq_chip subirq_chip; int subirq_base; @@ -61,29 +74,6 @@ struct iio_trigger { struct mutex pool_lock; }; -/** - * struct iio_poll_func - poll function pair - * - * @private_data: data specific to device (passed into poll func) - * @h: the function that is actually run on trigger - * @thread: threaded interrupt part - * @type: the type of interrupt (basically if oneshot) - * @name: name used to identify the trigger consumer. - * @irq: the corresponding irq as allocated from the - * trigger pool - * @timestamp: some devices need a timestamp grabbed as soon - * as possible after the trigger - hence handler - * passes it via here. - **/ -struct iio_poll_func { - void *private_data; - irqreturn_t (*h)(int irq, void *p); - irqreturn_t (*thread)(int irq, void *p); - int type; - char *name; - int irq; - s64 timestamp; -}; static inline struct iio_trigger *to_iio_trigger(struct device *d) { @@ -92,14 +82,14 @@ static inline struct iio_trigger *to_iio_trigger(struct device *d) static inline void iio_put_trigger(struct iio_trigger *trig) { + module_put(trig->ops->owner); put_device(&trig->dev); - module_put(trig->owner); }; static inline void iio_get_trigger(struct iio_trigger *trig) { - __module_get(trig->owner); get_device(&trig->dev); + __module_get(trig->ops->owner); }; /** @@ -115,23 +105,6 @@ int iio_trigger_register(struct iio_trigger *trig_info); void iio_trigger_unregister(struct iio_trigger *trig_info); /** - * iio_trigger_attach_poll_func() - add a function pair to be run on trigger - * @trig: trigger to which the function pair are being added - * @pf: poll function pair - **/ -int iio_trigger_attach_poll_func(struct iio_trigger *trig, - struct iio_poll_func *pf); - -/** - * iio_trigger_dettach_poll_func() - remove function pair from those to be - * run on trigger - * @trig: trigger from which the function is being removed - * @pf: poll function pair - **/ -int iio_trigger_dettach_poll_func(struct iio_trigger *trig, - struct iio_poll_func *pf); - -/** * iio_trigger_poll() - called on a trigger occurring * @trig: trigger which occurred * @@ -139,48 +112,9 @@ int iio_trigger_dettach_poll_func(struct iio_trigger *trig, **/ void iio_trigger_poll(struct iio_trigger *trig, s64 time); void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time); -void iio_trigger_notify_done(struct iio_trigger *trig); irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private); -static inline int iio_trigger_get_irq(struct iio_trigger *trig) -{ - int ret; - mutex_lock(&trig->pool_lock); - ret = bitmap_find_free_region(trig->pool, - CONFIG_IIO_CONSUMERS_PER_TRIGGER, - ilog2(1)); - mutex_unlock(&trig->pool_lock); - if (ret >= 0) - ret += trig->subirq_base; - - return ret; -}; - -static inline void iio_trigger_put_irq(struct iio_trigger *trig, int irq) -{ - mutex_lock(&trig->pool_lock); - clear_bit(irq - trig->subirq_base, trig->pool); - mutex_unlock(&trig->pool_lock); -}; - -struct iio_poll_func -*iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p), - irqreturn_t (*thread)(int irq, void *p), - int type, - void *private, - const char *fmt, - ...); -void iio_dealloc_pollfunc(struct iio_poll_func *pf); -irqreturn_t iio_pollfunc_store_time(int irq, void *p); - -/* - * Two functions for common case where all that happens is a pollfunc - * is attached and detached from a trigger - */ -int iio_triggered_ring_postenable(struct iio_dev *indio_dev); -int iio_triggered_ring_predisable(struct iio_dev *indio_dev); - struct iio_trigger *iio_allocate_trigger(const char *fmt, ...) __attribute__((format(printf, 1, 2))); void iio_free_trigger(struct iio_trigger *trig); diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c index 4f17295..1cbb25d 100644 --- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c +++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c @@ -143,6 +143,10 @@ static int iio_bfin_tmr_get_number(int irq) return -ENODEV; } +static const struct iio_trigger_ops iio_bfin_tmr_trigger_ops = { + .owner = THIS_MODULE, +}; + static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev) { struct bfin_tmr_state *st; @@ -175,7 +179,7 @@ static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev) } st->trig->private_data = st; - st->trig->owner = THIS_MODULE; + st->trig->ops = &iio_bfin_tmr_trigger_ops; st->trig->dev.groups = iio_bfin_tmr_trigger_attr_groups; ret = iio_trigger_register(st->trig); if (ret) diff --git a/drivers/staging/iio/trigger/iio-trig-gpio.c b/drivers/staging/iio/trigger/iio-trig-gpio.c index f1fb795..f2a6559 100644 --- a/drivers/staging/iio/trigger/iio-trig-gpio.c +++ b/drivers/staging/iio/trigger/iio-trig-gpio.c @@ -47,6 +47,10 @@ static irqreturn_t iio_gpio_trigger_poll(int irq, void *private) return IRQ_HANDLED; } +static const struct iio_trigger_ops iio_gpio_trigger_ops = { + .owner = THIS_MODULE, +}; + static int iio_gpio_trigger_probe(struct platform_device *pdev) { struct iio_gpio_trigger_info *trig_info; @@ -81,7 +85,7 @@ static int iio_gpio_trigger_probe(struct platform_device *pdev) } trig->private_data = trig_info; trig_info->irq = irq; - trig->owner = THIS_MODULE; + trig->ops = &iio_gpio_trigger_ops; ret = request_irq(irq, iio_gpio_trigger_poll, irqflags, trig->name, trig); if (ret) { diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c index 01cf7e2..d35d085 100644 --- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c +++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c @@ -96,6 +96,11 @@ static void iio_prtc_trigger_poll(void *private_data) iio_trigger_poll(private_data, 0); } +static const struct iio_trigger_ops iio_prtc_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = &iio_trig_periodic_rtc_set_state, +}; + static int iio_trig_periodic_rtc_probe(struct platform_device *dev) { char **pdata = dev->dev.platform_data; @@ -121,7 +126,7 @@ static int iio_trig_periodic_rtc_probe(struct platform_device *dev) } trig->private_data = trig_info; trig->owner = THIS_MODULE; - trig->set_trigger_state = &iio_trig_periodic_rtc_set_state; + trig->ops = &iio_prtc_trigger_ops; /* RTC access */ trig_info->rtc = rtc_class_open(pdata[i]); diff --git a/drivers/staging/iio/trigger/iio-trig-sysfs.c b/drivers/staging/iio/trigger/iio-trig-sysfs.c index 47248cd..174dc65 100644 --- a/drivers/staging/iio/trigger/iio-trig-sysfs.c +++ b/drivers/staging/iio/trigger/iio-trig-sysfs.c @@ -77,9 +77,16 @@ static const struct attribute_group *iio_sysfs_trig_groups[] = { NULL }; + +/* Nothing to actually do upon release */ +static void iio_trigger_sysfs_release(struct device *dev) +{ +} + static struct device iio_sysfs_trig_dev = { .bus = &iio_bus_type, .groups = iio_sysfs_trig_groups, + .release = &iio_trigger_sysfs_release, }; static ssize_t iio_sysfs_trigger_poll(struct device *dev, @@ -107,6 +114,10 @@ static const struct attribute_group *iio_sysfs_trigger_attr_groups[] = { NULL }; +static const struct iio_trigger_ops iio_sysfs_trigger_ops = { + .owner = THIS_MODULE, +}; + static int iio_sysfs_trigger_probe(int id) { struct iio_sysfs_trig *t; @@ -135,7 +146,7 @@ static int iio_sysfs_trigger_probe(int id) } t->trig->dev.groups = iio_sysfs_trigger_attr_groups; - t->trig->owner = THIS_MODULE; + t->trig->ops = &iio_sysfs_trigger_ops; t->trig->dev.parent = &iio_sysfs_trig_dev; ret = iio_trigger_register(t->trig); diff --git a/drivers/staging/iio/trigger_consumer.h b/drivers/staging/iio/trigger_consumer.h index 9d52d96..60d64b3 100644 --- a/drivers/staging/iio/trigger_consumer.h +++ b/drivers/staging/iio/trigger_consumer.h @@ -1,47 +1,52 @@ - -/* The industrial I/O core, trigger consumer handling functions +/* The industrial I/O core, trigger consumer functions * - * Copyright (c) 2008 Jonathan Cameron + * Copyright (c) 2008-2011 Jonathan Cameron * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. */ -#ifdef CONFIG_IIO_TRIGGER -/** - * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers - * @dev_info: iio_dev associated with the device that will consume the trigger - **/ -int iio_device_register_trigger_consumer(struct iio_dev *dev_info); - -/** - * iio_device_unregister_trigger_consumer() - reverse the registration process - * @dev_info: iio_dev associated with the device that consumed the trigger - **/ -int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info); - -#else - /** - * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers - * @dev_info: iio_dev associated with the device that will consume the trigger - **/ -static int iio_device_register_trigger_consumer(struct iio_dev *dev_info) -{ - return 0; -}; - -/** - * iio_device_unregister_trigger_consumer() - reverse the registration process - * @dev_info: iio_dev associated with the device that consumed the trigger + * struct iio_poll_func - poll function pair + * + * @indio_dev: data specific to device (passed into poll func) + * @h: the function that is actually run on trigger + * @thread: threaded interrupt part + * @type: the type of interrupt (basically if oneshot) + * @name: name used to identify the trigger consumer. + * @irq: the corresponding irq as allocated from the + * trigger pool + * @timestamp: some devices need a timestamp grabbed as soon + * as possible after the trigger - hence handler + * passes it via here. **/ -static int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info) -{ - return 0; +struct iio_poll_func { + struct iio_dev *indio_dev; + irqreturn_t (*h)(int irq, void *p); + irqreturn_t (*thread)(int irq, void *p); + int type; + char *name; + int irq; + s64 timestamp; }; -#endif /* CONFIG_TRIGGER_CONSUMER */ +struct iio_poll_func +*iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p), + irqreturn_t (*thread)(int irq, void *p), + int type, + struct iio_dev *indio_dev, + const char *fmt, + ...); +void iio_dealloc_pollfunc(struct iio_poll_func *pf); +irqreturn_t iio_pollfunc_store_time(int irq, void *p); +void iio_trigger_notify_done(struct iio_trigger *trig); +/* + * Two functions for common case where all that happens is a pollfunc + * is attached and detached from a trigger + */ +int iio_triggered_buffer_postenable(struct iio_dev *indio_dev); +int iio_triggered_buffer_predisable(struct iio_dev *indio_dev); |