Message ID | 20240311160557.437337-4-inv.git-commit@tdk.com (mailing list archive) |
---|---|
State | Accepted |
Headers | show |
Series | Add WoM feature as an IIO event | expand |
11.03.24 6:05 пп, inv.git-commit@tdk.com: > From: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> > > Add new interrupt handler for generating WoM event from int status register > bits. Launch from interrupt the trigger poll function for data buffer. > > Signed-off-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> > --- > drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 2 + > drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 11 --- > drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 69 +++++++++++++++++-- > 3 files changed, 66 insertions(+), 16 deletions(-) > > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > index d5b0465d1f74..ca5f7d45a6d4 100644 > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > @@ -185,6 +185,7 @@ struct inv_mpu6050_hw { > * @magn_orient: magnetometer sensor chip orientation if available. > * @suspended_sensors: sensors mask of sensors turned off for suspend > * @data: read buffer used for bulk reads. > + * @it_timestamp: interrupt timestamp. > */ > struct inv_mpu6050_state { > struct mutex lock; > @@ -210,6 +211,7 @@ struct inv_mpu6050_state { > unsigned int suspended_sensors; > bool level_shifter; > u8 *data; > + s64 it_timestamp; > }; > > /*register and associated bit definition*/ > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > index 13da6f523ca2..e282378ee2ca 100644 > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > @@ -51,21 +51,10 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) > u32 fifo_period; > s64 timestamp; > u8 data[INV_MPU6050_OUTPUT_DATA_SIZE]; > - int int_status; > size_t i, nb; > > mutex_lock(&st->lock); > > - /* ack interrupt and check status */ > - result = regmap_read(st->map, st->reg->int_status, &int_status); > - if (result) { > - dev_err(regmap_get_device(st->map), > - "failed to ack interrupt\n"); > - goto flush_fifo; > - } > - if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) > - goto end_session; > - > if (!(st->chip_config.accl_fifo_enable | > st->chip_config.gyro_fifo_enable | > st->chip_config.magn_fifo_enable)) > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > index ec2398a87f45..2514966f6495 100644 > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > @@ -6,6 +6,7 @@ > #include <linux/pm_runtime.h> > > #include <linux/iio/common/inv_sensors_timestamp.h> > +#include <linux/iio/events.h> > > #include "inv_mpu_iio.h" > > @@ -223,6 +224,65 @@ static const struct iio_trigger_ops inv_mpu_trigger_ops = { > .set_trigger_state = &inv_mpu_data_rdy_trigger_set_state, > }; > > +static irqreturn_t inv_mpu6050_interrupt_timestamp(int irq, void *p) > +{ > + struct iio_dev *indio_dev = p; > + struct inv_mpu6050_state *st = iio_priv(indio_dev); > + > + st->it_timestamp = iio_get_time_ns(indio_dev); > + > + return IRQ_WAKE_THREAD; > +} > + > +static irqreturn_t inv_mpu6050_interrupt_handle(int irq, void *p) > +{ > + struct iio_dev *indio_dev = p; > + struct inv_mpu6050_state *st = iio_priv(indio_dev); > + unsigned int int_status, wom_bits; > + u64 ev_code; > + int result; > + > + switch (st->chip_type) { > + case INV_MPU6050: > + case INV_MPU6500: > + case INV_MPU6515: > + case INV_MPU6880: > + case INV_MPU6000: > + case INV_MPU9150: > + case INV_MPU9250: > + case INV_MPU9255: > + wom_bits = INV_MPU6500_BIT_WOM_INT; > + break; > + default: > + wom_bits = INV_ICM20608_BIT_WOM_INT; > + break; > + } > + > + scoped_guard(mutex, &st->lock) { > + /* ack interrupt and check status */ > + result = regmap_read(st->map, st->reg->int_status, &int_status); > + if (result) { > + dev_err(regmap_get_device(st->map), "failed to ack interrupt\n"); > + return IRQ_HANDLED; > + } > + > + /* handle WoM event */ > + if (st->chip_config.wom_en && (int_status & wom_bits)) { > + ev_code = IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z, > + IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING); > + iio_push_event(indio_dev, ev_code, st->it_timestamp); > + } > + } > + > + /* handle raw data interrupt */ > + if (int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT) { > + indio_dev->pollfunc->timestamp = st->it_timestamp; > + iio_trigger_poll_nested(st->trig); > + } > + > + return IRQ_HANDLED; > +} > + > int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type) > { > int ret; > @@ -235,11 +295,10 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type) > if (!st->trig) > return -ENOMEM; > > - ret = devm_request_irq(&indio_dev->dev, st->irq, > - &iio_trigger_generic_data_rdy_poll, > - irq_type, > - "inv_mpu", > - st->trig); > + ret = devm_request_threaded_irq(&indio_dev->dev, st->irq, > + &inv_mpu6050_interrupt_timestamp, > + &inv_mpu6050_interrupt_handle, > + irq_type, "inv_mpu", indio_dev); > if (ret) > return ret; > Greetings! After this patch was applied to Linux kernel I faced a regression on my devices LG P895/P880. Dmesg is flooded with [ 50.035018] inv-mpu6050-i2c 0-0068: failed to ack interrupt -121 and mpu6050 used on this device refuses to work. It did not occur before WoM patches were applied and reverting patches restores normal work of mpu6050. Best regards, Svyatoslav R.
On Tue, 23 Jul 2024 11:25:03 +0300 Svyatoslav Ryhel <clamor95@gmail.com> wrote: > 11.03.24 6:05 пп, inv.git-commit@tdk.com: > > From: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> > > > > Add new interrupt handler for generating WoM event from int status register > > bits. Launch from interrupt the trigger poll function for data buffer. > > > > Signed-off-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> Jean-Baptiste, Please take a look at this report. I'd rather not revert the series if we can figure out what is wrong and get a fix on top in reasonably quickly. I'd guess a power problem so we are getting interrupts when device is powered down? Hence the reads fail. Jonathan > > --- > > drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 2 + > > drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 11 --- > > drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 69 +++++++++++++++++-- > > 3 files changed, 66 insertions(+), 16 deletions(-) > > > > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > > index d5b0465d1f74..ca5f7d45a6d4 100644 > > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > > @@ -185,6 +185,7 @@ struct inv_mpu6050_hw { > > * @magn_orient: magnetometer sensor chip orientation if available. > > * @suspended_sensors: sensors mask of sensors turned off for suspend > > * @data: read buffer used for bulk reads. > > + * @it_timestamp: interrupt timestamp. > > */ > > struct inv_mpu6050_state { > > struct mutex lock; > > @@ -210,6 +211,7 @@ struct inv_mpu6050_state { > > unsigned int suspended_sensors; > > bool level_shifter; > > u8 *data; > > + s64 it_timestamp; > > }; > > > > /*register and associated bit definition*/ > > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > > index 13da6f523ca2..e282378ee2ca 100644 > > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > > @@ -51,21 +51,10 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) > > u32 fifo_period; > > s64 timestamp; > > u8 data[INV_MPU6050_OUTPUT_DATA_SIZE]; > > - int int_status; > > size_t i, nb; > > > > mutex_lock(&st->lock); > > > > - /* ack interrupt and check status */ > > - result = regmap_read(st->map, st->reg->int_status, &int_status); > > - if (result) { > > - dev_err(regmap_get_device(st->map), > > - "failed to ack interrupt\n"); > > - goto flush_fifo; > > - } > > - if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) > > - goto end_session; > > - > > if (!(st->chip_config.accl_fifo_enable | > > st->chip_config.gyro_fifo_enable | > > st->chip_config.magn_fifo_enable)) > > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > > index ec2398a87f45..2514966f6495 100644 > > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > > @@ -6,6 +6,7 @@ > > #include <linux/pm_runtime.h> > > > > #include <linux/iio/common/inv_sensors_timestamp.h> > > +#include <linux/iio/events.h> > > > > #include "inv_mpu_iio.h" > > > > @@ -223,6 +224,65 @@ static const struct iio_trigger_ops inv_mpu_trigger_ops = { > > .set_trigger_state = &inv_mpu_data_rdy_trigger_set_state, > > }; > > > > +static irqreturn_t inv_mpu6050_interrupt_timestamp(int irq, void *p) > > +{ > > + struct iio_dev *indio_dev = p; > > + struct inv_mpu6050_state *st = iio_priv(indio_dev); > > + > > + st->it_timestamp = iio_get_time_ns(indio_dev); > > + > > + return IRQ_WAKE_THREAD; > > +} > > + > > +static irqreturn_t inv_mpu6050_interrupt_handle(int irq, void *p) > > +{ > > + struct iio_dev *indio_dev = p; > > + struct inv_mpu6050_state *st = iio_priv(indio_dev); > > + unsigned int int_status, wom_bits; > > + u64 ev_code; > > + int result; > > + > > + switch (st->chip_type) { > > + case INV_MPU6050: > > + case INV_MPU6500: > > + case INV_MPU6515: > > + case INV_MPU6880: > > + case INV_MPU6000: > > + case INV_MPU9150: > > + case INV_MPU9250: > > + case INV_MPU9255: > > + wom_bits = INV_MPU6500_BIT_WOM_INT; > > + break; > > + default: > > + wom_bits = INV_ICM20608_BIT_WOM_INT; > > + break; > > + } > > + > > + scoped_guard(mutex, &st->lock) { > > + /* ack interrupt and check status */ > > + result = regmap_read(st->map, st->reg->int_status, &int_status); > > + if (result) { > > + dev_err(regmap_get_device(st->map), "failed to ack interrupt\n"); > > + return IRQ_HANDLED; > > + } > > + > > + /* handle WoM event */ > > + if (st->chip_config.wom_en && (int_status & wom_bits)) { > > + ev_code = IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z, > > + IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING); > > + iio_push_event(indio_dev, ev_code, st->it_timestamp); > > + } > > + } > > + > > + /* handle raw data interrupt */ > > + if (int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT) { > > + indio_dev->pollfunc->timestamp = st->it_timestamp; > > + iio_trigger_poll_nested(st->trig); > > + } > > + > > + return IRQ_HANDLED; > > +} > > + > > int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type) > > { > > int ret; > > @@ -235,11 +295,10 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type) > > if (!st->trig) > > return -ENOMEM; > > > > - ret = devm_request_irq(&indio_dev->dev, st->irq, > > - &iio_trigger_generic_data_rdy_poll, > > - irq_type, > > - "inv_mpu", > > - st->trig); > > + ret = devm_request_threaded_irq(&indio_dev->dev, st->irq, > > + &inv_mpu6050_interrupt_timestamp, > > + &inv_mpu6050_interrupt_handle, > > + irq_type, "inv_mpu", indio_dev); > > if (ret) > > return ret; > > > > Greetings! > > After this patch was applied to Linux kernel I faced a regression on my > devices LG P895/P880. > > Dmesg is flooded with > > [ 50.035018] inv-mpu6050-i2c 0-0068: failed to ack interrupt -121 > > and mpu6050 used on this device refuses to work. It did not occur before > WoM patches were > > applied and reverting patches restores normal work of mpu6050. > > > Best regards, > > Svyatoslav R. >
Hello Jonathan and Svyatoslav, this is really strange because it is an I2C transaction error happening. The chip is obviously on, otherwise it would not be able to send interrupt and have sensors running. For investigating the issue, we need to know what is the chip used inside this device. The driver is supporting a lot of chips that may have some specific behaviors. Svyatoslav, can you give us the name of the chip in this LG device or the whoami value read by the driver? Thanks a lot for your help. JB
ср, 7 серп. 2024 р. о 18:48 Jean-Baptiste Maneyrol <Jean-Baptiste.Maneyrol@tdk.com> пише: > > Hello Jonathan and Svyatoslav, > > this is really strange because it is an I2C transaction error happening. > The chip is obviously on, otherwise it would not be able to send interrupt and have sensors running. > > For investigating the issue, we need to know what is the chip used inside this device. The driver is supporting a lot of chips that may have some specific behaviors. > > Svyatoslav, > can you give us the name of the chip in this LG device or the whoami value read by the driver? > According to available schematics it is named as MPU-6050 Accelerometer embedded Gyro Sensor 4X4 QFN R/TP 24P One Chip Solution INVENSENSE. > Thanks a lot for your help. > JB > > ________________________________________ > From: Jonathan Cameron <jic23@kernel.org> > Sent: Tuesday, August 6, 2024 18:53 > To: Svyatoslav Ryhel <clamor95@gmail.com> > Cc: INV Git Commit <INV.git-commit@tdk.com>; lars@metafoo.de <lars@metafoo.de>; linux-iio@vger.kernel.org <linux-iio@vger.kernel.org>; Jean-Baptiste Maneyrol <Jean-Baptiste.Maneyrol@tdk.com> > Subject: Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events > > This Message Is From an External Sender > This message came from outside your organization. > > On Tue, 23 Jul 2024 11:25:03 +0300 > Svyatoslav Ryhel <clamor95@gmail.com> wrote: > > > 11.03.24 6:05 пп, inv.git-commit@tdk.com: > > > From: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> > > > > > > Add new interrupt handler for generating WoM event from int status register > > > bits. Launch from interrupt the trigger poll function for data buffer. > > > > > > Signed-off-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> > > Jean-Baptiste, > > Please take a look at this report. I'd rather not revert the series > if we can figure out what is wrong and get a fix on top in reasonably > quickly. > > I'd guess a power problem so we are getting interrupts when device is powered down? > Hence the reads fail. > > Jonathan > > > > --- > > > drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 2 + > > > drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 11 --- > > > drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 69 +++++++++++++++++-- > > > 3 files changed, 66 insertions(+), 16 deletions(-) > > > > > > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > > > index d5b0465d1f74..ca5f7d45a6d4 100644 > > > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > > > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > > > @@ -185,6 +185,7 @@ struct inv_mpu6050_hw { > > > * @magn_orient: magnetometer sensor chip orientation if available. > > > * @suspended_sensors: sensors mask of sensors turned off for suspend > > > * @data: read buffer used for bulk reads. > > > + * @it_timestamp: interrupt timestamp. > > > */ > > > struct inv_mpu6050_state { > > > struct mutex lock; > > > @@ -210,6 +211,7 @@ struct inv_mpu6050_state { > > > unsigned int suspended_sensors; > > > bool level_shifter; > > > u8 *data; > > > + s64 it_timestamp; > > > }; > > > > > > /*register and associated bit definition*/ > > > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > > > index 13da6f523ca2..e282378ee2ca 100644 > > > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > > > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > > > @@ -51,21 +51,10 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) > > > u32 fifo_period; > > > s64 timestamp; > > > u8 data[INV_MPU6050_OUTPUT_DATA_SIZE]; > > > - int int_status; > > > size_t i, nb; > > > > > > mutex_lock(&st->lock); > > > > > > - /* ack interrupt and check status */ > > > - result = regmap_read(st->map, st->reg->int_status, &int_status); > > > - if (result) { > > > - dev_err(regmap_get_device(st->map), > > > - "failed to ack interrupt\n"); > > > - goto flush_fifo; > > > - } > > > - if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) > > > - goto end_session; > > > - > > > if (!(st->chip_config.accl_fifo_enable | > > > st->chip_config.gyro_fifo_enable | > > > st->chip_config.magn_fifo_enable)) > > > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > > > index ec2398a87f45..2514966f6495 100644 > > > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > > > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > > > @@ -6,6 +6,7 @@ > > > #include <linux/pm_runtime.h> > > > > > > #include <linux/iio/common/inv_sensors_timestamp.h> > > > +#include <linux/iio/events.h> > > > > > > #include "inv_mpu_iio.h" > > > > > > @@ -223,6 +224,65 @@ static const struct iio_trigger_ops inv_mpu_trigger_ops = { > > > .set_trigger_state = &inv_mpu_data_rdy_trigger_set_state, > > > }; > > > > > > +static irqreturn_t inv_mpu6050_interrupt_timestamp(int irq, void *p) > > > +{ > > > + struct iio_dev *indio_dev = p; > > > + struct inv_mpu6050_state *st = iio_priv(indio_dev); > > > + > > > + st->it_timestamp = iio_get_time_ns(indio_dev); > > > + > > > + return IRQ_WAKE_THREAD; > > > +} > > > + > > > +static irqreturn_t inv_mpu6050_interrupt_handle(int irq, void *p) > > > +{ > > > + struct iio_dev *indio_dev = p; > > > + struct inv_mpu6050_state *st = iio_priv(indio_dev); > > > + unsigned int int_status, wom_bits; > > > + u64 ev_code; > > > + int result; > > > + > > > + switch (st->chip_type) { > > > + case INV_MPU6050: > > > + case INV_MPU6500: > > > + case INV_MPU6515: > > > + case INV_MPU6880: > > > + case INV_MPU6000: > > > + case INV_MPU9150: > > > + case INV_MPU9250: > > > + case INV_MPU9255: > > > + wom_bits = INV_MPU6500_BIT_WOM_INT; > > > + break; > > > + default: > > > + wom_bits = INV_ICM20608_BIT_WOM_INT; > > > + break; > > > + } > > > + > > > + scoped_guard(mutex, &st->lock) { > > > + /* ack interrupt and check status */ > > > + result = regmap_read(st->map, st->reg->int_status, &int_status); > > > + if (result) { > > > + dev_err(regmap_get_device(st->map), "failed to ack interrupt\n"); > > > + return IRQ_HANDLED; > > > + } > > > + > > > + /* handle WoM event */ > > > + if (st->chip_config.wom_en && (int_status & wom_bits)) { > > > + ev_code = IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z, > > > + IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING); > > > + iio_push_event(indio_dev, ev_code, st->it_timestamp); > > > + } > > > + } > > > + > > > + /* handle raw data interrupt */ > > > + if (int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT) { > > > + indio_dev->pollfunc->timestamp = st->it_timestamp; > > > + iio_trigger_poll_nested(st->trig); > > > + } > > > + > > > + return IRQ_HANDLED; > > > +} > > > + > > > int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type) > > > { > > > int ret; > > > @@ -235,11 +295,10 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type) > > > if (!st->trig) > > > return -ENOMEM; > > > > > > - ret = devm_request_irq(&indio_dev->dev, st->irq, > > > - &iio_trigger_generic_data_rdy_poll, > > > - irq_type, > > > - "inv_mpu", > > > - st->trig); > > > + ret = devm_request_threaded_irq(&indio_dev->dev, st->irq, > > > + &inv_mpu6050_interrupt_timestamp, > > > + &inv_mpu6050_interrupt_handle, > > > + irq_type, "inv_mpu", indio_dev); > > > if (ret) > > > return ret; > > > > > > > Greetings! > > > > After this patch was applied to Linux kernel I faced a regression on my > > devices LG P895/P880. > > > > Dmesg is flooded with > > > > [ 50.035018] inv-mpu6050-i2c 0-0068: failed to ack interrupt -121 > > > > and mpu6050 used on this device refuses to work. It did not occur before > > WoM patches were > > > > applied and reverting patches restores normal work of mpu6050. > > > > > > Best regards, > > > > Svyatoslav R. > > >
Thanks for the response. Are you able to modify the driver to print the whoami value? Otherwise, you can also use the debug feature of iio to read manually the whoami register if you know how to do it. Are you seeing some sensor data coming or nothing? Are you seeing the error when turning a sensor on, or are sensors turned on automatically by the device? If you can explain the test case it would help to investigate. Thanks a lot, JB
ср, 7 серп. 2024 р. о 19:18 Jean-Baptiste Maneyrol <Jean-Baptiste.Maneyrol@tdk.com> пише: > > Thanks for the response. > > Are you able to modify the driver to print the whoami value? Otherwise, you can also use the debug feature of iio to read manually the whoami register if you know how to do it. > Sure, here you go [ 5.498447] inv-mpu6050-i2c 0-0068: The required whoami value is 104, name MPU6050 > Are you seeing some sensor data coming or nothing? > Data is coming, sensors seem to work as expected. Only constant dmesg flooding with [ 50.035018] inv-mpu6050-i2c 0-0068: failed to ack interrupt -121 Data from sensors accelerometer mpu6050 /sys/bus/iio/devices/iio:device2 working 0.13, 0.03, 10.64 g gyroscope mpu6050 /sys/bus/iio/devices/iio:device2 working -0.02, -0.01, 0.04 rad/s temperature mpu6050 /sys/bus/iio/devices/iio:device2 working 36.2 deg C accelerometer mpu6050 /sys/bus/iio/devices/iio:device2 working 10.04, -1.06, 1.02 g gyroscope mpu6050 /sys/bus/iio/devices/iio:device2 working 0.01, -0.02, 0.02 rad/s temperature mpu6050 /sys/bus/iio/devices/iio:device2 working 47.8 deg C > Are you seeing the error when turning a sensor on, or are sensors turned on automatically by the device? It is turned on automatically. > If you can explain the test case it would help to investigate. > > Thanks a lot, > JB > > ________________________________________ > From: Svyatoslav Ryhel <clamor95@gmail.com> > Sent: Wednesday, August 7, 2024 18:03 > To: Jean-Baptiste Maneyrol <Jean-Baptiste.Maneyrol@tdk.com> > Cc: Jonathan Cameron <jic23@kernel.org>; INV Git Commit <INV.git-commit@tdk.com>; lars@metafoo.de <lars@metafoo.de>; linux-iio@vger.kernel.org <linux-iio@vger.kernel.org> > Subject: Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events > > This Message Is From an Untrusted Sender > You have not previously corresponded with this sender. > > ср, 7 серп. 2024 р. о 18:48 Jean-Baptiste Maneyrol > <Jean-Baptiste.Maneyrol@tdk.com> пише: > > > > Hello Jonathan and Svyatoslav, > > > > this is really strange because it is an I2C transaction error happening. > > The chip is obviously on, otherwise it would not be able to send interrupt and have sensors running. > > > > For investigating the issue, we need to know what is the chip used inside this device. The driver is supporting a lot of chips that may have some specific behaviors. > > > > Svyatoslav, > > can you give us the name of the chip in this LG device or the whoami value read by the driver? > > > > According to available schematics it is named as MPU-6050 > Accelerometer embedded Gyro Sensor 4X4 QFN R/TP 24P One Chip Solution > INVENSENSE. > > > Thanks a lot for your help. > > JB > > > > ________________________________________ > > From: Jonathan Cameron <jic23@kernel.org> > > Sent: Tuesday, August 6, 2024 18:53 > > To: Svyatoslav Ryhel <clamor95@gmail.com> > > Cc: INV Git Commit <INV.git-commit@tdk.com>; lars@metafoo.de <lars@metafoo.de>; linux-iio@vger.kernel.org <linux-iio@vger.kernel.org>; Jean-Baptiste Maneyrol <Jean-Baptiste.Maneyrol@tdk.com> > > Subject: Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events > > > > This Message Is From an External Sender > > This message came from outside your organization. > > > > On Tue, 23 Jul 2024 11:25:03 +0300 > > Svyatoslav Ryhel <clamor95@gmail.com> wrote: > > > > > 11.03.24 6:05 пп, inv.git-commit@tdk.com: > > > > From: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> > > > > > > > > Add new interrupt handler for generating WoM event from int status register > > > > bits. Launch from interrupt the trigger poll function for data buffer. > > > > > > > > Signed-off-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> > > > > Jean-Baptiste, > > > > Please take a look at this report. I'd rather not revert the series > > if we can figure out what is wrong and get a fix on top in reasonably > > quickly. > > > > I'd guess a power problem so we are getting interrupts when device is powered down? > > Hence the reads fail. > > > > Jonathan > > > > > > --- > > > > drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 2 + > > > > drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 11 --- > > > > drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 69 +++++++++++++++++-- > > > > 3 files changed, 66 insertions(+), 16 deletions(-) > > > > > > > > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > > > > index d5b0465d1f74..ca5f7d45a6d4 100644 > > > > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > > > > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > > > > @@ -185,6 +185,7 @@ struct inv_mpu6050_hw { > > > > * @magn_orient: magnetometer sensor chip orientation if available. > > > > * @suspended_sensors: sensors mask of sensors turned off for suspend > > > > * @data: read buffer used for bulk reads. > > > > + * @it_timestamp: interrupt timestamp. > > > > */ > > > > struct inv_mpu6050_state { > > > > struct mutex lock; > > > > @@ -210,6 +211,7 @@ struct inv_mpu6050_state { > > > > unsigned int suspended_sensors; > > > > bool level_shifter; > > > > u8 *data; > > > > + s64 it_timestamp; > > > > }; > > > > > > > > /*register and associated bit definition*/ > > > > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > > > > index 13da6f523ca2..e282378ee2ca 100644 > > > > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > > > > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > > > > @@ -51,21 +51,10 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) > > > > u32 fifo_period; > > > > s64 timestamp; > > > > u8 data[INV_MPU6050_OUTPUT_DATA_SIZE]; > > > > - int int_status; > > > > size_t i, nb; > > > > > > > > mutex_lock(&st->lock); > > > > > > > > - /* ack interrupt and check status */ > > > > - result = regmap_read(st->map, st->reg->int_status, &int_status); > > > > - if (result) { > > > > - dev_err(regmap_get_device(st->map), > > > > - "failed to ack interrupt\n"); > > > > - goto flush_fifo; > > > > - } > > > > - if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) > > > > - goto end_session; > > > > - > > > > if (!(st->chip_config.accl_fifo_enable | > > > > st->chip_config.gyro_fifo_enable | > > > > st->chip_config.magn_fifo_enable)) > > > > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > > > > index ec2398a87f45..2514966f6495 100644 > > > > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > > > > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > > > > @@ -6,6 +6,7 @@ > > > > #include <linux/pm_runtime.h> > > > > > > > > #include <linux/iio/common/inv_sensors_timestamp.h> > > > > +#include <linux/iio/events.h> > > > > > > > > #include "inv_mpu_iio.h" > > > > > > > > @@ -223,6 +224,65 @@ static const struct iio_trigger_ops inv_mpu_trigger_ops = { > > > > .set_trigger_state = &inv_mpu_data_rdy_trigger_set_state, > > > > }; > > > > > > > > +static irqreturn_t inv_mpu6050_interrupt_timestamp(int irq, void *p) > > > > +{ > > > > + struct iio_dev *indio_dev = p; > > > > + struct inv_mpu6050_state *st = iio_priv(indio_dev); > > > > + > > > > + st->it_timestamp = iio_get_time_ns(indio_dev); > > > > + > > > > + return IRQ_WAKE_THREAD; > > > > +} > > > > + > > > > +static irqreturn_t inv_mpu6050_interrupt_handle(int irq, void *p) > > > > +{ > > > > + struct iio_dev *indio_dev = p; > > > > + struct inv_mpu6050_state *st = iio_priv(indio_dev); > > > > + unsigned int int_status, wom_bits; > > > > + u64 ev_code; > > > > + int result; > > > > + > > > > + switch (st->chip_type) { > > > > + case INV_MPU6050: > > > > + case INV_MPU6500: > > > > + case INV_MPU6515: > > > > + case INV_MPU6880: > > > > + case INV_MPU6000: > > > > + case INV_MPU9150: > > > > + case INV_MPU9250: > > > > + case INV_MPU9255: > > > > + wom_bits = INV_MPU6500_BIT_WOM_INT; > > > > + break; > > > > + default: > > > > + wom_bits = INV_ICM20608_BIT_WOM_INT; > > > > + break; > > > > + } > > > > + > > > > + scoped_guard(mutex, &st->lock) { > > > > + /* ack interrupt and check status */ > > > > + result = regmap_read(st->map, st->reg->int_status, &int_status); > > > > + if (result) { > > > > + dev_err(regmap_get_device(st->map), "failed to ack interrupt\n"); > > > > + return IRQ_HANDLED; > > > > + } > > > > + > > > > + /* handle WoM event */ > > > > + if (st->chip_config.wom_en && (int_status & wom_bits)) { > > > > + ev_code = IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z, > > > > + IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING); > > > > + iio_push_event(indio_dev, ev_code, st->it_timestamp); > > > > + } > > > > + } > > > > + > > > > + /* handle raw data interrupt */ > > > > + if (int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT) { > > > > + indio_dev->pollfunc->timestamp = st->it_timestamp; > > > > + iio_trigger_poll_nested(st->trig); > > > > + } > > > > + > > > > + return IRQ_HANDLED; > > > > +} > > > > + > > > > int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type) > > > > { > > > > int ret; > > > > @@ -235,11 +295,10 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type) > > > > if (!st->trig) > > > > return -ENOMEM; > > > > > > > > - ret = devm_request_irq(&indio_dev->dev, st->irq, > > > > - &iio_trigger_generic_data_rdy_poll, > > > > - irq_type, > > > > - "inv_mpu", > > > > - st->trig); > > > > + ret = devm_request_threaded_irq(&indio_dev->dev, st->irq, > > > > + &inv_mpu6050_interrupt_timestamp, > > > > + &inv_mpu6050_interrupt_handle, > > > > + irq_type, "inv_mpu", indio_dev); > > > > if (ret) > > > > return ret; > > > > > > > > > > Greetings! > > > > > > After this patch was applied to Linux kernel I faced a regression on my > > > devices LG P895/P880. > > > > > > Dmesg is flooded with > > > > > > [ 50.035018] inv-mpu6050-i2c 0-0068: failed to ack interrupt -121 > > > > > > and mpu6050 used on this device refuses to work. It did not occur before > > > WoM patches were > > > > > > applied and reverting patches restores normal work of mpu6050. > > > > > > > > > Best regards, > > > > > > Svyatoslav R. > > > > >
Hello, I was able to test the latest code with an old MPU-9150 (MPU-6050 + AKM mag inside a single package), and everything is working well. We can suspect that some MPU-6050 chips have perhaps an issue when reading interrupt status register. Explaining perhaps while the old implementation wasn't reading the interrupt status register before. 1 solution would be to delete this interrupt status register read for MPU-6050/MPU-9150 since WoM feature is not available on these chips. We can go back to original behavior of skipping interrupt status register read since data ready interrupt is the only interrupt source for these chips. Would that be an acceptable fix for you? Thanks for your response, JB
вт, 13 серп. 2024 р. о 19:06 Jean-Baptiste Maneyrol <Jean-Baptiste.Maneyrol@tdk.com> пише: > > Hello, > > I was able to test the latest code with an old MPU-9150 (MPU-6050 + AKM mag inside a single package), and everything is working well. > > We can suspect that some MPU-6050 chips have perhaps an issue when reading interrupt status register. Explaining perhaps while the old implementation wasn't reading the interrupt status register before. > > 1 solution would be to delete this interrupt status register read for MPU-6050/MPU-9150 since WoM feature is not available on these chips. We can go back to original behavior of skipping interrupt status register read since data ready interrupt is the only interrupt source for these chips. > > Would that be an acceptable fix for you? > Yes, sure. Thank you for response and fix. Best regards, Svyatoslav R. > Thanks for your response, > JB > > ________________________________________ > From: Jean-Baptiste Maneyrol <Jean-Baptiste.Maneyrol@tdk.com> > Sent: Wednesday, August 7, 2024 18:18 > To: Svyatoslav Ryhel <clamor95@gmail.com> > Cc: Jonathan Cameron <jic23@kernel.org>; INV Git Commit <INV.git-commit@tdk.com>; lars@metafoo.de <lars@metafoo.de>; linux-iio@vger.kernel.org <linux-iio@vger.kernel.org> > Subject: Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events > > This Message Is From an External Sender > This message came from outside your organization. > > Thanks for the response. > > Are you able to modify the driver to print the whoami value? Otherwise, you can also use the debug feature of iio to read manually the whoami register if you know how to do it. > > Are you seeing some sensor data coming or nothing? > > Are you seeing the error when turning a sensor on, or are sensors turned on automatically by the device? > > If you can explain the test case it would help to investigate. > > Thanks a lot, > JB > > ________________________________________ > From: Svyatoslav Ryhel <clamor95@gmail.com> > Sent: Wednesday, August 7, 2024 18:03 > To: Jean-Baptiste Maneyrol <Jean-Baptiste.Maneyrol@tdk.com> > Cc: Jonathan Cameron <jic23@kernel.org>; INV Git Commit <INV.git-commit@tdk.com>; lars@metafoo.de <lars@metafoo.de>; linux-iio@vger.kernel.org <linux-iio@vger.kernel.org> > Subject: Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events > > This Message Is From an Untrusted Sender > You have not previously corresponded with this sender. > > ср, 7 серп. 2024 р. о 18:48 Jean-Baptiste Maneyrol > <Jean-Baptiste.Maneyrol@tdk.com> пише: > > > > Hello Jonathan and Svyatoslav, > > > > this is really strange because it is an I2C transaction error happening. > > The chip is obviously on, otherwise it would not be able to send interrupt and have sensors running. > > > > For investigating the issue, we need to know what is the chip used inside this device. The driver is supporting a lot of chips that may have some specific behaviors. > > > > Svyatoslav, > > can you give us the name of the chip in this LG device or the whoami value read by the driver? > > > > According to available schematics it is named as MPU-6050 > Accelerometer embedded Gyro Sensor 4X4 QFN R/TP 24P One Chip Solution > INVENSENSE. > > > Thanks a lot for your help. > > JB > > > > ________________________________________ > > From: Jonathan Cameron <jic23@kernel.org> > > Sent: Tuesday, August 6, 2024 18:53 > > To: Svyatoslav Ryhel <clamor95@gmail.com> > > Cc: INV Git Commit <INV.git-commit@tdk.com>; lars@metafoo.de <lars@metafoo.de>; linux-iio@vger.kernel.org <linux-iio@vger.kernel.org>; Jean-Baptiste Maneyrol <Jean-Baptiste.Maneyrol@tdk.com> > > Subject: Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events > > > > This Message Is From an External Sender > > This message came from outside your organization. > > > > On Tue, 23 Jul 2024 11:25:03 +0300 > > Svyatoslav Ryhel <clamor95@gmail.com> wrote: > > > > > 11.03.24 6:05 пп, inv.git-commit@tdk.com: > > > > From: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> > > > > > > > > Add new interrupt handler for generating WoM event from int status register > > > > bits. Launch from interrupt the trigger poll function for data buffer. > > > > > > > > Signed-off-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> > > > > Jean-Baptiste, > > > > Please take a look at this report. I'd rather not revert the series > > if we can figure out what is wrong and get a fix on top in reasonably > > quickly. > > > > I'd guess a power problem so we are getting interrupts when device is powered down? > > Hence the reads fail. > > > > Jonathan > > > > > > --- > > > > drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 2 + > > > > drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 11 --- > > > > drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 69 +++++++++++++++++-- > > > > 3 files changed, 66 insertions(+), 16 deletions(-) > > > > > > > > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > > > > index d5b0465d1f74..ca5f7d45a6d4 100644 > > > > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > > > > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > > > > @@ -185,6 +185,7 @@ struct inv_mpu6050_hw { > > > > * @magn_orient: magnetometer sensor chip orientation if available. > > > > * @suspended_sensors: sensors mask of sensors turned off for suspend > > > > * @data: read buffer used for bulk reads. > > > > + * @it_timestamp: interrupt timestamp. > > > > */ > > > > struct inv_mpu6050_state { > > > > struct mutex lock; > > > > @@ -210,6 +211,7 @@ struct inv_mpu6050_state { > > > > unsigned int suspended_sensors; > > > > bool level_shifter; > > > > u8 *data; > > > > + s64 it_timestamp; > > > > }; > > > > > > > > /*register and associated bit definition*/ > > > > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > > > > index 13da6f523ca2..e282378ee2ca 100644 > > > > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > > > > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > > > > @@ -51,21 +51,10 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) > > > > u32 fifo_period; > > > > s64 timestamp; > > > > u8 data[INV_MPU6050_OUTPUT_DATA_SIZE]; > > > > - int int_status; > > > > size_t i, nb; > > > > > > > > mutex_lock(&st->lock); > > > > > > > > - /* ack interrupt and check status */ > > > > - result = regmap_read(st->map, st->reg->int_status, &int_status); > > > > - if (result) { > > > > - dev_err(regmap_get_device(st->map), > > > > - "failed to ack interrupt\n"); > > > > - goto flush_fifo; > > > > - } > > > > - if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) > > > > - goto end_session; > > > > - > > > > if (!(st->chip_config.accl_fifo_enable | > > > > st->chip_config.gyro_fifo_enable | > > > > st->chip_config.magn_fifo_enable)) > > > > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > > > > index ec2398a87f45..2514966f6495 100644 > > > > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > > > > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > > > > @@ -6,6 +6,7 @@ > > > > #include <linux/pm_runtime.h> > > > > > > > > #include <linux/iio/common/inv_sensors_timestamp.h> > > > > +#include <linux/iio/events.h> > > > > > > > > #include "inv_mpu_iio.h" > > > > > > > > @@ -223,6 +224,65 @@ static const struct iio_trigger_ops inv_mpu_trigger_ops = { > > > > .set_trigger_state = &inv_mpu_data_rdy_trigger_set_state, > > > > }; > > > > > > > > +static irqreturn_t inv_mpu6050_interrupt_timestamp(int irq, void *p) > > > > +{ > > > > + struct iio_dev *indio_dev = p; > > > > + struct inv_mpu6050_state *st = iio_priv(indio_dev); > > > > + > > > > + st->it_timestamp = iio_get_time_ns(indio_dev); > > > > + > > > > + return IRQ_WAKE_THREAD; > > > > +} > > > > + > > > > +static irqreturn_t inv_mpu6050_interrupt_handle(int irq, void *p) > > > > +{ > > > > + struct iio_dev *indio_dev = p; > > > > + struct inv_mpu6050_state *st = iio_priv(indio_dev); > > > > + unsigned int int_status, wom_bits; > > > > + u64 ev_code; > > > > + int result; > > > > + > > > > + switch (st->chip_type) { > > > > + case INV_MPU6050: > > > > + case INV_MPU6500: > > > > + case INV_MPU6515: > > > > + case INV_MPU6880: > > > > + case INV_MPU6000: > > > > + case INV_MPU9150: > > > > + case INV_MPU9250: > > > > + case INV_MPU9255: > > > > + wom_bits = INV_MPU6500_BIT_WOM_INT; > > > > + break; > > > > + default: > > > > + wom_bits = INV_ICM20608_BIT_WOM_INT; > > > > + break; > > > > + } > > > > + > > > > + scoped_guard(mutex, &st->lock) { > > > > + /* ack interrupt and check status */ > > > > + result = regmap_read(st->map, st->reg->int_status, &int_status); > > > > + if (result) { > > > > + dev_err(regmap_get_device(st->map), "failed to ack interrupt\n"); > > > > + return IRQ_HANDLED; > > > > + } > > > > + > > > > + /* handle WoM event */ > > > > + if (st->chip_config.wom_en && (int_status & wom_bits)) { > > > > + ev_code = IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z, > > > > + IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING); > > > > + iio_push_event(indio_dev, ev_code, st->it_timestamp); > > > > + } > > > > + } > > > > + > > > > + /* handle raw data interrupt */ > > > > + if (int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT) { > > > > + indio_dev->pollfunc->timestamp = st->it_timestamp; > > > > + iio_trigger_poll_nested(st->trig); > > > > + } > > > > + > > > > + return IRQ_HANDLED; > > > > +} > > > > + > > > > int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type) > > > > { > > > > int ret; > > > > @@ -235,11 +295,10 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type) > > > > if (!st->trig) > > > > return -ENOMEM; > > > > > > > > - ret = devm_request_irq(&indio_dev->dev, st->irq, > > > > - &iio_trigger_generic_data_rdy_poll, > > > > - irq_type, > > > > - "inv_mpu", > > > > - st->trig); > > > > + ret = devm_request_threaded_irq(&indio_dev->dev, st->irq, > > > > + &inv_mpu6050_interrupt_timestamp, > > > > + &inv_mpu6050_interrupt_handle, > > > > + irq_type, "inv_mpu", indio_dev); > > > > if (ret) > > > > return ret; > > > > > > > > > > Greetings! > > > > > > After this patch was applied to Linux kernel I faced a regression on my > > > devices LG P895/P880. > > > > > > Dmesg is flooded with > > > > > > [ 50.035018] inv-mpu6050-i2c 0-0068: failed to ack interrupt -121 > > > > > > and mpu6050 used on this device refuses to work. It did not occur before > > > WoM patches were > > > > > > applied and reverting patches restores normal work of mpu6050. > > > > > > > > > Best regards, > > > > > > Svyatoslav R. > > > > >
Hello, I've sent the patch on the mailing list implementing the fix. Svyatoslav, can you test it and check that it is working correctly for your device? Thanks, JB
ср, 14 серп. 2024 р. о 17:39 Jean-Baptiste Maneyrol <Jean-Baptiste.Maneyrol@tdk.com> пише: > > Hello, > > I've sent the patch on the mailing list implementing the fix. > > Svyatoslav, > can you test it and check that it is working correctly for your device? > Yes, sure. I have tested on P895 and asked my friend to test P880 which is similar device and it had same issue. Both work fine now. Thanks! > Thanks, > JB > > ________________________________________ > From: Svyatoslav Ryhel <clamor95@gmail.com> > Sent: Tuesday, August 13, 2024 18:09 > To: Jean-Baptiste Maneyrol <Jean-Baptiste.Maneyrol@tdk.com> > Cc: Jonathan Cameron <jic23@kernel.org>; INV Git Commit <INV.git-commit@tdk.com>; lars@metafoo.de <lars@metafoo.de>; linux-iio@vger.kernel.org <linux-iio@vger.kernel.org> > Subject: Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events > > This Message Is From an Untrusted Sender > You have not previously corresponded with this sender. > > вт, 13 серп. 2024 р. о 19:06 Jean-Baptiste Maneyrol > <Jean-Baptiste.Maneyrol@tdk.com> пише: > > > > Hello, > > > > I was able to test the latest code with an old MPU-9150 (MPU-6050 + AKM mag inside a single package), and everything is working well. > > > > We can suspect that some MPU-6050 chips have perhaps an issue when reading interrupt status register. Explaining perhaps while the old implementation wasn't reading the interrupt status register before. > > > > 1 solution would be to delete this interrupt status register read for MPU-6050/MPU-9150 since WoM feature is not available on these chips. We can go back to original behavior of skipping interrupt status register read since data ready interrupt is the only interrupt source for these chips. > > > > Would that be an acceptable fix for you? > > > > Yes, sure. Thank you for response and fix. > > Best regards, > Svyatoslav R. > > > Thanks for your response, > > JB > > > > ________________________________________ > > From: Jean-Baptiste Maneyrol <Jean-Baptiste.Maneyrol@tdk.com> > > Sent: Wednesday, August 7, 2024 18:18 > > To: Svyatoslav Ryhel <clamor95@gmail.com> > > Cc: Jonathan Cameron <jic23@kernel.org>; INV Git Commit <INV.git-commit@tdk.com>; lars@metafoo.de <lars@metafoo.de>; linux-iio@vger.kernel.org <linux-iio@vger.kernel.org> > > Subject: Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events > > > > This Message Is From an External Sender > > This message came from outside your organization. > > > > Thanks for the response. > > > > Are you able to modify the driver to print the whoami value? Otherwise, you can also use the debug feature of iio to read manually the whoami register if you know how to do it. > > > > Are you seeing some sensor data coming or nothing? > > > > Are you seeing the error when turning a sensor on, or are sensors turned on automatically by the device? > > > > If you can explain the test case it would help to investigate. > > > > Thanks a lot, > > JB > > > > ________________________________________ > > From: Svyatoslav Ryhel <clamor95@gmail.com> > > Sent: Wednesday, August 7, 2024 18:03 > > To: Jean-Baptiste Maneyrol <Jean-Baptiste.Maneyrol@tdk.com> > > Cc: Jonathan Cameron <jic23@kernel.org>; INV Git Commit <INV.git-commit@tdk.com>; lars@metafoo.de <lars@metafoo.de>; linux-iio@vger.kernel.org <linux-iio@vger.kernel.org> > > Subject: Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events > > > > This Message Is From an Untrusted Sender > > You have not previously corresponded with this sender. > > > > ср, 7 серп. 2024 р. о 18:48 Jean-Baptiste Maneyrol > > <Jean-Baptiste.Maneyrol@tdk.com> пише: > > > > > > Hello Jonathan and Svyatoslav, > > > > > > this is really strange because it is an I2C transaction error happening. > > > The chip is obviously on, otherwise it would not be able to send interrupt and have sensors running. > > > > > > For investigating the issue, we need to know what is the chip used inside this device. The driver is supporting a lot of chips that may have some specific behaviors. > > > > > > Svyatoslav, > > > can you give us the name of the chip in this LG device or the whoami value read by the driver? > > > > > > > According to available schematics it is named as MPU-6050 > > Accelerometer embedded Gyro Sensor 4X4 QFN R/TP 24P One Chip Solution > > INVENSENSE. > > > > > Thanks a lot for your help. > > > JB > > > > > > ________________________________________ > > > From: Jonathan Cameron <jic23@kernel.org> > > > Sent: Tuesday, August 6, 2024 18:53 > > > To: Svyatoslav Ryhel <clamor95@gmail.com> > > > Cc: INV Git Commit <INV.git-commit@tdk.com>; lars@metafoo.de <lars@metafoo.de>; linux-iio@vger.kernel.org <linux-iio@vger.kernel.org>; Jean-Baptiste Maneyrol <Jean-Baptiste.Maneyrol@tdk.com> > > > Subject: Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events > > > > > > This Message Is From an External Sender > > > This message came from outside your organization. > > > > > > On Tue, 23 Jul 2024 11:25:03 +0300 > > > Svyatoslav Ryhel <clamor95@gmail.com> wrote: > > > > > > > 11.03.24 6:05 пп, inv.git-commit@tdk.com: > > > > > From: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> > > > > > > > > > > Add new interrupt handler for generating WoM event from int status register > > > > > bits. Launch from interrupt the trigger poll function for data buffer. > > > > > > > > > > Signed-off-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> > > > > > > Jean-Baptiste, > > > > > > Please take a look at this report. I'd rather not revert the series > > > if we can figure out what is wrong and get a fix on top in reasonably > > > quickly. > > > > > > I'd guess a power problem so we are getting interrupts when device is powered down? > > > Hence the reads fail. > > > > > > Jonathan > > > > > > > > --- > > > > > drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 2 + > > > > > drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 11 --- > > > > > drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 69 +++++++++++++++++-- > > > > > 3 files changed, 66 insertions(+), 16 deletions(-) > > > > > > > > > > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > > > > > index d5b0465d1f74..ca5f7d45a6d4 100644 > > > > > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > > > > > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h > > > > > @@ -185,6 +185,7 @@ struct inv_mpu6050_hw { > > > > > * @magn_orient: magnetometer sensor chip orientation if available. > > > > > * @suspended_sensors: sensors mask of sensors turned off for suspend > > > > > * @data: read buffer used for bulk reads. > > > > > + * @it_timestamp: interrupt timestamp. > > > > > */ > > > > > struct inv_mpu6050_state { > > > > > struct mutex lock; > > > > > @@ -210,6 +211,7 @@ struct inv_mpu6050_state { > > > > > unsigned int suspended_sensors; > > > > > bool level_shifter; > > > > > u8 *data; > > > > > + s64 it_timestamp; > > > > > }; > > > > > > > > > > /*register and associated bit definition*/ > > > > > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > > > > > index 13da6f523ca2..e282378ee2ca 100644 > > > > > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > > > > > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c > > > > > @@ -51,21 +51,10 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) > > > > > u32 fifo_period; > > > > > s64 timestamp; > > > > > u8 data[INV_MPU6050_OUTPUT_DATA_SIZE]; > > > > > - int int_status; > > > > > size_t i, nb; > > > > > > > > > > mutex_lock(&st->lock); > > > > > > > > > > - /* ack interrupt and check status */ > > > > > - result = regmap_read(st->map, st->reg->int_status, &int_status); > > > > > - if (result) { > > > > > - dev_err(regmap_get_device(st->map), > > > > > - "failed to ack interrupt\n"); > > > > > - goto flush_fifo; > > > > > - } > > > > > - if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) > > > > > - goto end_session; > > > > > - > > > > > if (!(st->chip_config.accl_fifo_enable | > > > > > st->chip_config.gyro_fifo_enable | > > > > > st->chip_config.magn_fifo_enable)) > > > > > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > > > > > index ec2398a87f45..2514966f6495 100644 > > > > > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > > > > > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c > > > > > @@ -6,6 +6,7 @@ > > > > > #include <linux/pm_runtime.h> > > > > > > > > > > #include <linux/iio/common/inv_sensors_timestamp.h> > > > > > +#include <linux/iio/events.h> > > > > > > > > > > #include "inv_mpu_iio.h" > > > > > > > > > > @@ -223,6 +224,65 @@ static const struct iio_trigger_ops inv_mpu_trigger_ops = { > > > > > .set_trigger_state = &inv_mpu_data_rdy_trigger_set_state, > > > > > }; > > > > > > > > > > +static irqreturn_t inv_mpu6050_interrupt_timestamp(int irq, void *p) > > > > > +{ > > > > > + struct iio_dev *indio_dev = p; > > > > > + struct inv_mpu6050_state *st = iio_priv(indio_dev); > > > > > + > > > > > + st->it_timestamp = iio_get_time_ns(indio_dev); > > > > > + > > > > > + return IRQ_WAKE_THREAD; > > > > > +} > > > > > + > > > > > +static irqreturn_t inv_mpu6050_interrupt_handle(int irq, void *p) > > > > > +{ > > > > > + struct iio_dev *indio_dev = p; > > > > > + struct inv_mpu6050_state *st = iio_priv(indio_dev); > > > > > + unsigned int int_status, wom_bits; > > > > > + u64 ev_code; > > > > > + int result; > > > > > + > > > > > + switch (st->chip_type) { > > > > > + case INV_MPU6050: > > > > > + case INV_MPU6500: > > > > > + case INV_MPU6515: > > > > > + case INV_MPU6880: > > > > > + case INV_MPU6000: > > > > > + case INV_MPU9150: > > > > > + case INV_MPU9250: > > > > > + case INV_MPU9255: > > > > > + wom_bits = INV_MPU6500_BIT_WOM_INT; > > > > > + break; > > > > > + default: > > > > > + wom_bits = INV_ICM20608_BIT_WOM_INT; > > > > > + break; > > > > > + } > > > > > + > > > > > + scoped_guard(mutex, &st->lock) { > > > > > + /* ack interrupt and check status */ > > > > > + result = regmap_read(st->map, st->reg->int_status, &int_status); > > > > > + if (result) { > > > > > + dev_err(regmap_get_device(st->map), "failed to ack interrupt\n"); > > > > > + return IRQ_HANDLED; > > > > > + } > > > > > + > > > > > + /* handle WoM event */ > > > > > + if (st->chip_config.wom_en && (int_status & wom_bits)) { > > > > > + ev_code = IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z, > > > > > + IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING); > > > > > + iio_push_event(indio_dev, ev_code, st->it_timestamp); > > > > > + } > > > > > + } > > > > > + > > > > > + /* handle raw data interrupt */ > > > > > + if (int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT) { > > > > > + indio_dev->pollfunc->timestamp = st->it_timestamp; > > > > > + iio_trigger_poll_nested(st->trig); > > > > > + } > > > > > + > > > > > + return IRQ_HANDLED; > > > > > +} > > > > > + > > > > > int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type) > > > > > { > > > > > int ret; > > > > > @@ -235,11 +295,10 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type) > > > > > if (!st->trig) > > > > > return -ENOMEM; > > > > > > > > > > - ret = devm_request_irq(&indio_dev->dev, st->irq, > > > > > - &iio_trigger_generic_data_rdy_poll, > > > > > - irq_type, > > > > > - "inv_mpu", > > > > > - st->trig); > > > > > + ret = devm_request_threaded_irq(&indio_dev->dev, st->irq, > > > > > + &inv_mpu6050_interrupt_timestamp, > > > > > + &inv_mpu6050_interrupt_handle, > > > > > + irq_type, "inv_mpu", indio_dev); > > > > > if (ret) > > > > > return ret; > > > > > > > > > > > > > Greetings! > > > > > > > > After this patch was applied to Linux kernel I faced a regression on my > > > > devices LG P895/P880. > > > > > > > > Dmesg is flooded with > > > > > > > > [ 50.035018] inv-mpu6050-i2c 0-0068: failed to ack interrupt -121 > > > > > > > > and mpu6050 used on this device refuses to work. It did not occur before > > > > WoM patches were > > > > > > > > applied and reverting patches restores normal work of mpu6050. > > > > > > > > > > > > Best regards, > > > > > > > > Svyatoslav R. > > > > > > >
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index d5b0465d1f74..ca5f7d45a6d4 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -185,6 +185,7 @@ struct inv_mpu6050_hw { * @magn_orient: magnetometer sensor chip orientation if available. * @suspended_sensors: sensors mask of sensors turned off for suspend * @data: read buffer used for bulk reads. + * @it_timestamp: interrupt timestamp. */ struct inv_mpu6050_state { struct mutex lock; @@ -210,6 +211,7 @@ struct inv_mpu6050_state { unsigned int suspended_sensors; bool level_shifter; u8 *data; + s64 it_timestamp; }; /*register and associated bit definition*/ diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c index 13da6f523ca2..e282378ee2ca 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c @@ -51,21 +51,10 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) u32 fifo_period; s64 timestamp; u8 data[INV_MPU6050_OUTPUT_DATA_SIZE]; - int int_status; size_t i, nb; mutex_lock(&st->lock); - /* ack interrupt and check status */ - result = regmap_read(st->map, st->reg->int_status, &int_status); - if (result) { - dev_err(regmap_get_device(st->map), - "failed to ack interrupt\n"); - goto flush_fifo; - } - if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) - goto end_session; - if (!(st->chip_config.accl_fifo_enable | st->chip_config.gyro_fifo_enable | st->chip_config.magn_fifo_enable)) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c index ec2398a87f45..2514966f6495 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c @@ -6,6 +6,7 @@ #include <linux/pm_runtime.h> #include <linux/iio/common/inv_sensors_timestamp.h> +#include <linux/iio/events.h> #include "inv_mpu_iio.h" @@ -223,6 +224,65 @@ static const struct iio_trigger_ops inv_mpu_trigger_ops = { .set_trigger_state = &inv_mpu_data_rdy_trigger_set_state, }; +static irqreturn_t inv_mpu6050_interrupt_timestamp(int irq, void *p) +{ + struct iio_dev *indio_dev = p; + struct inv_mpu6050_state *st = iio_priv(indio_dev); + + st->it_timestamp = iio_get_time_ns(indio_dev); + + return IRQ_WAKE_THREAD; +} + +static irqreturn_t inv_mpu6050_interrupt_handle(int irq, void *p) +{ + struct iio_dev *indio_dev = p; + struct inv_mpu6050_state *st = iio_priv(indio_dev); + unsigned int int_status, wom_bits; + u64 ev_code; + int result; + + switch (st->chip_type) { + case INV_MPU6050: + case INV_MPU6500: + case INV_MPU6515: + case INV_MPU6880: + case INV_MPU6000: + case INV_MPU9150: + case INV_MPU9250: + case INV_MPU9255: + wom_bits = INV_MPU6500_BIT_WOM_INT; + break; + default: + wom_bits = INV_ICM20608_BIT_WOM_INT; + break; + } + + scoped_guard(mutex, &st->lock) { + /* ack interrupt and check status */ + result = regmap_read(st->map, st->reg->int_status, &int_status); + if (result) { + dev_err(regmap_get_device(st->map), "failed to ack interrupt\n"); + return IRQ_HANDLED; + } + + /* handle WoM event */ + if (st->chip_config.wom_en && (int_status & wom_bits)) { + ev_code = IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z, + IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING); + iio_push_event(indio_dev, ev_code, st->it_timestamp); + } + } + + /* handle raw data interrupt */ + if (int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT) { + indio_dev->pollfunc->timestamp = st->it_timestamp; + iio_trigger_poll_nested(st->trig); + } + + return IRQ_HANDLED; +} + int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type) { int ret; @@ -235,11 +295,10 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type) if (!st->trig) return -ENOMEM; - ret = devm_request_irq(&indio_dev->dev, st->irq, - &iio_trigger_generic_data_rdy_poll, - irq_type, - "inv_mpu", - st->trig); + ret = devm_request_threaded_irq(&indio_dev->dev, st->irq, + &inv_mpu6050_interrupt_timestamp, + &inv_mpu6050_interrupt_handle, + irq_type, "inv_mpu", indio_dev); if (ret) return ret;