Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
adis16204_core.c
Go to the documentation of this file.
1 /*
2  * ADIS16204 Programmable High-g Digital Impact Sensor and Recorder
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/delay.h>
12 #include <linux/mutex.h>
13 #include <linux/device.h>
14 #include <linux/kernel.h>
15 #include <linux/spi/spi.h>
16 #include <linux/slab.h>
17 #include <linux/sysfs.h>
18 #include <linux/list.h>
19 #include <linux/module.h>
20 
21 #include <linux/iio/iio.h>
22 #include <linux/iio/sysfs.h>
23 #include <linux/iio/buffer.h>
24 
25 #include "adis16204.h"
26 
27 #define DRIVER_NAME "adis16204"
28 
35 static int adis16204_spi_write_reg_8(struct iio_dev *indio_dev,
36  u8 reg_address,
37  u8 val)
38 {
39  int ret;
40  struct adis16204_state *st = iio_priv(indio_dev);
41 
42  mutex_lock(&st->buf_lock);
43  st->tx[0] = ADIS16204_WRITE_REG(reg_address);
44  st->tx[1] = val;
45 
46  ret = spi_write(st->us, st->tx, 2);
47  mutex_unlock(&st->buf_lock);
48 
49  return ret;
50 }
51 
59 static int adis16204_spi_write_reg_16(struct iio_dev *indio_dev,
60  u8 lower_reg_address,
61  u16 value)
62 {
63  int ret;
64  struct spi_message msg;
65  struct adis16204_state *st = iio_priv(indio_dev);
66  struct spi_transfer xfers[] = {
67  {
68  .tx_buf = st->tx,
69  .bits_per_word = 8,
70  .len = 2,
71  .cs_change = 1,
72  }, {
73  .tx_buf = st->tx + 2,
74  .bits_per_word = 8,
75  .len = 2,
76  .cs_change = 1,
77  },
78  };
79 
80  mutex_lock(&st->buf_lock);
81  st->tx[0] = ADIS16204_WRITE_REG(lower_reg_address);
82  st->tx[1] = value & 0xFF;
83  st->tx[2] = ADIS16204_WRITE_REG(lower_reg_address + 1);
84  st->tx[3] = (value >> 8) & 0xFF;
85 
86  spi_message_init(&msg);
87  spi_message_add_tail(&xfers[0], &msg);
88  spi_message_add_tail(&xfers[1], &msg);
89  ret = spi_sync(st->us, &msg);
90  mutex_unlock(&st->buf_lock);
91 
92  return ret;
93 }
94 
102 static int adis16204_spi_read_reg_16(struct iio_dev *indio_dev,
103  u8 lower_reg_address,
104  u16 *val)
105 {
106  struct spi_message msg;
107  struct adis16204_state *st = iio_priv(indio_dev);
108  int ret;
109  struct spi_transfer xfers[] = {
110  {
111  .tx_buf = st->tx,
112  .bits_per_word = 8,
113  .len = 2,
114  .cs_change = 1,
115  .delay_usecs = 20,
116  }, {
117  .rx_buf = st->rx,
118  .bits_per_word = 8,
119  .len = 2,
120  .delay_usecs = 20,
121  },
122  };
123 
124  mutex_lock(&st->buf_lock);
125  st->tx[0] = ADIS16204_READ_REG(lower_reg_address);
126  st->tx[1] = 0;
127 
128  spi_message_init(&msg);
129  spi_message_add_tail(&xfers[0], &msg);
130  spi_message_add_tail(&xfers[1], &msg);
131  ret = spi_sync(st->us, &msg);
132  if (ret) {
133  dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
134  lower_reg_address);
135  goto error_ret;
136  }
137  *val = (st->rx[0] << 8) | st->rx[1];
138 
139 error_ret:
140  mutex_unlock(&st->buf_lock);
141  return ret;
142 }
143 
144 static int adis16204_check_status(struct iio_dev *indio_dev)
145 {
146  u16 status;
147  int ret;
148 
149  ret = adis16204_spi_read_reg_16(indio_dev,
150  ADIS16204_DIAG_STAT, &status);
151  if (ret < 0) {
152  dev_err(&indio_dev->dev, "Reading status failed\n");
153  goto error_ret;
154  }
155  ret = status & 0x1F;
156 
158  dev_err(&indio_dev->dev, "Self test failure\n");
159  if (status & ADIS16204_DIAG_STAT_SPI_FAIL)
160  dev_err(&indio_dev->dev, "SPI failure\n");
161  if (status & ADIS16204_DIAG_STAT_FLASH_UPT)
162  dev_err(&indio_dev->dev, "Flash update failed\n");
163  if (status & ADIS16204_DIAG_STAT_POWER_HIGH)
164  dev_err(&indio_dev->dev, "Power supply above 3.625V\n");
165  if (status & ADIS16204_DIAG_STAT_POWER_LOW)
166  dev_err(&indio_dev->dev, "Power supply below 2.975V\n");
167 
168 error_ret:
169  return ret;
170 }
171 
172 static int adis16204_reset(struct iio_dev *indio_dev)
173 {
174  int ret;
175  ret = adis16204_spi_write_reg_8(indio_dev,
178  if (ret)
179  dev_err(&indio_dev->dev, "problem resetting device");
180 
181  return ret;
182 }
183 
184 int adis16204_set_irq(struct iio_dev *indio_dev, bool enable)
185 {
186  int ret = 0;
187  u16 msc;
188 
189  ret = adis16204_spi_read_reg_16(indio_dev, ADIS16204_MSC_CTRL, &msc);
190  if (ret)
191  goto error_ret;
192 
195  if (enable)
197  else
199 
200  ret = adis16204_spi_write_reg_16(indio_dev, ADIS16204_MSC_CTRL, msc);
201 
202 error_ret:
203  return ret;
204 }
205 
206 static int adis16204_self_test(struct iio_dev *indio_dev)
207 {
208  int ret;
209  ret = adis16204_spi_write_reg_16(indio_dev,
212  if (ret) {
213  dev_err(&indio_dev->dev, "problem starting self test");
214  goto err_ret;
215  }
216 
217  adis16204_check_status(indio_dev);
218 
219 err_ret:
220  return ret;
221 }
222 
223 static int adis16204_initial_setup(struct iio_dev *indio_dev)
224 {
225  int ret;
226 
227  /* Disable IRQ */
228  ret = adis16204_set_irq(indio_dev, false);
229  if (ret) {
230  dev_err(&indio_dev->dev, "disable irq failed");
231  goto err_ret;
232  }
233 
234  /* Do self test */
235  ret = adis16204_self_test(indio_dev);
236  if (ret) {
237  dev_err(&indio_dev->dev, "self test failure");
238  goto err_ret;
239  }
240 
241  /* Read status register to check the result */
242  ret = adis16204_check_status(indio_dev);
243  if (ret) {
244  adis16204_reset(indio_dev);
245  dev_err(&indio_dev->dev, "device not playing ball -> reset");
247  ret = adis16204_check_status(indio_dev);
248  if (ret) {
249  dev_err(&indio_dev->dev, "giving up");
250  goto err_ret;
251  }
252  }
253 
254 err_ret:
255  return ret;
256 }
257 
258 /* Unique to this driver currently */
259 
267 };
268 
269 static u8 adis16204_addresses[6][3] = {
271  [in_aux] = { ADIS16204_AUX_ADC },
272  [temp] = { ADIS16204_TEMP_OUT },
279 };
280 
281 static int adis16204_read_raw(struct iio_dev *indio_dev,
282  struct iio_chan_spec const *chan,
283  int *val, int *val2,
284  long mask)
285 {
286  int ret;
287  int bits;
288  u8 addr;
289  s16 val16;
290  int addrind;
291 
292  switch (mask) {
293  case IIO_CHAN_INFO_RAW:
294  mutex_lock(&indio_dev->mlock);
295  addr = adis16204_addresses[chan->address][0];
296  ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16);
297  if (ret) {
298  mutex_unlock(&indio_dev->mlock);
299  return ret;
300  }
301 
302  if (val16 & ADIS16204_ERROR_ACTIVE) {
303  ret = adis16204_check_status(indio_dev);
304  if (ret) {
305  mutex_unlock(&indio_dev->mlock);
306  return ret;
307  }
308  }
309  val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
310  if (chan->scan_type.sign == 's')
311  val16 = (s16)(val16 <<
312  (16 - chan->scan_type.realbits)) >>
313  (16 - chan->scan_type.realbits);
314  *val = val16;
315  mutex_unlock(&indio_dev->mlock);
316  return IIO_VAL_INT;
317  case IIO_CHAN_INFO_SCALE:
318  switch (chan->type) {
319  case IIO_VOLTAGE:
320  if (chan->channel == 0) {
321  *val = 1;
322  *val2 = 220000; /* 1.22 mV */
323  } else {
324  *val = 0;
325  *val2 = 610000; /* 0.61 mV */
326  }
327  return IIO_VAL_INT_PLUS_MICRO;
328  case IIO_TEMP:
329  *val = -470; /* 0.47 C */
330  *val2 = 0;
331  return IIO_VAL_INT_PLUS_MICRO;
332  case IIO_ACCEL:
333  *val = 0;
334  switch (chan->channel2) {
335  case IIO_MOD_X:
337  *val2 = IIO_G_TO_M_S_2(17125); /* 17.125 mg */
338  break;
339  case IIO_MOD_Y:
340  case IIO_MOD_Z:
341  *val2 = IIO_G_TO_M_S_2(8407); /* 8.407 mg */
342  break;
343  }
344  return IIO_VAL_INT_PLUS_MICRO;
345  default:
346  return -EINVAL;
347  }
348  break;
350  *val = 25000 / -470 - 1278; /* 25 C = 1278 */
351  return IIO_VAL_INT;
353  case IIO_CHAN_INFO_PEAK:
354  if (mask == IIO_CHAN_INFO_CALIBBIAS) {
355  bits = 12;
356  addrind = 1;
357  } else { /* PEAK_SEPARATE */
358  bits = 14;
359  addrind = 2;
360  }
361  mutex_lock(&indio_dev->mlock);
362  addr = adis16204_addresses[chan->address][addrind];
363  ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16);
364  if (ret) {
365  mutex_unlock(&indio_dev->mlock);
366  return ret;
367  }
368  val16 &= (1 << bits) - 1;
369  val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
370  *val = val16;
371  mutex_unlock(&indio_dev->mlock);
372  return IIO_VAL_INT;
373  }
374  return -EINVAL;
375 }
376 
377 static int adis16204_write_raw(struct iio_dev *indio_dev,
378  struct iio_chan_spec const *chan,
379  int val,
380  int val2,
381  long mask)
382 {
383  int bits;
384  s16 val16;
385  u8 addr;
386  switch (mask) {
388  switch (chan->type) {
389  case IIO_ACCEL:
390  bits = 12;
391  break;
392  default:
393  return -EINVAL;
394  };
395  val16 = val & ((1 << bits) - 1);
396  addr = adis16204_addresses[chan->address][1];
397  return adis16204_spi_write_reg_16(indio_dev, addr, val16);
398  }
399  return -EINVAL;
400 }
401 
402 static const struct iio_chan_spec adis16204_channels[] = {
403  {
404  .type = IIO_VOLTAGE,
405  .indexed = 1, /* Note was not previously indexed */
406  .channel = 0,
407  .extend_name = "supply",
408  .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
410  .address = in_supply,
411  .scan_index = ADIS16204_SCAN_SUPPLY,
412  .scan_type = {
413  .sign = 'u',
414  .realbits = 12,
415  .storagebits = 16,
416  },
417  }, {
418  .type = IIO_VOLTAGE,
419  .indexed = 1,
420  .channel = 1,
421  .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
423  .address = in_aux,
424  .scan_index = ADIS16204_SCAN_AUX_ADC,
425  .scan_type = {
426  .sign = 'u',
427  .realbits = 12,
428  .storagebits = 16,
429  },
430  }, {
431  .type = IIO_TEMP,
432  .indexed = 1,
433  .channel = 0,
434  .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
437  .address = temp,
438  .scan_index = ADIS16204_SCAN_TEMP,
439  .scan_type = {
440  .sign = 'u',
441  .realbits = 12,
442  .storagebits = 16,
443  },
444  }, {
445  .type = IIO_ACCEL,
446  .modified = 1,
447  .channel2 = IIO_MOD_X,
448  .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
452  .address = accel_x,
453  .scan_index = ADIS16204_SCAN_ACC_X,
454  .scan_type = {
455  .sign = 's',
456  .realbits = 14,
457  .storagebits = 16,
458  },
459  }, {
460  .type = IIO_ACCEL,
461  .modified = 1,
462  .channel2 = IIO_MOD_Y,
463  .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
467  .address = accel_y,
468  .scan_index = ADIS16204_SCAN_ACC_Y,
469  .scan_type = {
470  .sign = 's',
471  .realbits = 14,
472  .storagebits = 16,
473  },
474  },
476  {
477  .type = IIO_ACCEL,
478  .modified = 1,
479  .channel2 = IIO_MOD_ROOT_SUM_SQUARED_X_Y,
480  .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
483  .address = accel_xy,
484  .scan_type = {
485  .sign = 'u',
486  .realbits = 14,
487  .storagebits = 16,
488  },
489  }
490 };
491 
492 static const struct iio_info adis16204_info = {
493  .read_raw = &adis16204_read_raw,
494  .write_raw = &adis16204_write_raw,
495  .driver_module = THIS_MODULE,
496 };
497 
498 static int __devinit adis16204_probe(struct spi_device *spi)
499 {
500  int ret;
501  struct adis16204_state *st;
502  struct iio_dev *indio_dev;
503 
504  /* setup the industrialio driver allocated elements */
505  indio_dev = iio_device_alloc(sizeof(*st));
506  if (indio_dev == NULL) {
507  ret = -ENOMEM;
508  goto error_ret;
509  }
510  st = iio_priv(indio_dev);
511  /* this is only used for removal purposes */
512  spi_set_drvdata(spi, indio_dev);
513  st->us = spi;
514  mutex_init(&st->buf_lock);
515 
516  indio_dev->name = spi->dev.driver->name;
517  indio_dev->dev.parent = &spi->dev;
518  indio_dev->info = &adis16204_info;
519  indio_dev->channels = adis16204_channels;
520  indio_dev->num_channels = ARRAY_SIZE(adis16204_channels);
521  indio_dev->modes = INDIO_DIRECT_MODE;
522 
523  ret = adis16204_configure_ring(indio_dev);
524  if (ret)
525  goto error_free_dev;
526 
527  ret = iio_buffer_register(indio_dev,
528  adis16204_channels,
529  6);
530  if (ret) {
531  printk(KERN_ERR "failed to initialize the ring\n");
532  goto error_unreg_ring_funcs;
533  }
534 
535  if (spi->irq) {
536  ret = adis16204_probe_trigger(indio_dev);
537  if (ret)
538  goto error_uninitialize_ring;
539  }
540 
541  /* Get the device into a sane initial state */
542  ret = adis16204_initial_setup(indio_dev);
543  if (ret)
544  goto error_remove_trigger;
545  ret = iio_device_register(indio_dev);
546  if (ret)
547  goto error_remove_trigger;
548 
549  return 0;
550 
551 error_remove_trigger:
552  adis16204_remove_trigger(indio_dev);
553 error_uninitialize_ring:
554  iio_buffer_unregister(indio_dev);
555 error_unreg_ring_funcs:
556  adis16204_unconfigure_ring(indio_dev);
557 error_free_dev:
558  iio_device_free(indio_dev);
559 error_ret:
560  return ret;
561 }
562 
563 static int __devexit adis16204_remove(struct spi_device *spi)
564 {
565  struct iio_dev *indio_dev = spi_get_drvdata(spi);
566 
567  iio_device_unregister(indio_dev);
568  adis16204_remove_trigger(indio_dev);
569  iio_buffer_unregister(indio_dev);
570  adis16204_unconfigure_ring(indio_dev);
571  iio_device_free(indio_dev);
572 
573  return 0;
574 }
575 
576 static struct spi_driver adis16204_driver = {
577  .driver = {
578  .name = "adis16204",
579  .owner = THIS_MODULE,
580  },
581  .probe = adis16204_probe,
582  .remove = __devexit_p(adis16204_remove),
583 };
584 module_spi_driver(adis16204_driver);
585 
586 MODULE_AUTHOR("Barry Song <[email protected]>");
587 MODULE_DESCRIPTION("ADIS16204 High-g Digital Impact Sensor and Recorder");
588 MODULE_LICENSE("GPL v2");
589 MODULE_ALIAS("spi:adis16204");