Commit 0b70c084 authored by Jean-Baptiste Maneyrol's avatar Jean-Baptiste Maneyrol Committed by Jonathan Cameron

iio: imu: inv_mpu6050: add WoM (Wake-on-Motion) sensor

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: default avatarJean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
Link: https://lore.kernel.org/r/20240311160557.437337-2-inv.git-commit@tdk.comSigned-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent e264b086
This diff is collapsed.
......@@ -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 */
......
......@@ -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);
}
/*
......
......@@ -135,11 +135,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);
......@@ -172,9 +174,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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment