1/* 2 * ADIS16220 Programmable Digital Vibration Sensor driver 3 * 4 * Copyright 2010 Analog Devices Inc. 5 * 6 * Licensed under the GPL-2 or later. 7 */ 8 9#include <linux/delay.h> 10#include <linux/mutex.h> 11#include <linux/device.h> 12#include <linux/kernel.h> 13#include <linux/spi/spi.h> 14#include <linux/slab.h> 15#include <linux/sysfs.h> 16#include <linux/module.h> 17 18#include <linux/iio/iio.h> 19#include <linux/iio/sysfs.h> 20 21#include "adis16220.h" 22 23static ssize_t adis16220_read_16bit(struct device *dev, 24 struct device_attribute *attr, 25 char *buf) 26{ 27 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 28 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 29 struct adis16220_state *st = iio_priv(indio_dev); 30 ssize_t ret; 31 s16 val = 0; 32 33 /* Take the iio_dev status lock */ 34 mutex_lock(&indio_dev->mlock); 35 ret = adis_read_reg_16(&st->adis, this_attr->address, 36 (u16 *)&val); 37 mutex_unlock(&indio_dev->mlock); 38 if (ret) 39 return ret; 40 return sprintf(buf, "%d\n", val); 41} 42 43static ssize_t adis16220_write_16bit(struct device *dev, 44 struct device_attribute *attr, 45 const char *buf, 46 size_t len) 47{ 48 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 49 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 50 struct adis16220_state *st = iio_priv(indio_dev); 51 int ret; 52 u16 val; 53 54 ret = kstrtou16(buf, 10, &val); 55 if (ret) 56 goto error_ret; 57 ret = adis_write_reg_16(&st->adis, this_attr->address, val); 58 59error_ret: 60 return ret ? ret : len; 61} 62 63static int adis16220_capture(struct iio_dev *indio_dev) 64{ 65 struct adis16220_state *st = iio_priv(indio_dev); 66 int ret; 67 68 /* initiates a manual data capture */ 69 ret = adis_write_reg_16(&st->adis, ADIS16220_GLOB_CMD, 0xBF08); 70 if (ret) 71 dev_err(&indio_dev->dev, "problem beginning capture"); 72 73 usleep_range(10000, 11000); /* delay for capture to finish */ 74 75 return ret; 76} 77 78static ssize_t adis16220_write_capture(struct device *dev, 79 struct device_attribute *attr, 80 const char *buf, size_t len) 81{ 82 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 83 bool val; 84 int ret; 85 86 ret = strtobool(buf, &val); 87 if (ret) 88 return ret; 89 if (!val) 90 return -EINVAL; 91 ret = adis16220_capture(indio_dev); 92 if (ret) 93 return ret; 94 95 return len; 96} 97 98static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev, 99 char *buf, 100 loff_t off, 101 size_t count, 102 int addr) 103{ 104 struct adis16220_state *st = iio_priv(indio_dev); 105 struct spi_transfer xfers[] = { 106 { 107 .tx_buf = st->tx, 108 .bits_per_word = 8, 109 .len = 2, 110 .cs_change = 1, 111 .delay_usecs = 25, 112 }, { 113 .tx_buf = st->tx, 114 .rx_buf = st->rx, 115 .bits_per_word = 8, 116 .cs_change = 1, 117 .delay_usecs = 25, 118 }, 119 }; 120 int ret; 121 int i; 122 123 if (unlikely(!count)) 124 return count; 125 126 if ((off >= ADIS16220_CAPTURE_SIZE) || (count & 1) || (off & 1)) 127 return -EINVAL; 128 129 if (off + count > ADIS16220_CAPTURE_SIZE) 130 count = ADIS16220_CAPTURE_SIZE - off; 131 132 /* write the begin position of capture buffer */ 133 ret = adis_write_reg_16(&st->adis, 134 ADIS16220_CAPT_PNTR, 135 off > 1); 136 if (ret) 137 return -EIO; 138 139 /* read count/2 values from capture buffer */ 140 mutex_lock(&st->buf_lock); 141 142 143 for (i = 0; i < count; i += 2) { 144 st->tx[i] = ADIS_READ_REG(addr); 145 st->tx[i + 1] = 0; 146 } 147 xfers[1].len = count; 148 149 ret = spi_sync_transfer(st->adis.spi, xfers, ARRAY_SIZE(xfers)); 150 if (ret) { 151 152 mutex_unlock(&st->buf_lock); 153 return -EIO; 154 } 155 156 memcpy(buf, st->rx, count); 157 158 mutex_unlock(&st->buf_lock); 159 return count; 160} 161 162static ssize_t adis16220_accel_bin_read(struct file *filp, struct kobject *kobj, 163 struct bin_attribute *attr, 164 char *buf, 165 loff_t off, 166 size_t count) 167{ 168 struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj)); 169 170 return adis16220_capture_buffer_read(indio_dev, buf, 171 off, count, 172 ADIS16220_CAPT_BUFA); 173} 174 175static struct bin_attribute accel_bin = { 176 .attr = { 177 .name = "accel_bin", 178 .mode = S_IRUGO, 179 }, 180 .read = adis16220_accel_bin_read, 181 .size = ADIS16220_CAPTURE_SIZE, 182}; 183 184static ssize_t adis16220_adc1_bin_read(struct file *filp, struct kobject *kobj, 185 struct bin_attribute *attr, 186 char *buf, loff_t off, 187 size_t count) 188{ 189 struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj)); 190 191 return adis16220_capture_buffer_read(indio_dev, buf, 192 off, count, 193 ADIS16220_CAPT_BUF1); 194} 195 196static struct bin_attribute adc1_bin = { 197 .attr = { 198 .name = "in0_bin", 199 .mode = S_IRUGO, 200 }, 201 .read = adis16220_adc1_bin_read, 202 .size = ADIS16220_CAPTURE_SIZE, 203}; 204 205static ssize_t adis16220_adc2_bin_read(struct file *filp, struct kobject *kobj, 206 struct bin_attribute *attr, 207 char *buf, loff_t off, 208 size_t count) 209{ 210 struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj)); 211 212 return adis16220_capture_buffer_read(indio_dev, buf, 213 off, count, 214 ADIS16220_CAPT_BUF2); 215} 216 217 218static struct bin_attribute adc2_bin = { 219 .attr = { 220 .name = "in1_bin", 221 .mode = S_IRUGO, 222 }, 223 .read = adis16220_adc2_bin_read, 224 .size = ADIS16220_CAPTURE_SIZE, 225}; 226 227#define IIO_DEV_ATTR_CAPTURE(_store) \ 228 IIO_DEVICE_ATTR(capture, S_IWUSR, NULL, _store, 0) 229 230static IIO_DEV_ATTR_CAPTURE(adis16220_write_capture); 231 232#define IIO_DEV_ATTR_CAPTURE_COUNT(_mode, _show, _store, _addr) \ 233 IIO_DEVICE_ATTR(capture_count, _mode, _show, _store, _addr) 234 235static IIO_DEV_ATTR_CAPTURE_COUNT(S_IWUSR | S_IRUGO, 236 adis16220_read_16bit, 237 adis16220_write_16bit, 238 ADIS16220_CAPT_PNTR); 239 240enum adis16220_channel { 241 in_supply, in_1, in_2, accel, temp 242}; 243 244struct adis16220_address_spec { 245 u8 addr; 246 u8 bits; 247 bool sign; 248}; 249 250/* Address / bits / signed */ 251static const struct adis16220_address_spec adis16220_addresses[][3] = { 252 [in_supply] = { { ADIS16220_CAPT_SUPPLY, 12, 0 }, }, 253 [in_1] = { { ADIS16220_CAPT_BUF1, 16, 1 }, 254 { ADIS16220_AIN1_NULL, 16, 1 }, 255 { ADIS16220_CAPT_PEAK1, 16, 1 }, }, 256 [in_2] = { { ADIS16220_CAPT_BUF2, 16, 1 }, 257 { ADIS16220_AIN2_NULL, 16, 1 }, 258 { ADIS16220_CAPT_PEAK2, 16, 1 }, }, 259 [accel] = { { ADIS16220_CAPT_BUFA, 16, 1 }, 260 { ADIS16220_ACCL_NULL, 16, 1 }, 261 { ADIS16220_CAPT_PEAKA, 16, 1 }, }, 262 [temp] = { { ADIS16220_CAPT_TEMP, 12, 0 }, } 263}; 264 265static int adis16220_read_raw(struct iio_dev *indio_dev, 266 struct iio_chan_spec const *chan, 267 int *val, int *val2, 268 long mask) 269{ 270 struct adis16220_state *st = iio_priv(indio_dev); 271 const struct adis16220_address_spec *addr; 272 int ret = -EINVAL; 273 int addrind = 0; 274 u16 uval; 275 s16 sval; 276 u8 bits; 277 278 switch (mask) { 279 case IIO_CHAN_INFO_RAW: 280 addrind = 0; 281 break; 282 case IIO_CHAN_INFO_OFFSET: 283 if (chan->type == IIO_TEMP) { 284 *val = 25000 / -470 - 1278; /* 25 C = 1278 */ 285 return IIO_VAL_INT; 286 } 287 addrind = 1; 288 break; 289 case IIO_CHAN_INFO_PEAK: 290 addrind = 2; 291 break; 292 case IIO_CHAN_INFO_SCALE: 293 switch (chan->type) { 294 case IIO_TEMP: 295 *val = -470; /* -0.47 C */ 296 *val2 = 0; 297 return IIO_VAL_INT_PLUS_MICRO; 298 case IIO_ACCEL: 299 *val2 = IIO_G_TO_M_S_2(19073); /* 19.073 g */ 300 return IIO_VAL_INT_PLUS_MICRO; 301 case IIO_VOLTAGE: 302 if (chan->channel == 0) { 303 *val = 1; 304 *val2 = 220700; /* 1.2207 mV */ 305 } else { 306 /* Should really be dependent on VDD */ 307 *val2 = 305180; /* 305.18 uV */ 308 } 309 return IIO_VAL_INT_PLUS_MICRO; 310 default: 311 return -EINVAL; 312 } 313 default: 314 return -EINVAL; 315 } 316 addr = &adis16220_addresses[chan->address][addrind]; 317 if (addr->sign) { 318 ret = adis_read_reg_16(&st->adis, addr->addr, &sval); 319 if (ret) 320 return ret; 321 bits = addr->bits; 322 sval &= (1 << bits) - 1; 323 sval = (s16)(sval << (16 - bits)) >> (16 - bits); 324 *val = sval; 325 return IIO_VAL_INT; 326 } 327 ret = adis_read_reg_16(&st->adis, addr->addr, &uval); 328 if (ret) 329 return ret; 330 bits = addr->bits; 331 uval &= (1 << bits) - 1; 332 *val = uval; 333 return IIO_VAL_INT; 334} 335 336static const struct iio_chan_spec adis16220_channels[] = { 337 { 338 .type = IIO_VOLTAGE, 339 .indexed = 1, 340 .channel = 0, 341 .extend_name = "supply", 342 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 343 BIT(IIO_CHAN_INFO_SCALE), 344 .address = in_supply, 345 }, { 346 .type = IIO_ACCEL, 347 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 348 BIT(IIO_CHAN_INFO_OFFSET) | 349 BIT(IIO_CHAN_INFO_SCALE) | 350 BIT(IIO_CHAN_INFO_PEAK), 351 .address = accel, 352 }, { 353 .type = IIO_TEMP, 354 .indexed = 1, 355 .channel = 0, 356 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 357 BIT(IIO_CHAN_INFO_OFFSET) | 358 BIT(IIO_CHAN_INFO_SCALE), 359 .address = temp, 360 }, { 361 .type = IIO_VOLTAGE, 362 .indexed = 1, 363 .channel = 1, 364 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 365 BIT(IIO_CHAN_INFO_OFFSET) | 366 BIT(IIO_CHAN_INFO_SCALE), 367 .address = in_1, 368 }, { 369 .type = IIO_VOLTAGE, 370 .indexed = 1, 371 .channel = 2, 372 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 373 .address = in_2, 374 } 375}; 376 377static struct attribute *adis16220_attributes[] = { 378 &iio_dev_attr_capture.dev_attr.attr, 379 &iio_dev_attr_capture_count.dev_attr.attr, 380 NULL 381}; 382 383static const struct attribute_group adis16220_attribute_group = { 384 .attrs = adis16220_attributes, 385}; 386 387static const struct iio_info adis16220_info = { 388 .attrs = &adis16220_attribute_group, 389 .driver_module = THIS_MODULE, 390 .read_raw = &adis16220_read_raw, 391}; 392 393static const char * const adis16220_status_error_msgs[] = { 394 [ADIS16220_DIAG_STAT_VIOLATION_BIT] = "Capture period violation/interruption", 395 [ADIS16220_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure", 396 [ADIS16220_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed", 397 [ADIS16220_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V", 398 [ADIS16220_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V", 399}; 400 401static const struct adis_data adis16220_data = { 402 .read_delay = 35, 403 .write_delay = 35, 404 .msc_ctrl_reg = ADIS16220_MSC_CTRL, 405 .glob_cmd_reg = ADIS16220_GLOB_CMD, 406 .diag_stat_reg = ADIS16220_DIAG_STAT, 407 408 .self_test_mask = ADIS16220_MSC_CTRL_SELF_TEST_EN, 409 .startup_delay = ADIS16220_STARTUP_DELAY, 410 411 .status_error_msgs = adis16220_status_error_msgs, 412 .status_error_mask = BIT(ADIS16220_DIAG_STAT_VIOLATION_BIT) | 413 BIT(ADIS16220_DIAG_STAT_SPI_FAIL_BIT) | 414 BIT(ADIS16220_DIAG_STAT_FLASH_UPT_BIT) | 415 BIT(ADIS16220_DIAG_STAT_POWER_HIGH_BIT) | 416 BIT(ADIS16220_DIAG_STAT_POWER_LOW_BIT), 417}; 418 419static int adis16220_probe(struct spi_device *spi) 420{ 421 int ret; 422 struct adis16220_state *st; 423 struct iio_dev *indio_dev; 424 425 /* setup the industrialio driver allocated elements */ 426 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 427 if (!indio_dev) 428 return -ENOMEM; 429 430 st = iio_priv(indio_dev); 431 /* this is only used for removal purposes */ 432 spi_set_drvdata(spi, indio_dev); 433 434 indio_dev->name = spi->dev.driver->name; 435 indio_dev->dev.parent = &spi->dev; 436 indio_dev->info = &adis16220_info; 437 indio_dev->modes = INDIO_DIRECT_MODE; 438 indio_dev->channels = adis16220_channels; 439 indio_dev->num_channels = ARRAY_SIZE(adis16220_channels); 440 441 ret = devm_iio_device_register(&spi->dev, indio_dev); 442 if (ret) 443 return ret; 444 445 ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &accel_bin); 446 if (ret) 447 return ret; 448 449 ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &adc1_bin); 450 if (ret) 451 goto error_rm_accel_bin; 452 453 ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &adc2_bin); 454 if (ret) 455 goto error_rm_adc1_bin; 456 457 ret = adis_init(&st->adis, indio_dev, spi, &adis16220_data); 458 if (ret) 459 goto error_rm_adc2_bin; 460 /* Get the device into a sane initial state */ 461 ret = adis_initial_startup(&st->adis); 462 if (ret) 463 goto error_rm_adc2_bin; 464 return 0; 465 466error_rm_adc2_bin: 467 sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc2_bin); 468error_rm_adc1_bin: 469 sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin); 470error_rm_accel_bin: 471 sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin); 472 return ret; 473} 474 475static int adis16220_remove(struct spi_device *spi) 476{ 477 struct iio_dev *indio_dev = spi_get_drvdata(spi); 478 479 sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc2_bin); 480 sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin); 481 sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin); 482 483 return 0; 484} 485 486static struct spi_driver adis16220_driver = { 487 .driver = { 488 .name = "adis16220", 489 .owner = THIS_MODULE, 490 }, 491 .probe = adis16220_probe, 492 .remove = adis16220_remove, 493}; 494module_spi_driver(adis16220_driver); 495 496MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); 497MODULE_DESCRIPTION("Analog Devices ADIS16220 Digital Vibration Sensor"); 498MODULE_LICENSE("GPL v2"); 499MODULE_ALIAS("spi:adis16220"); 500