inv_mpu_ring.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /*
  2. * Copyright (C) 2012 Invensense, Inc.
  3. *
  4. * This software is licensed under the terms of the GNU General Public
  5. * License version 2, as published by the Free Software Foundation, and
  6. * may be copied, distributed, and modified under those terms.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/module.h>
  14. #include <linux/slab.h>
  15. #include <linux/err.h>
  16. #include <linux/delay.h>
  17. #include <linux/sysfs.h>
  18. #include <linux/jiffies.h>
  19. #include <linux/irq.h>
  20. #include <linux/interrupt.h>
  21. #include <linux/kfifo.h>
  22. #include <linux/poll.h>
  23. #include "inv_mpu_iio.h"
  24. static void inv_clear_kfifo(struct inv_mpu6050_state *st)
  25. {
  26. unsigned long flags;
  27. /* take the spin lock sem to avoid interrupt kick in */
  28. spin_lock_irqsave(&st->time_stamp_lock, flags);
  29. kfifo_reset(&st->timestamps);
  30. spin_unlock_irqrestore(&st->time_stamp_lock, flags);
  31. }
  32. int inv_reset_fifo(struct iio_dev *indio_dev)
  33. {
  34. int result;
  35. u8 d;
  36. struct inv_mpu6050_state *st = iio_priv(indio_dev);
  37. /* disable interrupt */
  38. result = regmap_write(st->map, st->reg->int_enable, 0);
  39. if (result) {
  40. dev_err(regmap_get_device(st->map), "int_enable failed %d\n",
  41. result);
  42. return result;
  43. }
  44. /* disable the sensor output to FIFO */
  45. result = regmap_write(st->map, st->reg->fifo_en, 0);
  46. if (result)
  47. goto reset_fifo_fail;
  48. /* disable fifo reading */
  49. result = regmap_write(st->map, st->reg->user_ctrl, 0);
  50. if (result)
  51. goto reset_fifo_fail;
  52. /* reset FIFO*/
  53. result = regmap_write(st->map, st->reg->user_ctrl,
  54. INV_MPU6050_BIT_FIFO_RST);
  55. if (result)
  56. goto reset_fifo_fail;
  57. /* clear timestamps fifo */
  58. inv_clear_kfifo(st);
  59. /* enable interrupt */
  60. if (st->chip_config.accl_fifo_enable ||
  61. st->chip_config.gyro_fifo_enable) {
  62. result = regmap_write(st->map, st->reg->int_enable,
  63. INV_MPU6050_BIT_DATA_RDY_EN);
  64. if (result)
  65. return result;
  66. }
  67. /* enable FIFO reading and I2C master interface*/
  68. result = regmap_write(st->map, st->reg->user_ctrl,
  69. INV_MPU6050_BIT_FIFO_EN);
  70. if (result)
  71. goto reset_fifo_fail;
  72. /* enable sensor output to FIFO */
  73. d = 0;
  74. if (st->chip_config.gyro_fifo_enable)
  75. d |= INV_MPU6050_BITS_GYRO_OUT;
  76. if (st->chip_config.accl_fifo_enable)
  77. d |= INV_MPU6050_BIT_ACCEL_OUT;
  78. result = regmap_write(st->map, st->reg->fifo_en, d);
  79. if (result)
  80. goto reset_fifo_fail;
  81. return 0;
  82. reset_fifo_fail:
  83. dev_err(regmap_get_device(st->map), "reset fifo failed %d\n", result);
  84. result = regmap_write(st->map, st->reg->int_enable,
  85. INV_MPU6050_BIT_DATA_RDY_EN);
  86. return result;
  87. }
  88. /**
  89. * inv_mpu6050_irq_handler() - Cache a timestamp at each data ready interrupt.
  90. */
  91. irqreturn_t inv_mpu6050_irq_handler(int irq, void *p)
  92. {
  93. struct iio_poll_func *pf = p;
  94. struct iio_dev *indio_dev = pf->indio_dev;
  95. struct inv_mpu6050_state *st = iio_priv(indio_dev);
  96. s64 timestamp;
  97. timestamp = iio_get_time_ns(indio_dev);
  98. kfifo_in_spinlocked(&st->timestamps, &timestamp, 1,
  99. &st->time_stamp_lock);
  100. return IRQ_WAKE_THREAD;
  101. }
  102. /**
  103. * inv_mpu6050_read_fifo() - Transfer data from hardware FIFO to KFIFO.
  104. */
  105. irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
  106. {
  107. struct iio_poll_func *pf = p;
  108. struct iio_dev *indio_dev = pf->indio_dev;
  109. struct inv_mpu6050_state *st = iio_priv(indio_dev);
  110. size_t bytes_per_datum;
  111. int result;
  112. u8 data[INV_MPU6050_OUTPUT_DATA_SIZE];
  113. u16 fifo_count;
  114. s64 timestamp;
  115. mutex_lock(&indio_dev->mlock);
  116. if (!(st->chip_config.accl_fifo_enable |
  117. st->chip_config.gyro_fifo_enable))
  118. goto end_session;
  119. bytes_per_datum = 0;
  120. if (st->chip_config.accl_fifo_enable)
  121. bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR;
  122. if (st->chip_config.gyro_fifo_enable)
  123. bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR;
  124. /*
  125. * read fifo_count register to know how many bytes inside FIFO
  126. * right now
  127. */
  128. result = regmap_bulk_read(st->map, st->reg->fifo_count_h, data,
  129. INV_MPU6050_FIFO_COUNT_BYTE);
  130. if (result)
  131. goto end_session;
  132. fifo_count = be16_to_cpup((__be16 *)(&data[0]));
  133. if (fifo_count < bytes_per_datum)
  134. goto end_session;
  135. /* fifo count can't be odd number, if it is odd, reset fifo*/
  136. if (fifo_count & 1)
  137. goto flush_fifo;
  138. if (fifo_count > INV_MPU6050_FIFO_THRESHOLD)
  139. goto flush_fifo;
  140. /* Timestamp mismatch. */
  141. if (kfifo_len(&st->timestamps) >
  142. fifo_count / bytes_per_datum + INV_MPU6050_TIME_STAMP_TOR)
  143. goto flush_fifo;
  144. while (fifo_count >= bytes_per_datum) {
  145. result = regmap_bulk_read(st->map, st->reg->fifo_r_w,
  146. data, bytes_per_datum);
  147. if (result)
  148. goto flush_fifo;
  149. result = kfifo_out(&st->timestamps, &timestamp, 1);
  150. /* when there is no timestamp, put timestamp as 0 */
  151. if (result == 0)
  152. timestamp = 0;
  153. result = iio_push_to_buffers_with_timestamp(indio_dev, data,
  154. timestamp);
  155. if (result)
  156. goto flush_fifo;
  157. fifo_count -= bytes_per_datum;
  158. }
  159. end_session:
  160. mutex_unlock(&indio_dev->mlock);
  161. iio_trigger_notify_done(indio_dev->trig);
  162. return IRQ_HANDLED;
  163. flush_fifo:
  164. /* Flush HW and SW FIFOs. */
  165. inv_reset_fifo(indio_dev);
  166. mutex_unlock(&indio_dev->mlock);
  167. iio_trigger_notify_done(indio_dev->trig);
  168. return IRQ_HANDLED;
  169. }