aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio/imu
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2013-01-16 07:48:00 -0500
committerJonathan Cameron <jic23@kernel.org>2013-01-26 05:07:50 -0500
commitd6b09bd85d57752395c6407bd8a9b32eb7b279ff (patch)
tree0ad920d6cd805a5e3a357bb678fcd0a1678fc9ea /drivers/iio/imu
parentf4c6d64bcf5b4bd868c53c6943d9b9bdd65eaa48 (diff)
staging:iio: Move adis16400 out of staging
This adis16400 driver is in pretty good shape now, so move it out of staging. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio/imu')
-rw-r--r--drivers/iio/imu/Kconfig11
-rw-r--r--drivers/iio/imu/Makefile3
-rw-r--r--drivers/iio/imu/adis16400.h204
-rw-r--r--drivers/iio/imu/adis16400_buffer.c96
-rw-r--r--drivers/iio/imu/adis16400_core.c812
5 files changed, 1126 insertions, 0 deletions
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index 3d79a40e916b..47f66ed9c4ef 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -3,6 +3,17 @@
3# 3#
4menu "Inertial measurement units" 4menu "Inertial measurement units"
5 5
6config ADIS16400
7 tristate "Analog Devices ADIS16400 and similar IMU SPI driver"
8 depends on SPI
9 select IIO_ADIS_LIB
10 select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
11 help
12 Say yes here to build support for Analog Devices adis16300, adis16344,
13 adis16350, adis16354, adis16355, adis16360, adis16362, adis16364,
14 adis16365, adis16400 and adis16405 triaxial inertial sensors
15 (adis16400 series also have magnetometers).
16
6config ADIS16480 17config ADIS16480
7 tristate "Analog Devices ADIS16480 and similar IMU driver" 18 tristate "Analog Devices ADIS16480 and similar IMU driver"
8 depends on SPI 19 depends on SPI
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
index cfe57638f6f9..019b717c5ff1 100644
--- a/drivers/iio/imu/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -2,6 +2,9 @@
2# Makefile for Inertial Measurement Units 2# Makefile for Inertial Measurement Units
3# 3#
4 4
5adis16400-y := adis16400_core.o
6adis16400-$(CONFIG_IIO_BUFFER) += adis16400_buffer.o
7obj-$(CONFIG_ADIS16400) += adis16400.o
5obj-$(CONFIG_ADIS16480) += adis16480.o 8obj-$(CONFIG_ADIS16480) += adis16480.o
6 9
7adis_lib-y += adis.o 10adis_lib-y += adis.o
diff --git a/drivers/iio/imu/adis16400.h b/drivers/iio/imu/adis16400.h
new file mode 100644
index 000000000000..a3b9e56c5bd1
--- /dev/null
+++ b/drivers/iio/imu/adis16400.h
@@ -0,0 +1,204 @@
1/*
2 * adis16400.h support Analog Devices ADIS16400
3 * 3d 18g accelerometers,
4 * 3d gyroscopes,
5 * 3d 2.5gauss magnetometers via SPI
6 *
7 * Copyright (c) 2009 Manuel Stahl <manuel.stahl@iis.fraunhofer.de>
8 * Copyright (c) 2007 Jonathan Cameron <jic23@kernel.org>
9 *
10 * Loosely based upon lis3l02dq.h
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 */
16
17#ifndef SPI_ADIS16400_H_
18#define SPI_ADIS16400_H_
19
20#include <linux/iio/imu/adis.h>
21
22#define ADIS16400_STARTUP_DELAY 290 /* ms */
23#define ADIS16400_MTEST_DELAY 90 /* ms */
24
25#define ADIS16400_FLASH_CNT 0x00 /* Flash memory write count */
26#define ADIS16400_SUPPLY_OUT 0x02 /* Power supply measurement */
27#define ADIS16400_XGYRO_OUT 0x04 /* X-axis gyroscope output */
28#define ADIS16400_YGYRO_OUT 0x06 /* Y-axis gyroscope output */
29#define ADIS16400_ZGYRO_OUT 0x08 /* Z-axis gyroscope output */
30#define ADIS16400_XACCL_OUT 0x0A /* X-axis accelerometer output */
31#define ADIS16400_YACCL_OUT 0x0C /* Y-axis accelerometer output */
32#define ADIS16400_ZACCL_OUT 0x0E /* Z-axis accelerometer output */
33#define ADIS16400_XMAGN_OUT 0x10 /* X-axis magnetometer measurement */
34#define ADIS16400_YMAGN_OUT 0x12 /* Y-axis magnetometer measurement */
35#define ADIS16400_ZMAGN_OUT 0x14 /* Z-axis magnetometer measurement */
36#define ADIS16400_TEMP_OUT 0x16 /* Temperature output */
37#define ADIS16400_AUX_ADC 0x18 /* Auxiliary ADC measurement */
38
39#define ADIS16350_XTEMP_OUT 0x10 /* X-axis gyroscope temperature measurement */
40#define ADIS16350_YTEMP_OUT 0x12 /* Y-axis gyroscope temperature measurement */
41#define ADIS16350_ZTEMP_OUT 0x14 /* Z-axis gyroscope temperature measurement */
42
43#define ADIS16300_PITCH_OUT 0x12 /* X axis inclinometer output measurement */
44#define ADIS16300_ROLL_OUT 0x14 /* Y axis inclinometer output measurement */
45#define ADIS16300_AUX_ADC 0x16 /* Auxiliary ADC measurement */
46
47/* Calibration parameters */
48#define ADIS16400_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */
49#define ADIS16400_YGYRO_OFF 0x1C /* Y-axis gyroscope bias offset factor */
50#define ADIS16400_ZGYRO_OFF 0x1E /* Z-axis gyroscope bias offset factor */
51#define ADIS16400_XACCL_OFF 0x20 /* X-axis acceleration bias offset factor */
52#define ADIS16400_YACCL_OFF 0x22 /* Y-axis acceleration bias offset factor */
53#define ADIS16400_ZACCL_OFF 0x24 /* Z-axis acceleration bias offset factor */
54#define ADIS16400_XMAGN_HIF 0x26 /* X-axis magnetometer, hard-iron factor */
55#define ADIS16400_YMAGN_HIF 0x28 /* Y-axis magnetometer, hard-iron factor */
56#define ADIS16400_ZMAGN_HIF 0x2A /* Z-axis magnetometer, hard-iron factor */
57#define ADIS16400_XMAGN_SIF 0x2C /* X-axis magnetometer, soft-iron factor */
58#define ADIS16400_YMAGN_SIF 0x2E /* Y-axis magnetometer, soft-iron factor */
59#define ADIS16400_ZMAGN_SIF 0x30 /* Z-axis magnetometer, soft-iron factor */
60
61#define ADIS16400_GPIO_CTRL 0x32 /* Auxiliary digital input/output control */
62#define ADIS16400_MSC_CTRL 0x34 /* Miscellaneous control */
63#define ADIS16400_SMPL_PRD 0x36 /* Internal sample period (rate) control */
64#define ADIS16400_SENS_AVG 0x38 /* Dynamic range and digital filter control */
65#define ADIS16400_SLP_CNT 0x3A /* Sleep mode control */
66#define ADIS16400_DIAG_STAT 0x3C /* System status */
67
68/* Alarm functions */
69#define ADIS16400_GLOB_CMD 0x3E /* System command */
70#define ADIS16400_ALM_MAG1 0x40 /* Alarm 1 amplitude threshold */
71#define ADIS16400_ALM_MAG2 0x42 /* Alarm 2 amplitude threshold */
72#define ADIS16400_ALM_SMPL1 0x44 /* Alarm 1 sample size */
73#define ADIS16400_ALM_SMPL2 0x46 /* Alarm 2 sample size */
74#define ADIS16400_ALM_CTRL 0x48 /* Alarm control */
75#define ADIS16400_AUX_DAC 0x4A /* Auxiliary DAC data */
76
77#define ADIS16400_PRODUCT_ID 0x56 /* Product identifier */
78
79#define ADIS16400_ERROR_ACTIVE (1<<14)
80#define ADIS16400_NEW_DATA (1<<14)
81
82/* MSC_CTRL */
83#define ADIS16400_MSC_CTRL_MEM_TEST (1<<11)
84#define ADIS16400_MSC_CTRL_INT_SELF_TEST (1<<10)
85#define ADIS16400_MSC_CTRL_NEG_SELF_TEST (1<<9)
86#define ADIS16400_MSC_CTRL_POS_SELF_TEST (1<<8)
87#define ADIS16400_MSC_CTRL_GYRO_BIAS (1<<7)
88#define ADIS16400_MSC_CTRL_ACCL_ALIGN (1<<6)
89#define ADIS16400_MSC_CTRL_DATA_RDY_EN (1<<2)
90#define ADIS16400_MSC_CTRL_DATA_RDY_POL_HIGH (1<<1)
91#define ADIS16400_MSC_CTRL_DATA_RDY_DIO2 (1<<0)
92
93/* SMPL_PRD */
94#define ADIS16400_SMPL_PRD_TIME_BASE (1<<7)
95#define ADIS16400_SMPL_PRD_DIV_MASK 0x7F
96
97/* DIAG_STAT */
98#define ADIS16400_DIAG_STAT_ZACCL_FAIL 15
99#define ADIS16400_DIAG_STAT_YACCL_FAIL 14
100#define ADIS16400_DIAG_STAT_XACCL_FAIL 13
101#define ADIS16400_DIAG_STAT_XGYRO_FAIL 12
102#define ADIS16400_DIAG_STAT_YGYRO_FAIL 11
103#define ADIS16400_DIAG_STAT_ZGYRO_FAIL 10
104#define ADIS16400_DIAG_STAT_ALARM2 9
105#define ADIS16400_DIAG_STAT_ALARM1 8
106#define ADIS16400_DIAG_STAT_FLASH_CHK 6
107#define ADIS16400_DIAG_STAT_SELF_TEST 5
108#define ADIS16400_DIAG_STAT_OVERFLOW 4
109#define ADIS16400_DIAG_STAT_SPI_FAIL 3
110#define ADIS16400_DIAG_STAT_FLASH_UPT 2
111#define ADIS16400_DIAG_STAT_POWER_HIGH 1
112#define ADIS16400_DIAG_STAT_POWER_LOW 0
113
114/* GLOB_CMD */
115#define ADIS16400_GLOB_CMD_SW_RESET (1<<7)
116#define ADIS16400_GLOB_CMD_P_AUTO_NULL (1<<4)
117#define ADIS16400_GLOB_CMD_FLASH_UPD (1<<3)
118#define ADIS16400_GLOB_CMD_DAC_LATCH (1<<2)
119#define ADIS16400_GLOB_CMD_FAC_CALIB (1<<1)
120#define ADIS16400_GLOB_CMD_AUTO_NULL (1<<0)
121
122/* SLP_CNT */
123#define ADIS16400_SLP_CNT_POWER_OFF (1<<8)
124
125#define ADIS16334_RATE_DIV_SHIFT 8
126#define ADIS16334_RATE_INT_CLK BIT(0)
127
128#define ADIS16400_SPI_SLOW (u32)(300 * 1000)
129#define ADIS16400_SPI_BURST (u32)(1000 * 1000)
130#define ADIS16400_SPI_FAST (u32)(2000 * 1000)
131
132#define ADIS16400_HAS_PROD_ID BIT(0)
133#define ADIS16400_NO_BURST BIT(1)
134#define ADIS16400_HAS_SLOW_MODE BIT(2)
135
136struct adis16400_state;
137
138struct adis16400_chip_info {
139 const struct iio_chan_spec *channels;
140 const int num_channels;
141 const long flags;
142 unsigned int gyro_scale_micro;
143 unsigned int accel_scale_micro;
144 int temp_scale_nano;
145 int temp_offset;
146 int (*set_freq)(struct adis16400_state *st, unsigned int freq);
147 int (*get_freq)(struct adis16400_state *st);
148};
149
150/**
151 * struct adis16400_state - device instance specific data
152 * @variant: chip variant info
153 * @filt_int: integer part of requested filter frequency
154 * @adis: adis device
155 **/
156struct adis16400_state {
157 struct adis16400_chip_info *variant;
158 int filt_int;
159
160 struct adis adis;
161};
162
163/* At the moment triggers are only used for ring buffer
164 * filling. This may change!
165 */
166
167enum {
168 ADIS16400_SCAN_SUPPLY,
169 ADIS16400_SCAN_GYRO_X,
170 ADIS16400_SCAN_GYRO_Y,
171 ADIS16400_SCAN_GYRO_Z,
172 ADIS16400_SCAN_ACC_X,
173 ADIS16400_SCAN_ACC_Y,
174 ADIS16400_SCAN_ACC_Z,
175 ADIS16400_SCAN_MAGN_X,
176 ADIS16400_SCAN_MAGN_Y,
177 ADIS16400_SCAN_MAGN_Z,
178 ADIS16350_SCAN_TEMP_X,
179 ADIS16350_SCAN_TEMP_Y,
180 ADIS16350_SCAN_TEMP_Z,
181 ADIS16300_SCAN_INCLI_X,
182 ADIS16300_SCAN_INCLI_Y,
183 ADIS16400_SCAN_ADC,
184};
185
186#ifdef CONFIG_IIO_BUFFER
187
188ssize_t adis16400_read_data_from_ring(struct device *dev,
189 struct device_attribute *attr,
190 char *buf);
191
192
193int adis16400_update_scan_mode(struct iio_dev *indio_dev,
194 const unsigned long *scan_mask);
195irqreturn_t adis16400_trigger_handler(int irq, void *p);
196
197#else /* CONFIG_IIO_BUFFER */
198
199#define adis16400_update_scan_mode NULL
200#define adis16400_trigger_handler NULL
201
202#endif /* CONFIG_IIO_BUFFER */
203
204#endif /* SPI_ADIS16400_H_ */
diff --git a/drivers/iio/imu/adis16400_buffer.c b/drivers/iio/imu/adis16400_buffer.c
new file mode 100644
index 000000000000..054c01d6e73c
--- /dev/null
+++ b/drivers/iio/imu/adis16400_buffer.c
@@ -0,0 +1,96 @@
1#include <linux/interrupt.h>
2#include <linux/mutex.h>
3#include <linux/kernel.h>
4#include <linux/spi/spi.h>
5#include <linux/slab.h>
6#include <linux/bitops.h>
7#include <linux/export.h>
8
9#include <linux/iio/iio.h>
10#include <linux/iio/buffer.h>
11#include <linux/iio/triggered_buffer.h>
12#include <linux/iio/trigger_consumer.h>
13
14#include "adis16400.h"
15
16int adis16400_update_scan_mode(struct iio_dev *indio_dev,
17 const unsigned long *scan_mask)
18{
19 struct adis16400_state *st = iio_priv(indio_dev);
20 struct adis *adis = &st->adis;
21 uint16_t *tx, *rx;
22
23 if (st->variant->flags & ADIS16400_NO_BURST)
24 return adis_update_scan_mode(indio_dev, scan_mask);
25
26 kfree(adis->xfer);
27 kfree(adis->buffer);
28
29 adis->xfer = kcalloc(2, sizeof(*adis->xfer), GFP_KERNEL);
30 if (!adis->xfer)
31 return -ENOMEM;
32
33 adis->buffer = kzalloc(indio_dev->scan_bytes + sizeof(u16),
34 GFP_KERNEL);
35 if (!adis->buffer)
36 return -ENOMEM;
37
38 rx = adis->buffer;
39 tx = adis->buffer + indio_dev->scan_bytes;
40
41 tx[0] = ADIS_READ_REG(ADIS16400_GLOB_CMD);
42 tx[1] = 0;
43
44 adis->xfer[0].tx_buf = tx;
45 adis->xfer[0].bits_per_word = 8;
46 adis->xfer[0].len = 2;
47 adis->xfer[1].tx_buf = tx;
48 adis->xfer[1].bits_per_word = 8;
49 adis->xfer[1].len = indio_dev->scan_bytes;
50
51 spi_message_init(&adis->msg);
52 spi_message_add_tail(&adis->xfer[0], &adis->msg);
53 spi_message_add_tail(&adis->xfer[1], &adis->msg);
54
55 return 0;
56}
57
58irqreturn_t adis16400_trigger_handler(int irq, void *p)
59{
60 struct iio_poll_func *pf = p;
61 struct iio_dev *indio_dev = pf->indio_dev;
62 struct adis16400_state *st = iio_priv(indio_dev);
63 struct adis *adis = &st->adis;
64 u32 old_speed_hz = st->adis.spi->max_speed_hz;
65 int ret;
66
67 if (!adis->buffer)
68 return -ENOMEM;
69
70 if (!(st->variant->flags & ADIS16400_NO_BURST) &&
71 st->adis.spi->max_speed_hz > ADIS16400_SPI_BURST) {
72 st->adis.spi->max_speed_hz = ADIS16400_SPI_BURST;
73 spi_setup(st->adis.spi);
74 }
75
76 ret = spi_sync(adis->spi, &adis->msg);
77 if (ret)
78 dev_err(&adis->spi->dev, "Failed to read data: %d\n", ret);
79
80 if (!(st->variant->flags & ADIS16400_NO_BURST)) {
81 st->adis.spi->max_speed_hz = old_speed_hz;
82 spi_setup(st->adis.spi);
83 }
84
85 /* Guaranteed to be aligned with 8 byte boundary */
86 if (indio_dev->scan_timestamp) {
87 void *b = adis->buffer + indio_dev->scan_bytes - sizeof(s64);
88 *(s64 *)b = pf->timestamp;
89 }
90
91 iio_push_to_buffers(indio_dev, adis->buffer);
92
93 iio_trigger_notify_done(indio_dev->trig);
94
95 return IRQ_HANDLED;
96}
diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c
new file mode 100644
index 000000000000..1bbe5eed0139
--- /dev/null
+++ b/drivers/iio/imu/adis16400_core.c
@@ -0,0 +1,812 @@
1/*
2 * adis16400.c support Analog Devices ADIS16400/5
3 * 3d 2g Linear Accelerometers,
4 * 3d Gyroscopes,
5 * 3d Magnetometers via SPI
6 *
7 * Copyright (c) 2009 Manuel Stahl <manuel.stahl@iis.fraunhofer.de>
8 * Copyright (c) 2007 Jonathan Cameron <jic23@kernel.org>
9 * Copyright (c) 2011 Analog Devices Inc.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 */
16
17#include <linux/interrupt.h>
18#include <linux/irq.h>
19#include <linux/delay.h>
20#include <linux/mutex.h>
21#include <linux/device.h>
22#include <linux/kernel.h>
23#include <linux/spi/spi.h>
24#include <linux/slab.h>
25#include <linux/sysfs.h>
26#include <linux/list.h>
27#include <linux/module.h>
28
29#include <linux/iio/iio.h>
30#include <linux/iio/sysfs.h>
31#include <linux/iio/buffer.h>
32
33#include "adis16400.h"
34
35enum adis16400_chip_variant {
36 ADIS16300,
37 ADIS16334,
38 ADIS16350,
39 ADIS16360,
40 ADIS16362,
41 ADIS16364,
42 ADIS16400,
43};
44
45static int adis16334_get_freq(struct adis16400_state *st)
46{
47 int ret;
48 uint16_t t;
49
50 ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t);
51 if (ret < 0)
52 return ret;
53
54 t >>= ADIS16334_RATE_DIV_SHIFT;
55
56 return (8192 >> t) / 10;
57}
58
59static int adis16334_set_freq(struct adis16400_state *st, unsigned int freq)
60{
61 unsigned int t;
62
63 freq *= 10;
64 if (freq < 8192)
65 t = ilog2(8192 / freq);
66 else
67 t = 0;
68
69 if (t > 0x31)
70 t = 0x31;
71
72 t <<= ADIS16334_RATE_DIV_SHIFT;
73 t |= ADIS16334_RATE_INT_CLK;
74
75 return adis_write_reg_16(&st->adis, ADIS16400_SMPL_PRD, t);
76}
77
78static int adis16400_get_freq(struct adis16400_state *st)
79{
80 int sps, ret;
81 uint16_t t;
82
83 ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t);
84 if (ret < 0)
85 return ret;
86
87 sps = (t & ADIS16400_SMPL_PRD_TIME_BASE) ? 53 : 1638;
88 sps /= (t & ADIS16400_SMPL_PRD_DIV_MASK) + 1;
89
90 return sps;
91}
92
93static int adis16400_set_freq(struct adis16400_state *st, unsigned int freq)
94{
95 unsigned int t;
96
97 t = 1638 / freq;
98 if (t > 0)
99 t--;
100 t &= ADIS16400_SMPL_PRD_DIV_MASK;
101
102 if ((t & ADIS16400_SMPL_PRD_DIV_MASK) >= 0x0A)
103 st->adis.spi->max_speed_hz = ADIS16400_SPI_SLOW;
104 else
105 st->adis.spi->max_speed_hz = ADIS16400_SPI_FAST;
106
107 return adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, t);
108}
109
110static ssize_t adis16400_read_frequency(struct device *dev,
111 struct device_attribute *attr,
112 char *buf)
113{
114 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
115 struct adis16400_state *st = iio_priv(indio_dev);
116 int ret;
117
118 ret = st->variant->get_freq(st);
119 if (ret < 0)
120 return ret;
121
122 return sprintf(buf, "%d\n", ret);
123}
124
125static const unsigned adis16400_3db_divisors[] = {
126 [0] = 2, /* Special case */
127 [1] = 6,
128 [2] = 12,
129 [3] = 25,
130 [4] = 50,
131 [5] = 100,
132 [6] = 200,
133 [7] = 200, /* Not a valid setting */
134};
135
136static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val)
137{
138 struct adis16400_state *st = iio_priv(indio_dev);
139 uint16_t val16;
140 int i, ret;
141
142 for (i = ARRAY_SIZE(adis16400_3db_divisors) - 1; i >= 1; i--) {
143 if (sps / adis16400_3db_divisors[i] >= val)
144 break;
145 }
146
147 ret = adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, &val16);
148 if (ret < 0)
149 return ret;
150
151 ret = adis_write_reg_16(&st->adis, ADIS16400_SENS_AVG,
152 (val16 & ~0x07) | i);
153 return ret;
154}
155
156static ssize_t adis16400_write_frequency(struct device *dev,
157 struct device_attribute *attr, const char *buf, size_t len)
158{
159 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
160 struct adis16400_state *st = iio_priv(indio_dev);
161 long val;
162 int ret;
163
164 ret = kstrtol(buf, 10, &val);
165 if (ret)
166 return ret;
167
168 if (val == 0)
169 return -EINVAL;
170
171 mutex_lock(&indio_dev->mlock);
172 st->variant->set_freq(st, val);
173 mutex_unlock(&indio_dev->mlock);
174
175 return ret ? ret : len;
176}
177
178/* Power down the device */
179static int adis16400_stop_device(struct iio_dev *indio_dev)
180{
181 struct adis16400_state *st = iio_priv(indio_dev);
182 int ret;
183
184 ret = adis_write_reg_16(&st->adis, ADIS16400_SLP_CNT,
185 ADIS16400_SLP_CNT_POWER_OFF);
186 if (ret)
187 dev_err(&indio_dev->dev,
188 "problem with turning device off: SLP_CNT");
189
190 return ret;
191}
192
193static int adis16400_initial_setup(struct iio_dev *indio_dev)
194{
195 struct adis16400_state *st = iio_priv(indio_dev);
196 uint16_t prod_id, smp_prd;
197 unsigned int device_id;
198 int ret;
199
200 /* use low spi speed for init if the device has a slow mode */
201 if (st->variant->flags & ADIS16400_HAS_SLOW_MODE)
202 st->adis.spi->max_speed_hz = ADIS16400_SPI_SLOW;
203 else
204 st->adis.spi->max_speed_hz = ADIS16400_SPI_FAST;
205 st->adis.spi->mode = SPI_MODE_3;
206 spi_setup(st->adis.spi);
207
208 ret = adis_initial_startup(&st->adis);
209 if (ret)
210 return ret;
211
212 if (st->variant->flags & ADIS16400_HAS_PROD_ID) {
213 ret = adis_read_reg_16(&st->adis,
214 ADIS16400_PRODUCT_ID, &prod_id);
215 if (ret)
216 goto err_ret;
217
218 sscanf(indio_dev->name, "adis%u\n", &device_id);
219
220 if (prod_id != device_id)
221 dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.",
222 device_id, prod_id);
223
224 dev_info(&indio_dev->dev, "%s: prod_id 0x%04x at CS%d (irq %d)\n",
225 indio_dev->name, prod_id,
226 st->adis.spi->chip_select, st->adis.spi->irq);
227 }
228 /* use high spi speed if possible */
229 if (st->variant->flags & ADIS16400_HAS_SLOW_MODE) {
230 ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &smp_prd);
231 if (ret)
232 goto err_ret;
233
234 if ((smp_prd & ADIS16400_SMPL_PRD_DIV_MASK) < 0x0A) {
235 st->adis.spi->max_speed_hz = ADIS16400_SPI_FAST;
236 spi_setup(st->adis.spi);
237 }
238 }
239
240err_ret:
241 return ret;
242}
243
244static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
245 adis16400_read_frequency,
246 adis16400_write_frequency);
247
248static const uint8_t adis16400_addresses[] = {
249 [ADIS16400_SCAN_GYRO_X] = ADIS16400_XGYRO_OFF,
250 [ADIS16400_SCAN_GYRO_Y] = ADIS16400_YGYRO_OFF,
251 [ADIS16400_SCAN_GYRO_Z] = ADIS16400_ZGYRO_OFF,
252 [ADIS16400_SCAN_ACC_X] = ADIS16400_XACCL_OFF,
253 [ADIS16400_SCAN_ACC_Y] = ADIS16400_YACCL_OFF,
254 [ADIS16400_SCAN_ACC_Z] = ADIS16400_ZACCL_OFF,
255};
256
257static int adis16400_write_raw(struct iio_dev *indio_dev,
258 struct iio_chan_spec const *chan, int val, int val2, long info)
259{
260 struct adis16400_state *st = iio_priv(indio_dev);
261 int ret, sps;
262
263 switch (info) {
264 case IIO_CHAN_INFO_CALIBBIAS:
265 mutex_lock(&indio_dev->mlock);
266 ret = adis_write_reg_16(&st->adis,
267 adis16400_addresses[chan->scan_index], val);
268 mutex_unlock(&indio_dev->mlock);
269 return ret;
270 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
271 /*
272 * Need to cache values so we can update if the frequency
273 * changes.
274 */
275 mutex_lock(&indio_dev->mlock);
276 st->filt_int = val;
277 /* Work out update to current value */
278 sps = st->variant->get_freq(st);
279 if (sps < 0) {
280 mutex_unlock(&indio_dev->mlock);
281 return sps;
282 }
283
284 ret = adis16400_set_filter(indio_dev, sps, val);
285 mutex_unlock(&indio_dev->mlock);
286 return ret;
287 default:
288 return -EINVAL;
289 }
290}
291
292static int adis16400_read_raw(struct iio_dev *indio_dev,
293 struct iio_chan_spec const *chan, int *val, int *val2, long info)
294{
295 struct adis16400_state *st = iio_priv(indio_dev);
296 int16_t val16;
297 int ret;
298
299 switch (info) {
300 case IIO_CHAN_INFO_RAW:
301 return adis_single_conversion(indio_dev, chan, 0, val);
302 case IIO_CHAN_INFO_SCALE:
303 switch (chan->type) {
304 case IIO_ANGL_VEL:
305 *val = 0;
306 *val2 = st->variant->gyro_scale_micro;
307 return IIO_VAL_INT_PLUS_MICRO;
308 case IIO_VOLTAGE:
309 *val = 0;
310 if (chan->channel == 0) {
311 *val = 2;
312 *val2 = 418000; /* 2.418 mV */
313 } else {
314 *val = 0;
315 *val2 = 805800; /* 805.8 uV */
316 }
317 return IIO_VAL_INT_PLUS_MICRO;
318 case IIO_ACCEL:
319 *val = 0;
320 *val2 = st->variant->accel_scale_micro;
321 return IIO_VAL_INT_PLUS_MICRO;
322 case IIO_MAGN:
323 *val = 0;
324 *val2 = 500; /* 0.5 mgauss */
325 return IIO_VAL_INT_PLUS_MICRO;
326 case IIO_TEMP:
327 *val = st->variant->temp_scale_nano / 1000000;
328 *val2 = (st->variant->temp_scale_nano % 1000000);
329 return IIO_VAL_INT_PLUS_MICRO;
330 default:
331 return -EINVAL;
332 }
333 case IIO_CHAN_INFO_CALIBBIAS:
334 mutex_lock(&indio_dev->mlock);
335 ret = adis_read_reg_16(&st->adis,
336 adis16400_addresses[chan->scan_index], &val16);
337 mutex_unlock(&indio_dev->mlock);
338 if (ret)
339 return ret;
340 val16 = ((val16 & 0xFFF) << 4) >> 4;
341 *val = val16;
342 return IIO_VAL_INT;
343 case IIO_CHAN_INFO_OFFSET:
344 /* currently only temperature */
345 *val = st->variant->temp_offset;
346 return IIO_VAL_INT;
347 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
348 mutex_lock(&indio_dev->mlock);
349 /* Need both the number of taps and the sampling frequency */
350 ret = adis_read_reg_16(&st->adis,
351 ADIS16400_SENS_AVG,
352 &val16);
353 if (ret < 0) {
354 mutex_unlock(&indio_dev->mlock);
355 return ret;
356 }
357 ret = st->variant->get_freq(st);
358 if (ret >= 0)
359 *val = ret / adis16400_3db_divisors[val16 & 0x07];
360 *val2 = 0;
361 mutex_unlock(&indio_dev->mlock);
362 if (ret < 0)
363 return ret;
364 return IIO_VAL_INT_PLUS_MICRO;
365 default:
366 return -EINVAL;
367 }
368}
369
370#define ADIS16400_VOLTAGE_CHAN(addr, bits, name, si) { \
371 .type = IIO_VOLTAGE, \
372 .indexed = 1, \
373 .channel = 0, \
374 .extend_name = name, \
375 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
376 IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
377 .address = (addr), \
378 .scan_index = (si), \
379 .scan_type = { \
380 .sign = 'u', \
381 .realbits = (bits), \
382 .storagebits = 16, \
383 .shift = 0, \
384 .endianness = IIO_BE, \
385 }, \
386}
387
388#define ADIS16400_SUPPLY_CHAN(addr, bits) \
389 ADIS16400_VOLTAGE_CHAN(addr, bits, "supply", ADIS16400_SCAN_SUPPLY)
390
391#define ADIS16400_AUX_ADC_CHAN(addr, bits) \
392 ADIS16400_VOLTAGE_CHAN(addr, bits, NULL, ADIS16400_SCAN_ADC)
393
394#define ADIS16400_GYRO_CHAN(mod, addr, bits) { \
395 .type = IIO_ANGL_VEL, \
396 .modified = 1, \
397 .channel2 = IIO_MOD_ ## mod, \
398 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
399 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
400 IIO_CHAN_INFO_SCALE_SHARED_BIT | \
401 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, \
402 .address = addr, \
403 .scan_index = ADIS16400_SCAN_GYRO_ ## mod, \
404 .scan_type = { \
405 .sign = 's', \
406 .realbits = (bits), \
407 .storagebits = 16, \
408 .shift = 0, \
409 .endianness = IIO_BE, \
410 }, \
411}
412
413#define ADIS16400_ACCEL_CHAN(mod, addr, bits) { \
414 .type = IIO_ACCEL, \
415 .modified = 1, \
416 .channel2 = IIO_MOD_ ## mod, \
417 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
418 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
419 IIO_CHAN_INFO_SCALE_SHARED_BIT | \
420 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, \
421 .address = (addr), \
422 .scan_index = ADIS16400_SCAN_ACC_ ## mod, \
423 .scan_type = { \
424 .sign = 's', \
425 .realbits = (bits), \
426 .storagebits = 16, \
427 .shift = 0, \
428 .endianness = IIO_BE, \
429 }, \
430}
431
432#define ADIS16400_MAGN_CHAN(mod, addr, bits) { \
433 .type = IIO_MAGN, \
434 .modified = 1, \
435 .channel2 = IIO_MOD_ ## mod, \
436 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
437 IIO_CHAN_INFO_SCALE_SHARED_BIT | \
438 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, \
439 .address = (addr), \
440 .scan_index = ADIS16400_SCAN_MAGN_ ## mod, \
441 .scan_type = { \
442 .sign = 's', \
443 .realbits = (bits), \
444 .storagebits = 16, \
445 .shift = 0, \
446 .endianness = IIO_BE, \
447 }, \
448}
449
450#define ADIS16400_MOD_TEMP_NAME_X "x"
451#define ADIS16400_MOD_TEMP_NAME_Y "y"
452#define ADIS16400_MOD_TEMP_NAME_Z "z"
453
454#define ADIS16400_MOD_TEMP_CHAN(mod, addr, bits) { \
455 .type = IIO_TEMP, \
456 .indexed = 1, \
457 .channel = 0, \
458 .extend_name = ADIS16400_MOD_TEMP_NAME_ ## mod, \
459 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
460 IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \
461 IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
462 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, \
463 .address = (addr), \
464 .scan_index = ADIS16350_SCAN_TEMP_ ## mod, \
465 .scan_type = { \
466 .sign = 's', \
467 .realbits = (bits), \
468 .storagebits = 16, \
469 .shift = 0, \
470 .endianness = IIO_BE, \
471 }, \
472}
473
474#define ADIS16400_TEMP_CHAN(addr, bits) { \
475 .type = IIO_TEMP, \
476 .indexed = 1, \
477 .channel = 0, \
478 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
479 IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \
480 IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
481 .address = (addr), \
482 .scan_index = ADIS16350_SCAN_TEMP_X, \
483 .scan_type = { \
484 .sign = 's', \
485 .realbits = (bits), \
486 .storagebits = 16, \
487 .shift = 0, \
488 .endianness = IIO_BE, \
489 }, \
490}
491
492#define ADIS16400_INCLI_CHAN(mod, addr, bits) { \
493 .type = IIO_INCLI, \
494 .modified = 1, \
495 .channel2 = IIO_MOD_ ## mod, \
496 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
497 IIO_CHAN_INFO_SCALE_SHARED_BIT, \
498 .address = (addr), \
499 .scan_index = ADIS16300_SCAN_INCLI_ ## mod, \
500 .scan_type = { \
501 .sign = 's', \
502 .realbits = (bits), \
503 .storagebits = 16, \
504 .shift = 0, \
505 .endianness = IIO_BE, \
506 }, \
507}
508
509static const struct iio_chan_spec adis16400_channels[] = {
510 ADIS16400_SUPPLY_CHAN(ADIS16400_SUPPLY_OUT, 14),
511 ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 14),
512 ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 14),
513 ADIS16400_GYRO_CHAN(Z, ADIS16400_ZGYRO_OUT, 14),
514 ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 14),
515 ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 14),
516 ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 14),
517 ADIS16400_MAGN_CHAN(X, ADIS16400_XMAGN_OUT, 14),
518 ADIS16400_MAGN_CHAN(Y, ADIS16400_YMAGN_OUT, 14),
519 ADIS16400_MAGN_CHAN(Z, ADIS16400_ZMAGN_OUT, 14),
520 ADIS16400_TEMP_CHAN(ADIS16400_TEMP_OUT, 12),
521 ADIS16400_AUX_ADC_CHAN(ADIS16400_AUX_ADC, 12),
522 IIO_CHAN_SOFT_TIMESTAMP(12)
523};
524
525static const struct iio_chan_spec adis16350_channels[] = {
526 ADIS16400_SUPPLY_CHAN(ADIS16400_SUPPLY_OUT, 12),
527 ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 14),
528 ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 14),
529 ADIS16400_GYRO_CHAN(Z, ADIS16400_ZGYRO_OUT, 14),
530 ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 14),
531 ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 14),
532 ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 14),
533 ADIS16400_MAGN_CHAN(X, ADIS16400_XMAGN_OUT, 14),
534 ADIS16400_MAGN_CHAN(Y, ADIS16400_YMAGN_OUT, 14),
535 ADIS16400_MAGN_CHAN(Z, ADIS16400_ZMAGN_OUT, 14),
536 ADIS16400_AUX_ADC_CHAN(ADIS16300_AUX_ADC, 12),
537 ADIS16400_MOD_TEMP_CHAN(X, ADIS16350_XTEMP_OUT, 12),
538 ADIS16400_MOD_TEMP_CHAN(Y, ADIS16350_YTEMP_OUT, 12),
539 ADIS16400_MOD_TEMP_CHAN(Z, ADIS16350_ZTEMP_OUT, 12),
540 IIO_CHAN_SOFT_TIMESTAMP(11)
541};
542
543static const struct iio_chan_spec adis16300_channels[] = {
544 ADIS16400_SUPPLY_CHAN(ADIS16400_SUPPLY_OUT, 12),
545 ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 14),
546 ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 14),
547 ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 14),
548 ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 14),
549 ADIS16400_TEMP_CHAN(ADIS16350_XTEMP_OUT, 12),
550 ADIS16400_AUX_ADC_CHAN(ADIS16300_AUX_ADC, 12),
551 ADIS16400_INCLI_CHAN(X, ADIS16300_PITCH_OUT, 13),
552 ADIS16400_INCLI_CHAN(Y, ADIS16300_ROLL_OUT, 13),
553 IIO_CHAN_SOFT_TIMESTAMP(14)
554};
555
556static const struct iio_chan_spec adis16334_channels[] = {
557 ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 14),
558 ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 14),
559 ADIS16400_GYRO_CHAN(Z, ADIS16400_ZGYRO_OUT, 14),
560 ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 14),
561 ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 14),
562 ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 14),
563 ADIS16400_TEMP_CHAN(ADIS16350_XTEMP_OUT, 12),
564 IIO_CHAN_SOFT_TIMESTAMP(8)
565};
566
567static struct attribute *adis16400_attributes[] = {
568 &iio_dev_attr_sampling_frequency.dev_attr.attr,
569 NULL
570};
571
572static const struct attribute_group adis16400_attribute_group = {
573 .attrs = adis16400_attributes,
574};
575
576static struct adis16400_chip_info adis16400_chips[] = {
577 [ADIS16300] = {
578 .channels = adis16300_channels,
579 .num_channels = ARRAY_SIZE(adis16300_channels),
580 .flags = ADIS16400_HAS_SLOW_MODE,
581 .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
582 .accel_scale_micro = 5884,
583 .temp_scale_nano = 140000000, /* 0.14 C */
584 .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
585 .set_freq = adis16400_set_freq,
586 .get_freq = adis16400_get_freq,
587 },
588 [ADIS16334] = {
589 .channels = adis16334_channels,
590 .num_channels = ARRAY_SIZE(adis16334_channels),
591 .flags = ADIS16400_HAS_PROD_ID,
592 .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
593 .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
594 .temp_scale_nano = 67850000, /* 0.06785 C */
595 .temp_offset = 25000000 / 67850, /* 25 C = 0x00 */
596 .set_freq = adis16334_set_freq,
597 .get_freq = adis16334_get_freq,
598 },
599 [ADIS16350] = {
600 .channels = adis16350_channels,
601 .num_channels = ARRAY_SIZE(adis16350_channels),
602 .gyro_scale_micro = IIO_DEGREE_TO_RAD(73260), /* 0.07326 deg/s */
603 .accel_scale_micro = IIO_G_TO_M_S_2(2522), /* 0.002522 g */
604 .temp_scale_nano = 145300000, /* 0.1453 C */
605 .temp_offset = 25000000 / 145300, /* 25 C = 0x00 */
606 .flags = ADIS16400_NO_BURST | ADIS16400_HAS_SLOW_MODE,
607 .set_freq = adis16400_set_freq,
608 .get_freq = adis16400_get_freq,
609 },
610 [ADIS16360] = {
611 .channels = adis16350_channels,
612 .num_channels = ARRAY_SIZE(adis16350_channels),
613 .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
614 .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
615 .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
616 .temp_scale_nano = 136000000, /* 0.136 C */
617 .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
618 .set_freq = adis16400_set_freq,
619 .get_freq = adis16400_get_freq,
620 },
621 [ADIS16362] = {
622 .channels = adis16350_channels,
623 .num_channels = ARRAY_SIZE(adis16350_channels),
624 .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
625 .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
626 .accel_scale_micro = IIO_G_TO_M_S_2(333), /* 0.333 mg */
627 .temp_scale_nano = 136000000, /* 0.136 C */
628 .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
629 .set_freq = adis16400_set_freq,
630 .get_freq = adis16400_get_freq,
631 },
632 [ADIS16364] = {
633 .channels = adis16350_channels,
634 .num_channels = ARRAY_SIZE(adis16350_channels),
635 .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
636 .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
637 .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
638 .temp_scale_nano = 136000000, /* 0.136 C */
639 .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
640 .set_freq = adis16400_set_freq,
641 .get_freq = adis16400_get_freq,
642 },
643 [ADIS16400] = {
644 .channels = adis16400_channels,
645 .num_channels = ARRAY_SIZE(adis16400_channels),
646 .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
647 .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
648 .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
649 .temp_scale_nano = 140000000, /* 0.14 C */
650 .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
651 .set_freq = adis16400_set_freq,
652 .get_freq = adis16400_get_freq,
653 }
654};
655
656static const struct iio_info adis16400_info = {
657 .driver_module = THIS_MODULE,
658 .read_raw = &adis16400_read_raw,
659 .write_raw = &adis16400_write_raw,
660 .attrs = &adis16400_attribute_group,
661 .update_scan_mode = adis16400_update_scan_mode,
662};
663
664static const unsigned long adis16400_burst_scan_mask[] = {
665 ~0UL,
666 0,
667};
668
669static const char * const adis16400_status_error_msgs[] = {
670 [ADIS16400_DIAG_STAT_ZACCL_FAIL] = "Z-axis accelerometer self-test failure",
671 [ADIS16400_DIAG_STAT_YACCL_FAIL] = "Y-axis accelerometer self-test failure",
672 [ADIS16400_DIAG_STAT_XACCL_FAIL] = "X-axis accelerometer self-test failure",
673 [ADIS16400_DIAG_STAT_XGYRO_FAIL] = "X-axis gyroscope self-test failure",
674 [ADIS16400_DIAG_STAT_YGYRO_FAIL] = "Y-axis gyroscope self-test failure",
675 [ADIS16400_DIAG_STAT_ZGYRO_FAIL] = "Z-axis gyroscope self-test failure",
676 [ADIS16400_DIAG_STAT_ALARM2] = "Alarm 2 active",
677 [ADIS16400_DIAG_STAT_ALARM1] = "Alarm 1 active",
678 [ADIS16400_DIAG_STAT_FLASH_CHK] = "Flash checksum error",
679 [ADIS16400_DIAG_STAT_SELF_TEST] = "Self test error",
680 [ADIS16400_DIAG_STAT_OVERFLOW] = "Sensor overrange",
681 [ADIS16400_DIAG_STAT_SPI_FAIL] = "SPI failure",
682 [ADIS16400_DIAG_STAT_FLASH_UPT] = "Flash update failed",
683 [ADIS16400_DIAG_STAT_POWER_HIGH] = "Power supply above 5.25V",
684 [ADIS16400_DIAG_STAT_POWER_LOW] = "Power supply below 4.75V",
685};
686
687static const struct adis_data adis16400_data = {
688 .msc_ctrl_reg = ADIS16400_MSC_CTRL,
689 .glob_cmd_reg = ADIS16400_GLOB_CMD,
690 .diag_stat_reg = ADIS16400_DIAG_STAT,
691
692 .read_delay = 50,
693 .write_delay = 50,
694
695 .self_test_mask = ADIS16400_MSC_CTRL_MEM_TEST,
696 .startup_delay = ADIS16400_STARTUP_DELAY,
697
698 .status_error_msgs = adis16400_status_error_msgs,
699 .status_error_mask = BIT(ADIS16400_DIAG_STAT_ZACCL_FAIL) |
700 BIT(ADIS16400_DIAG_STAT_YACCL_FAIL) |
701 BIT(ADIS16400_DIAG_STAT_XACCL_FAIL) |
702 BIT(ADIS16400_DIAG_STAT_XGYRO_FAIL) |
703 BIT(ADIS16400_DIAG_STAT_YGYRO_FAIL) |
704 BIT(ADIS16400_DIAG_STAT_ZGYRO_FAIL) |
705 BIT(ADIS16400_DIAG_STAT_ALARM2) |
706 BIT(ADIS16400_DIAG_STAT_ALARM1) |
707 BIT(ADIS16400_DIAG_STAT_FLASH_CHK) |
708 BIT(ADIS16400_DIAG_STAT_SELF_TEST) |
709 BIT(ADIS16400_DIAG_STAT_OVERFLOW) |
710 BIT(ADIS16400_DIAG_STAT_SPI_FAIL) |
711 BIT(ADIS16400_DIAG_STAT_FLASH_UPT) |
712 BIT(ADIS16400_DIAG_STAT_POWER_HIGH) |
713 BIT(ADIS16400_DIAG_STAT_POWER_LOW),
714};
715
716static int adis16400_probe(struct spi_device *spi)
717{
718 struct adis16400_state *st;
719 struct iio_dev *indio_dev;
720 int ret;
721
722 indio_dev = iio_device_alloc(sizeof(*st));
723 if (indio_dev == NULL)
724 return -ENOMEM;
725
726 st = iio_priv(indio_dev);
727 /* this is only used for removal purposes */
728 spi_set_drvdata(spi, indio_dev);
729
730 /* setup the industrialio driver allocated elements */
731 st->variant = &adis16400_chips[spi_get_device_id(spi)->driver_data];
732 indio_dev->dev.parent = &spi->dev;
733 indio_dev->name = spi_get_device_id(spi)->name;
734 indio_dev->channels = st->variant->channels;
735 indio_dev->num_channels = st->variant->num_channels;
736 indio_dev->info = &adis16400_info;
737 indio_dev->modes = INDIO_DIRECT_MODE;
738
739 if (!(st->variant->flags & ADIS16400_NO_BURST))
740 indio_dev->available_scan_masks = adis16400_burst_scan_mask;
741
742 ret = adis_init(&st->adis, indio_dev, spi, &adis16400_data);
743 if (ret)
744 goto error_free_dev;
745
746 ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev,
747 adis16400_trigger_handler);
748 if (ret)
749 goto error_free_dev;
750
751 /* Get the device into a sane initial state */
752 ret = adis16400_initial_setup(indio_dev);
753 if (ret)
754 goto error_cleanup_buffer;
755 ret = iio_device_register(indio_dev);
756 if (ret)
757 goto error_cleanup_buffer;
758
759 return 0;
760
761error_cleanup_buffer:
762 adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
763error_free_dev:
764 iio_device_free(indio_dev);
765 return ret;
766}
767
768static int adis16400_remove(struct spi_device *spi)
769{
770 struct iio_dev *indio_dev = spi_get_drvdata(spi);
771 struct adis16400_state *st = iio_priv(indio_dev);
772
773 iio_device_unregister(indio_dev);
774 adis16400_stop_device(indio_dev);
775
776 adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
777
778 iio_device_free(indio_dev);
779
780 return 0;
781}
782
783static const struct spi_device_id adis16400_id[] = {
784 {"adis16300", ADIS16300},
785 {"adis16334", ADIS16334},
786 {"adis16350", ADIS16350},
787 {"adis16354", ADIS16350},
788 {"adis16355", ADIS16350},
789 {"adis16360", ADIS16360},
790 {"adis16362", ADIS16362},
791 {"adis16364", ADIS16364},
792 {"adis16365", ADIS16360},
793 {"adis16400", ADIS16400},
794 {"adis16405", ADIS16400},
795 {}
796};
797MODULE_DEVICE_TABLE(spi, adis16400_id);
798
799static struct spi_driver adis16400_driver = {
800 .driver = {
801 .name = "adis16400",
802 .owner = THIS_MODULE,
803 },
804 .id_table = adis16400_id,
805 .probe = adis16400_probe,
806 .remove = adis16400_remove,
807};
808module_spi_driver(adis16400_driver);
809
810MODULE_AUTHOR("Manuel Stahl <manuel.stahl@iis.fraunhofer.de>");
811MODULE_DESCRIPTION("Analog Devices ADIS16400/5 IMU SPI driver");
812MODULE_LICENSE("GPL v2");