12c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song/*
22c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song * ADIS16240 Programmable Impact Sensor and Recorder driver
32c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song *
42c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song * Copyright 2010 Analog Devices Inc.
52c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song *
62c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song * Licensed under the GPL-2 or later.
72c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song */
82c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
92c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song#include <linux/interrupt.h>
102c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song#include <linux/irq.h>
112c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song#include <linux/gpio.h>
122c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song#include <linux/delay.h>
132c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song#include <linux/mutex.h>
142c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song#include <linux/device.h>
152c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song#include <linux/kernel.h>
162c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song#include <linux/spi/spi.h>
171cb6c1f59431f16e46f0d07398cc789ee0a26731Mike Frysinger#include <linux/slab.h>
182c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song#include <linux/sysfs.h>
192c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song#include <linux/list.h>
2099c978529a40132a6f7a5f136b4362b56fc88d8cPaul Gortmaker#include <linux/module.h>
212c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
2206458e277eac2b8761b0a04d3c808d57be281a2eJonathan Cameron#include <linux/iio/iio.h>
2306458e277eac2b8761b0a04d3c808d57be281a2eJonathan Cameron#include <linux/iio/sysfs.h>
2406458e277eac2b8761b0a04d3c808d57be281a2eJonathan Cameron#include <linux/iio/buffer.h>
25ec04cb048d79cd778c06e28f34395a46d774800dLars-Peter Clausen#include <linux/iio/imu/adis.h>
262c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
272c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song#include "adis16240.h"
282c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
292c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Songstatic ssize_t adis16240_spi_read_signed(struct device *dev,
302c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song		struct device_attribute *attr,
312c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song		char *buf,
322c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song		unsigned bits)
332c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song{
344b522ce709fd0591969ac9e8cfb52a8e44bac4b0Lars-Peter Clausen	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
355cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	struct adis *st = iio_priv(indio_dev);
362c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	int ret;
372c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	s16 val = 0;
382c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	unsigned shift = 16 - bits;
392c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
402c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
415cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	ret = adis_read_reg_16(st,
42cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron					this_attr->address, (u16 *)&val);
432c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	if (ret)
442c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song		return ret;
452c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
462c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	if (val & ADIS16240_ERROR_ACTIVE)
475cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen		adis_check_status(st);
482c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
492c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	val = ((s16)(val << shift) >> shift);
502c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	return sprintf(buf, "%d\n", val);
512c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song}
522c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
532c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Songstatic ssize_t adis16240_read_12bit_signed(struct device *dev,
542c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song		struct device_attribute *attr,
552c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song		char *buf)
562c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song{
572c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	ssize_t ret;
584b522ce709fd0591969ac9e8cfb52a8e44bac4b0Lars-Peter Clausen	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
592c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
602c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	/* Take the iio_dev status lock */
612c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	mutex_lock(&indio_dev->mlock);
622c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	ret =  adis16240_spi_read_signed(dev, attr, buf, 12);
632c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	mutex_unlock(&indio_dev->mlock);
642c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
652c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	return ret;
662c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song}
672c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
68322c95636739420631e51f3d3f24132dc220762aJonathan Cameronstatic IIO_DEVICE_ATTR(in_accel_xyz_squared_peak_raw, S_IRUGO,
692c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song		       adis16240_read_12bit_signed, NULL,
702c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song		       ADIS16240_XYZPEAK_OUT);
712c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
7251a0a5b02132f880ff2d2bd7dbbe73b2dfd708a4Manuel Stahlstatic IIO_CONST_ATTR_SAMP_FREQ_AVAIL("4096");
732c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
745cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausenstatic const u8 adis16240_addresses[][2] = {
755cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	[ADIS16240_SCAN_ACC_X] = { ADIS16240_XACCL_OFF, ADIS16240_XPEAK_OUT },
765cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	[ADIS16240_SCAN_ACC_Y] = { ADIS16240_YACCL_OFF, ADIS16240_YPEAK_OUT },
775cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	[ADIS16240_SCAN_ACC_Z] = { ADIS16240_ZACCL_OFF, ADIS16240_ZPEAK_OUT },
78cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron};
79cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron
80cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameronstatic int adis16240_read_raw(struct iio_dev *indio_dev,
81cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron			      struct iio_chan_spec const *chan,
82cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron			      int *val, int *val2,
83cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron			      long mask)
84cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron{
855cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	struct adis *st = iio_priv(indio_dev);
86cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron	int ret;
87cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron	int bits;
88cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron	u8 addr;
89cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron	s16 val16;
90cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron
91cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron	switch (mask) {
9231313fc64d51bbd8979997f9d6670cc882c5f963Jonathan Cameron	case IIO_CHAN_INFO_RAW:
935cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen		return adis_single_conversion(indio_dev, chan,
945cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen				ADIS16240_ERROR_ACTIVE, val);
95c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	case IIO_CHAN_INFO_SCALE:
96cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		switch (chan->type) {
976835cb6b438b77ba82ad5a23944bbfb12128f5dbJonathan Cameron		case IIO_VOLTAGE:
98acba41f81f4380ad24905df4c3c0ad7f272b338fLars-Peter Clausen			if (chan->channel == 0) {
99acba41f81f4380ad24905df4c3c0ad7f272b338fLars-Peter Clausen				*val = 4;
100acba41f81f4380ad24905df4c3c0ad7f272b338fLars-Peter Clausen				*val2 = 880000; /* 4.88 mV */
101acba41f81f4380ad24905df4c3c0ad7f272b338fLars-Peter Clausen				return IIO_VAL_INT_PLUS_MICRO;
102acba41f81f4380ad24905df4c3c0ad7f272b338fLars-Peter Clausen			}
103b5e736bd6881d9e78384eed8ab7fdcb586f0e402Tapasweni Pathak			return -EINVAL;
104cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		case IIO_TEMP:
105acba41f81f4380ad24905df4c3c0ad7f272b338fLars-Peter Clausen			*val = 244; /* 0.244 C */
106acba41f81f4380ad24905df4c3c0ad7f272b338fLars-Peter Clausen			*val2 = 0;
107cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron			return IIO_VAL_INT_PLUS_MICRO;
108cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		case IIO_ACCEL:
109cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron			*val = 0;
110acba41f81f4380ad24905df4c3c0ad7f272b338fLars-Peter Clausen			*val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */
111cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron			return IIO_VAL_INT_PLUS_MICRO;
112cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		default:
113cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron			return -EINVAL;
114cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		}
115cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		break;
116c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	case IIO_CHAN_INFO_PEAK_SCALE:
117acba41f81f4380ad24905df4c3c0ad7f272b338fLars-Peter Clausen		*val = 0;
118acba41f81f4380ad24905df4c3c0ad7f272b338fLars-Peter Clausen		*val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */
119cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		return IIO_VAL_INT_PLUS_MICRO;
120c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	case IIO_CHAN_INFO_OFFSET:
121acba41f81f4380ad24905df4c3c0ad7f272b338fLars-Peter Clausen		*val = 25000 / 244 - 0x133; /* 25 C = 0x133 */
122cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		return IIO_VAL_INT;
123c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	case IIO_CHAN_INFO_CALIBBIAS:
124cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		bits = 10;
125cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		mutex_lock(&indio_dev->mlock);
1265cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen		addr = adis16240_addresses[chan->scan_index][0];
1275cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen		ret = adis_read_reg_16(st, addr, &val16);
128cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		if (ret) {
129cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron			mutex_unlock(&indio_dev->mlock);
130cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron			return ret;
131cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		}
132cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		val16 &= (1 << bits) - 1;
133cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
134cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		*val = val16;
135cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		mutex_unlock(&indio_dev->mlock);
136cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		return IIO_VAL_INT;
137c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	case IIO_CHAN_INFO_PEAK:
138cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		bits = 10;
139cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		mutex_lock(&indio_dev->mlock);
1405cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen		addr = adis16240_addresses[chan->scan_index][1];
1415cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen		ret = adis_read_reg_16(st, addr, &val16);
142cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		if (ret) {
143cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron			mutex_unlock(&indio_dev->mlock);
144cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron			return ret;
145cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		}
146cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		val16 &= (1 << bits) - 1;
147cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
148cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		*val = val16;
149cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		mutex_unlock(&indio_dev->mlock);
150cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		return IIO_VAL_INT;
151cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron	}
152cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron	return -EINVAL;
153cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron}
154cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron
155cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameronstatic int adis16240_write_raw(struct iio_dev *indio_dev,
156cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron			       struct iio_chan_spec const *chan,
157cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron			       int val,
158cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron			       int val2,
159cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron			       long mask)
160cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron{
1615cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	struct adis *st = iio_priv(indio_dev);
162cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron	int bits = 10;
163cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron	s16 val16;
164cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron	u8 addr;
165d7b79519faa926a9d6d1cdebfddea7a58a9951f3Murilo Opsfelder Araujo
166cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron	switch (mask) {
167c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	case IIO_CHAN_INFO_CALIBBIAS:
168cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron		val16 = val & ((1 << bits) - 1);
1695cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen		addr = adis16240_addresses[chan->scan_index][0];
1705cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen		return adis_write_reg_16(st, addr, val16);
171cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron	}
172cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron	return -EINVAL;
173cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron}
174cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron
175f4e4b9558bc696cc89de460e754d3fecb50b13cbLars-Peter Clausenstatic const struct iio_chan_spec adis16240_channels[] = {
17682695ef549b5299d3d9e088d6648289bda8ef3d8Jonathan Cameron	ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 0, 10),
17782695ef549b5299d3d9e088d6648289bda8ef3d8Jonathan Cameron	ADIS_AUX_ADC_CHAN(ADIS16240_AUX_ADC, ADIS16240_SCAN_AUX_ADC, 0, 10),
1785cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	ADIS_ACCEL_CHAN(X, ADIS16240_XACCL_OUT, ADIS16240_SCAN_ACC_X,
17982695ef549b5299d3d9e088d6648289bda8ef3d8Jonathan Cameron		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10),
1805cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	ADIS_ACCEL_CHAN(Y, ADIS16240_YACCL_OUT, ADIS16240_SCAN_ACC_Y,
18182695ef549b5299d3d9e088d6648289bda8ef3d8Jonathan Cameron		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10),
1825cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	ADIS_ACCEL_CHAN(Z, ADIS16240_ZACCL_OUT, ADIS16240_SCAN_ACC_Z,
18382695ef549b5299d3d9e088d6648289bda8ef3d8Jonathan Cameron		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10),
18482695ef549b5299d3d9e088d6648289bda8ef3d8Jonathan Cameron	ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 0, 10),
185cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron	IIO_CHAN_SOFT_TIMESTAMP(6)
186cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron};
187cd69f57dee75cb27337bf5438359aae86503873fJonathan Cameron
1882c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Songstatic struct attribute *adis16240_attributes[] = {
189322c95636739420631e51f3d3f24132dc220762aJonathan Cameron	&iio_dev_attr_in_accel_xyz_squared_peak_raw.dev_attr.attr,
19051a0a5b02132f880ff2d2bd7dbbe73b2dfd708a4Manuel Stahl	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
1912c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	NULL
1922c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song};
1932c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
1942c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Songstatic const struct attribute_group adis16240_attribute_group = {
1952c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	.attrs = adis16240_attributes,
1962c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song};
1972c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
1986fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameronstatic const struct iio_info adis16240_info = {
1996fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.attrs = &adis16240_attribute_group,
2006fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.read_raw = &adis16240_read_raw,
2016fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.write_raw = &adis16240_write_raw,
202aacff892cbd5c6b1904a3906219548a65018d750Lars-Peter Clausen	.update_scan_mode = adis_update_scan_mode,
2036fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.driver_module = THIS_MODULE,
2046fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron};
2056fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron
2065cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausenstatic const char * const adis16240_status_error_msgs[] = {
2075cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	[ADIS16240_DIAG_STAT_PWRON_FAIL_BIT] = "Power on, self-test failed",
2085cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	[ADIS16240_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
2095cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	[ADIS16240_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
2105cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	[ADIS16240_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
2115cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	[ADIS16240_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.225V",
2125cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen};
2135cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen
2145cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausenstatic const struct adis_data adis16240_data = {
2155cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	.write_delay = 35,
2165cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	.read_delay = 35,
2175cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	.msc_ctrl_reg = ADIS16240_MSC_CTRL,
2185cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	.glob_cmd_reg = ADIS16240_GLOB_CMD,
2195cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	.diag_stat_reg = ADIS16240_DIAG_STAT,
2205cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen
2215cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	.self_test_mask = ADIS16240_MSC_CTRL_SELF_TEST_EN,
2225cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	.startup_delay = ADIS16240_STARTUP_DELAY,
2235cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen
2245cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	.status_error_msgs = adis16240_status_error_msgs,
2255cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	.status_error_mask = BIT(ADIS16240_DIAG_STAT_PWRON_FAIL_BIT) |
2265cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen		BIT(ADIS16240_DIAG_STAT_SPI_FAIL_BIT) |
2275cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen		BIT(ADIS16240_DIAG_STAT_FLASH_UPT_BIT) |
2285cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen		BIT(ADIS16240_DIAG_STAT_POWER_HIGH_BIT) |
2295cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen		BIT(ADIS16240_DIAG_STAT_POWER_LOW_BIT),
2305cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen};
2315cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen
2324ae1c61ff2ba4fea4e4c1a045cb1f34520608789Bill Pembertonstatic int adis16240_probe(struct spi_device *spi)
2332c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song{
23426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	int ret;
2355cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	struct adis *st;
236a22ff7066c0561c2aa92967f0eed4a1c77f088e7Jonathan Cameron	struct iio_dev *indio_dev;
237a22ff7066c0561c2aa92967f0eed4a1c77f088e7Jonathan Cameron
238a22ff7066c0561c2aa92967f0eed4a1c77f088e7Jonathan Cameron	/* setup the industrialio driver allocated elements */
239e8cac7f61452d45cd4bca8cb11c139edc9633f38Sachin Kamat	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
240e8cac7f61452d45cd4bca8cb11c139edc9633f38Sachin Kamat	if (!indio_dev)
241e8cac7f61452d45cd4bca8cb11c139edc9633f38Sachin Kamat		return -ENOMEM;
242a22ff7066c0561c2aa92967f0eed4a1c77f088e7Jonathan Cameron	st = iio_priv(indio_dev);
2432c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	/* this is only used for removal purposes */
244a22ff7066c0561c2aa92967f0eed4a1c77f088e7Jonathan Cameron	spi_set_drvdata(spi, indio_dev);
2452c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
246a22ff7066c0561c2aa92967f0eed4a1c77f088e7Jonathan Cameron	indio_dev->name = spi->dev.driver->name;
247a22ff7066c0561c2aa92967f0eed4a1c77f088e7Jonathan Cameron	indio_dev->dev.parent = &spi->dev;
248a22ff7066c0561c2aa92967f0eed4a1c77f088e7Jonathan Cameron	indio_dev->info = &adis16240_info;
249a22ff7066c0561c2aa92967f0eed4a1c77f088e7Jonathan Cameron	indio_dev->channels = adis16240_channels;
250a22ff7066c0561c2aa92967f0eed4a1c77f088e7Jonathan Cameron	indio_dev->num_channels = ARRAY_SIZE(adis16240_channels);
251a22ff7066c0561c2aa92967f0eed4a1c77f088e7Jonathan Cameron	indio_dev->modes = INDIO_DIRECT_MODE;
2522c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
2535cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	ret = adis_init(st, indio_dev, spi, &adis16240_data);
2545cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	if (ret)
255e8cac7f61452d45cd4bca8cb11c139edc9633f38Sachin Kamat		return ret;
2565cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL);
2572c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	if (ret)
258e8cac7f61452d45cd4bca8cb11c139edc9633f38Sachin Kamat		return ret;
2592c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
2602c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	/* Get the device into a sane initial state */
2615cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	ret = adis_initial_startup(st);
2622c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	if (ret)
2635cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen		goto error_cleanup_buffer_trigger;
26426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	ret = iio_device_register(indio_dev);
26526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	if (ret)
2665cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen		goto error_cleanup_buffer_trigger;
2672c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	return 0;
2682c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
2695cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausenerror_cleanup_buffer_trigger:
2705cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	adis_cleanup_buffer_and_trigger(st, indio_dev);
2712c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	return ret;
2722c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song}
2732c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
274447d4f29ee3fa62f13c65688bb7b74d5a9a0d767Bill Pembertonstatic int adis16240_remove(struct spi_device *spi)
2752c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song{
276a22ff7066c0561c2aa92967f0eed4a1c77f088e7Jonathan Cameron	struct iio_dev *indio_dev = spi_get_drvdata(spi);
2775cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	struct adis *st = iio_priv(indio_dev);
2782c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
279d2fffd6c2fd60fe9ab63ef30758d9d43a5057549Jonathan Cameron	iio_device_unregister(indio_dev);
2805cb7cb1191fc8fc0fcf9a1cc43b9ed7168c5c44aLars-Peter Clausen	adis_cleanup_buffer_and_trigger(st, indio_dev);
2812c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
2822c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	return 0;
2832c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song}
2842c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
2852c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Songstatic struct spi_driver adis16240_driver = {
2862c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	.driver = {
2872c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song		.name = "adis16240",
2882c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song		.owner = THIS_MODULE,
2892c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	},
2902c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song	.probe = adis16240_probe,
291e543acf07db78cfc135e45c4ce0ed26ccf774c37Bill Pemberton	.remove = adis16240_remove,
2922c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song};
293ae6ae6fec3f7d6919e0146996df37b665c75f662Lars-Peter Clausenmodule_spi_driver(adis16240_driver);
2942c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry Song
2952c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry SongMODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
2962c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry SongMODULE_DESCRIPTION("Analog Devices Programmable Impact Sensor and Recorder");
2972c834b4d2d30c8f8ae5365a66c50da95aed7b7eaBarry SongMODULE_LICENSE("GPL v2");
29855e4390cb04e8b0fbae8983c3494c9e24132db1bLars-Peter ClausenMODULE_ALIAS("spi:adis16240");
299