summaryrefslogtreecommitdiffstats
path: root/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c')
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c1056
1 files changed, 896 insertions, 160 deletions
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
index fd5ebe1e1594..11b2c7bc8041 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
@@ -32,7 +32,7 @@
* - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
* - FIFO size: 3KB
*
- * - LSM9DS1:
+ * - LSM9DS1/LSM6DS0:
* - Accelerometer supported ODR [Hz]: 10, 50, 119, 238, 476, 952
* - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
* - Gyroscope supported ODR [Hz]: 15, 60, 119, 238, 476, 952
@@ -48,8 +48,11 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/iio/events.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/bitfield.h>
@@ -58,17 +61,14 @@
#include "st_lsm6dsx.h"
-#define ST_LSM6DSX_REG_FIFO_FTH_IRQ_MASK BIT(3)
#define ST_LSM6DSX_REG_WHOAMI_ADDR 0x0f
-#define ST_LSM6DSX_REG_RESET_MASK BIT(0)
-#define ST_LSM6DSX_REG_BOOT_MASK BIT(7)
-#define ST_LSM6DSX_REG_BDU_ADDR 0x12
-#define ST_LSM6DSX_REG_BDU_MASK BIT(6)
+
+#define ST_LSM6DSX_TS_SENSITIVITY 25000UL /* 25us */
static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = {
- ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x28, IIO_MOD_X, 0),
- ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1),
- ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2c, IIO_MOD_Z, 2),
+ ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x28, IIO_MOD_X, 0),
+ ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1),
+ ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x2c, IIO_MOD_Z, 2),
IIO_CHAN_SOFT_TIMESTAMP(3),
};
@@ -89,14 +89,26 @@ static const struct iio_chan_spec st_lsm6ds0_gyro_channels[] = {
static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
{
.wai = 0x68,
- .int1_addr = 0x0c,
- .int2_addr = 0x0d,
- .reset_addr = 0x22,
+ .reset = {
+ .addr = 0x22,
+ .mask = BIT(0),
+ },
+ .boot = {
+ .addr = 0x22,
+ .mask = BIT(7),
+ },
+ .bdu = {
+ .addr = 0x22,
+ .mask = BIT(6),
+ },
.max_fifo_size = 32,
.id = {
{
.hw_id = ST_LSM9DS1_ID,
.name = ST_LSM9DS1_DEV_NAME,
+ }, {
+ .hw_id = ST_LSM6DS0_ID,
+ .name = ST_LSM6DS0_DEV_NAME,
},
},
.channels = {
@@ -115,24 +127,26 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.addr = 0x20,
.mask = GENMASK(7, 5),
},
- .odr_avl[0] = { 10, 0x01 },
- .odr_avl[1] = { 50, 0x02 },
- .odr_avl[2] = { 119, 0x03 },
- .odr_avl[3] = { 238, 0x04 },
- .odr_avl[4] = { 476, 0x05 },
- .odr_avl[5] = { 952, 0x06 },
+ .odr_avl[0] = { 10000, 0x01 },
+ .odr_avl[1] = { 50000, 0x02 },
+ .odr_avl[2] = { 119000, 0x03 },
+ .odr_avl[3] = { 238000, 0x04 },
+ .odr_avl[4] = { 476000, 0x05 },
+ .odr_avl[5] = { 952000, 0x06 },
+ .odr_len = 6,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
.addr = 0x10,
.mask = GENMASK(7, 5),
},
- .odr_avl[0] = { 15, 0x01 },
- .odr_avl[1] = { 60, 0x02 },
- .odr_avl[2] = { 119, 0x03 },
- .odr_avl[3] = { 238, 0x04 },
- .odr_avl[4] = { 476, 0x05 },
- .odr_avl[5] = { 952, 0x06 },
+ .odr_avl[0] = { 14900, 0x01 },
+ .odr_avl[1] = { 59500, 0x02 },
+ .odr_avl[2] = { 119000, 0x03 },
+ .odr_avl[3] = { 238000, 0x04 },
+ .odr_avl[4] = { 476000, 0x05 },
+ .odr_avl[5] = { 952000, 0x06 },
+ .odr_len = 6,
},
},
.fs_table = {
@@ -152,18 +166,46 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.addr = 0x10,
.mask = GENMASK(4, 3),
},
- .fs_avl[0] = { IIO_DEGREE_TO_RAD(245), 0x0 },
- .fs_avl[1] = { IIO_DEGREE_TO_RAD(500), 0x1 },
- .fs_avl[2] = { IIO_DEGREE_TO_RAD(2000), 0x3 },
+
+ .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 },
+ .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 },
+ .fs_avl[2] = { IIO_DEGREE_TO_RAD(70000), 0x3 },
.fs_len = 3,
},
},
+ .irq_config = {
+ .irq1 = {
+ .addr = 0x0c,
+ .mask = BIT(3),
+ },
+ .irq2 = {
+ .addr = 0x0d,
+ .mask = BIT(3),
+ },
+ .hla = {
+ .addr = 0x22,
+ .mask = BIT(5),
+ },
+ .od = {
+ .addr = 0x22,
+ .mask = BIT(4),
+ },
+ },
},
{
.wai = 0x69,
- .int1_addr = 0x0d,
- .int2_addr = 0x0e,
- .reset_addr = 0x12,
+ .reset = {
+ .addr = 0x12,
+ .mask = BIT(0),
+ },
+ .boot = {
+ .addr = 0x12,
+ .mask = BIT(7),
+ },
+ .bdu = {
+ .addr = 0x12,
+ .mask = BIT(6),
+ },
.max_fifo_size = 1365,
.id = {
{
@@ -187,24 +229,26 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.addr = 0x10,
.mask = GENMASK(7, 4),
},
- .odr_avl[0] = { 13, 0x01 },
- .odr_avl[1] = { 26, 0x02 },
- .odr_avl[2] = { 52, 0x03 },
- .odr_avl[3] = { 104, 0x04 },
- .odr_avl[4] = { 208, 0x05 },
- .odr_avl[5] = { 416, 0x06 },
+ .odr_avl[0] = { 12500, 0x01 },
+ .odr_avl[1] = { 26000, 0x02 },
+ .odr_avl[2] = { 52000, 0x03 },
+ .odr_avl[3] = { 104000, 0x04 },
+ .odr_avl[4] = { 208000, 0x05 },
+ .odr_avl[5] = { 416000, 0x06 },
+ .odr_len = 6,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
.addr = 0x11,
.mask = GENMASK(7, 4),
},
- .odr_avl[0] = { 13, 0x01 },
- .odr_avl[1] = { 26, 0x02 },
- .odr_avl[2] = { 52, 0x03 },
- .odr_avl[3] = { 104, 0x04 },
- .odr_avl[4] = { 208, 0x05 },
- .odr_avl[5] = { 416, 0x06 },
+ .odr_avl[0] = { 12500, 0x01 },
+ .odr_avl[1] = { 26000, 0x02 },
+ .odr_avl[2] = { 52000, 0x03 },
+ .odr_avl[3] = { 104000, 0x04 },
+ .odr_avl[4] = { 208000, 0x05 },
+ .odr_avl[5] = { 416000, 0x06 },
+ .odr_len = 6,
},
},
.fs_table = {
@@ -231,6 +275,36 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_len = 4,
},
},
+ .irq_config = {
+ .irq1 = {
+ .addr = 0x0d,
+ .mask = BIT(3),
+ },
+ .irq2 = {
+ .addr = 0x0e,
+ .mask = BIT(3),
+ },
+ .lir = {
+ .addr = 0x58,
+ .mask = BIT(0),
+ },
+ .irq1_func = {
+ .addr = 0x5e,
+ .mask = BIT(5),
+ },
+ .irq2_func = {
+ .addr = 0x5f,
+ .mask = BIT(5),
+ },
+ .hla = {
+ .addr = 0x12,
+ .mask = BIT(5),
+ },
+ .od = {
+ .addr = 0x12,
+ .mask = BIT(4),
+ },
+ },
.decimator = {
[ST_LSM6DSX_ID_ACC] = {
.addr = 0x08,
@@ -272,12 +346,32 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.mask = GENMASK(5, 3),
},
},
+ .event_settings = {
+ .wakeup_reg = {
+ .addr = 0x5B,
+ .mask = GENMASK(5, 0),
+ },
+ .wakeup_src_reg = 0x1b,
+ .wakeup_src_status_mask = BIT(3),
+ .wakeup_src_z_mask = BIT(0),
+ .wakeup_src_y_mask = BIT(1),
+ .wakeup_src_x_mask = BIT(2),
+ },
},
{
.wai = 0x69,
- .int1_addr = 0x0d,
- .int2_addr = 0x0e,
- .reset_addr = 0x12,
+ .reset = {
+ .addr = 0x12,
+ .mask = BIT(0),
+ },
+ .boot = {
+ .addr = 0x12,
+ .mask = BIT(7),
+ },
+ .bdu = {
+ .addr = 0x12,
+ .mask = BIT(6),
+ },
.max_fifo_size = 682,
.id = {
{
@@ -301,24 +395,26 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.addr = 0x10,
.mask = GENMASK(7, 4),
},
- .odr_avl[0] = { 13, 0x01 },
- .odr_avl[1] = { 26, 0x02 },
- .odr_avl[2] = { 52, 0x03 },
- .odr_avl[3] = { 104, 0x04 },
- .odr_avl[4] = { 208, 0x05 },
- .odr_avl[5] = { 416, 0x06 },
+ .odr_avl[0] = { 12500, 0x01 },
+ .odr_avl[1] = { 26000, 0x02 },
+ .odr_avl[2] = { 52000, 0x03 },
+ .odr_avl[3] = { 104000, 0x04 },
+ .odr_avl[4] = { 208000, 0x05 },
+ .odr_avl[5] = { 416000, 0x06 },
+ .odr_len = 6,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
.addr = 0x11,
.mask = GENMASK(7, 4),
},
- .odr_avl[0] = { 13, 0x01 },
- .odr_avl[1] = { 26, 0x02 },
- .odr_avl[2] = { 52, 0x03 },
- .odr_avl[3] = { 104, 0x04 },
- .odr_avl[4] = { 208, 0x05 },
- .odr_avl[5] = { 416, 0x06 },
+ .odr_avl[0] = { 12500, 0x01 },
+ .odr_avl[1] = { 26000, 0x02 },
+ .odr_avl[2] = { 52000, 0x03 },
+ .odr_avl[3] = { 104000, 0x04 },
+ .odr_avl[4] = { 208000, 0x05 },
+ .odr_avl[5] = { 416000, 0x06 },
+ .odr_len = 6,
},
},
.fs_table = {
@@ -345,6 +441,36 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_len = 4,
},
},
+ .irq_config = {
+ .irq1 = {
+ .addr = 0x0d,
+ .mask = BIT(3),
+ },
+ .irq2 = {
+ .addr = 0x0e,
+ .mask = BIT(3),
+ },
+ .lir = {
+ .addr = 0x58,
+ .mask = BIT(0),
+ },
+ .irq1_func = {
+ .addr = 0x5e,
+ .mask = BIT(5),
+ },
+ .irq2_func = {
+ .addr = 0x5f,
+ .mask = BIT(5),
+ },
+ .hla = {
+ .addr = 0x12,
+ .mask = BIT(5),
+ },
+ .od = {
+ .addr = 0x12,
+ .mask = BIT(4),
+ },
+ },
.decimator = {
[ST_LSM6DSX_ID_ACC] = {
.addr = 0x08,
@@ -386,12 +512,32 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.mask = GENMASK(5, 3),
},
},
+ .event_settings = {
+ .wakeup_reg = {
+ .addr = 0x5B,
+ .mask = GENMASK(5, 0),
+ },
+ .wakeup_src_reg = 0x1b,
+ .wakeup_src_status_mask = BIT(3),
+ .wakeup_src_z_mask = BIT(0),
+ .wakeup_src_y_mask = BIT(1),
+ .wakeup_src_x_mask = BIT(2),
+ },
},
{
.wai = 0x6a,
- .int1_addr = 0x0d,
- .int2_addr = 0x0e,
- .reset_addr = 0x12,
+ .reset = {
+ .addr = 0x12,
+ .mask = BIT(0),
+ },
+ .boot = {
+ .addr = 0x12,
+ .mask = BIT(7),
+ },
+ .bdu = {
+ .addr = 0x12,
+ .mask = BIT(6),
+ },
.max_fifo_size = 682,
.id = {
{
@@ -424,24 +570,26 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.addr = 0x10,
.mask = GENMASK(7, 4),
},
- .odr_avl[0] = { 13, 0x01 },
- .odr_avl[1] = { 26, 0x02 },
- .odr_avl[2] = { 52, 0x03 },
- .odr_avl[3] = { 104, 0x04 },
- .odr_avl[4] = { 208, 0x05 },
- .odr_avl[5] = { 416, 0x06 },
+ .odr_avl[0] = { 12500, 0x01 },
+ .odr_avl[1] = { 26000, 0x02 },
+ .odr_avl[2] = { 52000, 0x03 },
+ .odr_avl[3] = { 104000, 0x04 },
+ .odr_avl[4] = { 208000, 0x05 },
+ .odr_avl[5] = { 416000, 0x06 },
+ .odr_len = 6,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
.addr = 0x11,
.mask = GENMASK(7, 4),
},
- .odr_avl[0] = { 13, 0x01 },
- .odr_avl[1] = { 26, 0x02 },
- .odr_avl[2] = { 52, 0x03 },
- .odr_avl[3] = { 104, 0x04 },
- .odr_avl[4] = { 208, 0x05 },
- .odr_avl[5] = { 416, 0x06 },
+ .odr_avl[0] = { 12500, 0x01 },
+ .odr_avl[1] = { 26000, 0x02 },
+ .odr_avl[2] = { 52000, 0x03 },
+ .odr_avl[3] = { 104000, 0x04 },
+ .odr_avl[4] = { 208000, 0x05 },
+ .odr_avl[5] = { 416000, 0x06 },
+ .odr_len = 6,
},
},
.fs_table = {
@@ -468,6 +616,36 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_len = 4,
},
},
+ .irq_config = {
+ .irq1 = {
+ .addr = 0x0d,
+ .mask = BIT(3),
+ },
+ .irq2 = {
+ .addr = 0x0e,
+ .mask = BIT(3),
+ },
+ .lir = {
+ .addr = 0x58,
+ .mask = BIT(0),
+ },
+ .irq1_func = {
+ .addr = 0x5e,
+ .mask = BIT(5),
+ },
+ .irq2_func = {
+ .addr = 0x5f,
+ .mask = BIT(5),
+ },
+ .hla = {
+ .addr = 0x12,
+ .mask = BIT(5),
+ },
+ .od = {
+ .addr = 0x12,
+ .mask = BIT(4),
+ },
+ },
.decimator = {
[ST_LSM6DSX_ID_ACC] = {
.addr = 0x08,
@@ -509,12 +687,36 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.mask = GENMASK(5, 3),
},
},
+ .event_settings = {
+ .enable_reg = {
+ .addr = 0x58,
+ .mask = BIT(7),
+ },
+ .wakeup_reg = {
+ .addr = 0x5B,
+ .mask = GENMASK(5, 0),
+ },
+ .wakeup_src_reg = 0x1b,
+ .wakeup_src_status_mask = BIT(3),
+ .wakeup_src_z_mask = BIT(0),
+ .wakeup_src_y_mask = BIT(1),
+ .wakeup_src_x_mask = BIT(2),
+ },
},
{
.wai = 0x6c,
- .int1_addr = 0x0d,
- .int2_addr = 0x0e,
- .reset_addr = 0x12,
+ .reset = {
+ .addr = 0x12,
+ .mask = BIT(0),
+ },
+ .boot = {
+ .addr = 0x12,
+ .mask = BIT(7),
+ },
+ .bdu = {
+ .addr = 0x12,
+ .mask = BIT(6),
+ },
.max_fifo_size = 512,
.id = {
{
@@ -535,30 +737,36 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.len = ARRAY_SIZE(st_lsm6dsx_gyro_channels),
},
},
+ .drdy_mask = {
+ .addr = 0x13,
+ .mask = BIT(3),
+ },
.odr_table = {
[ST_LSM6DSX_ID_ACC] = {
.reg = {
.addr = 0x10,
.mask = GENMASK(7, 4),
},
- .odr_avl[0] = { 13, 0x01 },
- .odr_avl[1] = { 26, 0x02 },
- .odr_avl[2] = { 52, 0x03 },
- .odr_avl[3] = { 104, 0x04 },
- .odr_avl[4] = { 208, 0x05 },
- .odr_avl[5] = { 416, 0x06 },
+ .odr_avl[0] = { 12500, 0x01 },
+ .odr_avl[1] = { 26000, 0x02 },
+ .odr_avl[2] = { 52000, 0x03 },
+ .odr_avl[3] = { 104000, 0x04 },
+ .odr_avl[4] = { 208000, 0x05 },
+ .odr_avl[5] = { 416000, 0x06 },
+ .odr_len = 6,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
.addr = 0x11,
.mask = GENMASK(7, 4),
},
- .odr_avl[0] = { 13, 0x01 },
- .odr_avl[1] = { 26, 0x02 },
- .odr_avl[2] = { 52, 0x03 },
- .odr_avl[3] = { 104, 0x04 },
- .odr_avl[4] = { 208, 0x05 },
- .odr_avl[5] = { 416, 0x06 },
+ .odr_avl[0] = { 12500, 0x01 },
+ .odr_avl[1] = { 26000, 0x02 },
+ .odr_avl[2] = { 52000, 0x03 },
+ .odr_avl[3] = { 104000, 0x04 },
+ .odr_avl[4] = { 208000, 0x05 },
+ .odr_avl[5] = { 416000, 0x06 },
+ .odr_len = 6,
},
},
.fs_table = {
@@ -585,6 +793,40 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_len = 4,
},
},
+ .irq_config = {
+ .irq1 = {
+ .addr = 0x0d,
+ .mask = BIT(3),
+ },
+ .irq2 = {
+ .addr = 0x0e,
+ .mask = BIT(3),
+ },
+ .lir = {
+ .addr = 0x56,
+ .mask = BIT(0),
+ },
+ .clear_on_read = {
+ .addr = 0x56,
+ .mask = BIT(6),
+ },
+ .irq1_func = {
+ .addr = 0x5e,
+ .mask = BIT(5),
+ },
+ .irq2_func = {
+ .addr = 0x5f,
+ .mask = BIT(5),
+ },
+ .hla = {
+ .addr = 0x12,
+ .mask = BIT(5),
+ },
+ .od = {
+ .addr = 0x12,
+ .mask = BIT(4),
+ },
+ },
.batch = {
[ST_LSM6DSX_ID_ACC] = {
.addr = 0x09,
@@ -617,6 +859,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.addr = 0x0a,
.mask = GENMASK(7, 6),
},
+ .freq_fine = 0x63,
},
.shub_settings = {
.page_mux = {
@@ -643,13 +886,37 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.slv0_addr = 0x15,
.dw_slv0_addr = 0x21,
.batch_en = BIT(3),
- }
+ },
+ .event_settings = {
+ .enable_reg = {
+ .addr = 0x58,
+ .mask = BIT(7),
+ },
+ .wakeup_reg = {
+ .addr = 0x5b,
+ .mask = GENMASK(5, 0),
+ },
+ .wakeup_src_reg = 0x1b,
+ .wakeup_src_status_mask = BIT(3),
+ .wakeup_src_z_mask = BIT(0),
+ .wakeup_src_y_mask = BIT(1),
+ .wakeup_src_x_mask = BIT(2),
+ },
},
{
.wai = 0x6b,
- .int1_addr = 0x0d,
- .int2_addr = 0x0e,
- .reset_addr = 0x12,
+ .reset = {
+ .addr = 0x12,
+ .mask = BIT(0),
+ },
+ .boot = {
+ .addr = 0x12,
+ .mask = BIT(7),
+ },
+ .bdu = {
+ .addr = 0x12,
+ .mask = BIT(6),
+ },
.max_fifo_size = 512,
.id = {
{
@@ -667,30 +934,36 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.len = ARRAY_SIZE(st_lsm6dsx_gyro_channels),
},
},
+ .drdy_mask = {
+ .addr = 0x13,
+ .mask = BIT(3),
+ },
.odr_table = {
[ST_LSM6DSX_ID_ACC] = {
.reg = {
.addr = 0x10,
.mask = GENMASK(7, 4),
},
- .odr_avl[0] = { 13, 0x01 },
- .odr_avl[1] = { 26, 0x02 },
- .odr_avl[2] = { 52, 0x03 },
- .odr_avl[3] = { 104, 0x04 },
- .odr_avl[4] = { 208, 0x05 },
- .odr_avl[5] = { 416, 0x06 },
+ .odr_avl[0] = { 12500, 0x01 },
+ .odr_avl[1] = { 26000, 0x02 },
+ .odr_avl[2] = { 52000, 0x03 },
+ .odr_avl[3] = { 104000, 0x04 },
+ .odr_avl[4] = { 208000, 0x05 },
+ .odr_avl[5] = { 416000, 0x06 },
+ .odr_len = 6,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
.addr = 0x11,
.mask = GENMASK(7, 4),
},
- .odr_avl[0] = { 13, 0x01 },
- .odr_avl[1] = { 26, 0x02 },
- .odr_avl[2] = { 52, 0x03 },
- .odr_avl[3] = { 104, 0x04 },
- .odr_avl[4] = { 208, 0x05 },
- .odr_avl[5] = { 416, 0x06 },
+ .odr_avl[0] = { 12500, 0x01 },
+ .odr_avl[1] = { 26000, 0x02 },
+ .odr_avl[2] = { 52000, 0x03 },
+ .odr_avl[3] = { 104000, 0x04 },
+ .odr_avl[4] = { 208000, 0x05 },
+ .odr_avl[5] = { 416000, 0x06 },
+ .odr_len = 6,
},
},
.fs_table = {
@@ -717,6 +990,40 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_len = 4,
},
},
+ .irq_config = {
+ .irq1 = {
+ .addr = 0x0d,
+ .mask = BIT(3),
+ },
+ .irq2 = {
+ .addr = 0x0e,
+ .mask = BIT(3),
+ },
+ .lir = {
+ .addr = 0x56,
+ .mask = BIT(0),
+ },
+ .clear_on_read = {
+ .addr = 0x56,
+ .mask = BIT(6),
+ },
+ .irq1_func = {
+ .addr = 0x5e,
+ .mask = BIT(5),
+ },
+ .irq2_func = {
+ .addr = 0x5f,
+ .mask = BIT(5),
+ },
+ .hla = {
+ .addr = 0x12,
+ .mask = BIT(5),
+ },
+ .od = {
+ .addr = 0x12,
+ .mask = BIT(4),
+ },
+ },
.batch = {
[ST_LSM6DSX_ID_ACC] = {
.addr = 0x09,
@@ -749,13 +1056,38 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.addr = 0x0a,
.mask = GENMASK(7, 6),
},
+ .freq_fine = 0x63,
+ },
+ .event_settings = {
+ .enable_reg = {
+ .addr = 0x58,
+ .mask = BIT(7),
+ },
+ .wakeup_reg = {
+ .addr = 0x5B,
+ .mask = GENMASK(5, 0),
+ },
+ .wakeup_src_reg = 0x1b,
+ .wakeup_src_status_mask = BIT(3),
+ .wakeup_src_z_mask = BIT(0),
+ .wakeup_src_y_mask = BIT(1),
+ .wakeup_src_x_mask = BIT(2),
},
},
{
.wai = 0x6b,
- .int1_addr = 0x0d,
- .int2_addr = 0x0e,
- .reset_addr = 0x12,
+ .reset = {
+ .addr = 0x12,
+ .mask = BIT(0),
+ },
+ .boot = {
+ .addr = 0x12,
+ .mask = BIT(7),
+ },
+ .bdu = {
+ .addr = 0x12,
+ .mask = BIT(6),
+ },
.max_fifo_size = 512,
.id = {
{
@@ -764,6 +1096,9 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
}, {
.hw_id = ST_ISM330DHCX_ID,
.name = ST_ISM330DHCX_DEV_NAME,
+ }, {
+ .hw_id = ST_LSM6DSRX_ID,
+ .name = ST_LSM6DSRX_DEV_NAME,
},
},
.channels = {
@@ -776,30 +1111,36 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.len = ARRAY_SIZE(st_lsm6dsx_gyro_channels),
},
},
+ .drdy_mask = {
+ .addr = 0x13,
+ .mask = BIT(3),
+ },
.odr_table = {
[ST_LSM6DSX_ID_ACC] = {
.reg = {
.addr = 0x10,
.mask = GENMASK(7, 4),
},
- .odr_avl[0] = { 13, 0x01 },
- .odr_avl[1] = { 26, 0x02 },
- .odr_avl[2] = { 52, 0x03 },
- .odr_avl[3] = { 104, 0x04 },
- .odr_avl[4] = { 208, 0x05 },
- .odr_avl[5] = { 416, 0x06 },
+ .odr_avl[0] = { 12500, 0x01 },
+ .odr_avl[1] = { 26000, 0x02 },
+ .odr_avl[2] = { 52000, 0x03 },
+ .odr_avl[3] = { 104000, 0x04 },
+ .odr_avl[4] = { 208000, 0x05 },
+ .odr_avl[5] = { 416000, 0x06 },
+ .odr_len = 6,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
.addr = 0x11,
.mask = GENMASK(7, 4),
},
- .odr_avl[0] = { 13, 0x01 },
- .odr_avl[1] = { 26, 0x02 },
- .odr_avl[2] = { 52, 0x03 },
- .odr_avl[3] = { 104, 0x04 },
- .odr_avl[4] = { 208, 0x05 },
- .odr_avl[5] = { 416, 0x06 },
+ .odr_avl[0] = { 12500, 0x01 },
+ .odr_avl[1] = { 26000, 0x02 },
+ .odr_avl[2] = { 52000, 0x03 },
+ .odr_avl[3] = { 104000, 0x04 },
+ .odr_avl[4] = { 208000, 0x05 },
+ .odr_avl[5] = { 416000, 0x06 },
+ .odr_len = 6,
},
},
.fs_table = {
@@ -826,6 +1167,40 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_len = 4,
},
},
+ .irq_config = {
+ .irq1 = {
+ .addr = 0x0d,
+ .mask = BIT(3),
+ },
+ .irq2 = {
+ .addr = 0x0e,
+ .mask = BIT(3),
+ },
+ .lir = {
+ .addr = 0x56,
+ .mask = BIT(0),
+ },
+ .clear_on_read = {
+ .addr = 0x56,
+ .mask = BIT(6),
+ },
+ .irq1_func = {
+ .addr = 0x5e,
+ .mask = BIT(5),
+ },
+ .irq2_func = {
+ .addr = 0x5f,
+ .mask = BIT(5),
+ },
+ .hla = {
+ .addr = 0x12,
+ .mask = BIT(5),
+ },
+ .od = {
+ .addr = 0x12,
+ .mask = BIT(4),
+ },
+ },
.batch = {
[ST_LSM6DSX_ID_ACC] = {
.addr = 0x09,
@@ -858,6 +1233,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.addr = 0x0a,
.mask = GENMASK(7, 6),
},
+ .freq_fine = 0x63,
},
.shub_settings = {
.page_mux = {
@@ -884,6 +1260,21 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.slv0_addr = 0x15,
.dw_slv0_addr = 0x21,
.batch_en = BIT(3),
+ },
+ .event_settings = {
+ .enable_reg = {
+ .addr = 0x58,
+ .mask = BIT(7),
+ },
+ .wakeup_reg = {
+ .addr = 0x5B,
+ .mask = GENMASK(5, 0),
+ },
+ .wakeup_src_reg = 0x1b,
+ .wakeup_src_status_mask = BIT(3),
+ .wakeup_src_z_mask = BIT(0),
+ .wakeup_src_y_mask = BIT(1),
+ .wakeup_src_x_mask = BIT(2),
}
},
};
@@ -967,36 +1358,37 @@ static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor,
return 0;
}
-int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u16 odr, u8 *val)
+int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u32 odr, u8 *val)
{
const struct st_lsm6dsx_odr_table_entry *odr_table;
int i;
odr_table = &sensor->hw->settings->odr_table[sensor->id];
- for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++)
+ for (i = 0; i < odr_table->odr_len; i++) {
/*
* ext devices can run at different odr respect to
* accel sensor
*/
- if (odr_table->odr_avl[i].hz >= odr)
+ if (odr_table->odr_avl[i].milli_hz >= odr)
break;
+ }
- if (i == ST_LSM6DSX_ODR_LIST_SIZE)
+ if (i == odr_table->odr_len)
return -EINVAL;
*val = odr_table->odr_avl[i].val;
-
- return 0;
+ return odr_table->odr_avl[i].milli_hz;
}
-static u16 st_lsm6dsx_check_odr_dependency(struct st_lsm6dsx_hw *hw, u16 odr,
- enum st_lsm6dsx_sensor_id id)
+static int
+st_lsm6dsx_check_odr_dependency(struct st_lsm6dsx_hw *hw, u32 odr,
+ enum st_lsm6dsx_sensor_id id)
{
struct st_lsm6dsx_sensor *ref = iio_priv(hw->iio_devs[id]);
if (odr > 0) {
if (hw->enable_mask & BIT(id))
- return max_t(u16, ref->odr, odr);
+ return max_t(u32, ref->odr, odr);
else
return odr;
} else {
@@ -1004,7 +1396,8 @@ static u16 st_lsm6dsx_check_odr_dependency(struct st_lsm6dsx_hw *hw, u16 odr,
}
}
-static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 req_odr)
+static int
+st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u32 req_odr)
{
struct st_lsm6dsx_sensor *ref_sensor = sensor;
struct st_lsm6dsx_hw *hw = sensor->hw;
@@ -1018,7 +1411,7 @@ static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 req_odr)
case ST_LSM6DSX_ID_EXT1:
case ST_LSM6DSX_ID_EXT2:
case ST_LSM6DSX_ID_ACC: {
- u16 odr;
+ u32 odr;
int i;
/*
@@ -1058,7 +1451,7 @@ int st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor,
bool enable)
{
struct st_lsm6dsx_hw *hw = sensor->hw;
- u16 odr = enable ? sensor->odr : 0;
+ u32 odr = enable ? sensor->odr : 0;
int err;
err = st_lsm6dsx_set_odr(sensor, odr);
@@ -1084,14 +1477,15 @@ static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor,
if (err < 0)
return err;
- delay = 1000000 / sensor->odr;
+ delay = 1000000000 / sensor->odr;
usleep_range(delay, 2 * delay);
err = st_lsm6dsx_read_locked(hw, addr, &data, sizeof(data));
if (err < 0)
return err;
- st_lsm6dsx_sensor_set_enable(sensor, false);
+ if (!hw->enable_event)
+ st_lsm6dsx_sensor_set_enable(sensor, false);
*val = (s16)le16_to_cpu(data);
@@ -1115,8 +1509,9 @@ static int st_lsm6dsx_read_raw(struct iio_dev *iio_dev,
iio_device_release_direct_mode(iio_dev);
break;
case IIO_CHAN_INFO_SAMP_FREQ:
- *val = sensor->odr;
- ret = IIO_VAL_INT;
+ *val = sensor->odr / 1000;
+ *val2 = (sensor->odr % 1000) * 1000;
+ ret = IIO_VAL_INT_PLUS_MICRO;
break;
case IIO_CHAN_INFO_SCALE:
*val = 0;
@@ -1149,8 +1544,11 @@ static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev,
case IIO_CHAN_INFO_SAMP_FREQ: {
u8 data;
- err = st_lsm6dsx_check_odr(sensor, val, &data);
- if (!err)
+ val = val * 1000 + val2 / 1000;
+ val = st_lsm6dsx_check_odr(sensor, val, &data);
+ if (val < 0)
+ err = val;
+ else
sensor->odr = val;
break;
}
@@ -1164,6 +1562,144 @@ static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev,
return err;
}
+static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, int state)
+{
+ const struct st_lsm6dsx_reg *reg;
+ unsigned int data;
+ int err;
+
+ if (!hw->settings->irq_config.irq1_func.addr)
+ return -ENOTSUPP;
+
+ reg = &hw->settings->event_settings.enable_reg;
+ if (reg->addr) {
+ data = ST_LSM6DSX_SHIFT_VAL(state, reg->mask);
+ err = st_lsm6dsx_update_bits_locked(hw, reg->addr,
+ reg->mask, data);
+ if (err < 0)
+ return err;
+ }
+
+ /* Enable wakeup interrupt */
+ data = ST_LSM6DSX_SHIFT_VAL(state, hw->irq_routing->mask);
+ return st_lsm6dsx_update_bits_locked(hw, hw->irq_routing->addr,
+ hw->irq_routing->mask, data);
+}
+
+static int st_lsm6dsx_read_event(struct iio_dev *iio_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 st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
+ struct st_lsm6dsx_hw *hw = sensor->hw;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ *val2 = 0;
+ *val = hw->event_threshold;
+
+ return IIO_VAL_INT;
+}
+
+static int
+st_lsm6dsx_write_event(struct iio_dev *iio_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 st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
+ struct st_lsm6dsx_hw *hw = sensor->hw;
+ const struct st_lsm6dsx_reg *reg;
+ unsigned int data;
+ int err;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ if (val < 0 || val > 31)
+ return -EINVAL;
+
+ reg = &hw->settings->event_settings.wakeup_reg;
+ data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask);
+ err = st_lsm6dsx_update_bits_locked(hw, reg->addr,
+ reg->mask, data);
+ if (err < 0)
+ return -EINVAL;
+
+ hw->event_threshold = val;
+
+ return 0;
+}
+
+static int
+st_lsm6dsx_read_event_config(struct iio_dev *iio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
+ struct st_lsm6dsx_hw *hw = sensor->hw;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ return !!(hw->enable_event & BIT(chan->channel2));
+}
+
+static int
+st_lsm6dsx_write_event_config(struct iio_dev *iio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir, int state)
+{
+ struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
+ struct st_lsm6dsx_hw *hw = sensor->hw;
+ u8 enable_event;
+ int err = 0;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ if (state) {
+ enable_event = hw->enable_event | BIT(chan->channel2);
+
+ /* do not enable events if they are already enabled */
+ if (hw->enable_event)
+ goto out;
+ } else {
+ enable_event = hw->enable_event & ~BIT(chan->channel2);
+
+ /* only turn off sensor if no events is enabled */
+ if (enable_event)
+ goto out;
+ }
+
+ /* stop here if no changes have been made */
+ if (hw->enable_event == enable_event)
+ return 0;
+
+ err = st_lsm6dsx_event_setup(hw, state);
+ if (err < 0)
+ return err;
+
+ mutex_lock(&hw->conf_lock);
+ err = st_lsm6dsx_sensor_set_enable(sensor, state);
+ mutex_unlock(&hw->conf_lock);
+ if (err < 0)
+ return err;
+
+out:
+ hw->enable_event = enable_event;
+
+ return 0;
+}
+
int st_lsm6dsx_set_watermark(struct iio_dev *iio_dev, unsigned int val)
{
struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
@@ -1193,13 +1729,14 @@ st_lsm6dsx_sysfs_sampling_frequency_avail(struct device *dev,
char *buf)
{
struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev));
- enum st_lsm6dsx_sensor_id id = sensor->id;
- struct st_lsm6dsx_hw *hw = sensor->hw;
+ const struct st_lsm6dsx_odr_table_entry *odr_table;
int i, len = 0;
- for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++)
- len += scnprintf(buf + len, PAGE_SIZE - len, "%d ",
- hw->settings->odr_table[id].odr_avl[i].hz);
+ odr_table = &sensor->hw->settings->odr_table[sensor->id];
+ for (i = 0; i < odr_table->odr_len; i++)
+ len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%03d ",
+ odr_table->odr_avl[i].milli_hz / 1000,
+ odr_table->odr_avl[i].milli_hz % 1000);
buf[len - 1] = '\n';
return len;
@@ -1243,6 +1780,10 @@ static const struct iio_info st_lsm6dsx_acc_info = {
.attrs = &st_lsm6dsx_acc_attribute_group,
.read_raw = st_lsm6dsx_read_raw,
.write_raw = st_lsm6dsx_write_raw,
+ .read_event_value = st_lsm6dsx_read_event,
+ .write_event_value = st_lsm6dsx_write_event,
+ .read_event_config = st_lsm6dsx_read_event_config,
+ .write_event_config = st_lsm6dsx_write_event_config,
.hwfifo_set_watermark = st_lsm6dsx_set_watermark,
};
@@ -1273,7 +1814,9 @@ static int st_lsm6dsx_of_get_drdy_pin(struct st_lsm6dsx_hw *hw, int *drdy_pin)
return of_property_read_u32(np, "st,drdy-int-pin", drdy_pin);
}
-static int st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw, u8 *drdy_reg)
+static int
+st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw,
+ const struct st_lsm6dsx_reg **drdy_reg)
{
int err = 0, drdy_pin;
@@ -1287,10 +1830,12 @@ static int st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw, u8 *drdy_reg)
switch (drdy_pin) {
case 1:
- *drdy_reg = hw->settings->int1_addr;
+ hw->irq_routing = &hw->settings->irq_config.irq1_func;
+ *drdy_reg = &hw->settings->irq_config.irq1;
break;
case 2:
- *drdy_reg = hw->settings->int2_addr;
+ hw->irq_routing = &hw->settings->irq_config.irq2_func;
+ *drdy_reg = &hw->settings->irq_config.irq2;
break;
default:
dev_err(hw->dev, "unsupported data ready pin\n");
@@ -1381,51 +1926,95 @@ static int st_lsm6dsx_init_hw_timer(struct st_lsm6dsx_hw *hw)
if (err < 0)
return err;
}
+
+ /* calibrate timestamp sensitivity */
+ hw->ts_gain = ST_LSM6DSX_TS_SENSITIVITY;
+ if (ts_settings->freq_fine) {
+ err = regmap_read(hw->regmap, ts_settings->freq_fine, &val);
+ if (err < 0)
+ return err;
+
+ /*
+ * linearize the AN5192 formula:
+ * 1 / (1 + x) ~= 1 - x (Taylor’s Series)
+ * ttrim[s] = 1 / (40000 * (1 + 0.0015 * val))
+ * ttrim[ns] ~= 25000 - 37.5 * val
+ * ttrim[ns] ~= 25000 - (37500 * val) / 1000
+ */
+ hw->ts_gain -= ((s8)val * 37500) / 1000;
+ }
+
return 0;
}
static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw)
{
- u8 drdy_int_reg;
+ const struct st_lsm6dsx_reg *reg;
int err;
/* device sw reset */
-