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