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