1/* 2 * ADIS16240 Programmable Impact Sensor and Recorder driver 3 * 4 * Copyright 2010 Analog Devices Inc. 5 * 6 * Licensed under the GPL-2 or later. 7 */ 8 9#include <linux/interrupt.h> 10#include <linux/irq.h> 11#include <linux/gpio.h> 12#include <linux/delay.h> 13#include <linux/mutex.h> 14#include <linux/device.h> 15#include <linux/kernel.h> 16#include <linux/spi/spi.h> 17#include <linux/slab.h> 18#include <linux/sysfs.h> 19#include <linux/list.h> 20#include <linux/module.h> 21 22#include <linux/iio/iio.h> 23#include <linux/iio/sysfs.h> 24#include <linux/iio/buffer.h> 25#include <linux/iio/imu/adis.h> 26 27#include "adis16240.h" 28 29static ssize_t adis16240_spi_read_signed(struct device *dev, 30 struct device_attribute *attr, 31 char *buf, 32 unsigned bits) 33{ 34 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 35 struct adis *st = iio_priv(indio_dev); 36 int ret; 37 s16 val = 0; 38 unsigned shift = 16 - bits; 39 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 40 41 ret = adis_read_reg_16(st, 42 this_attr->address, (u16 *)&val); 43 if (ret) 44 return ret; 45 46 if (val & ADIS16240_ERROR_ACTIVE) 47 adis_check_status(st); 48 49 val = ((s16)(val << shift) >> shift); 50 return sprintf(buf, "%d\n", val); 51} 52 53static ssize_t adis16240_read_12bit_signed(struct device *dev, 54 struct device_attribute *attr, 55 char *buf) 56{ 57 ssize_t ret; 58 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 59 60 /* Take the iio_dev status lock */ 61 mutex_lock(&indio_dev->mlock); 62 ret = adis16240_spi_read_signed(dev, attr, buf, 12); 63 mutex_unlock(&indio_dev->mlock); 64 65 return ret; 66} 67 68static IIO_DEVICE_ATTR(in_accel_xyz_squared_peak_raw, S_IRUGO, 69 adis16240_read_12bit_signed, NULL, 70 ADIS16240_XYZPEAK_OUT); 71 72static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("4096"); 73 74static const u8 adis16240_addresses[][2] = { 75 [ADIS16240_SCAN_ACC_X] = { ADIS16240_XACCL_OFF, ADIS16240_XPEAK_OUT }, 76 [ADIS16240_SCAN_ACC_Y] = { ADIS16240_YACCL_OFF, ADIS16240_YPEAK_OUT }, 77 [ADIS16240_SCAN_ACC_Z] = { ADIS16240_ZACCL_OFF, ADIS16240_ZPEAK_OUT }, 78}; 79 80static int adis16240_read_raw(struct iio_dev *indio_dev, 81 struct iio_chan_spec const *chan, 82 int *val, int *val2, 83 long mask) 84{ 85 struct adis *st = iio_priv(indio_dev); 86 int ret; 87 int bits; 88 u8 addr; 89 s16 val16; 90 91 switch (mask) { 92 case IIO_CHAN_INFO_RAW: 93 return adis_single_conversion(indio_dev, chan, 94 ADIS16240_ERROR_ACTIVE, val); 95 case IIO_CHAN_INFO_SCALE: 96 switch (chan->type) { 97 case IIO_VOLTAGE: 98 if (chan->channel == 0) { 99 *val = 4; 100 *val2 = 880000; /* 4.88 mV */ 101 return IIO_VAL_INT_PLUS_MICRO; 102 } 103 return -EINVAL; 104 case IIO_TEMP: 105 *val = 244; /* 0.244 C */ 106 *val2 = 0; 107 return IIO_VAL_INT_PLUS_MICRO; 108 case IIO_ACCEL: 109 *val = 0; 110 *val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */ 111 return IIO_VAL_INT_PLUS_MICRO; 112 default: 113 return -EINVAL; 114 } 115 break; 116 case IIO_CHAN_INFO_PEAK_SCALE: 117 *val = 0; 118 *val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */ 119 return IIO_VAL_INT_PLUS_MICRO; 120 case IIO_CHAN_INFO_OFFSET: 121 *val = 25000 / 244 - 0x133; /* 25 C = 0x133 */ 122 return IIO_VAL_INT; 123 case IIO_CHAN_INFO_CALIBBIAS: 124 bits = 10; 125 mutex_lock(&indio_dev->mlock); 126 addr = adis16240_addresses[chan->scan_index][0]; 127 ret = adis_read_reg_16(st, addr, &val16); 128 if (ret) { 129 mutex_unlock(&indio_dev->mlock); 130 return ret; 131 } 132 val16 &= (1 << bits) - 1; 133 val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); 134 *val = val16; 135 mutex_unlock(&indio_dev->mlock); 136 return IIO_VAL_INT; 137 case IIO_CHAN_INFO_PEAK: 138 bits = 10; 139 mutex_lock(&indio_dev->mlock); 140 addr = adis16240_addresses[chan->scan_index][1]; 141 ret = adis_read_reg_16(st, addr, &val16); 142 if (ret) { 143 mutex_unlock(&indio_dev->mlock); 144 return ret; 145 } 146 val16 &= (1 << bits) - 1; 147 val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); 148 *val = val16; 149 mutex_unlock(&indio_dev->mlock); 150 return IIO_VAL_INT; 151 } 152 return -EINVAL; 153} 154 155static int adis16240_write_raw(struct iio_dev *indio_dev, 156 struct iio_chan_spec const *chan, 157 int val, 158 int val2, 159 long mask) 160{ 161 struct adis *st = iio_priv(indio_dev); 162 int bits = 10; 163 s16 val16; 164 u8 addr; 165 166 switch (mask) { 167 case IIO_CHAN_INFO_CALIBBIAS: 168 val16 = val & ((1 << bits) - 1); 169 addr = adis16240_addresses[chan->scan_index][0]; 170 return adis_write_reg_16(st, addr, val16); 171 } 172 return -EINVAL; 173} 174 175static const struct iio_chan_spec adis16240_channels[] = { 176 ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 0, 10), 177 ADIS_AUX_ADC_CHAN(ADIS16240_AUX_ADC, ADIS16240_SCAN_AUX_ADC, 0, 10), 178 ADIS_ACCEL_CHAN(X, ADIS16240_XACCL_OUT, ADIS16240_SCAN_ACC_X, 179 BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10), 180 ADIS_ACCEL_CHAN(Y, ADIS16240_YACCL_OUT, ADIS16240_SCAN_ACC_Y, 181 BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10), 182 ADIS_ACCEL_CHAN(Z, ADIS16240_ZACCL_OUT, ADIS16240_SCAN_ACC_Z, 183 BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10), 184 ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 0, 10), 185 IIO_CHAN_SOFT_TIMESTAMP(6) 186}; 187 188static struct attribute *adis16240_attributes[] = { 189 &iio_dev_attr_in_accel_xyz_squared_peak_raw.dev_attr.attr, 190 &iio_const_attr_sampling_frequency_available.dev_attr.attr, 191 NULL 192}; 193 194static const struct attribute_group adis16240_attribute_group = { 195 .attrs = adis16240_attributes, 196}; 197 198static const struct iio_info adis16240_info = { 199 .attrs = &adis16240_attribute_group, 200 .read_raw = &adis16240_read_raw, 201 .write_raw = &adis16240_write_raw, 202 .update_scan_mode = adis_update_scan_mode, 203 .driver_module = THIS_MODULE, 204}; 205 206static const char * const adis16240_status_error_msgs[] = { 207 [ADIS16240_DIAG_STAT_PWRON_FAIL_BIT] = "Power on, self-test failed", 208 [ADIS16240_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure", 209 [ADIS16240_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed", 210 [ADIS16240_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V", 211 [ADIS16240_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.225V", 212}; 213 214static const struct adis_data adis16240_data = { 215 .write_delay = 35, 216 .read_delay = 35, 217 .msc_ctrl_reg = ADIS16240_MSC_CTRL, 218 .glob_cmd_reg = ADIS16240_GLOB_CMD, 219 .diag_stat_reg = ADIS16240_DIAG_STAT, 220 221 .self_test_mask = ADIS16240_MSC_CTRL_SELF_TEST_EN, 222 .startup_delay = ADIS16240_STARTUP_DELAY, 223 224 .status_error_msgs = adis16240_status_error_msgs, 225 .status_error_mask = BIT(ADIS16240_DIAG_STAT_PWRON_FAIL_BIT) | 226 BIT(ADIS16240_DIAG_STAT_SPI_FAIL_BIT) | 227 BIT(ADIS16240_DIAG_STAT_FLASH_UPT_BIT) | 228 BIT(ADIS16240_DIAG_STAT_POWER_HIGH_BIT) | 229 BIT(ADIS16240_DIAG_STAT_POWER_LOW_BIT), 230}; 231 232static int adis16240_probe(struct spi_device *spi) 233{ 234 int ret; 235 struct adis *st; 236 struct iio_dev *indio_dev; 237 238 /* setup the industrialio driver allocated elements */ 239 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 240 if (!indio_dev) 241 return -ENOMEM; 242 st = iio_priv(indio_dev); 243 /* this is only used for removal purposes */ 244 spi_set_drvdata(spi, indio_dev); 245 246 indio_dev->name = spi->dev.driver->name; 247 indio_dev->dev.parent = &spi->dev; 248 indio_dev->info = &adis16240_info; 249 indio_dev->channels = adis16240_channels; 250 indio_dev->num_channels = ARRAY_SIZE(adis16240_channels); 251 indio_dev->modes = INDIO_DIRECT_MODE; 252 253 ret = adis_init(st, indio_dev, spi, &adis16240_data); 254 if (ret) 255 return ret; 256 ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL); 257 if (ret) 258 return ret; 259 260 /* Get the device into a sane initial state */ 261 ret = adis_initial_startup(st); 262 if (ret) 263 goto error_cleanup_buffer_trigger; 264 ret = iio_device_register(indio_dev); 265 if (ret) 266 goto error_cleanup_buffer_trigger; 267 return 0; 268 269error_cleanup_buffer_trigger: 270 adis_cleanup_buffer_and_trigger(st, indio_dev); 271 return ret; 272} 273 274static int adis16240_remove(struct spi_device *spi) 275{ 276 struct iio_dev *indio_dev = spi_get_drvdata(spi); 277 struct adis *st = iio_priv(indio_dev); 278 279 iio_device_unregister(indio_dev); 280 adis_cleanup_buffer_and_trigger(st, indio_dev); 281 282 return 0; 283} 284 285static struct spi_driver adis16240_driver = { 286 .driver = { 287 .name = "adis16240", 288 .owner = THIS_MODULE, 289 }, 290 .probe = adis16240_probe, 291 .remove = adis16240_remove, 292}; 293module_spi_driver(adis16240_driver); 294 295MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); 296MODULE_DESCRIPTION("Analog Devices Programmable Impact Sensor and Recorder"); 297MODULE_LICENSE("GPL v2"); 298MODULE_ALIAS("spi:adis16240"); 299