1
2
3
4
5
6#include <linux/kernel.h>
7#include <linux/device.h>
8#include <linux/mutex.h>
9#include <linux/pm_runtime.h>
10#include <linux/regmap.h>
11#include <linux/delay.h>
12#include <linux/iio/iio.h>
13#include <linux/iio/buffer.h>
14
15#include "inv_icm42600.h"
16#include "inv_icm42600_timestamp.h"
17#include "inv_icm42600_buffer.h"
18
19
20#define INV_ICM42600_FIFO_HEADER_MSG BIT(7)
21#define INV_ICM42600_FIFO_HEADER_ACCEL BIT(6)
22#define INV_ICM42600_FIFO_HEADER_GYRO BIT(5)
23#define INV_ICM42600_FIFO_HEADER_TMST_FSYNC GENMASK(3, 2)
24#define INV_ICM42600_FIFO_HEADER_ODR_ACCEL BIT(1)
25#define INV_ICM42600_FIFO_HEADER_ODR_GYRO BIT(0)
26
27struct inv_icm42600_fifo_1sensor_packet {
28 uint8_t header;
29 struct inv_icm42600_fifo_sensor_data data;
30 int8_t temp;
31} __packed;
32#define INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE 8
33
34struct inv_icm42600_fifo_2sensors_packet {
35 uint8_t header;
36 struct inv_icm42600_fifo_sensor_data accel;
37 struct inv_icm42600_fifo_sensor_data gyro;
38 int8_t temp;
39 __be16 timestamp;
40} __packed;
41#define INV_ICM42600_FIFO_2SENSORS_PACKET_SIZE 16
42
43ssize_t inv_icm42600_fifo_decode_packet(const void *packet, const void **accel,
44 const void **gyro, const int8_t **temp,
45 const void **timestamp, unsigned int *odr)
46{
47 const struct inv_icm42600_fifo_1sensor_packet *pack1 = packet;
48 const struct inv_icm42600_fifo_2sensors_packet *pack2 = packet;
49 uint8_t header = *((const uint8_t *)packet);
50
51
52 if (header & INV_ICM42600_FIFO_HEADER_MSG) {
53 *accel = NULL;
54 *gyro = NULL;
55 *temp = NULL;
56 *timestamp = NULL;
57 *odr = 0;
58 return 0;
59 }
60
61
62 *odr = 0;
63 if (header & INV_ICM42600_FIFO_HEADER_ODR_GYRO)
64 *odr |= INV_ICM42600_SENSOR_GYRO;
65 if (header & INV_ICM42600_FIFO_HEADER_ODR_ACCEL)
66 *odr |= INV_ICM42600_SENSOR_ACCEL;
67
68
69 if ((header & INV_ICM42600_FIFO_HEADER_ACCEL) &&
70 (header & INV_ICM42600_FIFO_HEADER_GYRO)) {
71 *accel = &pack2->accel;
72 *gyro = &pack2->gyro;
73 *temp = &pack2->temp;
74 *timestamp = &pack2->timestamp;
75 return INV_ICM42600_FIFO_2SENSORS_PACKET_SIZE;
76 }
77
78
79 if (header & INV_ICM42600_FIFO_HEADER_ACCEL) {
80 *accel = &pack1->data;
81 *gyro = NULL;
82 *temp = &pack1->temp;
83 *timestamp = NULL;
84 return INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE;
85 }
86
87
88 if (header & INV_ICM42600_FIFO_HEADER_GYRO) {
89 *accel = NULL;
90 *gyro = &pack1->data;
91 *temp = &pack1->temp;
92 *timestamp = NULL;
93 return INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE;
94 }
95
96
97 return -EINVAL;
98}
99
100void inv_icm42600_buffer_update_fifo_period(struct inv_icm42600_state *st)
101{
102 uint32_t period_gyro, period_accel, period;
103
104 if (st->fifo.en & INV_ICM42600_SENSOR_GYRO)
105 period_gyro = inv_icm42600_odr_to_period(st->conf.gyro.odr);
106 else
107 period_gyro = U32_MAX;
108
109 if (st->fifo.en & INV_ICM42600_SENSOR_ACCEL)
110 period_accel = inv_icm42600_odr_to_period(st->conf.accel.odr);
111 else
112 period_accel = U32_MAX;
113
114 if (period_gyro <= period_accel)
115 period = period_gyro;
116 else
117 period = period_accel;
118
119 st->fifo.period = period;
120}
121
122int inv_icm42600_buffer_set_fifo_en(struct inv_icm42600_state *st,
123 unsigned int fifo_en)
124{
125 unsigned int mask, val;
126 int ret;
127
128
129 mask = INV_ICM42600_FIFO_CONFIG1_TMST_FSYNC_EN |
130 INV_ICM42600_FIFO_CONFIG1_TEMP_EN |
131 INV_ICM42600_FIFO_CONFIG1_GYRO_EN |
132 INV_ICM42600_FIFO_CONFIG1_ACCEL_EN;
133
134 val = 0;
135 if (fifo_en & INV_ICM42600_SENSOR_GYRO)
136 val |= INV_ICM42600_FIFO_CONFIG1_GYRO_EN;
137 if (fifo_en & INV_ICM42600_SENSOR_ACCEL)
138 val |= INV_ICM42600_FIFO_CONFIG1_ACCEL_EN;
139 if (fifo_en & INV_ICM42600_SENSOR_TEMP)
140 val |= INV_ICM42600_FIFO_CONFIG1_TEMP_EN;
141
142 ret = regmap_update_bits(st->map, INV_ICM42600_REG_FIFO_CONFIG1, mask, val);
143 if (ret)
144 return ret;
145
146 st->fifo.en = fifo_en;
147 inv_icm42600_buffer_update_fifo_period(st);
148
149 return 0;
150}
151
152static size_t inv_icm42600_get_packet_size(unsigned int fifo_en)
153{
154 size_t packet_size;
155
156 if ((fifo_en & INV_ICM42600_SENSOR_GYRO) &&
157 (fifo_en & INV_ICM42600_SENSOR_ACCEL))
158 packet_size = INV_ICM42600_FIFO_2SENSORS_PACKET_SIZE;
159 else
160 packet_size = INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE;
161
162 return packet_size;
163}
164
165static unsigned int inv_icm42600_wm_truncate(unsigned int watermark,
166 size_t packet_size)
167{
168 size_t wm_size;
169 unsigned int wm;
170
171 wm_size = watermark * packet_size;
172 if (wm_size > INV_ICM42600_FIFO_WATERMARK_MAX)
173 wm_size = INV_ICM42600_FIFO_WATERMARK_MAX;
174
175 wm = wm_size / packet_size;
176
177 return wm;
178}
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202int inv_icm42600_buffer_update_watermark(struct inv_icm42600_state *st)
203{
204 size_t packet_size, wm_size;
205 unsigned int wm_gyro, wm_accel, watermark;
206 uint32_t period_gyro, period_accel, period;
207 uint32_t latency_gyro, latency_accel, latency;
208 bool restore;
209 __le16 raw_wm;
210 int ret;
211
212 packet_size = inv_icm42600_get_packet_size(st->fifo.en);
213
214
215 wm_gyro = inv_icm42600_wm_truncate(st->fifo.watermark.gyro, packet_size);
216 wm_accel = inv_icm42600_wm_truncate(st->fifo.watermark.accel, packet_size);
217
218 period_gyro = inv_icm42600_odr_to_period(st->conf.gyro.odr) / 1000UL;
219 period_accel = inv_icm42600_odr_to_period(st->conf.accel.odr) / 1000UL;
220 latency_gyro = period_gyro * wm_gyro;
221 latency_accel = period_accel * wm_accel;
222
223
224 if (latency_gyro == 0) {
225 watermark = wm_accel;
226 } else if (latency_accel == 0) {
227 watermark = wm_gyro;
228 } else {
229
230 if (latency_gyro <= latency_accel)
231 latency = latency_gyro - (latency_accel % latency_gyro);
232 else
233 latency = latency_accel - (latency_gyro % latency_accel);
234
235 if (period_gyro <= period_accel)
236 period = period_gyro;
237 else
238 period = period_accel;
239
240 watermark = latency / period;
241 if (watermark < 1)
242 watermark = 1;
243 }
244
245
246 wm_size = watermark * packet_size;
247
248
249 ret = regmap_update_bits_check(st->map, INV_ICM42600_REG_INT_SOURCE0,
250 INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN,
251 0, &restore);
252 if (ret)
253 return ret;
254
255 raw_wm = INV_ICM42600_FIFO_WATERMARK_VAL(wm_size);
256 memcpy(st->buffer, &raw_wm, sizeof(raw_wm));
257 ret = regmap_bulk_write(st->map, INV_ICM42600_REG_FIFO_WATERMARK,
258 st->buffer, sizeof(raw_wm));
259 if (ret)
260 return ret;
261
262
263 if (restore) {
264 ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0,
265 INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN,
266 INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN);
267 if (ret)
268 return ret;
269 }
270
271 return 0;
272}
273
274static int inv_icm42600_buffer_preenable(struct iio_dev *indio_dev)
275{
276 struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
277 struct device *dev = regmap_get_device(st->map);
278
279 pm_runtime_get_sync(dev);
280
281 return 0;
282}
283
284
285
286
287
288static int inv_icm42600_buffer_postenable(struct iio_dev *indio_dev)
289{
290 struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
291 int ret;
292
293 mutex_lock(&st->lock);
294
295
296 if (st->fifo.on) {
297 ret = 0;
298 goto out_on;
299 }
300
301
302 ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0,
303 INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN,
304 INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN);
305 if (ret)
306 goto out_unlock;
307
308
309 ret = regmap_write(st->map, INV_ICM42600_REG_SIGNAL_PATH_RESET,
310 INV_ICM42600_SIGNAL_PATH_RESET_FIFO_FLUSH);
311 if (ret)
312 goto out_unlock;
313
314
315 ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG,
316 INV_ICM42600_FIFO_CONFIG_STREAM);
317 if (ret)
318 goto out_unlock;
319
320
321 ret = regmap_bulk_read(st->map, INV_ICM42600_REG_FIFO_COUNT, st->buffer, 2);
322 if (ret)
323 goto out_unlock;
324
325out_on:
326
327 st->fifo.on++;
328out_unlock:
329 mutex_unlock(&st->lock);
330 return ret;
331}
332
333static int inv_icm42600_buffer_predisable(struct iio_dev *indio_dev)
334{
335 struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
336 int ret;
337
338 mutex_lock(&st->lock);
339
340
341 if (st->fifo.on > 1) {
342 ret = 0;
343 goto out_off;
344 }
345
346
347 ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG,
348 INV_ICM42600_FIFO_CONFIG_BYPASS);
349 if (ret)
350 goto out_unlock;
351
352
353 ret = regmap_write(st->map, INV_ICM42600_REG_SIGNAL_PATH_RESET,
354 INV_ICM42600_SIGNAL_PATH_RESET_FIFO_FLUSH);
355 if (ret)
356 goto out_unlock;
357
358
359 ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0,
360 INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN, 0);
361 if (ret)
362 goto out_unlock;
363
364out_off:
365
366 st->fifo.on--;
367out_unlock:
368 mutex_unlock(&st->lock);
369 return ret;
370}
371
372static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev)
373{
374 struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
375 struct device *dev = regmap_get_device(st->map);
376 unsigned int sensor;
377 unsigned int *watermark;
378 struct inv_icm42600_timestamp *ts;
379 struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
380 unsigned int sleep_temp = 0;
381 unsigned int sleep_sensor = 0;
382 unsigned int sleep;
383 int ret;
384
385 if (indio_dev == st->indio_gyro) {
386 sensor = INV_ICM42600_SENSOR_GYRO;
387 watermark = &st->fifo.watermark.gyro;
388 ts = iio_priv(st->indio_gyro);
389 } else if (indio_dev == st->indio_accel) {
390 sensor = INV_ICM42600_SENSOR_ACCEL;
391 watermark = &st->fifo.watermark.accel;
392 ts = iio_priv(st->indio_accel);
393 } else {
394 return -EINVAL;
395 }
396
397 mutex_lock(&st->lock);
398
399 ret = inv_icm42600_buffer_set_fifo_en(st, st->fifo.en & ~sensor);
400 if (ret)
401 goto out_unlock;
402
403 *watermark = 0;
404 ret = inv_icm42600_buffer_update_watermark(st);
405 if (ret)
406 goto out_unlock;
407
408 conf.mode = INV_ICM42600_SENSOR_MODE_OFF;
409 if (sensor == INV_ICM42600_SENSOR_GYRO)
410 ret = inv_icm42600_set_gyro_conf(st, &conf, &sleep_sensor);
411 else
412 ret = inv_icm42600_set_accel_conf(st, &conf, &sleep_sensor);
413 if (ret)
414 goto out_unlock;
415
416
417 if (!st->fifo.on)
418 ret = inv_icm42600_set_temp_conf(st, false, &sleep_temp);
419
420 inv_icm42600_timestamp_reset(ts);
421
422out_unlock:
423 mutex_unlock(&st->lock);
424
425
426 if (sleep_sensor > sleep_temp)
427 sleep = sleep_sensor;
428 else
429 sleep = sleep_temp;
430 if (sleep)
431 msleep(sleep);
432
433 pm_runtime_mark_last_busy(dev);
434 pm_runtime_put_autosuspend(dev);
435
436 return ret;
437}
438
439const struct iio_buffer_setup_ops inv_icm42600_buffer_ops = {
440 .preenable = inv_icm42600_buffer_preenable,
441 .postenable = inv_icm42600_buffer_postenable,
442 .predisable = inv_icm42600_buffer_predisable,
443 .postdisable = inv_icm42600_buffer_postdisable,
444};
445
446int inv_icm42600_buffer_fifo_read(struct inv_icm42600_state *st,
447 unsigned int max)
448{
449 size_t max_count;
450 __be16 *raw_fifo_count;
451 ssize_t i, size;
452 const void *accel, *gyro, *timestamp;
453 const int8_t *temp;
454 unsigned int odr;
455 int ret;
456
457
458 st->fifo.count = 0;
459 st->fifo.nb.gyro = 0;
460 st->fifo.nb.accel = 0;
461 st->fifo.nb.total = 0;
462
463
464 if (max == 0)
465 max_count = sizeof(st->fifo.data);
466 else
467 max_count = max * inv_icm42600_get_packet_size(st->fifo.en);
468
469
470 raw_fifo_count = (__be16 *)st->buffer;
471 ret = regmap_bulk_read(st->map, INV_ICM42600_REG_FIFO_COUNT,
472 raw_fifo_count, sizeof(*raw_fifo_count));
473 if (ret)
474 return ret;
475 st->fifo.count = be16_to_cpup(raw_fifo_count);
476
477
478 if (st->fifo.count == 0)
479 return 0;
480 if (st->fifo.count > max_count)
481 st->fifo.count = max_count;
482
483
484 ret = regmap_noinc_read(st->map, INV_ICM42600_REG_FIFO_DATA,
485 st->fifo.data, st->fifo.count);
486 if (ret)
487 return ret;
488
489
490 for (i = 0; i < st->fifo.count; i += size) {
491 size = inv_icm42600_fifo_decode_packet(&st->fifo.data[i],
492 &accel, &gyro, &temp, ×tamp, &odr);
493 if (size <= 0)
494 break;
495 if (gyro != NULL && inv_icm42600_fifo_is_data_valid(gyro))
496 st->fifo.nb.gyro++;
497 if (accel != NULL && inv_icm42600_fifo_is_data_valid(accel))
498 st->fifo.nb.accel++;
499 st->fifo.nb.total++;
500 }
501
502 return 0;
503}
504
505int inv_icm42600_buffer_fifo_parse(struct inv_icm42600_state *st)
506{
507 struct inv_icm42600_timestamp *ts;
508 int ret;
509
510 if (st->fifo.nb.total == 0)
511 return 0;
512
513
514 ts = iio_priv(st->indio_gyro);
515 inv_icm42600_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total,
516 st->fifo.nb.gyro, st->timestamp.gyro);
517 if (st->fifo.nb.gyro > 0) {
518 ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro);
519 if (ret)
520 return ret;
521 }
522
523
524 ts = iio_priv(st->indio_accel);
525 inv_icm42600_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total,
526 st->fifo.nb.accel, st->timestamp.accel);
527 if (st->fifo.nb.accel > 0) {
528 ret = inv_icm42600_accel_parse_fifo(st->indio_accel);
529 if (ret)
530 return ret;
531 }
532
533 return 0;
534}
535
536int inv_icm42600_buffer_hwfifo_flush(struct inv_icm42600_state *st,
537 unsigned int count)
538{
539 struct inv_icm42600_timestamp *ts;
540 int64_t gyro_ts, accel_ts;
541 int ret;
542
543 gyro_ts = iio_get_time_ns(st->indio_gyro);
544 accel_ts = iio_get_time_ns(st->indio_accel);
545
546 ret = inv_icm42600_buffer_fifo_read(st, count);
547 if (ret)
548 return ret;
549
550 if (st->fifo.nb.total == 0)
551 return 0;
552
553 if (st->fifo.nb.gyro > 0) {
554 ts = iio_priv(st->indio_gyro);
555 inv_icm42600_timestamp_interrupt(ts, st->fifo.period,
556 st->fifo.nb.total, st->fifo.nb.gyro,
557 gyro_ts);
558 ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro);
559 if (ret)
560 return ret;
561 }
562
563 if (st->fifo.nb.accel > 0) {
564 ts = iio_priv(st->indio_accel);
565 inv_icm42600_timestamp_interrupt(ts, st->fifo.period,
566 st->fifo.nb.total, st->fifo.nb.accel,
567 accel_ts);
568 ret = inv_icm42600_accel_parse_fifo(st->indio_accel);
569 if (ret)
570 return ret;
571 }
572
573 return 0;
574}
575
576int inv_icm42600_buffer_init(struct inv_icm42600_state *st)
577{
578 unsigned int val;
579 int ret;
580
581
582
583
584
585
586
587 val = INV_ICM42600_INTF_CONFIG0_FIFO_COUNT_ENDIAN;
588 ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0,
589 GENMASK(7, 5), val);
590 if (ret)
591 return ret;
592
593
594
595
596
597 val = INV_ICM42600_FIFO_CONFIG1_RESUME_PARTIAL_RD |
598 INV_ICM42600_FIFO_CONFIG1_WM_GT_TH;
599 return regmap_update_bits(st->map, INV_ICM42600_REG_FIFO_CONFIG1,
600 GENMASK(6, 5) | GENMASK(3, 0), val);
601}
602