staging:iio:tsl2x7x: Use iio_str_to_fixedpoint instead of open-coding it
[deliverable/linux.git] / drivers / staging / iio / imu / adis16400_core.c
CommitLineData
a9d26f00
BS
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>
0f8c9620 8 * Copyright (c) 2007 Jonathan Cameron <jic23@kernel.org>
6a6ec623 9 * Copyright (c) 2011 Analog Devices Inc.
a9d26f00
BS
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>
a9d26f00
BS
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>
1cb6c1f5 24#include <linux/slab.h>
a9d26f00
BS
25#include <linux/sysfs.h>
26#include <linux/list.h>
99c97852 27#include <linux/module.h>
a9d26f00 28
06458e27
JC
29#include <linux/iio/iio.h>
30#include <linux/iio/sysfs.h>
31#include <linux/iio/buffer.h>
a9d26f00
BS
32#include "adis16400.h"
33
2a29a90b 34enum adis16400_chip_variant {
8e886e65 35 ADIS16300,
85da5059 36 ADIS16334,
2a29a90b
JC
37 ADIS16350,
38 ADIS16360,
39 ADIS16362,
40 ADIS16364,
2a29a90b
JC
41 ADIS16400,
42};
43
a9d26f00
BS
44/**
45 * adis16400_spi_write_reg_8() - write single byte to a register
46 * @dev: device associated with child of actual device (iio_dev or iio_trig)
47 * @reg_address: the address of the register to be written
48 * @val: the value to write
521de518 49 */
e7854845
JC
50static int adis16400_spi_write_reg_8(struct iio_dev *indio_dev,
51 u8 reg_address,
52 u8 val)
a9d26f00
BS
53{
54 int ret;
38d15f06 55 struct adis16400_state *st = iio_priv(indio_dev);
a9d26f00
BS
56
57 mutex_lock(&st->buf_lock);
58 st->tx[0] = ADIS16400_WRITE_REG(reg_address);
59 st->tx[1] = val;
60
61 ret = spi_write(st->us, st->tx, 2);
62 mutex_unlock(&st->buf_lock);
63
64 return ret;
65}
66
67/**
68 * adis16400_spi_write_reg_16() - write 2 bytes to a pair of registers
69 * @dev: device associated with child of actual device (iio_dev or iio_trig)
70 * @reg_address: the address of the lower of the two registers. Second register
71 * is assumed to have address one greater.
72 * @val: value to be written
521de518
JC
73 *
74 * At the moment the spi framework doesn't allow global setting of cs_change.
75 * This means that use cannot be made of spi_write.
76 */
e7854845 77static int adis16400_spi_write_reg_16(struct iio_dev *indio_dev,
a9d26f00
BS
78 u8 lower_reg_address,
79 u16 value)
80{
81 int ret;
82 struct spi_message msg;
38d15f06 83 struct adis16400_state *st = iio_priv(indio_dev);
a9d26f00
BS
84 struct spi_transfer xfers[] = {
85 {
86 .tx_buf = st->tx,
87 .bits_per_word = 8,
88 .len = 2,
89 .cs_change = 1,
90 }, {
91 .tx_buf = st->tx + 2,
92 .bits_per_word = 8,
93 .len = 2,
a9d26f00
BS
94 },
95 };
96
97 mutex_lock(&st->buf_lock);
98 st->tx[0] = ADIS16400_WRITE_REG(lower_reg_address);
99 st->tx[1] = value & 0xFF;
100 st->tx[2] = ADIS16400_WRITE_REG(lower_reg_address + 1);
101 st->tx[3] = (value >> 8) & 0xFF;
102
103 spi_message_init(&msg);
104 spi_message_add_tail(&xfers[0], &msg);
105 spi_message_add_tail(&xfers[1], &msg);
106 ret = spi_sync(st->us, &msg);
107 mutex_unlock(&st->buf_lock);
108
109 return ret;
110}
111
112/**
113 * adis16400_spi_read_reg_16() - read 2 bytes from a 16-bit register
e7854845 114 * @indio_dev: iio device
a9d26f00
BS
115 * @reg_address: the address of the lower of the two registers. Second register
116 * is assumed to have address one greater.
117 * @val: somewhere to pass back the value read
521de518
JC
118 *
119 * At the moment the spi framework doesn't allow global setting of cs_change.
120 * This means that use cannot be made of spi_read.
a9d26f00 121 **/
e7854845 122static int adis16400_spi_read_reg_16(struct iio_dev *indio_dev,
a9d26f00
BS
123 u8 lower_reg_address,
124 u16 *val)
125{
126 struct spi_message msg;
38d15f06 127 struct adis16400_state *st = iio_priv(indio_dev);
a9d26f00
BS
128 int ret;
129 struct spi_transfer xfers[] = {
130 {
131 .tx_buf = st->tx,
132 .bits_per_word = 8,
133 .len = 2,
134 .cs_change = 1,
135 }, {
136 .rx_buf = st->rx,
137 .bits_per_word = 8,
138 .len = 2,
a9d26f00
BS
139 },
140 };
141
142 mutex_lock(&st->buf_lock);
143 st->tx[0] = ADIS16400_READ_REG(lower_reg_address);
144 st->tx[1] = 0;
a9d26f00
BS
145
146 spi_message_init(&msg);
147 spi_message_add_tail(&xfers[0], &msg);
148 spi_message_add_tail(&xfers[1], &msg);
149 ret = spi_sync(st->us, &msg);
150 if (ret) {
151 dev_err(&st->us->dev,
152 "problem when reading 16 bit register 0x%02X",
153 lower_reg_address);
154 goto error_ret;
155 }
156 *val = (st->rx[0] << 8) | st->rx[1];
157
158error_ret:
159 mutex_unlock(&st->buf_lock);
160 return ret;
161}
162
ea2ccb3e 163static int adis16334_get_freq(struct iio_dev *indio_dev)
98c9373d 164{
ea2ccb3e 165 int ret;
98c9373d 166 u16 t;
ea2ccb3e
LPC
167
168 ret = adis16400_spi_read_reg_16(indio_dev, ADIS16400_SMPL_PRD, &t);
169 if (ret < 0)
170 return ret;
171
172 t >>= ADIS16334_RATE_DIV_SHIFT;
173
174 return (8192 >> t) / 10;
175}
176
177static int adis16334_set_freq(struct iio_dev *indio_dev, unsigned int freq)
178{
179 unsigned int t;
180
181 t = ilog2(8192 / (freq * 10));
182
183 if (t > 0x31)
184 t = 0x31;
185
186 t <<= ADIS16334_RATE_DIV_SHIFT;
187 t |= ADIS16334_RATE_INT_CLK;
188
189 return adis16400_spi_write_reg_16(indio_dev, ADIS16400_SMPL_PRD, t);
190}
191
192static int adis16400_get_freq(struct iio_dev *indio_dev)
193{
98c9373d 194 int sps, ret;
ea2ccb3e 195 u16 t;
98c9373d
JC
196
197 ret = adis16400_spi_read_reg_16(indio_dev, ADIS16400_SMPL_PRD, &t);
198 if (ret < 0)
199 return ret;
200 sps = (t & ADIS16400_SMPL_PRD_TIME_BASE) ? 53 : 1638;
201 sps /= (t & ADIS16400_SMPL_PRD_DIV_MASK) + 1;
202
203 return sps;
204}
205
ea2ccb3e
LPC
206static int adis16400_set_freq(struct iio_dev *indio_dev, unsigned int freq)
207{
208 struct adis16400_state *st = iio_priv(indio_dev);
209 unsigned int t;
210
211 t = 1638 / freq;
212 if (t > 0)
213 t--;
214 t &= ADIS16400_SMPL_PRD_DIV_MASK;
215 if ((t & ADIS16400_SMPL_PRD_DIV_MASK) >= 0x0A)
216 st->us->max_speed_hz = ADIS16400_SPI_SLOW;
217 else
218 st->us->max_speed_hz = ADIS16400_SPI_FAST;
219
220 return adis16400_spi_write_reg_8(indio_dev,
221 ADIS16400_SMPL_PRD, t);
222}
223
a9d26f00
BS
224static ssize_t adis16400_read_frequency(struct device *dev,
225 struct device_attribute *attr,
226 char *buf)
227{
dedb1e77 228 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
ea2ccb3e 229 struct adis16400_state *st = iio_priv(indio_dev);
a9d26f00 230 int ret, len = 0;
ea2ccb3e
LPC
231
232 ret = st->variant->get_freq(indio_dev);
98c9373d 233 if (ret < 0)
a9d26f00 234 return ret;
98c9373d 235 len = sprintf(buf, "%d SPS\n", ret);
a9d26f00
BS
236 return len;
237}
238
98c9373d
JC
239static const unsigned adis16400_3db_divisors[] = {
240 [0] = 2, /* Special case */
241 [1] = 5,
242 [2] = 10,
243 [3] = 50,
244 [4] = 200,
245};
246
247static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val)
248{
249 int i, ret;
250 u16 val16;
251 for (i = ARRAY_SIZE(adis16400_3db_divisors) - 1; i >= 0; i--)
252 if (sps/adis16400_3db_divisors[i] > val)
253 break;
254 if (i == -1)
255 ret = -EINVAL;
256 else {
257 ret = adis16400_spi_read_reg_16(indio_dev,
258 ADIS16400_SENS_AVG,
259 &val16);
260 if (ret < 0)
261 goto error_ret;
262
263 ret = adis16400_spi_write_reg_16(indio_dev,
264 ADIS16400_SENS_AVG,
265 (val16 & ~0x03) | i);
266 }
267error_ret:
268 return ret;
269}
270
a9d26f00
BS
271static ssize_t adis16400_write_frequency(struct device *dev,
272 struct device_attribute *attr,
273 const char *buf,
274 size_t len)
275{
dedb1e77 276 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
38d15f06 277 struct adis16400_state *st = iio_priv(indio_dev);
a9d26f00
BS
278 long val;
279 int ret;
a9d26f00
BS
280
281 ret = strict_strtol(buf, 10, &val);
282 if (ret)
283 return ret;
50d4b306
DC
284 if (val == 0)
285 return -EINVAL;
a9d26f00
BS
286
287 mutex_lock(&indio_dev->mlock);
288
ea2ccb3e 289 st->variant->set_freq(indio_dev, val);
a9d26f00 290
98c9373d 291 /* Also update the filter */
a9d26f00
BS
292 mutex_unlock(&indio_dev->mlock);
293
294 return ret ? ret : len;
295}
296
e7854845 297static int adis16400_reset(struct iio_dev *indio_dev)
3fd66da1
BS
298{
299 int ret;
e7854845 300 ret = adis16400_spi_write_reg_8(indio_dev,
3fd66da1
BS
301 ADIS16400_GLOB_CMD,
302 ADIS16400_GLOB_CMD_SW_RESET);
303 if (ret)
e7854845 304 dev_err(&indio_dev->dev, "problem resetting device");
3fd66da1
BS
305
306 return ret;
307}
308
e7854845 309int adis16400_set_irq(struct iio_dev *indio_dev, bool enable)
a9d26f00
BS
310{
311 int ret;
312 u16 msc;
521de518 313
e7854845 314 ret = adis16400_spi_read_reg_16(indio_dev, ADIS16400_MSC_CTRL, &msc);
a9d26f00
BS
315 if (ret)
316 goto error_ret;
317
318 msc |= ADIS16400_MSC_CTRL_DATA_RDY_POL_HIGH;
319 if (enable)
320 msc |= ADIS16400_MSC_CTRL_DATA_RDY_EN;
321 else
322 msc &= ~ADIS16400_MSC_CTRL_DATA_RDY_EN;
323
e7854845 324 ret = adis16400_spi_write_reg_16(indio_dev, ADIS16400_MSC_CTRL, msc);
a9d26f00
BS
325 if (ret)
326 goto error_ret;
327
328error_ret:
329 return ret;
330}
331
a9d26f00 332/* Power down the device */
e7854845 333static int adis16400_stop_device(struct iio_dev *indio_dev)
a9d26f00
BS
334{
335 int ret;
336 u16 val = ADIS16400_SLP_CNT_POWER_OFF;
337
e7854845 338 ret = adis16400_spi_write_reg_16(indio_dev, ADIS16400_SLP_CNT, val);
a9d26f00 339 if (ret)
e7854845
JC
340 dev_err(&indio_dev->dev,
341 "problem with turning device off: SLP_CNT");
a9d26f00
BS
342
343 return ret;
344}
345
e7854845 346static int adis16400_check_status(struct iio_dev *indio_dev)
a9d26f00
BS
347{
348 u16 status;
349 int ret;
e7854845 350 struct device *dev = &indio_dev->dev;
a9d26f00 351
e7854845
JC
352 ret = adis16400_spi_read_reg_16(indio_dev,
353 ADIS16400_DIAG_STAT, &status);
a9d26f00
BS
354
355 if (ret < 0) {
356 dev_err(dev, "Reading status failed\n");
357 goto error_ret;
358 }
359 ret = status;
360 if (status & ADIS16400_DIAG_STAT_ZACCL_FAIL)
361 dev_err(dev, "Z-axis accelerometer self-test failure\n");
362 if (status & ADIS16400_DIAG_STAT_YACCL_FAIL)
363 dev_err(dev, "Y-axis accelerometer self-test failure\n");
364 if (status & ADIS16400_DIAG_STAT_XACCL_FAIL)
365 dev_err(dev, "X-axis accelerometer self-test failure\n");
366 if (status & ADIS16400_DIAG_STAT_XGYRO_FAIL)
367 dev_err(dev, "X-axis gyroscope self-test failure\n");
368 if (status & ADIS16400_DIAG_STAT_YGYRO_FAIL)
369 dev_err(dev, "Y-axis gyroscope self-test failure\n");
370 if (status & ADIS16400_DIAG_STAT_ZGYRO_FAIL)
371 dev_err(dev, "Z-axis gyroscope self-test failure\n");
372 if (status & ADIS16400_DIAG_STAT_ALARM2)
373 dev_err(dev, "Alarm 2 active\n");
374 if (status & ADIS16400_DIAG_STAT_ALARM1)
375 dev_err(dev, "Alarm 1 active\n");
376 if (status & ADIS16400_DIAG_STAT_FLASH_CHK)
377 dev_err(dev, "Flash checksum error\n");
378 if (status & ADIS16400_DIAG_STAT_SELF_TEST)
379 dev_err(dev, "Self test error\n");
380 if (status & ADIS16400_DIAG_STAT_OVERFLOW)
381 dev_err(dev, "Sensor overrange\n");
382 if (status & ADIS16400_DIAG_STAT_SPI_FAIL)
383 dev_err(dev, "SPI failure\n");
384 if (status & ADIS16400_DIAG_STAT_FLASH_UPT)
385 dev_err(dev, "Flash update failed\n");
386 if (status & ADIS16400_DIAG_STAT_POWER_HIGH)
387 dev_err(dev, "Power supply above 5.25V\n");
388 if (status & ADIS16400_DIAG_STAT_POWER_LOW)
389 dev_err(dev, "Power supply below 4.75V\n");
390
391error_ret:
392 return ret;
393}
394
521de518
JC
395static int adis16400_self_test(struct iio_dev *indio_dev)
396{
397 int ret;
398 ret = adis16400_spi_write_reg_16(indio_dev,
399 ADIS16400_MSC_CTRL,
400 ADIS16400_MSC_CTRL_MEM_TEST);
401 if (ret) {
402 dev_err(&indio_dev->dev, "problem starting self test");
403 goto err_ret;
404 }
405
406 msleep(ADIS16400_MTEST_DELAY);
407 adis16400_check_status(indio_dev);
408
409err_ret:
410 return ret;
411}
412
38d15f06 413static int adis16400_initial_setup(struct iio_dev *indio_dev)
a9d26f00
BS
414{
415 int ret;
416 u16 prod_id, smp_prd;
fc8850c0 417 unsigned int device_id;
38d15f06 418 struct adis16400_state *st = iio_priv(indio_dev);
a9d26f00 419
ea2ccb3e
LPC
420 /* use low spi speed for init if the device has a slow mode */
421 if (st->variant->flags & ADIS16400_HAS_SLOW_MODE)
422 st->us->max_speed_hz = ADIS16400_SPI_SLOW;
423 else
424 st->us->max_speed_hz = ADIS16400_SPI_FAST;
a9d26f00
BS
425 st->us->mode = SPI_MODE_3;
426 spi_setup(st->us);
427
38d15f06 428 ret = adis16400_set_irq(indio_dev, false);
a9d26f00 429 if (ret) {
521de518 430 dev_err(&indio_dev->dev, "disable irq failed");
a9d26f00
BS
431 goto err_ret;
432 }
433
38d15f06 434 ret = adis16400_self_test(indio_dev);
3fd66da1 435 if (ret) {
521de518 436 dev_err(&indio_dev->dev, "self test failure");
3fd66da1
BS
437 goto err_ret;
438 }
a9d26f00 439
38d15f06 440 ret = adis16400_check_status(indio_dev);
a9d26f00 441 if (ret) {
38d15f06 442 adis16400_reset(indio_dev);
521de518 443 dev_err(&indio_dev->dev, "device not playing ball -> reset");
a9d26f00 444 msleep(ADIS16400_STARTUP_DELAY);
38d15f06 445 ret = adis16400_check_status(indio_dev);
a9d26f00 446 if (ret) {
521de518 447 dev_err(&indio_dev->dev, "giving up");
a9d26f00
BS
448 goto err_ret;
449 }
450 }
2a29a90b 451 if (st->variant->flags & ADIS16400_HAS_PROD_ID) {
38d15f06 452 ret = adis16400_spi_read_reg_16(indio_dev,
2a29a90b
JC
453 ADIS16400_PRODUCT_ID, &prod_id);
454 if (ret)
455 goto err_ret;
a9d26f00 456
fc8850c0
LPC
457 sscanf(indio_dev->name, "adis%u\n", &device_id);
458
459 if (prod_id != device_id)
460 dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.",
461 device_id, prod_id);
a9d26f00 462
69d80bae 463 dev_info(&indio_dev->dev, "%s: prod_id 0x%04x at CS%d (irq %d)\n",
521de518
JC
464 indio_dev->name, prod_id,
465 st->us->chip_select, st->us->irq);
2a29a90b 466 }
a9d26f00 467 /* use high spi speed if possible */
ea2ccb3e
LPC
468 if (st->variant->flags & ADIS16400_HAS_SLOW_MODE) {
469 ret = adis16400_spi_read_reg_16(indio_dev,
470 ADIS16400_SMPL_PRD, &smp_prd);
471 if (ret)
472 goto err_ret;
473
474 if ((smp_prd & ADIS16400_SMPL_PRD_DIV_MASK) < 0x0A) {
475 st->us->max_speed_hz = ADIS16400_SPI_FAST;
476 spi_setup(st->us);
477 }
a9d26f00
BS
478 }
479
a9d26f00 480err_ret:
a9d26f00
BS
481 return ret;
482}
483
a9d26f00 484static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
521de518
JC
485 adis16400_read_frequency,
486 adis16400_write_frequency);
a9d26f00 487
51a0a5b0 488static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("409 546 819 1638");
a9d26f00 489
e7854845
JC
490enum adis16400_chan {
491 in_supply,
492 gyro_x,
493 gyro_y,
494 gyro_z,
495 accel_x,
496 accel_y,
497 accel_z,
498 magn_x,
499 magn_y,
500 magn_z,
501 temp,
2a29a90b 502 temp0, temp1, temp2,
91ab3fc9 503 in1,
07a8329c 504 in2,
91ab3fc9
JC
505 incli_x,
506 incli_y,
e7854845
JC
507};
508
07a8329c 509static u8 adis16400_addresses[18][2] = {
521de518 510 [in_supply] = { ADIS16400_SUPPLY_OUT },
e7854845
JC
511 [gyro_x] = { ADIS16400_XGYRO_OUT, ADIS16400_XGYRO_OFF },
512 [gyro_y] = { ADIS16400_YGYRO_OUT, ADIS16400_YGYRO_OFF },
513 [gyro_z] = { ADIS16400_ZGYRO_OUT, ADIS16400_ZGYRO_OFF },
514 [accel_x] = { ADIS16400_XACCL_OUT, ADIS16400_XACCL_OFF },
515 [accel_y] = { ADIS16400_YACCL_OUT, ADIS16400_YACCL_OFF },
516 [accel_z] = { ADIS16400_ZACCL_OUT, ADIS16400_ZACCL_OFF },
521de518
JC
517 [magn_x] = { ADIS16400_XMAGN_OUT },
518 [magn_y] = { ADIS16400_YMAGN_OUT },
519 [magn_z] = { ADIS16400_ZMAGN_OUT },
520 [temp] = { ADIS16400_TEMP_OUT },
2a29a90b
JC
521 [temp0] = { ADIS16350_XTEMP_OUT },
522 [temp1] = { ADIS16350_YTEMP_OUT },
523 [temp2] = { ADIS16350_ZTEMP_OUT },
07a8329c
LPC
524 [in1] = { ADIS16300_AUX_ADC },
525 [in2] = { ADIS16400_AUX_ADC },
521de518
JC
526 [incli_x] = { ADIS16300_PITCH_OUT },
527 [incli_y] = { ADIS16300_ROLL_OUT }
e7854845
JC
528};
529
98c9373d 530
e7854845
JC
531static int adis16400_write_raw(struct iio_dev *indio_dev,
532 struct iio_chan_spec const *chan,
533 int val,
534 int val2,
535 long mask)
536{
98c9373d
JC
537 struct adis16400_state *st = iio_priv(indio_dev);
538 int ret, sps;
521de518 539
e7854845 540 switch (mask) {
c8a9f805 541 case IIO_CHAN_INFO_CALIBBIAS:
e7854845
JC
542 mutex_lock(&indio_dev->mlock);
543 ret = adis16400_spi_write_reg_16(indio_dev,
544 adis16400_addresses[chan->address][1],
545 val);
546 mutex_unlock(&indio_dev->mlock);
547 return ret;
98c9373d
JC
548 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
549 /* Need to cache values so we can update if the frequency
550 changes */
551 mutex_lock(&indio_dev->mlock);
552 st->filt_int = val;
553 /* Work out update to current value */
ea2ccb3e 554 sps = st->variant->get_freq(indio_dev);
98c9373d
JC
555 if (sps < 0) {
556 mutex_unlock(&indio_dev->mlock);
557 return sps;
558 }
559
560 ret = adis16400_set_filter(indio_dev, sps, val);
561 mutex_unlock(&indio_dev->mlock);
562 return ret;
e7854845
JC
563 default:
564 return -EINVAL;
565 }
566}
567
568static int adis16400_read_raw(struct iio_dev *indio_dev,
569 struct iio_chan_spec const *chan,
570 int *val,
571 int *val2,
572 long mask)
573{
38d15f06 574 struct adis16400_state *st = iio_priv(indio_dev);
521de518 575 int ret, shift;
e7854845 576 s16 val16;
e7854845
JC
577
578 switch (mask) {
a5d016d4 579 case IIO_CHAN_INFO_RAW:
e7854845
JC
580 mutex_lock(&indio_dev->mlock);
581 ret = adis16400_spi_read_reg_16(indio_dev,
582 adis16400_addresses[chan->address][0],
583 &val16);
584 if (ret) {
585 mutex_unlock(&indio_dev->mlock);
586 return ret;
587 }
588 val16 &= (1 << chan->scan_type.realbits) - 1;
589 if (chan->scan_type.sign == 's') {
590 shift = 16 - chan->scan_type.realbits;
591 val16 = (s16)(val16 << shift) >> shift;
592 }
593 *val = val16;
594 mutex_unlock(&indio_dev->mlock);
595 return IIO_VAL_INT;
c8a9f805 596 case IIO_CHAN_INFO_SCALE:
e7854845 597 switch (chan->type) {
41ea040c 598 case IIO_ANGL_VEL:
e7854845 599 *val = 0;
2a29a90b 600 *val2 = st->variant->gyro_scale_micro;
e7854845 601 return IIO_VAL_INT_PLUS_MICRO;
6835cb6b 602 case IIO_VOLTAGE:
e7854845 603 *val = 0;
1cf8c97f
LPC
604 if (chan->channel == 0) {
605 *val = 2;
606 *val2 = 418000; /* 2.418 mV */
607 } else {
608 *val = 0;
609 *val2 = 805800; /* 805.8 uV */
610 }
e7854845
JC
611 return IIO_VAL_INT_PLUS_MICRO;
612 case IIO_ACCEL:
613 *val = 0;
2a29a90b 614 *val2 = st->variant->accel_scale_micro;
e7854845
JC
615 return IIO_VAL_INT_PLUS_MICRO;
616 case IIO_MAGN:
617 *val = 0;
1cf8c97f 618 *val2 = 500; /* 0.5 mgauss */
e7854845
JC
619 return IIO_VAL_INT_PLUS_MICRO;
620 case IIO_TEMP:
760ebc0d
LPC
621 *val = st->variant->temp_scale_nano / 1000000;
622 *val2 = (st->variant->temp_scale_nano % 1000000);
e7854845
JC
623 return IIO_VAL_INT_PLUS_MICRO;
624 default:
625 return -EINVAL;
626 }
c8a9f805 627 case IIO_CHAN_INFO_CALIBBIAS:
e7854845
JC
628 mutex_lock(&indio_dev->mlock);
629 ret = adis16400_spi_read_reg_16(indio_dev,
630 adis16400_addresses[chan->address][1],
631 &val16);
2a29a90b
JC
632 mutex_unlock(&indio_dev->mlock);
633 if (ret)
e7854845 634 return ret;
e7854845
JC
635 val16 = ((val16 & 0xFFF) << 4) >> 4;
636 *val = val16;
637 return IIO_VAL_INT;
c8a9f805 638 case IIO_CHAN_INFO_OFFSET:
e7854845 639 /* currently only temperature */
760ebc0d 640 *val = st->variant->temp_offset;
1cf8c97f 641 return IIO_VAL_INT;
98c9373d
JC
642 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
643 mutex_lock(&indio_dev->mlock);
644 /* Need both the number of taps and the sampling frequency */
645 ret = adis16400_spi_read_reg_16(indio_dev,
646 ADIS16400_SENS_AVG,
647 &val16);
648 if (ret < 0) {
649 mutex_unlock(&indio_dev->mlock);
650 return ret;
651 }
ea2ccb3e 652 val16 = st->variant->get_freq(indio_dev);
98c9373d
JC
653 if (ret > 0)
654 *val = ret/adis16400_3db_divisors[val16 & 0x03];
655 *val2 = 0;
656 mutex_unlock(&indio_dev->mlock);
657 if (ret < 0)
658 return ret;
659 return IIO_VAL_INT_PLUS_MICRO;
e7854845
JC
660 default:
661 return -EINVAL;
662 }
663}
664
f4e4b955 665static const struct iio_chan_spec adis16400_channels[] = {
521de518
JC
666 {
667 .type = IIO_VOLTAGE,
668 .indexed = 1,
669 .channel = 0,
670 .extend_name = "supply",
a5d016d4
JC
671 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
672 IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
521de518
JC
673 .address = in_supply,
674 .scan_index = ADIS16400_SCAN_SUPPLY,
cdf71c7f 675 .scan_type = IIO_ST('u', 14, 16, 0),
521de518 676 }, {
41ea040c 677 .type = IIO_ANGL_VEL,
521de518
JC
678 .modified = 1,
679 .channel2 = IIO_MOD_X,
a5d016d4
JC
680 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
681 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
682 IIO_CHAN_INFO_SCALE_SHARED_BIT |
683 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
684 .address = gyro_x,
685 .scan_index = ADIS16400_SCAN_GYRO_X,
cdf71c7f 686 .scan_type = IIO_ST('s', 14, 16, 0),
521de518 687 }, {
41ea040c 688 .type = IIO_ANGL_VEL,
521de518
JC
689 .modified = 1,
690 .channel2 = IIO_MOD_Y,
a5d016d4
JC
691 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
692 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
693 IIO_CHAN_INFO_SCALE_SHARED_BIT |
694 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
695 .address = gyro_y,
696 .scan_index = ADIS16400_SCAN_GYRO_Y,
697 .scan_type = IIO_ST('s', 14, 16, 0),
698 }, {
41ea040c 699 .type = IIO_ANGL_VEL,
521de518
JC
700 .modified = 1,
701 .channel2 = IIO_MOD_Z,
a5d016d4
JC
702 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
703 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
704 IIO_CHAN_INFO_SCALE_SHARED_BIT |
705 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
706 .address = gyro_z,
707 .scan_index = ADIS16400_SCAN_GYRO_Z,
708 .scan_type = IIO_ST('s', 14, 16, 0),
709 }, {
710 .type = IIO_ACCEL,
711 .modified = 1,
712 .channel2 = IIO_MOD_X,
a5d016d4
JC
713 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
714 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
715 IIO_CHAN_INFO_SCALE_SHARED_BIT |
716 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
717 .address = accel_x,
718 .scan_index = ADIS16400_SCAN_ACC_X,
719 .scan_type = IIO_ST('s', 14, 16, 0),
720 }, {
721 .type = IIO_ACCEL,
722 .modified = 1,
723 .channel2 = IIO_MOD_Y,
a5d016d4
JC
724 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
725 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
726 IIO_CHAN_INFO_SCALE_SHARED_BIT |
727 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
728 .address = accel_y,
729 .scan_index = ADIS16400_SCAN_ACC_Y,
730 .scan_type = IIO_ST('s', 14, 16, 0),
731 }, {
732 .type = IIO_ACCEL,
733 .modified = 1,
734 .channel2 = IIO_MOD_Z,
a5d016d4
JC
735 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
736 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
737 IIO_CHAN_INFO_SCALE_SHARED_BIT |
738 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
739 .address = accel_z,
740 .scan_index = ADIS16400_SCAN_ACC_Z,
741 .scan_type = IIO_ST('s', 14, 16, 0),
742 }, {
743 .type = IIO_MAGN,
744 .modified = 1,
745 .channel2 = IIO_MOD_X,
a5d016d4
JC
746 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
747 IIO_CHAN_INFO_SCALE_SHARED_BIT |
98c9373d 748 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
749 .address = magn_x,
750 .scan_index = ADIS16400_SCAN_MAGN_X,
751 .scan_type = IIO_ST('s', 14, 16, 0),
752 }, {
753 .type = IIO_MAGN,
754 .modified = 1,
755 .channel2 = IIO_MOD_Y,
a5d016d4
JC
756 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
757 IIO_CHAN_INFO_SCALE_SHARED_BIT |
98c9373d 758 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
759 .address = magn_y,
760 .scan_index = ADIS16400_SCAN_MAGN_Y,
761 .scan_type = IIO_ST('s', 14, 16, 0),
762 }, {
763 .type = IIO_MAGN,
764 .modified = 1,
765 .channel2 = IIO_MOD_Z,
a5d016d4
JC
766 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
767 IIO_CHAN_INFO_SCALE_SHARED_BIT |
98c9373d 768 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
769 .address = magn_z,
770 .scan_index = ADIS16400_SCAN_MAGN_Z,
771 .scan_type = IIO_ST('s', 14, 16, 0),
772 }, {
773 .type = IIO_TEMP,
774 .indexed = 1,
775 .channel = 0,
a5d016d4
JC
776 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
777 IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
c8a9f805 778 IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
521de518
JC
779 .address = temp,
780 .scan_index = ADIS16400_SCAN_TEMP,
781 .scan_type = IIO_ST('s', 12, 16, 0),
782 }, {
6835cb6b 783 .type = IIO_VOLTAGE,
521de518
JC
784 .indexed = 1,
785 .channel = 1,
a5d016d4
JC
786 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
787 IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
07a8329c 788 .address = in2,
521de518
JC
789 .scan_index = ADIS16400_SCAN_ADC_0,
790 .scan_type = IIO_ST('s', 12, 16, 0),
791 },
e7854845
JC
792 IIO_CHAN_SOFT_TIMESTAMP(12)
793};
794
f4e4b955 795static const struct iio_chan_spec adis16350_channels[] = {
521de518
JC
796 {
797 .type = IIO_VOLTAGE,
798 .indexed = 1,
799 .channel = 0,
800 .extend_name = "supply",
a5d016d4
JC
801 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
802 IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
521de518
JC
803 .address = in_supply,
804 .scan_index = ADIS16400_SCAN_SUPPLY,
cdf71c7f 805 .scan_type = IIO_ST('u', 12, 16, 0),
521de518 806 }, {
41ea040c 807 .type = IIO_ANGL_VEL,
521de518
JC
808 .modified = 1,
809 .channel2 = IIO_MOD_X,
a5d016d4
JC
810 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
811 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
812 IIO_CHAN_INFO_SCALE_SHARED_BIT |
813 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
814 .address = gyro_x,
815 .scan_index = ADIS16400_SCAN_GYRO_X,
cdf71c7f 816 .scan_type = IIO_ST('s', 14, 16, 0),
521de518 817 }, {
41ea040c 818 .type = IIO_ANGL_VEL,
521de518
JC
819 .modified = 1,
820 .channel2 = IIO_MOD_Y,
a5d016d4
JC
821 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
822 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
823 IIO_CHAN_INFO_SCALE_SHARED_BIT |
824 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
825 .address = gyro_y,
826 .scan_index = ADIS16400_SCAN_GYRO_Y,
827 .scan_type = IIO_ST('s', 14, 16, 0),
828 }, {
41ea040c 829 .type = IIO_ANGL_VEL,
521de518
JC
830 .modified = 1,
831 .channel2 = IIO_MOD_Z,
a5d016d4
JC
832 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
833 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
834 IIO_CHAN_INFO_SCALE_SHARED_BIT |
835 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
836 .address = gyro_z,
837 .scan_index = ADIS16400_SCAN_GYRO_Z,
838 .scan_type = IIO_ST('s', 14, 16, 0),
839 }, {
a5d016d4 840 .type = IIO_ACCEL,
521de518
JC
841 .modified = 1,
842 .channel2 = IIO_MOD_X,
a5d016d4
JC
843 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
844 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
845 IIO_CHAN_INFO_SCALE_SHARED_BIT |
846 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
847 .address = accel_x,
848 .scan_index = ADIS16400_SCAN_ACC_X,
849 .scan_type = IIO_ST('s', 14, 16, 0),
850 }, {
851 .type = IIO_ACCEL,
852 .modified = 1,
853 .channel2 = IIO_MOD_Y,
a5d016d4
JC
854 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
855 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
856 IIO_CHAN_INFO_SCALE_SHARED_BIT |
857 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
858 .address = accel_y,
859 .scan_index = ADIS16400_SCAN_ACC_Y,
860 .scan_type = IIO_ST('s', 14, 16, 0),
861 }, {
862 .type = IIO_ACCEL,
863 .modified = 1,
864 .channel2 = IIO_MOD_Z,
a5d016d4
JC
865 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
866 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
867 IIO_CHAN_INFO_SCALE_SHARED_BIT |
868 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
869 .address = accel_z,
870 .scan_index = ADIS16400_SCAN_ACC_Z,
871 .scan_type = IIO_ST('s', 14, 16, 0),
872 }, {
873 .type = IIO_TEMP,
874 .indexed = 1,
875 .channel = 0,
876 .extend_name = "x",
a5d016d4
JC
877 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
878 IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
98c9373d
JC
879 IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
880 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
881 .address = temp0,
882 .scan_index = ADIS16350_SCAN_TEMP_X,
883 .scan_type = IIO_ST('s', 12, 16, 0),
884 }, {
885 .type = IIO_TEMP,
886 .indexed = 1,
887 .channel = 1,
888 .extend_name = "y",
a5d016d4
JC
889 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
890 IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
98c9373d
JC
891 IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
892 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
893 .address = temp1,
894 .scan_index = ADIS16350_SCAN_TEMP_Y,
895 .scan_type = IIO_ST('s', 12, 16, 0),
896 }, {
897 .type = IIO_TEMP,
898 .indexed = 1,
899 .channel = 2,
900 .extend_name = "z",
a5d016d4
JC
901 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
902 IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
c8a9f805 903 IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
521de518
JC
904 .address = temp2,
905 .scan_index = ADIS16350_SCAN_TEMP_Z,
906 .scan_type = IIO_ST('s', 12, 16, 0),
907 }, {
6835cb6b 908 .type = IIO_VOLTAGE,
521de518
JC
909 .indexed = 1,
910 .channel = 1,
a5d016d4
JC
911 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
912 IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
521de518
JC
913 .address = in1,
914 .scan_index = ADIS16350_SCAN_ADC_0,
915 .scan_type = IIO_ST('s', 12, 16, 0),
916 },
2a29a90b
JC
917 IIO_CHAN_SOFT_TIMESTAMP(11)
918};
919
f4e4b955 920static const struct iio_chan_spec adis16300_channels[] = {
521de518
JC
921 {
922 .type = IIO_VOLTAGE,
923 .indexed = 1,
924 .channel = 0,
925 .extend_name = "supply",
a5d016d4
JC
926 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
927 IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
521de518
JC
928 .address = in_supply,
929 .scan_index = ADIS16400_SCAN_SUPPLY,
cdf71c7f 930 .scan_type = IIO_ST('u', 12, 16, 0),
521de518 931 }, {
41ea040c 932 .type = IIO_ANGL_VEL,
521de518
JC
933 .modified = 1,
934 .channel2 = IIO_MOD_X,
a5d016d4
JC
935 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
936 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
937 IIO_CHAN_INFO_SCALE_SHARED_BIT |
938 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
939 .address = gyro_x,
940 .scan_index = ADIS16400_SCAN_GYRO_X,
941 .scan_type = IIO_ST('s', 14, 16, 0),
942 }, {
943 .type = IIO_ACCEL,
944 .modified = 1,
945 .channel2 = IIO_MOD_X,
a5d016d4
JC
946 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
947 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
948 IIO_CHAN_INFO_SCALE_SHARED_BIT |
949 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
950 .address = accel_x,
951 .scan_index = ADIS16400_SCAN_ACC_X,
952 .scan_type = IIO_ST('s', 14, 16, 0),
953 }, {
954 .type = IIO_ACCEL,
955 .modified = 1,
956 .channel2 = IIO_MOD_Y,
a5d016d4
JC
957 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
958 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
959 IIO_CHAN_INFO_SCALE_SHARED_BIT |
960 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
961 .address = accel_y,
962 .scan_index = ADIS16400_SCAN_ACC_Y,
963 .scan_type = IIO_ST('s', 14, 16, 0),
964 }, {
965 .type = IIO_ACCEL,
966 .modified = 1,
967 .channel2 = IIO_MOD_Z,
a5d016d4
JC
968 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
969 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
970 IIO_CHAN_INFO_SCALE_SHARED_BIT |
971 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
972 .address = accel_z,
973 .scan_index = ADIS16400_SCAN_ACC_Z,
974 .scan_type = IIO_ST('s', 14, 16, 0),
975 }, {
976 .type = IIO_TEMP,
977 .indexed = 1,
978 .channel = 0,
a5d016d4
JC
979 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
980 IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
c8a9f805 981 IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
6f30592e 982 .address = temp0,
521de518
JC
983 .scan_index = ADIS16400_SCAN_TEMP,
984 .scan_type = IIO_ST('s', 12, 16, 0),
985 }, {
6835cb6b 986 .type = IIO_VOLTAGE,
521de518
JC
987 .indexed = 1,
988 .channel = 1,
a5d016d4
JC
989 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
990 IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
521de518
JC
991 .address = in1,
992 .scan_index = ADIS16350_SCAN_ADC_0,
993 .scan_type = IIO_ST('s', 12, 16, 0),
994 }, {
995 .type = IIO_INCLI,
996 .modified = 1,
997 .channel2 = IIO_MOD_X,
a5d016d4
JC
998 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
999 IIO_CHAN_INFO_SCALE_SHARED_BIT,
521de518
JC
1000 .address = incli_x,
1001 .scan_index = ADIS16300_SCAN_INCLI_X,
1002 .scan_type = IIO_ST('s', 13, 16, 0),
1003 }, {
1004 .type = IIO_INCLI,
1005 .modified = 1,
1006 .channel2 = IIO_MOD_Y,
a5d016d4
JC
1007 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
1008 IIO_CHAN_INFO_SCALE_SHARED_BIT,
521de518
JC
1009 .address = incli_y,
1010 .scan_index = ADIS16300_SCAN_INCLI_Y,
1011 .scan_type = IIO_ST('s', 13, 16, 0),
1012 },
8e886e65
JC
1013 IIO_CHAN_SOFT_TIMESTAMP(14)
1014};
1015
85da5059 1016static const struct iio_chan_spec adis16334_channels[] = {
521de518 1017 {
41ea040c 1018 .type = IIO_ANGL_VEL,
521de518
JC
1019 .modified = 1,
1020 .channel2 = IIO_MOD_X,
a5d016d4
JC
1021 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
1022 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
1023 IIO_CHAN_INFO_SCALE_SHARED_BIT |
1024 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
1025 .address = gyro_x,
1026 .scan_index = ADIS16400_SCAN_GYRO_X,
1027 .scan_type = IIO_ST('s', 14, 16, 0),
1028 }, {
41ea040c 1029 .type = IIO_ANGL_VEL,
521de518
JC
1030 .modified = 1,
1031 .channel2 = IIO_MOD_Y,
a5d016d4
JC
1032 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
1033 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
1034 IIO_CHAN_INFO_SCALE_SHARED_BIT |
1035 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
1036 .address = gyro_y,
1037 .scan_index = ADIS16400_SCAN_GYRO_Y,
1038 .scan_type = IIO_ST('s', 14, 16, 0),
1039 }, {
41ea040c 1040 .type = IIO_ANGL_VEL,
521de518
JC
1041 .modified = 1,
1042 .channel2 = IIO_MOD_Z,
a5d016d4
JC
1043 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
1044 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
1045 IIO_CHAN_INFO_SCALE_SHARED_BIT |
1046 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
1047 .address = gyro_z,
1048 .scan_index = ADIS16400_SCAN_GYRO_Z,
1049 .scan_type = IIO_ST('s', 14, 16, 0),
1050 }, {
1051 .type = IIO_ACCEL,
1052 .modified = 1,
1053 .channel2 = IIO_MOD_X,
a5d016d4
JC
1054 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
1055 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
1056 IIO_CHAN_INFO_SCALE_SHARED_BIT |
1057 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
1058 .address = accel_x,
1059 .scan_index = ADIS16400_SCAN_ACC_X,
1060 .scan_type = IIO_ST('s', 14, 16, 0),
1061 }, {
1062 .type = IIO_ACCEL,
1063 .modified = 1,
1064 .channel2 = IIO_MOD_Y,
a5d016d4
JC
1065 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
1066 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
1067 IIO_CHAN_INFO_SCALE_SHARED_BIT |
1068 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
1069 .address = accel_y,
1070 .scan_index = ADIS16400_SCAN_ACC_Y,
1071 .scan_type = IIO_ST('s', 14, 16, 0),
1072 }, {
1073 .type = IIO_ACCEL,
1074 .modified = 1,
1075 .channel2 = IIO_MOD_Z,
a5d016d4
JC
1076 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
1077 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
98c9373d
JC
1078 IIO_CHAN_INFO_SCALE_SHARED_BIT |
1079 IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
521de518
JC
1080 .address = accel_z,
1081 .scan_index = ADIS16400_SCAN_ACC_Z,
1082 .scan_type = IIO_ST('s', 14, 16, 0),
1083 }, {
1084 .type = IIO_TEMP,
1085 .indexed = 1,
1086 .channel = 0,
a5d016d4 1087 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
2e132e46 1088 IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
c8a9f805 1089 IIO_CHAN_INFO_SCALE_SHARED_BIT,
bb7cf8bc
LPC
1090 .address = temp0,
1091 .scan_index = ADIS16400_SCAN_TEMP,
521de518
JC
1092 .scan_type = IIO_ST('s', 14, 16, 0),
1093 },
88b42f3a
JC
1094 IIO_CHAN_SOFT_TIMESTAMP(12)
1095};
1096
a9d26f00 1097static struct attribute *adis16400_attributes[] = {
a9d26f00 1098 &iio_dev_attr_sampling_frequency.dev_attr.attr,
51a0a5b0 1099 &iio_const_attr_sampling_frequency_available.dev_attr.attr,
a9d26f00
BS
1100 NULL
1101};
1102
1103static const struct attribute_group adis16400_attribute_group = {
1104 .attrs = adis16400_attributes,
1105};
1106
2a29a90b 1107static struct adis16400_chip_info adis16400_chips[] = {
8e886e65
JC
1108 [ADIS16300] = {
1109 .channels = adis16300_channels,
1110 .num_channels = ARRAY_SIZE(adis16300_channels),
ea2ccb3e 1111 .flags = ADIS16400_HAS_SLOW_MODE,
1cf8c97f 1112 .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
8e886e65 1113 .accel_scale_micro = 5884,
760ebc0d
LPC
1114 .temp_scale_nano = 140000000, /* 0.14 C */
1115 .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
8e886e65
JC
1116 .default_scan_mask = (1 << ADIS16400_SCAN_SUPPLY) |
1117 (1 << ADIS16400_SCAN_GYRO_X) | (1 << ADIS16400_SCAN_ACC_X) |
1118 (1 << ADIS16400_SCAN_ACC_Y) | (1 << ADIS16400_SCAN_ACC_Z) |
1119 (1 << ADIS16400_SCAN_TEMP) | (1 << ADIS16400_SCAN_ADC_0) |
1120 (1 << ADIS16300_SCAN_INCLI_X) | (1 << ADIS16300_SCAN_INCLI_Y) |
1121 (1 << 14),
ea2ccb3e
LPC
1122 .set_freq = adis16400_set_freq,
1123 .get_freq = adis16400_get_freq,
8e886e65 1124 },
85da5059
JC
1125 [ADIS16334] = {
1126 .channels = adis16334_channels,
1127 .num_channels = ARRAY_SIZE(adis16334_channels),
3c7f0c2b 1128 .flags = ADIS16400_HAS_PROD_ID,
1cf8c97f
LPC
1129 .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
1130 .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
760ebc0d
LPC
1131 .temp_scale_nano = 67850000, /* 0.06785 C */
1132 .temp_offset = 25000000 / 67850, /* 25 C = 0x00 */
88b42f3a
JC
1133 .default_scan_mask = (1 << ADIS16400_SCAN_GYRO_X) |
1134 (1 << ADIS16400_SCAN_GYRO_Y) | (1 << ADIS16400_SCAN_GYRO_Z) |
1135 (1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) |
1136 (1 << ADIS16400_SCAN_ACC_Z),
ea2ccb3e
LPC
1137 .set_freq = adis16334_set_freq,
1138 .get_freq = adis16334_get_freq,
88b42f3a 1139 },
2a29a90b
JC
1140 [ADIS16350] = {
1141 .channels = adis16350_channels,
1142 .num_channels = ARRAY_SIZE(adis16350_channels),
1cf8c97f
LPC
1143 .gyro_scale_micro = IIO_DEGREE_TO_RAD(73260), /* 0.07326 deg/s */
1144 .accel_scale_micro = IIO_G_TO_M_S_2(2522), /* 0.002522 g */
760ebc0d
LPC
1145 .temp_scale_nano = 145300000, /* 0.1453 C */
1146 .temp_offset = 25000000 / 145300, /* 25 C = 0x00 */
2a29a90b 1147 .default_scan_mask = 0x7FF,
ea2ccb3e
LPC
1148 .flags = ADIS16400_NO_BURST | ADIS16400_HAS_SLOW_MODE,
1149 .set_freq = adis16400_set_freq,
1150 .get_freq = adis16400_get_freq,
2a29a90b
JC
1151 },
1152 [ADIS16360] = {
1153 .channels = adis16350_channels,
1154 .num_channels = ARRAY_SIZE(adis16350_channels),
ea2ccb3e 1155 .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
1cf8c97f
LPC
1156 .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
1157 .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
760ebc0d
LPC
1158 .temp_scale_nano = 136000000, /* 0.136 C */
1159 .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
2a29a90b 1160 .default_scan_mask = 0x7FF,
ea2ccb3e
LPC
1161 .set_freq = adis16400_set_freq,
1162 .get_freq = adis16400_get_freq,
2a29a90b
JC
1163 },
1164 [ADIS16362] = {
1165 .channels = adis16350_channels,
1166 .num_channels = ARRAY_SIZE(adis16350_channels),
ea2ccb3e 1167 .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
1cf8c97f
LPC
1168 .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
1169 .accel_scale_micro = IIO_G_TO_M_S_2(333), /* 0.333 mg */
760ebc0d
LPC
1170 .temp_scale_nano = 136000000, /* 0.136 C */
1171 .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
2a29a90b 1172 .default_scan_mask = 0x7FF,
ea2ccb3e
LPC
1173 .set_freq = adis16400_set_freq,
1174 .get_freq = adis16400_get_freq,
2a29a90b
JC
1175 },
1176 [ADIS16364] = {
1177 .channels = adis16350_channels,
1178 .num_channels = ARRAY_SIZE(adis16350_channels),
ea2ccb3e 1179 .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
1cf8c97f
LPC
1180 .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
1181 .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
760ebc0d
LPC
1182 .temp_scale_nano = 136000000, /* 0.136 C */
1183 .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
2a29a90b 1184 .default_scan_mask = 0x7FF,
ea2ccb3e
LPC
1185 .set_freq = adis16400_set_freq,
1186 .get_freq = adis16400_get_freq,
2a29a90b 1187 },
2a29a90b
JC
1188 [ADIS16400] = {
1189 .channels = adis16400_channels,
1190 .num_channels = ARRAY_SIZE(adis16400_channels),
ea2ccb3e 1191 .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
1cf8c97f
LPC
1192 .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
1193 .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
2a29a90b 1194 .default_scan_mask = 0xFFF,
760ebc0d
LPC
1195 .temp_scale_nano = 140000000, /* 0.14 C */
1196 .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
ea2ccb3e
LPC
1197 .set_freq = adis16400_set_freq,
1198 .get_freq = adis16400_get_freq,
2a29a90b
JC
1199 }
1200};
1201
6fe8135f
JC
1202static const struct iio_info adis16400_info = {
1203 .driver_module = THIS_MODULE,
1204 .read_raw = &adis16400_read_raw,
1205 .write_raw = &adis16400_write_raw,
1206 .attrs = &adis16400_attribute_group,
1207};
2a29a90b 1208
4ae1c61f 1209static int adis16400_probe(struct spi_device *spi)
a9d26f00 1210{
26d25ae3 1211 int ret;
38d15f06 1212 struct adis16400_state *st;
7cbb7537 1213 struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
38d15f06 1214 if (indio_dev == NULL) {
a9d26f00
BS
1215 ret = -ENOMEM;
1216 goto error_ret;
1217 }
38d15f06 1218 st = iio_priv(indio_dev);
a9d26f00 1219 /* this is only used for removal purposes */
38d15f06 1220 spi_set_drvdata(spi, indio_dev);
a9d26f00 1221
a9d26f00
BS
1222 st->us = spi;
1223 mutex_init(&st->buf_lock);
38d15f06 1224
a9d26f00 1225 /* setup the industrialio driver allocated elements */
2a29a90b 1226 st->variant = &adis16400_chips[spi_get_device_id(spi)->driver_data];
38d15f06
JC
1227 indio_dev->dev.parent = &spi->dev;
1228 indio_dev->name = spi_get_device_id(spi)->name;
38d15f06
JC
1229 indio_dev->channels = st->variant->channels;
1230 indio_dev->num_channels = st->variant->num_channels;
6fe8135f 1231 indio_dev->info = &adis16400_info;
38d15f06
JC
1232 indio_dev->modes = INDIO_DIRECT_MODE;
1233
1234 ret = adis16400_configure_ring(indio_dev);
a9d26f00
BS
1235 if (ret)
1236 goto error_free_dev;
1237
14555b14
JC
1238 ret = iio_buffer_register(indio_dev,
1239 st->variant->channels,
1240 st->variant->num_channels);
a9d26f00 1241 if (ret) {
6a6ec623 1242 dev_err(&spi->dev, "failed to initialize the ring\n");
a9d26f00
BS
1243 goto error_unreg_ring_funcs;
1244 }
1245
521de518 1246 if (spi->irq) {
38d15f06 1247 ret = adis16400_probe_trigger(indio_dev);
a9d26f00 1248 if (ret)
b333a240 1249 goto error_uninitialize_ring;
a9d26f00
BS
1250 }
1251
1252 /* Get the device into a sane initial state */
38d15f06 1253 ret = adis16400_initial_setup(indio_dev);
a9d26f00
BS
1254 if (ret)
1255 goto error_remove_trigger;
26d25ae3
JC
1256 ret = iio_device_register(indio_dev);
1257 if (ret)
1258 goto error_remove_trigger;
1259
a9d26f00
BS
1260 return 0;
1261
1262error_remove_trigger:
487db485 1263 if (spi->irq)
38d15f06 1264 adis16400_remove_trigger(indio_dev);
a9d26f00 1265error_uninitialize_ring:
14555b14 1266 iio_buffer_unregister(indio_dev);
a9d26f00 1267error_unreg_ring_funcs:
38d15f06 1268 adis16400_unconfigure_ring(indio_dev);
a9d26f00 1269error_free_dev:
7cbb7537 1270 iio_device_free(indio_dev);
a9d26f00
BS
1271error_ret:
1272 return ret;
1273}
1274
1275/* fixme, confirm ordering in this function */
447d4f29 1276static int adis16400_remove(struct spi_device *spi)
a9d26f00 1277{
38d15f06 1278 struct iio_dev *indio_dev = spi_get_drvdata(spi);
a9d26f00 1279
d2fffd6c 1280 iio_device_unregister(indio_dev);
0b4ac3dc 1281 adis16400_stop_device(indio_dev);
a9d26f00 1282
a9d26f00 1283 adis16400_remove_trigger(indio_dev);
14555b14 1284 iio_buffer_unregister(indio_dev);
a9d26f00 1285 adis16400_unconfigure_ring(indio_dev);
7cbb7537 1286 iio_device_free(indio_dev);
2a29a90b 1287
a9d26f00 1288 return 0;
a9d26f00
BS
1289}
1290
2a29a90b 1291static const struct spi_device_id adis16400_id[] = {
8e886e65 1292 {"adis16300", ADIS16300},
85da5059 1293 {"adis16334", ADIS16334},
2a29a90b
JC
1294 {"adis16350", ADIS16350},
1295 {"adis16354", ADIS16350},
1296 {"adis16355", ADIS16350},
1297 {"adis16360", ADIS16360},
1298 {"adis16362", ADIS16362},
1299 {"adis16364", ADIS16364},
a7462e64 1300 {"adis16365", ADIS16360},
2a29a90b
JC
1301 {"adis16400", ADIS16400},
1302 {"adis16405", ADIS16400},
1303 {}
1304};
55e4390c 1305MODULE_DEVICE_TABLE(spi, adis16400_id);
2a29a90b 1306
a9d26f00
BS
1307static struct spi_driver adis16400_driver = {
1308 .driver = {
1309 .name = "adis16400",
1310 .owner = THIS_MODULE,
1311 },
2a29a90b 1312 .id_table = adis16400_id,
a9d26f00 1313 .probe = adis16400_probe,
e543acf0 1314 .remove = adis16400_remove,
a9d26f00 1315};
ae6ae6fe 1316module_spi_driver(adis16400_driver);
a9d26f00
BS
1317
1318MODULE_AUTHOR("Manuel Stahl <manuel.stahl@iis.fraunhofer.de>");
1319MODULE_DESCRIPTION("Analog Devices ADIS16400/5 IMU SPI driver");
1320MODULE_LICENSE("GPL v2");
This page took 0.390618 seconds and 5 git commands to generate.