提交 cd888a17 编写于 作者: L Lars-Peter Clausen 提交者: Jonathan Cameron

staging:iio:adis16400: Use adis library

Use the new adis library for the adis16400 driver. This allows us to completely
scrap the adis16400 trigger code and more than half of the core driver code. For
now we can not make use of the generic adis buffer implementation since the
adis16400 driver has special requirements due to its burst mode support. But
we will eventually get to this.
Signed-off-by: NLars-Peter Clausen <lars@metafoo.de>
Signed-off-by: NJonathan Cameron <jic23@kernel.org>
上级 ca6907df
......@@ -6,8 +6,8 @@ menu "Inertial measurement units"
config ADIS16400
tristate "Analog Devices ADIS16400 and similar IMU SPI driver"
depends on SPI
select IIO_SW_RING if IIO_BUFFER
select IIO_TRIGGER if IIO_BUFFER
select IIO_ADIS_LIB
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say yes here to build support for Analog Devices adis16300, adis16344,
adis16350, adis16354, adis16355, adis16360, adis16362, adis16364,
......
......@@ -3,5 +3,5 @@
#
adis16400-y := adis16400_core.o
adis16400-$(CONFIG_IIO_BUFFER) += adis16400_ring.o adis16400_trigger.o
adis16400-$(CONFIG_IIO_BUFFER) += adis16400_ring.o
obj-$(CONFIG_ADIS16400) += adis16400.o
......@@ -17,12 +17,11 @@
#ifndef SPI_ADIS16400_H_
#define SPI_ADIS16400_H_
#include <linux/iio/imu/adis.h>
#define ADIS16400_STARTUP_DELAY 290 /* ms */
#define ADIS16400_MTEST_DELAY 90 /* ms */
#define ADIS16400_READ_REG(a) a
#define ADIS16400_WRITE_REG(a) ((a) | 0x80)
#define ADIS16400_FLASH_CNT 0x00 /* Flash memory write count */
#define ADIS16400_SUPPLY_OUT 0x02 /* Power supply measurement */
#define ADIS16400_XGYRO_OUT 0x04 /* X-axis gyroscope output */
......@@ -96,21 +95,21 @@
#define ADIS16400_SMPL_PRD_DIV_MASK 0x7F
/* DIAG_STAT */
#define ADIS16400_DIAG_STAT_ZACCL_FAIL (1<<15)
#define ADIS16400_DIAG_STAT_YACCL_FAIL (1<<14)
#define ADIS16400_DIAG_STAT_XACCL_FAIL (1<<13)
#define ADIS16400_DIAG_STAT_XGYRO_FAIL (1<<12)
#define ADIS16400_DIAG_STAT_YGYRO_FAIL (1<<11)
#define ADIS16400_DIAG_STAT_ZGYRO_FAIL (1<<10)
#define ADIS16400_DIAG_STAT_ALARM2 (1<<9)
#define ADIS16400_DIAG_STAT_ALARM1 (1<<8)
#define ADIS16400_DIAG_STAT_FLASH_CHK (1<<6)
#define ADIS16400_DIAG_STAT_SELF_TEST (1<<5)
#define ADIS16400_DIAG_STAT_OVERFLOW (1<<4)
#define ADIS16400_DIAG_STAT_SPI_FAIL (1<<3)
#define ADIS16400_DIAG_STAT_FLASH_UPT (1<<2)
#define ADIS16400_DIAG_STAT_POWER_HIGH (1<<1)
#define ADIS16400_DIAG_STAT_POWER_LOW (1<<0)
#define ADIS16400_DIAG_STAT_ZACCL_FAIL 15
#define ADIS16400_DIAG_STAT_YACCL_FAIL 14
#define ADIS16400_DIAG_STAT_XACCL_FAIL 13
#define ADIS16400_DIAG_STAT_XGYRO_FAIL 12
#define ADIS16400_DIAG_STAT_YGYRO_FAIL 11
#define ADIS16400_DIAG_STAT_ZGYRO_FAIL 10
#define ADIS16400_DIAG_STAT_ALARM2 9
#define ADIS16400_DIAG_STAT_ALARM1 8
#define ADIS16400_DIAG_STAT_FLASH_CHK 6
#define ADIS16400_DIAG_STAT_SELF_TEST 5
#define ADIS16400_DIAG_STAT_OVERFLOW 4
#define ADIS16400_DIAG_STAT_SPI_FAIL 3
#define ADIS16400_DIAG_STAT_FLASH_UPT 2
#define ADIS16400_DIAG_STAT_POWER_HIGH 1
#define ADIS16400_DIAG_STAT_POWER_LOW 0
/* GLOB_CMD */
#define ADIS16400_GLOB_CMD_SW_RESET (1<<7)
......@@ -126,9 +125,6 @@
#define ADIS16334_RATE_DIV_SHIFT 8
#define ADIS16334_RATE_INT_CLK BIT(0)
#define ADIS16400_MAX_TX 24
#define ADIS16400_MAX_RX 24
#define ADIS16400_SPI_SLOW (u32)(300 * 1000)
#define ADIS16400_SPI_BURST (u32)(1000 * 1000)
#define ADIS16400_SPI_FAST (u32)(2000 * 1000)
......@@ -137,6 +133,8 @@
#define ADIS16400_NO_BURST BIT(1)
#define ADIS16400_HAS_SLOW_MODE BIT(2)
struct adis16400_state;
struct adis16400_chip_info {
const struct iio_chan_spec *channels;
const int num_channels;
......@@ -145,58 +143,47 @@ struct adis16400_chip_info {
unsigned int accel_scale_micro;
int temp_scale_nano;
int temp_offset;
int (*set_freq)(struct iio_dev *indio_dev, unsigned int freq);
int (*get_freq)(struct iio_dev *indio_dev);
int (*set_freq)(struct adis16400_state *st, unsigned int freq);
int (*get_freq)(struct adis16400_state *st);
};
/**
* struct adis16400_state - device instance specific data
* @us: actual spi_device
* @trig: data ready trigger registered with iio
* @tx: transmit buffer
* @rx: receive buffer
* @buf_lock: mutex to protect tx and rx
* @filt_int: integer part of requested filter frequency
* @variant: chip variant info
* @filt_int: integer part of requested filter frequency
* @adis: adis device
**/
struct adis16400_state {
struct spi_device *us;
struct iio_trigger *trig;
struct mutex buf_lock;
struct adis16400_chip_info *variant;
int filt_int;
u8 tx[ADIS16400_MAX_TX] ____cacheline_aligned;
u8 rx[ADIS16400_MAX_RX] ____cacheline_aligned;
struct adis adis;
};
int adis16400_set_irq(struct iio_dev *indio_dev, bool enable);
/* At the moment triggers are only used for ring buffer
* filling. This may change!
*/
#define ADIS16400_SCAN_SUPPLY 0
#define ADIS16400_SCAN_GYRO_X 1
#define ADIS16400_SCAN_GYRO_Y 2
#define ADIS16400_SCAN_GYRO_Z 3
#define ADIS16400_SCAN_ACC_X 4
#define ADIS16400_SCAN_ACC_Y 5
#define ADIS16400_SCAN_ACC_Z 6
#define ADIS16400_SCAN_MAGN_X 7
#define ADIS16350_SCAN_TEMP_X 7
#define ADIS16400_SCAN_MAGN_Y 8
#define ADIS16350_SCAN_TEMP_Y 8
#define ADIS16400_SCAN_MAGN_Z 9
#define ADIS16350_SCAN_TEMP_Z 9
#define ADIS16400_SCAN_TEMP 10
#define ADIS16350_SCAN_ADC_0 10
#define ADIS16400_SCAN_ADC_0 11
#define ADIS16300_SCAN_INCLI_X 12
#define ADIS16300_SCAN_INCLI_Y 13
enum {
ADIS16400_SCAN_SUPPLY,
ADIS16400_SCAN_GYRO_X,
ADIS16400_SCAN_GYRO_Y,
ADIS16400_SCAN_GYRO_Z,
ADIS16400_SCAN_ACC_X,
ADIS16400_SCAN_ACC_Y,
ADIS16400_SCAN_ACC_Z,
ADIS16400_SCAN_MAGN_X,
ADIS16400_SCAN_MAGN_Y,
ADIS16400_SCAN_MAGN_Z,
ADIS16350_SCAN_TEMP_X,
ADIS16350_SCAN_TEMP_Y,
ADIS16350_SCAN_TEMP_Z,
ADIS16300_SCAN_INCLI_X,
ADIS16300_SCAN_INCLI_Y,
ADIS16400_SCAN_ADC,
};
#ifdef CONFIG_IIO_BUFFER
void adis16400_remove_trigger(struct iio_dev *indio_dev);
int adis16400_probe_trigger(struct iio_dev *indio_dev);
ssize_t adis16400_read_data_from_ring(struct device *dev,
struct device_attribute *attr,
......@@ -208,15 +195,6 @@ void adis16400_unconfigure_ring(struct iio_dev *indio_dev);
#else /* CONFIG_IIO_BUFFER */
static inline void adis16400_remove_trigger(struct iio_dev *indio_dev)
{
}
static inline int adis16400_probe_trigger(struct iio_dev *indio_dev)
{
return 0;
}
static inline ssize_t
adis16400_read_data_from_ring(struct device *dev,
struct device_attribute *attr,
......@@ -235,4 +213,5 @@ static inline void adis16400_unconfigure_ring(struct iio_dev *indio_dev)
}
#endif /* CONFIG_IIO_BUFFER */
#endif /* SPI_ADIS16400_H_ */
......@@ -9,6 +9,7 @@
#include <linux/iio/iio.h>
#include "../ring_sw.h"
#include <linux/iio/trigger_consumer.h>
#include "adis16400.h"
/**
......@@ -20,12 +21,12 @@ static int adis16400_spi_read_burst(struct iio_dev *indio_dev, u8 *rx)
{
struct spi_message msg;
struct adis16400_state *st = iio_priv(indio_dev);
u32 old_speed_hz = st->us->max_speed_hz;
u32 old_speed_hz = st->adis.spi->max_speed_hz;
int ret;
struct spi_transfer xfers[] = {
{
.tx_buf = st->tx,
.tx_buf = st->adis.tx,
.bits_per_word = 8,
.len = 2,
}, {
......@@ -35,39 +36,39 @@ static int adis16400_spi_read_burst(struct iio_dev *indio_dev, u8 *rx)
},
};
mutex_lock(&st->buf_lock);
st->tx[0] = ADIS16400_READ_REG(ADIS16400_GLOB_CMD);
st->tx[1] = 0;
mutex_lock(&st->adis.txrx_lock);
st->adis.tx[0] = ADIS_READ_REG(ADIS16400_GLOB_CMD);
st->adis.tx[1] = 0;
spi_message_init(&msg);
spi_message_add_tail(&xfers[0], &msg);
spi_message_add_tail(&xfers[1], &msg);
st->us->max_speed_hz = min(ADIS16400_SPI_BURST, old_speed_hz);
spi_setup(st->us);
st->adis.spi->max_speed_hz = min(ADIS16400_SPI_BURST, old_speed_hz);
spi_setup(st->adis.spi);
ret = spi_sync(st->us, &msg);
ret = spi_sync(st->adis.spi, &msg);
if (ret)
dev_err(&st->us->dev, "problem when burst reading");
dev_err(&st->adis.spi->dev, "problem when burst reading");
st->us->max_speed_hz = old_speed_hz;
spi_setup(st->us);
mutex_unlock(&st->buf_lock);
st->adis.spi->max_speed_hz = old_speed_hz;
spi_setup(st->adis.spi);
mutex_unlock(&st->adis.txrx_lock);
return ret;
}
static const u16 read_all_tx_array[] = {
cpu_to_be16(ADIS16400_READ_REG(ADIS16400_SUPPLY_OUT)),
cpu_to_be16(ADIS16400_READ_REG(ADIS16400_XGYRO_OUT)),
cpu_to_be16(ADIS16400_READ_REG(ADIS16400_YGYRO_OUT)),
cpu_to_be16(ADIS16400_READ_REG(ADIS16400_ZGYRO_OUT)),
cpu_to_be16(ADIS16400_READ_REG(ADIS16400_XACCL_OUT)),
cpu_to_be16(ADIS16400_READ_REG(ADIS16400_YACCL_OUT)),
cpu_to_be16(ADIS16400_READ_REG(ADIS16400_ZACCL_OUT)),
cpu_to_be16(ADIS16400_READ_REG(ADIS16350_XTEMP_OUT)),
cpu_to_be16(ADIS16400_READ_REG(ADIS16350_YTEMP_OUT)),
cpu_to_be16(ADIS16400_READ_REG(ADIS16350_ZTEMP_OUT)),
cpu_to_be16(ADIS16400_READ_REG(ADIS16400_AUX_ADC)),
cpu_to_be16(ADIS_READ_REG(ADIS16400_SUPPLY_OUT)),
cpu_to_be16(ADIS_READ_REG(ADIS16400_XGYRO_OUT)),
cpu_to_be16(ADIS_READ_REG(ADIS16400_YGYRO_OUT)),
cpu_to_be16(ADIS_READ_REG(ADIS16400_ZGYRO_OUT)),
cpu_to_be16(ADIS_READ_REG(ADIS16400_XACCL_OUT)),
cpu_to_be16(ADIS_READ_REG(ADIS16400_YACCL_OUT)),
cpu_to_be16(ADIS_READ_REG(ADIS16400_ZACCL_OUT)),
cpu_to_be16(ADIS_READ_REG(ADIS16350_XTEMP_OUT)),
cpu_to_be16(ADIS_READ_REG(ADIS16350_YTEMP_OUT)),
cpu_to_be16(ADIS_READ_REG(ADIS16350_ZTEMP_OUT)),
cpu_to_be16(ADIS_READ_REG(ADIS16400_AUX_ADC)),
};
static int adis16350_spi_read_all(struct iio_dev *indio_dev, u8 *rx)
......@@ -100,7 +101,7 @@ static int adis16350_spi_read_all(struct iio_dev *indio_dev, u8 *rx)
for (j = 0; j < scan_count + 1; j++)
spi_message_add_tail(&xfers[j], &msg);
ret = spi_sync(st->us, &msg);
ret = spi_sync(st->adis.spi, &msg);
kfree(xfers);
return ret;
......@@ -123,26 +124,26 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
indio_dev->masklength);
data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
dev_err(&st->adis.spi->dev, "memory alloc failed in ring bh");
goto done;
}
if (scan_count) {
if (st->variant->flags & ADIS16400_NO_BURST) {
ret = adis16350_spi_read_all(indio_dev, st->rx);
ret = adis16350_spi_read_all(indio_dev, st->adis.rx);
if (ret < 0)
goto done;
for (; i < scan_count; i++)
data[i] = *(s16 *)(st->rx + i*2);
data[i] = *(s16 *)(st->adis.rx + i*2);
} else {
ret = adis16400_spi_read_burst(indio_dev, st->rx);
ret = adis16400_spi_read_burst(indio_dev, st->adis.rx);
if (ret < 0)
goto done;
for (; i < scan_count; i++) {
j = __ffs(mask);
mask &= ~(1 << j);
data[i] = be16_to_cpup(
(__be16 *)&(st->rx[j*2]));
(__be16 *)&(st->adis.rx[j*2]));
}
}
}
......
#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 "adis16400.h"
/**
* adis16400_data_rdy_trigger_set_state() set datardy interrupt state
**/
static int adis16400_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
struct iio_dev *indio_dev = trig->private_data;
dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
return adis16400_set_irq(indio_dev, state);
}
static const struct iio_trigger_ops adis16400_trigger_ops = {
.owner = THIS_MODULE,
.set_trigger_state = &adis16400_data_rdy_trigger_set_state,
};
int adis16400_probe_trigger(struct iio_dev *indio_dev)
{
int ret;
struct adis16400_state *st = iio_priv(indio_dev);
st->trig = iio_trigger_alloc("%s-dev%d",
indio_dev->name,
indio_dev->id);
if (st->trig == NULL) {
ret = -ENOMEM;
goto error_ret;
}
ret = request_irq(st->us->irq,
&iio_trigger_generic_data_rdy_poll,
IRQF_TRIGGER_RISING,
"adis16400",
st->trig);
if (ret)
goto error_free_trig;
st->trig->dev.parent = &st->us->dev;
st->trig->private_data = indio_dev;
st->trig->ops = &adis16400_trigger_ops;
ret = iio_trigger_register(st->trig);
/* select default trigger */
indio_dev->trig = st->trig;
if (ret)
goto error_free_irq;
return 0;
error_free_irq:
free_irq(st->us->irq, st->trig);
error_free_trig:
iio_trigger_free(st->trig);
error_ret:
return ret;
}
void adis16400_remove_trigger(struct iio_dev *indio_dev)
{
struct adis16400_state *st = iio_priv(indio_dev);
iio_trigger_unregister(st->trig);
free_irq(st->us->irq, st->trig);
iio_trigger_free(st->trig);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册