blob: bf1b9c498ee8bc760ddd31051d330431b0804048 [file] [log] [blame]
Eiji Iwatsukia71da782018-04-17 11:56:16 -07001/*
2* Copyright (C) 2012-2018 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#define pr_fmt(fmt) "inv_mpu: " fmt
14
15#include <linux/export.h>
16#include <linux/kernel.h>
17#include <linux/device.h>
18#include <linux/slab.h>
19#include <linux/err.h>
20#include <linux/delay.h>
21#include <linux/sysfs.h>
22#include <linux/jiffies.h>
23#include <linux/irq.h>
24#include <linux/interrupt.h>
25#include <linux/kfifo.h>
26#include <linux/poll.h>
27#include <linux/math64.h>
28#include <linux/miscdevice.h>
29
30#include "inv_mpu_iio.h"
31
32static void inv_push_timestamp(struct iio_dev *indio_dev, u64 t)
33{
34 u8 buf[IIO_BUFFER_BYTES];
35 struct inv_mpu_state *st;
36
37 st = iio_priv(indio_dev);
38 if (st->poke_mode_on)
39 memcpy(buf, &st->poke_ts, sizeof(t));
40 else
41 memcpy(buf, &t, sizeof(t));
42 iio_push_to_buffers(indio_dev, buf);
43}
44
45int inv_push_marker_to_buffer(struct inv_mpu_state *st, u16 hdr, int data)
46{
47 struct iio_dev *indio_dev = iio_priv_to_dev(st);
48 u8 buf[IIO_BUFFER_BYTES];
49
50 memcpy(buf, &hdr, sizeof(hdr));
51 memcpy(&buf[4], &data, sizeof(data));
52 iio_push_to_buffers(indio_dev, buf);
53
54 return 0;
55}
56static int inv_calc_precision(struct inv_mpu_state *st)
57{
58 int diff;
59 int init;
60
61 if (st->eis.voting_state != 8)
62 return 0;
63 diff = abs(st->eis.fsync_delay_s[1] - st->eis.fsync_delay_s[0]);
64 init = 0;
65 if (diff)
66 init = st->sensor[SENSOR_GYRO].dur / diff;
67
68 if (abs(init - NSEC_PER_USEC) < (NSEC_PER_USEC >> 3))
69 st->eis.count_precision = init;
70 else
71 st->eis.voting_state = 0;
72
73 pr_debug("dur= %d prc= %d\n", st->sensor[SENSOR_GYRO].dur,
74 st->eis.count_precision);
75
76 return 0;
77}
78
79static s64 calc_frame_ave(struct inv_mpu_state *st, int delay)
80{
81 s64 ts;
82
83 ts = st->eis.current_timestamp - delay;
84#if defined(CONFIG_INV_MPU_IIO_ICM20648) | defined(CONFIG_INV_MPU_IIO_ICM20690)
85 ts -= st->ts_algo.gyro_ts_shift;
86#endif
87 pr_debug("shift= %d ts = %lld\n", st->ts_algo.gyro_ts_shift, ts);
88
89 return ts;
90}
91
92static void inv_push_eis_ring(struct inv_mpu_state *st, int *q, bool sync,
93 s64 t)
94{
95 struct iio_dev *indio_dev = iio_priv_to_dev(st);
96 struct inv_eis *eis = &st->eis;
97 u8 buf[IIO_BUFFER_BYTES];
98 int tmp, ii;
99
100 buf[0] = (EIS_GYRO_HDR & 0xff);
101 buf[1] = (EIS_GYRO_HDR >> 8);
102 memcpy(buf + 4, &q[0], sizeof(q[0]));
103 iio_push_to_buffers(indio_dev, buf);
104 for (ii = 0; ii < 2; ii++)
105 memcpy(buf + 4 * ii, &q[ii + 1], sizeof(q[ii]));
106 iio_push_to_buffers(indio_dev, buf);
107 tmp = eis->frame_count;
108 if (sync)
109 tmp |= 0x80000000;
110 memcpy(buf, &tmp, sizeof(tmp));
111 iio_push_to_buffers(indio_dev, buf);
112 inv_push_timestamp(indio_dev, t);
113}
114static int inv_do_interpolation_gyro(struct inv_mpu_state *st, int *prev,
115 s64 prev_t, int *curr, s64 curr_t, s64 t, bool trigger)
116{
117 int i;
118 int out[3];
119#if defined(CONFIG_INV_MPU_IIO_ICM20648) | defined(CONFIG_INV_MPU_IIO_ICM20690)
120 prev_t -= st->ts_algo.gyro_ts_shift;
121 prev_t += MPU_4X_TS_GYRO_SHIFT;
122 curr_t -= st->ts_algo.gyro_ts_shift;
123 curr_t += MPU_4X_TS_GYRO_SHIFT;
124#endif
125 if ((t > prev_t) && (t < curr_t)) {
126 for (i = 0; i < 3; i++)
127 out[i] = (int)div_s64((s64)(curr[i] - prev[i]) *
128 (s64)(t - prev_t), curr_t - prev_t) + prev[i];
129 } else if (t < prev_t) {
130 for (i = 0; i < 3; i++)
131 out[i] = prev[i];
132 } else {
133 for (i = 0; i < 3; i++)
134 out[i] = curr[i];
135 }
136 pr_debug("prev= %lld t = %lld curr= %lld\n", prev_t, t, curr_t);
137 pr_debug("prev = %d, %d, %d\n", prev[0], prev[1], prev[2]);
138 pr_debug("curr = %d, %d, %d\n", curr[0], curr[1], curr[2]);
139 pr_debug("out = %d, %d, %d\n", out[0], out[1], out[2]);
140 inv_push_eis_ring(st, out, trigger, t);
141
142 return 0;
143}
144#if defined(CONFIG_INV_MPU_IIO_ICM20648) | defined(CONFIG_INV_MPU_IIO_ICM20690)
145static void inv_handle_triggered_eis(struct inv_mpu_state *st)
146{
147 struct inv_eis *eis = &st->eis;
148 int delay;
149
150 if (st->eis.eis_frame) {
151 inv_calc_precision(st);
152 delay = ((int)st->eis.fsync_delay) * st->eis.count_precision;
153 eis->fsync_timestamp = calc_frame_ave(st, delay);
154 inv_do_interpolation_gyro(st,
155 st->eis.prev_gyro, st->eis.prev_timestamp,
156 st->eis.current_gyro, st->eis.current_timestamp,
157 eis->fsync_timestamp, true);
158 pr_debug("fsync=%lld, curr=%lld, delay=%d\n",
159 eis->fsync_timestamp, eis->current_timestamp, delay);
160 inv_push_eis_ring(st, st->eis.current_gyro, false,
161 st->eis.current_timestamp - st->ts_algo.gyro_ts_shift
162 + MPU_4X_TS_GYRO_SHIFT);
163 eis->last_fsync_timestamp = eis->fsync_timestamp;
164 } else {
165 pr_debug("cur= %lld\n", st->eis.current_timestamp);
166 inv_push_eis_ring(st, st->eis.current_gyro, false,
167 st->eis.current_timestamp - st->ts_algo.gyro_ts_shift
168 + MPU_4X_TS_GYRO_SHIFT);
169 }
170}
171#else
172static void inv_handle_triggered_eis(struct inv_mpu_state *st)
173{
174 struct inv_eis *eis = &st->eis;
175 int delay;
176
177 if ((st->eis.eis_frame && (st->eis.fsync_delay != 5)) ||
178 (st->eis.eis_frame && (st->eis.fsync_delay == 5) &&
179 (!st->eis.current_sync))
180 ) {
181 inv_calc_precision(st);
182 delay = ((int)st->eis.fsync_delay) * st->eis.count_precision;
183 eis->fsync_timestamp = calc_frame_ave(st, delay);
184 inv_do_interpolation_gyro(st,
185 st->eis.prev_gyro, st->eis.prev_timestamp,
186 st->eis.current_gyro, st->eis.current_timestamp,
187 eis->fsync_timestamp, true);
188 pr_debug("fsync=%lld, curr=%lld, delay=%d\n",
189 eis->fsync_timestamp, eis->current_timestamp, delay);
190 inv_push_eis_ring(st, st->eis.current_gyro, false,
191 st->eis.current_timestamp);
192 eis->last_fsync_timestamp = eis->fsync_timestamp;
193 st->eis.eis_frame = false;
194 } else {
195 st->eis.current_sync = false;
196 pr_debug("cur= %lld\n", st->eis.current_timestamp);
197 inv_push_eis_ring(st, st->eis.current_gyro, false,
198 st->eis.current_timestamp);
199 }
200}
201#endif
202static void inv_push_eis_buffer(struct inv_mpu_state *st, u64 t, int *q)
203{
204 int ii;
205
206 if (st->eis.eis_triggered) {
207 for (ii = 0; ii < 3; ii++)
208 st->eis.prev_gyro[ii] = st->eis.current_gyro[ii];
209 st->eis.prev_timestamp = st->eis.current_timestamp;
210
211 for (ii = 0; ii < 3; ii++)
212 st->eis.current_gyro[ii] = q[ii];
213 st->eis.current_timestamp = t;
214 inv_handle_triggered_eis(st);
215 } else {
216 for (ii = 0; ii < 3; ii++)
217 st->eis.current_gyro[ii] = q[ii];
218 st->eis.current_timestamp = t;
219 }
220}
221static int inv_push_16bytes_final(struct inv_mpu_state *st, int j,
222 s32 *q, u64 t, s16 accur)
223{
224 struct iio_dev *indio_dev = iio_priv_to_dev(st);
225 u8 buf[IIO_BUFFER_BYTES];
226 int ii;
227
228 memcpy(buf, &st->sensor_l[j].header, sizeof(st->sensor_l[j].header));
229 memcpy(buf + 2, &accur, sizeof(accur));
230 memcpy(buf + 4, &q[0], sizeof(q[0]));
231 iio_push_to_buffers(indio_dev, buf);
232 for (ii = 0; ii < 2; ii++)
233 memcpy(buf + 4 * ii, &q[ii + 1], sizeof(q[ii]));
234 iio_push_to_buffers(indio_dev, buf);
235 inv_push_timestamp(indio_dev, t);
236 st->sensor_l[j].counter = 0;
237 if (st->sensor_l[j].wake_on)
238 st->wake_sensor_received = true;
239
240 return 0;
241}
242int inv_push_16bytes_buffer(struct inv_mpu_state *st, u16 sensor,
243 u64 t, int *q, s16 accur)
244{
245 int j;
246
247 for (j = 0; j < SENSOR_L_NUM_MAX; j++) {
248 if (st->sensor_l[j].on && (st->sensor_l[j].base == sensor)) {
249 st->sensor_l[j].counter++;
250 if ((st->sensor_l[j].div != 0xffff) &&
251 (st->sensor_l[j].counter >=
252 st->sensor_l[j].div)) {
253 pr_debug(
254 "Sensor_l = %d sensor = %d header [%04X] div [%d] ts [%lld] %d %d %d\n",
255 j, sensor,
256 st->sensor_l[j].header,
257 st->sensor_l[j].div,
258 t, q[0], q[1], q[2]);
259 inv_push_16bytes_final(st, j, q, t, accur);
260 }
261 }
262 }
263 return 0;
264}
265
266void inv_convert_and_push_16bytes(struct inv_mpu_state *st, u16 hdr,
267 u8 *d, u64 t, s8 *m)
268{
269 int i, j;
270 s32 in[3], out[3];
271
272 for (i = 0; i < 3; i++)
273 in[i] = be32_to_int(d + i * 4);
274 /* multiply with orientation matrix can be optimized like this */
275 for (i = 0; i < 3; i++)
276 for (j = 0; j < 3; j++)
277 if (m[i * 3 + j])
278 out[i] = in[j] * m[i * 3 + j];
279
280 inv_push_16bytes_buffer(st, hdr, t, out, 0);
281}
282
283void inv_convert_and_push_8bytes(struct inv_mpu_state *st, u16 hdr,
284 u8 *d, u64 t, s8 *m)
285{
286 int i, j;
287 s16 in[3], out[3];
288
289 for (i = 0; i < 3; i++)
290 in[i] = be16_to_cpup((__be16 *) (d + i * 2));
291
292 /* multiply with orientation matrix can be optimized like this */
293 for (i = 0; i < 3; i++)
294 for (j = 0; j < 3; j++)
295 if (m[i * 3 + j])
296 out[i] = in[j] * m[i * 3 + j];
297
298 inv_push_8bytes_buffer(st, hdr, t, out);
299}
Puneet yatnala6cf41402018-05-18 10:30:41 +0530300#ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING
301static void store_acc_boot_sample(struct inv_mpu_state *st, u64 t,
302 s16 x, s16 y, s16 z)
303{
304 if (false == st->acc_buffer_inv_samples)
305 return;
306 st->timestamp.tv64 = t;
307 if (ktime_to_timespec(st->timestamp).tv_sec
308 < st->max_buffer_time) {
309 if (st->acc_bufsample_cnt < INV_ACC_MAXSAMPLE) {
310 st->inv_acc_samplist[st->
311 acc_bufsample_cnt]->xyz[0] = x;
312 st->inv_acc_samplist[st->
313 acc_bufsample_cnt]->xyz[1] = y;
314 st->inv_acc_samplist[st->
315 acc_bufsample_cnt]->xyz[2] = z;
316 st->inv_acc_samplist[st->
317 acc_bufsample_cnt]->tsec =
318 ktime_to_timespec(st
319 ->timestamp).tv_sec;
320 st->inv_acc_samplist[st->
321 acc_bufsample_cnt]->tnsec =
322 ktime_to_timespec(st
323 ->timestamp).tv_nsec;
324 st->acc_bufsample_cnt++;
325 }
326 } else {
327 dev_info(st->dev, "End of ACC buffering %d\n",
328 st->acc_bufsample_cnt);
329 st->acc_buffer_inv_samples = false;
330 }
331}
332static void store_gyro_boot_sample(struct inv_mpu_state *st, u64 t,
333 s16 x, s16 y, s16 z)
334{
335
336 if (false == st->gyro_buffer_inv_samples)
337 return;
338 st->timestamp.tv64 = t;
339 if (ktime_to_timespec(st->timestamp).tv_sec
340 < st->max_buffer_time) {
341 if (st->gyro_bufsample_cnt < INV_GYRO_MAXSAMPLE) {
342 st->inv_gyro_samplist[st->
343 gyro_bufsample_cnt]->xyz[0] = x;
344 st->inv_gyro_samplist[st->
345 gyro_bufsample_cnt]->xyz[1] = y;
346 st->inv_gyro_samplist[st->
347 gyro_bufsample_cnt]->xyz[2] = z;
348 st->inv_gyro_samplist[st->
349 gyro_bufsample_cnt]->tsec =
350 ktime_to_timespec(st->
351 timestamp).tv_sec;
352 st->inv_gyro_samplist[st->
353 gyro_bufsample_cnt]->tnsec =
354 ktime_to_timespec(st->
355 timestamp).tv_nsec;
356 st->gyro_bufsample_cnt++;
357 }
358 } else {
359 dev_info(st->dev, "End of GYRO buffering %d\n",
360 st->gyro_bufsample_cnt);
361 st->gyro_buffer_inv_samples = false;
362 }
363}
364#else
365static void store_acc_boot_sample(struct inv_mpu_state *st, u64 t,
366 s16 x, s16 y, s16 z)
367{
368}
369static void store_gyro_boot_sample(struct inv_mpu_state *st, u64 t,
370 s16 x, s16 y, s16 z)
371{
372}
373#endif
Eiji Iwatsukia71da782018-04-17 11:56:16 -0700374
375int inv_push_special_8bytes_buffer(struct inv_mpu_state *st,
376 u16 hdr, u64 t, s16 *d)
377{
378 struct iio_dev *indio_dev = iio_priv_to_dev(st);
379 u8 buf[IIO_BUFFER_BYTES];
380 int j;
381
382 memcpy(buf, &hdr, sizeof(hdr));
383 memcpy(&buf[2], &d[0], sizeof(d[0]));
384 for (j = 0; j < 2; j++)
385 memcpy(&buf[4 + j * 2], &d[j + 1], sizeof(d[j]));
Puneet Yatnal3cbaa6f2020-01-08 18:09:41 +0530386 mutex_lock(&st->gyro_sensor_buff);
Puneet yatnala6cf41402018-05-18 10:30:41 +0530387 store_gyro_boot_sample(st, t, d[0], d[1], d[2]);
Puneet Yatnal3cbaa6f2020-01-08 18:09:41 +0530388 mutex_unlock(&st->gyro_sensor_buff);
Eiji Iwatsukia71da782018-04-17 11:56:16 -0700389 iio_push_to_buffers(indio_dev, buf);
390 inv_push_timestamp(indio_dev, t);
391
392 return 0;
393}
394
395static int inv_s16_gyro_push(struct inv_mpu_state *st, int i, s16 *raw, u64 t)
396{
397 if (st->sensor_l[i].on) {
398 st->sensor_l[i].counter++;
399 if ((st->sensor_l[i].div != 0xffff) &&
400 (st->sensor_l[i].counter >= st->sensor_l[i].div)) {
401 inv_push_special_8bytes_buffer(st,
402 st->sensor_l[i].header, t, raw);
403 st->sensor_l[i].counter = 0;
404 if (st->sensor_l[i].wake_on)
405 st->wake_sensor_received = true;
406 }
407 }
408
409 return 0;
410}
411
412static int inv_s32_gyro_push(struct inv_mpu_state *st, int i, s32 *calib, u64 t)
413{
414 if (st->sensor_l[i].on) {
415 st->sensor_l[i].counter++;
416 if ((st->sensor_l[i].div != 0xffff) &&
417 (st->sensor_l[i].counter >= st->sensor_l[i].div)) {
418 inv_push_16bytes_final(st, i, calib, t, 0);
419 st->sensor_l[i].counter = 0;
420 if (st->sensor_l[i].wake_on)
421 st->wake_sensor_received = true;
422 }
423 }
424
425 return 0;
426}
427
428int inv_push_gyro_data(struct inv_mpu_state *st, s16 *raw, s32 *calib, u64 t)
429{
430 int gyro_data[] = {SENSOR_L_GYRO, SENSOR_L_GYRO_WAKE};
431 int calib_data[] = {SENSOR_L_GYRO_CAL, SENSOR_L_GYRO_CAL_WAKE};
432 int i;
433
434 if (st->sensor_l[SENSOR_L_EIS_GYRO].on)
435 inv_push_eis_buffer(st, t, calib);
436
437 for (i = 0; i < 2; i++)
438 inv_s16_gyro_push(st, gyro_data[i], raw, t);
439 for (i = 0; i < 2; i++)
440 inv_s32_gyro_push(st, calib_data[i], calib, t);
441
442 return 0;
443}
444int inv_push_8bytes_buffer(struct inv_mpu_state *st, u16 sensor, u64 t, s16 *d)
445{
446 struct iio_dev *indio_dev = iio_priv_to_dev(st);
447 u8 buf[IIO_BUFFER_BYTES];
448 int ii, j;
449
450 if ((sensor == STEP_DETECTOR_HDR) ||
451 (sensor == STEP_DETECTOR_WAKE_HDR)) {
452 memcpy(buf, &sensor, sizeof(sensor));
453 memcpy(&buf[2], &d[0], sizeof(d[0]));
454 for (j = 0; j < 2; j++)
455 memcpy(&buf[4 + j * 2], &d[j + 1], sizeof(d[j]));
456 iio_push_to_buffers(indio_dev, buf);
457 inv_push_timestamp(indio_dev, t);
458 if (sensor == STEP_DETECTOR_WAKE_HDR)
459 st->wake_sensor_received = true;
460 return 0;
461 }
462 for (ii = 0; ii < SENSOR_L_NUM_MAX; ii++) {
463 if (st->sensor_l[ii].on &&
464 (st->sensor_l[ii].base == sensor) &&
465 (st->sensor_l[ii].div != 0xffff)) {
466 st->sensor_l[ii].counter++;
467 if (st->sensor_l[ii].counter >= st->sensor_l[ii].div) {
468 pr_debug(
469 "Sensor_l = %d sensor = %d header [%04X] div [%d] ts [%lld] %d %d %d\n",
470 ii, sensor, st->sensor_l[ii].header,
471 st->sensor_l[ii].div, t, d[0], d[1], d[2]);
472
473 memcpy(buf, &st->sensor_l[ii].header,
474 sizeof(st->sensor_l[ii].header));
475 memcpy(&buf[2], &d[0], sizeof(d[0]));
476 for (j = 0; j < 2; j++)
477 memcpy(&buf[4 + j * 2], &d[j + 1],
478 sizeof(d[j]));
Puneet Yatnal3cbaa6f2020-01-08 18:09:41 +0530479 mutex_lock(&st->acc_sensor_buff);
Puneet yatnala6cf41402018-05-18 10:30:41 +0530480 store_acc_boot_sample(st, t, d[0], d[1], d[2]);
Puneet Yatnal3cbaa6f2020-01-08 18:09:41 +0530481 mutex_unlock(&st->acc_sensor_buff);
Eiji Iwatsukia71da782018-04-17 11:56:16 -0700482 iio_push_to_buffers(indio_dev, buf);
483 inv_push_timestamp(indio_dev, t);
484 st->sensor_l[ii].counter = 0;
485 if (st->sensor_l[ii].wake_on)
486 st->wake_sensor_received = true;
487 }
488 }
489 }
490
491 return 0;
492}
493#ifdef CONFIG_INV_MPU_IIO_ICM20648
494/* Implemented activity to string function for BAC test */
495#define TILT_DETECTED 0x1000
496#define NONE 0x00
497#define DRIVE 0x01
498#define WALK 0x02
499#define RUN 0x04
500#define BIKE 0x08
501#define TILT 0x10
502#define STILL 0x20
503#define DRIVE_WALK (DRIVE | WALK)
504#define DRIVE_RUN (DRIVE | RUN)
505
506char *act_string(s16 data)
507{
508 data &= (~TILT);
509 switch (data) {
510 case NONE:
511 return "None";
512 case DRIVE:
513 return "Drive";
514 case WALK:
515 return "Walk";
516 case RUN:
517 return "Run";
518 case BIKE:
519 return "Bike";
520 case STILL:
521 return "Still";
522 case DRIVE_WALK:
523 return "drive and walk";
524 case DRIVE_RUN:
525 return "drive and run";
526 default:
527 return "Unknown";
528 }
529 return "Unknown";
530}
531
532char *inv_tilt_check(s16 data)
533{
534 if (data & TILT)
535 return "Tilt";
536 else
537 return "None";
538}
539
540int inv_push_8bytes_kf(struct inv_mpu_state *st, u16 hdr, u64 t, s16 *d)
541{
542 struct iio_dev *indio_dev = iio_priv_to_dev(st);
543 u8 buf[IIO_BUFFER_BYTES];
544 int i;
545
546 if (st->chip_config.activity_on) {
547 memcpy(buf, &hdr, sizeof(hdr));
548 for (i = 0; i < 3; i++)
549 memcpy(&buf[2 + i * 2], &d[i], sizeof(d[i]));
550
551 kfifo_in(&st->kf, buf, IIO_BUFFER_BYTES);
552 memcpy(buf, &t, sizeof(t));
553 kfifo_in(&st->kf, buf, IIO_BUFFER_BYTES);
554 st->activity_size += IIO_BUFFER_BYTES * 2;
555 }
556 if (st->chip_config.tilt_enable) {
557 pr_debug("d[0] = %04X, [%X : %s] to [%X : %s]",
558 d[0], d[0] & 0x00FF,
559 inv_tilt_check(d[0] & 0x00FF),
560 (d[0] & 0xFF00) >> 8, inv_tilt_check((d[0] & 0xFF00) >> 8));
561 sysfs_notify(&indio_dev->dev.kobj, NULL, "poll_tilt");
562 }
563
564 pr_debug("d[0] = %04X, [%X : %s] to [%X : %s]", d[0], d[0] & 0x00FF,
565 act_string(d[0] & 0x00FF),
566 (d[0] & 0xFF00) >> 8, act_string((d[0] & 0xFF00) >> 8));
567
568 read_be32_from_mem(st, &st->bac_drive_conf, BAC_DRIVE_CONFIDENCE);
569 read_be32_from_mem(st, &st->bac_walk_conf, BAC_WALK_CONFIDENCE);
570 read_be32_from_mem(st, &st->bac_smd_conf, BAC_SMD_CONFIDENCE);
571 read_be32_from_mem(st, &st->bac_bike_conf, BAC_BIKE_CONFIDENCE);
572 read_be32_from_mem(st, &st->bac_still_conf, BAC_STILL_CONFIDENCE);
573 read_be32_from_mem(st, &st->bac_run_conf, BAC_RUN_CONFIDENCE);
574
575 return 0;
576}
577#endif
578
579int inv_send_steps(struct inv_mpu_state *st, int step, u64 ts)
580{
581 s16 s[3];
582
583 s[0] = 0;
584 s[1] = (s16) (step & 0xffff);
585 s[2] = (s16) ((step >> 16) & 0xffff);
586 if (st->step_counter_l_on)
587 inv_push_special_8bytes_buffer(st, STEP_COUNTER_HDR, ts, s);
588 if (st->step_counter_wake_l_on) {
589 inv_push_special_8bytes_buffer(st, STEP_COUNTER_WAKE_HDR,
590 ts, s);
591 st->wake_sensor_received = true;
592 }
593 return 0;
594}
595
596void inv_push_step_indicator(struct inv_mpu_state *st, u64 t)
597{
598 s16 sen[3];
599#define STEP_INDICATOR_HEADER 0x0001
600
601 sen[0] = 0;
602 sen[1] = 0;
603 sen[2] = 0;
604 inv_push_8bytes_buffer(st, STEP_INDICATOR_HEADER, t, sen);
605}
606
607/*
608 * inv_irq_handler() - Cache a timestamp at each data ready interrupt.
609 */
610static irqreturn_t inv_irq_handler(int irq, void *dev_id)
611{
612 return IRQ_WAKE_THREAD;
613}
614
Eiji Iwatsukib1c8f252018-05-01 10:26:25 -0700615#ifdef TIMER_BASED_BATCHING
616static enum hrtimer_restart inv_batch_timer_handler(struct hrtimer *timer)
617{
618 struct inv_mpu_state *st =
619 container_of(timer, struct inv_mpu_state, hr_batch_timer);
620
621 if (st->chip_config.gyro_enable || st->chip_config.accel_enable) {
622 hrtimer_forward_now(&st->hr_batch_timer,
623 ns_to_ktime(st->batch_timeout));
624 schedule_work(&st->batch_work);
625 return HRTIMER_RESTART;
626 }
627 st->is_batch_timer_running = 0;
628 return HRTIMER_NORESTART;
629}
630#endif
631
Eiji Iwatsukia71da782018-04-17 11:56:16 -0700632void inv_mpu_unconfigure_ring(struct iio_dev *indio_dev)
633{
634 struct inv_mpu_state *st = iio_priv(indio_dev);
635#ifdef KERNEL_VERSION_4_X
636 devm_free_irq(st->dev, st->irq, st);
637 devm_iio_kfifo_free(st->dev, indio_dev->buffer);
638#else
639 free_irq(st->irq, st);
640 iio_kfifo_free(indio_dev->buffer);
641#endif
642};
643EXPORT_SYMBOL_GPL(inv_mpu_unconfigure_ring);
644
645#ifndef KERNEL_VERSION_4_X
646static int inv_predisable(struct iio_dev *indio_dev)
647{
648 return 0;
649}
650
651static int inv_preenable(struct iio_dev *indio_dev)
652{
653 return 0;
654}
655
656static const struct iio_buffer_setup_ops inv_mpu_ring_setup_ops = {
657 .preenable = &inv_preenable,
658 .predisable = &inv_predisable,
659};
660#endif
661
662int inv_mpu_configure_ring(struct iio_dev *indio_dev)
663{
664 int ret;
665 struct inv_mpu_state *st = iio_priv(indio_dev);
666 struct iio_buffer *ring;
667
Eiji Iwatsukib1c8f252018-05-01 10:26:25 -0700668#ifdef TIMER_BASED_BATCHING
669 /* configure hrtimer */
670 hrtimer_init(&st->hr_batch_timer, CLOCK_BOOTTIME, HRTIMER_MODE_REL);
671 st->hr_batch_timer.function = inv_batch_timer_handler;
672 INIT_WORK(&st->batch_work, inv_batch_work);
673#endif
Eiji Iwatsukia71da782018-04-17 11:56:16 -0700674#ifdef KERNEL_VERSION_4_X
675 ring = devm_iio_kfifo_allocate(st->dev);
676 if (!ring)
677 return -ENOMEM;
678 ring->scan_timestamp = true;
679 iio_device_attach_buffer(indio_dev, ring);
680 ret = devm_request_threaded_irq(st->dev,
681 st->irq,
682 inv_irq_handler,
683 inv_read_fifo,
684 IRQF_TRIGGER_RISING | IRQF_SHARED,
685 "inv_irq",
686 st);
687 if (ret) {
688 devm_iio_kfifo_free(st->dev, ring);
689 return ret;
690 }
691
692 // this mode does not use ops
693 indio_dev->modes = INDIO_ALL_BUFFER_MODES;
694
695 return ret;
696#else
697 ring = iio_kfifo_allocate(indio_dev);
698 if (!ring)
699 return -ENOMEM;
700 indio_dev->buffer = ring;
701 /* setup ring buffer */
702 ring->scan_timestamp = true;
703 indio_dev->setup_ops = &inv_mpu_ring_setup_ops;
704 ret = request_threaded_irq(st->irq,
705 inv_irq_handler,
706 inv_read_fifo,
707 IRQF_TRIGGER_RISING | IRQF_SHARED,
708 "inv_irq",
709 st);
710 if (ret)
711 goto error_iio_sw_rb_free;
712
713 indio_dev->modes |= INDIO_BUFFER_HARDWARE;
714
715 return 0;
716error_iio_sw_rb_free:
717 iio_kfifo_free(indio_dev->buffer);
718
719 return ret;
720#endif
721}
722EXPORT_SYMBOL_GPL(inv_mpu_configure_ring);