inv_mpu_ring.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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/i2c.h>
  16. #include <linux/err.h>
  17. #include <linux/delay.h>
  18. #include <linux/sysfs.h>
  19. #include <linux/jiffies.h>
  20. #include <linux/irq.h>
  21. #include <linux/interrupt.h>
  22. #include <linux/kfifo.h>
  23. #include <linux/poll.h>
  24. #include "inv_mpu_iio.h"
  25. int inv_reset_fifo(struct iio_dev *indio_dev)
  26. {
  27. int result;
  28. u8 d;
  29. struct inv_mpu6050_state *st = iio_priv(indio_dev);
  30. /* disable interrupt */
  31. result = inv_mpu6050_write_reg(st, st->reg->int_enable, 0);
  32. if (result) {
  33. dev_err(&st->client->dev, "int_enable failed %d\n", result);
  34. return result;
  35. }
  36. /* disable the sensor output to FIFO */
  37. result = inv_mpu6050_write_reg(st, st->reg->fifo_en, 0);
  38. if (result)
  39. goto reset_fifo_fail;
  40. /* disable fifo reading */
  41. result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, 0);
  42. if (result)
  43. goto reset_fifo_fail;
  44. /* reset FIFO*/
  45. result = inv_mpu6050_write_reg(st, st->reg->user_ctrl,
  46. INV_MPU6050_BIT_FIFO_RST);
  47. if (result)
  48. goto reset_fifo_fail;
  49. /* enable interrupt */
  50. if (st->chip_config.accl_fifo_enable ||
  51. st->chip_config.gyro_fifo_enable) {
  52. result = inv_mpu6050_write_reg(st, st->reg->int_enable,
  53. INV_MPU6050_BIT_DATA_RDY_EN);
  54. if (result)
  55. return result;
  56. }
  57. /* enable FIFO reading and I2C master interface*/
  58. result = inv_mpu6050_write_reg(st, st->reg->user_ctrl,
  59. INV_MPU6050_BIT_FIFO_EN);
  60. if (result)
  61. goto reset_fifo_fail;
  62. /* enable sensor output to FIFO */
  63. d = 0;
  64. if (st->chip_config.gyro_fifo_enable)
  65. d |= INV_MPU6050_BITS_GYRO_OUT;
  66. if (st->chip_config.accl_fifo_enable)
  67. d |= INV_MPU6050_BIT_ACCEL_OUT;
  68. result = inv_mpu6050_write_reg(st, st->reg->fifo_en, d);
  69. if (result)
  70. goto reset_fifo_fail;
  71. return 0;
  72. reset_fifo_fail:
  73. dev_err(&st->client->dev, "reset fifo failed %d\n", result);
  74. result = inv_mpu6050_write_reg(st, st->reg->int_enable,
  75. INV_MPU6050_BIT_DATA_RDY_EN);
  76. return result;
  77. }
  78. static void inv_clear_kfifo(struct inv_mpu6050_state *st)
  79. {
  80. unsigned long flags;
  81. /* take the spin lock sem to avoid interrupt kick in */
  82. spin_lock_irqsave(&st->time_stamp_lock, flags);
  83. kfifo_reset(&st->timestamps);
  84. spin_unlock_irqrestore(&st->time_stamp_lock, flags);
  85. }
  86. /**
  87. * inv_mpu6050_irq_handler() - Cache a timestamp at each data ready interrupt.
  88. */
  89. irqreturn_t inv_mpu6050_irq_handler(int irq, void *p)
  90. {
  91. struct iio_poll_func *pf = p;
  92. struct iio_dev *indio_dev = pf->indio_dev;
  93. struct inv_mpu6050_state *st = iio_priv(indio_dev);
  94. s64 timestamp;
  95. timestamp = iio_get_time_ns();
  96. kfifo_in_spinlocked(&st->timestamps, &timestamp, 1,
  97. &st->time_stamp_lock);
  98. return IRQ_WAKE_THREAD;
  99. }
  100. /**
  101. * inv_mpu6050_read_fifo() - Transfer data from hardware FIFO to KFIFO.
  102. */
  103. irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
  104. {
  105. struct iio_poll_func *pf = p;
  106. struct iio_dev *indio_dev = pf->indio_dev;
  107. struct inv_mpu6050_state *st = iio_priv(indio_dev);
  108. size_t bytes_per_datum;
  109. int result;
  110. u8 data[INV_MPU6050_OUTPUT_DATA_SIZE];
  111. u16 fifo_count;
  112. s64 timestamp;
  113. mutex_lock(&indio_dev->mlock);
  114. if (!(st->chip_config.accl_fifo_enable |
  115. st->chip_config.gyro_fifo_enable))
  116. goto end_session;
  117. bytes_per_datum = 0;
  118. if (st->chip_config.accl_fifo_enable)
  119. bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR;
  120. if (st->chip_config.gyro_fifo_enable)
  121. bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR;
  122. /*
  123. * read fifo_count register to know how many bytes inside FIFO
  124. * right now
  125. */
  126. result = i2c_smbus_read_i2c_block_data(st->client,
  127. st->reg->fifo_count_h,
  128. INV_MPU6050_FIFO_COUNT_BYTE, data);
  129. if (result != INV_MPU6050_FIFO_COUNT_BYTE)
  130. goto end_session;
  131. fifo_count = be16_to_cpup((__be16 *)(&data[0]));
  132. if (fifo_count < bytes_per_datum)
  133. goto end_session;
  134. /* fifo count can't be odd number, if it is odd, reset fifo*/
  135. if (fifo_count & 1)
  136. goto flush_fifo;
  137. if (fifo_count > INV_MPU6050_FIFO_THRESHOLD)
  138. goto flush_fifo;
  139. /* Timestamp mismatch. */
  140. if (kfifo_len(&st->timestamps) >
  141. fifo_count / bytes_per_datum + INV_MPU6050_TIME_STAMP_TOR)
  142. goto flush_fifo;
  143. while (fifo_count >= bytes_per_datum) {
  144. result = i2c_smbus_read_i2c_block_data(st->client,
  145. st->reg->fifo_r_w,
  146. bytes_per_datum, data);
  147. if (result != bytes_per_datum)
  148. goto flush_fifo;
  149. result = kfifo_out(&st->timestamps, &timestamp, 1);
  150. /* when there is no timestamp, put timestamp as 0 */
  151. if (0 == result)
  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. inv_clear_kfifo(st);
  167. mutex_unlock(&indio_dev->mlock);
  168. iio_trigger_notify_done(indio_dev->trig);
  169. return IRQ_HANDLED;
  170. }