2 * Copyright (C) 2012 Invensense, Inc.
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.
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.
14 #include <linux/module.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"
27 int inv_reset_fifo(struct iio_dev
*indio_dev
)
31 struct inv_mpu6050_state
*st
= iio_priv(indio_dev
);
33 /* disable interrupt */
34 result
= inv_mpu6050_write_reg(st
, st
->reg
->int_enable
, 0);
36 dev_err(&st
->client
->dev
, "int_enable failed %d\n", result
);
39 /* disable the sensor output to FIFO */
40 result
= inv_mpu6050_write_reg(st
, st
->reg
->fifo_en
, 0);
43 /* disable fifo reading */
44 result
= inv_mpu6050_write_reg(st
, st
->reg
->user_ctrl
, 0);
49 result
= inv_mpu6050_write_reg(st
, st
->reg
->user_ctrl
,
50 INV_MPU6050_BIT_FIFO_RST
);
53 /* enable interrupt */
54 if (st
->chip_config
.accl_fifo_enable
||
55 st
->chip_config
.gyro_fifo_enable
) {
56 result
= inv_mpu6050_write_reg(st
, st
->reg
->int_enable
,
57 INV_MPU6050_BIT_DATA_RDY_EN
);
61 /* enable FIFO reading and I2C master interface*/
62 result
= inv_mpu6050_write_reg(st
, st
->reg
->user_ctrl
,
63 INV_MPU6050_BIT_FIFO_EN
);
66 /* enable sensor output to FIFO */
68 if (st
->chip_config
.gyro_fifo_enable
)
69 d
|= INV_MPU6050_BITS_GYRO_OUT
;
70 if (st
->chip_config
.accl_fifo_enable
)
71 d
|= INV_MPU6050_BIT_ACCEL_OUT
;
72 result
= inv_mpu6050_write_reg(st
, st
->reg
->fifo_en
, d
);
79 dev_err(&st
->client
->dev
, "reset fifo failed %d\n", result
);
80 result
= inv_mpu6050_write_reg(st
, st
->reg
->int_enable
,
81 INV_MPU6050_BIT_DATA_RDY_EN
);
86 static void inv_clear_kfifo(struct inv_mpu6050_state
*st
)
90 /* take the spin lock sem to avoid interrupt kick in */
91 spin_lock_irqsave(&st
->time_stamp_lock
, flags
);
92 kfifo_reset(&st
->timestamps
);
93 spin_unlock_irqrestore(&st
->time_stamp_lock
, flags
);
97 * inv_mpu6050_irq_handler() - Cache a timestamp at each data ready interrupt.
99 irqreturn_t
inv_mpu6050_irq_handler(int irq
, void *p
)
101 struct iio_poll_func
*pf
= p
;
102 struct iio_dev
*indio_dev
= pf
->indio_dev
;
103 struct inv_mpu6050_state
*st
= iio_priv(indio_dev
);
106 timestamp
= iio_get_time_ns();
107 kfifo_in_spinlocked(&st
->timestamps
, ×tamp
, 1,
108 &st
->time_stamp_lock
);
110 return IRQ_WAKE_THREAD
;
114 * inv_mpu6050_read_fifo() - Transfer data from hardware FIFO to KFIFO.
116 irqreturn_t
inv_mpu6050_read_fifo(int irq
, void *p
)
118 struct iio_poll_func
*pf
= p
;
119 struct iio_dev
*indio_dev
= pf
->indio_dev
;
120 struct inv_mpu6050_state
*st
= iio_priv(indio_dev
);
121 size_t bytes_per_datum
;
123 u8 data
[INV_MPU6050_OUTPUT_DATA_SIZE
];
127 mutex_lock(&indio_dev
->mlock
);
128 if (!(st
->chip_config
.accl_fifo_enable
|
129 st
->chip_config
.gyro_fifo_enable
))
132 if (st
->chip_config
.accl_fifo_enable
)
133 bytes_per_datum
+= INV_MPU6050_BYTES_PER_3AXIS_SENSOR
;
135 if (st
->chip_config
.gyro_fifo_enable
)
136 bytes_per_datum
+= INV_MPU6050_BYTES_PER_3AXIS_SENSOR
;
139 * read fifo_count register to know how many bytes inside FIFO
142 result
= i2c_smbus_read_i2c_block_data(st
->client
,
143 st
->reg
->fifo_count_h
,
144 INV_MPU6050_FIFO_COUNT_BYTE
, data
);
145 if (result
!= INV_MPU6050_FIFO_COUNT_BYTE
)
147 fifo_count
= be16_to_cpup((__be16
*)(&data
[0]));
148 if (fifo_count
< bytes_per_datum
)
150 /* fifo count can't be odd number, if it is odd, reset fifo*/
153 if (fifo_count
> INV_MPU6050_FIFO_THRESHOLD
)
155 /* Timestamp mismatch. */
156 if (kfifo_len(&st
->timestamps
) >
157 fifo_count
/ bytes_per_datum
+ INV_MPU6050_TIME_STAMP_TOR
)
159 while (fifo_count
>= bytes_per_datum
) {
160 result
= i2c_smbus_read_i2c_block_data(st
->client
,
162 bytes_per_datum
, data
);
163 if (result
!= bytes_per_datum
)
166 result
= kfifo_out(&st
->timestamps
, ×tamp
, 1);
167 /* when there is no timestamp, put timestamp as 0 */
171 result
= iio_push_to_buffers_with_timestamp(indio_dev
, data
,
175 fifo_count
-= bytes_per_datum
;
179 mutex_unlock(&indio_dev
->mlock
);
180 iio_trigger_notify_done(indio_dev
->trig
);
185 /* Flush HW and SW FIFOs. */
186 inv_reset_fifo(indio_dev
);
188 mutex_unlock(&indio_dev
->mlock
);
189 iio_trigger_notify_done(indio_dev
->trig
);