Merge 6.4-rc5 into usb-next
[platform/kernel/linux-starfive.git] / drivers / iio / imu / inv_icm42600 / inv_icm42600_buffer.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2020 Invensense, Inc.
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 /* FIFO header: 1 byte */
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
27 struct 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
34 struct 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
43 ssize_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         /* FIFO empty */
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         /* handle odr flags */
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         /* accel + gyro */
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         /* accel only */
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         /* gyro only */
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         /* invalid packet if here */
97         return -EINVAL;
98 }
99
100 void 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
122 int 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         /* update only FIFO EN bits */
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
152 static 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
165 static 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  * inv_icm42600_buffer_update_watermark - update watermark FIFO threshold
182  * @st: driver internal state
183  *
184  * Returns 0 on success, a negative error code otherwise.
185  *
186  * FIFO watermark threshold is computed based on the required watermark values
187  * set for gyro and accel sensors. Since watermark is all about acceptable data
188  * latency, use the smallest setting between the 2. It means choosing the
189  * smallest latency but this is not as simple as choosing the smallest watermark
190  * value. Latency depends on watermark and ODR. It requires several steps:
191  * 1) compute gyro and accel latencies and choose the smallest value.
192  * 2) adapt the choosen latency so that it is a multiple of both gyro and accel
193  *    ones. Otherwise it is possible that you don't meet a requirement. (for
194  *    example with gyro @100Hz wm 4 and accel @100Hz with wm 6, choosing the
195  *    value of 4 will not meet accel latency requirement because 6 is not a
196  *    multiple of 4. You need to use the value 2.)
197  * 3) Since all periods are multiple of each others, watermark is computed by
198  *    dividing this computed latency by the smallest period, which corresponds
199  *    to the FIFO frequency. Beware that this is only true because we are not
200  *    using 500Hz frequency which is not a multiple of the others.
201  */
202 int 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         /* compute sensors latency, depending on sensor watermark and odr */
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         /* use us for odr to avoid overflow using 32 bits values */
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         /* 0 value for watermark means that the sensor is turned off */
224         if (latency_gyro == 0) {
225                 watermark = wm_accel;
226         } else if (latency_accel == 0) {
227                 watermark = wm_gyro;
228         } else {
229                 /* compute the smallest latency that is a multiple of both */
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                 /* use the shortest period */
235                 if (period_gyro <= period_accel)
236                         period = period_gyro;
237                 else
238                         period = period_accel;
239                 /* all this works because periods are multiple of each others */
240                 watermark = latency / period;
241                 if (watermark < 1)
242                         watermark = 1;
243         }
244
245         /* compute watermark value in bytes */
246         wm_size = watermark * packet_size;
247
248         /* changing FIFO watermark requires to turn off watermark interrupt */
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         /* restore watermark interrupt */
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
274 static 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         struct inv_icm42600_timestamp *ts = iio_priv(indio_dev);
279
280         pm_runtime_get_sync(dev);
281
282         mutex_lock(&st->lock);
283         inv_icm42600_timestamp_reset(ts);
284         mutex_unlock(&st->lock);
285
286         return 0;
287 }
288
289 /*
290  * update_scan_mode callback is turning sensors on and setting data FIFO enable
291  * bits.
292  */
293 static int inv_icm42600_buffer_postenable(struct iio_dev *indio_dev)
294 {
295         struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
296         int ret;
297
298         mutex_lock(&st->lock);
299
300         /* exit if FIFO is already on */
301         if (st->fifo.on) {
302                 ret = 0;
303                 goto out_on;
304         }
305
306         /* set FIFO threshold interrupt */
307         ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0,
308                                  INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN,
309                                  INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN);
310         if (ret)
311                 goto out_unlock;
312
313         /* flush FIFO data */
314         ret = regmap_write(st->map, INV_ICM42600_REG_SIGNAL_PATH_RESET,
315                            INV_ICM42600_SIGNAL_PATH_RESET_FIFO_FLUSH);
316         if (ret)
317                 goto out_unlock;
318
319         /* set FIFO in streaming mode */
320         ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG,
321                            INV_ICM42600_FIFO_CONFIG_STREAM);
322         if (ret)
323                 goto out_unlock;
324
325         /* workaround: first read of FIFO count after reset is always 0 */
326         ret = regmap_bulk_read(st->map, INV_ICM42600_REG_FIFO_COUNT, st->buffer, 2);
327         if (ret)
328                 goto out_unlock;
329
330 out_on:
331         /* increase FIFO on counter */
332         st->fifo.on++;
333 out_unlock:
334         mutex_unlock(&st->lock);
335         return ret;
336 }
337
338 static int inv_icm42600_buffer_predisable(struct iio_dev *indio_dev)
339 {
340         struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
341         int ret;
342
343         mutex_lock(&st->lock);
344
345         /* exit if there are several sensors using the FIFO */
346         if (st->fifo.on > 1) {
347                 ret = 0;
348                 goto out_off;
349         }
350
351         /* set FIFO in bypass mode */
352         ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG,
353                            INV_ICM42600_FIFO_CONFIG_BYPASS);
354         if (ret)
355                 goto out_unlock;
356
357         /* flush FIFO data */
358         ret = regmap_write(st->map, INV_ICM42600_REG_SIGNAL_PATH_RESET,
359                            INV_ICM42600_SIGNAL_PATH_RESET_FIFO_FLUSH);
360         if (ret)
361                 goto out_unlock;
362
363         /* disable FIFO threshold interrupt */
364         ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0,
365                                  INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN, 0);
366         if (ret)
367                 goto out_unlock;
368
369 out_off:
370         /* decrease FIFO on counter */
371         st->fifo.on--;
372 out_unlock:
373         mutex_unlock(&st->lock);
374         return ret;
375 }
376
377 static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev)
378 {
379         struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
380         struct device *dev = regmap_get_device(st->map);
381         unsigned int sensor;
382         unsigned int *watermark;
383         struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
384         unsigned int sleep_temp = 0;
385         unsigned int sleep_sensor = 0;
386         unsigned int sleep;
387         int ret;
388
389         if (indio_dev == st->indio_gyro) {
390                 sensor = INV_ICM42600_SENSOR_GYRO;
391                 watermark = &st->fifo.watermark.gyro;
392         } else if (indio_dev == st->indio_accel) {
393                 sensor = INV_ICM42600_SENSOR_ACCEL;
394                 watermark = &st->fifo.watermark.accel;
395         } else {
396                 return -EINVAL;
397         }
398
399         mutex_lock(&st->lock);
400
401         ret = inv_icm42600_buffer_set_fifo_en(st, st->fifo.en & ~sensor);
402         if (ret)
403                 goto out_unlock;
404
405         *watermark = 0;
406         ret = inv_icm42600_buffer_update_watermark(st);
407         if (ret)
408                 goto out_unlock;
409
410         conf.mode = INV_ICM42600_SENSOR_MODE_OFF;
411         if (sensor == INV_ICM42600_SENSOR_GYRO)
412                 ret = inv_icm42600_set_gyro_conf(st, &conf, &sleep_sensor);
413         else
414                 ret = inv_icm42600_set_accel_conf(st, &conf, &sleep_sensor);
415         if (ret)
416                 goto out_unlock;
417
418         /* if FIFO is off, turn temperature off */
419         if (!st->fifo.on)
420                 ret = inv_icm42600_set_temp_conf(st, false, &sleep_temp);
421
422 out_unlock:
423         mutex_unlock(&st->lock);
424
425         /* sleep maximum required time */
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
439 const 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
446 int 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         /* reset all samples counters */
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         /* compute maximum FIFO read size */
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         /* read FIFO count value */
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         /* check and clamp FIFO count value */
478         if (st->fifo.count == 0)
479                 return 0;
480         if (st->fifo.count > max_count)
481                 st->fifo.count = max_count;
482
483         /* read all FIFO data in internal buffer */
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         /* compute number of samples for each sensor */
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, &timestamp, &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
505 int 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         /* handle gyroscope timestamp and FIFO data parsing */
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         /* handle accelerometer timestamp and FIFO data parsing */
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
536 int 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
576 int inv_icm42600_buffer_init(struct inv_icm42600_state *st)
577 {
578         unsigned int val;
579         int ret;
580
581         /*
582          * Default FIFO configuration (bits 7 to 5)
583          * - use invalid value
584          * - FIFO count in bytes
585          * - FIFO count in big endian
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          * Enable FIFO partial read and continuous watermark interrupt.
595          * Disable all FIFO EN bits.
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 }