1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/module.h>
15#include <linux/slab.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
26static void inv_clear_kfifo(struct inv_mpu6050_state *st)
27{
28 unsigned long flags;
29
30
31 spin_lock_irqsave(&st->time_stamp_lock, flags);
32 kfifo_reset(&st->timestamps);
33 spin_unlock_irqrestore(&st->time_stamp_lock, flags);
34}
35
36int inv_reset_fifo(struct iio_dev *indio_dev)
37{
38 int result;
39 u8 d;
40 struct inv_mpu6050_state *st = iio_priv(indio_dev);
41
42
43 result = regmap_write(st->map, st->reg->int_enable, 0);
44 if (result) {
45 dev_err(regmap_get_device(st->map), "int_enable failed %d\n",
46 result);
47 return result;
48 }
49
50 result = regmap_write(st->map, st->reg->fifo_en, 0);
51 if (result)
52 goto reset_fifo_fail;
53
54 result = regmap_write(st->map, st->reg->user_ctrl, 0);
55 if (result)
56 goto reset_fifo_fail;
57
58
59 result = regmap_write(st->map, st->reg->user_ctrl,
60 INV_MPU6050_BIT_FIFO_RST);
61 if (result)
62 goto reset_fifo_fail;
63
64
65 inv_clear_kfifo(st);
66
67
68 if (st->chip_config.accl_fifo_enable ||
69 st->chip_config.gyro_fifo_enable) {
70 result = regmap_write(st->map, st->reg->int_enable,
71 INV_MPU6050_BIT_DATA_RDY_EN);
72 if (result)
73 return result;
74 }
75
76 result = regmap_write(st->map, st->reg->user_ctrl,
77 INV_MPU6050_BIT_FIFO_EN);
78 if (result)
79 goto reset_fifo_fail;
80
81 d = 0;
82 if (st->chip_config.gyro_fifo_enable)
83 d |= INV_MPU6050_BITS_GYRO_OUT;
84 if (st->chip_config.accl_fifo_enable)
85 d |= INV_MPU6050_BIT_ACCEL_OUT;
86 result = regmap_write(st->map, st->reg->fifo_en, d);
87 if (result)
88 goto reset_fifo_fail;
89
90 return 0;
91
92reset_fifo_fail:
93 dev_err(regmap_get_device(st->map), "reset fifo failed %d\n", result);
94 result = regmap_write(st->map, st->reg->int_enable,
95 INV_MPU6050_BIT_DATA_RDY_EN);
96
97 return result;
98}
99
100
101
102
103irqreturn_t inv_mpu6050_irq_handler(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 s64 timestamp;
109
110 timestamp = iio_get_time_ns(indio_dev);
111 kfifo_in_spinlocked(&st->timestamps, ×tamp, 1,
112 &st->time_stamp_lock);
113
114 return IRQ_WAKE_THREAD;
115}
116
117
118
119
120irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
121{
122 struct iio_poll_func *pf = p;
123 struct iio_dev *indio_dev = pf->indio_dev;
124 struct inv_mpu6050_state *st = iio_priv(indio_dev);
125 size_t bytes_per_datum;
126 int result;
127 u8 data[INV_MPU6050_OUTPUT_DATA_SIZE];
128 u16 fifo_count;
129 s64 timestamp;
130
131 mutex_lock(&st->lock);
132 if (!(st->chip_config.accl_fifo_enable |
133 st->chip_config.gyro_fifo_enable))
134 goto end_session;
135 bytes_per_datum = 0;
136 if (st->chip_config.accl_fifo_enable)
137 bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR;
138
139 if (st->chip_config.gyro_fifo_enable)
140 bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR;
141
142
143
144
145
146 result = regmap_bulk_read(st->map, st->reg->fifo_count_h, data,
147 INV_MPU6050_FIFO_COUNT_BYTE);
148 if (result)
149 goto end_session;
150 fifo_count = be16_to_cpup((__be16 *)(&data[0]));
151 if (fifo_count < bytes_per_datum)
152 goto end_session;
153
154 if (fifo_count & 1)
155 goto flush_fifo;
156 if (fifo_count > INV_MPU6050_FIFO_THRESHOLD)
157 goto flush_fifo;
158
159 if (kfifo_len(&st->timestamps) >
160 fifo_count / bytes_per_datum + INV_MPU6050_TIME_STAMP_TOR)
161 goto flush_fifo;
162 while (fifo_count >= bytes_per_datum) {
163 result = regmap_bulk_read(st->map, st->reg->fifo_r_w,
164 data, bytes_per_datum);
165 if (result)
166 goto flush_fifo;
167
168 result = kfifo_out(&st->timestamps, ×tamp, 1);
169
170 if (result == 0)
171 timestamp = 0;
172
173 result = iio_push_to_buffers_with_timestamp(indio_dev, data,
174 timestamp);
175 if (result)
176 goto flush_fifo;
177 fifo_count -= bytes_per_datum;
178 }
179
180end_session:
181 mutex_unlock(&st->lock);
182 iio_trigger_notify_done(indio_dev->trig);
183
184 return IRQ_HANDLED;
185
186flush_fifo:
187
188 inv_reset_fifo(indio_dev);
189 mutex_unlock(&st->lock);
190 iio_trigger_notify_done(indio_dev->trig);
191
192 return IRQ_HANDLED;
193}
194