inv_mpu_ring.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  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. spin_lock(&st->time_stamp_lock);
  98. kfifo_in(&st->timestamps, &timestamp, 1);
  99. spin_unlock(&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. u64 *tmp;
  116. mutex_lock(&indio_dev->mlock);
  117. if (!(st->chip_config.accl_fifo_enable |
  118. st->chip_config.gyro_fifo_enable))
  119. goto end_session;
  120. bytes_per_datum = 0;
  121. if (st->chip_config.accl_fifo_enable)
  122. bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR;
  123. if (st->chip_config.gyro_fifo_enable)
  124. bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR;
  125. /*
  126. * read fifo_count register to know how many bytes inside FIFO
  127. * right now
  128. */
  129. result = i2c_smbus_read_i2c_block_data(st->client,
  130. st->reg->fifo_count_h,
  131. INV_MPU6050_FIFO_COUNT_BYTE, data);
  132. if (result != INV_MPU6050_FIFO_COUNT_BYTE)
  133. goto end_session;
  134. fifo_count = be16_to_cpup((__be16 *)(&data[0]));
  135. if (fifo_count < bytes_per_datum)
  136. goto end_session;
  137. /* fifo count can't be odd number, if it is odd, reset fifo*/
  138. if (fifo_count & 1)
  139. goto flush_fifo;
  140. if (fifo_count > INV_MPU6050_FIFO_THRESHOLD)
  141. goto flush_fifo;
  142. /* Timestamp mismatch. */
  143. if (kfifo_len(&st->timestamps) >
  144. fifo_count / bytes_per_datum + INV_MPU6050_TIME_STAMP_TOR)
  145. goto flush_fifo;
  146. while (fifo_count >= bytes_per_datum) {
  147. result = i2c_smbus_read_i2c_block_data(st->client,
  148. st->reg->fifo_r_w,
  149. bytes_per_datum, data);
  150. if (result != bytes_per_datum)
  151. goto flush_fifo;
  152. result = kfifo_out(&st->timestamps, &timestamp, 1);
  153. /* when there is no timestamp, put timestamp as 0 */
  154. if (0 == result)
  155. timestamp = 0;
  156. tmp = (u64 *)data;
  157. tmp[DIV_ROUND_UP(bytes_per_datum, 8)] = timestamp;
  158. result = iio_push_to_buffers(indio_dev, data);
  159. if (result)
  160. goto flush_fifo;
  161. fifo_count -= bytes_per_datum;
  162. }
  163. end_session:
  164. mutex_unlock(&indio_dev->mlock);
  165. iio_trigger_notify_done(indio_dev->trig);
  166. return IRQ_HANDLED;
  167. flush_fifo:
  168. /* Flush HW and SW FIFOs. */
  169. inv_reset_fifo(indio_dev);
  170. inv_clear_kfifo(st);
  171. mutex_unlock(&indio_dev->mlock);
  172. iio_trigger_notify_done(indio_dev->trig);
  173. return IRQ_HANDLED;
  174. }