adis16204_core.c revision 4de66bbb3eb1099a76e1bbf87e376c7a31dc30d5
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/gpio.h>
12bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/delay.h>
13bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/mutex.h>
14bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/device.h>
15bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/kernel.h>
16bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/spi/spi.h>
17bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/slab.h>
18bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/sysfs.h>
19bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include <linux/list.h>
20bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
21bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include "../iio.h"
22bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include "../sysfs.h"
23ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron#include "../ring_generic.h"
24bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include "accel.h"
25bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include "../adc/adc.h"
26bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
27bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#include "adis16204.h"
28bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
29bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song#define DRIVER_NAME		"adis16204"
30bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
31bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song/**
32bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * adis16204_spi_write_reg_8() - write single byte to a register
33bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * @dev: device associated with child of actual device (iio_dev or iio_trig)
34bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * @reg_address: the address of the register to be written
35bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * @val: the value to write
36bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song **/
37ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_spi_write_reg_8(struct iio_dev *indio_dev,
38bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		u8 reg_address,
39bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		u8 val)
40bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
41bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	int ret;
424de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	struct adis16204_state *st = iio_priv(indio_dev);
43bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
44bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_lock(&st->buf_lock);
45bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->tx[0] = ADIS16204_WRITE_REG(reg_address);
46bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->tx[1] = val;
47bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
48bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	ret = spi_write(st->us, st->tx, 2);
49bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_unlock(&st->buf_lock);
50bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
51bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
52bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
53bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
54bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song/**
55bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * adis16204_spi_write_reg_16() - write 2 bytes to a pair of registers
56ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron * @indio_dev: iio device associated with child of actual device
57bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * @reg_address: the address of the lower of the two registers. Second register
58bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song *               is assumed to have address one greater.
59bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * @val: value to be written
60bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song **/
61ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_spi_write_reg_16(struct iio_dev *indio_dev,
62bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		u8 lower_reg_address,
63bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		u16 value)
64bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
65bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	int ret;
66bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	struct spi_message msg;
674de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	struct adis16204_state *st = iio_priv(indio_dev);
68bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	struct spi_transfer xfers[] = {
69bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		{
70bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.tx_buf = st->tx,
71bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.bits_per_word = 8,
72bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.len = 2,
73bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.cs_change = 1,
74bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		}, {
75bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.tx_buf = st->tx + 2,
76bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.bits_per_word = 8,
77bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.len = 2,
78bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.cs_change = 1,
79bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		},
80bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	};
81bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
82bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_lock(&st->buf_lock);
83bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->tx[0] = ADIS16204_WRITE_REG(lower_reg_address);
84bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->tx[1] = value & 0xFF;
85bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->tx[2] = ADIS16204_WRITE_REG(lower_reg_address + 1);
86bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->tx[3] = (value >> 8) & 0xFF;
87bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
88bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	spi_message_init(&msg);
89bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	spi_message_add_tail(&xfers[0], &msg);
90bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	spi_message_add_tail(&xfers[1], &msg);
91bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	ret = spi_sync(st->us, &msg);
92bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_unlock(&st->buf_lock);
93bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
94bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
95bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
96bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
97bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song/**
98bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * adis16204_spi_read_reg_16() - read 2 bytes from a 16-bit register
99ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron * @indio_dev: iio device associated with child of actual device
100bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * @reg_address: the address of the lower of the two registers. Second register
101bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song *               is assumed to have address one greater.
102bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song * @val: somewhere to pass back the value read
103bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song **/
104ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_spi_read_reg_16(struct iio_dev *indio_dev,
105ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				     u8 lower_reg_address,
106ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				     u16 *val)
107bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
108bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	struct spi_message msg;
1094de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	struct adis16204_state *st = iio_priv(indio_dev);
110bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	int ret;
111bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	struct spi_transfer xfers[] = {
112bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		{
113bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.tx_buf = st->tx,
114bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.bits_per_word = 8,
115bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.len = 2,
116bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.cs_change = 1,
117bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.delay_usecs = 20,
118bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		}, {
119bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.rx_buf = st->rx,
120bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.bits_per_word = 8,
121bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.len = 2,
122bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			.delay_usecs = 20,
123bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		},
124bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	};
125bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
126bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_lock(&st->buf_lock);
127bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->tx[0] = ADIS16204_READ_REG(lower_reg_address);
128bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->tx[1] = 0;
129bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
130bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	spi_message_init(&msg);
131bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	spi_message_add_tail(&xfers[0], &msg);
132bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	spi_message_add_tail(&xfers[1], &msg);
133bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	ret = spi_sync(st->us, &msg);
134bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret) {
135bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
136bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song				lower_reg_address);
137bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto error_ret;
138bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
139bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	*val = (st->rx[0] << 8) | st->rx[1];
140bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
141bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerror_ret:
142bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_unlock(&st->buf_lock);
143bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
144bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
145bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
146ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_check_status(struct iio_dev *indio_dev)
147bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
148ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	u16 status;
149bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	int ret;
150bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
151ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_spi_read_reg_16(indio_dev,
152ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron					ADIS16204_DIAG_STAT, &status);
153ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	if (ret < 0) {
154ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "Reading status failed\n");
155bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto error_ret;
156bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
157ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = status & 0x1F;
158bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
159ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	if (status & ADIS16204_DIAG_STAT_SELFTEST_FAIL)
160ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "Self test failure\n");
161ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	if (status & ADIS16204_DIAG_STAT_SPI_FAIL)
162ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "SPI failure\n");
163ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	if (status & ADIS16204_DIAG_STAT_FLASH_UPT)
164ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "Flash update failed\n");
165ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	if (status & ADIS16204_DIAG_STAT_POWER_HIGH)
166ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "Power supply above 3.625V\n");
167ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	if (status & ADIS16204_DIAG_STAT_POWER_LOW)
168ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "Power supply below 2.975V\n");
169bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
170ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronerror_ret:
171bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
172bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
173bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
174bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic ssize_t adis16204_read_14bit_signed(struct device *dev,
175bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		struct device_attribute *attr,
176bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		char *buf)
177bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
178bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	struct iio_dev *indio_dev = dev_get_drvdata(dev);
179bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
180bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	s16 val = 0;
181bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	ssize_t ret;
182bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
183bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_lock(&indio_dev->mlock);
184bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
185ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_spi_read_reg_16(indio_dev,
186ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron					this_attr->address, (u16 *)&val);
187bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (!ret) {
188bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		if (val & ADIS16204_ERROR_ACTIVE)
189ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			adis16204_check_status(indio_dev);
190bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
191bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		val = ((s16)(val << 2) >> 2);
192bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		ret = sprintf(buf, "%d\n", val);
193bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
194bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
195bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_unlock(&indio_dev->mlock);
196bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
197bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
198bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
199bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
200ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_reset(struct iio_dev *indio_dev)
201bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
202bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	int ret;
203ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_spi_write_reg_8(indio_dev,
204bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			ADIS16204_GLOB_CMD,
205bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			ADIS16204_GLOB_CMD_SW_RESET);
206bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret)
207ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "problem resetting device");
208bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
209bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
210bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
211bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
212bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic ssize_t adis16204_write_reset(struct device *dev,
213bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		struct device_attribute *attr,
214bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		const char *buf, size_t len)
215bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
216ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
217ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron
218bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (len < 1)
219bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		return -EINVAL;
220bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	switch (buf[0]) {
221bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	case '1':
222bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	case 'y':
223bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	case 'Y':
224ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		return adis16204_reset(indio_dev);
225bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
226bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return -EINVAL;
227bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
228bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
229ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronint adis16204_set_irq(struct iio_dev *indio_dev, bool enable)
230bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
231bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	int ret = 0;
232bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	u16 msc;
233bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
234ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_spi_read_reg_16(indio_dev, ADIS16204_MSC_CTRL, &msc);
235bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret)
236bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto error_ret;
237bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
238bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	msc |= ADIS16204_MSC_CTRL_ACTIVE_HIGH;
239bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	msc &= ~ADIS16204_MSC_CTRL_DATA_RDY_DIO2;
240bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (enable)
241bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		msc |= ADIS16204_MSC_CTRL_DATA_RDY_EN;
242bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	else
243bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		msc &= ~ADIS16204_MSC_CTRL_DATA_RDY_EN;
244bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
245ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_spi_write_reg_16(indio_dev, ADIS16204_MSC_CTRL, msc);
246bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
247bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerror_ret:
248bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
249bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
250bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
251ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_self_test(struct iio_dev *indio_dev)
252bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
253bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	int ret;
254ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_spi_write_reg_16(indio_dev,
255bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			ADIS16204_MSC_CTRL,
256bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			ADIS16204_MSC_CTRL_SELF_TEST_EN);
257bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret) {
258ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "problem starting self test");
259bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto err_ret;
260bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
261bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
262ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	adis16204_check_status(indio_dev);
263bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
264bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerr_ret:
265bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
266bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
267bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
268ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_initial_setup(struct iio_dev *indio_dev)
269bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
270bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	int ret;
271bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
272bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	/* Disable IRQ */
273ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_set_irq(indio_dev, false);
274bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret) {
275ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "disable irq failed");
276bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto err_ret;
277bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
278bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
279bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	/* Do self test */
280ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_self_test(indio_dev);
281bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret) {
282ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "self test failure");
283bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto err_ret;
284bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
285bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
286bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	/* Read status register to check the result */
287ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	ret = adis16204_check_status(indio_dev);
288bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret) {
289ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		adis16204_reset(indio_dev);
290ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		dev_err(&indio_dev->dev, "device not playing ball -> reset");
291bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		msleep(ADIS16204_STARTUP_DELAY);
292ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		ret = adis16204_check_status(indio_dev);
293bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		if (ret) {
294ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			dev_err(&indio_dev->dev, "giving up");
295bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song			goto err_ret;
296bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		}
297bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
298bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
299bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerr_ret:
300bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
301bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
302bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic IIO_DEV_ATTR_ACCEL_XY(adis16204_read_14bit_signed,
303bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		ADIS16204_XY_RSS_OUT);
304bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic IIO_DEV_ATTR_ACCEL_XPEAK(adis16204_read_14bit_signed,
305bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		ADIS16204_X_PEAK_OUT);
306bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic IIO_DEV_ATTR_ACCEL_YPEAK(adis16204_read_14bit_signed,
307bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		ADIS16204_Y_PEAK_OUT);
308bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic IIO_DEV_ATTR_ACCEL_XYPEAK(adis16204_read_14bit_signed,
309bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		ADIS16204_XY_PEAK_OUT);
310bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic IIO_CONST_ATTR(accel_xy_scale, "0.017125");
311bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
312bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16204_write_reset, 0);
313bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
314ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronenum adis16204_channel {
315ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	in_supply,
316ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	in_aux,
317ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	temp,
318ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	accel_x,
319ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	accel_y,
320ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron};
321ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron
322ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic u8 adis16204_addresses[5][2] = {
323ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	[in_supply] = { ADIS16204_SUPPLY_OUT },
324ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	[in_aux] = { ADIS16204_AUX_ADC },
325ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	[temp] = { ADIS16204_TEMP_OUT },
326ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	[accel_x] = { ADIS16204_XACCL_OUT, ADIS16204_XACCL_NULL },
327ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	[accel_y] = { ADIS16204_XACCL_OUT, ADIS16204_YACCL_NULL },
328ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron};
329ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_read_raw(struct iio_dev *indio_dev,
330ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			      struct iio_chan_spec const *chan,
331ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			      int *val, int *val2,
332ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			      long mask)
333ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron{
334ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	int ret;
335ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	int bits;
336ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	u8 addr;
337ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	s16 val16;
338ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron
339ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	switch (mask) {
340ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	case 0:
341ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		mutex_lock(&indio_dev->mlock);
342ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		addr = adis16204_addresses[chan->address][0];
343ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16);
344ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		if (ret)
345ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			return ret;
346ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron
347ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		if (val16 & ADIS16204_ERROR_ACTIVE) {
348ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			ret = adis16204_check_status(indio_dev);
349ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			if (ret)
350ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				return ret;
351ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		}
352ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
353ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		if (chan->scan_type.sign == 's')
354ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			val16 = (s16)(val16 <<
355ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				      (16 - chan->scan_type.realbits)) >>
356ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				(16 - chan->scan_type.realbits);
357ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		*val = val16;
358ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		mutex_unlock(&indio_dev->mlock);
359ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		return IIO_VAL_INT;
360ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
361ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		switch (chan->type) {
362ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		case IIO_IN:
363ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			*val = 0;
364ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			if (chan->channel == 0)
365ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				*val2 = 1220;
366ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			else
367ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				*val2 = 610;
368ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			return IIO_VAL_INT_PLUS_MICRO;
369ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		case IIO_TEMP:
370ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			*val = 0;
371ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			*val2 = -470000;
372ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			return IIO_VAL_INT_PLUS_MICRO;
373ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		case IIO_ACCEL:
374ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			*val = 0;
375ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			if (chan->channel == 'x')
376ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				*val2 = 17125;
377ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			else
378ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron				*val2 = 8407;
379ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			return IIO_VAL_INT_PLUS_MICRO;
380ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		default:
381ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			return -EINVAL;
382ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		}
383ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		break;
384ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
385ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		*val = 25;
386ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		return IIO_VAL_INT;
387ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
388ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		switch (chan->type) {
389ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		case IIO_ACCEL:
390ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			bits = 12;
391ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			break;
392ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		default:
393ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			return -EINVAL;
394ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		};
395ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		mutex_lock(&indio_dev->mlock);
396ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		addr = adis16204_addresses[chan->address][1];
397ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16);
398ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		if (ret) {
399ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			mutex_unlock(&indio_dev->mlock);
400ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			return ret;
401ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		}
402ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		val16 &= (1 << bits) - 1;
403ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
404ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		*val = val16;
405ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		mutex_unlock(&indio_dev->mlock);
406ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		return IIO_VAL_INT;
407ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	}
408ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	return -EINVAL;
409ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron}
410ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron
411ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic int adis16204_write_raw(struct iio_dev *indio_dev,
412ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			       struct iio_chan_spec const *chan,
413ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			       int val,
414ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			       int val2,
415ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			       long mask)
416ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron{
417ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	int bits;
418ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	s16 val16;
419ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	u8 addr;
420ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	switch (mask) {
421ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
422ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		switch (chan->type) {
423ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		case IIO_ACCEL:
424ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			bits = 12;
425ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			break;
426ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		default:
427ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron			return -EINVAL;
428ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		};
429ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		val16 = val & ((1 << bits) - 1);
430ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		addr = adis16204_addresses[chan->address][1];
431ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		return adis16204_spi_write_reg_16(indio_dev, addr, val16);
432ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	}
433ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	return -EINVAL;
434ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron}
435ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron
436ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameronstatic struct iio_chan_spec adis16204_channels[] = {
437ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	IIO_CHAN(IIO_IN, 0, 0, 0, "supply", 0, 0,
438ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
439ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 in_supply, ADIS16204_SCAN_SUPPLY,
440ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 IIO_ST('u', 12, 16, 0), 0),
441ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
442ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
443ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 in_aux, ADIS16204_SCAN_AUX_ADC,
444ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 IIO_ST('u', 12, 16, 0), 0),
445ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
446ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 (1 << IIO_CHAN_INFO_SCALE_SEPARATE) |
447ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 (1 << IIO_CHAN_INFO_OFFSET_SEPARATE),
448ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 temp, ADIS16204_SCAN_TEMP,
449ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 IIO_ST('u', 12, 16, 0), 0),
450ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
451ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 (1 << IIO_CHAN_INFO_SCALE_SEPARATE) |
452ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
453ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 accel_x, ADIS16204_SCAN_ACC_X,
454ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 IIO_ST('s', 14, 16, 0), 0),
455ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
456ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 (1 << IIO_CHAN_INFO_SCALE_SEPARATE) |
457ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
458ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 accel_y, ADIS16204_SCAN_ACC_Y,
459ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron		 IIO_ST('s', 14, 16, 0), 0),
460ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron	IIO_CHAN_SOFT_TIMESTAMP(5),
461ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron};
462bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic struct attribute *adis16204_attributes[] = {
463bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	&iio_dev_attr_reset.dev_attr.attr,
464bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	&iio_dev_attr_accel_xy.dev_attr.attr,
465bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	&iio_dev_attr_accel_xpeak.dev_attr.attr,
466bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	&iio_dev_attr_accel_ypeak.dev_attr.attr,
467bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	&iio_dev_attr_accel_xypeak.dev_attr.attr,
468bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	&iio_const_attr_accel_xy_scale.dev_attr.attr,
469bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	NULL
470bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song};
471bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
472bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic const struct attribute_group adis16204_attribute_group = {
473bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	.attrs = adis16204_attributes,
474bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song};
475bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
4766fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameronstatic const struct iio_info adis16204_info = {
4776fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.attrs = &adis16204_attribute_group,
4786fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.read_raw = &adis16204_read_raw,
4796fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.write_raw = &adis16204_write_raw,
4806fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.driver_module = THIS_MODULE,
4816fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron};
4826fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron
483bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic int __devinit adis16204_probe(struct spi_device *spi)
484bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
485bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	int ret, regdone = 0;
4864de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	struct adis16204_state *st;
4874de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	struct iio_dev *indio_dev;
488bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
4894de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	/* setup the industrialio driver allocated elements */
4904de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	indio_dev = iio_allocate_device(sizeof(*st));
4914de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	if (indio_dev == NULL) {
492bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		ret = -ENOMEM;
4934de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron		goto error_ret;
494bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
4954de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	st = iio_priv(indio_dev);
4964de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	/* this is only used for removal purposes */
4974de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	spi_set_drvdata(spi, indio_dev);
498bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	st->us = spi;
499bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	mutex_init(&st->buf_lock);
500bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
5014de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	indio_dev->name = spi->dev.driver->name;
5024de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	indio_dev->dev.parent = &spi->dev;
5034de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	indio_dev->info = &adis16204_info;
5044de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	indio_dev->channels = adis16204_channels;
5054de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	indio_dev->num_channels = ARRAY_SIZE(adis16204_channels);
5064de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	indio_dev->modes = INDIO_DIRECT_MODE;
507bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
5084de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	ret = adis16204_configure_ring(indio_dev);
509bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret)
510bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto error_free_dev;
511bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
5124de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	ret = iio_device_register(indio_dev);
513bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret)
514bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto error_unreg_ring_funcs;
515bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	regdone = 1;
516bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
5174de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
518ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron					  adis16204_channels,
519ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan Cameron					  ARRAY_SIZE(adis16204_channels));
520bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret) {
521bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		printk(KERN_ERR "failed to initialize the ring\n");
522bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto error_unreg_ring_funcs;
523bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
524bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
525bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (spi->irq) {
5264de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron		ret = adis16204_probe_trigger(indio_dev);
527bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		if (ret)
52837f9d2714a0a95cf7f45e0ed9422eea80490a77cJonathan Cameron			goto error_uninitialize_ring;
529bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	}
530bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
531bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	/* Get the device into a sane initial state */
5324de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	ret = adis16204_initial_setup(indio_dev);
533bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (ret)
534bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		goto error_remove_trigger;
535bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return 0;
536bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
537bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerror_remove_trigger:
5384de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	adis16204_remove_trigger(indio_dev);
539bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerror_uninitialize_ring:
5404de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	iio_ring_buffer_unregister(indio_dev->ring);
541bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerror_unreg_ring_funcs:
5424de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	adis16204_unconfigure_ring(indio_dev);
543bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerror_free_dev:
544bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	if (regdone)
5454de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron		iio_device_unregister(indio_dev);
546bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	else
5474de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron		iio_free_device(indio_dev);
548bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songerror_ret:
549bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return ret;
550bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
551bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
552bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic int adis16204_remove(struct spi_device *spi)
553bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
5544de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	struct iio_dev *indio_dev = spi_get_drvdata(spi);
555bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
556bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	adis16204_remove_trigger(indio_dev);
5574de66bbb3eb1099a76e1bbf87e376c7a31dc30d5Jonathan Cameron	iio_ring_buffer_unregister(indio_dev->ring);
558bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	iio_device_unregister(indio_dev);
559bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	adis16204_unconfigure_ring(indio_dev);
560bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
561bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return 0;
562bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
563bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
564bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic struct spi_driver adis16204_driver = {
565bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	.driver = {
566bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		.name = "adis16204",
567bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song		.owner = THIS_MODULE,
568bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	},
569bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	.probe = adis16204_probe,
570bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	.remove = __devexit_p(adis16204_remove),
571bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song};
572bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
573bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic __init int adis16204_init(void)
574bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
575bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	return spi_register_driver(&adis16204_driver);
576bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
577bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songmodule_init(adis16204_init);
578bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
579bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songstatic __exit void adis16204_exit(void)
580bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song{
581bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song	spi_unregister_driver(&adis16204_driver);
582bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song}
583bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Songmodule_exit(adis16204_exit);
584bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry Song
585bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry SongMODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
586ad3eb9ab1276cc69bb9cc72dffc074d1a317a6c0Jonathan CameronMODULE_DESCRIPTION("ADIS16204 High-g Digital Impact Sensor and Recorder");
587bb6f19eafe3a1a5dd937ce66668e70aeaa1b0bf4Barry SongMODULE_LICENSE("GPL v2");
588