Commit 5cb7cb11 authored by Lars-Peter Clausen's avatar Lars-Peter Clausen Committed by Jonathan Cameron

staging:iio:adis16240: Use adis library

Use the new adis library for the adis16240 driver. This allows us to completely
scrap the adis16240 buffer and trigger code and more than half of the core
driver code.
Signed-off-by: default avatarLars-Peter Clausen <lars@metafoo.de>
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
parent edcf6009
......@@ -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.
......
......@@ -18,7 +18,6 @@ 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 ADIS16240_STARTUP_DELAY 220 /* ms */
#define ADIS16240_READ_REG(a) a
#define ADIS16240_WRITE_REG(a) ((a) | 0x80)
/* Flash memory write count */
#define ADIS16240_FLASH_CNT 0x00
/* Output, power supply */
......@@ -75,8 +72,6 @@
/* System command */
#define ADIS16240_GLOB_CMD 0x4A
#define ADIS16240_OUTPUTS 6
/* MSC_CTRL */
/* Enables sum-of-squares output (XYZPEAK_OUT) */
#define ADIS16240_MSC_CTRL_XYZPEAK_OUT_EN (1 << 15)
......@@ -101,17 +96,17 @@
/* Flash test, checksum flag: 1 = mismatch, 0 = match */
#define ADIS16240_DIAG_STAT_CHKSUM (1<<6)
/* Power-on, self-test flag: 1 = failure, 0 = pass */
#define ADIS16240_DIAG_STAT_PWRON_FAIL (1<<5)
#define ADIS16240_DIAG_STAT_PWRON_FAIL_BIT 5
/* Power-on self-test: 1 = in-progress, 0 = complete */
#define ADIS16240_DIAG_STAT_PWRON_BUSY (1<<4)
/* SPI communications failure */
#define ADIS16240_DIAG_STAT_SPI_FAIL (1<<3)
#define ADIS16240_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16240_DIAG_STAT_FLASH_UPT (1<<2)
#define ADIS16240_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16240_DIAG_STAT_POWER_HIGH (1<<1)
#define ADIS16240_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16240_DIAG_STAT_POWER_LOW (1<<0)
#define ADIS16240_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16240_GLOB_CMD_RESUME (1<<8)
......@@ -120,77 +115,15 @@
#define ADIS16240_ERROR_ACTIVE (1<<14)
#define ADIS16240_MAX_TX 24
#define ADIS16240_MAX_RX 24
/**
* struct adis16240_state - device instance specific data
* @us: actual spi_device
* @trig: data ready trigger registered with iio
* @tx: transmit buffer
* @rx: receive buffer
* @buf_lock: mutex to protect tx and rx
**/
struct adis16240_state {
struct spi_device *us;
struct iio_trigger *trig;
struct mutex buf_lock;
u8 tx[ADIS16240_MAX_TX] ____cacheline_aligned;
u8 rx[ADIS16240_MAX_RX];
};
int adis16240_set_irq(struct iio_dev *indio_dev, bool enable);
/* At the moment triggers are only used for ring buffer
* filling. This may change!
*/
#define ADIS16240_SCAN_SUPPLY 0
#define ADIS16240_SCAN_ACC_X 1
#define ADIS16240_SCAN_ACC_Y 2
#define ADIS16240_SCAN_ACC_Z 3
#define ADIS16240_SCAN_ACC_X 0
#define ADIS16240_SCAN_ACC_Y 1
#define ADIS16240_SCAN_ACC_Z 2
#define ADIS16240_SCAN_SUPPLY 3
#define ADIS16240_SCAN_AUX_ADC 4
#define ADIS16240_SCAN_TEMP 5
#ifdef CONFIG_IIO_BUFFER
void adis16240_remove_trigger(struct iio_dev *indio_dev);
int adis16240_probe_trigger(struct iio_dev *indio_dev);
ssize_t adis16240_read_data_from_ring(struct device *dev,
struct device_attribute *attr,
char *buf);
int adis16240_configure_ring(struct iio_dev *indio_dev);
void adis16240_unconfigure_ring(struct iio_dev *indio_dev);
#else /* CONFIG_IIO_BUFFER */
static inline void adis16240_remove_trigger(struct iio_dev *indio_dev)
{
}
static inline int adis16240_probe_trigger(struct iio_dev *indio_dev)
{
return 0;
}
static inline ssize_t
adis16240_read_data_from_ring(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return 0;
}
static int adis16240_configure_ring(struct iio_dev *indio_dev)
{
return 0;
}
static inline void adis16240_unconfigure_ring(struct iio_dev *indio_dev)
{
}
#endif /* CONFIG_IIO_BUFFER */
#endif /* SPI_ADIS16240_H_ */
......@@ -24,128 +24,7 @@
#include <linux/iio/buffer.h>
#include "adis16240.h"
static int adis16240_check_status(struct iio_dev *indio_dev);
/**
* adis16240_spi_write_reg_8() - write single byte to a register
* @indio_dev: iio_dev associated with device
* @reg_address: the address of the register to be written
* @val: the value to write
**/
static int adis16240_spi_write_reg_8(struct iio_dev *indio_dev,
u8 reg_address,
u8 val)
{
int ret;
struct adis16240_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
st->tx[0] = ADIS16240_WRITE_REG(reg_address);
st->tx[1] = val;
ret = spi_write(st->us, st->tx, 2);
mutex_unlock(&st->buf_lock);
return ret;
}
/**
* adis16240_spi_write_reg_16() - write 2 bytes to a pair of registers
* @indio_dev: iio_dev for this device
* @reg_address: the address of the lower of the two registers. Second register
* is assumed to have address one greater.
* @val: value to be written
**/
static int adis16240_spi_write_reg_16(struct iio_dev *indio_dev,
u8 lower_reg_address,
u16 value)
{
int ret;
struct spi_message msg;
struct adis16240_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[] = {
{
.tx_buf = st->tx,
.bits_per_word = 8,
.len = 2,
.cs_change = 1,
.delay_usecs = 35,
}, {
.tx_buf = st->tx + 2,
.bits_per_word = 8,
.len = 2,
.delay_usecs = 35,
},
};
mutex_lock(&st->buf_lock);
st->tx[0] = ADIS16240_WRITE_REG(lower_reg_address);
st->tx[1] = value & 0xFF;
st->tx[2] = ADIS16240_WRITE_REG(lower_reg_address + 1);
st->tx[3] = (value >> 8) & 0xFF;
spi_message_init(&msg);
spi_message_add_tail(&xfers[0], &msg);
spi_message_add_tail(&xfers[1], &msg);
ret = spi_sync(st->us, &msg);
mutex_unlock(&st->buf_lock);
return ret;
}
/**
* adis16240_spi_read_reg_16() - read 2 bytes from a 16-bit register
* @indio_dev: iio_dev for this device
* @reg_address: the address of the lower of the two registers. Second register
* is assumed to have address one greater.
* @val: somewhere to pass back the value read
**/
static int adis16240_spi_read_reg_16(struct iio_dev *indio_dev,
u8 lower_reg_address,
u16 *val)
{
struct spi_message msg;
struct adis16240_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
{
.tx_buf = st->tx,
.bits_per_word = 8,
.len = 2,
.cs_change = 1,
.delay_usecs = 35,
}, {
.rx_buf = st->rx,
.bits_per_word = 8,
.len = 2,
.cs_change = 1,
.delay_usecs = 35,
},
};
mutex_lock(&st->buf_lock);
st->tx[0] = ADIS16240_READ_REG(lower_reg_address);
st->tx[1] = 0;
st->tx[2] = 0;
st->tx[3] = 0;
spi_message_init(&msg);
spi_message_add_tail(&xfers[0], &msg);
spi_message_add_tail(&xfers[1], &msg);
ret = spi_sync(st->us, &msg);
if (ret) {
dev_err(&st->us->dev,
"problem when reading 16 bit register 0x%02X",
lower_reg_address);
goto error_ret;
}
*val = (st->rx[0] << 8) | st->rx[1];
error_ret:
mutex_unlock(&st->buf_lock);
return ret;
}
#include "../imu/adis.h"
static ssize_t adis16240_spi_read_signed(struct device *dev,
struct device_attribute *attr,
......@@ -153,18 +32,19 @@ static ssize_t adis16240_spi_read_signed(struct device *dev,
unsigned bits)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct adis *st = iio_priv(indio_dev);
int ret;
s16 val = 0;
unsigned shift = 16 - bits;
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
ret = adis16240_spi_read_reg_16(indio_dev,
ret = adis_read_reg_16(st,
this_attr->address, (u16 *)&val);
if (ret)
return ret;
if (val & ADIS16240_ERROR_ACTIVE)
adis16240_check_status(indio_dev);
adis_check_status(st);
val = ((s16)(val << shift) >> shift);
return sprintf(buf, "%d\n", val);
......@@ -185,152 +65,16 @@ static ssize_t adis16240_read_12bit_signed(struct device *dev,
return ret;
}
static int adis16240_reset(struct iio_dev *indio_dev)
{
int ret;
ret = adis16240_spi_write_reg_8(indio_dev,
ADIS16240_GLOB_CMD,
ADIS16240_GLOB_CMD_SW_RESET);
if (ret)
dev_err(&indio_dev->dev, "problem resetting device");
return ret;
}
int adis16240_set_irq(struct iio_dev *indio_dev, bool enable)
{
int ret = 0;
u16 msc;
ret = adis16240_spi_read_reg_16(indio_dev,
ADIS16240_MSC_CTRL, &msc);
if (ret)
goto error_ret;
msc |= ADIS16240_MSC_CTRL_ACTIVE_HIGH;
msc &= ~ADIS16240_MSC_CTRL_DATA_RDY_DIO2;
if (enable)
msc |= ADIS16240_MSC_CTRL_DATA_RDY_EN;
else
msc &= ~ADIS16240_MSC_CTRL_DATA_RDY_EN;
ret = adis16240_spi_write_reg_16(indio_dev,
ADIS16240_MSC_CTRL, msc);
error_ret:
return ret;
}
static int adis16240_self_test(struct iio_dev *indio_dev)
{
int ret;
ret = adis16240_spi_write_reg_16(indio_dev,
ADIS16240_MSC_CTRL,
ADIS16240_MSC_CTRL_SELF_TEST_EN);
if (ret) {
dev_err(&indio_dev->dev, "problem starting self test");
goto err_ret;
}
msleep(ADIS16240_STARTUP_DELAY);
adis16240_check_status(indio_dev);
err_ret:
return ret;
}
static int adis16240_check_status(struct iio_dev *indio_dev)
{
u16 status;
int ret;
struct device *dev = &indio_dev->dev;
ret = adis16240_spi_read_reg_16(indio_dev,
ADIS16240_DIAG_STAT, &status);
if (ret < 0) {
dev_err(dev, "Reading status failed\n");
goto error_ret;
}
ret = status & 0x2F;
if (status & ADIS16240_DIAG_STAT_PWRON_FAIL)
dev_err(dev, "Power-on, self-test fail\n");
if (status & ADIS16240_DIAG_STAT_SPI_FAIL)
dev_err(dev, "SPI failure\n");
if (status & ADIS16240_DIAG_STAT_FLASH_UPT)
dev_err(dev, "Flash update failed\n");
if (status & ADIS16240_DIAG_STAT_POWER_HIGH)
dev_err(dev, "Power supply above 3.625V\n");
if (status & ADIS16240_DIAG_STAT_POWER_LOW)
dev_err(dev, "Power supply below 2.225V\n");
error_ret:
return ret;
}
static int adis16240_initial_setup(struct iio_dev *indio_dev)
{
int ret;
struct device *dev = &indio_dev->dev;
/* Disable IRQ */
ret = adis16240_set_irq(indio_dev, false);
if (ret) {
dev_err(dev, "disable irq failed");
goto err_ret;
}
/* Do self test */
ret = adis16240_self_test(indio_dev);
if (ret) {
dev_err(dev, "self test failure");
goto err_ret;
}
/* Read status register to check the result */
ret = adis16240_check_status(indio_dev);
if (ret) {
adis16240_reset(indio_dev);
dev_err(dev, "device not playing ball -> reset");
msleep(ADIS16240_STARTUP_DELAY);
ret = adis16240_check_status(indio_dev);
if (ret) {
dev_err(dev, "giving up");
goto err_ret;
}
}
err_ret:
return ret;
}
static IIO_DEVICE_ATTR(in_accel_xyz_squared_peak_raw, S_IRUGO,
adis16240_read_12bit_signed, NULL,
ADIS16240_XYZPEAK_OUT);
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("4096");
enum adis16240_chan {
in_supply,
in_aux,
accel_x,
accel_y,
accel_z,
temp,
};
static const u8 adis16240_addresses[6][3] = {
[in_supply] = { ADIS16240_SUPPLY_OUT },
[in_aux] = { ADIS16240_AUX_ADC },
[accel_x] = { ADIS16240_XACCL_OUT, ADIS16240_XACCL_OFF,
ADIS16240_XPEAK_OUT },
[accel_y] = { ADIS16240_YACCL_OUT, ADIS16240_YACCL_OFF,
ADIS16240_YPEAK_OUT },
[accel_z] = { ADIS16240_ZACCL_OUT, ADIS16240_ZACCL_OFF,
ADIS16240_ZPEAK_OUT },
[temp] = { ADIS16240_TEMP_OUT },
static const u8 adis16240_addresses[][2] = {
[ADIS16240_SCAN_ACC_X] = { ADIS16240_XACCL_OFF, ADIS16240_XPEAK_OUT },
[ADIS16240_SCAN_ACC_Y] = { ADIS16240_YACCL_OFF, ADIS16240_YPEAK_OUT },
[ADIS16240_SCAN_ACC_Z] = { ADIS16240_ZACCL_OFF, ADIS16240_ZPEAK_OUT },
};
static int adis16240_read_raw(struct iio_dev *indio_dev,
......@@ -338,6 +82,7 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
int *val, int *val2,
long mask)
{
struct adis *st = iio_priv(indio_dev);
int ret;
int bits;
u8 addr;
......@@ -345,29 +90,8 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
addr = adis16240_addresses[chan->address][0];
ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16);
if (ret) {
mutex_unlock(&indio_dev->mlock);
return ret;
}
if (val16 & ADIS16240_ERROR_ACTIVE) {
ret = adis16240_check_status(indio_dev);
if (ret) {
mutex_unlock(&indio_dev->mlock);
return ret;
}
}
val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
if (chan->scan_type.sign == 's')
val16 = (s16)(val16 <<
(16 - chan->scan_type.realbits)) >>
(16 - chan->scan_type.realbits);
*val = val16;
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
return adis_single_conversion(indio_dev, chan,
ADIS16240_ERROR_ACTIVE, val);
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
......@@ -400,8 +124,8 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_CALIBBIAS:
bits = 10;
mutex_lock(&indio_dev->mlock);
addr = adis16240_addresses[chan->address][1];
ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16);
addr = adis16240_addresses[chan->scan_index][0];
ret = adis_read_reg_16(st, addr, &val16);
if (ret) {
mutex_unlock(&indio_dev->mlock);
return ret;
......@@ -414,8 +138,8 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_PEAK:
bits = 10;
mutex_lock(&indio_dev->mlock);
addr = adis16240_addresses[chan->address][2];
ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16);
addr = adis16240_addresses[chan->scan_index][1];
ret = adis_read_reg_16(st, addr, &val16);
if (ret) {
mutex_unlock(&indio_dev->mlock);
return ret;
......@@ -435,104 +159,32 @@ static int adis16240_write_raw(struct iio_dev *indio_dev,
int val2,
long mask)
{
struct adis *st = iio_priv(indio_dev);
int bits = 10;
s16 val16;
u8 addr;
switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS:
val16 = val & ((1 << bits) - 1);
addr = adis16240_addresses[chan->address][1];
return adis16240_spi_write_reg_16(indio_dev, addr, val16);
addr = adis16240_addresses[chan->scan_index][0];
return adis_write_reg_16(st, addr, val16);
}
return -EINVAL;
}
static const struct iio_chan_spec adis16240_channels[] = {
{
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
.extend_name = "supply",
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in_supply,
.scan_index = ADIS16240_SCAN_SUPPLY,
.scan_type = {
.sign = 'u',
.realbits = 10,
.storagebits = 16,
},
}, {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.address = in_aux,
.scan_index = ADIS16240_SCAN_AUX_ADC,
.scan_type = {
.sign = 'u',
.realbits = 10,
.storagebits = 16,
},
}, {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_X,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 10),
ADIS_AUX_ADC_CHAN(ADIS16240_AUX_ADC, ADIS16240_SCAN_AUX_ADC, 10),
ADIS_ACCEL_CHAN(X, ADIS16240_XACCL_OUT, ADIS16240_SCAN_ACC_X,
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
.address = accel_x,
.scan_index = ADIS16240_SCAN_ACC_X,
.scan_type = {
.sign = 's',
.realbits = 10,
.storagebits = 16,
},
}, {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 10),
ADIS_ACCEL_CHAN(Y, ADIS16240_YACCL_OUT, ADIS16240_SCAN_ACC_Y,
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
.address = accel_y,
.scan_index = ADIS16240_SCAN_ACC_Y,
.scan_type = {
.sign = 's',
.realbits = 10,
.storagebits = 16,
},
}, {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 10),
ADIS_ACCEL_CHAN(Z, ADIS16240_ZACCL_OUT, ADIS16240_SCAN_ACC_Z,
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
.address = accel_z,
.scan_index = ADIS16240_SCAN_ACC_Z,
.scan_type = {
.sign = 's',
.realbits = 10,
.storagebits = 16,
},
}, {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = temp,
.scan_index = ADIS16240_SCAN_TEMP,
.scan_type = {
.sign = 'u',
.realbits = 10,
.storagebits = 16,
},
},
IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 10),
ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 10),
IIO_CHAN_SOFT_TIMESTAMP(6)
};
......@@ -553,10 +205,36 @@ static const struct iio_info adis16240_info = {
.driver_module = THIS_MODULE,
};
static const char * const adis16240_status_error_msgs[] = {
[ADIS16240_DIAG_STAT_PWRON_FAIL_BIT] = "Power on, self-test failed",
[ADIS16240_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
[ADIS16240_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
[ADIS16240_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
[ADIS16240_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.225V",
};
static const struct adis_data adis16240_data = {
.write_delay = 35,
.read_delay = 35,
.msc_ctrl_reg = ADIS16240_MSC_CTRL,
.glob_cmd_reg = ADIS16240_GLOB_CMD,
.diag_stat_reg = ADIS16240_DIAG_STAT,
.self_test_mask = ADIS16240_MSC_CTRL_SELF_TEST_EN,
.startup_delay = ADIS16240_STARTUP_DELAY,
.status_error_msgs = adis16240_status_error_msgs,
.status_error_mask = BIT(ADIS16240_DIAG_STAT_PWRON_FAIL_BIT) |
BIT(ADIS16240_DIAG_STAT_SPI_FAIL_BIT) |
BIT(ADIS16240_DIAG_STAT_FLASH_UPT_BIT) |
BIT(ADIS16240_DIAG_STAT_POWER_HIGH_BIT) |
BIT(ADIS16240_DIAG_STAT_POWER_LOW_BIT),
};
static int __devinit adis16240_probe(struct spi_device *spi)
{
int ret;
struct adis16240_state *st;
struct adis *st;
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
......@@ -569,9 +247,6 @@ static int __devinit adis16240_probe(struct spi_device *spi)
/* this is only used for removal purposes */
spi_set_drvdata(spi, indio_dev);
st->us = spi;
mutex_init(&st->buf_lock);
indio_dev->name = spi->dev.driver->name;
indio_dev->dev.parent = &spi->dev;
indio_dev->info = &adis16240_info;
......@@ -579,39 +254,24 @@ static int __devinit adis16240_probe(struct spi_device *spi)
indio_dev->num_channels = ARRAY_SIZE(adis16240_channels);
indio_dev->modes = INDIO_DIRECT_MODE;
ret = adis16240_configure_ring(indio_dev);
ret = adis_init(st, indio_dev, spi, &adis16240_data);
if (ret)
goto error_free_dev;
ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL);
if (ret)
goto error_free_dev;
ret = iio_buffer_register(indio_dev,
adis16240_channels,
ARRAY_SIZE(adis16240_channels));
if (ret) {
printk(KERN_ERR "failed to initialize the ring\n");
goto error_unreg_ring_funcs;
}
if (spi->irq) {
ret = adis16240_probe_trigger(indio_dev);
if (ret)
goto error_uninitialize_ring;
}
/* Get the device into a sane initial state */
ret = adis16240_initial_setup(indio_dev);
ret = adis_initial_startup(st);
if (ret)
goto error_remove_trigger;
goto error_cleanup_buffer_trigger;
ret = iio_device_register(indio_dev);
if (ret)
goto error_remove_trigger;
goto error_cleanup_buffer_trigger;
return 0;
error_remove_trigger:
adis16240_remove_trigger(indio_dev);
error_uninitialize_ring:
iio_buffer_unregister(indio_dev);
error_unreg_ring_funcs:
adis16240_unconfigure_ring(indio_dev);
error_cleanup_buffer_trigger:
adis_cleanup_buffer_and_trigger(st, indio_dev);
error_free_dev:
iio_device_free(indio_dev);
error_ret:
......@@ -620,13 +280,11 @@ static int __devinit adis16240_probe(struct spi_device *spi)
static int __devexit adis16240_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct adis *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
adis16240_remove_trigger(indio_dev);
iio_buffer_unregister(indio_dev);
adis16240_unconfigure_ring(indio_dev);
adis_cleanup_buffer_and_trigger(st, indio_dev);
iio_device_free(indio_dev);
return 0;
......
#include <linux/export.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/iio/iio.h>
#include "../ring_sw.h"
#include <linux/iio/trigger_consumer.h>
#include "adis16240.h"
/**
* adis16240_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 adis16240_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
{
struct spi_message msg;
struct adis16240_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[ADIS16240_OUTPUTS + 1];
int ret;
int i;
mutex_lock(&st->buf_lock);
spi_message_init(&msg);
memset(xfers, 0, sizeof(xfers));
for (i = 0; i <= ADIS16240_OUTPUTS; i++) {
xfers[i].bits_per_word = 8;
xfers[i].cs_change = 1;
xfers[i].len = 2;
xfers[i].delay_usecs = 30;
xfers[i].tx_buf = st->tx + 2 * i;
st->tx[2 * i]
= ADIS16240_READ_REG(ADIS16240_SUPPLY_OUT + 2 * i);
st->tx[2 * i + 1] = 0;
if (i >= 1)
xfers[i].rx_buf = rx + 2 * (i - 1);
spi_message_add_tail(&xfers[i], &msg);
}
ret = spi_sync(st->us, &msg);
if (ret)
dev_err(&st->us->dev, "problem when burst reading");
mutex_unlock(&st->buf_lock);
return ret;
}
static irqreturn_t adis16240_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct adis16240_state *st = iio_priv(indio_dev);
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) &&
adis16240_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 adis16240_unconfigure_ring(struct iio_dev *indio_dev)
{
iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_sw_rb_free(indio_dev->buffer);
}
static const struct iio_buffer_setup_ops adis16240_ring_setup_ops = {
.preenable = &iio_sw_buffer_preenable,
.postenable = &iio_triggered_buffer_postenable,
.predisable = &iio_triggered_buffer_predisable,
};
int adis16240_configure_ring(struct iio_dev *indio_dev)
{
int ret = 0;
struct iio_buffer *ring;
ring = iio_sw_rb_allocate(indio_dev);
if (!ring) {
ret = -ENOMEM;
return ret;
}
indio_dev->buffer = ring;
ring->scan_timestamp = true;
indio_dev->setup_ops = &adis16240_ring_setup_ops;
indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
&adis16240_trigger_handler,
IRQF_ONESHOT,
indio_dev,
"%s_consumer%d",
indio_dev->name,
indio_dev->id);
if (indio_dev->pollfunc == NULL) {
ret = -ENOMEM;
goto error_iio_sw_rb_free;
}
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
return 0;
error_iio_sw_rb_free:
iio_sw_rb_free(indio_dev->buffer);
return ret;
}
#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 "adis16240.h"
/**
* adis16240_data_rdy_trigger_set_state() set datardy interrupt state
**/
static int adis16240_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
struct iio_dev *indio_dev = trig->private_data;
dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
return adis16240_set_irq(indio_dev, state);
}
static const struct iio_trigger_ops adis16240_trigger_ops = {
.owner = THIS_MODULE,
.set_trigger_state = &adis16240_data_rdy_trigger_set_state,
};
int adis16240_probe_trigger(struct iio_dev *indio_dev)
{
int ret;
struct adis16240_state *st = iio_priv(indio_dev);
st->trig = iio_trigger_alloc("adis16240-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,
"adis16240",
st->trig);
if (ret)
goto error_free_trig;
st->trig->dev.parent = &st->us->dev;
st->trig->ops = &adis16240_trigger_ops;
st->trig->private_data = indio_dev;
ret = iio_trigger_register(st->trig);
/* select default trigger */
indio_dev->trig = st->trig;
if (ret)
goto error_free_irq;
return 0;
error_free_irq:
free_irq(st->us->irq, st->trig);
error_free_trig:
iio_trigger_free(st->trig);
error_ret:
return ret;
}
void adis16240_remove_trigger(struct iio_dev *indio_dev)
{
struct adis16240_state *st = iio_priv(indio_dev);
iio_trigger_unregister(st->trig);
free_irq(st->us->irq, st->trig);
iio_trigger_free(st->trig);
}
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