1bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song/*
2bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * ADIS16204 Programmable High-g Digital Impact Sensor and Recorder
3bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song *
4bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * Copyright 2010 Analog Devices Inc.
5bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song *
6bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * Licensed under the GPL-2 or later.
7bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song */
8bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
9bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/interrupt.h>
10bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/irq.h>
11bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/delay.h>
12bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/mutex.h>
13bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/device.h>
14bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/kernel.h>
15bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/spi/spi.h>
16bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/slab.h>
17bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/sysfs.h>
18bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/list.h>
1999c978529a40132a6f7a5f136b4362b56fc88d8cPaul Gortmaker#include <linux/module.h>
20bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
21bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include "../iio.h"
22bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include "../sysfs.h"
23af5046af1c812839f085030f358a01814666fc80Jonathan Cameron#include "../buffer.h"
24bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
25bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include "adis16204.h"
26bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
27bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#define DRIVER_NAME		"adis16204"
28bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
29bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song/**
30bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * adis16204_spi_write_reg_8() - write single byte to a register
31bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * @dev: device associated with child of actual device (iio_dev or iio_trig)
32bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * @reg_address: the address of the register to be written
33bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * @val: the value to write
34bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song **/
35ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_spi_write_reg_8(struct iio_dev *indio_dev,
36bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		u8 reg_address,
37bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		u8 val)
38bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
39bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	int ret;
404de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	struct adis16204_state *st = iio_priv(indio_dev);
41bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
42bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_lock(&st->buf_lock);
43bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->tx[0] = ADIS16204_WRITE_REG(reg_address);
44bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->tx[1] = val;
45bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
46bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	ret = spi_write(st->us, st->tx, 2);
47bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_unlock(&st->buf_lock);
48bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
49bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
50bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
51bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
52bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song/**
53bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * adis16204_spi_write_reg_16() - write 2 bytes to a pair of registers
54ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron * @indio_dev: iio device associated with child of actual device
55bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * @reg_address: the address of the lower of the two registers. Second register
56bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song *               is assumed to have address one greater.
57bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * @val: value to be written
58bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song **/
59ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_spi_write_reg_16(struct iio_dev *indio_dev,
60bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		u8 lower_reg_address,
61bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		u16 value)
62bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
63bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	int ret;
64bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	struct spi_message msg;
654de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	struct adis16204_state *st = iio_priv(indio_dev);
66bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	struct spi_transfer xfers[] = {
67bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		{
68bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.tx_buf = st->tx,
69bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.bits_per_word = 8,
70bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.len = 2,
71bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.cs_change = 1,
72bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		}, {
73bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.tx_buf = st->tx + 2,
74bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.bits_per_word = 8,
75bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.len = 2,
76bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.cs_change = 1,
77bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		},
78bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	};
79bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
80bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_lock(&st->buf_lock);
81bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->tx[0] = ADIS16204_WRITE_REG(lower_reg_address);
82bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->tx[1] = value & 0xFF;
83bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->tx[2] = ADIS16204_WRITE_REG(lower_reg_address + 1);
84bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->tx[3] = (value >> 8) & 0xFF;
85bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
86bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	spi_message_init(&msg);
87bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	spi_message_add_tail(&xfers[0], &msg);
88bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	spi_message_add_tail(&xfers[1], &msg);
89bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	ret = spi_sync(st->us, &msg);
90bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_unlock(&st->buf_lock);
91bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
92bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
93bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
94bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
95bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song/**
96bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * adis16204_spi_read_reg_16() - read 2 bytes from a 16-bit register
97ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron * @indio_dev: iio device associated with child of actual device
98bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * @reg_address: the address of the lower of the two registers. Second register
99bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song *               is assumed to have address one greater.
100bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * @val: somewhere to pass back the value read
101bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song **/
102ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_spi_read_reg_16(struct iio_dev *indio_dev,
103ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				     u8 lower_reg_address,
104ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				     u16 *val)
105bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
106bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	struct spi_message msg;
1074de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	struct adis16204_state *st = iio_priv(indio_dev);
108bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	int ret;
109bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	struct spi_transfer xfers[] = {
110bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		{
111bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.tx_buf = st->tx,
112bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.bits_per_word = 8,
113bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.len = 2,
114bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.cs_change = 1,
115bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.delay_usecs = 20,
116bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		}, {
117bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.rx_buf = st->rx,
118bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.bits_per_word = 8,
119bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.len = 2,
120bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.delay_usecs = 20,
121bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		},
122bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	};
123bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
124bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_lock(&st->buf_lock);
125bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->tx[0] = ADIS16204_READ_REG(lower_reg_address);
126bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->tx[1] = 0;
127bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
128bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	spi_message_init(&msg);
129bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	spi_message_add_tail(&xfers[0], &msg);
130bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	spi_message_add_tail(&xfers[1], &msg);
131bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	ret = spi_sync(st->us, &msg);
132bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret) {
133bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
134bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song				lower_reg_address);
135bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto error_ret;
136bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
137bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	*val = (st->rx[0] << 8) | st->rx[1];
138bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
139bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerror_ret:
140bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_unlock(&st->buf_lock);
141bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
142bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
143bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
144ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_check_status(struct iio_dev *indio_dev)
145bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
146ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	u16 status;
147bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	int ret;
148bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
149ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_spi_read_reg_16(indio_dev,
150ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron					ADIS16204_DIAG_STAT, &status);
151ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	if (ret < 0) {
152ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "Reading status failed\n");
153bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto error_ret;
154bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
155ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = status & 0x1F;
156bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
157ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	if (status & ADIS16204_DIAG_STAT_SELFTEST_FAIL)
158ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "Self test failure\n");
159ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	if (status & ADIS16204_DIAG_STAT_SPI_FAIL)
160ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "SPI failure\n");
161ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	if (status & ADIS16204_DIAG_STAT_FLASH_UPT)
162ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "Flash update failed\n");
163ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	if (status & ADIS16204_DIAG_STAT_POWER_HIGH)
164ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "Power supply above 3.625V\n");
165ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	if (status & ADIS16204_DIAG_STAT_POWER_LOW)
166ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "Power supply below 2.975V\n");
167bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
168ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronerror_ret:
169bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
170bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
171bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
172bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic ssize_t adis16204_read_14bit_signed(struct device *dev,
173bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		struct device_attribute *attr,
174bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		char *buf)
175bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
176bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	struct iio_dev *indio_dev = dev_get_drvdata(dev);
177bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
178bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	s16 val = 0;
179bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	ssize_t ret;
180bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
181bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_lock(&indio_dev->mlock);
182bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
183ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_spi_read_reg_16(indio_dev,
184ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron					this_attr->address, (u16 *)&val);
185bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (!ret) {
186bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		if (val & ADIS16204_ERROR_ACTIVE)
187ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			adis16204_check_status(indio_dev);
188bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
189bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		val = ((s16)(val << 2) >> 2);
190bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		ret = sprintf(buf, "%d\n", val);
191bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
192bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
193bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_unlock(&indio_dev->mlock);
194bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
195bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
196bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
197bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
198ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_reset(struct iio_dev *indio_dev)
199bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
200bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	int ret;
201ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_spi_write_reg_8(indio_dev,
202bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			ADIS16204_GLOB_CMD,
203bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			ADIS16204_GLOB_CMD_SW_RESET);
204bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret)
205ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "problem resetting device");
206bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
207bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
208bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
209bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
210bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic ssize_t adis16204_write_reset(struct device *dev,
211bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		struct device_attribute *attr,
212bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		const char *buf, size_t len)
213bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
214ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
215ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron
216bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (len < 1)
217bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		return -EINVAL;
218bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	switch (buf[0]) {
219bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	case '1':
220bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	case 'y':
221bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	case 'Y':
222ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		return adis16204_reset(indio_dev);
223bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
224bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return -EINVAL;
225bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
226bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
227ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronint adis16204_set_irq(struct iio_dev *indio_dev, bool enable)
228bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
229bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	int ret = 0;
230bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	u16 msc;
231bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
232ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_spi_read_reg_16(indio_dev, ADIS16204_MSC_CTRL, &msc);
233bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret)
234bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto error_ret;
235bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
236bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	msc |= ADIS16204_MSC_CTRL_ACTIVE_HIGH;
237bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	msc &= ~ADIS16204_MSC_CTRL_DATA_RDY_DIO2;
238bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (enable)
239bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		msc |= ADIS16204_MSC_CTRL_DATA_RDY_EN;
240bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	else
241bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		msc &= ~ADIS16204_MSC_CTRL_DATA_RDY_EN;
242bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
243ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_spi_write_reg_16(indio_dev, ADIS16204_MSC_CTRL, msc);
244bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
245bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerror_ret:
246bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
247bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
248bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
249ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_self_test(struct iio_dev *indio_dev)
250bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
251bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	int ret;
252ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_spi_write_reg_16(indio_dev,
253bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			ADIS16204_MSC_CTRL,
254bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			ADIS16204_MSC_CTRL_SELF_TEST_EN);
255bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret) {
256ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "problem starting self test");
257bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto err_ret;
258bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
259bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
260ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	adis16204_check_status(indio_dev);
261bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
262bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerr_ret:
263bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
264bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
265bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
266ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_initial_setup(struct iio_dev *indio_dev)
267bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
268bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	int ret;
269bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
270bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	/* Disable IRQ */
271ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_set_irq(indio_dev, false);
272bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret) {
273ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "disable irq failed");
274bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto err_ret;
275bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
276bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
277bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	/* Do self test */
278ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_self_test(indio_dev);
279bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret) {
280ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "self test failure");
281bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto err_ret;
282bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
283bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
284bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	/* Read status register to check the result */
285ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_check_status(indio_dev);
286bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret) {
287ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		adis16204_reset(indio_dev);
288ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "device not playing ball -> reset");
289bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		msleep(ADIS16204_STARTUP_DELAY);
290ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		ret = adis16204_check_status(indio_dev);
291bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		if (ret) {
292ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			dev_err(&indio_dev->dev, "giving up");
293bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			goto err_ret;
294bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		}
295bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
296bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
297bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerr_ret:
298bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
299bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
300c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron
301c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron/* Unique to this driver currently */
302c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron#define IIO_DEV_ATTR_ACCEL_XY(_show, _addr)			\
303322c95636739420631e51f3d3f24132dc220762aJonathan Cameron	IIO_DEVICE_ATTR(in_accel_xy, S_IRUGO, _show, NULL, _addr)
304c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron#define IIO_DEV_ATTR_ACCEL_XYPEAK(_show, _addr)		\
305322c95636739420631e51f3d3f24132dc220762aJonathan Cameron	IIO_DEVICE_ATTR(in_accel_xypeak, S_IRUGO, _show, NULL, _addr)
306c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron
307bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic IIO_DEV_ATTR_ACCEL_XY(adis16204_read_14bit_signed,
308bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		ADIS16204_XY_RSS_OUT);
309bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic IIO_DEV_ATTR_ACCEL_XYPEAK(adis16204_read_14bit_signed,
310bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		ADIS16204_XY_PEAK_OUT);
311322c95636739420631e51f3d3f24132dc220762aJonathan Cameronstatic IIO_CONST_ATTR(in_accel_xy_scale, "0.017125");
312bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
313bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16204_write_reset, 0);
314bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
315ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronenum adis16204_channel {
316ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	in_supply,
317ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	in_aux,
318ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	temp,
319ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	accel_x,
320ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	accel_y,
321ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron};
322ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron
323c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameronstatic u8 adis16204_addresses[5][3] = {
324ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	[in_supply] = { ADIS16204_SUPPLY_OUT },
325ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	[in_aux] = { ADIS16204_AUX_ADC },
326ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	[temp] = { ADIS16204_TEMP_OUT },
327c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron	[accel_x] = { ADIS16204_XACCL_OUT, ADIS16204_XACCL_NULL,
328c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron		      ADIS16204_X_PEAK_OUT },
329c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron	[accel_y] = { ADIS16204_XACCL_OUT, ADIS16204_YACCL_NULL,
330c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron		      ADIS16204_Y_PEAK_OUT },
331ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron};
332c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron
333ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_read_raw(struct iio_dev *indio_dev,
334ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			      struct iio_chan_spec const *chan,
335ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			      int *val, int *val2,
336ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			      long mask)
337ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron{
338ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	int ret;
339ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	int bits;
340ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	u8 addr;
341ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	s16 val16;
342c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron	int addrind;
343ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron
344ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	switch (mask) {
345ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	case 0:
346ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		mutex_lock(&indio_dev->mlock);
347ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		addr = adis16204_addresses[chan->address][0];
348ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16);
3498f89615528b11eabda68faaf2438d09c9565a125Dan Carpenter		if (ret) {
3508f89615528b11eabda68faaf2438d09c9565a125Dan Carpenter			mutex_unlock(&indio_dev->mlock);
351ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			return ret;
3528f89615528b11eabda68faaf2438d09c9565a125Dan Carpenter		}
353ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron
354ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		if (val16 & ADIS16204_ERROR_ACTIVE) {
355ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			ret = adis16204_check_status(indio_dev);
3568f89615528b11eabda68faaf2438d09c9565a125Dan Carpenter			if (ret) {
3578f89615528b11eabda68faaf2438d09c9565a125Dan Carpenter				mutex_unlock(&indio_dev->mlock);
358ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				return ret;
3598f89615528b11eabda68faaf2438d09c9565a125Dan Carpenter			}
360ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		}
361ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
362ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		if (chan->scan_type.sign == 's')
363ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			val16 = (s16)(val16 <<
364ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				      (16 - chan->scan_type.realbits)) >>
365ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				(16 - chan->scan_type.realbits);
366ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		*val = val16;
367ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		mutex_unlock(&indio_dev->mlock);
368ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		return IIO_VAL_INT;
369c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	case IIO_CHAN_INFO_SCALE:
370ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		switch (chan->type) {
3716835cb6b438b77ba82ad5a23944bbfb12128f5dbJonathan Cameron		case IIO_VOLTAGE:
372ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			*val = 0;
373ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			if (chan->channel == 0)
374ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				*val2 = 1220;
375ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			else
376ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				*val2 = 610;
377ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			return IIO_VAL_INT_PLUS_MICRO;
378ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		case IIO_TEMP:
379ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			*val = 0;
380ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			*val2 = -470000;
381ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			return IIO_VAL_INT_PLUS_MICRO;
382ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		case IIO_ACCEL:
383ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			*val = 0;
384ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			if (chan->channel == 'x')
385ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				*val2 = 17125;
386ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			else
387ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				*val2 = 8407;
388ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			return IIO_VAL_INT_PLUS_MICRO;
389ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		default:
390ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			return -EINVAL;
391ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		}
392ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		break;
393c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	case IIO_CHAN_INFO_OFFSET:
394ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		*val = 25;
395ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		return IIO_VAL_INT;
396c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	case IIO_CHAN_INFO_CALIBBIAS:
397c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	case IIO_CHAN_INFO_PEAK:
398c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron		if (mask == IIO_CHAN_INFO_CALIBBIAS) {
399ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			bits = 12;
400c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron			addrind = 1;
401c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron		} else { /* PEAK_SEPARATE */
402c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron			bits = 14;
403c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron			addrind = 2;
404c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron		}
405ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		mutex_lock(&indio_dev->mlock);
406c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron		addr = adis16204_addresses[chan->address][addrind];
407ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16);
408ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		if (ret) {
409ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			mutex_unlock(&indio_dev->mlock);
410ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			return ret;
411ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		}
412ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		val16 &= (1 << bits) - 1;
413ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
414ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		*val = val16;
415ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		mutex_unlock(&indio_dev->mlock);
416ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		return IIO_VAL_INT;
417ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	}
418ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	return -EINVAL;
419ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron}
420ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron
421ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_write_raw(struct iio_dev *indio_dev,
422ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			       struct iio_chan_spec const *chan,
423ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			       int val,
424ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			       int val2,
425ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			       long mask)
426ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron{
427ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	int bits;
428ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	s16 val16;
429ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	u8 addr;
430ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	switch (mask) {
431c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	case IIO_CHAN_INFO_CALIBBIAS:
432ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		switch (chan->type) {
433ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		case IIO_ACCEL:
434ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			bits = 12;
435ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			break;
436ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		default:
437ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			return -EINVAL;
438ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		};
439ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		val16 = val & ((1 << bits) - 1);
440ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		addr = adis16204_addresses[chan->address][1];
441ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		return adis16204_spi_write_reg_16(indio_dev, addr, val16);
442ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	}
443ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	return -EINVAL;
444ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron}
445ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron
446ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic struct iio_chan_spec adis16204_channels[] = {
4476835cb6b438b77ba82ad5a23944bbfb12128f5dbJonathan Cameron	IIO_CHAN(IIO_VOLTAGE, 0, 0, 0, "supply", 0, 0,
448c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron		 IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
449ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 in_supply, ADIS16204_SCAN_SUPPLY,
450ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 IIO_ST('u', 12, 16, 0), 0),
4516835cb6b438b77ba82ad5a23944bbfb12128f5dbJonathan Cameron	IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0,
452c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron		 IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
453ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 in_aux, ADIS16204_SCAN_AUX_ADC,
454ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 IIO_ST('u', 12, 16, 0), 0),
455ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
456c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron		 IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
457c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron		 IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
458ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 temp, ADIS16204_SCAN_TEMP,
459ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 IIO_ST('u', 12, 16, 0), 0),
460ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
461c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron		 IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
462c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron		 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
463c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron		 IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
464ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 accel_x, ADIS16204_SCAN_ACC_X,
465ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 IIO_ST('s', 14, 16, 0), 0),
466ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
467c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron		 IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
468c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron		 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
469c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron		 IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
470ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 accel_y, ADIS16204_SCAN_ACC_Y,
471ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 IIO_ST('s', 14, 16, 0), 0),
472ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	IIO_CHAN_SOFT_TIMESTAMP(5),
473ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron};
474c9b9e49e131ccf51aad931b490134f0d1f04a8e7Jonathan Cameron
475bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic struct attribute *adis16204_attributes[] = {
476bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	&iio_dev_attr_reset.dev_attr.attr,
477322c95636739420631e51f3d3f24132dc220762aJonathan Cameron	&iio_dev_attr_in_accel_xy.dev_attr.attr,
478322c95636739420631e51f3d3f24132dc220762aJonathan Cameron	&iio_dev_attr_in_accel_xypeak.dev_attr.attr,
479322c95636739420631e51f3d3f24132dc220762aJonathan Cameron	&iio_const_attr_in_accel_xy_scale.dev_attr.attr,
480bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	NULL
481bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song};
482bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
483bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic const struct attribute_group adis16204_attribute_group = {
484bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	.attrs = adis16204_attributes,
485bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song};
486bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
4876fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameronstatic const struct iio_info adis16204_info = {
4886fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.attrs = &adis16204_attribute_group,
4896fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.read_raw = &adis16204_read_raw,
4906fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.write_raw = &adis16204_write_raw,
4916fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.driver_module = THIS_MODULE,
4926fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron};
4936fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron
494bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic int __devinit adis16204_probe(struct spi_device *spi)
495bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
49626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	int ret;
4974de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	struct adis16204_state *st;
4984de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	struct iio_dev *indio_dev;
499bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
5004de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	/* setup the industrialio driver allocated elements */
5014de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	indio_dev = iio_allocate_device(sizeof(*st));
5024de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	if (indio_dev == NULL) {
503bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		ret = -ENOMEM;
5044de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron		goto error_ret;
505bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
5064de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	st = iio_priv(indio_dev);
5074de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	/* this is only used for removal purposes */
5084de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	spi_set_drvdata(spi, indio_dev);
509bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->us = spi;
510bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_init(&st->buf_lock);
511bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
5124de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	indio_dev->name = spi->dev.driver->name;
5134de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	indio_dev->dev.parent = &spi->dev;
5144de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	indio_dev->info = &adis16204_info;
5154de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	indio_dev->channels = adis16204_channels;
5164de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	indio_dev->num_channels = ARRAY_SIZE(adis16204_channels);
5174de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	indio_dev->modes = INDIO_DIRECT_MODE;
518bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
5194de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	ret = adis16204_configure_ring(indio_dev);
520bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret)
521bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto error_free_dev;
522bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
52314555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron	ret = iio_buffer_register(indio_dev,
52414555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron				  adis16204_channels,
52514555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron				  ARRAY_SIZE(adis16204_channels));
526bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret) {
527bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		printk(KERN_ERR "failed to initialize the ring\n");
528bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto error_unreg_ring_funcs;
529bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
530bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
531bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (spi->irq) {
5324de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron		ret = adis16204_probe_trigger(indio_dev);
533bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		if (ret)
53437f9d2714a0a95cf7f45e0ed9422eea80490a77cJonathan Cameron			goto error_uninitialize_ring;
535bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
536bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
537bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	/* Get the device into a sane initial state */
5384de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	ret = adis16204_initial_setup(indio_dev);
539bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret)
540bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto error_remove_trigger;
54126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	ret = iio_device_register(indio_dev);
54226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	if (ret)
54326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		goto error_remove_trigger;
54426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
545bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return 0;
546bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
547bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerror_remove_trigger:
5484de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	adis16204_remove_trigger(indio_dev);
549bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerror_uninitialize_ring:
55014555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron	iio_buffer_unregister(indio_dev);
551bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerror_unreg_ring_funcs:
5524de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	adis16204_unconfigure_ring(indio_dev);
553bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerror_free_dev:
55426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	iio_free_device(indio_dev);
555bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerror_ret:
556bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
557bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
558bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
559bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic int adis16204_remove(struct spi_device *spi)
560bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
5614de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	struct iio_dev *indio_dev = spi_get_drvdata(spi);
562bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
563d2fffd6c2fd60fe9ab63ef30758d9d43a5057549Jonathan Cameron	iio_device_unregister(indio_dev);
564bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	adis16204_remove_trigger(indio_dev);
56514555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron	iio_buffer_unregister(indio_dev);
566bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	adis16204_unconfigure_ring(indio_dev);
567d2fffd6c2fd60fe9ab63ef30758d9d43a5057549Jonathan Cameron	iio_free_device(indio_dev);
568bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
569bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return 0;
570bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
571bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
572bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic struct spi_driver adis16204_driver = {
573bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	.driver = {
574bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		.name = "adis16204",
575bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		.owner = THIS_MODULE,
576bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	},
577bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	.probe = adis16204_probe,
578bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	.remove = __devexit_p(adis16204_remove),
579bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song};
580ae6ae6fec3f7d6919e0146996df37b665c75f662Lars-Peter Clausenmodule_spi_driver(adis16204_driver);
581bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
582bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry SongMODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
583ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan CameronMODULE_DESCRIPTION("ADIS16204 High-g Digital Impact Sensor and Recorder");
584bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry SongMODULE_LICENSE("GPL v2");
58555e4390cb04e8b0fbae8983c3494c9e24132db1bLars-Peter ClausenMODULE_ALIAS("spi:adis16204");
586