Commit 3ce14acb authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-for-3.8e' of...

Merge tag 'iio-for-3.8e' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next

From Jonathan:

  "Fifth round of new IIO drivers, cleanups and fixes for the 3.8 cycle.

  Here we have a number of minor fixes.
  * a quirk for the hid sensor driver should be a boolean option.
  * return an error for a failed memdup in the hid sensor driver.
  * Fix a return value in adt7410.
  * A double free in the IIO event infrastructure.
  * Disabling interrupts in tsl2563 was wrong (never been correct!)
  * Incorrect signature for the iio_buffer_register stub
  * Incorrect return for isl29018 write_raw callback.
  * A number of minor fixes as part of the various rework series.

  New drivers and major rework.
  * Introduce and use extensively an adis library for numerous spi
    Analog Devices mems sensors.  This then moves out of staging.
  * Lots of new stuff then added to this library to support newer
    sensors.
  * New drivers for ADIS16136 and ADIS16480 and similar.
  * Core support for barometric pressure sensors.
  * ad7298 cleanup and move out of staging.

  The bulk of this is from Lars-Peter Clausen.  He's been rather
  busy!"
parents acf1cf6a be7fd3b8
......@@ -189,6 +189,14 @@ Description:
A computed peak value based on the sum squared magnitude of
the underlying value in the specified directions.
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_raw
What: /sys/bus/iio/devices/iio:deviceX/in_pressure_raw
KernelVersion: 3.8
Contact: linux-iio@vger.kernel.org
Description:
Raw pressure measurement from channel Y. Units after
application of scale and offset are kilopascal.
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
......@@ -197,6 +205,8 @@ 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
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_offset
What: /sys/bus/iio/devices/iio:deviceX/in_pressure_offset
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
......@@ -226,6 +236,8 @@ 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
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_scale
What: /sys/bus/iio/devices/iio:deviceX/in_pressure_scale
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
......@@ -245,6 +257,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibbias
What: /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibbias
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_calibbias
What: /sys/bus/iio/devices/iio:deviceX/in_pressure_calibbias
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
......@@ -262,6 +276,8 @@ What /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibscale
What /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibscale
what /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibscale
what /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibscale
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_calibscale
What: /sys/bus/iio/devices/iio:deviceX/in_pressure_calibscale
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
......@@ -275,6 +291,8 @@ What: /sys/.../iio:deviceX/in_voltage-voltage_scale_available
What: /sys/.../iio:deviceX/out_voltageX_scale_available
What: /sys/.../iio:deviceX/out_altvoltageX_scale_available
What: /sys/.../iio:deviceX/in_capacitance_scale_available
What: /sys/.../iio:deviceX/in_pressure_scale_available
What: /sys/.../iio:deviceX/in_pressureY_scale_available
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
......@@ -694,6 +712,8 @@ 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
What: /sys/.../buffer/scan_elements/in_pressureY_en
What: /sys/.../buffer/scan_elements/in_pressure_en
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
......@@ -707,6 +727,8 @@ What: /sys/.../buffer/scan_elements/in_voltageY_type
What: /sys/.../buffer/scan_elements/in_voltage_type
What: /sys/.../buffer/scan_elements/in_voltageY_supply_type
What: /sys/.../buffer/scan_elements/in_timestamp_type
What: /sys/.../buffer/scan_elements/in_pressureY_type
What: /sys/.../buffer/scan_elements/in_pressure_type
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
......@@ -751,6 +773,8 @@ 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
What: /sys/.../buffer/scan_elements/in_pressureY_index
What: /sys/.../buffer/scan_elements/in_pressure_index
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
......
......@@ -63,11 +63,12 @@ config IIO_CONSUMERS_PER_TRIGGER
source "drivers/iio/accel/Kconfig"
source "drivers/iio/adc/Kconfig"
source "drivers/iio/amplifiers/Kconfig"
source "drivers/iio/light/Kconfig"
source "drivers/iio/frequency/Kconfig"
source "drivers/iio/dac/Kconfig"
source "drivers/iio/common/Kconfig"
source "drivers/iio/dac/Kconfig"
source "drivers/iio/frequency/Kconfig"
source "drivers/iio/gyro/Kconfig"
source "drivers/iio/imu/Kconfig"
source "drivers/iio/light/Kconfig"
source "drivers/iio/magnetometer/Kconfig"
endif # IIO
......@@ -14,9 +14,10 @@ obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
obj-y += accel/
obj-y += adc/
obj-y += amplifiers/
obj-y += light/
obj-y += frequency/
obj-y += dac/
obj-y += common/
obj-y += dac/
obj-y += gyro/
obj-y += frequency/
obj-y += imu/
obj-y += light/
obj-y += magnetometer/
......@@ -306,10 +306,10 @@ static int __devinit hid_accel_3d_probe(struct platform_device *pdev)
goto error_free_dev;
}
channels = kmemdup(accel_3d_channels,
sizeof(accel_3d_channels),
channels = kmemdup(accel_3d_channels, sizeof(accel_3d_channels),
GFP_KERNEL);
if (!channels) {
ret = -ENOMEM;
dev_err(&pdev->dev, "failed to duplicate channels\n");
goto error_free_dev;
}
......
......@@ -18,6 +18,18 @@ config AD7266
Say yes here to build support for Analog Devices AD7265 and AD7266
ADCs.
config AD7298
tristate "Analog Devices AD7298 ADC driver"
depends on SPI
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for Analog Devices AD7298
8 Channel ADC with temperature sensor.
To compile this driver as a module, choose M here: the
module will be called ad7298.
config AD7791
tristate "Analog Devices AD7791 ADC driver"
depends on SPI
......
......@@ -4,6 +4,7 @@
obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
obj-$(CONFIG_AD7266) += ad7266.o
obj-$(CONFIG_AD7298) += ad7298.o
obj-$(CONFIG_AD7476) += ad7476.o
obj-$(CONFIG_AD7791) += ad7791.o
obj-$(CONFIG_AD7887) += ad7887.o
......
......@@ -15,12 +15,48 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
#include "ad7298.h"
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/platform_data/ad7298.h>
#define AD7298_WRITE (1 << 15) /* write to the control register */
#define AD7298_REPEAT (1 << 14) /* repeated conversion enable */
#define AD7298_CH(x) (1 << (13 - (x))) /* channel select */
#define AD7298_TSENSE (1 << 5) /* temperature conversion enable */
#define AD7298_EXTREF (1 << 2) /* external reference enable */
#define AD7298_TAVG (1 << 1) /* temperature sensor averaging enable */
#define AD7298_PDD (1 << 0) /* partial power down enable */
#define AD7298_MAX_CHAN 8
#define AD7298_BITS 12
#define AD7298_STORAGE_BITS 16
#define AD7298_INTREF_mV 2500
#define AD7298_CH_TEMP 9
#define RES_MASK(bits) ((1 << (bits)) - 1)
struct ad7298_state {
struct spi_device *spi;
struct regulator *reg;
unsigned ext_ref;
struct spi_transfer ring_xfer[10];
struct spi_transfer scan_single_xfer[3];
struct spi_message ring_msg;
struct spi_message scan_single_msg;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
__be16 rx_buf[12] ____cacheline_aligned;
__be16 tx_buf[2];
};
#define AD7298_V_CHAN(index) \
{ \
......@@ -35,6 +71,7 @@
.sign = 'u', \
.realbits = 12, \
.storagebits = 16, \
.endianness = IIO_BE, \
}, \
}
......@@ -44,7 +81,8 @@ static const struct iio_chan_spec ad7298_channels[] = {
.indexed = 1,
.channel = 0,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
.address = AD7298_CH_TEMP,
.scan_index = -1,
.scan_type = {
......@@ -64,6 +102,84 @@ static const struct iio_chan_spec ad7298_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(8),
};
/**
* ad7298_update_scan_mode() setup the spi transfer buffer for the new scan mask
**/
static int ad7298_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *active_scan_mask)
{
struct ad7298_state *st = iio_priv(indio_dev);
int i, m;
unsigned short command;
int scan_count;
/* Now compute overall size */
scan_count = bitmap_weight(active_scan_mask, indio_dev->masklength);
command = AD7298_WRITE | st->ext_ref;
for (i = 0, m = AD7298_CH(0); i < AD7298_MAX_CHAN; i++, m >>= 1)
if (test_bit(i, active_scan_mask))
command |= m;
st->tx_buf[0] = cpu_to_be16(command);
/* build spi ring message */
st->ring_xfer[0].tx_buf = &st->tx_buf[0];
st->ring_xfer[0].len = 2;
st->ring_xfer[0].cs_change = 1;
st->ring_xfer[1].tx_buf = &st->tx_buf[1];
st->ring_xfer[1].len = 2;
st->ring_xfer[1].cs_change = 1;
spi_message_init(&st->ring_msg);
spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg);
spi_message_add_tail(&st->ring_xfer[1], &st->ring_msg);
for (i = 0; i < scan_count; i++) {
st->ring_xfer[i + 2].rx_buf = &st->rx_buf[i];
st->ring_xfer[i + 2].len = 2;
st->ring_xfer[i + 2].cs_change = 1;
spi_message_add_tail(&st->ring_xfer[i + 2], &st->ring_msg);
}
/* make sure last transfer cs_change is not set */
st->ring_xfer[i + 1].cs_change = 0;
return 0;
}
/**
* ad7298_trigger_handler() bh of trigger launched polling to ring buffer
*
* Currently there is no option in this driver to disable the saving of
* timestamps within the ring.
**/
static irqreturn_t ad7298_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct ad7298_state *st = iio_priv(indio_dev);
s64 time_ns = 0;
int b_sent;
b_sent = spi_sync(st->spi, &st->ring_msg);
if (b_sent)
goto done;
if (indio_dev->scan_timestamp) {
time_ns = iio_get_time_ns();
memcpy((u8 *)st->rx_buf + indio_dev->scan_bytes - sizeof(s64),
&time_ns, sizeof(time_ns));
}
iio_push_to_buffers(indio_dev, (u8 *)st->rx_buf);
done:
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
static int ad7298_scan_direct(struct ad7298_state *st, unsigned ch)
{
int ret;
......@@ -79,7 +195,7 @@ static int ad7298_scan_direct(struct ad7298_state *st, unsigned ch)
static int ad7298_scan_temp(struct ad7298_state *st, int *val)
{
int tmp, ret;
int ret;
__be16 buf;
buf = cpu_to_be16(AD7298_WRITE | AD7298_TSENSE |
......@@ -101,24 +217,24 @@ static int ad7298_scan_temp(struct ad7298_state *st, int *val)
if (ret)
return ret;
tmp = be16_to_cpu(buf) & RES_MASK(AD7298_BITS);
*val = sign_extend32(be16_to_cpu(buf), 11);
/*
* One LSB of the ADC corresponds to 0.25 deg C.
* The temperature reading is in 12-bit twos complement format
*/
return 0;
}
if (tmp & (1 << (AD7298_BITS - 1))) {
tmp = (4096 - tmp) * 250;
tmp -= (2 * tmp);
static int ad7298_get_ref_voltage(struct ad7298_state *st)
{
int vref;
if (st->ext_ref) {
vref = regulator_get_voltage(st->reg);
if (vref < 0)
return vref;
return vref / 1000;
} else {
tmp *= 250; /* temperature in milli degrees Celsius */
return AD7298_INTREF_mV;
}
*val = tmp;
return 0;
}
static int ad7298_read_raw(struct iio_dev *indio_dev,
......@@ -129,7 +245,6 @@ static int ad7298_read_raw(struct iio_dev *indio_dev,
{
int ret;
struct ad7298_state *st = iio_priv(indio_dev);
unsigned int scale_uv;
switch (m) {
case IIO_CHAN_INFO_RAW:
......@@ -154,17 +269,19 @@ static int ad7298_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
scale_uv = (st->int_vref_mv * 1000) >> AD7298_BITS;
*val = scale_uv / 1000;
*val2 = (scale_uv % 1000) * 1000;
return IIO_VAL_INT_PLUS_MICRO;
*val = ad7298_get_ref_voltage(st);
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_TEMP:
*val = 1;
*val2 = 0;
return IIO_VAL_INT_PLUS_MICRO;
*val = ad7298_get_ref_voltage(st);
*val2 = 10;
return IIO_VAL_FRACTIONAL;
default:
return -EINVAL;
}
case IIO_CHAN_INFO_OFFSET:
*val = 1093 - 2732500 / ad7298_get_ref_voltage(st);
return IIO_VAL_INT;
}
return -EINVAL;
}
......@@ -179,16 +296,23 @@ static int __devinit ad7298_probe(struct spi_device *spi)
{
struct ad7298_platform_data *pdata = spi->dev.platform_data;
struct ad7298_state *st;
int ret;
struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
int ret;
if (indio_dev == NULL)
return -ENOMEM;
st = iio_priv(indio_dev);
st->reg = regulator_get(&spi->dev, "vcc");
if (!IS_ERR(st->reg)) {
if (pdata && pdata->ext_ref)
st->ext_ref = AD7298_EXTREF;
if (st->ext_ref) {
st->reg = regulator_get(&spi->dev, "vref");
if (IS_ERR(st->reg)) {
ret = PTR_ERR(st->reg);
goto error_free;
}
ret = regulator_enable(st->reg);
if (ret)
goto error_put_reg;
......@@ -221,14 +345,8 @@ static int __devinit ad7298_probe(struct spi_device *spi)
spi_message_add_tail(&st->scan_single_xfer[1], &st->scan_single_msg);
spi_message_add_tail(&st->scan_single_xfer[2], &st->scan_single_msg);
if (pdata && pdata->vref_mv) {
st->int_vref_mv = pdata->vref_mv;
st->ext_ref = AD7298_EXTREF;
} else {
st->int_vref_mv = AD7298_INTREF_mV;
}
ret = ad7298_register_ring_funcs_and_init(indio_dev);
ret = iio_triggered_buffer_setup(indio_dev, NULL,
&ad7298_trigger_handler, NULL);
if (ret)
goto error_disable_reg;
......@@ -239,13 +357,14 @@ static int __devinit ad7298_probe(struct spi_device *spi)
return 0;
error_cleanup_ring:
ad7298_ring_cleanup(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
error_disable_reg:
if (!IS_ERR(st->reg))
if (st->ext_ref)
regulator_disable(st->reg);
error_put_reg:
if (!IS_ERR(st->reg))
if (st->ext_ref)
regulator_put(st->reg);
error_free:
iio_device_free(indio_dev);
return ret;
......@@ -257,8 +376,8 @@ static int __devexit ad7298_remove(struct spi_device *spi)
struct ad7298_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
ad7298_ring_cleanup(indio_dev);
if (!IS_ERR(st->reg)) {
iio_triggered_buffer_cleanup(indio_dev);
if (st->ext_ref) {
regulator_disable(st->reg);
regulator_put(st->reg);
}
......
......@@ -15,7 +15,7 @@ config HID_SENSOR_IIO_COMMON
attributes.
config HID_SENSOR_ENUM_BASE_QUIRKS
tristate "ENUM base quirks for HID Sensor IIO drivers"
bool "ENUM base quirks for HID Sensor IIO drivers"
depends on HID_SENSOR_IIO_COMMON
help
Say yes here to build support for sensor hub FW using
......
......@@ -36,10 +36,8 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
int state_val;
state_val = state ? 1 : 0;
#if (defined CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS) || \
(defined CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS_MODULE)
if (IS_ENABLED(CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS))
++state_val;
#endif
st->data_ready = state;
sensor_hub_set_feature(st->hsdev, st->power_state.report_id,
st->power_state.index,
......
......@@ -3,6 +3,15 @@
#
menu "Digital gyroscope sensors"
config ADIS16136
tristate "Analog devices ADIS16136 and similar gyroscopes driver"
depends on SPI_MASTER
select IIO_ADIS_LIB
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say yes here to build support for the Analog Devices ADIS16133, ADIS16135,
ADIS16136 gyroscope devices.
config HID_SENSOR_GYRO_3D
depends on HID_SENSOR_HUB
select IIO_BUFFER
......
......@@ -2,4 +2,5 @@
# Makefile for industrial I/O gyroscope sensor drivers
#
obj-$(CONFIG_ADIS16136) += adis16136.o
obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o
This diff is collapsed.
......@@ -306,10 +306,10 @@ static int __devinit hid_gyro_3d_probe(struct platform_device *pdev)
goto error_free_dev;
}
channels = kmemdup(gyro_3d_channels,
sizeof(gyro_3d_channels),
channels = kmemdup(gyro_3d_channels, sizeof(gyro_3d_channels),
GFP_KERNEL);
if (!channels) {
ret = -ENOMEM;
dev_err(&pdev->dev, "failed to duplicate channels\n");
goto error_free_dev;
}
......
#
# IIO imu drivers configuration
#
menu "Inertial measurement units"
config ADIS16480
tristate "Analog Devices ADIS16480 and similar IMU driver"
depends on SPI
select IIO_ADIS_LIB
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say yes here to build support for Analog Devices ADIS16375, ADIS16480,
ADIS16485, ADIS16488 inertial sensors.
endmenu
config IIO_ADIS_LIB
tristate
help
A set of IO helper functions for the Analog Devices ADIS* device family.
config IIO_ADIS_LIB_BUFFER
bool
select IIO_TRIGGERED_BUFFER
help
A set of buffer helper functions for the Analog Devices ADIS* device
family.
#
# Makefile for Inertial Measurement Units
#
obj-$(CONFIG_ADIS16480) += adis16480.o
adis_lib-y += adis.o
adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o
adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
This diff is collapsed.
This diff is collapsed.
/*
* Common library for ADIS16XXX devices
*
* Copyright 2012 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2 or later.
*/
#include <linux/export.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/imu/adis.h>
int adis_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
struct adis *adis = iio_device_get_drvdata(indio_dev);
const struct iio_chan_spec *chan;
unsigned int scan_count;
unsigned int i, j;
__be16 *tx, *rx;
kfree(adis->xfer);
kfree(adis->buffer);
scan_count = indio_dev->scan_bytes / 2;
adis->xfer = kcalloc(scan_count + 1, sizeof(*adis->xfer), GFP_KERNEL);
if (!adis->xfer)
return -ENOMEM;
adis->buffer = kzalloc(indio_dev->scan_bytes * 2, GFP_KERNEL);
if (!adis->buffer)
return -ENOMEM;
rx = adis->buffer;
tx = rx + indio_dev->scan_bytes;
spi_message_init(&adis->msg);
for (j = 0; j <= scan_count; j++) {
adis->xfer[j].bits_per_word = 8;
if (j != scan_count)
adis->xfer[j].cs_change = 1;
adis->xfer[j].len = 2;
adis->xfer[j].delay_usecs = adis->data->read_delay;
if (j < scan_count)
adis->xfer[j].tx_buf = &tx[j];
if (j >= 1)
adis->xfer[j].rx_buf = &rx[j - 1];
spi_message_add_tail(&adis->xfer[j], &adis->msg);
}
chan = indio_dev->channels;
for (i = 0; i < indio_dev->num_channels; i++, chan++) {
if (!test_bit(chan->scan_index, scan_mask))
continue;
if (chan->scan_type.storagebits == 32)
*tx++ = cpu_to_be16((chan->address + 2) << 8);
*tx++ = cpu_to_be16(chan->address << 8);
}
return 0;
}
EXPORT_SYMBOL_GPL(adis_update_scan_mode);
static irqreturn_t adis_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct adis *adis = iio_device_get_drvdata(indio_dev);
int ret;
if (!adis->buffer)
return -ENOMEM;
if (adis->data->has_paging) {
mutex_lock(&adis->txrx_lock);
if (adis->current_page != 0) {
adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID);
adis->tx[1] = 0;
spi_write(adis->spi, adis->tx, 2);
}
}
ret = spi_sync(adis->spi, &adis->msg);
if (ret)
dev_err(&adis->spi->dev, "Failed to read data: %d", ret);
if (adis->data->has_paging) {
adis->current_page = 0;
mutex_unlock(&adis->txrx_lock);
}
/* Guaranteed to be aligned with 8 byte boundary */
if (indio_dev->scan_timestamp) {
void *b = adis->buffer + indio_dev->scan_bytes - sizeof(s64);
*(s64 *)b = pf->timestamp;
}
iio_push_to_buffers(indio_dev, adis->buffer);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
/**
* adis_setup_buffer_and_trigger() - Sets up buffer and trigger for the adis device
* @adis: The adis device.
* @indio_dev: The IIO device.
* @trigger_handler: Optional trigger handler, may be NULL.
*
* Returns 0 on success, a negative error code otherwise.
*
* This function sets up the buffer and trigger for a adis devices. If
* 'trigger_handler' is NULL the default trigger handler will be used. The
* default trigger handler will simply read the registers assigned to the
* currently active channels.
*
* adis_cleanup_buffer_and_trigger() should be called to free the resources
* allocated by this function.
*/
int adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev,
irqreturn_t (*trigger_handler)(int, void *))
{
int ret;
if (!trigger_handler)
trigger_handler = adis_trigger_handler;
ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
trigger_handler, NULL);
if (ret)
return ret;
if (adis->spi->irq) {
ret = adis_probe_trigger(adis, indio_dev);
if (ret)
goto error_buffer_cleanup;
}
return 0;
error_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
return ret;
}
EXPORT_SYMBOL_GPL(adis_setup_buffer_and_trigger);
/**
* adis_cleanup_buffer_and_trigger() - Free buffer and trigger resources
* @adis: The adis device.
* @indio_dev: The IIO device.
*
* Frees resources allocated by adis_setup_buffer_and_trigger()
*/
void adis_cleanup_buffer_and_trigger(struct adis *adis,
struct iio_dev *indio_dev)
{
if (adis->spi->irq)
adis_remove_trigger(adis);
kfree(adis->buffer);
kfree(adis->xfer);
iio_triggered_buffer_cleanup(indio_dev);
}
EXPORT_SYMBOL_GPL(adis_cleanup_buffer_and_trigger);
/*
* Common library for ADIS16XXX devices
*
* Copyright 2012 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2 or later.
*/
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/export.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
#include <linux/iio/imu/adis.h>
static int adis_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
struct adis *adis = trig->private_data;
return adis_enable_irq(adis, state);
}
static const struct iio_trigger_ops adis_trigger_ops = {
.owner = THIS_MODULE,
.set_trigger_state = &adis_data_rdy_trigger_set_state,
};
/**
* adis_probe_trigger() - Sets up trigger for a adis device
* @adis: The adis device
* @indio_dev: The IIO device
*
* Returns 0 on success or a negative error code
*
* adis_remove_trigger() should be used to free the trigger.
*/
int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
{
int ret;
adis->trig = iio_trigger_alloc("%s-dev%d", indio_dev->name,
indio_dev->id);
if (adis->trig == NULL)
return -ENOMEM;
ret = request_irq(adis->spi->irq,
&iio_trigger_generic_data_rdy_poll,
IRQF_TRIGGER_RISING,
indio_dev->name,
adis->trig);
if (ret)
goto error_free_trig;
adis->trig->dev.parent = &adis->spi->dev;
adis->trig->ops = &adis_trigger_ops;
adis->trig->private_data = adis;
ret = iio_trigger_register(adis->trig);
indio_dev->trig = adis->trig;
if (ret)
goto error_free_irq;
return 0;
error_free_irq:
free_irq(adis->spi->irq, adis->trig);
error_free_trig:
iio_trigger_free(adis->trig);
return ret;
}
EXPORT_SYMBOL_GPL(adis_probe_trigger);
/**
* adis_remove_trigger() - Remove trigger for a adis devices
* @adis: The adis device
*
* Removes the trigger previously registered with adis_probe_trigger().
*/
void adis_remove_trigger(struct adis *adis)
{
iio_trigger_unregister(adis->trig);
free_irq(adis->spi->irq, adis->trig);
iio_trigger_free(adis->trig);
}
EXPORT_SYMBOL_GPL(adis_remove_trigger);
......@@ -65,6 +65,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_CAPACITANCE] = "capacitance",
[IIO_ALTVOLTAGE] = "altvoltage",
[IIO_CCT] = "cct",
[IIO_PRESSURE] = "pressure",
};
static const char * const iio_modifier_names[] = {
......@@ -407,6 +408,64 @@ static ssize_t iio_read_channel_info(struct device *dev,
}
}
/**
* iio_str_to_fixpoint() - Parse a fixed-point number from a string
* @str: The string to parse
* @fract_mult: Multiplier for the first decimal place, should be a power of 10
* @integer: The integer part of the number
* @fract: The fractional part of the number
*
* Returns 0 on success, or a negative error code if the string could not be
* parsed.
*/
int iio_str_to_fixpoint(const char *str, int fract_mult,
int *integer, int *fract)
{
int i = 0, f = 0;
bool integer_part = true, negative = false;
if (str[0] == '-') {
negative = true;
str++;
} else if (str[0] == '+') {
str++;
}
while (*str) {
if ('0' <= *str && *str <= '9') {
if (integer_part) {
i = i * 10 + *str - '0';
} else {
f += fract_mult * (*str - '0');
fract_mult /= 10;
}
} else if (*str == '\n') {
if (*(str + 1) == '\0')
break;
else
return -EINVAL;
} else if (*str == '.' && integer_part) {
integer_part = false;
} else {
return -EINVAL;
}
str++;
}
if (negative) {
if (i)
i = -i;
else
f = -f;
}
*integer = i;
*fract = f;
return 0;
}
EXPORT_SYMBOL_GPL(iio_str_to_fixpoint);
static ssize_t iio_write_channel_info(struct device *dev,
struct device_attribute *attr,
const char *buf,
......@@ -414,8 +473,8 @@ static ssize_t iio_write_channel_info(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret, integer = 0, fract = 0, fract_mult = 100000;
bool integer_part = true, negative = false;
int ret, fract_mult = 100000;
int integer, fract;
/* Assumes decimal - precision based on number of digits */
if (!indio_dev->info->write_raw)
......@@ -434,39 +493,9 @@ static ssize_t iio_write_channel_info(struct device *dev,
return -EINVAL;
}
if (buf[0] == '-') {
negative = true;
buf++;
} else if (buf[0] == '+') {
buf++;
}
while (*buf) {
if ('0' <= *buf && *buf <= '9') {
if (integer_part)
integer = integer*10 + *buf - '0';
else {
fract += fract_mult*(*buf - '0');
fract_mult /= 10;
}
} else if (*buf == '\n') {
if (*(buf + 1) == '\0')
break;
else
return -EINVAL;
} else if (*buf == '.' && integer_part) {
integer_part = false;
} else {
return -EINVAL;
}
buf++;
}
if (negative) {
if (integer)
integer = -integer;
else
fract = -fract;
}
ret = iio_str_to_fixpoint(buf, fract_mult, &integer, &fract);
if (ret)
return ret;
ret = indio_dev->info->write_raw(indio_dev, this_attr->c,
integer, fract, this_attr->address);
......
......@@ -350,15 +350,10 @@ static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev)
ret = iio_device_add_event_sysfs(indio_dev,
&indio_dev->channels[j]);
if (ret < 0)
goto error_clear_attrs;
return ret;
attrcount += ret;
}
return attrcount;
error_clear_attrs:
__iio_remove_event_config_attrs(indio_dev);
return ret;
}
static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev)
......
......@@ -272,10 +272,9 @@ static int __devinit hid_als_probe(struct platform_device *pdev)
goto error_free_dev;
}
channels = kmemdup(als_channels,
sizeof(als_channels),
GFP_KERNEL);
channels = kmemdup(als_channels, sizeof(als_channels), GFP_KERNEL);
if (!channels) {
ret = -ENOMEM;
dev_err(&pdev->dev, "failed to duplicate channels\n");
goto error_free_dev;
}
......
......@@ -307,10 +307,10 @@ static int __devinit hid_magn_3d_probe(struct platform_device *pdev)
goto error_free_dev;
}
channels = kmemdup(magn_3d_channels,
sizeof(magn_3d_channels),
channels = kmemdup(magn_3d_channels, sizeof(magn_3d_channels),
GFP_KERNEL);
if (!channels) {
ret = -ENOMEM;
dev_err(&pdev->dev, "failed to duplicate channels\n");
goto error_free_dev;
}
......
......@@ -6,8 +6,8 @@ menu "Accelerometers"
config ADIS16201
tristate "Analog Devices ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer"
depends on SPI
select IIO_TRIGGER if IIO_BUFFER
select IIO_SW_RING if IIO_BUFFER
select IIO_ADIS_LIB
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say yes here to build support for Analog Devices adis16201 dual-axis
digital inclinometer and accelerometer.
......@@ -15,8 +15,8 @@ config ADIS16201
config ADIS16203
tristate "Analog Devices ADIS16203 Programmable 360 Degrees Inclinometer"
depends on SPI
select IIO_TRIGGER if IIO_BUFFER
select IIO_SW_RING if IIO_BUFFER
select IIO_ADIS_LIB
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say yes here to build support for Analog Devices adis16203 Programmable
360 Degrees Inclinometer.
......@@ -24,8 +24,8 @@ config ADIS16203
config ADIS16204
tristate "Analog Devices ADIS16204 Programmable High-g Digital Impact Sensor and Recorder"
depends on SPI
select IIO_TRIGGER if IIO_BUFFER
select IIO_SW_RING if IIO_BUFFER
select IIO_ADIS_LIB
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say yes here to build support for Analog Devices adis16204 Programmable
High-g Digital Impact Sensor and Recorder.
......@@ -33,8 +33,8 @@ config ADIS16204
config ADIS16209
tristate "Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer"
depends on SPI
select IIO_TRIGGER if IIO_BUFFER
select IIO_SW_RING if IIO_BUFFER
select IIO_ADIS_LIB
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say yes here to build support for Analog Devices adis16209 dual-axis digital inclinometer
and accelerometer.
......@@ -42,6 +42,7 @@ config ADIS16209
config ADIS16220
tristate "Analog Devices ADIS16220 Programmable Digital Vibration Sensor"
depends on SPI
select IIO_ADIS_LIB
help
Say yes here to build support for Analog Devices adis16220 programmable
digital vibration sensor.
......@@ -49,8 +50,8 @@ config ADIS16220
config ADIS16240
tristate "Analog Devices ADIS16240 Programmable Impact Sensor and Recorder"
depends on SPI
select IIO_TRIGGER if IIO_BUFFER
select IIO_SW_RING if IIO_BUFFER
select IIO_ADIS_LIB
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say yes here to build support for Analog Devices adis16240 programmable
impact Sensor and recorder.
......
......@@ -3,26 +3,21 @@
#
adis16201-y := adis16201_core.o
adis16201-$(CONFIG_IIO_BUFFER) += adis16201_ring.o adis16201_trigger.o
obj-$(CONFIG_ADIS16201) += adis16201.o
adis16203-y := adis16203_core.o
adis16203-$(CONFIG_IIO_BUFFER) += adis16203_ring.o adis16203_trigger.o
obj-$(CONFIG_ADIS16203) += adis16203.o
adis16204-y := adis16204_core.o
adis16204-$(CONFIG_IIO_BUFFER) += adis16204_ring.o adis16204_trigger.o
obj-$(CONFIG_ADIS16204) += adis16204.o
adis16209-y := adis16209_core.o
adis16209-$(CONFIG_IIO_BUFFER) += adis16209_ring.o adis16209_trigger.o
obj-$(CONFIG_ADIS16209) += adis16209.o
adis16220-y := adis16220_core.o
obj-$(CONFIG_ADIS16220) += adis16220.o
adis16240-y := adis16240_core.o
adis16240-$(CONFIG_IIO_BUFFER) += adis16240_ring.o adis16240_trigger.o
obj-$(CONFIG_ADIS16240) += adis16240.o
obj-$(CONFIG_KXSD9) += kxsd9.o
......
......@@ -3,9 +3,6 @@
#define ADIS16201_STARTUP_DELAY 220 /* ms */
#define ADIS16201_READ_REG(a) a
#define ADIS16201_WRITE_REG(a) ((a) | 0x80)
#define ADIS16201_FLASH_CNT 0x00 /* Flash memory write count */
#define ADIS16201_SUPPLY_OUT 0x02 /* Output, power supply */
#define ADIS16201_XACCL_OUT 0x04 /* Output, x-axis accelerometer */
......@@ -36,8 +33,6 @@
#define ADIS16201_DIAG_STAT 0x3C /* Diagnostics, system status register */
#define ADIS16201_GLOB_CMD 0x3E /* Operation, system command register */
#define ADIS16201_OUTPUTS 7
/* MSC_CTRL */
#define ADIS16201_MSC_CTRL_SELF_TEST_EN (1 << 8) /* Self-test enable */
#define ADIS16201_MSC_CTRL_DATA_RDY_EN (1 << 2) /* Data-ready enable: 1 = enabled, 0 = disabled */
......@@ -47,95 +42,25 @@
/* DIAG_STAT */
#define ADIS16201_DIAG_STAT_ALARM2 (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16201_DIAG_STAT_ALARM1 (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16201_DIAG_STAT_SPI_FAIL (1<<3) /* SPI communications failure */
#define ADIS16201_DIAG_STAT_FLASH_UPT (1<<2) /* Flash update failure */
#define ADIS16201_DIAG_STAT_POWER_HIGH (1<<1) /* Power supply above 3.625 V */
#define ADIS16201_DIAG_STAT_POWER_LOW (1<<0) /* Power supply below 3.15 V */
#define ADIS16201_DIAG_STAT_SPI_FAIL_BIT 3 /* SPI communications failure */
#define ADIS16201_DIAG_STAT_FLASH_UPT_BIT 2 /* Flash update failure */
#define ADIS16201_DIAG_STAT_POWER_HIGH_BIT 1 /* Power supply above 3.625 V */
#define ADIS16201_DIAG_STAT_POWER_LOW_BIT 0 /* Power supply below 3.15 V */
/* GLOB_CMD */
#define ADIS16201_GLOB_CMD_SW_RESET (1<<7)
#define ADIS16201_GLOB_CMD_FACTORY_CAL (1<<1)
#define ADIS16201_MAX_TX 14
#define ADIS16201_MAX_RX 14
#define ADIS16201_ERROR_ACTIVE (1<<14)
/**
* struct adis16201_state - device instance specific data
* @us: actual spi_device
* @trig: data ready trigger registered with iio
* @tx: transmit buffer
* @rx: receive buffer
* @buf_lock: mutex to protect tx and rx
**/
struct adis16201_state {
struct spi_device *us;
struct iio_trigger *trig;
struct mutex buf_lock;
u8 tx[14] ____cacheline_aligned;
u8 rx[14];
};
int adis16201_set_irq(struct iio_dev *indio_dev, bool enable);
enum adis16201_scan {
ADIS16201_SCAN_SUPPLY,
ADIS16201_SCAN_ACC_X,
ADIS16201_SCAN_ACC_Y,
ADIS16201_SCAN_AUX_ADC,
ADIS16201_SCAN_TEMP,
ADIS16201_SCAN_INCLI_X,
ADIS16201_SCAN_INCLI_Y,
ADIS16201_SCAN_SUPPLY,
ADIS16201_SCAN_AUX_ADC,
ADIS16201_SCAN_TEMP,
};
#ifdef CONFIG_IIO_BUFFER
void adis16201_remove_trigger(struct iio_dev *indio_dev);
int adis16201_probe_trigger(struct iio_dev *indio_dev);
ssize_t adis16201_read_data_from_ring(struct device *dev,
struct device_attribute *attr,
char *buf);
int adis16201_configure_ring(struct iio_dev *indio_dev);
void adis16201_unconfigure_ring(struct iio_dev *indio_dev);
#else /* CONFIG_IIO_BUFFER */
static inline void adis16201_remove_trigger(struct iio_dev *indio_dev)
{
}
static inline int adis16201_probe_trigger(struct iio_dev *indio_dev)
{
return 0;
}
static inline ssize_t
adis16201_read_data_from_ring(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return 0;
}
static int adis16201_configure_ring(struct iio_dev *indio_dev)
{
return 0;
}
static inline void adis16201_unconfigure_ring(struct iio_dev *indio_dev)
{
}
static inline int adis16201_initialize_ring(struct iio_ring_buffer *ring)
{
return 0;
}
static inline void adis16201_uninitialize_ring(struct iio_ring_buffer *ring)
{
}
#endif /* CONFIG_IIO_BUFFER */
#endif /* SPI_ADIS16201_H_ */
This diff is collapsed.
#include <linux/export.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/iio/iio.h>
#include "../ring_sw.h"
#include <linux/iio/trigger_consumer.h>
#include "adis16201.h"
/**
* adis16201_read_ring_data() read data registers which will be placed into ring
* @dev: device associated with child of actual device (iio_dev or iio_trig)
* @rx: somewhere to pass back the value read
**/
static int adis16201_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
{
struct spi_message msg;
struct adis16201_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[ADIS16201_OUTPUTS + 1];
int ret;
int i;
mutex_lock(&st->buf_lock);
spi_message_init(&msg);
memset(xfers, 0, sizeof(xfers));
for (i = 0; i <= ADIS16201_OUTPUTS; i++) {
xfers[i].bits_per_word = 8;
xfers[i].cs_change = 1;
xfers[i].len = 2;
xfers[i].delay_usecs = 20;
if (i < ADIS16201_OUTPUTS) {
xfers[i].tx_buf = st->tx + 2 * i;
st->tx[2 * i] = ADIS16201_READ_REG(ADIS16201_SUPPLY_OUT +
2 * i);
st->tx[2 * i + 1] = 0;
}
if (i >= 1)
xfers[i].rx_buf = rx + 2 * (i - 1);
spi_message_add_tail(&xfers[i], &msg);
}
ret = spi_sync(st->us, &msg);
if (ret)
dev_err(&st->us->dev, "problem when burst reading");
mutex_unlock(&st->buf_lock);
return ret;
}
/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
* specific to be rolled into the core.
*/
static irqreturn_t adis16201_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct adis16201_state *st = iio_priv(indio_dev);
int i = 0;
s16 *data;
data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
goto done;
}
if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)
&& adis16201_read_ring_data(indio_dev, st->rx) >= 0)
for (; i < bitmap_weight(indio_dev->active_scan_mask,
indio_dev->masklength); i++)
data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
iio_push_to_buffers(indio_dev, (u8 *)data);
kfree(data);
done:
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
void adis16201_unconfigure_ring(struct iio_dev *indio_dev)
{
iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->buffer);
}
static const struct iio_buffer_setup_ops adis16201_ring_setup_ops = {
.preenable = &iio_sw_buffer_preenable,
.postenable = &iio_triggered_buffer_postenable,
.predisable = &iio_triggered_buffer_predisable,
};
int adis16201_configure_ring(struct iio_dev *indio_dev)
{
int ret = 0;
struct iio_buffer *ring;
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
ret = -ENOMEM;
return ret;
}
indio_dev->buffer = ring;
ring->scan_timestamp = true;
indio_dev->setup_ops = &adis16201_ring_setup_ops;
indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
&adis16201_trigger_handler,
IRQF_ONESHOT,
indio_dev,
"adis16201_consumer%d",
indio_dev->id);
if (indio_dev->pollfunc == NULL) {
ret = -ENOMEM;
goto error_iio_sw_rb_free;
}
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
return 0;
error_iio_sw_rb_free:
iio_sw_rb_free(indio_dev->buffer);
return ret;
}
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/export.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
#include "adis16201.h"
/**
* adis16201_data_rdy_trigger_set_state() set datardy interrupt state
**/
static int adis16201_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
struct iio_dev *indio_dev = trig->private_data;
dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
return adis16201_set_irq(indio_dev, state);
}
static const struct iio_trigger_ops adis16201_trigger_ops = {
.owner = THIS_MODULE,
.set_trigger_state = &adis16201_data_rdy_trigger_set_state,
};
int adis16201_probe_trigger(struct iio_dev *indio_dev)
{
int ret;
struct adis16201_state *st = iio_priv(indio_dev);
st->trig = iio_trigger_alloc("adis16201-dev%d", indio_dev->id);
if (st->trig == NULL) {
ret = -ENOMEM;
goto error_ret;
}
ret = request_irq(st->us->irq,
&iio_trigger_generic_data_rdy_poll,
IRQF_TRIGGER_RISING,
"adis16201",
st->trig);
if (ret)
goto error_free_trig;
st->trig->dev.parent = &st->us->dev;
st->trig->ops = &adis16201_trigger_ops;
st->trig->private_data = indio_dev;
ret = iio_trigger_register(st->trig);
/* select default trigger */
indio_dev->trig = st->trig;
if (ret)
goto error_free_irq;
return 0;
error_free_irq:
free_irq(st->us->irq, st->trig);
error_free_trig:
iio_trigger_free(st->trig);
error_ret:
return ret;
}
void adis16201_remove_trigger(struct iio_dev *indio_dev)
{
struct adis16201_state *state = iio_priv(indio_dev);
iio_trigger_unregister(state->trig);
free_irq(state->us->irq, state->trig);
iio_trigger_free(state->trig);
}
......@@ -3,9 +3,6 @@
#define ADIS16203_STARTUP_DELAY 220 /* ms */
#define ADIS16203_READ_REG(a) a
#define ADIS16203_WRITE_REG(a) ((a) | 0x80)
#define ADIS16203_FLASH_CNT 0x00 /* Flash memory write count */
#define ADIS16203_SUPPLY_OUT 0x02 /* Output, power supply */
#define ADIS16203_AUX_ADC 0x08 /* Output, auxiliary ADC input */
......@@ -27,8 +24,6 @@
#define ADIS16203_DIAG_STAT 0x3C /* Diagnostics, system status register */
#define ADIS16203_GLOB_CMD 0x3E /* Operation, system command register */
#define ADIS16203_OUTPUTS 5
/* MSC_CTRL */
#define ADIS16203_MSC_CTRL_PWRUP_SELF_TEST (1 << 10) /* Self-test at power-on: 1 = disabled, 0 = enabled */
#define ADIS16203_MSC_CTRL_REVERSE_ROT_EN (1 << 9) /* Reverses rotation of both inclination outputs */
......@@ -40,86 +35,25 @@
/* DIAG_STAT */
#define ADIS16203_DIAG_STAT_ALARM2 (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16203_DIAG_STAT_ALARM1 (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16203_DIAG_STAT_SELFTEST_FAIL (1<<5) /* Self-test diagnostic error flag */
#define ADIS16203_DIAG_STAT_SPI_FAIL (1<<3) /* SPI communications failure */
#define ADIS16203_DIAG_STAT_FLASH_UPT (1<<2) /* Flash update failure */
#define ADIS16203_DIAG_STAT_POWER_HIGH (1<<1) /* Power supply above 3.625 V */
#define ADIS16203_DIAG_STAT_POWER_LOW (1<<0) /* Power supply below 3.15 V */
#define ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT 5 /* Self-test diagnostic error flag */
#define ADIS16203_DIAG_STAT_SPI_FAIL_BIT 3 /* SPI communications failure */
#define ADIS16203_DIAG_STAT_FLASH_UPT_BIT 2 /* Flash update failure */
#define ADIS16203_DIAG_STAT_POWER_HIGH_BIT 1 /* Power supply above 3.625 V */
#define ADIS16203_DIAG_STAT_POWER_LOW_BIT 0 /* Power supply below 3.15 V */
/* GLOB_CMD */
#define ADIS16203_GLOB_CMD_SW_RESET (1<<7)
#define ADIS16203_GLOB_CMD_CLEAR_STAT (1<<4)
#define ADIS16203_GLOB_CMD_FACTORY_CAL (1<<1)
#define ADIS16203_MAX_TX 12
#define ADIS16203_MAX_RX 10
#define ADIS16203_ERROR_ACTIVE (1<<14)
/**
* struct adis16203_state - device instance specific data
* @us: actual spi_device
* @trig: data ready trigger registered with iio
* @tx: transmit buffer
* @rx: receive buffer
* @buf_lock: mutex to protect tx and rx
**/
struct adis16203_state {
struct spi_device *us;
struct iio_trigger *trig;
struct mutex buf_lock;
u8 tx[ADIS16203_MAX_TX] ____cacheline_aligned;
u8 rx[ADIS16203_MAX_RX];
};
int adis16203_set_irq(struct iio_dev *indio_dev, bool enable);
enum adis16203_scan {
ADIS16203_SCAN_INCLI_X,
ADIS16203_SCAN_INCLI_Y,
ADIS16203_SCAN_SUPPLY,
ADIS16203_SCAN_AUX_ADC,
ADIS16203_SCAN_TEMP,
ADIS16203_SCAN_INCLI_X,
ADIS16203_SCAN_INCLI_Y,
};
#ifdef CONFIG_IIO_BUFFER
void adis16203_remove_trigger(struct iio_dev *indio_dev);
int adis16203_probe_trigger(struct iio_dev *indio_dev);
ssize_t adis16203_read_data_from_ring(struct device *dev,
struct device_attribute *attr,
char *buf);
int adis16203_configure_ring(struct iio_dev *indio_dev);
void adis16203_unconfigure_ring(struct iio_dev *indio_dev);
#else /* CONFIG_IIO_BUFFER */
static inline void adis16203_remove_trigger(struct iio_dev *indio_dev)
{
}
static inline int adis16203_probe_trigger(struct iio_dev *indio_dev)
{
return 0;
}
static inline ssize_t
adis16203_read_data_from_ring(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return 0;
}
static int adis16203_configure_ring(struct iio_dev *indio_dev)
{
return 0;
}
static inline void adis16203_unconfigure_ring(struct iio_dev *indio_dev)
{
}
#endif /* CONFIG_IIO_BUFFER */
#endif /* SPI_ADIS16203_H_ */
This diff is collapsed.
#include <linux/export.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/iio/iio.h>
#include "../ring_sw.h"
#include <linux/iio/trigger_consumer.h>
#include "adis16203.h"
/**
* adis16203_read_ring_data() read data registers which will be placed into ring
* @indio_dev: the IIO device
* @rx: somewhere to pass back the value read
**/
static int adis16203_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
{
struct spi_message msg;
struct adis16203_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[ADIS16203_OUTPUTS + 1];
int ret;
int i;
mutex_lock(&st->buf_lock);
spi_message_init(&msg);
memset(xfers, 0, sizeof(xfers));
for (i = 0; i <= ADIS16203_OUTPUTS; i++) {
xfers[i].bits_per_word = 8;
xfers[i].cs_change = 1;
xfers[i].len = 2;
xfers[i].delay_usecs = 20;
xfers[i].tx_buf = st->tx + 2 * i;
if (i < 1) /* SUPPLY_OUT: 0x02, AUX_ADC: 0x08 */
st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i);
else
st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i + 6);
st->tx[2 * i + 1] = 0;
if (i >= 1)
xfers[i].rx_buf = rx + 2 * (i - 1);
spi_message_add_tail(&xfers[i], &msg);
}
ret = spi_sync(st->us, &msg);
if (ret)
dev_err(&st->us->dev, "problem when burst reading");
mutex_unlock(&st->buf_lock);
return ret;
}
/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
* specific to be rolled into the core.
*/
static irqreturn_t adis16203_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct adis16203_state *st = iio_priv(indio_dev);
int i = 0;
s16 *data;
data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
goto done;
}
if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
adis16203_read_ring_data(indio_dev, st->rx) >= 0)
for (; i < bitmap_weight(indio_dev->active_scan_mask,
indio_dev->masklength); i++)
data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
iio_push_to_buffers(indio_dev, (u8 *)data);
kfree(data);
done:
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
void adis16203_unconfigure_ring(struct iio_dev *indio_dev)
{
iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->buffer);
}
static const struct iio_buffer_setup_ops adis16203_ring_setup_ops = {
.preenable = &iio_sw_buffer_preenable,
.postenable = &iio_triggered_buffer_postenable,
.predisable = &iio_triggered_buffer_predisable,
};
int adis16203_configure_ring(struct iio_dev *indio_dev)
{
int ret = 0;
struct iio_buffer *ring;
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
ret = -ENOMEM;
return ret;
}
indio_dev->buffer = ring;
ring->scan_timestamp = true;
indio_dev->setup_ops = &adis16203_ring_setup_ops;
indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
&adis16203_trigger_handler,
IRQF_ONESHOT,
indio_dev,
"adis16203_consumer%d",
indio_dev->id);
if (indio_dev->pollfunc == NULL) {
ret = -ENOMEM;
goto error_iio_sw_rb_free;
}
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
return 0;
error_iio_sw_rb_free:
iio_sw_rb_free(indio_dev->buffer);
return ret;
}
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/export.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
#include "adis16203.h"
/**
* adis16203_data_rdy_trigger_set_state() set datardy interrupt state
**/
static int adis16203_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
struct iio_dev *indio_dev = trig->private_data;
dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
return adis16203_set_irq(indio_dev, state);
}
static const struct iio_trigger_ops adis16203_trigger_ops = {
.owner = THIS_MODULE,
.set_trigger_state = &adis16203_data_rdy_trigger_set_state,
};
int adis16203_probe_trigger(struct iio_dev *indio_dev)
{
int ret;
struct adis16203_state *st = iio_priv(indio_dev);
st->trig = iio_trigger_alloc("adis16203-dev%d", indio_dev->id);
if (st->trig == NULL) {
ret = -ENOMEM;
goto error_ret;
}
ret = request_irq(st->us->irq,
&iio_trigger_generic_data_rdy_poll,
IRQF_TRIGGER_RISING,
"adis16203",
st->trig);
if (ret)
goto error_free_trig;
st->trig->dev.parent = &st->us->dev;
st->trig->ops = &adis16203_trigger_ops;
st->trig->private_data = indio_dev;
ret = iio_trigger_register(st->trig);
/* select default trigger */
indio_dev->trig = st->trig;
if (ret)
goto error_free_irq;
return 0;
error_free_irq:
free_irq(st->us->irq, st->trig);
error_free_trig:
iio_trigger_free(st->trig);
error_ret:
return ret;
}
void adis16203_remove_trigger(struct iio_dev *indio_dev)
{
struct adis16203_state *st = iio_priv(indio_dev);
iio_trigger_unregister(st->trig);
free_irq(st->us->irq, st->trig);
iio_trigger_free(st->trig);
}
......@@ -3,9 +3,6 @@
#define ADIS16204_STARTUP_DELAY 220 /* ms */
#define ADIS16204_READ_REG(a) a
#define ADIS16204_WRITE_REG(a) ((a) | 0x80)
#define ADIS16204_FLASH_CNT 0x00 /* Flash memory write count */
#define ADIS16204_SUPPLY_OUT 0x02 /* Output, power supply */
#define ADIS16204_XACCL_OUT 0x04 /* Output, x-axis accelerometer */
......@@ -35,8 +32,6 @@
#define ADIS16204_DIAG_STAT 0x3C /* Diagnostics, system status register */
#define ADIS16204_GLOB_CMD 0x3E /* Operation, system command register */
#define ADIS16204_OUTPUTS 5
/* MSC_CTRL */
#define ADIS16204_MSC_CTRL_PWRUP_SELF_TEST (1 << 10) /* Self-test at power-on: 1 = disabled, 0 = enabled */
#define ADIS16204_MSC_CTRL_SELF_TEST_EN (1 << 8) /* Self-test enable */
......@@ -47,87 +42,27 @@
/* DIAG_STAT */
#define ADIS16204_DIAG_STAT_ALARM2 (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16204_DIAG_STAT_ALARM1 (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16204_DIAG_STAT_SELFTEST_FAIL (1<<5) /* Self-test diagnostic error flag: 1 = error condition,
#define ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT 5 /* Self-test diagnostic error flag: 1 = error condition,
0 = normal operation */
#define ADIS16204_DIAG_STAT_SPI_FAIL (1<<3) /* SPI communications failure */
#define ADIS16204_DIAG_STAT_FLASH_UPT (1<<2) /* Flash update failure */
#define ADIS16204_DIAG_STAT_POWER_HIGH (1<<1) /* Power supply above 3.625 V */
#define ADIS16204_DIAG_STAT_POWER_LOW (1<<0) /* Power supply below 2.975 V */
#define ADIS16204_DIAG_STAT_SPI_FAIL_BIT 3 /* SPI communications failure */
#define ADIS16204_DIAG_STAT_FLASH_UPT_BIT 2 /* Flash update failure */
#define ADIS16204_DIAG_STAT_POWER_HIGH_BIT 1 /* Power supply above 3.625 V */
#define ADIS16204_DIAG_STAT_POWER_LOW_BIT 0 /* Power supply below 2.975 V */
/* GLOB_CMD */
#define ADIS16204_GLOB_CMD_SW_RESET (1<<7)
#define ADIS16204_GLOB_CMD_CLEAR_STAT (1<<4)
#define ADIS16204_GLOB_CMD_FACTORY_CAL (1<<1)
#define ADIS16204_MAX_TX 24
#define ADIS16204_MAX_RX 24
#define ADIS16204_ERROR_ACTIVE (1<<14)
/**
* struct adis16204_state - device instance specific data
* @us: actual spi_device
* @trig: data ready trigger registered with iio
* @tx: transmit buffer
* @rx: receive buffer
* @buf_lock: mutex to protect tx and rx
**/
struct adis16204_state {
struct spi_device *us;
struct iio_trigger *trig;
struct mutex buf_lock;
u8 tx[ADIS16204_MAX_TX] ____cacheline_aligned;
u8 rx[ADIS16204_MAX_RX];
};
int adis16204_set_irq(struct iio_dev *indio_dev, bool enable);
enum adis16204_scan {
ADIS16204_SCAN_SUPPLY,
ADIS16204_SCAN_ACC_X,
ADIS16204_SCAN_ACC_Y,
ADIS16204_SCAN_ACC_XY,
ADIS16204_SCAN_SUPPLY,
ADIS16204_SCAN_AUX_ADC,
ADIS16204_SCAN_TEMP,
};
#ifdef CONFIG_IIO_BUFFER
void adis16204_remove_trigger(struct iio_dev *indio_dev);
int adis16204_probe_trigger(struct iio_dev *indio_dev);
ssize_t adis16204_read_data_from_ring(struct device *dev,
struct device_attribute *attr,
char *buf);
int adis16204_configure_ring(struct iio_dev *indio_dev);
void adis16204_unconfigure_ring(struct iio_dev *indio_dev);
#else /* CONFIG_IIO_BUFFER */
static inline void adis16204_remove_trigger(struct iio_dev *indio_dev)
{
}
static inline int adis16204_probe_trigger(struct iio_dev *indio_dev)
{
return 0;
}
static inline ssize_t
adis16204_read_data_from_ring(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return 0;
}
static int adis16204_configure_ring(struct iio_dev *indio_dev)
{
return 0;
}
static inline void adis16204_unconfigure_ring(struct iio_dev *indio_dev)
{
}
#endif /* CONFIG_IIO_BUFFER */
#endif /* SPI_ADIS16204_H_ */
This diff is collapsed.
#include <linux/export.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/iio/iio.h>
#include "../ring_sw.h"
#include <linux/iio/trigger_consumer.h>
#include "adis16204.h"
/**
* adis16204_read_ring_data() read data registers which will be placed into ring
* @indio_dev: the IIO device
* @rx: somewhere to pass back the value read
**/
static int adis16204_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
{
struct spi_message msg;
struct adis16204_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[ADIS16204_OUTPUTS + 1];
int ret;
int i;
mutex_lock(&st->buf_lock);
spi_message_init(&msg);
memset(xfers, 0, sizeof(xfers));
for (i = 0; i <= ADIS16204_OUTPUTS; i++) {
xfers[i].bits_per_word = 8;
xfers[i].cs_change = 1;
xfers[i].len = 2;
xfers[i].delay_usecs = 20;
xfers[i].tx_buf = st->tx + 2 * i;
st->tx[2 * i]
= ADIS16204_READ_REG(ADIS16204_SUPPLY_OUT + 2 * i);
st->tx[2 * i + 1] = 0;
if (i >= 1)
xfers[i].rx_buf = rx + 2 * (i - 1);
spi_message_add_tail(&xfers[i], &msg);
}
ret = spi_sync(st->us, &msg);
if (ret)
dev_err(&st->us->dev, "problem when burst reading");
mutex_unlock(&st->buf_lock);
return ret;
}
/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
* specific to be rolled into the core.
*/
static irqreturn_t adis16204_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct adis16204_state *st = iio_priv(indio_dev);
int i = 0;
s16 *data;
data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
goto done;
}
if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
adis16204_read_ring_data(indio_dev, st->rx) >= 0)
for (; i < bitmap_weight(indio_dev->active_scan_mask,
indio_dev->masklength); i++)
data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
iio_push_to_buffers(indio_dev, (u8 *)data);
kfree(data);
done:
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
void adis16204_unconfigure_ring(struct iio_dev *indio_dev)
{
iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->buffer);
}
static const struct iio_buffer_setup_ops adis16204_ring_setup_ops = {
.preenable = &iio_sw_buffer_preenable,
.postenable = &iio_triggered_buffer_postenable,
.predisable = &iio_triggered_buffer_predisable,
};
int adis16204_configure_ring(struct iio_dev *indio_dev)
{
int ret = 0;
struct iio_buffer *ring;
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
ret = -ENOMEM;
return ret;
}
indio_dev->buffer = ring;
ring->scan_timestamp = true;
indio_dev->setup_ops = &adis16204_ring_setup_ops;
indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
&adis16204_trigger_handler,
IRQF_ONESHOT,
indio_dev,
"%s_consumer%d",
indio_dev->name,
indio_dev->id);
if (indio_dev->pollfunc == NULL) {
ret = -ENOMEM;
goto error_iio_sw_rb_free;
}
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
return 0;
error_iio_sw_rb_free:
iio_sw_rb_free(indio_dev->buffer);
return ret;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#ifndef SPI_ADIS16220_H_
#define SPI_ADIS16220_H_
#define ADIS16220_STARTUP_DELAY 220 /* ms */
#include <linux/iio/imu/adis.h>
#define ADIS16220_READ_REG(a) a
#define ADIS16220_WRITE_REG(a) ((a) | 0x80)
#define ADIS16220_STARTUP_DELAY 220 /* ms */
/* Flash memory write count */
#define ADIS16220_FLASH_CNT 0x00
......@@ -102,15 +101,15 @@
#define ADIS16220_DIAG_STAT_FLASH_CHK (1<<6)
#define ADIS16220_DIAG_STAT_SELF_TEST (1<<5)
/* Capture period violation/interruption */
#define ADIS16220_DIAG_STAT_VIOLATION (1<<4)
#define ADIS16220_DIAG_STAT_VIOLATION_BIT 4
/* SPI communications failure */
#define ADIS16220_DIAG_STAT_SPI_FAIL (1<<3)
#define ADIS16220_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16220_DIAG_STAT_FLASH_UPT (1<<2)
#define ADIS16220_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16220_DIAG_STAT_POWER_HIGH (1<<1)
#define ADIS16220_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16220_DIAG_STAT_POWER_LOW (1<<0)
#define ADIS16220_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16220_GLOB_CMD_SW_RESET (1<<7)
......@@ -125,13 +124,14 @@
/**
* struct adis16220_state - device instance specific data
* @us: actual spi_device
* @adis: adis device
* @tx: transmit buffer
* @rx: receive buffer
* @buf_lock: mutex to protect tx and rx
**/
struct adis16220_state {
struct spi_device *us;
struct adis adis;
struct mutex buf_lock;
u8 tx[ADIS16220_MAX_TX] ____cacheline_aligned;
u8 rx[ADIS16220_MAX_RX];
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -181,7 +181,7 @@ static ssize_t adt7410_store_mode(struct device *dev,
chip->config = config;
return ret;
return len;
}
static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment