iio: imu: inv_mpu6050: fix no data on MPU6050
authorJean-Baptiste Maneyrol <JManeyrol@invensense.com>
Wed, 16 Oct 2019 14:43:28 +0000 (14:43 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 12 Nov 2019 18:21:20 +0000 (19:21 +0100)
[ Upstream commit 6e82ae6b8d11b948b74e71396efd8e074c415f44 ]

Some chips have a fifo overflow bit issue where the bit is always
set. The result is that every data is dropped.

Change fifo overflow management by checking fifo count against
a maximum value.

Add fifo size in chip hardware set of values.

Fixes: f5057e7b2dba ("iio: imu: inv_mpu6050: better fifo overflow handling")
Cc: stable@vger.kernel.org
Signed-off-by: Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c

index cb80c9e..ea09952 100644 (file)
@@ -121,54 +121,63 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .name = "MPU6050",
                .reg = &reg_set_6050,
                .config = &chip_config_6050,
+               .fifo_size = 1024,
        },
        {
                .whoami = INV_MPU6500_WHOAMI_VALUE,
                .name = "MPU6500",
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
+               .fifo_size = 512,
        },
        {
                .whoami = INV_MPU6515_WHOAMI_VALUE,
                .name = "MPU6515",
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
+               .fifo_size = 512,
        },
        {
                .whoami = INV_MPU6000_WHOAMI_VALUE,
                .name = "MPU6000",
                .reg = &reg_set_6050,
                .config = &chip_config_6050,
+               .fifo_size = 1024,
        },
        {
                .whoami = INV_MPU9150_WHOAMI_VALUE,
                .name = "MPU9150",
                .reg = &reg_set_6050,
                .config = &chip_config_6050,
+               .fifo_size = 1024,
        },
        {
                .whoami = INV_MPU9250_WHOAMI_VALUE,
                .name = "MPU9250",
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
+               .fifo_size = 512,
        },
        {
                .whoami = INV_MPU9255_WHOAMI_VALUE,
                .name = "MPU9255",
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
+               .fifo_size = 512,
        },
        {
                .whoami = INV_ICM20608_WHOAMI_VALUE,
                .name = "ICM20608",
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
+               .fifo_size = 512,
        },
        {
                .whoami = INV_ICM20602_WHOAMI_VALUE,
                .name = "ICM20602",
                .reg = &reg_set_icm20602,
                .config = &chip_config_6050,
+               .fifo_size = 1008,
        },
 };
 
index bdbaf6e..e56c1d1 100644 (file)
@@ -108,12 +108,14 @@ struct inv_mpu6050_chip_config {
  *  @name:      name of the chip.
  *  @reg:   register map of the chip.
  *  @config:    configuration of the chip.
+ *  @fifo_size:        size of the FIFO in bytes.
  */
 struct inv_mpu6050_hw {
        u8 whoami;
        u8 *name;
        const struct inv_mpu6050_reg_map *reg;
        const struct inv_mpu6050_chip_config *config;
+       size_t fifo_size;
 };
 
 /*
index 548e042..4f9c276 100644 (file)
@@ -188,9 +188,6 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
                        "failed to ack interrupt\n");
                goto flush_fifo;
        }
-       /* handle fifo overflow by reseting fifo */
-       if (int_status & INV_MPU6050_BIT_FIFO_OVERFLOW_INT)
-               goto flush_fifo;
        if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) {
                dev_warn(regmap_get_device(st->map),
                        "spurious interrupt with status 0x%x\n", int_status);
@@ -216,6 +213,18 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
        if (result)
                goto end_session;
        fifo_count = get_unaligned_be16(&data[0]);
+
+       /*
+        * 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;
+       }
+
        /* compute and process all complete datum */
        nb = fifo_count / bytes_per_datum;
        inv_mpu6050_update_period(st, pf->timestamp, nb);