2019-05-29 07:17:56 -07:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
2013-02-02 00:26:00 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2012 Invensense, Inc.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/slab.h>
|
|
|
|
#include <linux/err.h>
|
|
|
|
#include <linux/delay.h>
|
|
|
|
#include <linux/sysfs.h>
|
|
|
|
#include <linux/jiffies.h>
|
|
|
|
#include <linux/irq.h>
|
|
|
|
#include <linux/interrupt.h>
|
|
|
|
#include <linux/poll.h>
|
2018-05-28 15:22:04 +02:00
|
|
|
#include <linux/math64.h>
|
|
|
|
|
2023-06-06 16:21:47 +00:00
|
|
|
#include <linux/iio/common/inv_sensors_timestamp.h>
|
2018-05-28 15:22:04 +02:00
|
|
|
|
2023-06-06 16:21:47 +00:00
|
|
|
#include "inv_mpu_iio.h"
|
2018-05-28 15:22:04 +02:00
|
|
|
|
2020-02-19 15:39:55 +01:00
|
|
|
static int inv_reset_fifo(struct iio_dev *indio_dev)
|
2013-02-02 00:26:00 +00:00
|
|
|
{
|
|
|
|
int result;
|
|
|
|
struct inv_mpu6050_state *st = iio_priv(indio_dev);
|
|
|
|
|
2020-02-19 15:39:55 +01:00
|
|
|
/* disable fifo and reenable it */
|
|
|
|
inv_mpu6050_prepare_fifo(st, false);
|
|
|
|
result = inv_mpu6050_prepare_fifo(st, true);
|
2013-02-02 00:26:00 +00:00
|
|
|
if (result)
|
|
|
|
goto reset_fifo_fail;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
reset_fifo_fail:
|
2016-02-12 13:44:44 +02:00
|
|
|
dev_err(regmap_get_device(st->map), "reset fifo failed %d\n", result);
|
2024-03-11 16:05:54 +00:00
|
|
|
return regmap_update_bits(st->map, st->reg->int_enable,
|
|
|
|
INV_MPU6050_BIT_DATA_RDY_EN, INV_MPU6050_BIT_DATA_RDY_EN);
|
2013-02-02 00:26:00 +00:00
|
|
|
}
|
|
|
|
|
2020-07-17 17:55:33 +01:00
|
|
|
/*
|
2013-02-02 00:26:00 +00:00
|
|
|
* inv_mpu6050_read_fifo() - Transfer data from hardware FIFO to KFIFO.
|
|
|
|
*/
|
|
|
|
irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
|
|
|
|
{
|
|
|
|
struct iio_poll_func *pf = p;
|
|
|
|
struct iio_dev *indio_dev = pf->indio_dev;
|
|
|
|
struct inv_mpu6050_state *st = iio_priv(indio_dev);
|
|
|
|
size_t bytes_per_datum;
|
|
|
|
int result;
|
|
|
|
u16 fifo_count;
|
2023-06-06 16:21:47 +00:00
|
|
|
u32 fifo_period;
|
2018-05-28 15:22:04 +02:00
|
|
|
s64 timestamp;
|
2025-06-11 17:39:09 -05:00
|
|
|
/* clear internal data buffer for avoiding kernel data leak */
|
|
|
|
u8 data[INV_MPU6050_OUTPUT_DATA_SIZE] __aligned(8) = { };
|
2018-05-22 16:18:20 +02:00
|
|
|
size_t i, nb;
|
2013-02-02 00:26:00 +00:00
|
|
|
|
2017-06-07 13:41:42 +00:00
|
|
|
mutex_lock(&st->lock);
|
2018-04-20 09:54:00 -07:00
|
|
|
|
2013-02-02 00:26:00 +00:00
|
|
|
if (!(st->chip_config.accl_fifo_enable |
|
2019-09-16 09:42:09 +00:00
|
|
|
st->chip_config.gyro_fifo_enable |
|
|
|
|
st->chip_config.magn_fifo_enable))
|
2013-02-02 00:26:00 +00:00
|
|
|
goto end_session;
|
|
|
|
bytes_per_datum = 0;
|
|
|
|
if (st->chip_config.accl_fifo_enable)
|
|
|
|
bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR;
|
|
|
|
|
|
|
|
if (st->chip_config.gyro_fifo_enable)
|
|
|
|
bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR;
|
|
|
|
|
2020-01-16 18:56:45 +01:00
|
|
|
if (st->chip_config.temp_fifo_enable)
|
|
|
|
bytes_per_datum += INV_MPU6050_BYTES_PER_TEMP_SENSOR;
|
2019-04-02 23:28:56 -07:00
|
|
|
|
2019-09-16 09:42:09 +00:00
|
|
|
if (st->chip_config.magn_fifo_enable)
|
|
|
|
bytes_per_datum += INV_MPU9X50_BYTES_MAGN;
|
|
|
|
|
2013-02-02 00:26:00 +00:00
|
|
|
/*
|
2018-05-01 10:56:41 -07:00
|
|
|
* read fifo_count register to know how many bytes are inside the FIFO
|
2013-02-02 00:26:00 +00:00
|
|
|
* right now
|
|
|
|
*/
|
2020-07-22 16:50:53 +01:00
|
|
|
result = regmap_bulk_read(st->map, st->reg->fifo_count_h,
|
|
|
|
st->data, INV_MPU6050_FIFO_COUNT_BYTE);
|
2016-02-12 13:44:43 +02:00
|
|
|
if (result)
|
2013-02-02 00:26:00 +00:00
|
|
|
goto end_session;
|
2020-07-22 16:50:53 +01:00
|
|
|
fifo_count = be16_to_cpup((__be16 *)&st->data[0]);
|
2019-10-16 14:43:28 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Handle fifo overflow by resetting fifo.
|
|
|
|
* Reset if there is only 3 data set free remaining to mitigate
|
|
|
|
* possible delay between reading fifo count and fifo data.
|
|
|
|
*/
|
|
|
|
nb = 3 * bytes_per_datum;
|
|
|
|
if (fifo_count >= st->hw->fifo_size - nb) {
|
|
|
|
dev_warn(regmap_get_device(st->map), "fifo overflow reset\n");
|
|
|
|
goto flush_fifo;
|
|
|
|
}
|
|
|
|
|
2023-06-23 08:29:24 +00:00
|
|
|
/* compute and process only all complete datum */
|
2018-05-22 16:18:20 +02:00
|
|
|
nb = fifo_count / bytes_per_datum;
|
2023-06-23 08:29:24 +00:00
|
|
|
fifo_count = nb * bytes_per_datum;
|
2024-02-19 15:48:25 +00:00
|
|
|
if (nb == 0)
|
|
|
|
goto end_session;
|
2023-06-06 16:21:47 +00:00
|
|
|
/* Each FIFO data contains all sensors, so same number for FIFO and sensor data */
|
|
|
|
fifo_period = NSEC_PER_SEC / INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider);
|
2024-05-27 15:01:17 +00:00
|
|
|
inv_sensors_timestamp_interrupt(&st->timestamp, 1, pf->timestamp);
|
|
|
|
inv_sensors_timestamp_apply_odr(&st->timestamp, fifo_period, 1, 0);
|
2023-06-23 08:29:24 +00:00
|
|
|
|
|
|
|
/* read all data once and process every samples */
|
|
|
|
result = regmap_noinc_read(st->map, st->reg->fifo_r_w, st->data, fifo_count);
|
|
|
|
if (result)
|
|
|
|
goto flush_fifo;
|
2018-05-22 16:18:20 +02:00
|
|
|
for (i = 0; i < nb; ++i) {
|
2018-04-30 12:14:10 +02:00
|
|
|
/* skip first samples if needed */
|
2018-05-22 16:18:20 +02:00
|
|
|
if (st->skip_samples) {
|
2018-04-30 12:14:10 +02:00
|
|
|
st->skip_samples--;
|
2018-05-22 16:18:20 +02:00
|
|
|
continue;
|
|
|
|
}
|
2023-06-23 08:29:24 +00:00
|
|
|
memcpy(data, &st->data[i * bytes_per_datum], bytes_per_datum);
|
2023-06-06 16:21:47 +00:00
|
|
|
timestamp = inv_sensors_timestamp_pop(&st->timestamp);
|
2023-06-23 08:29:24 +00:00
|
|
|
iio_push_to_buffers_with_timestamp(indio_dev, data, timestamp);
|
2018-05-22 16:18:20 +02:00
|
|
|
}
|
2013-02-02 00:26:00 +00:00
|
|
|
|
|
|
|
end_session:
|
2017-06-07 13:41:42 +00:00
|
|
|
mutex_unlock(&st->lock);
|
2013-02-02 00:26:00 +00:00
|
|
|
iio_trigger_notify_done(indio_dev->trig);
|
|
|
|
|
|
|
|
return IRQ_HANDLED;
|
|
|
|
|
|
|
|
flush_fifo:
|
|
|
|
/* Flush HW and SW FIFOs. */
|
|
|
|
inv_reset_fifo(indio_dev);
|
2017-06-07 13:41:42 +00:00
|
|
|
mutex_unlock(&st->lock);
|
2013-02-02 00:26:00 +00:00
|
|
|
iio_trigger_notify_done(indio_dev->trig);
|
|
|
|
|
|
|
|
return IRQ_HANDLED;
|
|
|
|
}
|