inv_mpu_ring.c 5.3 KB

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