* [PATCH v3 0/4] Add WoM feature as an IIO event
@ 2024-03-11 16:05 inv.git-commit
2024-03-11 16:05 ` [PATCH v3 1/4] iio: imu: inv_mpu6050: add WoM (Wake-on-Motion) sensor inv.git-commit
` (4 more replies)
0 siblings, 5 replies; 16+ messages in thread
From: inv.git-commit @ 2024-03-11 16:05 UTC (permalink / raw)
To: jic23; +Cc: lars, linux-iio, Jean-Baptiste Maneyrol
From: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
Add WoM (Wake-on-Motion) feature for all chips supporting it (all except
MPU-6000/6050/9150). WoM compares the magnitude of the current accel sample
with the previous one against a threshold and returns an interrupt event if
the value is higher.
WoM is checking against all axes and maps best to ROC since it compares the
last 2 samples. Thus report WoM as an accel x|y|z roc_rising IIO event, add
system wakeup functionality if WoM is on and put the chip in low-power mode
when the system is suspended. Corresponding ROC value is in SI units since
the chip is using an absolute value in mg.
v2:
- Rework to use accel x|y|z roc for reporting WoM event
- Use only datasheet advertised bits for MPU-6500 family chips
v3
- Coding style fixes
- Convert mutex usage to guard/scoped_guard
Jean-Baptiste Maneyrol (4):
iio: imu: inv_mpu6050: add WoM (Wake-on-Motion) sensor
iio: imu: inv_mpu6050: add WoM event as accel event
iio: imu: inv_mpu6050: add new interrupt handler for WoM events
iio: imu: inv_mpu6050: add WoM suspend wakeup with low-power mode
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 542 ++++++++++++++++--
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 36 +-
drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 17 +-
drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 83 ++-
4 files changed, 595 insertions(+), 83 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 1/4] iio: imu: inv_mpu6050: add WoM (Wake-on-Motion) sensor
2024-03-11 16:05 [PATCH v3 0/4] Add WoM feature as an IIO event inv.git-commit
@ 2024-03-11 16:05 ` inv.git-commit
2024-03-11 16:05 ` [PATCH v3 2/4] iio: imu: inv_mpu6050: add WoM event as accel event inv.git-commit
` (3 subsequent siblings)
4 siblings, 0 replies; 16+ messages in thread
From: inv.git-commit @ 2024-03-11 16:05 UTC (permalink / raw)
To: jic23; +Cc: lars, linux-iio, Jean-Baptiste Maneyrol
From: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
WoM is a threshold test on accel value comparing actual sample with
previous one. It maps best to roc rising event.
Add support of a new WOM sensor and functions for handling the associated
roc_rising event. The event value is in SI units. Ensure WOM is stopped and
restarted at suspend-resume, handle usage with buffer data ready interrupt,
and handle change in sampling rate impacting already set roc value.
Signed-off-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
---
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 282 +++++++++++++++++-
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 20 +-
drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 6 +-
drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 14 +-
4 files changed, 309 insertions(+), 13 deletions(-)
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 0e94e5335e93..d49c0ac91a59 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -15,6 +15,8 @@
#include <linux/acpi.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
+#include <linux/math64.h>
+#include <linux/minmax.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
@@ -332,7 +334,7 @@ static int inv_mpu6050_clock_switch(struct inv_mpu6050_state *st,
int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en,
unsigned int mask)
{
- unsigned int sleep;
+ unsigned int sleep, val;
u8 pwr_mgmt2, user_ctrl;
int ret;
@@ -345,6 +347,14 @@ int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en,
mask &= ~INV_MPU6050_SENSOR_TEMP;
if (mask & INV_MPU6050_SENSOR_MAGN && en == st->chip_config.magn_en)
mask &= ~INV_MPU6050_SENSOR_MAGN;
+ if (mask & INV_MPU6050_SENSOR_WOM && en == st->chip_config.wom_en)
+ mask &= ~INV_MPU6050_SENSOR_WOM;
+
+ /* force accel on if WoM is on and not going off */
+ if (!en && (mask & INV_MPU6050_SENSOR_ACCL) && st->chip_config.wom_en &&
+ !(mask & INV_MPU6050_SENSOR_WOM))
+ mask &= ~INV_MPU6050_SENSOR_ACCL;
+
if (mask == 0)
return 0;
@@ -439,6 +449,16 @@ int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en,
}
}
+ /* enable/disable accel intelligence control */
+ if (mask & INV_MPU6050_SENSOR_WOM) {
+ val = en ? INV_MPU6500_BIT_ACCEL_INTEL_EN |
+ INV_MPU6500_BIT_ACCEL_INTEL_MODE : 0;
+ ret = regmap_write(st->map, INV_MPU6500_REG_ACCEL_INTEL_CTRL, val);
+ if (ret)
+ return ret;
+ st->chip_config.wom_en = en;
+ }
+
return 0;
}
@@ -893,6 +913,239 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
return result;
}
+static u64 inv_mpu6050_convert_wom_to_roc(unsigned int threshold, unsigned int freq_div)
+{
+ /* 4mg per LSB converted in m/s² in micro (1000000) */
+ const unsigned int convert = 4U * 9807U;
+ u64 value;
+
+ value = threshold * convert;
+
+ /* compute the differential by multiplying by the frequency */
+ return div_u64(value * INV_MPU6050_INTERNAL_FREQ_HZ, freq_div);
+}
+
+static unsigned int inv_mpu6050_convert_roc_to_wom(u64 roc, unsigned int freq_div)
+{
+ /* 4mg per LSB converted in m/s² in micro (1000000) */
+ const unsigned int convert = 4U * 9807U;
+ u64 value;
+
+ /* return 0 only if roc is 0 */
+ if (roc == 0)
+ return 0;
+
+ value = div_u64(roc * freq_div, convert * INV_MPU6050_INTERNAL_FREQ_HZ);
+
+ /* limit value to 8 bits and prevent 0 */
+ return min(255, max(1, value));
+}
+
+static int inv_mpu6050_set_wom_int(struct inv_mpu6050_state *st, bool on)
+{
+ unsigned int reg_val, val;
+
+ 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:
+ reg_val = INV_MPU6500_BIT_WOM_INT_EN;
+ break;
+ default:
+ reg_val = INV_ICM20608_BIT_WOM_INT_EN;
+ break;
+ }
+
+ val = on ? reg_val : 0;
+
+ return regmap_update_bits(st->map, st->reg->int_enable, reg_val, val);
+}
+
+static int inv_mpu6050_set_wom_threshold(struct inv_mpu6050_state *st, u64 value,
+ unsigned int freq_div)
+{
+ unsigned int threshold;
+ int result;
+
+ /* convert roc to wom threshold and convert back to handle clipping */
+ threshold = inv_mpu6050_convert_roc_to_wom(value, freq_div);
+ value = inv_mpu6050_convert_wom_to_roc(threshold, freq_div);
+
+ dev_dbg(regmap_get_device(st->map), "wom_threshold: 0x%x\n", threshold);
+
+ switch (st->chip_type) {
+ case INV_ICM20609:
+ case INV_ICM20689:
+ case INV_ICM20600:
+ case INV_ICM20602:
+ case INV_ICM20690:
+ st->data[0] = threshold;
+ st->data[1] = threshold;
+ st->data[2] = threshold;
+ result = regmap_bulk_write(st->map, INV_ICM20609_REG_ACCEL_WOM_X_THR,
+ st->data, 3);
+ break;
+ default:
+ result = regmap_write(st->map, INV_MPU6500_REG_WOM_THRESHOLD, threshold);
+ break;
+ }
+ if (result)
+ return result;
+
+ st->chip_config.roc_threshold = value;
+
+ return 0;
+}
+
+static int inv_mpu6050_enable_wom(struct inv_mpu6050_state *st, bool en)
+{
+ struct device *pdev = regmap_get_device(st->map);
+ unsigned int mask;
+ int result;
+
+ if (en) {
+ result = pm_runtime_resume_and_get(pdev);
+ if (result)
+ return result;
+
+ mask = INV_MPU6050_SENSOR_ACCL | INV_MPU6050_SENSOR_WOM;
+ result = inv_mpu6050_switch_engine(st, true, mask);
+ if (result)
+ goto error_suspend;
+
+ result = inv_mpu6050_set_wom_int(st, true);
+ if (result)
+ goto error_suspend;
+ } else {
+ result = inv_mpu6050_set_wom_int(st, false);
+ if (result)
+ dev_err(pdev, "error %d disabling WoM interrupt bit", result);
+
+ /* disable only WoM and let accel be disabled by autosuspend */
+ result = inv_mpu6050_switch_engine(st, false, INV_MPU6050_SENSOR_WOM);
+ if (result) {
+ dev_err(pdev, "error %d disabling WoM force off", result);
+ /* force WoM off */
+ st->chip_config.wom_en = false;
+ }
+
+ pm_runtime_mark_last_busy(pdev);
+ pm_runtime_put_autosuspend(pdev);
+ }
+
+ return result;
+
+error_suspend:
+ pm_runtime_mark_last_busy(pdev);
+ pm_runtime_put_autosuspend(pdev);
+ return result;
+}
+
+static int inv_mpu6050_read_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct inv_mpu6050_state *st = iio_priv(indio_dev);
+
+ /* support only WoM (accel roc rising) event */
+ if (chan->type != IIO_ACCEL || type != IIO_EV_TYPE_ROC ||
+ dir != IIO_EV_DIR_RISING)
+ return -EINVAL;
+
+ guard(mutex)(&st->lock);
+
+ return st->chip_config.wom_en ? 1 : 0;
+}
+
+static int inv_mpu6050_write_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ int state)
+{
+ struct inv_mpu6050_state *st = iio_priv(indio_dev);
+ int enable;
+
+ /* support only WoM (accel roc rising) event */
+ if (chan->type != IIO_ACCEL || type != IIO_EV_TYPE_ROC ||
+ dir != IIO_EV_DIR_RISING)
+ return -EINVAL;
+
+ enable = !!state;
+
+ guard(mutex)(&st->lock);
+
+ if (st->chip_config.wom_en == enable)
+ return 0;
+
+ return inv_mpu6050_enable_wom(st, enable);
+}
+
+static int inv_mpu6050_read_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int *val, int *val2)
+{
+ struct inv_mpu6050_state *st = iio_priv(indio_dev);
+ u32 rem;
+
+ /* support only WoM (accel roc rising) event value */
+ if (chan->type != IIO_ACCEL || type != IIO_EV_TYPE_ROC ||
+ dir != IIO_EV_DIR_RISING || info != IIO_EV_INFO_VALUE)
+ return -EINVAL;
+
+ guard(mutex)(&st->lock);
+
+ /* return value in micro */
+ *val = div_u64_rem(st->chip_config.roc_threshold, 1000000U, &rem);
+ *val2 = rem;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int inv_mpu6050_write_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int val, int val2)
+{
+ struct inv_mpu6050_state *st = iio_priv(indio_dev);
+ struct device *pdev = regmap_get_device(st->map);
+ u64 value;
+ int result;
+
+ /* support only WoM (accel roc rising) event value */
+ if (chan->type != IIO_ACCEL || type != IIO_EV_TYPE_ROC ||
+ dir != IIO_EV_DIR_RISING || info != IIO_EV_INFO_VALUE)
+ return -EINVAL;
+
+ if (val < 0 || val2 < 0)
+ return -EINVAL;
+
+ guard(mutex)(&st->lock);
+
+ result = pm_runtime_resume_and_get(pdev);
+ if (result)
+ return result;
+
+ value = (u64)val * 1000000ULL + (u64)val2;
+ result = inv_mpu6050_set_wom_threshold(st, value, INV_MPU6050_FREQ_DIVIDER(st));
+
+ pm_runtime_mark_last_busy(pdev);
+ pm_runtime_put_autosuspend(pdev);
+
+ return result;
+}
+
/*
* inv_mpu6050_set_lpf() - set low pass filer based on fifo rate.
*
@@ -989,6 +1242,12 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr,
if (result)
goto fifo_rate_fail_power_off;
+ /* update wom threshold since roc is dependent on sampling frequency */
+ result = inv_mpu6050_set_wom_threshold(st, st->chip_config.roc_threshold,
+ INV_MPU6050_FREQ_DIVIDER(st));
+ if (result)
+ goto fifo_rate_fail_power_off;
+
pm_runtime_mark_last_busy(pdev);
fifo_rate_fail_power_off:
pm_runtime_put_autosuspend(pdev);
@@ -1326,6 +1585,10 @@ static const struct iio_info mpu_info = {
.write_raw = &inv_mpu6050_write_raw,
.write_raw_get_fmt = &inv_write_raw_get_fmt,
.attrs = &inv_attribute_group,
+ .read_event_config = inv_mpu6050_read_event_config,
+ .write_event_config = inv_mpu6050_write_event_config,
+ .read_event_value = inv_mpu6050_read_event_value,
+ .write_event_value = inv_mpu6050_write_event_value,
.validate_trigger = inv_mpu6050_validate_trigger,
.debugfs_reg_access = &inv_mpu6050_reg_access,
};
@@ -1706,6 +1969,12 @@ static int inv_mpu_resume(struct device *dev)
if (result)
goto out_unlock;
+ if (st->chip_config.wom_en) {
+ result = inv_mpu6050_set_wom_int(st, true);
+ if (result)
+ goto out_unlock;
+ }
+
if (iio_buffer_enabled(indio_dev))
result = inv_mpu6050_prepare_fifo(st, true);
@@ -1735,6 +2004,12 @@ static int inv_mpu_suspend(struct device *dev)
goto out_unlock;
}
+ if (st->chip_config.wom_en) {
+ result = inv_mpu6050_set_wom_int(st, false);
+ if (result)
+ goto out_unlock;
+ }
+
if (st->chip_config.accl_en)
st->suspended_sensors |= INV_MPU6050_SENSOR_ACCL;
if (st->chip_config.gyro_en)
@@ -1743,6 +2018,8 @@ static int inv_mpu_suspend(struct device *dev)
st->suspended_sensors |= INV_MPU6050_SENSOR_TEMP;
if (st->chip_config.magn_en)
st->suspended_sensors |= INV_MPU6050_SENSOR_MAGN;
+ if (st->chip_config.wom_en)
+ st->suspended_sensors |= INV_MPU6050_SENSOR_WOM;
result = inv_mpu6050_switch_engine(st, false, st->suspended_sensors);
if (result)
goto out_unlock;
@@ -1767,7 +2044,8 @@ static int inv_mpu_runtime_suspend(struct device *dev)
mutex_lock(&st->lock);
sensors = INV_MPU6050_SENSOR_ACCL | INV_MPU6050_SENSOR_GYRO |
- INV_MPU6050_SENSOR_TEMP | INV_MPU6050_SENSOR_MAGN;
+ INV_MPU6050_SENSOR_TEMP | INV_MPU6050_SENSOR_MAGN |
+ INV_MPU6050_SENSOR_WOM;
ret = inv_mpu6050_switch_engine(st, false, sensors);
if (ret)
goto out_unlock;
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index 5950e2419ebb..d5b0465d1f74 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -88,11 +88,12 @@ enum inv_devices {
INV_NUM_PARTS
};
-/* chip sensors mask: accelerometer, gyroscope, temperature, magnetometer */
+/* chip sensors mask: accelerometer, gyroscope, temperature, magnetometer, WoM */
#define INV_MPU6050_SENSOR_ACCL BIT(0)
#define INV_MPU6050_SENSOR_GYRO BIT(1)
#define INV_MPU6050_SENSOR_TEMP BIT(2)
#define INV_MPU6050_SENSOR_MAGN BIT(3)
+#define INV_MPU6050_SENSOR_WOM BIT(4)
/**
* struct inv_mpu6050_chip_config - Cached chip configuration data.
@@ -104,11 +105,13 @@ enum inv_devices {
* @gyro_en: gyro engine enabled
* @temp_en: temperature sensor enabled
* @magn_en: magn engine (i2c master) enabled
+ * @wom_en: Wake-on-Motion enabled
* @accl_fifo_enable: enable accel data output
* @gyro_fifo_enable: enable gyro data output
* @temp_fifo_enable: enable temp data output
* @magn_fifo_enable: enable magn data output
* @divider: chip sample rate divider (sample rate divider - 1)
+ * @roc_threshold: save ROC threshold (WoM) set value
*/
struct inv_mpu6050_chip_config {
unsigned int clk:3;
@@ -119,12 +122,14 @@ struct inv_mpu6050_chip_config {
unsigned int gyro_en:1;
unsigned int temp_en:1;
unsigned int magn_en:1;
+ unsigned int wom_en:1;
unsigned int accl_fifo_enable:1;
unsigned int gyro_fifo_enable:1;
unsigned int temp_fifo_enable:1;
unsigned int magn_fifo_enable:1;
u8 divider;
u8 user_ctrl;
+ u64 roc_threshold;
};
/*
@@ -256,12 +261,16 @@ struct inv_mpu6050_state {
#define INV_MPU6050_REG_INT_ENABLE 0x38
#define INV_MPU6050_BIT_DATA_RDY_EN 0x01
#define INV_MPU6050_BIT_DMP_INT_EN 0x02
+#define INV_MPU6500_BIT_WOM_INT_EN BIT(6)
+#define INV_ICM20608_BIT_WOM_INT_EN GENMASK(7, 5)
#define INV_MPU6050_REG_RAW_ACCEL 0x3B
#define INV_MPU6050_REG_TEMPERATURE 0x41
#define INV_MPU6050_REG_RAW_GYRO 0x43
#define INV_MPU6050_REG_INT_STATUS 0x3A
+#define INV_MPU6500_BIT_WOM_INT BIT(6)
+#define INV_ICM20608_BIT_WOM_INT GENMASK(7, 5)
#define INV_MPU6050_BIT_FIFO_OVERFLOW_INT 0x10
#define INV_MPU6050_BIT_RAW_DATA_RDY_INT 0x01
@@ -301,6 +310,11 @@ struct inv_mpu6050_state {
#define INV_MPU6050_BIT_PWR_ACCL_STBY 0x38
#define INV_MPU6050_BIT_PWR_GYRO_STBY 0x07
+/* ICM20609 registers */
+#define INV_ICM20609_REG_ACCEL_WOM_X_THR 0x20
+#define INV_ICM20609_REG_ACCEL_WOM_Y_THR 0x21
+#define INV_ICM20609_REG_ACCEL_WOM_Z_THR 0x22
+
/* ICM20602 register */
#define INV_ICM20602_REG_I2C_IF 0x70
#define INV_ICM20602_BIT_I2C_IF_DIS 0x40
@@ -320,6 +334,10 @@ struct inv_mpu6050_state {
/* mpu6500 registers */
#define INV_MPU6500_REG_ACCEL_CONFIG_2 0x1D
#define INV_ICM20689_BITS_FIFO_SIZE_MAX 0xC0
+#define INV_MPU6500_REG_WOM_THRESHOLD 0x1F
+#define INV_MPU6500_REG_ACCEL_INTEL_CTRL 0x69
+#define INV_MPU6500_BIT_ACCEL_INTEL_EN BIT(7)
+#define INV_MPU6500_BIT_ACCEL_INTEL_MODE BIT(6)
#define INV_MPU6500_REG_ACCEL_OFFSET 0x77
/* delay time in milliseconds */
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
index 66d4ba088e70..13da6f523ca2 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
@@ -33,10 +33,8 @@ static int inv_reset_fifo(struct iio_dev *indio_dev)
reset_fifo_fail:
dev_err(regmap_get_device(st->map), "reset fifo failed %d\n", result);
- result = regmap_write(st->map, st->reg->int_enable,
- INV_MPU6050_BIT_DATA_RDY_EN);
-
- return result;
+ return regmap_update_bits(st->map, st->reg->int_enable,
+ INV_MPU6050_BIT_DATA_RDY_EN, INV_MPU6050_BIT_DATA_RDY_EN);
}
/*
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
index 676704f9151f..ec2398a87f45 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
@@ -134,11 +134,13 @@ int inv_mpu6050_prepare_fifo(struct inv_mpu6050_state *st, bool enable)
ret = regmap_write(st->map, st->reg->user_ctrl, d);
if (ret)
return ret;
- /* enable interrupt */
- ret = regmap_write(st->map, st->reg->int_enable,
- INV_MPU6050_BIT_DATA_RDY_EN);
+ /* enable data interrupt */
+ ret = regmap_update_bits(st->map, st->reg->int_enable,
+ INV_MPU6050_BIT_DATA_RDY_EN, INV_MPU6050_BIT_DATA_RDY_EN);
} else {
- ret = regmap_write(st->map, st->reg->int_enable, 0);
+ /* disable data interrupt */
+ ret = regmap_update_bits(st->map, st->reg->int_enable,
+ INV_MPU6050_BIT_DATA_RDY_EN, 0);
if (ret)
return ret;
ret = regmap_write(st->map, st->reg->fifo_en, 0);
@@ -171,9 +173,9 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
return result;
/*
* In case autosuspend didn't trigger, turn off first not
- * required sensors.
+ * required sensors excepted WoM
*/
- result = inv_mpu6050_switch_engine(st, false, ~scan);
+ result = inv_mpu6050_switch_engine(st, false, ~scan & ~INV_MPU6050_SENSOR_WOM);
if (result)
goto error_power_off;
result = inv_mpu6050_switch_engine(st, true, scan);
--
2.34.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v3 2/4] iio: imu: inv_mpu6050: add WoM event as accel event
2024-03-11 16:05 [PATCH v3 0/4] Add WoM feature as an IIO event inv.git-commit
2024-03-11 16:05 ` [PATCH v3 1/4] iio: imu: inv_mpu6050: add WoM (Wake-on-Motion) sensor inv.git-commit
@ 2024-03-11 16:05 ` inv.git-commit
2024-03-11 16:05 ` [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events inv.git-commit
` (2 subsequent siblings)
4 siblings, 0 replies; 16+ messages in thread
From: inv.git-commit @ 2024-03-11 16:05 UTC (permalink / raw)
To: jic23; +Cc: lars, linux-iio, Jean-Baptiste Maneyrol
From: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
Add WoM (roc rising) event as accel x_or_y_or_z event for all chips >=
MPU-6500. This requires to create new MPU-6500 channels as default and
MPU-6050 channels for older chips.
Signed-off-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
---
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 67 +++++++++++++++++++---
1 file changed, 59 insertions(+), 8 deletions(-)
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index d49c0ac91a59..281fbd8eb791 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -1348,6 +1348,15 @@ static const struct iio_chan_spec_ext_info inv_ext_info[] = {
{ }
};
+static const struct iio_event_spec inv_wom_events[] = {
+ {
+ .type = IIO_EV_TYPE_ROC,
+ .dir = IIO_EV_DIR_RISING,
+ .mask_separate = BIT(IIO_EV_INFO_ENABLE) |
+ BIT(IIO_EV_INFO_VALUE),
+ },
+};
+
#define INV_MPU6050_CHAN(_type, _channel2, _index) \
{ \
.type = _type, \
@@ -1383,7 +1392,17 @@ static const struct iio_chan_spec_ext_info inv_ext_info[] = {
}, \
}
-static const struct iio_chan_spec inv_mpu_channels[] = {
+#define INV_MPU6050_EVENT_CHAN(_type, _channel2, _events, _events_nb) \
+{ \
+ .type = _type, \
+ .modified = 1, \
+ .channel2 = _channel2, \
+ .event_spec = _events, \
+ .num_event_specs = _events_nb, \
+ .scan_index = -1, \
+}
+
+static const struct iio_chan_spec inv_mpu6050_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(INV_MPU6050_SCAN_TIMESTAMP),
INV_MPU6050_TEMP_CHAN(INV_MPU6050_SCAN_TEMP),
@@ -1397,6 +1416,23 @@ static const struct iio_chan_spec inv_mpu_channels[] = {
INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z),
};
+static const struct iio_chan_spec inv_mpu6500_channels[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(INV_MPU6050_SCAN_TIMESTAMP),
+
+ INV_MPU6050_TEMP_CHAN(INV_MPU6050_SCAN_TEMP),
+
+ INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X),
+ INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y),
+ INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z),
+
+ INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_MPU6050_SCAN_ACCL_X),
+ INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_MPU6050_SCAN_ACCL_Y),
+ INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z),
+
+ INV_MPU6050_EVENT_CHAN(IIO_ACCEL, IIO_MOD_X_OR_Y_OR_Z,
+ inv_wom_events, ARRAY_SIZE(inv_wom_events)),
+};
+
#define INV_MPU6050_SCAN_MASK_3AXIS_ACCEL \
(BIT(INV_MPU6050_SCAN_ACCL_X) \
| BIT(INV_MPU6050_SCAN_ACCL_Y) \
@@ -1876,6 +1912,12 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
return result;
switch (chip_type) {
+ case INV_MPU6000:
+ case INV_MPU6050:
+ indio_dev->channels = inv_mpu6050_channels;
+ indio_dev->num_channels = ARRAY_SIZE(inv_mpu6050_channels);
+ indio_dev->available_scan_masks = inv_mpu_scan_masks;
+ break;
case INV_MPU9150:
indio_dev->channels = inv_mpu9150_channels;
indio_dev->num_channels = ARRAY_SIZE(inv_mpu9150_channels);
@@ -1889,13 +1931,13 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
break;
case INV_ICM20600:
case INV_ICM20602:
- indio_dev->channels = inv_mpu_channels;
- indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
+ indio_dev->channels = inv_mpu6500_channels;
+ indio_dev->num_channels = ARRAY_SIZE(inv_mpu6500_channels);
indio_dev->available_scan_masks = inv_icm20602_scan_masks;
break;
default:
- indio_dev->channels = inv_mpu_channels;
- indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
+ indio_dev->channels = inv_mpu6500_channels;
+ indio_dev->num_channels = ARRAY_SIZE(inv_mpu6500_channels);
indio_dev->available_scan_masks = inv_mpu_scan_masks;
break;
}
@@ -1904,9 +1946,18 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
* auxiliary device in use. Otherwise Going back to 6-axis only.
*/
if (st->magn_disabled) {
- indio_dev->channels = inv_mpu_channels;
- indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
- indio_dev->available_scan_masks = inv_mpu_scan_masks;
+ switch (chip_type) {
+ case INV_MPU9150:
+ indio_dev->channels = inv_mpu6050_channels;
+ indio_dev->num_channels = ARRAY_SIZE(inv_mpu6050_channels);
+ indio_dev->available_scan_masks = inv_mpu_scan_masks;
+ break;
+ default:
+ indio_dev->channels = inv_mpu6500_channels;
+ indio_dev->num_channels = ARRAY_SIZE(inv_mpu6500_channels);
+ indio_dev->available_scan_masks = inv_mpu_scan_masks;
+ break;
+ }
}
indio_dev->info = &mpu_info;
--
2.34.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events
2024-03-11 16:05 [PATCH v3 0/4] Add WoM feature as an IIO event inv.git-commit
2024-03-11 16:05 ` [PATCH v3 1/4] iio: imu: inv_mpu6050: add WoM (Wake-on-Motion) sensor inv.git-commit
2024-03-11 16:05 ` [PATCH v3 2/4] iio: imu: inv_mpu6050: add WoM event as accel event inv.git-commit
@ 2024-03-11 16:05 ` inv.git-commit
2024-07-23 8:25 ` Svyatoslav Ryhel
2024-03-11 16:05 ` [PATCH v3 4/4] iio: imu: inv_mpu6050: add WoM suspend wakeup with low-power mode inv.git-commit
2024-03-16 13:54 ` [PATCH v3 0/4] Add WoM feature as an IIO event Jonathan Cameron
4 siblings, 1 reply; 16+ messages in thread
From: inv.git-commit @ 2024-03-11 16:05 UTC (permalink / raw)
To: jic23; +Cc: lars, linux-iio, Jean-Baptiste Maneyrol
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;
--
2.34.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v3 4/4] iio: imu: inv_mpu6050: add WoM suspend wakeup with low-power mode
2024-03-11 16:05 [PATCH v3 0/4] Add WoM feature as an IIO event inv.git-commit
` (2 preceding siblings ...)
2024-03-11 16:05 ` [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events inv.git-commit
@ 2024-03-11 16:05 ` inv.git-commit
2024-03-16 13:54 ` [PATCH v3 0/4] Add WoM feature as an IIO event Jonathan Cameron
4 siblings, 0 replies; 16+ messages in thread
From: inv.git-commit @ 2024-03-11 16:05 UTC (permalink / raw)
To: jic23; +Cc: lars, linux-iio, Jean-Baptiste Maneyrol
From: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
Add wakeup from suspend for WoM when enabled and put accel in low-power
mode when suspended. Requires rewriting pwr_mgmt_1 register handling and
factorize out accel LPF settings. Use a low-power rate similar to the chip
sampling rate but always lower for a best match of the sampling rate while
saving power and adjust threshold to follow the required roc value.
Signed-off-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
---
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 203 +++++++++++++++------
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 14 ++
2 files changed, 166 insertions(+), 51 deletions(-)
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 281fbd8eb791..caa486bbe865 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -289,7 +289,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
};
static int inv_mpu6050_pwr_mgmt_1_write(struct inv_mpu6050_state *st, bool sleep,
- int clock, int temp_dis)
+ bool cycle, int clock, int temp_dis)
{
u8 val;
@@ -303,6 +303,8 @@ static int inv_mpu6050_pwr_mgmt_1_write(struct inv_mpu6050_state *st, bool sleep
val |= INV_MPU6050_BIT_TEMP_DIS;
if (sleep)
val |= INV_MPU6050_BIT_SLEEP;
+ if (cycle)
+ val |= INV_MPU6050_BIT_CYCLE;
dev_dbg(regmap_get_device(st->map), "pwr_mgmt_1: 0x%x\n", val);
return regmap_write(st->map, st->reg->pwr_mgmt_1, val);
@@ -318,7 +320,7 @@ static int inv_mpu6050_clock_switch(struct inv_mpu6050_state *st,
case INV_MPU6000:
case INV_MPU9150:
/* old chips: switch clock manually */
- ret = inv_mpu6050_pwr_mgmt_1_write(st, false, clock, -1);
+ ret = inv_mpu6050_pwr_mgmt_1_write(st, false, false, clock, -1);
if (ret)
return ret;
st->chip_config.clk = clock;
@@ -360,7 +362,7 @@ int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en,
/* turn on/off temperature sensor */
if (mask & INV_MPU6050_SENSOR_TEMP) {
- ret = inv_mpu6050_pwr_mgmt_1_write(st, false, -1, !en);
+ ret = inv_mpu6050_pwr_mgmt_1_write(st, false, false, -1, !en);
if (ret)
return ret;
st->chip_config.temp_en = en;
@@ -467,7 +469,7 @@ static int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st,
{
int result;
- result = inv_mpu6050_pwr_mgmt_1_write(st, !power_on, -1, -1);
+ result = inv_mpu6050_pwr_mgmt_1_write(st, !power_on, false, -1, -1);
if (result)
return result;
@@ -497,22 +499,9 @@ static int inv_mpu6050_set_gyro_fsr(struct inv_mpu6050_state *st,
return regmap_write(st->map, st->reg->gyro_config, data);
}
-/*
- * inv_mpu6050_set_lpf_regs() - set low pass filter registers, chip dependent
- *
- * MPU60xx/MPU9150 use only 1 register for accelerometer + gyroscope
- * MPU6500 and above have a dedicated register for accelerometer
- */
-static int inv_mpu6050_set_lpf_regs(struct inv_mpu6050_state *st,
- enum inv_mpu6050_filter_e val)
+static int inv_mpu6050_set_accel_lpf_regs(struct inv_mpu6050_state *st,
+ enum inv_mpu6050_filter_e val)
{
- int result;
-
- result = regmap_write(st->map, st->reg->lpf, val);
- if (result)
- return result;
-
- /* set accel lpf */
switch (st->chip_type) {
case INV_MPU6050:
case INV_MPU6000:
@@ -531,6 +520,25 @@ static int inv_mpu6050_set_lpf_regs(struct inv_mpu6050_state *st,
return regmap_write(st->map, st->reg->accel_lpf, val);
}
+/*
+ * inv_mpu6050_set_lpf_regs() - set low pass filter registers, chip dependent
+ *
+ * MPU60xx/MPU9150 use only 1 register for accelerometer + gyroscope
+ * MPU6500 and above have a dedicated register for accelerometer
+ */
+static int inv_mpu6050_set_lpf_regs(struct inv_mpu6050_state *st,
+ enum inv_mpu6050_filter_e val)
+{
+ int result;
+
+ result = regmap_write(st->map, st->reg->lpf, val);
+ if (result)
+ return result;
+
+ /* set accel lpf */
+ return inv_mpu6050_set_accel_lpf_regs(st, val);
+}
+
/*
* inv_mpu6050_init_config() - Initialize hardware, disable FIFO.
*
@@ -1002,6 +1010,84 @@ static int inv_mpu6050_set_wom_threshold(struct inv_mpu6050_state *st, u64 value
return 0;
}
+static int inv_mpu6050_set_lp_odr(struct inv_mpu6050_state *st, unsigned int freq_div,
+ unsigned int *lp_div)
+{
+ static const unsigned int freq_dividers[] = {2, 4, 8, 16, 32, 64, 128, 256};
+ static const unsigned int reg_values[] = {
+ INV_MPU6050_LPOSC_500HZ, INV_MPU6050_LPOSC_250HZ,
+ INV_MPU6050_LPOSC_125HZ, INV_MPU6050_LPOSC_62HZ,
+ INV_MPU6050_LPOSC_31HZ, INV_MPU6050_LPOSC_16HZ,
+ INV_MPU6050_LPOSC_8HZ, INV_MPU6050_LPOSC_4HZ,
+ };
+ unsigned int val, i;
+
+ switch (st->chip_type) {
+ case INV_ICM20609:
+ case INV_ICM20689:
+ case INV_ICM20600:
+ case INV_ICM20602:
+ case INV_ICM20690:
+ /* nothing to do */
+ *lp_div = INV_MPU6050_FREQ_DIVIDER(st);
+ return 0;
+ default:
+ break;
+ }
+
+ /* found the nearest superior frequency divider */
+ i = ARRAY_SIZE(reg_values) - 1;
+ val = reg_values[i];
+ *lp_div = freq_dividers[i];
+ for (i = 0; i < ARRAY_SIZE(freq_dividers); ++i) {
+ if (freq_div <= freq_dividers[i]) {
+ val = reg_values[i];
+ *lp_div = freq_dividers[i];
+ break;
+ }
+ }
+
+ dev_dbg(regmap_get_device(st->map), "lp_odr: 0x%x\n", val);
+ return regmap_write(st->map, INV_MPU6500_REG_LP_ODR, val);
+}
+
+static int inv_mpu6050_set_wom_lp(struct inv_mpu6050_state *st, bool on)
+{
+ unsigned int lp_div;
+ int result;
+
+ if (on) {
+ /* set low power ODR */
+ result = inv_mpu6050_set_lp_odr(st, INV_MPU6050_FREQ_DIVIDER(st), &lp_div);
+ if (result)
+ return result;
+ /* disable accel low pass filter */
+ result = inv_mpu6050_set_accel_lpf_regs(st, INV_MPU6050_FILTER_NOLPF);
+ if (result)
+ return result;
+ /* update wom threshold with new low-power frequency divider */
+ result = inv_mpu6050_set_wom_threshold(st, st->chip_config.roc_threshold, lp_div);
+ if (result)
+ return result;
+ /* set cycle mode */
+ result = inv_mpu6050_pwr_mgmt_1_write(st, false, true, -1, -1);
+ } else {
+ /* disable cycle mode */
+ result = inv_mpu6050_pwr_mgmt_1_write(st, false, false, -1, -1);
+ if (result)
+ return result;
+ /* restore wom threshold */
+ result = inv_mpu6050_set_wom_threshold(st, st->chip_config.roc_threshold,
+ INV_MPU6050_FREQ_DIVIDER(st));
+ if (result)
+ return result;
+ /* restore accel low pass filter */
+ result = inv_mpu6050_set_accel_lpf_regs(st, st->chip_config.lpf);
+ }
+
+ return result;
+}
+
static int inv_mpu6050_enable_wom(struct inv_mpu6050_state *st, bool en)
{
struct device *pdev = regmap_get_device(st->map);
@@ -1836,6 +1922,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
irq_type);
return -EINVAL;
}
+ device_set_wakeup_capable(dev, true);
st->vdd_supply = devm_regulator_get(dev, "vdd");
if (IS_ERR(st->vdd_supply))
@@ -2001,16 +2088,27 @@ static int inv_mpu_resume(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
+ bool wakeup;
int result;
- mutex_lock(&st->lock);
- result = inv_mpu_core_enable_regulator_vddio(st);
- if (result)
- goto out_unlock;
+ guard(mutex)(&st->lock);
- result = inv_mpu6050_set_power_itg(st, true);
- if (result)
- goto out_unlock;
+ wakeup = device_may_wakeup(dev) && st->chip_config.wom_en;
+
+ if (wakeup) {
+ enable_irq(st->irq);
+ disable_irq_wake(st->irq);
+ result = inv_mpu6050_set_wom_lp(st, false);
+ if (result)
+ return result;
+ } else {
+ result = inv_mpu_core_enable_regulator_vddio(st);
+ if (result)
+ return result;
+ result = inv_mpu6050_set_power_itg(st, true);
+ if (result)
+ return result;
+ }
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
@@ -2018,20 +2116,17 @@ static int inv_mpu_resume(struct device *dev)
result = inv_mpu6050_switch_engine(st, true, st->suspended_sensors);
if (result)
- goto out_unlock;
+ return result;
- if (st->chip_config.wom_en) {
+ if (st->chip_config.wom_en && !wakeup) {
result = inv_mpu6050_set_wom_int(st, true);
if (result)
- goto out_unlock;
+ return result;
}
if (iio_buffer_enabled(indio_dev))
result = inv_mpu6050_prepare_fifo(st, true);
-out_unlock:
- mutex_unlock(&st->lock);
-
return result;
}
@@ -2039,29 +2134,30 @@ static int inv_mpu_suspend(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
+ bool wakeup;
int result;
- mutex_lock(&st->lock);
+ guard(mutex)(&st->lock);
st->suspended_sensors = 0;
- if (pm_runtime_suspended(dev)) {
- result = 0;
- goto out_unlock;
- }
+ if (pm_runtime_suspended(dev))
+ return 0;
if (iio_buffer_enabled(indio_dev)) {
result = inv_mpu6050_prepare_fifo(st, false);
if (result)
- goto out_unlock;
+ return result;
}
- if (st->chip_config.wom_en) {
+ wakeup = device_may_wakeup(dev) && st->chip_config.wom_en;
+
+ if (st->chip_config.wom_en && !wakeup) {
result = inv_mpu6050_set_wom_int(st, false);
if (result)
- goto out_unlock;
+ return result;
}
- if (st->chip_config.accl_en)
+ if (st->chip_config.accl_en && !wakeup)
st->suspended_sensors |= INV_MPU6050_SENSOR_ACCL;
if (st->chip_config.gyro_en)
st->suspended_sensors |= INV_MPU6050_SENSOR_GYRO;
@@ -2069,21 +2165,26 @@ static int inv_mpu_suspend(struct device *dev)
st->suspended_sensors |= INV_MPU6050_SENSOR_TEMP;
if (st->chip_config.magn_en)
st->suspended_sensors |= INV_MPU6050_SENSOR_MAGN;
- if (st->chip_config.wom_en)
+ if (st->chip_config.wom_en && !wakeup)
st->suspended_sensors |= INV_MPU6050_SENSOR_WOM;
result = inv_mpu6050_switch_engine(st, false, st->suspended_sensors);
if (result)
- goto out_unlock;
-
- result = inv_mpu6050_set_power_itg(st, false);
- if (result)
- goto out_unlock;
+ return result;
- inv_mpu_core_disable_regulator_vddio(st);
-out_unlock:
- mutex_unlock(&st->lock);
+ if (wakeup) {
+ result = inv_mpu6050_set_wom_lp(st, true);
+ if (result)
+ return result;
+ enable_irq_wake(st->irq);
+ disable_irq(st->irq);
+ } else {
+ result = inv_mpu6050_set_power_itg(st, false);
+ if (result)
+ return result;
+ inv_mpu_core_disable_regulator_vddio(st);
+ }
- return result;
+ return 0;
}
static int inv_mpu_runtime_suspend(struct device *dev)
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index ca5f7d45a6d4..d65b8776004a 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -305,6 +305,7 @@ struct inv_mpu6050_state {
#define INV_MPU6050_REG_PWR_MGMT_1 0x6B
#define INV_MPU6050_BIT_H_RESET 0x80
#define INV_MPU6050_BIT_SLEEP 0x40
+#define INV_MPU6050_BIT_CYCLE 0x20
#define INV_MPU6050_BIT_TEMP_DIS 0x08
#define INV_MPU6050_BIT_CLK_MASK 0x7
@@ -336,6 +337,7 @@ struct inv_mpu6050_state {
/* mpu6500 registers */
#define INV_MPU6500_REG_ACCEL_CONFIG_2 0x1D
#define INV_ICM20689_BITS_FIFO_SIZE_MAX 0xC0
+#define INV_MPU6500_REG_LP_ODR 0x1E
#define INV_MPU6500_REG_WOM_THRESHOLD 0x1F
#define INV_MPU6500_REG_ACCEL_INTEL_CTRL 0x69
#define INV_MPU6500_BIT_ACCEL_INTEL_EN BIT(7)
@@ -452,6 +454,18 @@ enum inv_mpu6050_filter_e {
NUM_MPU6050_FILTER
};
+enum inv_mpu6050_lposc_e {
+ INV_MPU6050_LPOSC_4HZ = 4,
+ INV_MPU6050_LPOSC_8HZ,
+ INV_MPU6050_LPOSC_16HZ,
+ INV_MPU6050_LPOSC_31HZ,
+ INV_MPU6050_LPOSC_62HZ,
+ INV_MPU6050_LPOSC_125HZ,
+ INV_MPU6050_LPOSC_250HZ,
+ INV_MPU6050_LPOSC_500HZ,
+ NUM_MPU6050_LPOSC,
+};
+
/* IIO attribute address */
enum INV_MPU6050_IIO_ATTR_ADDR {
ATTR_GYRO_MATRIX,
--
2.34.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v3 0/4] Add WoM feature as an IIO event
2024-03-11 16:05 [PATCH v3 0/4] Add WoM feature as an IIO event inv.git-commit
` (3 preceding siblings ...)
2024-03-11 16:05 ` [PATCH v3 4/4] iio: imu: inv_mpu6050: add WoM suspend wakeup with low-power mode inv.git-commit
@ 2024-03-16 13:54 ` Jonathan Cameron
4 siblings, 0 replies; 16+ messages in thread
From: Jonathan Cameron @ 2024-03-16 13:54 UTC (permalink / raw)
To: inv.git-commit; +Cc: lars, linux-iio, Jean-Baptiste Maneyrol
On Mon, 11 Mar 2024 16:05:53 +0000
inv.git-commit@tdk.com wrote:
> From: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
>
> Add WoM (Wake-on-Motion) feature for all chips supporting it (all except
> MPU-6000/6050/9150). WoM compares the magnitude of the current accel sample
> with the previous one against a threshold and returns an interrupt event if
> the value is higher.
>
> WoM is checking against all axes and maps best to ROC since it compares the
> last 2 samples. Thus report WoM as an accel x|y|z roc_rising IIO event, add
> system wakeup functionality if WoM is on and put the chip in low-power mode
> when the system is suspended. Corresponding ROC value is in SI units since
> the chip is using an absolute value in mg.
>
> v2:
> - Rework to use accel x|y|z roc for reporting WoM event
> - Use only datasheet advertised bits for MPU-6500 family chips
>
> v3
> - Coding style fixes
> - Convert mutex usage to guard/scoped_guard
>
Applied to the togreg-normal branch of iio.git and pushed out for 0-day
to get started. I'll be rebasing that tree after rc1 so use at your
own risk ;)
btw thought I'd sent this on Thursday - just found it still open on my screen :(
Jonathan
> Jean-Baptiste Maneyrol (4):
> iio: imu: inv_mpu6050: add WoM (Wake-on-Motion) sensor
> iio: imu: inv_mpu6050: add WoM event as accel event
> iio: imu: inv_mpu6050: add new interrupt handler for WoM events
> iio: imu: inv_mpu6050: add WoM suspend wakeup with low-power mode
>
> drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 542 ++++++++++++++++--
> drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 36 +-
> drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 17 +-
> drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 83 ++-
> 4 files changed, 595 insertions(+), 83 deletions(-)
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events
2024-03-11 16:05 ` [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events inv.git-commit
@ 2024-07-23 8:25 ` Svyatoslav Ryhel
2024-08-06 16:53 ` Jonathan Cameron
0 siblings, 1 reply; 16+ messages in thread
From: Svyatoslav Ryhel @ 2024-07-23 8:25 UTC (permalink / raw)
To: inv.git-commit, jic23; +Cc: lars, linux-iio, Jean-Baptiste Maneyrol
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.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events
2024-07-23 8:25 ` Svyatoslav Ryhel
@ 2024-08-06 16:53 ` Jonathan Cameron
2024-08-07 15:48 ` Jean-Baptiste Maneyrol
0 siblings, 1 reply; 16+ messages in thread
From: Jonathan Cameron @ 2024-08-06 16:53 UTC (permalink / raw)
To: Svyatoslav Ryhel; +Cc: inv.git-commit, lars, linux-iio, Jean-Baptiste Maneyrol
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.
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events
2024-08-06 16:53 ` Jonathan Cameron
@ 2024-08-07 15:48 ` Jean-Baptiste Maneyrol
2024-08-07 16:03 ` Svyatoslav Ryhel
0 siblings, 1 reply; 16+ messages in thread
From: Jean-Baptiste Maneyrol @ 2024-08-07 15:48 UTC (permalink / raw)
To: Jonathan Cameron, Svyatoslav Ryhel
Cc: INV Git Commit, lars@metafoo.de, linux-iio@vger.kernel.org
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
________________________________________
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.
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events
2024-08-07 15:48 ` Jean-Baptiste Maneyrol
@ 2024-08-07 16:03 ` Svyatoslav Ryhel
2024-08-07 16:18 ` Jean-Baptiste Maneyrol
0 siblings, 1 reply; 16+ messages in thread
From: Svyatoslav Ryhel @ 2024-08-07 16:03 UTC (permalink / raw)
To: Jean-Baptiste Maneyrol
Cc: Jonathan Cameron, INV Git Commit, lars@metafoo.de,
linux-iio@vger.kernel.org
ср, 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.
> >
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events
2024-08-07 16:03 ` Svyatoslav Ryhel
@ 2024-08-07 16:18 ` Jean-Baptiste Maneyrol
2024-08-07 16:48 ` Svyatoslav Ryhel
2024-08-13 16:06 ` Jean-Baptiste Maneyrol
0 siblings, 2 replies; 16+ messages in thread
From: Jean-Baptiste Maneyrol @ 2024-08-07 16:18 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: Jonathan Cameron, INV Git Commit, lars@metafoo.de,
linux-iio@vger.kernel.org
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.
> >
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events
2024-08-07 16:18 ` Jean-Baptiste Maneyrol
@ 2024-08-07 16:48 ` Svyatoslav Ryhel
2024-08-13 16:06 ` Jean-Baptiste Maneyrol
1 sibling, 0 replies; 16+ messages in thread
From: Svyatoslav Ryhel @ 2024-08-07 16:48 UTC (permalink / raw)
To: Jean-Baptiste Maneyrol
Cc: Jonathan Cameron, INV Git Commit, lars@metafoo.de,
linux-iio@vger.kernel.org
ср, 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.
> > >
> >
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events
2024-08-07 16:18 ` Jean-Baptiste Maneyrol
2024-08-07 16:48 ` Svyatoslav Ryhel
@ 2024-08-13 16:06 ` Jean-Baptiste Maneyrol
2024-08-13 16:09 ` Svyatoslav Ryhel
1 sibling, 1 reply; 16+ messages in thread
From: Jean-Baptiste Maneyrol @ 2024-08-13 16:06 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: Jonathan Cameron, INV Git Commit, lars@metafoo.de,
linux-iio@vger.kernel.org
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
________________________________________
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.
> >
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events
2024-08-13 16:06 ` Jean-Baptiste Maneyrol
@ 2024-08-13 16:09 ` Svyatoslav Ryhel
2024-08-14 14:39 ` Jean-Baptiste Maneyrol
0 siblings, 1 reply; 16+ messages in thread
From: Svyatoslav Ryhel @ 2024-08-13 16:09 UTC (permalink / raw)
To: Jean-Baptiste Maneyrol
Cc: Jonathan Cameron, INV Git Commit, lars@metafoo.de,
linux-iio@vger.kernel.org
вт, 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.
> > >
> >
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events
2024-08-13 16:09 ` Svyatoslav Ryhel
@ 2024-08-14 14:39 ` Jean-Baptiste Maneyrol
2024-08-14 15:53 ` Svyatoslav Ryhel
0 siblings, 1 reply; 16+ messages in thread
From: Jean-Baptiste Maneyrol @ 2024-08-14 14:39 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: Jonathan Cameron, lars@metafoo.de, linux-iio@vger.kernel.org
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
________________________________________
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.
> > >
> >
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events
2024-08-14 14:39 ` Jean-Baptiste Maneyrol
@ 2024-08-14 15:53 ` Svyatoslav Ryhel
0 siblings, 0 replies; 16+ messages in thread
From: Svyatoslav Ryhel @ 2024-08-14 15:53 UTC (permalink / raw)
To: Jean-Baptiste Maneyrol
Cc: Jonathan Cameron, lars@metafoo.de, linux-iio@vger.kernel.org
ср, 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.
> > > >
> > >
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2024-08-14 15:53 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-11 16:05 [PATCH v3 0/4] Add WoM feature as an IIO event inv.git-commit
2024-03-11 16:05 ` [PATCH v3 1/4] iio: imu: inv_mpu6050: add WoM (Wake-on-Motion) sensor inv.git-commit
2024-03-11 16:05 ` [PATCH v3 2/4] iio: imu: inv_mpu6050: add WoM event as accel event inv.git-commit
2024-03-11 16:05 ` [PATCH v3 3/4] iio: imu: inv_mpu6050: add new interrupt handler for WoM events inv.git-commit
2024-07-23 8:25 ` Svyatoslav Ryhel
2024-08-06 16:53 ` Jonathan Cameron
2024-08-07 15:48 ` Jean-Baptiste Maneyrol
2024-08-07 16:03 ` Svyatoslav Ryhel
2024-08-07 16:18 ` Jean-Baptiste Maneyrol
2024-08-07 16:48 ` Svyatoslav Ryhel
2024-08-13 16:06 ` Jean-Baptiste Maneyrol
2024-08-13 16:09 ` Svyatoslav Ryhel
2024-08-14 14:39 ` Jean-Baptiste Maneyrol
2024-08-14 15:53 ` Svyatoslav Ryhel
2024-03-11 16:05 ` [PATCH v3 4/4] iio: imu: inv_mpu6050: add WoM suspend wakeup with low-power mode inv.git-commit
2024-03-16 13:54 ` [PATCH v3 0/4] Add WoM feature as an IIO event Jonathan Cameron
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).