forked from Minki/linux
iio: imu: inv_mpu6050: fix no data on MPU6050
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: f5057e7b2d
("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>
This commit is contained in:
parent
431f7667bd
commit
6e82ae6b8d
@ -114,54 +114,63 @@ static const struct inv_mpu6050_hw hw_info[] = {
|
|||||||
.name = "MPU6050",
|
.name = "MPU6050",
|
||||||
.reg = ®_set_6050,
|
.reg = ®_set_6050,
|
||||||
.config = &chip_config_6050,
|
.config = &chip_config_6050,
|
||||||
|
.fifo_size = 1024,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.whoami = INV_MPU6500_WHOAMI_VALUE,
|
.whoami = INV_MPU6500_WHOAMI_VALUE,
|
||||||
.name = "MPU6500",
|
.name = "MPU6500",
|
||||||
.reg = ®_set_6500,
|
.reg = ®_set_6500,
|
||||||
.config = &chip_config_6050,
|
.config = &chip_config_6050,
|
||||||
|
.fifo_size = 512,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.whoami = INV_MPU6515_WHOAMI_VALUE,
|
.whoami = INV_MPU6515_WHOAMI_VALUE,
|
||||||
.name = "MPU6515",
|
.name = "MPU6515",
|
||||||
.reg = ®_set_6500,
|
.reg = ®_set_6500,
|
||||||
.config = &chip_config_6050,
|
.config = &chip_config_6050,
|
||||||
|
.fifo_size = 512,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.whoami = INV_MPU6000_WHOAMI_VALUE,
|
.whoami = INV_MPU6000_WHOAMI_VALUE,
|
||||||
.name = "MPU6000",
|
.name = "MPU6000",
|
||||||
.reg = ®_set_6050,
|
.reg = ®_set_6050,
|
||||||
.config = &chip_config_6050,
|
.config = &chip_config_6050,
|
||||||
|
.fifo_size = 1024,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.whoami = INV_MPU9150_WHOAMI_VALUE,
|
.whoami = INV_MPU9150_WHOAMI_VALUE,
|
||||||
.name = "MPU9150",
|
.name = "MPU9150",
|
||||||
.reg = ®_set_6050,
|
.reg = ®_set_6050,
|
||||||
.config = &chip_config_6050,
|
.config = &chip_config_6050,
|
||||||
|
.fifo_size = 1024,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.whoami = INV_MPU9250_WHOAMI_VALUE,
|
.whoami = INV_MPU9250_WHOAMI_VALUE,
|
||||||
.name = "MPU9250",
|
.name = "MPU9250",
|
||||||
.reg = ®_set_6500,
|
.reg = ®_set_6500,
|
||||||
.config = &chip_config_6050,
|
.config = &chip_config_6050,
|
||||||
|
.fifo_size = 512,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.whoami = INV_MPU9255_WHOAMI_VALUE,
|
.whoami = INV_MPU9255_WHOAMI_VALUE,
|
||||||
.name = "MPU9255",
|
.name = "MPU9255",
|
||||||
.reg = ®_set_6500,
|
.reg = ®_set_6500,
|
||||||
.config = &chip_config_6050,
|
.config = &chip_config_6050,
|
||||||
|
.fifo_size = 512,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.whoami = INV_ICM20608_WHOAMI_VALUE,
|
.whoami = INV_ICM20608_WHOAMI_VALUE,
|
||||||
.name = "ICM20608",
|
.name = "ICM20608",
|
||||||
.reg = ®_set_6500,
|
.reg = ®_set_6500,
|
||||||
.config = &chip_config_6050,
|
.config = &chip_config_6050,
|
||||||
|
.fifo_size = 512,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.whoami = INV_ICM20602_WHOAMI_VALUE,
|
.whoami = INV_ICM20602_WHOAMI_VALUE,
|
||||||
.name = "ICM20602",
|
.name = "ICM20602",
|
||||||
.reg = ®_set_icm20602,
|
.reg = ®_set_icm20602,
|
||||||
.config = &chip_config_6050,
|
.config = &chip_config_6050,
|
||||||
|
.fifo_size = 1008,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -100,12 +100,14 @@ struct inv_mpu6050_chip_config {
|
|||||||
* @name: name of the chip.
|
* @name: name of the chip.
|
||||||
* @reg: register map of the chip.
|
* @reg: register map of the chip.
|
||||||
* @config: configuration of the chip.
|
* @config: configuration of the chip.
|
||||||
|
* @fifo_size: size of the FIFO in bytes.
|
||||||
*/
|
*/
|
||||||
struct inv_mpu6050_hw {
|
struct inv_mpu6050_hw {
|
||||||
u8 whoami;
|
u8 whoami;
|
||||||
u8 *name;
|
u8 *name;
|
||||||
const struct inv_mpu6050_reg_map *reg;
|
const struct inv_mpu6050_reg_map *reg;
|
||||||
const struct inv_mpu6050_chip_config *config;
|
const struct inv_mpu6050_chip_config *config;
|
||||||
|
size_t fifo_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -180,9 +180,6 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
|
|||||||
"failed to ack interrupt\n");
|
"failed to ack interrupt\n");
|
||||||
goto flush_fifo;
|
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)) {
|
if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) {
|
||||||
dev_warn(regmap_get_device(st->map),
|
dev_warn(regmap_get_device(st->map),
|
||||||
"spurious interrupt with status 0x%x\n", int_status);
|
"spurious interrupt with status 0x%x\n", int_status);
|
||||||
@ -211,6 +208,18 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
|
|||||||
if (result)
|
if (result)
|
||||||
goto end_session;
|
goto end_session;
|
||||||
fifo_count = get_unaligned_be16(&data[0]);
|
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 */
|
/* compute and process all complete datum */
|
||||||
nb = fifo_count / bytes_per_datum;
|
nb = fifo_count / bytes_per_datum;
|
||||||
inv_mpu6050_update_period(st, pf->timestamp, nb);
|
inv_mpu6050_update_period(st, pf->timestamp, nb);
|
||||||
|
Loading…
Reference in New Issue
Block a user