0001
0002
0003
0004
0005
0006 #include <linux/kernel.h>
0007 #include <linux/device.h>
0008 #include <linux/mutex.h>
0009 #include <linux/pm_runtime.h>
0010 #include <linux/regmap.h>
0011 #include <linux/delay.h>
0012 #include <linux/iio/iio.h>
0013 #include <linux/iio/buffer.h>
0014
0015 #include "inv_icm42600.h"
0016 #include "inv_icm42600_timestamp.h"
0017 #include "inv_icm42600_buffer.h"
0018
0019
0020 #define INV_ICM42600_FIFO_HEADER_MSG BIT(7)
0021 #define INV_ICM42600_FIFO_HEADER_ACCEL BIT(6)
0022 #define INV_ICM42600_FIFO_HEADER_GYRO BIT(5)
0023 #define INV_ICM42600_FIFO_HEADER_TMST_FSYNC GENMASK(3, 2)
0024 #define INV_ICM42600_FIFO_HEADER_ODR_ACCEL BIT(1)
0025 #define INV_ICM42600_FIFO_HEADER_ODR_GYRO BIT(0)
0026
0027 struct inv_icm42600_fifo_1sensor_packet {
0028 uint8_t header;
0029 struct inv_icm42600_fifo_sensor_data data;
0030 int8_t temp;
0031 } __packed;
0032 #define INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE 8
0033
0034 struct inv_icm42600_fifo_2sensors_packet {
0035 uint8_t header;
0036 struct inv_icm42600_fifo_sensor_data accel;
0037 struct inv_icm42600_fifo_sensor_data gyro;
0038 int8_t temp;
0039 __be16 timestamp;
0040 } __packed;
0041 #define INV_ICM42600_FIFO_2SENSORS_PACKET_SIZE 16
0042
0043 ssize_t inv_icm42600_fifo_decode_packet(const void *packet, const void **accel,
0044 const void **gyro, const int8_t **temp,
0045 const void **timestamp, unsigned int *odr)
0046 {
0047 const struct inv_icm42600_fifo_1sensor_packet *pack1 = packet;
0048 const struct inv_icm42600_fifo_2sensors_packet *pack2 = packet;
0049 uint8_t header = *((const uint8_t *)packet);
0050
0051
0052 if (header & INV_ICM42600_FIFO_HEADER_MSG) {
0053 *accel = NULL;
0054 *gyro = NULL;
0055 *temp = NULL;
0056 *timestamp = NULL;
0057 *odr = 0;
0058 return 0;
0059 }
0060
0061
0062 *odr = 0;
0063 if (header & INV_ICM42600_FIFO_HEADER_ODR_GYRO)
0064 *odr |= INV_ICM42600_SENSOR_GYRO;
0065 if (header & INV_ICM42600_FIFO_HEADER_ODR_ACCEL)
0066 *odr |= INV_ICM42600_SENSOR_ACCEL;
0067
0068
0069 if ((header & INV_ICM42600_FIFO_HEADER_ACCEL) &&
0070 (header & INV_ICM42600_FIFO_HEADER_GYRO)) {
0071 *accel = &pack2->accel;
0072 *gyro = &pack2->gyro;
0073 *temp = &pack2->temp;
0074 *timestamp = &pack2->timestamp;
0075 return INV_ICM42600_FIFO_2SENSORS_PACKET_SIZE;
0076 }
0077
0078
0079 if (header & INV_ICM42600_FIFO_HEADER_ACCEL) {
0080 *accel = &pack1->data;
0081 *gyro = NULL;
0082 *temp = &pack1->temp;
0083 *timestamp = NULL;
0084 return INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE;
0085 }
0086
0087
0088 if (header & INV_ICM42600_FIFO_HEADER_GYRO) {
0089 *accel = NULL;
0090 *gyro = &pack1->data;
0091 *temp = &pack1->temp;
0092 *timestamp = NULL;
0093 return INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE;
0094 }
0095
0096
0097 return -EINVAL;
0098 }
0099
0100 void inv_icm42600_buffer_update_fifo_period(struct inv_icm42600_state *st)
0101 {
0102 uint32_t period_gyro, period_accel, period;
0103
0104 if (st->fifo.en & INV_ICM42600_SENSOR_GYRO)
0105 period_gyro = inv_icm42600_odr_to_period(st->conf.gyro.odr);
0106 else
0107 period_gyro = U32_MAX;
0108
0109 if (st->fifo.en & INV_ICM42600_SENSOR_ACCEL)
0110 period_accel = inv_icm42600_odr_to_period(st->conf.accel.odr);
0111 else
0112 period_accel = U32_MAX;
0113
0114 if (period_gyro <= period_accel)
0115 period = period_gyro;
0116 else
0117 period = period_accel;
0118
0119 st->fifo.period = period;
0120 }
0121
0122 int inv_icm42600_buffer_set_fifo_en(struct inv_icm42600_state *st,
0123 unsigned int fifo_en)
0124 {
0125 unsigned int mask, val;
0126 int ret;
0127
0128
0129 mask = INV_ICM42600_FIFO_CONFIG1_TMST_FSYNC_EN |
0130 INV_ICM42600_FIFO_CONFIG1_TEMP_EN |
0131 INV_ICM42600_FIFO_CONFIG1_GYRO_EN |
0132 INV_ICM42600_FIFO_CONFIG1_ACCEL_EN;
0133
0134 val = 0;
0135 if (fifo_en & INV_ICM42600_SENSOR_GYRO)
0136 val |= INV_ICM42600_FIFO_CONFIG1_GYRO_EN;
0137 if (fifo_en & INV_ICM42600_SENSOR_ACCEL)
0138 val |= INV_ICM42600_FIFO_CONFIG1_ACCEL_EN;
0139 if (fifo_en & INV_ICM42600_SENSOR_TEMP)
0140 val |= INV_ICM42600_FIFO_CONFIG1_TEMP_EN;
0141
0142 ret = regmap_update_bits(st->map, INV_ICM42600_REG_FIFO_CONFIG1, mask, val);
0143 if (ret)
0144 return ret;
0145
0146 st->fifo.en = fifo_en;
0147 inv_icm42600_buffer_update_fifo_period(st);
0148
0149 return 0;
0150 }
0151
0152 static size_t inv_icm42600_get_packet_size(unsigned int fifo_en)
0153 {
0154 size_t packet_size;
0155
0156 if ((fifo_en & INV_ICM42600_SENSOR_GYRO) &&
0157 (fifo_en & INV_ICM42600_SENSOR_ACCEL))
0158 packet_size = INV_ICM42600_FIFO_2SENSORS_PACKET_SIZE;
0159 else
0160 packet_size = INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE;
0161
0162 return packet_size;
0163 }
0164
0165 static unsigned int inv_icm42600_wm_truncate(unsigned int watermark,
0166 size_t packet_size)
0167 {
0168 size_t wm_size;
0169 unsigned int wm;
0170
0171 wm_size = watermark * packet_size;
0172 if (wm_size > INV_ICM42600_FIFO_WATERMARK_MAX)
0173 wm_size = INV_ICM42600_FIFO_WATERMARK_MAX;
0174
0175 wm = wm_size / packet_size;
0176
0177 return wm;
0178 }
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202 int inv_icm42600_buffer_update_watermark(struct inv_icm42600_state *st)
0203 {
0204 size_t packet_size, wm_size;
0205 unsigned int wm_gyro, wm_accel, watermark;
0206 uint32_t period_gyro, period_accel, period;
0207 uint32_t latency_gyro, latency_accel, latency;
0208 bool restore;
0209 __le16 raw_wm;
0210 int ret;
0211
0212 packet_size = inv_icm42600_get_packet_size(st->fifo.en);
0213
0214
0215 wm_gyro = inv_icm42600_wm_truncate(st->fifo.watermark.gyro, packet_size);
0216 wm_accel = inv_icm42600_wm_truncate(st->fifo.watermark.accel, packet_size);
0217
0218 period_gyro = inv_icm42600_odr_to_period(st->conf.gyro.odr) / 1000UL;
0219 period_accel = inv_icm42600_odr_to_period(st->conf.accel.odr) / 1000UL;
0220 latency_gyro = period_gyro * wm_gyro;
0221 latency_accel = period_accel * wm_accel;
0222
0223
0224 if (latency_gyro == 0) {
0225 watermark = wm_accel;
0226 } else if (latency_accel == 0) {
0227 watermark = wm_gyro;
0228 } else {
0229
0230 if (latency_gyro <= latency_accel)
0231 latency = latency_gyro - (latency_accel % latency_gyro);
0232 else
0233 latency = latency_accel - (latency_gyro % latency_accel);
0234
0235 if (period_gyro <= period_accel)
0236 period = period_gyro;
0237 else
0238 period = period_accel;
0239
0240 watermark = latency / period;
0241 if (watermark < 1)
0242 watermark = 1;
0243 }
0244
0245
0246 wm_size = watermark * packet_size;
0247
0248
0249 ret = regmap_update_bits_check(st->map, INV_ICM42600_REG_INT_SOURCE0,
0250 INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN,
0251 0, &restore);
0252 if (ret)
0253 return ret;
0254
0255 raw_wm = INV_ICM42600_FIFO_WATERMARK_VAL(wm_size);
0256 memcpy(st->buffer, &raw_wm, sizeof(raw_wm));
0257 ret = regmap_bulk_write(st->map, INV_ICM42600_REG_FIFO_WATERMARK,
0258 st->buffer, sizeof(raw_wm));
0259 if (ret)
0260 return ret;
0261
0262
0263 if (restore) {
0264 ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0,
0265 INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN,
0266 INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN);
0267 if (ret)
0268 return ret;
0269 }
0270
0271 return 0;
0272 }
0273
0274 static int inv_icm42600_buffer_preenable(struct iio_dev *indio_dev)
0275 {
0276 struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
0277 struct device *dev = regmap_get_device(st->map);
0278
0279 pm_runtime_get_sync(dev);
0280
0281 return 0;
0282 }
0283
0284
0285
0286
0287
0288 static int inv_icm42600_buffer_postenable(struct iio_dev *indio_dev)
0289 {
0290 struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
0291 int ret;
0292
0293 mutex_lock(&st->lock);
0294
0295
0296 if (st->fifo.on) {
0297 ret = 0;
0298 goto out_on;
0299 }
0300
0301
0302 ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0,
0303 INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN,
0304 INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN);
0305 if (ret)
0306 goto out_unlock;
0307
0308
0309 ret = regmap_write(st->map, INV_ICM42600_REG_SIGNAL_PATH_RESET,
0310 INV_ICM42600_SIGNAL_PATH_RESET_FIFO_FLUSH);
0311 if (ret)
0312 goto out_unlock;
0313
0314
0315 ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG,
0316 INV_ICM42600_FIFO_CONFIG_STREAM);
0317 if (ret)
0318 goto out_unlock;
0319
0320
0321 ret = regmap_bulk_read(st->map, INV_ICM42600_REG_FIFO_COUNT, st->buffer, 2);
0322 if (ret)
0323 goto out_unlock;
0324
0325 out_on:
0326
0327 st->fifo.on++;
0328 out_unlock:
0329 mutex_unlock(&st->lock);
0330 return ret;
0331 }
0332
0333 static int inv_icm42600_buffer_predisable(struct iio_dev *indio_dev)
0334 {
0335 struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
0336 int ret;
0337
0338 mutex_lock(&st->lock);
0339
0340
0341 if (st->fifo.on > 1) {
0342 ret = 0;
0343 goto out_off;
0344 }
0345
0346
0347 ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG,
0348 INV_ICM42600_FIFO_CONFIG_BYPASS);
0349 if (ret)
0350 goto out_unlock;
0351
0352
0353 ret = regmap_write(st->map, INV_ICM42600_REG_SIGNAL_PATH_RESET,
0354 INV_ICM42600_SIGNAL_PATH_RESET_FIFO_FLUSH);
0355 if (ret)
0356 goto out_unlock;
0357
0358
0359 ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0,
0360 INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN, 0);
0361 if (ret)
0362 goto out_unlock;
0363
0364 out_off:
0365
0366 st->fifo.on--;
0367 out_unlock:
0368 mutex_unlock(&st->lock);
0369 return ret;
0370 }
0371
0372 static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev)
0373 {
0374 struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
0375 struct device *dev = regmap_get_device(st->map);
0376 unsigned int sensor;
0377 unsigned int *watermark;
0378 struct inv_icm42600_timestamp *ts;
0379 struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
0380 unsigned int sleep_temp = 0;
0381 unsigned int sleep_sensor = 0;
0382 unsigned int sleep;
0383 int ret;
0384
0385 if (indio_dev == st->indio_gyro) {
0386 sensor = INV_ICM42600_SENSOR_GYRO;
0387 watermark = &st->fifo.watermark.gyro;
0388 ts = iio_priv(st->indio_gyro);
0389 } else if (indio_dev == st->indio_accel) {
0390 sensor = INV_ICM42600_SENSOR_ACCEL;
0391 watermark = &st->fifo.watermark.accel;
0392 ts = iio_priv(st->indio_accel);
0393 } else {
0394 return -EINVAL;
0395 }
0396
0397 mutex_lock(&st->lock);
0398
0399 ret = inv_icm42600_buffer_set_fifo_en(st, st->fifo.en & ~sensor);
0400 if (ret)
0401 goto out_unlock;
0402
0403 *watermark = 0;
0404 ret = inv_icm42600_buffer_update_watermark(st);
0405 if (ret)
0406 goto out_unlock;
0407
0408 conf.mode = INV_ICM42600_SENSOR_MODE_OFF;
0409 if (sensor == INV_ICM42600_SENSOR_GYRO)
0410 ret = inv_icm42600_set_gyro_conf(st, &conf, &sleep_sensor);
0411 else
0412 ret = inv_icm42600_set_accel_conf(st, &conf, &sleep_sensor);
0413 if (ret)
0414 goto out_unlock;
0415
0416
0417 if (!st->fifo.on)
0418 ret = inv_icm42600_set_temp_conf(st, false, &sleep_temp);
0419
0420 inv_icm42600_timestamp_reset(ts);
0421
0422 out_unlock:
0423 mutex_unlock(&st->lock);
0424
0425
0426 if (sleep_sensor > sleep_temp)
0427 sleep = sleep_sensor;
0428 else
0429 sleep = sleep_temp;
0430 if (sleep)
0431 msleep(sleep);
0432
0433 pm_runtime_mark_last_busy(dev);
0434 pm_runtime_put_autosuspend(dev);
0435
0436 return ret;
0437 }
0438
0439 const struct iio_buffer_setup_ops inv_icm42600_buffer_ops = {
0440 .preenable = inv_icm42600_buffer_preenable,
0441 .postenable = inv_icm42600_buffer_postenable,
0442 .predisable = inv_icm42600_buffer_predisable,
0443 .postdisable = inv_icm42600_buffer_postdisable,
0444 };
0445
0446 int inv_icm42600_buffer_fifo_read(struct inv_icm42600_state *st,
0447 unsigned int max)
0448 {
0449 size_t max_count;
0450 __be16 *raw_fifo_count;
0451 ssize_t i, size;
0452 const void *accel, *gyro, *timestamp;
0453 const int8_t *temp;
0454 unsigned int odr;
0455 int ret;
0456
0457
0458 st->fifo.count = 0;
0459 st->fifo.nb.gyro = 0;
0460 st->fifo.nb.accel = 0;
0461 st->fifo.nb.total = 0;
0462
0463
0464 if (max == 0)
0465 max_count = sizeof(st->fifo.data);
0466 else
0467 max_count = max * inv_icm42600_get_packet_size(st->fifo.en);
0468
0469
0470 raw_fifo_count = (__be16 *)st->buffer;
0471 ret = regmap_bulk_read(st->map, INV_ICM42600_REG_FIFO_COUNT,
0472 raw_fifo_count, sizeof(*raw_fifo_count));
0473 if (ret)
0474 return ret;
0475 st->fifo.count = be16_to_cpup(raw_fifo_count);
0476
0477
0478 if (st->fifo.count == 0)
0479 return 0;
0480 if (st->fifo.count > max_count)
0481 st->fifo.count = max_count;
0482
0483
0484 ret = regmap_noinc_read(st->map, INV_ICM42600_REG_FIFO_DATA,
0485 st->fifo.data, st->fifo.count);
0486 if (ret)
0487 return ret;
0488
0489
0490 for (i = 0; i < st->fifo.count; i += size) {
0491 size = inv_icm42600_fifo_decode_packet(&st->fifo.data[i],
0492 &accel, &gyro, &temp, ×tamp, &odr);
0493 if (size <= 0)
0494 break;
0495 if (gyro != NULL && inv_icm42600_fifo_is_data_valid(gyro))
0496 st->fifo.nb.gyro++;
0497 if (accel != NULL && inv_icm42600_fifo_is_data_valid(accel))
0498 st->fifo.nb.accel++;
0499 st->fifo.nb.total++;
0500 }
0501
0502 return 0;
0503 }
0504
0505 int inv_icm42600_buffer_fifo_parse(struct inv_icm42600_state *st)
0506 {
0507 struct inv_icm42600_timestamp *ts;
0508 int ret;
0509
0510 if (st->fifo.nb.total == 0)
0511 return 0;
0512
0513
0514 ts = iio_priv(st->indio_gyro);
0515 inv_icm42600_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total,
0516 st->fifo.nb.gyro, st->timestamp.gyro);
0517 if (st->fifo.nb.gyro > 0) {
0518 ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro);
0519 if (ret)
0520 return ret;
0521 }
0522
0523
0524 ts = iio_priv(st->indio_accel);
0525 inv_icm42600_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total,
0526 st->fifo.nb.accel, st->timestamp.accel);
0527 if (st->fifo.nb.accel > 0) {
0528 ret = inv_icm42600_accel_parse_fifo(st->indio_accel);
0529 if (ret)
0530 return ret;
0531 }
0532
0533 return 0;
0534 }
0535
0536 int inv_icm42600_buffer_hwfifo_flush(struct inv_icm42600_state *st,
0537 unsigned int count)
0538 {
0539 struct inv_icm42600_timestamp *ts;
0540 int64_t gyro_ts, accel_ts;
0541 int ret;
0542
0543 gyro_ts = iio_get_time_ns(st->indio_gyro);
0544 accel_ts = iio_get_time_ns(st->indio_accel);
0545
0546 ret = inv_icm42600_buffer_fifo_read(st, count);
0547 if (ret)
0548 return ret;
0549
0550 if (st->fifo.nb.total == 0)
0551 return 0;
0552
0553 if (st->fifo.nb.gyro > 0) {
0554 ts = iio_priv(st->indio_gyro);
0555 inv_icm42600_timestamp_interrupt(ts, st->fifo.period,
0556 st->fifo.nb.total, st->fifo.nb.gyro,
0557 gyro_ts);
0558 ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro);
0559 if (ret)
0560 return ret;
0561 }
0562
0563 if (st->fifo.nb.accel > 0) {
0564 ts = iio_priv(st->indio_accel);
0565 inv_icm42600_timestamp_interrupt(ts, st->fifo.period,
0566 st->fifo.nb.total, st->fifo.nb.accel,
0567 accel_ts);
0568 ret = inv_icm42600_accel_parse_fifo(st->indio_accel);
0569 if (ret)
0570 return ret;
0571 }
0572
0573 return 0;
0574 }
0575
0576 int inv_icm42600_buffer_init(struct inv_icm42600_state *st)
0577 {
0578 unsigned int val;
0579 int ret;
0580
0581
0582
0583
0584
0585
0586
0587 val = INV_ICM42600_INTF_CONFIG0_FIFO_COUNT_ENDIAN;
0588 ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0,
0589 GENMASK(7, 5), val);
0590 if (ret)
0591 return ret;
0592
0593
0594
0595
0596
0597 val = INV_ICM42600_FIFO_CONFIG1_RESUME_PARTIAL_RD |
0598 INV_ICM42600_FIFO_CONFIG1_WM_GT_TH;
0599 return regmap_update_bits(st->map, INV_ICM42600_REG_FIFO_CONFIG1,
0600 GENMASK(6, 5) | GENMASK(3, 0), val);
0601 }