1fda8d26eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2290a6ce1SLorenzo Bianconi /*
3290a6ce1SLorenzo Bianconi  * STMicroelectronics st_lsm6dsx sensor driver
4290a6ce1SLorenzo Bianconi  *
5290a6ce1SLorenzo Bianconi  * The ST LSM6DSx IMU MEMS series consists of 3D digital accelerometer
6290a6ce1SLorenzo Bianconi  * and 3D digital gyroscope system-in-package with a digital I2C/SPI serial
7290a6ce1SLorenzo Bianconi  * interface standard output.
8290a6ce1SLorenzo Bianconi  * LSM6DSx IMU MEMS series has a dynamic user-selectable full-scale
9290a6ce1SLorenzo Bianconi  * acceleration range of +-2/+-4/+-8/+-16 g and an angular rate range of
10290a6ce1SLorenzo Bianconi  * +-125/+-245/+-500/+-1000/+-2000 dps
11290a6ce1SLorenzo Bianconi  * LSM6DSx series has an integrated First-In-First-Out (FIFO) buffer
12290a6ce1SLorenzo Bianconi  * allowing dynamic batching of sensor data.
1352f4b1f1SMartin Kepplinger  * LSM9DSx series is similar but includes an additional magnetometer, handled
1452f4b1f1SMartin Kepplinger  * by a different driver.
15290a6ce1SLorenzo Bianconi  *
16290a6ce1SLorenzo Bianconi  * Supported sensors:
17290a6ce1SLorenzo Bianconi  * - LSM6DS3:
18f7d5c18aSSean Nyekjaer  *   - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416
19290a6ce1SLorenzo Bianconi  *   - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
20290a6ce1SLorenzo Bianconi  *   - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
21290a6ce1SLorenzo Bianconi  *   - FIFO size: 8KB
22290a6ce1SLorenzo Bianconi  *
23dbcd2088SLorenzo Bianconi  * - LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC/LSM6DS3TR-C:
24f7d5c18aSSean Nyekjaer  *   - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416
25290a6ce1SLorenzo Bianconi  *   - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
26290a6ce1SLorenzo Bianconi  *   - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
27290a6ce1SLorenzo Bianconi  *   - FIFO size: 4KB
28290a6ce1SLorenzo Bianconi  *
29186b9e38SLorenzo Bianconi  * - LSM6DSO/LSM6DSOX/ASM330LHH/ASM330LHHX/LSM6DSR/ISM330DHCX/LSM6DST/LSM6DSOP/
30186b9e38SLorenzo Bianconi  *   LSM6DSTX:
31f7d5c18aSSean Nyekjaer  *   - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416,
328f9a5249SLorenzo Bianconi  *     833
33801a6e0aSLorenzo Bianconi  *   - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
34801a6e0aSLorenzo Bianconi  *   - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
35801a6e0aSLorenzo Bianconi  *   - FIFO size: 3KB
36801a6e0aSLorenzo Bianconi  *
37fa060a3dSLorenzo Bianconi  * - LSM9DS1/LSM6DS0:
3852f4b1f1SMartin Kepplinger  *   - Accelerometer supported ODR [Hz]: 10, 50, 119, 238, 476, 952
3952f4b1f1SMartin Kepplinger  *   - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
4052f4b1f1SMartin Kepplinger  *   - Gyroscope supported ODR [Hz]: 15, 60, 119, 238, 476, 952
4152f4b1f1SMartin Kepplinger  *   - Gyroscope supported full-scale [dps]: +-245/+-500/+-2000
4252f4b1f1SMartin Kepplinger  *   - FIFO size: 32
4352f4b1f1SMartin Kepplinger  *
44290a6ce1SLorenzo Bianconi  * Copyright 2016 STMicroelectronics Inc.
45290a6ce1SLorenzo Bianconi  *
46290a6ce1SLorenzo Bianconi  * Lorenzo Bianconi <lorenzo.bianconi@st.com>
47290a6ce1SLorenzo Bianconi  * Denis Ciocca <denis.ciocca@st.com>
48290a6ce1SLorenzo Bianconi  */
49290a6ce1SLorenzo Bianconi 
50290a6ce1SLorenzo Bianconi #include <linux/kernel.h>
51290a6ce1SLorenzo Bianconi #include <linux/module.h>
52290a6ce1SLorenzo Bianconi #include <linux/delay.h>
531aabad1fSSean Nyekjaer #include <linux/iio/events.h>
54290a6ce1SLorenzo Bianconi #include <linux/iio/iio.h>
55290a6ce1SLorenzo Bianconi #include <linux/iio/sysfs.h>
566ee6a368SSean Nyekjaer #include <linux/interrupt.h>
576ee6a368SSean Nyekjaer #include <linux/irq.h>
589e5b4cd2SPaul Cercueil #include <linux/minmax.h>
59d3f77058SLorenzo Bianconi #include <linux/pm.h>
6003d4c566SAndy Shevchenko #include <linux/property.h>
6151a8b707SLorenzo Bianconi #include <linux/regmap.h>
6251a8b707SLorenzo Bianconi #include <linux/bitfield.h>
63290a6ce1SLorenzo Bianconi 
64dba32904SLorenzo Bianconi #include <linux/platform_data/st_sensors_pdata.h>
65dba32904SLorenzo Bianconi 
66290a6ce1SLorenzo Bianconi #include "st_lsm6dsx.h"
67290a6ce1SLorenzo Bianconi 
68290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_WHOAMI_ADDR		0x0f
69290a6ce1SLorenzo Bianconi 
70cb3b6b8eSMario Tesi #define ST_LSM6DSX_TS_SENSITIVITY		25000UL /* 25us */
71cb3b6b8eSMario Tesi 
72f48bc49bSLorenzo Bianconi static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = {
73b5969abfSSean Nyekjaer 	ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x28, IIO_MOD_X, 0),
74b5969abfSSean Nyekjaer 	ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1),
75b5969abfSSean Nyekjaer 	ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x2c, IIO_MOD_Z, 2),
76f48bc49bSLorenzo Bianconi 	IIO_CHAN_SOFT_TIMESTAMP(3),
77f48bc49bSLorenzo Bianconi };
78f48bc49bSLorenzo Bianconi 
79f48bc49bSLorenzo Bianconi static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = {
80f48bc49bSLorenzo Bianconi 	ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x22, IIO_MOD_X, 0),
81f48bc49bSLorenzo Bianconi 	ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x24, IIO_MOD_Y, 1),
82f48bc49bSLorenzo Bianconi 	ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x26, IIO_MOD_Z, 2),
83f48bc49bSLorenzo Bianconi 	IIO_CHAN_SOFT_TIMESTAMP(3),
84f48bc49bSLorenzo Bianconi };
85f48bc49bSLorenzo Bianconi 
8652f4b1f1SMartin Kepplinger static const struct iio_chan_spec st_lsm6ds0_gyro_channels[] = {
8752f4b1f1SMartin Kepplinger 	ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x18, IIO_MOD_X, 0),
8852f4b1f1SMartin Kepplinger 	ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x1a, IIO_MOD_Y, 1),
8952f4b1f1SMartin Kepplinger 	ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x1c, IIO_MOD_Z, 2),
9052f4b1f1SMartin Kepplinger 	IIO_CHAN_SOFT_TIMESTAMP(3),
9152f4b1f1SMartin Kepplinger };
9252f4b1f1SMartin Kepplinger 
93290a6ce1SLorenzo Bianconi static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
94290a6ce1SLorenzo Bianconi 	{
9566b662a1SLorenzo Bianconi 		.reset = {
9666b662a1SLorenzo Bianconi 			.addr = 0x22,
9766b662a1SLorenzo Bianconi 			.mask = BIT(0),
9866b662a1SLorenzo Bianconi 		},
9966b662a1SLorenzo Bianconi 		.boot = {
10066b662a1SLorenzo Bianconi 			.addr = 0x22,
10166b662a1SLorenzo Bianconi 			.mask = BIT(7),
10266b662a1SLorenzo Bianconi 		},
10366b662a1SLorenzo Bianconi 		.bdu = {
10466b662a1SLorenzo Bianconi 			.addr = 0x22,
10566b662a1SLorenzo Bianconi 			.mask = BIT(6),
10666b662a1SLorenzo Bianconi 		},
10752f4b1f1SMartin Kepplinger 		.id = {
10852f4b1f1SMartin Kepplinger 			{
10952f4b1f1SMartin Kepplinger 				.hw_id = ST_LSM9DS1_ID,
11052f4b1f1SMartin Kepplinger 				.name = ST_LSM9DS1_DEV_NAME,
11198c3544aSLorenzo Bianconi 				.wai = 0x68,
112fa060a3dSLorenzo Bianconi 			}, {
113fa060a3dSLorenzo Bianconi 				.hw_id = ST_LSM6DS0_ID,
114fa060a3dSLorenzo Bianconi 				.name = ST_LSM6DS0_DEV_NAME,
11598c3544aSLorenzo Bianconi 				.wai = 0x68,
11652f4b1f1SMartin Kepplinger 			},
11752f4b1f1SMartin Kepplinger 		},
11852f4b1f1SMartin Kepplinger 		.channels = {
11952f4b1f1SMartin Kepplinger 			[ST_LSM6DSX_ID_ACC] = {
12052f4b1f1SMartin Kepplinger 				.chan = st_lsm6dsx_acc_channels,
12152f4b1f1SMartin Kepplinger 				.len = ARRAY_SIZE(st_lsm6dsx_acc_channels),
12252f4b1f1SMartin Kepplinger 			},
12352f4b1f1SMartin Kepplinger 			[ST_LSM6DSX_ID_GYRO] = {
12452f4b1f1SMartin Kepplinger 				.chan = st_lsm6ds0_gyro_channels,
12552f4b1f1SMartin Kepplinger 				.len = ARRAY_SIZE(st_lsm6ds0_gyro_channels),
12652f4b1f1SMartin Kepplinger 			},
12752f4b1f1SMartin Kepplinger 		},
12852f4b1f1SMartin Kepplinger 		.odr_table = {
12952f4b1f1SMartin Kepplinger 			[ST_LSM6DSX_ID_ACC] = {
13052f4b1f1SMartin Kepplinger 				.reg = {
13152f4b1f1SMartin Kepplinger 					.addr = 0x20,
13252f4b1f1SMartin Kepplinger 					.mask = GENMASK(7, 5),
13352f4b1f1SMartin Kepplinger 				},
134f8710f03SLorenzo Bianconi 				.odr_avl[0] = {  10000, 0x01 },
135f8710f03SLorenzo Bianconi 				.odr_avl[1] = {  50000, 0x02 },
136f8710f03SLorenzo Bianconi 				.odr_avl[2] = { 119000, 0x03 },
137f8710f03SLorenzo Bianconi 				.odr_avl[3] = { 238000, 0x04 },
138f8710f03SLorenzo Bianconi 				.odr_avl[4] = { 476000, 0x05 },
139f8710f03SLorenzo Bianconi 				.odr_avl[5] = { 952000, 0x06 },
14059af4e20SLorenzo Bianconi 				.odr_len = 6,
14152f4b1f1SMartin Kepplinger 			},
14252f4b1f1SMartin Kepplinger 			[ST_LSM6DSX_ID_GYRO] = {
14352f4b1f1SMartin Kepplinger 				.reg = {
14452f4b1f1SMartin Kepplinger 					.addr = 0x10,
14552f4b1f1SMartin Kepplinger 					.mask = GENMASK(7, 5),
14652f4b1f1SMartin Kepplinger 				},
147f8710f03SLorenzo Bianconi 				.odr_avl[0] = {  14900, 0x01 },
148f8710f03SLorenzo Bianconi 				.odr_avl[1] = {  59500, 0x02 },
149f8710f03SLorenzo Bianconi 				.odr_avl[2] = { 119000, 0x03 },
150f8710f03SLorenzo Bianconi 				.odr_avl[3] = { 238000, 0x04 },
151f8710f03SLorenzo Bianconi 				.odr_avl[4] = { 476000, 0x05 },
152f8710f03SLorenzo Bianconi 				.odr_avl[5] = { 952000, 0x06 },
15359af4e20SLorenzo Bianconi 				.odr_len = 6,
15452f4b1f1SMartin Kepplinger 			},
15552f4b1f1SMartin Kepplinger 		},
15652f4b1f1SMartin Kepplinger 		.fs_table = {
15752f4b1f1SMartin Kepplinger 			[ST_LSM6DSX_ID_ACC] = {
15852f4b1f1SMartin Kepplinger 				.reg = {
15952f4b1f1SMartin Kepplinger 					.addr = 0x20,
16052f4b1f1SMartin Kepplinger 					.mask = GENMASK(4, 3),
16152f4b1f1SMartin Kepplinger 				},
16244a76de8SMario Tesi 				.fs_avl[0] = {  IIO_G_TO_M_S_2(61000), 0x0 },
16344a76de8SMario Tesi 				.fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 },
16444a76de8SMario Tesi 				.fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 },
16544a76de8SMario Tesi 				.fs_avl[3] = { IIO_G_TO_M_S_2(732000), 0x1 },
16685ae3aeeSLorenzo Bianconi 				.fs_len = 4,
16752f4b1f1SMartin Kepplinger 			},
16852f4b1f1SMartin Kepplinger 			[ST_LSM6DSX_ID_GYRO] = {
16952f4b1f1SMartin Kepplinger 				.reg = {
17052f4b1f1SMartin Kepplinger 					.addr = 0x10,
17152f4b1f1SMartin Kepplinger 					.mask = GENMASK(4, 3),
17252f4b1f1SMartin Kepplinger 				},
1731b375101SLorenzo Bianconi 
17444a76de8SMario Tesi 				.fs_avl[0] = {  IIO_DEGREE_TO_RAD(8750000), 0x0 },
17544a76de8SMario Tesi 				.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 },
17644a76de8SMario Tesi 				.fs_avl[2] = { IIO_DEGREE_TO_RAD(70000000), 0x3 },
17785ae3aeeSLorenzo Bianconi 				.fs_len = 3,
17852f4b1f1SMartin Kepplinger 			},
17952f4b1f1SMartin Kepplinger 		},
1807e906103SLorenzo Bianconi 		.irq_config = {
1817e906103SLorenzo Bianconi 			.irq1 = {
1827e906103SLorenzo Bianconi 				.addr = 0x0c,
1837e906103SLorenzo Bianconi 				.mask = BIT(3),
1847e906103SLorenzo Bianconi 			},
1857e906103SLorenzo Bianconi 			.irq2 = {
1867e906103SLorenzo Bianconi 				.addr = 0x0d,
1877e906103SLorenzo Bianconi 				.mask = BIT(3),
1887e906103SLorenzo Bianconi 			},
18931fe8d4eSLorenzo Bianconi 			.hla = {
19031fe8d4eSLorenzo Bianconi 				.addr = 0x22,
19131fe8d4eSLorenzo Bianconi 				.mask = BIT(5),
19231fe8d4eSLorenzo Bianconi 			},
19331fe8d4eSLorenzo Bianconi 			.od = {
19431fe8d4eSLorenzo Bianconi 				.addr = 0x22,
19531fe8d4eSLorenzo Bianconi 				.mask = BIT(4),
19631fe8d4eSLorenzo Bianconi 			},
1977e906103SLorenzo Bianconi 		},
1981b7da2faSLorenzo Bianconi 		.fifo_ops = {
1991b7da2faSLorenzo Bianconi 			.max_size = 32,
2001b7da2faSLorenzo Bianconi 		},
20152f4b1f1SMartin Kepplinger 	},
20252f4b1f1SMartin Kepplinger 	{
20366b662a1SLorenzo Bianconi 		.reset = {
20466b662a1SLorenzo Bianconi 			.addr = 0x12,
20566b662a1SLorenzo Bianconi 			.mask = BIT(0),
20666b662a1SLorenzo Bianconi 		},
20766b662a1SLorenzo Bianconi 		.boot = {
20866b662a1SLorenzo Bianconi 			.addr = 0x12,
20966b662a1SLorenzo Bianconi 			.mask = BIT(7),
21066b662a1SLorenzo Bianconi 		},
21166b662a1SLorenzo Bianconi 		.bdu = {
21266b662a1SLorenzo Bianconi 			.addr = 0x12,
21366b662a1SLorenzo Bianconi 			.mask = BIT(6),
21466b662a1SLorenzo Bianconi 		},
215d068e4a0SLorenzo Bianconi 		.id = {
21681956a93SLorenzo Bianconi 			{
21781956a93SLorenzo Bianconi 				.hw_id = ST_LSM6DS3_ID,
21881956a93SLorenzo Bianconi 				.name = ST_LSM6DS3_DEV_NAME,
21998c3544aSLorenzo Bianconi 				.wai = 0x69,
22081956a93SLorenzo Bianconi 			},
221d068e4a0SLorenzo Bianconi 		},
222f48bc49bSLorenzo Bianconi 		.channels = {
223f48bc49bSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
224f48bc49bSLorenzo Bianconi 				.chan = st_lsm6dsx_acc_channels,
225f48bc49bSLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_acc_channels),
226f48bc49bSLorenzo Bianconi 			},
227f48bc49bSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
228f48bc49bSLorenzo Bianconi 				.chan = st_lsm6dsx_gyro_channels,
229f48bc49bSLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_gyro_channels),
230f48bc49bSLorenzo Bianconi 			},
231f48bc49bSLorenzo Bianconi 		},
23240dd7343SLorenzo Bianconi 		.odr_table = {
23340dd7343SLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
23440dd7343SLorenzo Bianconi 				.reg = {
23540dd7343SLorenzo Bianconi 					.addr = 0x10,
23640dd7343SLorenzo Bianconi 					.mask = GENMASK(7, 4),
23740dd7343SLorenzo Bianconi 				},
238f8710f03SLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
239f8710f03SLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
240f8710f03SLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
241f8710f03SLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
242f8710f03SLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
243f8710f03SLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
24459af4e20SLorenzo Bianconi 				.odr_len = 6,
24540dd7343SLorenzo Bianconi 			},
24640dd7343SLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
24740dd7343SLorenzo Bianconi 				.reg = {
24840dd7343SLorenzo Bianconi 					.addr = 0x11,
24940dd7343SLorenzo Bianconi 					.mask = GENMASK(7, 4),
25040dd7343SLorenzo Bianconi 				},
251f8710f03SLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
252f8710f03SLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
253f8710f03SLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
254f8710f03SLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
255f8710f03SLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
256f8710f03SLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
25759af4e20SLorenzo Bianconi 				.odr_len = 6,
25840dd7343SLorenzo Bianconi 			},
25940dd7343SLorenzo Bianconi 		},
260640aca3fSLorenzo Bianconi 		.fs_table = {
261640aca3fSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
262640aca3fSLorenzo Bianconi 				.reg = {
263640aca3fSLorenzo Bianconi 					.addr = 0x10,
264640aca3fSLorenzo Bianconi 					.mask = GENMASK(3, 2),
265640aca3fSLorenzo Bianconi 				},
26644a76de8SMario Tesi 				.fs_avl[0] = {  IIO_G_TO_M_S_2(61000), 0x0 },
26744a76de8SMario Tesi 				.fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 },
26844a76de8SMario Tesi 				.fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 },
26944a76de8SMario Tesi 				.fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 },
27085ae3aeeSLorenzo Bianconi 				.fs_len = 4,
271640aca3fSLorenzo Bianconi 			},
272640aca3fSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
273640aca3fSLorenzo Bianconi 				.reg = {
274640aca3fSLorenzo Bianconi 					.addr = 0x11,
275640aca3fSLorenzo Bianconi 					.mask = GENMASK(3, 2),
276640aca3fSLorenzo Bianconi 				},
27744a76de8SMario Tesi 				.fs_avl[0] = {  IIO_DEGREE_TO_RAD(8750000), 0x0 },
27844a76de8SMario Tesi 				.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 },
27944a76de8SMario Tesi 				.fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 },
28044a76de8SMario Tesi 				.fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 },
28185ae3aeeSLorenzo Bianconi 				.fs_len = 4,
282640aca3fSLorenzo Bianconi 			},
283640aca3fSLorenzo Bianconi 		},
2847e906103SLorenzo Bianconi 		.irq_config = {
2857e906103SLorenzo Bianconi 			.irq1 = {
2867e906103SLorenzo Bianconi 				.addr = 0x0d,
2877e906103SLorenzo Bianconi 				.mask = BIT(3),
2887e906103SLorenzo Bianconi 			},
2897e906103SLorenzo Bianconi 			.irq2 = {
2907e906103SLorenzo Bianconi 				.addr = 0x0e,
2917e906103SLorenzo Bianconi 				.mask = BIT(3),
2927e906103SLorenzo Bianconi 			},
2937e906103SLorenzo Bianconi 			.lir = {
2947e906103SLorenzo Bianconi 				.addr = 0x58,
2957e906103SLorenzo Bianconi 				.mask = BIT(0),
2967e906103SLorenzo Bianconi 			},
2977e906103SLorenzo Bianconi 			.irq1_func = {
2987e906103SLorenzo Bianconi 				.addr = 0x5e,
2997e906103SLorenzo Bianconi 				.mask = BIT(5),
3007e906103SLorenzo Bianconi 			},
3017e906103SLorenzo Bianconi 			.irq2_func = {
3027e906103SLorenzo Bianconi 				.addr = 0x5f,
3037e906103SLorenzo Bianconi 				.mask = BIT(5),
3047e906103SLorenzo Bianconi 			},
30531fe8d4eSLorenzo Bianconi 			.hla = {
30631fe8d4eSLorenzo Bianconi 				.addr = 0x12,
30731fe8d4eSLorenzo Bianconi 				.mask = BIT(5),
30831fe8d4eSLorenzo Bianconi 			},
30931fe8d4eSLorenzo Bianconi 			.od = {
31031fe8d4eSLorenzo Bianconi 				.addr = 0x12,
31131fe8d4eSLorenzo Bianconi 				.mask = BIT(4),
31231fe8d4eSLorenzo Bianconi 			},
3137e906103SLorenzo Bianconi 		},
3147ca3ac9eSLorenzo Bianconi 		.decimator = {
3157ca3ac9eSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
3167ca3ac9eSLorenzo Bianconi 				.addr = 0x08,
3177ca3ac9eSLorenzo Bianconi 				.mask = GENMASK(2, 0),
3187ca3ac9eSLorenzo Bianconi 			},
3197ca3ac9eSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
3207ca3ac9eSLorenzo Bianconi 				.addr = 0x08,
3217ca3ac9eSLorenzo Bianconi 				.mask = GENMASK(5, 3),
3227ca3ac9eSLorenzo Bianconi 			},
3237ca3ac9eSLorenzo Bianconi 		},
32492617c15SLorenzo Bianconi 		.fifo_ops = {
3253b72950dSLorenzo Bianconi 			.update_fifo = st_lsm6dsx_update_fifo,
32650ff457dSLorenzo Bianconi 			.read_fifo = st_lsm6dsx_read_fifo,
32792617c15SLorenzo Bianconi 			.fifo_th = {
32892617c15SLorenzo Bianconi 				.addr = 0x06,
32992617c15SLorenzo Bianconi 				.mask = GENMASK(11, 0),
33092617c15SLorenzo Bianconi 			},
33192617c15SLorenzo Bianconi 			.fifo_diff = {
33292617c15SLorenzo Bianconi 				.addr = 0x3a,
33392617c15SLorenzo Bianconi 				.mask = GENMASK(11, 0),
33492617c15SLorenzo Bianconi 			},
3351b7da2faSLorenzo Bianconi 			.max_size = 1365,
33692617c15SLorenzo Bianconi 			.th_wl = 3, /* 1LSB = 2B */
33792617c15SLorenzo Bianconi 		},
33821345107SLorenzo Bianconi 		.ts_settings = {
33921345107SLorenzo Bianconi 			.timer_en = {
34021345107SLorenzo Bianconi 				.addr = 0x58,
34121345107SLorenzo Bianconi 				.mask = BIT(7),
34221345107SLorenzo Bianconi 			},
34321345107SLorenzo Bianconi 			.hr_timer = {
34421345107SLorenzo Bianconi 				.addr = 0x5c,
34521345107SLorenzo Bianconi 				.mask = BIT(4),
34621345107SLorenzo Bianconi 			},
34721345107SLorenzo Bianconi 			.fifo_en = {
34821345107SLorenzo Bianconi 				.addr = 0x07,
34921345107SLorenzo Bianconi 				.mask = BIT(7),
35021345107SLorenzo Bianconi 			},
35121345107SLorenzo Bianconi 			.decimator = {
35221345107SLorenzo Bianconi 				.addr = 0x09,
35321345107SLorenzo Bianconi 				.mask = GENMASK(5, 3),
35421345107SLorenzo Bianconi 			},
35521345107SLorenzo Bianconi 		},
356b5969abfSSean Nyekjaer 		.event_settings = {
357b5969abfSSean Nyekjaer 			.wakeup_reg = {
358b5969abfSSean Nyekjaer 				.addr = 0x5B,
359b5969abfSSean Nyekjaer 				.mask = GENMASK(5, 0),
360b5969abfSSean Nyekjaer 			},
3611aabad1fSSean Nyekjaer 			.wakeup_src_reg = 0x1b,
3621aabad1fSSean Nyekjaer 			.wakeup_src_status_mask = BIT(3),
3631aabad1fSSean Nyekjaer 			.wakeup_src_z_mask = BIT(0),
3641aabad1fSSean Nyekjaer 			.wakeup_src_y_mask = BIT(1),
3651aabad1fSSean Nyekjaer 			.wakeup_src_x_mask = BIT(2),
366b5969abfSSean Nyekjaer 		},
367290a6ce1SLorenzo Bianconi 	},
368290a6ce1SLorenzo Bianconi 	{
36966b662a1SLorenzo Bianconi 		.reset = {
37066b662a1SLorenzo Bianconi 			.addr = 0x12,
37166b662a1SLorenzo Bianconi 			.mask = BIT(0),
37266b662a1SLorenzo Bianconi 		},
37366b662a1SLorenzo Bianconi 		.boot = {
37466b662a1SLorenzo Bianconi 			.addr = 0x12,
37566b662a1SLorenzo Bianconi 			.mask = BIT(7),
37666b662a1SLorenzo Bianconi 		},
37766b662a1SLorenzo Bianconi 		.bdu = {
37866b662a1SLorenzo Bianconi 			.addr = 0x12,
37966b662a1SLorenzo Bianconi 			.mask = BIT(6),
38066b662a1SLorenzo Bianconi 		},
381df47710aSLorenzo Bianconi 		.id = {
38281956a93SLorenzo Bianconi 			{
38381956a93SLorenzo Bianconi 				.hw_id = ST_LSM6DS3H_ID,
38481956a93SLorenzo Bianconi 				.name = ST_LSM6DS3H_DEV_NAME,
38598c3544aSLorenzo Bianconi 				.wai = 0x69,
38681956a93SLorenzo Bianconi 			},
387df47710aSLorenzo Bianconi 		},
388f48bc49bSLorenzo Bianconi 		.channels = {
389f48bc49bSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
390f48bc49bSLorenzo Bianconi 				.chan = st_lsm6dsx_acc_channels,
391f48bc49bSLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_acc_channels),
392f48bc49bSLorenzo Bianconi 			},
393f48bc49bSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
394f48bc49bSLorenzo Bianconi 				.chan = st_lsm6dsx_gyro_channels,
395f48bc49bSLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_gyro_channels),
396f48bc49bSLorenzo Bianconi 			},
397f48bc49bSLorenzo Bianconi 		},
39840dd7343SLorenzo Bianconi 		.odr_table = {
39940dd7343SLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
40040dd7343SLorenzo Bianconi 				.reg = {
40140dd7343SLorenzo Bianconi 					.addr = 0x10,
40240dd7343SLorenzo Bianconi 					.mask = GENMASK(7, 4),
40340dd7343SLorenzo Bianconi 				},
404f8710f03SLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
405f8710f03SLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
406f8710f03SLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
407f8710f03SLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
408f8710f03SLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
409f8710f03SLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
41059af4e20SLorenzo Bianconi 				.odr_len = 6,
41140dd7343SLorenzo Bianconi 			},
41240dd7343SLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
41340dd7343SLorenzo Bianconi 				.reg = {
41440dd7343SLorenzo Bianconi 					.addr = 0x11,
41540dd7343SLorenzo Bianconi 					.mask = GENMASK(7, 4),
41640dd7343SLorenzo Bianconi 				},
417f8710f03SLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
418f8710f03SLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
419f8710f03SLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
420f8710f03SLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
421f8710f03SLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
422f8710f03SLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
42359af4e20SLorenzo Bianconi 				.odr_len = 6,
42440dd7343SLorenzo Bianconi 			},
42540dd7343SLorenzo Bianconi 		},
426640aca3fSLorenzo Bianconi 		.fs_table = {
427640aca3fSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
428640aca3fSLorenzo Bianconi 				.reg = {
429640aca3fSLorenzo Bianconi 					.addr = 0x10,
430640aca3fSLorenzo Bianconi 					.mask = GENMASK(3, 2),
431640aca3fSLorenzo Bianconi 				},
43244a76de8SMario Tesi 				.fs_avl[0] = {  IIO_G_TO_M_S_2(61000), 0x0 },
43344a76de8SMario Tesi 				.fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 },
43444a76de8SMario Tesi 				.fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 },
43544a76de8SMario Tesi 				.fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 },
43685ae3aeeSLorenzo Bianconi 				.fs_len = 4,
437640aca3fSLorenzo Bianconi 			},
438640aca3fSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
439640aca3fSLorenzo Bianconi 				.reg = {
440640aca3fSLorenzo Bianconi 					.addr = 0x11,
441640aca3fSLorenzo Bianconi 					.mask = GENMASK(3, 2),
442640aca3fSLorenzo Bianconi 				},
44344a76de8SMario Tesi 				.fs_avl[0] = {  IIO_DEGREE_TO_RAD(8750000), 0x0 },
44444a76de8SMario Tesi 				.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 },
44544a76de8SMario Tesi 				.fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 },
44644a76de8SMario Tesi 				.fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 },
44785ae3aeeSLorenzo Bianconi 				.fs_len = 4,
448640aca3fSLorenzo Bianconi 			},
449640aca3fSLorenzo Bianconi 		},
4507e906103SLorenzo Bianconi 		.irq_config = {
4517e906103SLorenzo Bianconi 			.irq1 = {
4527e906103SLorenzo Bianconi 				.addr = 0x0d,
4537e906103SLorenzo Bianconi 				.mask = BIT(3),
4547e906103SLorenzo Bianconi 			},
4557e906103SLorenzo Bianconi 			.irq2 = {
4567e906103SLorenzo Bianconi 				.addr = 0x0e,
4577e906103SLorenzo Bianconi 				.mask = BIT(3),
4587e906103SLorenzo Bianconi 			},
4597e906103SLorenzo Bianconi 			.lir = {
4607e906103SLorenzo Bianconi 				.addr = 0x58,
4617e906103SLorenzo Bianconi 				.mask = BIT(0),
4627e906103SLorenzo Bianconi 			},
4637e906103SLorenzo Bianconi 			.irq1_func = {
4647e906103SLorenzo Bianconi 				.addr = 0x5e,
4657e906103SLorenzo Bianconi 				.mask = BIT(5),
4667e906103SLorenzo Bianconi 			},
4677e906103SLorenzo Bianconi 			.irq2_func = {
4687e906103SLorenzo Bianconi 				.addr = 0x5f,
4697e906103SLorenzo Bianconi 				.mask = BIT(5),
4707e906103SLorenzo Bianconi 			},
47131fe8d4eSLorenzo Bianconi 			.hla = {
47231fe8d4eSLorenzo Bianconi 				.addr = 0x12,
47331fe8d4eSLorenzo Bianconi 				.mask = BIT(5),
47431fe8d4eSLorenzo Bianconi 			},
47531fe8d4eSLorenzo Bianconi 			.od = {
47631fe8d4eSLorenzo Bianconi 				.addr = 0x12,
47731fe8d4eSLorenzo Bianconi 				.mask = BIT(4),
47831fe8d4eSLorenzo Bianconi 			},
4797e906103SLorenzo Bianconi 		},
4807ca3ac9eSLorenzo Bianconi 		.decimator = {
4817ca3ac9eSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
4827ca3ac9eSLorenzo Bianconi 				.addr = 0x08,
4837ca3ac9eSLorenzo Bianconi 				.mask = GENMASK(2, 0),
4847ca3ac9eSLorenzo Bianconi 			},
4857ca3ac9eSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
4867ca3ac9eSLorenzo Bianconi 				.addr = 0x08,
4877ca3ac9eSLorenzo Bianconi 				.mask = GENMASK(5, 3),
4887ca3ac9eSLorenzo Bianconi 			},
4897ca3ac9eSLorenzo Bianconi 		},
49092617c15SLorenzo Bianconi 		.fifo_ops = {
4913b72950dSLorenzo Bianconi 			.update_fifo = st_lsm6dsx_update_fifo,
49250ff457dSLorenzo Bianconi 			.read_fifo = st_lsm6dsx_read_fifo,
49392617c15SLorenzo Bianconi 			.fifo_th = {
49492617c15SLorenzo Bianconi 				.addr = 0x06,
49592617c15SLorenzo Bianconi 				.mask = GENMASK(11, 0),
49692617c15SLorenzo Bianconi 			},
49792617c15SLorenzo Bianconi 			.fifo_diff = {
49892617c15SLorenzo Bianconi 				.addr = 0x3a,
49992617c15SLorenzo Bianconi 				.mask = GENMASK(11, 0),
50092617c15SLorenzo Bianconi 			},
5011b7da2faSLorenzo Bianconi 			.max_size = 682,
50292617c15SLorenzo Bianconi 			.th_wl = 3, /* 1LSB = 2B */
50392617c15SLorenzo Bianconi 		},
50421345107SLorenzo Bianconi 		.ts_settings = {
50521345107SLorenzo Bianconi 			.timer_en = {
50621345107SLorenzo Bianconi 				.addr = 0x58,
50721345107SLorenzo Bianconi 				.mask = BIT(7),
50821345107SLorenzo Bianconi 			},
50921345107SLorenzo Bianconi 			.hr_timer = {
51021345107SLorenzo Bianconi 				.addr = 0x5c,
51121345107SLorenzo Bianconi 				.mask = BIT(4),
51221345107SLorenzo Bianconi 			},
51321345107SLorenzo Bianconi 			.fifo_en = {
51421345107SLorenzo Bianconi 				.addr = 0x07,
51521345107SLorenzo Bianconi 				.mask = BIT(7),
51621345107SLorenzo Bianconi 			},
51721345107SLorenzo Bianconi 			.decimator = {
51821345107SLorenzo Bianconi 				.addr = 0x09,
51921345107SLorenzo Bianconi 				.mask = GENMASK(5, 3),
52021345107SLorenzo Bianconi 			},
52121345107SLorenzo Bianconi 		},
522b5969abfSSean Nyekjaer 		.event_settings = {
523b5969abfSSean Nyekjaer 			.wakeup_reg = {
524b5969abfSSean Nyekjaer 				.addr = 0x5B,
525b5969abfSSean Nyekjaer 				.mask = GENMASK(5, 0),
526b5969abfSSean Nyekjaer 			},
5271aabad1fSSean Nyekjaer 			.wakeup_src_reg = 0x1b,
5281aabad1fSSean Nyekjaer 			.wakeup_src_status_mask = BIT(3),
5291aabad1fSSean Nyekjaer 			.wakeup_src_z_mask = BIT(0),
5301aabad1fSSean Nyekjaer 			.wakeup_src_y_mask = BIT(1),
5311aabad1fSSean Nyekjaer 			.wakeup_src_x_mask = BIT(2),
532b5969abfSSean Nyekjaer 		},
533df47710aSLorenzo Bianconi 	},
534df47710aSLorenzo Bianconi 	{
53566b662a1SLorenzo Bianconi 		.reset = {
53666b662a1SLorenzo Bianconi 			.addr = 0x12,
53766b662a1SLorenzo Bianconi 			.mask = BIT(0),
53866b662a1SLorenzo Bianconi 		},
53966b662a1SLorenzo Bianconi 		.boot = {
54066b662a1SLorenzo Bianconi 			.addr = 0x12,
54166b662a1SLorenzo Bianconi 			.mask = BIT(7),
54266b662a1SLorenzo Bianconi 		},
54366b662a1SLorenzo Bianconi 		.bdu = {
54466b662a1SLorenzo Bianconi 			.addr = 0x12,
54566b662a1SLorenzo Bianconi 			.mask = BIT(6),
54666b662a1SLorenzo Bianconi 		},
547d068e4a0SLorenzo Bianconi 		.id = {
54881956a93SLorenzo Bianconi 			{
54981956a93SLorenzo Bianconi 				.hw_id = ST_LSM6DSL_ID,
55081956a93SLorenzo Bianconi 				.name = ST_LSM6DSL_DEV_NAME,
55198c3544aSLorenzo Bianconi 				.wai = 0x6a,
55281956a93SLorenzo Bianconi 			}, {
55381956a93SLorenzo Bianconi 				.hw_id = ST_LSM6DSM_ID,
55481956a93SLorenzo Bianconi 				.name = ST_LSM6DSM_DEV_NAME,
55598c3544aSLorenzo Bianconi 				.wai = 0x6a,
55681956a93SLorenzo Bianconi 			}, {
55781956a93SLorenzo Bianconi 				.hw_id = ST_ISM330DLC_ID,
55881956a93SLorenzo Bianconi 				.name = ST_ISM330DLC_DEV_NAME,
55998c3544aSLorenzo Bianconi 				.wai = 0x6a,
560dbcd2088SLorenzo Bianconi 			}, {
561dbcd2088SLorenzo Bianconi 				.hw_id = ST_LSM6DS3TRC_ID,
562dbcd2088SLorenzo Bianconi 				.name = ST_LSM6DS3TRC_DEV_NAME,
56398c3544aSLorenzo Bianconi 				.wai = 0x6a,
56481956a93SLorenzo Bianconi 			},
565d068e4a0SLorenzo Bianconi 		},
566f48bc49bSLorenzo Bianconi 		.channels = {
567f48bc49bSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
568f48bc49bSLorenzo Bianconi 				.chan = st_lsm6dsx_acc_channels,
569f48bc49bSLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_acc_channels),
570f48bc49bSLorenzo Bianconi 			},
571f48bc49bSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
572f48bc49bSLorenzo Bianconi 				.chan = st_lsm6dsx_gyro_channels,
573f48bc49bSLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_gyro_channels),
574f48bc49bSLorenzo Bianconi 			},
575f48bc49bSLorenzo Bianconi 		},
57640dd7343SLorenzo Bianconi 		.odr_table = {
57740dd7343SLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
57840dd7343SLorenzo Bianconi 				.reg = {
57940dd7343SLorenzo Bianconi 					.addr = 0x10,
58040dd7343SLorenzo Bianconi 					.mask = GENMASK(7, 4),
58140dd7343SLorenzo Bianconi 				},
582f8710f03SLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
583f8710f03SLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
584f8710f03SLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
585f8710f03SLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
586f8710f03SLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
587f8710f03SLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
58859af4e20SLorenzo Bianconi 				.odr_len = 6,
58940dd7343SLorenzo Bianconi 			},
59040dd7343SLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
59140dd7343SLorenzo Bianconi 				.reg = {
59240dd7343SLorenzo Bianconi 					.addr = 0x11,
59340dd7343SLorenzo Bianconi 					.mask = GENMASK(7, 4),
59440dd7343SLorenzo Bianconi 				},
595f8710f03SLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
596f8710f03SLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
597f8710f03SLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
598f8710f03SLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
599f8710f03SLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
600f8710f03SLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
60159af4e20SLorenzo Bianconi 				.odr_len = 6,
60240dd7343SLorenzo Bianconi 			},
60340dd7343SLorenzo Bianconi 		},
604640aca3fSLorenzo Bianconi 		.fs_table = {
605640aca3fSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
606640aca3fSLorenzo Bianconi 				.reg = {
607640aca3fSLorenzo Bianconi 					.addr = 0x10,
608640aca3fSLorenzo Bianconi 					.mask = GENMASK(3, 2),
609640aca3fSLorenzo Bianconi 				},
61044a76de8SMario Tesi 				.fs_avl[0] = {  IIO_G_TO_M_S_2(61000), 0x0 },
61144a76de8SMario Tesi 				.fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 },
61244a76de8SMario Tesi 				.fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 },
61344a76de8SMario Tesi 				.fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 },
61485ae3aeeSLorenzo Bianconi 				.fs_len = 4,
615640aca3fSLorenzo Bianconi 			},
616640aca3fSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
617640aca3fSLorenzo Bianconi 				.reg = {
618640aca3fSLorenzo Bianconi 					.addr = 0x11,
619640aca3fSLorenzo Bianconi 					.mask = GENMASK(3, 2),
620640aca3fSLorenzo Bianconi 				},
62144a76de8SMario Tesi 				.fs_avl[0] = {  IIO_DEGREE_TO_RAD(8750000), 0x0 },
62244a76de8SMario Tesi 				.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 },
62344a76de8SMario Tesi 				.fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 },
62444a76de8SMario Tesi 				.fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 },
62585ae3aeeSLorenzo Bianconi 				.fs_len = 4,
626640aca3fSLorenzo Bianconi 			},
627640aca3fSLorenzo Bianconi 		},
6287e906103SLorenzo Bianconi 		.irq_config = {
6297e906103SLorenzo Bianconi 			.irq1 = {
6307e906103SLorenzo Bianconi 				.addr = 0x0d,
6317e906103SLorenzo Bianconi 				.mask = BIT(3),
6327e906103SLorenzo Bianconi 			},
6337e906103SLorenzo Bianconi 			.irq2 = {
6347e906103SLorenzo Bianconi 				.addr = 0x0e,
6357e906103SLorenzo Bianconi 				.mask = BIT(3),
6367e906103SLorenzo Bianconi 			},
6377e906103SLorenzo Bianconi 			.lir = {
6387e906103SLorenzo Bianconi 				.addr = 0x58,
6397e906103SLorenzo Bianconi 				.mask = BIT(0),
6407e906103SLorenzo Bianconi 			},
6417e906103SLorenzo Bianconi 			.irq1_func = {
6427e906103SLorenzo Bianconi 				.addr = 0x5e,
6437e906103SLorenzo Bianconi 				.mask = BIT(5),
6447e906103SLorenzo Bianconi 			},
6457e906103SLorenzo Bianconi 			.irq2_func = {
6467e906103SLorenzo Bianconi 				.addr = 0x5f,
6477e906103SLorenzo Bianconi 				.mask = BIT(5),
6487e906103SLorenzo Bianconi 			},
64931fe8d4eSLorenzo Bianconi 			.hla = {
65031fe8d4eSLorenzo Bianconi 				.addr = 0x12,
65131fe8d4eSLorenzo Bianconi 				.mask = BIT(5),
65231fe8d4eSLorenzo Bianconi 			},
65331fe8d4eSLorenzo Bianconi 			.od = {
65431fe8d4eSLorenzo Bianconi 				.addr = 0x12,
65531fe8d4eSLorenzo Bianconi 				.mask = BIT(4),
65631fe8d4eSLorenzo Bianconi 			},
6577e906103SLorenzo Bianconi 		},
6587ca3ac9eSLorenzo Bianconi 		.decimator = {
6597ca3ac9eSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
6607ca3ac9eSLorenzo Bianconi 				.addr = 0x08,
6617ca3ac9eSLorenzo Bianconi 				.mask = GENMASK(2, 0),
6627ca3ac9eSLorenzo Bianconi 			},
6637ca3ac9eSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
6647ca3ac9eSLorenzo Bianconi 				.addr = 0x08,
6657ca3ac9eSLorenzo Bianconi 				.mask = GENMASK(5, 3),
6667ca3ac9eSLorenzo Bianconi 			},
667e485e2a2SLorenzo Bianconi 			[ST_LSM6DSX_ID_EXT0] = {
668e485e2a2SLorenzo Bianconi 				.addr = 0x09,
669e485e2a2SLorenzo Bianconi 				.mask = GENMASK(2, 0),
670e485e2a2SLorenzo Bianconi 			},
6717ca3ac9eSLorenzo Bianconi 		},
67292617c15SLorenzo Bianconi 		.fifo_ops = {
6733b72950dSLorenzo Bianconi 			.update_fifo = st_lsm6dsx_update_fifo,
67450ff457dSLorenzo Bianconi 			.read_fifo = st_lsm6dsx_read_fifo,
67592617c15SLorenzo Bianconi 			.fifo_th = {
67692617c15SLorenzo Bianconi 				.addr = 0x06,
677be75eb86SLorenzo Bianconi 				.mask = GENMASK(10, 0),
67892617c15SLorenzo Bianconi 			},
67992617c15SLorenzo Bianconi 			.fifo_diff = {
68092617c15SLorenzo Bianconi 				.addr = 0x3a,
681be75eb86SLorenzo Bianconi 				.mask = GENMASK(10, 0),
68292617c15SLorenzo Bianconi 			},
6831b7da2faSLorenzo Bianconi 			.max_size = 682,
68492617c15SLorenzo Bianconi 			.th_wl = 3, /* 1LSB = 2B */
68592617c15SLorenzo Bianconi 		},
68621345107SLorenzo Bianconi 		.ts_settings = {
68721345107SLorenzo Bianconi 			.timer_en = {
68821345107SLorenzo Bianconi 				.addr = 0x19,
68921345107SLorenzo Bianconi 				.mask = BIT(5),
69021345107SLorenzo Bianconi 			},
69121345107SLorenzo Bianconi 			.hr_timer = {
69221345107SLorenzo Bianconi 				.addr = 0x5c,
69321345107SLorenzo Bianconi 				.mask = BIT(4),
69421345107SLorenzo Bianconi 			},
69521345107SLorenzo Bianconi 			.fifo_en = {
69621345107SLorenzo Bianconi 				.addr = 0x07,
69721345107SLorenzo Bianconi 				.mask = BIT(7),
69821345107SLorenzo Bianconi 			},
69921345107SLorenzo Bianconi 			.decimator = {
70021345107SLorenzo Bianconi 				.addr = 0x09,
70121345107SLorenzo Bianconi 				.mask = GENMASK(5, 3),
70221345107SLorenzo Bianconi 			},
70321345107SLorenzo Bianconi 		},
704e485e2a2SLorenzo Bianconi 		.shub_settings = {
705e485e2a2SLorenzo Bianconi 			.page_mux = {
706e485e2a2SLorenzo Bianconi 				.addr = 0x01,
707e485e2a2SLorenzo Bianconi 				.mask = BIT(7),
708e485e2a2SLorenzo Bianconi 			},
709e485e2a2SLorenzo Bianconi 			.master_en = {
710e485e2a2SLorenzo Bianconi 				.addr = 0x1a,
711e485e2a2SLorenzo Bianconi 				.mask = BIT(0),
712e485e2a2SLorenzo Bianconi 			},
713e485e2a2SLorenzo Bianconi 			.pullup_en = {
714e485e2a2SLorenzo Bianconi 				.addr = 0x1a,
715e485e2a2SLorenzo Bianconi 				.mask = BIT(3),
716e485e2a2SLorenzo Bianconi 			},
717e485e2a2SLorenzo Bianconi 			.aux_sens = {
718e485e2a2SLorenzo Bianconi 				.addr = 0x04,
719e485e2a2SLorenzo Bianconi 				.mask = GENMASK(5, 4),
720e485e2a2SLorenzo Bianconi 			},
721e485e2a2SLorenzo Bianconi 			.wr_once = {
722e485e2a2SLorenzo Bianconi 				.addr = 0x07,
723e485e2a2SLorenzo Bianconi 				.mask = BIT(5),
724e485e2a2SLorenzo Bianconi 			},
725e485e2a2SLorenzo Bianconi 			.emb_func = {
726e485e2a2SLorenzo Bianconi 				.addr = 0x19,
727e485e2a2SLorenzo Bianconi 				.mask = BIT(2),
728e485e2a2SLorenzo Bianconi 			},
729e485e2a2SLorenzo Bianconi 			.num_ext_dev = 1,
730e485e2a2SLorenzo Bianconi 			.shub_out = {
731e485e2a2SLorenzo Bianconi 				.addr = 0x2e,
732e485e2a2SLorenzo Bianconi 			},
733e485e2a2SLorenzo Bianconi 			.slv0_addr = 0x02,
734e485e2a2SLorenzo Bianconi 			.dw_slv0_addr = 0x0e,
735e485e2a2SLorenzo Bianconi 			.pause = 0x7,
736e485e2a2SLorenzo Bianconi 		},
737b5969abfSSean Nyekjaer 		.event_settings = {
738b5969abfSSean Nyekjaer 			.enable_reg = {
739b5969abfSSean Nyekjaer 				.addr = 0x58,
740b5969abfSSean Nyekjaer 				.mask = BIT(7),
741b5969abfSSean Nyekjaer 			},
742b5969abfSSean Nyekjaer 			.wakeup_reg = {
743b5969abfSSean Nyekjaer 				.addr = 0x5B,
744b5969abfSSean Nyekjaer 				.mask = GENMASK(5, 0),
745b5969abfSSean Nyekjaer 			},
7461aabad1fSSean Nyekjaer 			.wakeup_src_reg = 0x1b,
7471aabad1fSSean Nyekjaer 			.wakeup_src_status_mask = BIT(3),
7481aabad1fSSean Nyekjaer 			.wakeup_src_z_mask = BIT(0),
7491aabad1fSSean Nyekjaer 			.wakeup_src_y_mask = BIT(1),
7501aabad1fSSean Nyekjaer 			.wakeup_src_x_mask = BIT(2),
751b5969abfSSean Nyekjaer 		},
752290a6ce1SLorenzo Bianconi 	},
753801a6e0aSLorenzo Bianconi 	{
75466b662a1SLorenzo Bianconi 		.reset = {
75566b662a1SLorenzo Bianconi 			.addr = 0x12,
75666b662a1SLorenzo Bianconi 			.mask = BIT(0),
75766b662a1SLorenzo Bianconi 		},
75866b662a1SLorenzo Bianconi 		.boot = {
75966b662a1SLorenzo Bianconi 			.addr = 0x12,
76066b662a1SLorenzo Bianconi 			.mask = BIT(7),
76166b662a1SLorenzo Bianconi 		},
76266b662a1SLorenzo Bianconi 		.bdu = {
76366b662a1SLorenzo Bianconi 			.addr = 0x12,
76466b662a1SLorenzo Bianconi 			.mask = BIT(6),
76566b662a1SLorenzo Bianconi 		},
76643901008SLorenzo Bianconi 		.id = {
76781956a93SLorenzo Bianconi 			{
76881956a93SLorenzo Bianconi 				.hw_id = ST_LSM6DSR_ID,
76981956a93SLorenzo Bianconi 				.name = ST_LSM6DSR_DEV_NAME,
77098c3544aSLorenzo Bianconi 				.wai = 0x6b,
771db947a79SLorenzo Bianconi 			}, {
772db947a79SLorenzo Bianconi 				.hw_id = ST_ISM330DHCX_ID,
773db947a79SLorenzo Bianconi 				.name = ST_ISM330DHCX_DEV_NAME,
77498c3544aSLorenzo Bianconi 				.wai = 0x6b,
775cf9c71b3SLorenzo Bianconi 			}, {
776cf9c71b3SLorenzo Bianconi 				.hw_id = ST_LSM6DSRX_ID,
777cf9c71b3SLorenzo Bianconi 				.name = ST_LSM6DSRX_DEV_NAME,
77898c3544aSLorenzo Bianconi 				.wai = 0x6b,
77998c3544aSLorenzo Bianconi 			}, {
78098c3544aSLorenzo Bianconi 				.hw_id = ST_LSM6DSO_ID,
78198c3544aSLorenzo Bianconi 				.name = ST_LSM6DSO_DEV_NAME,
78298c3544aSLorenzo Bianconi 				.wai = 0x6c,
78398c3544aSLorenzo Bianconi 			}, {
78498c3544aSLorenzo Bianconi 				.hw_id = ST_LSM6DSOX_ID,
78598c3544aSLorenzo Bianconi 				.name = ST_LSM6DSOX_DEV_NAME,
78698c3544aSLorenzo Bianconi 				.wai = 0x6c,
78798c3544aSLorenzo Bianconi 			}, {
7884393e4c5SLorenzo Bianconi 				.hw_id = ST_LSM6DST_ID,
7894393e4c5SLorenzo Bianconi 				.name = ST_LSM6DST_DEV_NAME,
79098c3544aSLorenzo Bianconi 				.wai = 0x6d,
791fdd70d7aSLorenzo Bianconi 			}, {
792fdd70d7aSLorenzo Bianconi 				.hw_id = ST_ASM330LHHX_ID,
793fdd70d7aSLorenzo Bianconi 				.name = ST_ASM330LHHX_DEV_NAME,
794fdd70d7aSLorenzo Bianconi 				.wai = 0x6b,
795186b9e38SLorenzo Bianconi 			}, {
796186b9e38SLorenzo Bianconi 				.hw_id = ST_LSM6DSTX_ID,
797186b9e38SLorenzo Bianconi 				.name = ST_LSM6DSTX_DEV_NAME,
798186b9e38SLorenzo Bianconi 				.wai = 0x6d,
7994393e4c5SLorenzo Bianconi 			},
8004393e4c5SLorenzo Bianconi 		},
8014393e4c5SLorenzo Bianconi 		.channels = {
8024393e4c5SLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
8034393e4c5SLorenzo Bianconi 				.chan = st_lsm6dsx_acc_channels,
8044393e4c5SLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_acc_channels),
8054393e4c5SLorenzo Bianconi 			},
8064393e4c5SLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
8074393e4c5SLorenzo Bianconi 				.chan = st_lsm6dsx_gyro_channels,
8084393e4c5SLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_gyro_channels),
8094393e4c5SLorenzo Bianconi 			},
8104393e4c5SLorenzo Bianconi 		},
8114393e4c5SLorenzo Bianconi 		.drdy_mask = {
8124393e4c5SLorenzo Bianconi 			.addr = 0x13,
8134393e4c5SLorenzo Bianconi 			.mask = BIT(3),
8144393e4c5SLorenzo Bianconi 		},
8154393e4c5SLorenzo Bianconi 		.odr_table = {
8164393e4c5SLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
8174393e4c5SLorenzo Bianconi 				.reg = {
8184393e4c5SLorenzo Bianconi 					.addr = 0x10,
8194393e4c5SLorenzo Bianconi 					.mask = GENMASK(7, 4),
8204393e4c5SLorenzo Bianconi 				},
8214393e4c5SLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
8224393e4c5SLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
8234393e4c5SLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
8244393e4c5SLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
8254393e4c5SLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
8264393e4c5SLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
8274393e4c5SLorenzo Bianconi 				.odr_avl[6] = { 833000, 0x07 },
8284393e4c5SLorenzo Bianconi 				.odr_len = 7,
8294393e4c5SLorenzo Bianconi 			},
8304393e4c5SLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
8314393e4c5SLorenzo Bianconi 				.reg = {
8324393e4c5SLorenzo Bianconi 					.addr = 0x11,
8334393e4c5SLorenzo Bianconi 					.mask = GENMASK(7, 4),
8344393e4c5SLorenzo Bianconi 				},
8354393e4c5SLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
8364393e4c5SLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
8374393e4c5SLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
8384393e4c5SLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
8394393e4c5SLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
8404393e4c5SLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
8414393e4c5SLorenzo Bianconi 				.odr_avl[6] = { 833000, 0x07 },
8424393e4c5SLorenzo Bianconi 				.odr_len = 7,
8434393e4c5SLorenzo Bianconi 			},
8444393e4c5SLorenzo Bianconi 		},
8454393e4c5SLorenzo Bianconi 		.fs_table = {
8464393e4c5SLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
8474393e4c5SLorenzo Bianconi 				.reg = {
8484393e4c5SLorenzo Bianconi 					.addr = 0x10,
8494393e4c5SLorenzo Bianconi 					.mask = GENMASK(3, 2),
8504393e4c5SLorenzo Bianconi 				},
8514393e4c5SLorenzo Bianconi 				.fs_avl[0] = {  IIO_G_TO_M_S_2(61000), 0x0 },
8524393e4c5SLorenzo Bianconi 				.fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 },
8534393e4c5SLorenzo Bianconi 				.fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 },
8544393e4c5SLorenzo Bianconi 				.fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 },
8554393e4c5SLorenzo Bianconi 				.fs_len = 4,
8564393e4c5SLorenzo Bianconi 			},
8574393e4c5SLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
8584393e4c5SLorenzo Bianconi 				.reg = {
8594393e4c5SLorenzo Bianconi 					.addr = 0x11,
8604393e4c5SLorenzo Bianconi 					.mask = GENMASK(3, 2),
8614393e4c5SLorenzo Bianconi 				},
8624393e4c5SLorenzo Bianconi 				.fs_avl[0] = {  IIO_DEGREE_TO_RAD(8750000), 0x0 },
8634393e4c5SLorenzo Bianconi 				.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 },
8644393e4c5SLorenzo Bianconi 				.fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 },
8654393e4c5SLorenzo Bianconi 				.fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 },
8664393e4c5SLorenzo Bianconi 				.fs_len = 4,
8674393e4c5SLorenzo Bianconi 			},
8684393e4c5SLorenzo Bianconi 		},
8694393e4c5SLorenzo Bianconi 		.irq_config = {
8704393e4c5SLorenzo Bianconi 			.irq1 = {
8714393e4c5SLorenzo Bianconi 				.addr = 0x0d,
8724393e4c5SLorenzo Bianconi 				.mask = BIT(3),
8734393e4c5SLorenzo Bianconi 			},
8744393e4c5SLorenzo Bianconi 			.irq2 = {
8754393e4c5SLorenzo Bianconi 				.addr = 0x0e,
8764393e4c5SLorenzo Bianconi 				.mask = BIT(3),
8774393e4c5SLorenzo Bianconi 			},
8784393e4c5SLorenzo Bianconi 			.lir = {
8794393e4c5SLorenzo Bianconi 				.addr = 0x56,
8804393e4c5SLorenzo Bianconi 				.mask = BIT(0),
8814393e4c5SLorenzo Bianconi 			},
8824393e4c5SLorenzo Bianconi 			.clear_on_read = {
8834393e4c5SLorenzo Bianconi 				.addr = 0x56,
8844393e4c5SLorenzo Bianconi 				.mask = BIT(6),
8854393e4c5SLorenzo Bianconi 			},
8864393e4c5SLorenzo Bianconi 			.irq1_func = {
8874393e4c5SLorenzo Bianconi 				.addr = 0x5e,
8884393e4c5SLorenzo Bianconi 				.mask = BIT(5),
8894393e4c5SLorenzo Bianconi 			},
8904393e4c5SLorenzo Bianconi 			.irq2_func = {
8914393e4c5SLorenzo Bianconi 				.addr = 0x5f,
8924393e4c5SLorenzo Bianconi 				.mask = BIT(5),
8934393e4c5SLorenzo Bianconi 			},
8944393e4c5SLorenzo Bianconi 			.hla = {
8954393e4c5SLorenzo Bianconi 				.addr = 0x12,
8964393e4c5SLorenzo Bianconi 				.mask = BIT(5),
8974393e4c5SLorenzo Bianconi 			},
8984393e4c5SLorenzo Bianconi 			.od = {
8994393e4c5SLorenzo Bianconi 				.addr = 0x12,
9004393e4c5SLorenzo Bianconi 				.mask = BIT(4),
9014393e4c5SLorenzo Bianconi 			},
9024393e4c5SLorenzo Bianconi 		},
9034393e4c5SLorenzo Bianconi 		.batch = {
9044393e4c5SLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
9054393e4c5SLorenzo Bianconi 				.addr = 0x09,
9064393e4c5SLorenzo Bianconi 				.mask = GENMASK(3, 0),
9074393e4c5SLorenzo Bianconi 			},
9084393e4c5SLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
9094393e4c5SLorenzo Bianconi 				.addr = 0x09,
9104393e4c5SLorenzo Bianconi 				.mask = GENMASK(7, 4),
9114393e4c5SLorenzo Bianconi 			},
9124393e4c5SLorenzo Bianconi 		},
9134393e4c5SLorenzo Bianconi 		.fifo_ops = {
9144393e4c5SLorenzo Bianconi 			.update_fifo = st_lsm6dsx_update_fifo,
9154393e4c5SLorenzo Bianconi 			.read_fifo = st_lsm6dsx_read_tagged_fifo,
9164393e4c5SLorenzo Bianconi 			.fifo_th = {
9174393e4c5SLorenzo Bianconi 				.addr = 0x07,
9184393e4c5SLorenzo Bianconi 				.mask = GENMASK(8, 0),
9194393e4c5SLorenzo Bianconi 			},
9204393e4c5SLorenzo Bianconi 			.fifo_diff = {
9214393e4c5SLorenzo Bianconi 				.addr = 0x3a,
9224393e4c5SLorenzo Bianconi 				.mask = GENMASK(9, 0),
9234393e4c5SLorenzo Bianconi 			},
9241b7da2faSLorenzo Bianconi 			.max_size = 512,
9254393e4c5SLorenzo Bianconi 			.th_wl = 1,
9264393e4c5SLorenzo Bianconi 		},
9274393e4c5SLorenzo Bianconi 		.ts_settings = {
9284393e4c5SLorenzo Bianconi 			.timer_en = {
9294393e4c5SLorenzo Bianconi 				.addr = 0x19,
9304393e4c5SLorenzo Bianconi 				.mask = BIT(5),
9314393e4c5SLorenzo Bianconi 			},
9324393e4c5SLorenzo Bianconi 			.decimator = {
9334393e4c5SLorenzo Bianconi 				.addr = 0x0a,
9344393e4c5SLorenzo Bianconi 				.mask = GENMASK(7, 6),
9354393e4c5SLorenzo Bianconi 			},
9364393e4c5SLorenzo Bianconi 			.freq_fine = 0x63,
9374393e4c5SLorenzo Bianconi 		},
9384393e4c5SLorenzo Bianconi 		.shub_settings = {
9394393e4c5SLorenzo Bianconi 			.page_mux = {
9404393e4c5SLorenzo Bianconi 				.addr = 0x01,
9414393e4c5SLorenzo Bianconi 				.mask = BIT(6),
9424393e4c5SLorenzo Bianconi 			},
9434393e4c5SLorenzo Bianconi 			.master_en = {
9444393e4c5SLorenzo Bianconi 				.sec_page = true,
9454393e4c5SLorenzo Bianconi 				.addr = 0x14,
9464393e4c5SLorenzo Bianconi 				.mask = BIT(2),
9474393e4c5SLorenzo Bianconi 			},
9484393e4c5SLorenzo Bianconi 			.pullup_en = {
9494393e4c5SLorenzo Bianconi 				.sec_page = true,
9504393e4c5SLorenzo Bianconi 				.addr = 0x14,
9514393e4c5SLorenzo Bianconi 				.mask = BIT(3),
9524393e4c5SLorenzo Bianconi 			},
9534393e4c5SLorenzo Bianconi 			.aux_sens = {
9544393e4c5SLorenzo Bianconi 				.addr = 0x14,
9554393e4c5SLorenzo Bianconi 				.mask = GENMASK(1, 0),
9564393e4c5SLorenzo Bianconi 			},
9574393e4c5SLorenzo Bianconi 			.wr_once = {
9584393e4c5SLorenzo Bianconi 				.addr = 0x14,
9594393e4c5SLorenzo Bianconi 				.mask = BIT(6),
9604393e4c5SLorenzo Bianconi 			},
9614393e4c5SLorenzo Bianconi 			.num_ext_dev = 3,
9624393e4c5SLorenzo Bianconi 			.shub_out = {
9634393e4c5SLorenzo Bianconi 				.sec_page = true,
9644393e4c5SLorenzo Bianconi 				.addr = 0x02,
9654393e4c5SLorenzo Bianconi 			},
9664393e4c5SLorenzo Bianconi 			.slv0_addr = 0x15,
9674393e4c5SLorenzo Bianconi 			.dw_slv0_addr = 0x21,
9684393e4c5SLorenzo Bianconi 			.batch_en = BIT(3),
9694393e4c5SLorenzo Bianconi 		},
9704393e4c5SLorenzo Bianconi 		.event_settings = {
9714393e4c5SLorenzo Bianconi 			.enable_reg = {
9724393e4c5SLorenzo Bianconi 				.addr = 0x58,
9734393e4c5SLorenzo Bianconi 				.mask = BIT(7),
9744393e4c5SLorenzo Bianconi 			},
9754393e4c5SLorenzo Bianconi 			.wakeup_reg = {
9764393e4c5SLorenzo Bianconi 				.addr = 0x5b,
9774393e4c5SLorenzo Bianconi 				.mask = GENMASK(5, 0),
9784393e4c5SLorenzo Bianconi 			},
9794393e4c5SLorenzo Bianconi 			.wakeup_src_reg = 0x1b,
9804393e4c5SLorenzo Bianconi 			.wakeup_src_status_mask = BIT(3),
9814393e4c5SLorenzo Bianconi 			.wakeup_src_z_mask = BIT(0),
9824393e4c5SLorenzo Bianconi 			.wakeup_src_y_mask = BIT(1),
9834393e4c5SLorenzo Bianconi 			.wakeup_src_x_mask = BIT(2),
9844393e4c5SLorenzo Bianconi 		},
9854393e4c5SLorenzo Bianconi 	},
98698c3544aSLorenzo Bianconi 	{
98798c3544aSLorenzo Bianconi 		.reset = {
98898c3544aSLorenzo Bianconi 			.addr = 0x12,
98998c3544aSLorenzo Bianconi 			.mask = BIT(0),
99098c3544aSLorenzo Bianconi 		},
99198c3544aSLorenzo Bianconi 		.boot = {
99298c3544aSLorenzo Bianconi 			.addr = 0x12,
99398c3544aSLorenzo Bianconi 			.mask = BIT(7),
99498c3544aSLorenzo Bianconi 		},
99598c3544aSLorenzo Bianconi 		.bdu = {
99698c3544aSLorenzo Bianconi 			.addr = 0x12,
99798c3544aSLorenzo Bianconi 			.mask = BIT(6),
99898c3544aSLorenzo Bianconi 		},
99998c3544aSLorenzo Bianconi 		.id = {
100098c3544aSLorenzo Bianconi 			{
100198c3544aSLorenzo Bianconi 				.hw_id = ST_ASM330LHH_ID,
100298c3544aSLorenzo Bianconi 				.name = ST_ASM330LHH_DEV_NAME,
100398c3544aSLorenzo Bianconi 				.wai = 0x6b,
10042c57d265SLorenzo Bianconi 			}, {
10052c57d265SLorenzo Bianconi 				.hw_id = ST_LSM6DSOP_ID,
10062c57d265SLorenzo Bianconi 				.name = ST_LSM6DSOP_DEV_NAME,
10072c57d265SLorenzo Bianconi 				.wai = 0x6c,
100898c3544aSLorenzo Bianconi 			},
100998c3544aSLorenzo Bianconi 		},
101098c3544aSLorenzo Bianconi 		.channels = {
101198c3544aSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
101298c3544aSLorenzo Bianconi 				.chan = st_lsm6dsx_acc_channels,
101398c3544aSLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_acc_channels),
101498c3544aSLorenzo Bianconi 			},
101598c3544aSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
101698c3544aSLorenzo Bianconi 				.chan = st_lsm6dsx_gyro_channels,
101798c3544aSLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_gyro_channels),
101898c3544aSLorenzo Bianconi 			},
101998c3544aSLorenzo Bianconi 		},
102098c3544aSLorenzo Bianconi 		.drdy_mask = {
102198c3544aSLorenzo Bianconi 			.addr = 0x13,
102298c3544aSLorenzo Bianconi 			.mask = BIT(3),
102398c3544aSLorenzo Bianconi 		},
102498c3544aSLorenzo Bianconi 		.odr_table = {
102598c3544aSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
102698c3544aSLorenzo Bianconi 				.reg = {
102798c3544aSLorenzo Bianconi 					.addr = 0x10,
102898c3544aSLorenzo Bianconi 					.mask = GENMASK(7, 4),
102998c3544aSLorenzo Bianconi 				},
103098c3544aSLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
103198c3544aSLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
103298c3544aSLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
103398c3544aSLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
103498c3544aSLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
103598c3544aSLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
103698c3544aSLorenzo Bianconi 				.odr_avl[6] = { 833000, 0x07 },
103798c3544aSLorenzo Bianconi 				.odr_len = 7,
103898c3544aSLorenzo Bianconi 			},
103998c3544aSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
104098c3544aSLorenzo Bianconi 				.reg = {
104198c3544aSLorenzo Bianconi 					.addr = 0x11,
104298c3544aSLorenzo Bianconi 					.mask = GENMASK(7, 4),
104398c3544aSLorenzo Bianconi 				},
104498c3544aSLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
104598c3544aSLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
104698c3544aSLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
104798c3544aSLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
104898c3544aSLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
104998c3544aSLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
105098c3544aSLorenzo Bianconi 				.odr_avl[6] = { 833000, 0x07 },
105198c3544aSLorenzo Bianconi 				.odr_len = 7,
105298c3544aSLorenzo Bianconi 			},
105398c3544aSLorenzo Bianconi 		},
105498c3544aSLorenzo Bianconi 		.fs_table = {
105598c3544aSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
105698c3544aSLorenzo Bianconi 				.reg = {
105798c3544aSLorenzo Bianconi 					.addr = 0x10,
105898c3544aSLorenzo Bianconi 					.mask = GENMASK(3, 2),
105998c3544aSLorenzo Bianconi 				},
106098c3544aSLorenzo Bianconi 				.fs_avl[0] = {  IIO_G_TO_M_S_2(61000), 0x0 },
106198c3544aSLorenzo Bianconi 				.fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 },
106298c3544aSLorenzo Bianconi 				.fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 },
106398c3544aSLorenzo Bianconi 				.fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 },
106498c3544aSLorenzo Bianconi 				.fs_len = 4,
106598c3544aSLorenzo Bianconi 			},
106698c3544aSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
106798c3544aSLorenzo Bianconi 				.reg = {
106898c3544aSLorenzo Bianconi 					.addr = 0x11,
106998c3544aSLorenzo Bianconi 					.mask = GENMASK(3, 2),
107098c3544aSLorenzo Bianconi 				},
107198c3544aSLorenzo Bianconi 				.fs_avl[0] = {  IIO_DEGREE_TO_RAD(8750000), 0x0 },
107298c3544aSLorenzo Bianconi 				.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 },
107398c3544aSLorenzo Bianconi 				.fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 },
107498c3544aSLorenzo Bianconi 				.fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 },
107598c3544aSLorenzo Bianconi 				.fs_len = 4,
107698c3544aSLorenzo Bianconi 			},
107798c3544aSLorenzo Bianconi 		},
107898c3544aSLorenzo Bianconi 		.irq_config = {
107998c3544aSLorenzo Bianconi 			.irq1 = {
108098c3544aSLorenzo Bianconi 				.addr = 0x0d,
108198c3544aSLorenzo Bianconi 				.mask = BIT(3),
108298c3544aSLorenzo Bianconi 			},
108398c3544aSLorenzo Bianconi 			.irq2 = {
108498c3544aSLorenzo Bianconi 				.addr = 0x0e,
108598c3544aSLorenzo Bianconi 				.mask = BIT(3),
108698c3544aSLorenzo Bianconi 			},
108798c3544aSLorenzo Bianconi 			.lir = {
108898c3544aSLorenzo Bianconi 				.addr = 0x56,
108998c3544aSLorenzo Bianconi 				.mask = BIT(0),
109098c3544aSLorenzo Bianconi 			},
109198c3544aSLorenzo Bianconi 			.clear_on_read = {
109298c3544aSLorenzo Bianconi 				.addr = 0x56,
109398c3544aSLorenzo Bianconi 				.mask = BIT(6),
109498c3544aSLorenzo Bianconi 			},
109598c3544aSLorenzo Bianconi 			.irq1_func = {
109698c3544aSLorenzo Bianconi 				.addr = 0x5e,
109798c3544aSLorenzo Bianconi 				.mask = BIT(5),
109898c3544aSLorenzo Bianconi 			},
109998c3544aSLorenzo Bianconi 			.irq2_func = {
110098c3544aSLorenzo Bianconi 				.addr = 0x5f,
110198c3544aSLorenzo Bianconi 				.mask = BIT(5),
110298c3544aSLorenzo Bianconi 			},
110398c3544aSLorenzo Bianconi 			.hla = {
110498c3544aSLorenzo Bianconi 				.addr = 0x12,
110598c3544aSLorenzo Bianconi 				.mask = BIT(5),
110698c3544aSLorenzo Bianconi 			},
110798c3544aSLorenzo Bianconi 			.od = {
110898c3544aSLorenzo Bianconi 				.addr = 0x12,
110998c3544aSLorenzo Bianconi 				.mask = BIT(4),
111098c3544aSLorenzo Bianconi 			},
111198c3544aSLorenzo Bianconi 		},
111298c3544aSLorenzo Bianconi 		.batch = {
111398c3544aSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
111498c3544aSLorenzo Bianconi 				.addr = 0x09,
111598c3544aSLorenzo Bianconi 				.mask = GENMASK(3, 0),
111698c3544aSLorenzo Bianconi 			},
111798c3544aSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
111898c3544aSLorenzo Bianconi 				.addr = 0x09,
111998c3544aSLorenzo Bianconi 				.mask = GENMASK(7, 4),
112098c3544aSLorenzo Bianconi 			},
112198c3544aSLorenzo Bianconi 		},
112298c3544aSLorenzo Bianconi 		.fifo_ops = {
112398c3544aSLorenzo Bianconi 			.update_fifo = st_lsm6dsx_update_fifo,
112498c3544aSLorenzo Bianconi 			.read_fifo = st_lsm6dsx_read_tagged_fifo,
112598c3544aSLorenzo Bianconi 			.fifo_th = {
112698c3544aSLorenzo Bianconi 				.addr = 0x07,
112798c3544aSLorenzo Bianconi 				.mask = GENMASK(8, 0),
112898c3544aSLorenzo Bianconi 			},
112998c3544aSLorenzo Bianconi 			.fifo_diff = {
113098c3544aSLorenzo Bianconi 				.addr = 0x3a,
113198c3544aSLorenzo Bianconi 				.mask = GENMASK(9, 0),
113298c3544aSLorenzo Bianconi 			},
11331b7da2faSLorenzo Bianconi 			.max_size = 512,
113498c3544aSLorenzo Bianconi 			.th_wl = 1,
113598c3544aSLorenzo Bianconi 		},
113698c3544aSLorenzo Bianconi 		.ts_settings = {
113798c3544aSLorenzo Bianconi 			.timer_en = {
113898c3544aSLorenzo Bianconi 				.addr = 0x19,
113998c3544aSLorenzo Bianconi 				.mask = BIT(5),
114098c3544aSLorenzo Bianconi 			},
114198c3544aSLorenzo Bianconi 			.decimator = {
114298c3544aSLorenzo Bianconi 				.addr = 0x0a,
114398c3544aSLorenzo Bianconi 				.mask = GENMASK(7, 6),
114498c3544aSLorenzo Bianconi 			},
114598c3544aSLorenzo Bianconi 			.freq_fine = 0x63,
114698c3544aSLorenzo Bianconi 		},
114798c3544aSLorenzo Bianconi 		.event_settings = {
114898c3544aSLorenzo Bianconi 			.enable_reg = {
114998c3544aSLorenzo Bianconi 				.addr = 0x58,
115098c3544aSLorenzo Bianconi 				.mask = BIT(7),
115198c3544aSLorenzo Bianconi 			},
115298c3544aSLorenzo Bianconi 			.wakeup_reg = {
115398c3544aSLorenzo Bianconi 				.addr = 0x5B,
115498c3544aSLorenzo Bianconi 				.mask = GENMASK(5, 0),
115598c3544aSLorenzo Bianconi 			},
115698c3544aSLorenzo Bianconi 			.wakeup_src_reg = 0x1b,
115798c3544aSLorenzo Bianconi 			.wakeup_src_status_mask = BIT(3),
115898c3544aSLorenzo Bianconi 			.wakeup_src_z_mask = BIT(0),
115998c3544aSLorenzo Bianconi 			.wakeup_src_y_mask = BIT(1),
116098c3544aSLorenzo Bianconi 			.wakeup_src_x_mask = BIT(2),
116198c3544aSLorenzo Bianconi 		},
116298c3544aSLorenzo Bianconi 	},
1163290a6ce1SLorenzo Bianconi };
1164290a6ce1SLorenzo Bianconi 
1165c91c1c84SLorenzo Bianconi int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable)
1166c91c1c84SLorenzo Bianconi {
1167c91c1c84SLorenzo Bianconi 	const struct st_lsm6dsx_shub_settings *hub_settings;
1168c91c1c84SLorenzo Bianconi 	unsigned int data;
1169c91c1c84SLorenzo Bianconi 	int err;
1170c91c1c84SLorenzo Bianconi 
1171c91c1c84SLorenzo Bianconi 	hub_settings = &hw->settings->shub_settings;
1172c91c1c84SLorenzo Bianconi 	data = ST_LSM6DSX_SHIFT_VAL(enable, hub_settings->page_mux.mask);
1173c91c1c84SLorenzo Bianconi 	err = regmap_update_bits(hw->regmap, hub_settings->page_mux.addr,
1174c91c1c84SLorenzo Bianconi 				 hub_settings->page_mux.mask, data);
1175c91c1c84SLorenzo Bianconi 	usleep_range(100, 150);
1176c91c1c84SLorenzo Bianconi 
1177c91c1c84SLorenzo Bianconi 	return err;
1178c91c1c84SLorenzo Bianconi }
1179c91c1c84SLorenzo Bianconi 
118081956a93SLorenzo Bianconi static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id,
118181956a93SLorenzo Bianconi 				   const char **name)
1182290a6ce1SLorenzo Bianconi {
118351a8b707SLorenzo Bianconi 	int err, i, j, data;
1184290a6ce1SLorenzo Bianconi 
1185290a6ce1SLorenzo Bianconi 	for (i = 0; i < ARRAY_SIZE(st_lsm6dsx_sensor_settings); i++) {
1186d068e4a0SLorenzo Bianconi 		for (j = 0; j < ST_LSM6DSX_MAX_ID; j++) {
1187fb4fbc89SStephan Gerhold 			if (st_lsm6dsx_sensor_settings[i].id[j].name &&
1188fb4fbc89SStephan Gerhold 			    id == st_lsm6dsx_sensor_settings[i].id[j].hw_id)
1189d068e4a0SLorenzo Bianconi 				break;
1190d068e4a0SLorenzo Bianconi 		}
1191d068e4a0SLorenzo Bianconi 		if (j < ST_LSM6DSX_MAX_ID)
1192290a6ce1SLorenzo Bianconi 			break;
1193290a6ce1SLorenzo Bianconi 	}
1194290a6ce1SLorenzo Bianconi 
1195290a6ce1SLorenzo Bianconi 	if (i == ARRAY_SIZE(st_lsm6dsx_sensor_settings)) {
1196290a6ce1SLorenzo Bianconi 		dev_err(hw->dev, "unsupported hw id [%02x]\n", id);
1197290a6ce1SLorenzo Bianconi 		return -ENODEV;
1198290a6ce1SLorenzo Bianconi 	}
1199290a6ce1SLorenzo Bianconi 
120051a8b707SLorenzo Bianconi 	err = regmap_read(hw->regmap, ST_LSM6DSX_REG_WHOAMI_ADDR, &data);
1201290a6ce1SLorenzo Bianconi 	if (err < 0) {
1202290a6ce1SLorenzo Bianconi 		dev_err(hw->dev, "failed to read whoami register\n");
1203290a6ce1SLorenzo Bianconi 		return err;
1204290a6ce1SLorenzo Bianconi 	}
1205290a6ce1SLorenzo Bianconi 
120698c3544aSLorenzo Bianconi 	if (data != st_lsm6dsx_sensor_settings[i].id[j].wai) {
1207290a6ce1SLorenzo Bianconi 		dev_err(hw->dev, "unsupported whoami [%02x]\n", data);
1208290a6ce1SLorenzo Bianconi 		return -ENODEV;
1209290a6ce1SLorenzo Bianconi 	}
1210290a6ce1SLorenzo Bianconi 
121181956a93SLorenzo Bianconi 	*name = st_lsm6dsx_sensor_settings[i].id[j].name;
1212290a6ce1SLorenzo Bianconi 	hw->settings = &st_lsm6dsx_sensor_settings[i];
1213290a6ce1SLorenzo Bianconi 
1214290a6ce1SLorenzo Bianconi 	return 0;
1215290a6ce1SLorenzo Bianconi }
1216290a6ce1SLorenzo Bianconi 
1217290a6ce1SLorenzo Bianconi static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor,
1218290a6ce1SLorenzo Bianconi 				     u32 gain)
1219290a6ce1SLorenzo Bianconi {
1220640aca3fSLorenzo Bianconi 	const struct st_lsm6dsx_fs_table_entry *fs_table;
1221739aff87SLorenzo Bianconi 	unsigned int data;
1222290a6ce1SLorenzo Bianconi 	int i, err;
1223290a6ce1SLorenzo Bianconi 
1224640aca3fSLorenzo Bianconi 	fs_table = &sensor->hw->settings->fs_table[sensor->id];
122585ae3aeeSLorenzo Bianconi 	for (i = 0; i < fs_table->fs_len; i++) {
1226640aca3fSLorenzo Bianconi 		if (fs_table->fs_avl[i].gain == gain)
1227290a6ce1SLorenzo Bianconi 			break;
122885ae3aeeSLorenzo Bianconi 	}
1229290a6ce1SLorenzo Bianconi 
123085ae3aeeSLorenzo Bianconi 	if (i == fs_table->fs_len)
1231290a6ce1SLorenzo Bianconi 		return -EINVAL;
1232290a6ce1SLorenzo Bianconi 
1233640aca3fSLorenzo Bianconi 	data = ST_LSM6DSX_SHIFT_VAL(fs_table->fs_avl[i].val,
1234640aca3fSLorenzo Bianconi 				    fs_table->reg.mask);
1235640aca3fSLorenzo Bianconi 	err = st_lsm6dsx_update_bits_locked(sensor->hw, fs_table->reg.addr,
1236640aca3fSLorenzo Bianconi 					    fs_table->reg.mask, data);
1237290a6ce1SLorenzo Bianconi 	if (err < 0)
1238290a6ce1SLorenzo Bianconi 		return err;
1239290a6ce1SLorenzo Bianconi 
1240290a6ce1SLorenzo Bianconi 	sensor->gain = gain;
1241290a6ce1SLorenzo Bianconi 
1242290a6ce1SLorenzo Bianconi 	return 0;
1243290a6ce1SLorenzo Bianconi }
1244290a6ce1SLorenzo Bianconi 
1245f8710f03SLorenzo Bianconi int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u32 odr, u8 *val)
1246290a6ce1SLorenzo Bianconi {
124740dd7343SLorenzo Bianconi 	const struct st_lsm6dsx_odr_table_entry *odr_table;
12482ccc1503SLorenzo Bianconi 	int i;
1249290a6ce1SLorenzo Bianconi 
125040dd7343SLorenzo Bianconi 	odr_table = &sensor->hw->settings->odr_table[sensor->id];
125159af4e20SLorenzo Bianconi 	for (i = 0; i < odr_table->odr_len; i++) {
12526ffb55e5SLorenzo Bianconi 		/*
12536ffb55e5SLorenzo Bianconi 		 * ext devices can run at different odr respect to
12546ffb55e5SLorenzo Bianconi 		 * accel sensor
12556ffb55e5SLorenzo Bianconi 		 */
1256f8710f03SLorenzo Bianconi 		if (odr_table->odr_avl[i].milli_hz >= odr)
1257290a6ce1SLorenzo Bianconi 			break;
125859af4e20SLorenzo Bianconi 	}
1259290a6ce1SLorenzo Bianconi 
126059af4e20SLorenzo Bianconi 	if (i == odr_table->odr_len)
1261290a6ce1SLorenzo Bianconi 		return -EINVAL;
1262290a6ce1SLorenzo Bianconi 
126340dd7343SLorenzo Bianconi 	*val = odr_table->odr_avl[i].val;
1264f8710f03SLorenzo Bianconi 	return odr_table->odr_avl[i].milli_hz;
1265290a6ce1SLorenzo Bianconi }
1266290a6ce1SLorenzo Bianconi 
1267f8710f03SLorenzo Bianconi static int
1268f8710f03SLorenzo Bianconi st_lsm6dsx_check_odr_dependency(struct st_lsm6dsx_hw *hw, u32 odr,
12696ffb55e5SLorenzo Bianconi 				enum st_lsm6dsx_sensor_id id)
12702ccc1503SLorenzo Bianconi {
12716ffb55e5SLorenzo Bianconi 	struct st_lsm6dsx_sensor *ref = iio_priv(hw->iio_devs[id]);
12726ffb55e5SLorenzo Bianconi 
12736ffb55e5SLorenzo Bianconi 	if (odr > 0) {
12746ffb55e5SLorenzo Bianconi 		if (hw->enable_mask & BIT(id))
1275f8710f03SLorenzo Bianconi 			return max_t(u32, ref->odr, odr);
12766ffb55e5SLorenzo Bianconi 		else
12776ffb55e5SLorenzo Bianconi 			return odr;
12786ffb55e5SLorenzo Bianconi 	} else {
12796ffb55e5SLorenzo Bianconi 		return (hw->enable_mask & BIT(id)) ? ref->odr : 0;
12806ffb55e5SLorenzo Bianconi 	}
12816ffb55e5SLorenzo Bianconi }
12826ffb55e5SLorenzo Bianconi 
1283f8710f03SLorenzo Bianconi static int
1284f8710f03SLorenzo Bianconi st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u32 req_odr)
12856ffb55e5SLorenzo Bianconi {
12866ffb55e5SLorenzo Bianconi 	struct st_lsm6dsx_sensor *ref_sensor = sensor;
128751a8b707SLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = sensor->hw;
128851a8b707SLorenzo Bianconi 	const struct st_lsm6dsx_reg *reg;
1289739aff87SLorenzo Bianconi 	unsigned int data;
12906ffb55e5SLorenzo Bianconi 	u8 val = 0;
12912ccc1503SLorenzo Bianconi 	int err;
12922ccc1503SLorenzo Bianconi 
12936ffb55e5SLorenzo Bianconi 	switch (sensor->id) {
129494be878cSTeng Qi 	case ST_LSM6DSX_ID_GYRO:
129594be878cSTeng Qi 		break;
12966ffb55e5SLorenzo Bianconi 	case ST_LSM6DSX_ID_EXT0:
12976ffb55e5SLorenzo Bianconi 	case ST_LSM6DSX_ID_EXT1:
12986ffb55e5SLorenzo Bianconi 	case ST_LSM6DSX_ID_EXT2:
12996ffb55e5SLorenzo Bianconi 	case ST_LSM6DSX_ID_ACC: {
1300f8710f03SLorenzo Bianconi 		u32 odr;
13016ffb55e5SLorenzo Bianconi 		int i;
13026ffb55e5SLorenzo Bianconi 
13036ffb55e5SLorenzo Bianconi 		/*
13046ffb55e5SLorenzo Bianconi 		 * i2c embedded controller relies on the accelerometer sensor as
13056ffb55e5SLorenzo Bianconi 		 * bus read/write trigger so we need to enable accel device
13066ffb55e5SLorenzo Bianconi 		 * at odr = max(accel_odr, ext_odr) in order to properly
13076ffb55e5SLorenzo Bianconi 		 * communicate with i2c slave devices
13086ffb55e5SLorenzo Bianconi 		 */
13096ffb55e5SLorenzo Bianconi 		ref_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]);
13106ffb55e5SLorenzo Bianconi 		for (i = ST_LSM6DSX_ID_ACC; i < ST_LSM6DSX_ID_MAX; i++) {
13116ffb55e5SLorenzo Bianconi 			if (!hw->iio_devs[i] || i == sensor->id)
13126ffb55e5SLorenzo Bianconi 				continue;
13136ffb55e5SLorenzo Bianconi 
13146ffb55e5SLorenzo Bianconi 			odr = st_lsm6dsx_check_odr_dependency(hw, req_odr, i);
13156ffb55e5SLorenzo Bianconi 			if (odr != req_odr)
13166ffb55e5SLorenzo Bianconi 				/* device already configured */
13176ffb55e5SLorenzo Bianconi 				return 0;
13186ffb55e5SLorenzo Bianconi 		}
13196ffb55e5SLorenzo Bianconi 		break;
13206ffb55e5SLorenzo Bianconi 	}
132194be878cSTeng Qi 	default: /* should never occur */
132294be878cSTeng Qi 		return -EINVAL;
13236ffb55e5SLorenzo Bianconi 	}
13246ffb55e5SLorenzo Bianconi 
13256ffb55e5SLorenzo Bianconi 	if (req_odr > 0) {
13266ffb55e5SLorenzo Bianconi 		err = st_lsm6dsx_check_odr(ref_sensor, req_odr, &val);
13272ccc1503SLorenzo Bianconi 		if (err < 0)
13282ccc1503SLorenzo Bianconi 			return err;
13296ffb55e5SLorenzo Bianconi 	}
13302ccc1503SLorenzo Bianconi 
133140dd7343SLorenzo Bianconi 	reg = &hw->settings->odr_table[ref_sensor->id].reg;
1332739aff87SLorenzo Bianconi 	data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask);
1333739aff87SLorenzo Bianconi 	return st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data);
13342ccc1503SLorenzo Bianconi }
13352ccc1503SLorenzo Bianconi 
1336bd41c445SLorenzo Bianconi static int
1337bd41c445SLorenzo Bianconi __st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor,
133817750443SLorenzo Bianconi 			       bool enable)
1339290a6ce1SLorenzo Bianconi {
134051a8b707SLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = sensor->hw;
1341f8710f03SLorenzo Bianconi 	u32 odr = enable ? sensor->odr : 0;
1342290a6ce1SLorenzo Bianconi 	int err;
1343290a6ce1SLorenzo Bianconi 
134417750443SLorenzo Bianconi 	err = st_lsm6dsx_set_odr(sensor, odr);
1345290a6ce1SLorenzo Bianconi 	if (err < 0)
1346290a6ce1SLorenzo Bianconi 		return err;
1347290a6ce1SLorenzo Bianconi 
134817750443SLorenzo Bianconi 	if (enable)
134917750443SLorenzo Bianconi 		hw->enable_mask |= BIT(sensor->id);
135017750443SLorenzo Bianconi 	else
135117750443SLorenzo Bianconi 		hw->enable_mask &= ~BIT(sensor->id);
1352290a6ce1SLorenzo Bianconi 
1353290a6ce1SLorenzo Bianconi 	return 0;
1354290a6ce1SLorenzo Bianconi }
1355290a6ce1SLorenzo Bianconi 
1356bd41c445SLorenzo Bianconi static int
1357bd41c445SLorenzo Bianconi st_lsm6dsx_check_events(struct st_lsm6dsx_sensor *sensor, bool enable)
1358bd41c445SLorenzo Bianconi {
1359bd41c445SLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = sensor->hw;
1360bd41c445SLorenzo Bianconi 
1361bd41c445SLorenzo Bianconi 	if (sensor->id == ST_LSM6DSX_ID_GYRO || enable)
1362bd41c445SLorenzo Bianconi 		return 0;
1363bd41c445SLorenzo Bianconi 
1364bd41c445SLorenzo Bianconi 	return hw->enable_event;
1365bd41c445SLorenzo Bianconi }
1366bd41c445SLorenzo Bianconi 
1367bd41c445SLorenzo Bianconi int st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor,
1368bd41c445SLorenzo Bianconi 				 bool enable)
1369bd41c445SLorenzo Bianconi {
1370bd41c445SLorenzo Bianconi 	if (st_lsm6dsx_check_events(sensor, enable))
1371bd41c445SLorenzo Bianconi 		return 0;
1372bd41c445SLorenzo Bianconi 
1373bd41c445SLorenzo Bianconi 	return __st_lsm6dsx_sensor_set_enable(sensor, enable);
1374bd41c445SLorenzo Bianconi }
1375bd41c445SLorenzo Bianconi 
1376290a6ce1SLorenzo Bianconi static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor,
1377290a6ce1SLorenzo Bianconi 				   u8 addr, int *val)
1378290a6ce1SLorenzo Bianconi {
137951a8b707SLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = sensor->hw;
1380290a6ce1SLorenzo Bianconi 	int err, delay;
1381290a6ce1SLorenzo Bianconi 	__le16 data;
1382290a6ce1SLorenzo Bianconi 
138317750443SLorenzo Bianconi 	err = st_lsm6dsx_sensor_set_enable(sensor, true);
1384290a6ce1SLorenzo Bianconi 	if (err < 0)
1385290a6ce1SLorenzo Bianconi 		return err;
1386290a6ce1SLorenzo Bianconi 
1387ea85bf90SLorenzo Bianconi 	/*
1388ea85bf90SLorenzo Bianconi 	 * we need to wait for sensor settling time before
1389ea85bf90SLorenzo Bianconi 	 * reading data in order to avoid corrupted samples
1390ea85bf90SLorenzo Bianconi 	 */
1391f8710f03SLorenzo Bianconi 	delay = 1000000000 / sensor->odr;
1392ea85bf90SLorenzo Bianconi 	usleep_range(3 * delay, 4 * delay);
1393290a6ce1SLorenzo Bianconi 
1394739aff87SLorenzo Bianconi 	err = st_lsm6dsx_read_locked(hw, addr, &data, sizeof(data));
1395290a6ce1SLorenzo Bianconi 	if (err < 0)
1396290a6ce1SLorenzo Bianconi 		return err;
1397290a6ce1SLorenzo Bianconi 
1398a2dd9bd9SLorenzo Bianconi 	if (!hw->enable_event) {
1399a2dd9bd9SLorenzo Bianconi 		err = st_lsm6dsx_sensor_set_enable(sensor, false);
1400a2dd9bd9SLorenzo Bianconi 		if (err < 0)
1401a2dd9bd9SLorenzo Bianconi 			return err;
1402a2dd9bd9SLorenzo Bianconi 	}
1403290a6ce1SLorenzo Bianconi 
14047b9ebe42SLorenzo Bianconi 	*val = (s16)le16_to_cpu(data);
1405290a6ce1SLorenzo Bianconi 
1406290a6ce1SLorenzo Bianconi 	return IIO_VAL_INT;
1407290a6ce1SLorenzo Bianconi }
1408290a6ce1SLorenzo Bianconi 
1409290a6ce1SLorenzo Bianconi static int st_lsm6dsx_read_raw(struct iio_dev *iio_dev,
1410290a6ce1SLorenzo Bianconi 			       struct iio_chan_spec const *ch,
1411290a6ce1SLorenzo Bianconi 			       int *val, int *val2, long mask)
1412290a6ce1SLorenzo Bianconi {
1413290a6ce1SLorenzo Bianconi 	struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
1414290a6ce1SLorenzo Bianconi 	int ret;
1415290a6ce1SLorenzo Bianconi 
1416290a6ce1SLorenzo Bianconi 	switch (mask) {
1417290a6ce1SLorenzo Bianconi 	case IIO_CHAN_INFO_RAW:
1418290a6ce1SLorenzo Bianconi 		ret = iio_device_claim_direct_mode(iio_dev);
1419290a6ce1SLorenzo Bianconi 		if (ret)
1420290a6ce1SLorenzo Bianconi 			break;
1421290a6ce1SLorenzo Bianconi 
1422290a6ce1SLorenzo Bianconi 		ret = st_lsm6dsx_read_oneshot(sensor, ch->address, val);
1423290a6ce1SLorenzo Bianconi 		iio_device_release_direct_mode(iio_dev);
1424290a6ce1SLorenzo Bianconi 		break;
1425290a6ce1SLorenzo Bianconi 	case IIO_CHAN_INFO_SAMP_FREQ:
1426f8710f03SLorenzo Bianconi 		*val = sensor->odr / 1000;
1427f8710f03SLorenzo Bianconi 		*val2 = (sensor->odr % 1000) * 1000;
1428f8710f03SLorenzo Bianconi 		ret = IIO_VAL_INT_PLUS_MICRO;
1429290a6ce1SLorenzo Bianconi 		break;
1430290a6ce1SLorenzo Bianconi 	case IIO_CHAN_INFO_SCALE:
1431290a6ce1SLorenzo Bianconi 		*val = 0;
1432290a6ce1SLorenzo Bianconi 		*val2 = sensor->gain;
143344a76de8SMario Tesi 		ret = IIO_VAL_INT_PLUS_NANO;
1434290a6ce1SLorenzo Bianconi 		break;
1435290a6ce1SLorenzo Bianconi 	default:
1436290a6ce1SLorenzo Bianconi 		ret = -EINVAL;
1437290a6ce1SLorenzo Bianconi 		break;
1438290a6ce1SLorenzo Bianconi 	}
1439290a6ce1SLorenzo Bianconi 
1440290a6ce1SLorenzo Bianconi 	return ret;
1441290a6ce1SLorenzo Bianconi }
1442290a6ce1SLorenzo Bianconi 
1443290a6ce1SLorenzo Bianconi static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev,
1444290a6ce1SLorenzo Bianconi 				struct iio_chan_spec const *chan,
1445290a6ce1SLorenzo Bianconi 				int val, int val2, long mask)
1446290a6ce1SLorenzo Bianconi {
1447290a6ce1SLorenzo Bianconi 	struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
1448290a6ce1SLorenzo Bianconi 	int err;
1449290a6ce1SLorenzo Bianconi 
1450290a6ce1SLorenzo Bianconi 	err = iio_device_claim_direct_mode(iio_dev);
1451290a6ce1SLorenzo Bianconi 	if (err)
1452290a6ce1SLorenzo Bianconi 		return err;
1453290a6ce1SLorenzo Bianconi 
1454290a6ce1SLorenzo Bianconi 	switch (mask) {
1455290a6ce1SLorenzo Bianconi 	case IIO_CHAN_INFO_SCALE:
1456290a6ce1SLorenzo Bianconi 		err = st_lsm6dsx_set_full_scale(sensor, val2);
1457290a6ce1SLorenzo Bianconi 		break;
14582ccc1503SLorenzo Bianconi 	case IIO_CHAN_INFO_SAMP_FREQ: {
14592ccc1503SLorenzo Bianconi 		u8 data;
14602ccc1503SLorenzo Bianconi 
1461f8710f03SLorenzo Bianconi 		val = val * 1000 + val2 / 1000;
1462fc3f6ad7SLorenzo Bianconi 		val = st_lsm6dsx_check_odr(sensor, val, &data);
1463fc3f6ad7SLorenzo Bianconi 		if (val < 0)
1464fc3f6ad7SLorenzo Bianconi 			err = val;
1465fc3f6ad7SLorenzo Bianconi 		else
14665e3c3e33SLorenzo Bianconi 			sensor->odr = val;
1467290a6ce1SLorenzo Bianconi 		break;
14682ccc1503SLorenzo Bianconi 	}
1469290a6ce1SLorenzo Bianconi 	default:
1470290a6ce1SLorenzo Bianconi 		err = -EINVAL;
1471290a6ce1SLorenzo Bianconi 		break;
1472290a6ce1SLorenzo Bianconi 	}
1473290a6ce1SLorenzo Bianconi 
1474290a6ce1SLorenzo Bianconi 	iio_device_release_direct_mode(iio_dev);
1475290a6ce1SLorenzo Bianconi 
1476290a6ce1SLorenzo Bianconi 	return err;
1477290a6ce1SLorenzo Bianconi }
1478290a6ce1SLorenzo Bianconi 
1479b5969abfSSean Nyekjaer static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, int state)
1480b5969abfSSean Nyekjaer {
148184b2e7c3SLorenzo Bianconi 	const struct st_lsm6dsx_reg *reg;
148204ca37d5SLorenzo Bianconi 	unsigned int data;
1483b5969abfSSean Nyekjaer 	int err;
1484b5969abfSSean Nyekjaer 
14857e906103SLorenzo Bianconi 	if (!hw->settings->irq_config.irq1_func.addr)
1486b5969abfSSean Nyekjaer 		return -ENOTSUPP;
1487b5969abfSSean Nyekjaer 
148884b2e7c3SLorenzo Bianconi 	reg = &hw->settings->event_settings.enable_reg;
148984b2e7c3SLorenzo Bianconi 	if (reg->addr) {
149004ca37d5SLorenzo Bianconi 		data = ST_LSM6DSX_SHIFT_VAL(state, reg->mask);
149104ca37d5SLorenzo Bianconi 		err = st_lsm6dsx_update_bits_locked(hw, reg->addr,
149204ca37d5SLorenzo Bianconi 						    reg->mask, data);
1493b5969abfSSean Nyekjaer 		if (err < 0)
1494b5969abfSSean Nyekjaer 			return err;
149584b2e7c3SLorenzo Bianconi 	}
1496b5969abfSSean Nyekjaer 
1497b5969abfSSean Nyekjaer 	/* Enable wakeup interrupt */
149804ca37d5SLorenzo Bianconi 	data = ST_LSM6DSX_SHIFT_VAL(state, hw->irq_routing->mask);
149904ca37d5SLorenzo Bianconi 	return st_lsm6dsx_update_bits_locked(hw, hw->irq_routing->addr,
150004ca37d5SLorenzo Bianconi 					     hw->irq_routing->mask, data);
1501b5969abfSSean Nyekjaer }
1502b5969abfSSean Nyekjaer 
1503b5969abfSSean Nyekjaer static int st_lsm6dsx_read_event(struct iio_dev *iio_dev,
1504b5969abfSSean Nyekjaer 				 const struct iio_chan_spec *chan,
1505b5969abfSSean Nyekjaer 				 enum iio_event_type type,
1506b5969abfSSean Nyekjaer 				 enum iio_event_direction dir,
1507b5969abfSSean Nyekjaer 				 enum iio_event_info info,
1508b5969abfSSean Nyekjaer 				 int *val, int *val2)
1509b5969abfSSean Nyekjaer {
1510b5969abfSSean Nyekjaer 	struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
1511b5969abfSSean Nyekjaer 	struct st_lsm6dsx_hw *hw = sensor->hw;
1512b5969abfSSean Nyekjaer 
1513b5969abfSSean Nyekjaer 	if (type != IIO_EV_TYPE_THRESH)
1514b5969abfSSean Nyekjaer 		return -EINVAL;
1515b5969abfSSean Nyekjaer 
1516b5969abfSSean Nyekjaer 	*val2 = 0;
1517b5969abfSSean Nyekjaer 	*val = hw->event_threshold;
1518b5969abfSSean Nyekjaer 
1519b5969abfSSean Nyekjaer 	return IIO_VAL_INT;
1520b5969abfSSean Nyekjaer }
1521b5969abfSSean Nyekjaer 
1522b307f495SLorenzo Bianconi static int
1523b307f495SLorenzo Bianconi st_lsm6dsx_write_event(struct iio_dev *iio_dev,
1524b5969abfSSean Nyekjaer 		       const struct iio_chan_spec *chan,
1525b5969abfSSean Nyekjaer 		       enum iio_event_type type,
1526b5969abfSSean Nyekjaer 		       enum iio_event_direction dir,
1527b5969abfSSean Nyekjaer 		       enum iio_event_info info,
1528b5969abfSSean Nyekjaer 		       int val, int val2)
1529b5969abfSSean Nyekjaer {
1530b5969abfSSean Nyekjaer 	struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
1531b5969abfSSean Nyekjaer 	struct st_lsm6dsx_hw *hw = sensor->hw;
153204ca37d5SLorenzo Bianconi 	const struct st_lsm6dsx_reg *reg;
153304ca37d5SLorenzo Bianconi 	unsigned int data;
1534b5969abfSSean Nyekjaer 	int err;
1535b5969abfSSean Nyekjaer 
1536b5969abfSSean Nyekjaer 	if (type != IIO_EV_TYPE_THRESH)
1537b5969abfSSean Nyekjaer 		return -EINVAL;
1538b5969abfSSean Nyekjaer 
1539b5969abfSSean Nyekjaer 	if (val < 0 || val > 31)
1540b5969abfSSean Nyekjaer 		return -EINVAL;
1541b5969abfSSean Nyekjaer 
154204ca37d5SLorenzo Bianconi 	reg = &hw->settings->event_settings.wakeup_reg;
154304ca37d5SLorenzo Bianconi 	data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask);
154404ca37d5SLorenzo Bianconi 	err = st_lsm6dsx_update_bits_locked(hw, reg->addr,
154504ca37d5SLorenzo Bianconi 					    reg->mask, data);
154604ca37d5SLorenzo Bianconi 	if (err < 0)
1547b5969abfSSean Nyekjaer 		return -EINVAL;
1548b5969abfSSean Nyekjaer 
1549b5969abfSSean Nyekjaer 	hw->event_threshold = val;
1550b5969abfSSean Nyekjaer 
1551b5969abfSSean Nyekjaer 	return 0;
1552b5969abfSSean Nyekjaer }
1553b5969abfSSean Nyekjaer 
1554b307f495SLorenzo Bianconi static int
1555b307f495SLorenzo Bianconi st_lsm6dsx_read_event_config(struct iio_dev *iio_dev,
1556b5969abfSSean Nyekjaer 			     const struct iio_chan_spec *chan,
1557b5969abfSSean Nyekjaer 			     enum iio_event_type type,
1558b5969abfSSean Nyekjaer 			     enum iio_event_direction dir)
1559b5969abfSSean Nyekjaer {
1560b5969abfSSean Nyekjaer 	struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
1561b5969abfSSean Nyekjaer 	struct st_lsm6dsx_hw *hw = sensor->hw;
1562b5969abfSSean Nyekjaer 
1563b5969abfSSean Nyekjaer 	if (type != IIO_EV_TYPE_THRESH)
1564b5969abfSSean Nyekjaer 		return -EINVAL;
1565b5969abfSSean Nyekjaer 
15661aabad1fSSean Nyekjaer 	return !!(hw->enable_event & BIT(chan->channel2));
1567b5969abfSSean Nyekjaer }
1568b5969abfSSean Nyekjaer 
1569b307f495SLorenzo Bianconi static int
1570b307f495SLorenzo Bianconi st_lsm6dsx_write_event_config(struct iio_dev *iio_dev,
1571b5969abfSSean Nyekjaer 			      const struct iio_chan_spec *chan,
1572b5969abfSSean Nyekjaer 			      enum iio_event_type type,
1573b307f495SLorenzo Bianconi 			      enum iio_event_direction dir, int state)
1574b5969abfSSean Nyekjaer {
1575b5969abfSSean Nyekjaer 	struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
1576b5969abfSSean Nyekjaer 	struct st_lsm6dsx_hw *hw = sensor->hw;
15771aabad1fSSean Nyekjaer 	u8 enable_event;
1578bd41c445SLorenzo Bianconi 	int err;
1579b5969abfSSean Nyekjaer 
1580b5969abfSSean Nyekjaer 	if (type != IIO_EV_TYPE_THRESH)
1581b5969abfSSean Nyekjaer 		return -EINVAL;
1582b5969abfSSean Nyekjaer 
15831aabad1fSSean Nyekjaer 	if (state) {
15841aabad1fSSean Nyekjaer 		enable_event = hw->enable_event | BIT(chan->channel2);
15851aabad1fSSean Nyekjaer 
1586b5969abfSSean Nyekjaer 		/* do not enable events if they are already enabled */
15871aabad1fSSean Nyekjaer 		if (hw->enable_event)
15881aabad1fSSean Nyekjaer 			goto out;
15891aabad1fSSean Nyekjaer 	} else {
15901aabad1fSSean Nyekjaer 		enable_event = hw->enable_event & ~BIT(chan->channel2);
15911aabad1fSSean Nyekjaer 
15921aabad1fSSean Nyekjaer 		/* only turn off sensor if no events is enabled */
15931aabad1fSSean Nyekjaer 		if (enable_event)
15941aabad1fSSean Nyekjaer 			goto out;
15951aabad1fSSean Nyekjaer 	}
15961aabad1fSSean Nyekjaer 
15971aabad1fSSean Nyekjaer 	/* stop here if no changes have been made */
15981aabad1fSSean Nyekjaer 	if (hw->enable_event == enable_event)
1599b5969abfSSean Nyekjaer 		return 0;
1600b5969abfSSean Nyekjaer 
1601b5969abfSSean Nyekjaer 	err = st_lsm6dsx_event_setup(hw, state);
1602b5969abfSSean Nyekjaer 	if (err < 0)
1603b5969abfSSean Nyekjaer 		return err;
1604b5969abfSSean Nyekjaer 
1605d278d447SLorenzo Bianconi 	mutex_lock(&hw->conf_lock);
1606bd41c445SLorenzo Bianconi 	if (enable_event || !(hw->fifo_mask & BIT(sensor->id)))
1607bd41c445SLorenzo Bianconi 		err = __st_lsm6dsx_sensor_set_enable(sensor, state);
1608d278d447SLorenzo Bianconi 	mutex_unlock(&hw->conf_lock);
1609b5969abfSSean Nyekjaer 	if (err < 0)
1610b5969abfSSean Nyekjaer 		return err;
1611b5969abfSSean Nyekjaer 
16121aabad1fSSean Nyekjaer out:
16131aabad1fSSean Nyekjaer 	hw->enable_event = enable_event;
1614b5969abfSSean Nyekjaer 
1615b5969abfSSean Nyekjaer 	return 0;
1616b5969abfSSean Nyekjaer }
1617b5969abfSSean Nyekjaer 
1618d40464f3SLorenzo Bianconi int st_lsm6dsx_set_watermark(struct iio_dev *iio_dev, unsigned int val)
1619290a6ce1SLorenzo Bianconi {
1620290a6ce1SLorenzo Bianconi 	struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
1621290a6ce1SLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = sensor->hw;
16228f2a88a2SLorenzo Bianconi 	int err;
1623290a6ce1SLorenzo Bianconi 
16249e5b4cd2SPaul Cercueil 	val = clamp_val(val, 1, hw->settings->fifo_ops.max_size);
1625290a6ce1SLorenzo Bianconi 
1626335eaedcSLorenzo Bianconi 	mutex_lock(&hw->conf_lock);
1627335eaedcSLorenzo Bianconi 
1628290a6ce1SLorenzo Bianconi 	err = st_lsm6dsx_update_watermark(sensor, val);
1629335eaedcSLorenzo Bianconi 
1630335eaedcSLorenzo Bianconi 	mutex_unlock(&hw->conf_lock);
1631335eaedcSLorenzo Bianconi 
1632290a6ce1SLorenzo Bianconi 	if (err < 0)
1633290a6ce1SLorenzo Bianconi 		return err;
1634290a6ce1SLorenzo Bianconi 
1635290a6ce1SLorenzo Bianconi 	sensor->watermark = val;
1636290a6ce1SLorenzo Bianconi 
1637290a6ce1SLorenzo Bianconi 	return 0;
1638290a6ce1SLorenzo Bianconi }
1639290a6ce1SLorenzo Bianconi 
1640290a6ce1SLorenzo Bianconi static ssize_t
1641290a6ce1SLorenzo Bianconi st_lsm6dsx_sysfs_sampling_frequency_avail(struct device *dev,
1642290a6ce1SLorenzo Bianconi 					  struct device_attribute *attr,
1643290a6ce1SLorenzo Bianconi 					  char *buf)
1644290a6ce1SLorenzo Bianconi {
16456270bf1fSHaibo Chen 	struct st_lsm6dsx_sensor *sensor = iio_priv(dev_to_iio_dev(dev));
164659af4e20SLorenzo Bianconi 	const struct st_lsm6dsx_odr_table_entry *odr_table;
1647290a6ce1SLorenzo Bianconi 	int i, len = 0;
1648290a6ce1SLorenzo Bianconi 
164959af4e20SLorenzo Bianconi 	odr_table = &sensor->hw->settings->odr_table[sensor->id];
165059af4e20SLorenzo Bianconi 	for (i = 0; i < odr_table->odr_len; i++)
1651f8710f03SLorenzo Bianconi 		len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%03d ",
1652f8710f03SLorenzo Bianconi 				 odr_table->odr_avl[i].milli_hz / 1000,
1653f8710f03SLorenzo Bianconi 				 odr_table->odr_avl[i].milli_hz % 1000);
1654290a6ce1SLorenzo Bianconi 	buf[len - 1] = '\n';
1655290a6ce1SLorenzo Bianconi 
1656290a6ce1SLorenzo Bianconi 	return len;
1657290a6ce1SLorenzo Bianconi }
1658290a6ce1SLorenzo Bianconi 
1659290a6ce1SLorenzo Bianconi static ssize_t st_lsm6dsx_sysfs_scale_avail(struct device *dev,
1660290a6ce1SLorenzo Bianconi 					    struct device_attribute *attr,
1661290a6ce1SLorenzo Bianconi 					    char *buf)
1662290a6ce1SLorenzo Bianconi {
16636270bf1fSHaibo Chen 	struct st_lsm6dsx_sensor *sensor = iio_priv(dev_to_iio_dev(dev));
16640f7e1728SLorenzo Bianconi 	const struct st_lsm6dsx_fs_table_entry *fs_table;
1665640aca3fSLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = sensor->hw;
1666290a6ce1SLorenzo Bianconi 	int i, len = 0;
1667290a6ce1SLorenzo Bianconi 
166885ae3aeeSLorenzo Bianconi 	fs_table = &hw->settings->fs_table[sensor->id];
166985ae3aeeSLorenzo Bianconi 	for (i = 0; i < fs_table->fs_len; i++)
167044a76de8SMario Tesi 		len += scnprintf(buf + len, PAGE_SIZE - len, "0.%09u ",
16710f7e1728SLorenzo Bianconi 				 fs_table->fs_avl[i].gain);
1672290a6ce1SLorenzo Bianconi 	buf[len - 1] = '\n';
1673290a6ce1SLorenzo Bianconi 
1674290a6ce1SLorenzo Bianconi 	return len;
1675290a6ce1SLorenzo Bianconi }
1676290a6ce1SLorenzo Bianconi 
167744a76de8SMario Tesi static int st_lsm6dsx_write_raw_get_fmt(struct iio_dev *indio_dev,
167844a76de8SMario Tesi 					struct iio_chan_spec const *chan,
167944a76de8SMario Tesi 					long mask)
168044a76de8SMario Tesi {
168144a76de8SMario Tesi 	switch (mask) {
168244a76de8SMario Tesi 	case IIO_CHAN_INFO_SCALE:
168344a76de8SMario Tesi 		switch (chan->type) {
168444a76de8SMario Tesi 		case IIO_ANGL_VEL:
168544a76de8SMario Tesi 		case IIO_ACCEL:
168644a76de8SMario Tesi 			return IIO_VAL_INT_PLUS_NANO;
168744a76de8SMario Tesi 		default:
168844a76de8SMario Tesi 			return IIO_VAL_INT_PLUS_MICRO;
168944a76de8SMario Tesi 		}
169044a76de8SMario Tesi 	default:
169144a76de8SMario Tesi 		return IIO_VAL_INT_PLUS_MICRO;
169244a76de8SMario Tesi 	}
169344a76de8SMario Tesi }
169444a76de8SMario Tesi 
1695290a6ce1SLorenzo Bianconi static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(st_lsm6dsx_sysfs_sampling_frequency_avail);
1696290a6ce1SLorenzo Bianconi static IIO_DEVICE_ATTR(in_accel_scale_available, 0444,
1697290a6ce1SLorenzo Bianconi 		       st_lsm6dsx_sysfs_scale_avail, NULL, 0);
1698290a6ce1SLorenzo Bianconi static IIO_DEVICE_ATTR(in_anglvel_scale_available, 0444,
1699290a6ce1SLorenzo Bianconi 		       st_lsm6dsx_sysfs_scale_avail, NULL, 0);
1700290a6ce1SLorenzo Bianconi 
1701290a6ce1SLorenzo Bianconi static struct attribute *st_lsm6dsx_acc_attributes[] = {
1702290a6ce1SLorenzo Bianconi 	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
1703290a6ce1SLorenzo Bianconi 	&iio_dev_attr_in_accel_scale_available.dev_attr.attr,
1704290a6ce1SLorenzo Bianconi 	NULL,
1705290a6ce1SLorenzo Bianconi };
1706290a6ce1SLorenzo Bianconi 
1707290a6ce1SLorenzo Bianconi static const struct attribute_group st_lsm6dsx_acc_attribute_group = {
1708290a6ce1SLorenzo Bianconi 	.attrs = st_lsm6dsx_acc_attributes,
1709290a6ce1SLorenzo Bianconi };
1710290a6ce1SLorenzo Bianconi 
1711290a6ce1SLorenzo Bianconi static const struct iio_info st_lsm6dsx_acc_info = {
1712290a6ce1SLorenzo Bianconi 	.attrs = &st_lsm6dsx_acc_attribute_group,
1713290a6ce1SLorenzo Bianconi 	.read_raw = st_lsm6dsx_read_raw,
1714290a6ce1SLorenzo Bianconi 	.write_raw = st_lsm6dsx_write_raw,
1715b5969abfSSean Nyekjaer 	.read_event_value = st_lsm6dsx_read_event,
1716b5969abfSSean Nyekjaer 	.write_event_value = st_lsm6dsx_write_event,
1717b5969abfSSean Nyekjaer 	.read_event_config = st_lsm6dsx_read_event_config,
1718b5969abfSSean Nyekjaer 	.write_event_config = st_lsm6dsx_write_event_config,
1719290a6ce1SLorenzo Bianconi 	.hwfifo_set_watermark = st_lsm6dsx_set_watermark,
172044a76de8SMario Tesi 	.write_raw_get_fmt = st_lsm6dsx_write_raw_get_fmt,
1721290a6ce1SLorenzo Bianconi };
1722290a6ce1SLorenzo Bianconi 
1723290a6ce1SLorenzo Bianconi static struct attribute *st_lsm6dsx_gyro_attributes[] = {
1724290a6ce1SLorenzo Bianconi 	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
1725290a6ce1SLorenzo Bianconi 	&iio_dev_attr_in_anglvel_scale_available.dev_attr.attr,
1726290a6ce1SLorenzo Bianconi 	NULL,
1727290a6ce1SLorenzo Bianconi };
1728290a6ce1SLorenzo Bianconi 
1729290a6ce1SLorenzo Bianconi static const struct attribute_group st_lsm6dsx_gyro_attribute_group = {
1730290a6ce1SLorenzo Bianconi 	.attrs = st_lsm6dsx_gyro_attributes,
1731290a6ce1SLorenzo Bianconi };
1732290a6ce1SLorenzo Bianconi 
1733290a6ce1SLorenzo Bianconi static const struct iio_info st_lsm6dsx_gyro_info = {
1734290a6ce1SLorenzo Bianconi 	.attrs = &st_lsm6dsx_gyro_attribute_group,
1735290a6ce1SLorenzo Bianconi 	.read_raw = st_lsm6dsx_read_raw,
1736290a6ce1SLorenzo Bianconi 	.write_raw = st_lsm6dsx_write_raw,
1737290a6ce1SLorenzo Bianconi 	.hwfifo_set_watermark = st_lsm6dsx_set_watermark,
173844a76de8SMario Tesi 	.write_raw_get_fmt = st_lsm6dsx_write_raw_get_fmt,
1739290a6ce1SLorenzo Bianconi };
1740290a6ce1SLorenzo Bianconi 
174103d4c566SAndy Shevchenko static int st_lsm6dsx_get_drdy_pin(struct st_lsm6dsx_hw *hw, int *drdy_pin)
1742dba32904SLorenzo Bianconi {
174303d4c566SAndy Shevchenko 	struct device *dev = hw->dev;
1744dba32904SLorenzo Bianconi 
174503d4c566SAndy Shevchenko 	if (!dev_fwnode(dev))
1746dba32904SLorenzo Bianconi 		return -EINVAL;
1747dba32904SLorenzo Bianconi 
174803d4c566SAndy Shevchenko 	return device_property_read_u32(dev, "st,drdy-int-pin", drdy_pin);
1749dba32904SLorenzo Bianconi }
1750dba32904SLorenzo Bianconi 
17517e906103SLorenzo Bianconi static int
17527e906103SLorenzo Bianconi st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw,
17537e906103SLorenzo Bianconi 			const struct st_lsm6dsx_reg **drdy_reg)
1754dba32904SLorenzo Bianconi {
1755dba32904SLorenzo Bianconi 	int err = 0, drdy_pin;
1756dba32904SLorenzo Bianconi 
175703d4c566SAndy Shevchenko 	if (st_lsm6dsx_get_drdy_pin(hw, &drdy_pin) < 0) {
1758dba32904SLorenzo Bianconi 		struct st_sensors_platform_data *pdata;
1759dba32904SLorenzo Bianconi 		struct device *dev = hw->dev;
1760dba32904SLorenzo Bianconi 
1761dba32904SLorenzo Bianconi 		pdata = (struct st_sensors_platform_data *)dev->platform_data;
1762dba32904SLorenzo Bianconi 		drdy_pin = pdata ? pdata->drdy_int_pin : 1;
1763dba32904SLorenzo Bianconi 	}
1764dba32904SLorenzo Bianconi 
1765dba32904SLorenzo Bianconi 	switch (drdy_pin) {
1766dba32904SLorenzo Bianconi 	case 1:
17677e906103SLorenzo Bianconi 		hw->irq_routing = &hw->settings->irq_config.irq1_func;
17687e906103SLorenzo Bianconi 		*drdy_reg = &hw->settings->irq_config.irq1;
1769dba32904SLorenzo Bianconi 		break;
1770dba32904SLorenzo Bianconi 	case 2:
17717e906103SLorenzo Bianconi 		hw->irq_routing = &hw->settings->irq_config.irq2_func;
17727e906103SLorenzo Bianconi 		*drdy_reg = &hw->settings->irq_config.irq2;
1773dba32904SLorenzo Bianconi 		break;
1774dba32904SLorenzo Bianconi 	default:
1775dba32904SLorenzo Bianconi 		dev_err(hw->dev, "unsupported data ready pin\n");
1776dba32904SLorenzo Bianconi 		err = -EINVAL;
1777dba32904SLorenzo Bianconi 		break;
1778dba32904SLorenzo Bianconi 	}
1779dba32904SLorenzo Bianconi 
1780dba32904SLorenzo Bianconi 	return err;
1781dba32904SLorenzo Bianconi }
1782dba32904SLorenzo Bianconi 
1783c91c1c84SLorenzo Bianconi static int st_lsm6dsx_init_shub(struct st_lsm6dsx_hw *hw)
1784c91c1c84SLorenzo Bianconi {
1785c91c1c84SLorenzo Bianconi 	const struct st_lsm6dsx_shub_settings *hub_settings;
1786c91c1c84SLorenzo Bianconi 	struct st_sensors_platform_data *pdata;
178703d4c566SAndy Shevchenko 	struct device *dev = hw->dev;
1788c91c1c84SLorenzo Bianconi 	unsigned int data;
1789c91c1c84SLorenzo Bianconi 	int err = 0;
1790c91c1c84SLorenzo Bianconi 
1791c91c1c84SLorenzo Bianconi 	hub_settings = &hw->settings->shub_settings;
1792c91c1c84SLorenzo Bianconi 
179303d4c566SAndy Shevchenko 	pdata = (struct st_sensors_platform_data *)dev->platform_data;
179403d4c566SAndy Shevchenko 	if ((dev_fwnode(dev) && device_property_read_bool(dev, "st,pullups")) ||
1795c91c1c84SLorenzo Bianconi 	    (pdata && pdata->pullups)) {
17963a431957SLorenzo Bianconi 		if (hub_settings->pullup_en.sec_page) {
1797c91c1c84SLorenzo Bianconi 			err = st_lsm6dsx_set_page(hw, true);
1798c91c1c84SLorenzo Bianconi 			if (err < 0)
1799c91c1c84SLorenzo Bianconi 				return err;
18003a431957SLorenzo Bianconi 		}
1801c91c1c84SLorenzo Bianconi 
1802c91c1c84SLorenzo Bianconi 		data = ST_LSM6DSX_SHIFT_VAL(1, hub_settings->pullup_en.mask);
1803c91c1c84SLorenzo Bianconi 		err = regmap_update_bits(hw->regmap,
1804c91c1c84SLorenzo Bianconi 					 hub_settings->pullup_en.addr,
1805c91c1c84SLorenzo Bianconi 					 hub_settings->pullup_en.mask, data);
1806c91c1c84SLorenzo Bianconi 
18073a431957SLorenzo Bianconi 		if (hub_settings->pullup_en.sec_page)
1808c91c1c84SLorenzo Bianconi 			st_lsm6dsx_set_page(hw, false);
1809c91c1c84SLorenzo Bianconi 
1810c91c1c84SLorenzo Bianconi 		if (err < 0)
1811c91c1c84SLorenzo Bianconi 			return err;
1812c91c1c84SLorenzo Bianconi 	}
1813c91c1c84SLorenzo Bianconi 
1814c91c1c84SLorenzo Bianconi 	if (hub_settings->aux_sens.addr) {
1815c91c1c84SLorenzo Bianconi 		/* configure aux sensors */
1816c91c1c84SLorenzo Bianconi 		err = st_lsm6dsx_set_page(hw, true);
1817c91c1c84SLorenzo Bianconi 		if (err < 0)
1818c91c1c84SLorenzo Bianconi 			return err;
1819c91c1c84SLorenzo Bianconi 
1820c91c1c84SLorenzo Bianconi 		data = ST_LSM6DSX_SHIFT_VAL(3, hub_settings->aux_sens.mask);
1821c91c1c84SLorenzo Bianconi 		err = regmap_update_bits(hw->regmap,
1822c91c1c84SLorenzo Bianconi 					 hub_settings->aux_sens.addr,
1823c91c1c84SLorenzo Bianconi 					 hub_settings->aux_sens.mask, data);
1824c91c1c84SLorenzo Bianconi 
1825c91c1c84SLorenzo Bianconi 		st_lsm6dsx_set_page(hw, false);
1826e485e2a2SLorenzo Bianconi 
1827e485e2a2SLorenzo Bianconi 		if (err < 0)
1828e485e2a2SLorenzo Bianconi 			return err;
1829e485e2a2SLorenzo Bianconi 	}
1830e485e2a2SLorenzo Bianconi 
1831e485e2a2SLorenzo Bianconi 	if (hub_settings->emb_func.addr) {
1832e485e2a2SLorenzo Bianconi 		data = ST_LSM6DSX_SHIFT_VAL(1, hub_settings->emb_func.mask);
1833e485e2a2SLorenzo Bianconi 		err = regmap_update_bits(hw->regmap,
1834e485e2a2SLorenzo Bianconi 					 hub_settings->emb_func.addr,
1835e485e2a2SLorenzo Bianconi 					 hub_settings->emb_func.mask, data);
1836c91c1c84SLorenzo Bianconi 	}
1837c91c1c84SLorenzo Bianconi 
1838c91c1c84SLorenzo Bianconi 	return err;
1839c91c1c84SLorenzo Bianconi }
1840c91c1c84SLorenzo Bianconi 
184121345107SLorenzo Bianconi static int st_lsm6dsx_init_hw_timer(struct st_lsm6dsx_hw *hw)
184221345107SLorenzo Bianconi {
184321345107SLorenzo Bianconi 	const struct st_lsm6dsx_hw_ts_settings *ts_settings;
184421345107SLorenzo Bianconi 	int err, val;
184521345107SLorenzo Bianconi 
184621345107SLorenzo Bianconi 	ts_settings = &hw->settings->ts_settings;
184721345107SLorenzo Bianconi 	/* enable hw timestamp generation if necessary */
184821345107SLorenzo Bianconi 	if (ts_settings->timer_en.addr) {
184921345107SLorenzo Bianconi 		val = ST_LSM6DSX_SHIFT_VAL(1, ts_settings->timer_en.mask);
185021345107SLorenzo Bianconi 		err = regmap_update_bits(hw->regmap,
185121345107SLorenzo Bianconi 					 ts_settings->timer_en.addr,
185221345107SLorenzo Bianconi 					 ts_settings->timer_en.mask, val);
185321345107SLorenzo Bianconi 		if (err < 0)
185421345107SLorenzo Bianconi 			return err;
185521345107SLorenzo Bianconi 	}
185621345107SLorenzo Bianconi 
185721345107SLorenzo Bianconi 	/* enable high resolution for hw ts timer if necessary */
185821345107SLorenzo Bianconi 	if (ts_settings->hr_timer.addr) {
185921345107SLorenzo Bianconi 		val = ST_LSM6DSX_SHIFT_VAL(1, ts_settings->hr_timer.mask);
186021345107SLorenzo Bianconi 		err = regmap_update_bits(hw->regmap,
186121345107SLorenzo Bianconi 					 ts_settings->hr_timer.addr,
186221345107SLorenzo Bianconi 					 ts_settings->hr_timer.mask, val);
186321345107SLorenzo Bianconi 		if (err < 0)
186421345107SLorenzo Bianconi 			return err;
186521345107SLorenzo Bianconi 	}
186621345107SLorenzo Bianconi 
186721345107SLorenzo Bianconi 	/* enable ts queueing in FIFO if necessary */
186821345107SLorenzo Bianconi 	if (ts_settings->fifo_en.addr) {
186921345107SLorenzo Bianconi 		val = ST_LSM6DSX_SHIFT_VAL(1, ts_settings->fifo_en.mask);
187021345107SLorenzo Bianconi 		err = regmap_update_bits(hw->regmap,
187121345107SLorenzo Bianconi 					 ts_settings->fifo_en.addr,
187221345107SLorenzo Bianconi 					 ts_settings->fifo_en.mask, val);
187321345107SLorenzo Bianconi 		if (err < 0)
187421345107SLorenzo Bianconi 			return err;
187521345107SLorenzo Bianconi 	}
1876cb3b6b8eSMario Tesi 
1877cb3b6b8eSMario Tesi 	/* calibrate timestamp sensitivity */
1878cb3b6b8eSMario Tesi 	hw->ts_gain = ST_LSM6DSX_TS_SENSITIVITY;
1879cb3b6b8eSMario Tesi 	if (ts_settings->freq_fine) {
1880cb3b6b8eSMario Tesi 		err = regmap_read(hw->regmap, ts_settings->freq_fine, &val);
1881cb3b6b8eSMario Tesi 		if (err < 0)
1882cb3b6b8eSMario Tesi 			return err;
1883cb3b6b8eSMario Tesi 
1884cb3b6b8eSMario Tesi 		/*
1885cb3b6b8eSMario Tesi 		 * linearize the AN5192 formula:
1886cb3b6b8eSMario Tesi 		 * 1 / (1 + x) ~= 1 - x (Taylor’s Series)
1887cb3b6b8eSMario Tesi 		 * ttrim[s] = 1 / (40000 * (1 + 0.0015 * val))
1888cb3b6b8eSMario Tesi 		 * ttrim[ns] ~= 25000 - 37.5 * val
1889cb3b6b8eSMario Tesi 		 * ttrim[ns] ~= 25000 - (37500 * val) / 1000
1890cb3b6b8eSMario Tesi 		 */
1891cb3b6b8eSMario Tesi 		hw->ts_gain -= ((s8)val * 37500) / 1000;
1892cb3b6b8eSMario Tesi 	}
1893cb3b6b8eSMario Tesi 
189421345107SLorenzo Bianconi 	return 0;
189521345107SLorenzo Bianconi }
189621345107SLorenzo Bianconi 
18973a63da26SLorenzo Bianconi static int st_lsm6dsx_reset_device(struct st_lsm6dsx_hw *hw)
1898290a6ce1SLorenzo Bianconi {
18997e906103SLorenzo Bianconi 	const struct st_lsm6dsx_reg *reg;
1900290a6ce1SLorenzo Bianconi 	int err;
1901290a6ce1SLorenzo Bianconi 
19023a63da26SLorenzo Bianconi 	/*
19033a63da26SLorenzo Bianconi 	 * flush hw FIFO before device reset in order to avoid
19043a63da26SLorenzo Bianconi 	 * possible races on interrupt line 1. If the first interrupt
19053a63da26SLorenzo Bianconi 	 * line is asserted during hw reset the device will work in
19063a63da26SLorenzo Bianconi 	 * I3C-only mode (if it is supported)
19073a63da26SLorenzo Bianconi 	 */
19083a63da26SLorenzo Bianconi 	err = st_lsm6dsx_flush_fifo(hw);
19093a63da26SLorenzo Bianconi 	if (err < 0 && err != -ENOTSUPP)
19103a63da26SLorenzo Bianconi 		return err;
19113a63da26SLorenzo Bianconi 
191219435425SLorenzo Bianconi 	/* device sw reset */
191366b662a1SLorenzo Bianconi 	reg = &hw->settings->reset;
191466b662a1SLorenzo Bianconi 	err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
191566b662a1SLorenzo Bianconi 				 ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
1916290a6ce1SLorenzo Bianconi 	if (err < 0)
1917290a6ce1SLorenzo Bianconi 		return err;
1918290a6ce1SLorenzo Bianconi 
191919435425SLorenzo Bianconi 	msleep(50);
192019435425SLorenzo Bianconi 
192119435425SLorenzo Bianconi 	/* reload trimming parameter */
192266b662a1SLorenzo Bianconi 	reg = &hw->settings->boot;
192366b662a1SLorenzo Bianconi 	err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
192466b662a1SLorenzo Bianconi 				 ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
192519435425SLorenzo Bianconi 	if (err < 0)
192619435425SLorenzo Bianconi 		return err;
192719435425SLorenzo Bianconi 
192819435425SLorenzo Bianconi 	msleep(50);
1929290a6ce1SLorenzo Bianconi 
19303a63da26SLorenzo Bianconi 	return 0;
19313a63da26SLorenzo Bianconi }
19323a63da26SLorenzo Bianconi 
19333a63da26SLorenzo Bianconi static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw)
19343a63da26SLorenzo Bianconi {
19353a63da26SLorenzo Bianconi 	const struct st_lsm6dsx_reg *reg;
19363a63da26SLorenzo Bianconi 	int err;
19373a63da26SLorenzo Bianconi 
19383a63da26SLorenzo Bianconi 	err = st_lsm6dsx_reset_device(hw);
19393a63da26SLorenzo Bianconi 	if (err < 0)
19403a63da26SLorenzo Bianconi 		return err;
19413a63da26SLorenzo Bianconi 
1942290a6ce1SLorenzo Bianconi 	/* enable Block Data Update */
194366b662a1SLorenzo Bianconi 	reg = &hw->settings->bdu;
194466b662a1SLorenzo Bianconi 	err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
194566b662a1SLorenzo Bianconi 				 ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
1946290a6ce1SLorenzo Bianconi 	if (err < 0)
1947290a6ce1SLorenzo Bianconi 		return err;
1948290a6ce1SLorenzo Bianconi 
1949290a6ce1SLorenzo Bianconi 	/* enable FIFO watermak interrupt */
19507e906103SLorenzo Bianconi 	err = st_lsm6dsx_get_drdy_reg(hw, &reg);
1951290a6ce1SLorenzo Bianconi 	if (err < 0)
1952290a6ce1SLorenzo Bianconi 		return err;
1953290a6ce1SLorenzo Bianconi 
19547e906103SLorenzo Bianconi 	err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
19557e906103SLorenzo Bianconi 				 ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
195621345107SLorenzo Bianconi 	if (err < 0)
195721345107SLorenzo Bianconi 		return err;
195821345107SLorenzo Bianconi 
19599db02d32SLorenzo Bianconi 	/* enable Latched interrupts for device events */
19607e906103SLorenzo Bianconi 	if (hw->settings->irq_config.lir.addr) {
19617e906103SLorenzo Bianconi 		reg = &hw->settings->irq_config.lir;
19627e906103SLorenzo Bianconi 		err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
19637e906103SLorenzo Bianconi 					 ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
19649db02d32SLorenzo Bianconi 		if (err < 0)
19659db02d32SLorenzo Bianconi 			return err;
196622ea5651SLorenzo Bianconi 
196722ea5651SLorenzo Bianconi 		/* enable clear on read for latched interrupts */
19687e906103SLorenzo Bianconi 		if (hw->settings->irq_config.clear_on_read.addr) {
19697e906103SLorenzo Bianconi 			reg = &hw->settings->irq_config.clear_on_read;
197022ea5651SLorenzo Bianconi 			err = regmap_update_bits(hw->regmap,
19717e906103SLorenzo Bianconi 					reg->addr, reg->mask,
19727e906103SLorenzo Bianconi 					ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
197322ea5651SLorenzo Bianconi 			if (err < 0)
197422ea5651SLorenzo Bianconi 				return err;
197522ea5651SLorenzo Bianconi 		}
19769db02d32SLorenzo Bianconi 	}
19779db02d32SLorenzo Bianconi 
1978960506edSLorenzo Bianconi 	/* enable drdy-mas if available */
1979960506edSLorenzo Bianconi 	if (hw->settings->drdy_mask.addr) {
1980960506edSLorenzo Bianconi 		reg = &hw->settings->drdy_mask;
1981960506edSLorenzo Bianconi 		err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
1982960506edSLorenzo Bianconi 					 ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
1983960506edSLorenzo Bianconi 		if (err < 0)
1984960506edSLorenzo Bianconi 			return err;
1985960506edSLorenzo Bianconi 	}
1986960506edSLorenzo Bianconi 
1987c91c1c84SLorenzo Bianconi 	err = st_lsm6dsx_init_shub(hw);
1988c91c1c84SLorenzo Bianconi 	if (err < 0)
1989c91c1c84SLorenzo Bianconi 		return err;
1990c91c1c84SLorenzo Bianconi 
199121345107SLorenzo Bianconi 	return st_lsm6dsx_init_hw_timer(hw);
1992290a6ce1SLorenzo Bianconi }
1993290a6ce1SLorenzo Bianconi 
1994290a6ce1SLorenzo Bianconi static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw,
1995510c0106SLorenzo Bianconi 					       enum st_lsm6dsx_sensor_id id,
1996510c0106SLorenzo Bianconi 					       const char *name)
1997290a6ce1SLorenzo Bianconi {
1998290a6ce1SLorenzo Bianconi 	struct st_lsm6dsx_sensor *sensor;
1999290a6ce1SLorenzo Bianconi 	struct iio_dev *iio_dev;
2000290a6ce1SLorenzo Bianconi 
2001290a6ce1SLorenzo Bianconi 	iio_dev = devm_iio_device_alloc(hw->dev, sizeof(*sensor));
2002290a6ce1SLorenzo Bianconi 	if (!iio_dev)
2003290a6ce1SLorenzo Bianconi 		return NULL;
2004290a6ce1SLorenzo Bianconi 
2005290a6ce1SLorenzo Bianconi 	iio_dev->modes = INDIO_DIRECT_MODE;
2006290a6ce1SLorenzo Bianconi 	iio_dev->available_scan_masks = st_lsm6dsx_available_scan_masks;
2007f48bc49bSLorenzo Bianconi 	iio_dev->channels = hw->settings->channels[id].chan;
2008f48bc49bSLorenzo Bianconi 	iio_dev->num_channels = hw->settings->channels[id].len;
2009290a6ce1SLorenzo Bianconi 
2010290a6ce1SLorenzo Bianconi 	sensor = iio_priv(iio_dev);
2011290a6ce1SLorenzo Bianconi 	sensor->id = id;
2012290a6ce1SLorenzo Bianconi 	sensor->hw = hw;
2013f8710f03SLorenzo Bianconi 	sensor->odr = hw->settings->odr_table[id].odr_avl[0].milli_hz;
2014640aca3fSLorenzo Bianconi 	sensor->gain = hw->settings->fs_table[id].fs_avl[0].gain;
2015290a6ce1SLorenzo Bianconi 	sensor->watermark = 1;
2016290a6ce1SLorenzo Bianconi 
2017290a6ce1SLorenzo Bianconi 	switch (id) {
2018290a6ce1SLorenzo Bianconi 	case ST_LSM6DSX_ID_ACC:
2019290a6ce1SLorenzo Bianconi 		iio_dev->info = &st_lsm6dsx_acc_info;
2020510c0106SLorenzo Bianconi 		scnprintf(sensor->name, sizeof(sensor->name), "%s_accel",
2021510c0106SLorenzo Bianconi 			  name);
2022290a6ce1SLorenzo Bianconi 		break;
2023290a6ce1SLorenzo Bianconi 	case ST_LSM6DSX_ID_GYRO:
2024290a6ce1SLorenzo Bianconi 		iio_dev->info = &st_lsm6dsx_gyro_info;
2025510c0106SLorenzo Bianconi 		scnprintf(sensor->name, sizeof(sensor->name), "%s_gyro",
2026510c0106SLorenzo Bianconi 			  name);
2027290a6ce1SLorenzo Bianconi 		break;
2028290a6ce1SLorenzo Bianconi 	default:
2029290a6ce1SLorenzo Bianconi 		return NULL;
2030290a6ce1SLorenzo Bianconi 	}
2031510c0106SLorenzo Bianconi 	iio_dev->name = sensor->name;
2032290a6ce1SLorenzo Bianconi 
2033290a6ce1SLorenzo Bianconi 	return iio_dev;
2034290a6ce1SLorenzo Bianconi }
2035290a6ce1SLorenzo Bianconi 
2036615bd378SLorenzo Bianconi static bool
2037615bd378SLorenzo Bianconi st_lsm6dsx_report_motion_event(struct st_lsm6dsx_hw *hw)
20381aabad1fSSean Nyekjaer {
2039615bd378SLorenzo Bianconi 	const struct st_lsm6dsx_event_settings *event_settings;
2040615bd378SLorenzo Bianconi 	int err, data;
2041615bd378SLorenzo Bianconi 	s64 timestamp;
20421aabad1fSSean Nyekjaer 
2043615bd378SLorenzo Bianconi 	if (!hw->enable_event)
2044615bd378SLorenzo Bianconi 		return false;
2045615bd378SLorenzo Bianconi 
2046615bd378SLorenzo Bianconi 	event_settings = &hw->settings->event_settings;
2047615bd378SLorenzo Bianconi 	err = st_lsm6dsx_read_locked(hw, event_settings->wakeup_src_reg,
2048615bd378SLorenzo Bianconi 				     &data, sizeof(data));
2049615bd378SLorenzo Bianconi 	if (err < 0)
2050615bd378SLorenzo Bianconi 		return false;
2051615bd378SLorenzo Bianconi 
2052615bd378SLorenzo Bianconi 	timestamp = iio_get_time_ns(hw->iio_devs[ST_LSM6DSX_ID_ACC]);
20531aabad1fSSean Nyekjaer 	if ((data & hw->settings->event_settings.wakeup_src_z_mask) &&
20541aabad1fSSean Nyekjaer 	    (hw->enable_event & BIT(IIO_MOD_Z)))
20551aabad1fSSean Nyekjaer 		iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC],
20561aabad1fSSean Nyekjaer 			       IIO_MOD_EVENT_CODE(IIO_ACCEL,
20571aabad1fSSean Nyekjaer 						  0,
20581aabad1fSSean Nyekjaer 						  IIO_MOD_Z,
20591aabad1fSSean Nyekjaer 						  IIO_EV_TYPE_THRESH,
20601aabad1fSSean Nyekjaer 						  IIO_EV_DIR_EITHER),
20611aabad1fSSean Nyekjaer 						  timestamp);
20621aabad1fSSean Nyekjaer 
20631aabad1fSSean Nyekjaer 	if ((data & hw->settings->event_settings.wakeup_src_y_mask) &&
20641aabad1fSSean Nyekjaer 	    (hw->enable_event & BIT(IIO_MOD_Y)))
20651aabad1fSSean Nyekjaer 		iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC],
20661aabad1fSSean Nyekjaer 			       IIO_MOD_EVENT_CODE(IIO_ACCEL,
20671aabad1fSSean Nyekjaer 						  0,
20681aabad1fSSean Nyekjaer 						  IIO_MOD_Y,
20691aabad1fSSean Nyekjaer 						  IIO_EV_TYPE_THRESH,
20701aabad1fSSean Nyekjaer 						  IIO_EV_DIR_EITHER),
20711aabad1fSSean Nyekjaer 						  timestamp);
20721aabad1fSSean Nyekjaer 
20731aabad1fSSean Nyekjaer 	if ((data & hw->settings->event_settings.wakeup_src_x_mask) &&
20741aabad1fSSean Nyekjaer 	    (hw->enable_event & BIT(IIO_MOD_X)))
20751aabad1fSSean Nyekjaer 		iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC],
20761aabad1fSSean Nyekjaer 			       IIO_MOD_EVENT_CODE(IIO_ACCEL,
20771aabad1fSSean Nyekjaer 						  0,
20781aabad1fSSean Nyekjaer 						  IIO_MOD_X,
20791aabad1fSSean Nyekjaer 						  IIO_EV_TYPE_THRESH,
20801aabad1fSSean Nyekjaer 						  IIO_EV_DIR_EITHER),
20811aabad1fSSean Nyekjaer 						  timestamp);
2082615bd378SLorenzo Bianconi 
2083615bd378SLorenzo Bianconi 	return data & event_settings->wakeup_src_status_mask;
20841aabad1fSSean Nyekjaer }
20851aabad1fSSean Nyekjaer 
20866ee6a368SSean Nyekjaer static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private)
20876ee6a368SSean Nyekjaer {
20886ee6a368SSean Nyekjaer 	struct st_lsm6dsx_hw *hw = private;
20893f9bce7aSLorenzo Bianconi 	int fifo_len = 0, len;
2090615bd378SLorenzo Bianconi 	bool event;
20911aabad1fSSean Nyekjaer 
2092615bd378SLorenzo Bianconi 	event = st_lsm6dsx_report_motion_event(hw);
20936ee6a368SSean Nyekjaer 
2094a912ee4cSLorenzo Bianconi 	if (!hw->settings->fifo_ops.read_fifo)
2095a912ee4cSLorenzo Bianconi 		return event ? IRQ_HANDLED : IRQ_NONE;
2096a912ee4cSLorenzo Bianconi 
20973f9bce7aSLorenzo Bianconi 	/*
20983f9bce7aSLorenzo Bianconi 	 * If we are using edge IRQs, new samples can arrive while
20993f9bce7aSLorenzo Bianconi 	 * processing current interrupt since there are no hw
21003f9bce7aSLorenzo Bianconi 	 * guarantees the irq line stays "low" long enough to properly
21013f9bce7aSLorenzo Bianconi 	 * detect the new interrupt. In this case the new sample will
21023f9bce7aSLorenzo Bianconi 	 * be missed.
21033f9bce7aSLorenzo Bianconi 	 * Polling FIFO status register allow us to read new
21043f9bce7aSLorenzo Bianconi 	 * samples even if the interrupt arrives while processing
21053f9bce7aSLorenzo Bianconi 	 * previous data and the timeslot where the line is "low" is
21063f9bce7aSLorenzo Bianconi 	 * too short to be properly detected.
21073f9bce7aSLorenzo Bianconi 	 */
21083f9bce7aSLorenzo Bianconi 	do {
21096ee6a368SSean Nyekjaer 		mutex_lock(&hw->fifo_lock);
21103f9bce7aSLorenzo Bianconi 		len = hw->settings->fifo_ops.read_fifo(hw);
21116ee6a368SSean Nyekjaer 		mutex_unlock(&hw->fifo_lock);
21126ee6a368SSean Nyekjaer 
21133f9bce7aSLorenzo Bianconi 		if (len > 0)
21143f9bce7aSLorenzo Bianconi 			fifo_len += len;
21153f9bce7aSLorenzo Bianconi 	} while (len > 0);
21163f9bce7aSLorenzo Bianconi 
21173f9bce7aSLorenzo Bianconi 	return fifo_len || event ? IRQ_HANDLED : IRQ_NONE;
21186ee6a368SSean Nyekjaer }
21196ee6a368SSean Nyekjaer 
21206ee6a368SSean Nyekjaer static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw)
21216ee6a368SSean Nyekjaer {
212231fe8d4eSLorenzo Bianconi 	struct st_sensors_platform_data *pdata;
212331fe8d4eSLorenzo Bianconi 	const struct st_lsm6dsx_reg *reg;
212403d4c566SAndy Shevchenko 	struct device *dev = hw->dev;
21256ee6a368SSean Nyekjaer 	unsigned long irq_type;
21266ee6a368SSean Nyekjaer 	bool irq_active_low;
21276ee6a368SSean Nyekjaer 	int err;
21286ee6a368SSean Nyekjaer 
21296ee6a368SSean Nyekjaer 	irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
21306ee6a368SSean Nyekjaer 
21316ee6a368SSean Nyekjaer 	switch (irq_type) {
21326ee6a368SSean Nyekjaer 	case IRQF_TRIGGER_HIGH:
21336ee6a368SSean Nyekjaer 	case IRQF_TRIGGER_RISING:
21346ee6a368SSean Nyekjaer 		irq_active_low = false;
21356ee6a368SSean Nyekjaer 		break;
21366ee6a368SSean Nyekjaer 	case IRQF_TRIGGER_LOW:
21376ee6a368SSean Nyekjaer 	case IRQF_TRIGGER_FALLING:
21386ee6a368SSean Nyekjaer 		irq_active_low = true;
21396ee6a368SSean Nyekjaer 		break;
21406ee6a368SSean Nyekjaer 	default:
21416ee6a368SSean Nyekjaer 		dev_info(hw->dev, "mode %lx unsupported\n", irq_type);
21426ee6a368SSean Nyekjaer 		return -EINVAL;
21436ee6a368SSean Nyekjaer 	}
21446ee6a368SSean Nyekjaer 
214531fe8d4eSLorenzo Bianconi 	reg = &hw->settings->irq_config.hla;
214631fe8d4eSLorenzo Bianconi 	err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
214731fe8d4eSLorenzo Bianconi 				 ST_LSM6DSX_SHIFT_VAL(irq_active_low,
214831fe8d4eSLorenzo Bianconi 						      reg->mask));
21496ee6a368SSean Nyekjaer 	if (err < 0)
21506ee6a368SSean Nyekjaer 		return err;
21516ee6a368SSean Nyekjaer 
215203d4c566SAndy Shevchenko 	pdata = (struct st_sensors_platform_data *)dev->platform_data;
215303d4c566SAndy Shevchenko 	if ((dev_fwnode(dev) && device_property_read_bool(dev, "drive-open-drain")) ||
21546ee6a368SSean Nyekjaer 	    (pdata && pdata->open_drain)) {
215531fe8d4eSLorenzo Bianconi 		reg = &hw->settings->irq_config.od;
215631fe8d4eSLorenzo Bianconi 		err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
215731fe8d4eSLorenzo Bianconi 					 ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
21586ee6a368SSean Nyekjaer 		if (err < 0)
21596ee6a368SSean Nyekjaer 			return err;
21606ee6a368SSean Nyekjaer 
21616ee6a368SSean Nyekjaer 		irq_type |= IRQF_SHARED;
21626ee6a368SSean Nyekjaer 	}
21636ee6a368SSean Nyekjaer 
21646ee6a368SSean Nyekjaer 	err = devm_request_threaded_irq(hw->dev, hw->irq,
2165a3aa17d4SSean Nyekjaer 					NULL,
21666ee6a368SSean Nyekjaer 					st_lsm6dsx_handler_thread,
21676ee6a368SSean Nyekjaer 					irq_type | IRQF_ONESHOT,
21686ee6a368SSean Nyekjaer 					"lsm6dsx", hw);
21696ee6a368SSean Nyekjaer 	if (err) {
21706ee6a368SSean Nyekjaer 		dev_err(hw->dev, "failed to request trigger irq %d\n",
21716ee6a368SSean Nyekjaer 			hw->irq);
21726ee6a368SSean Nyekjaer 		return err;
21736ee6a368SSean Nyekjaer 	}
21746ee6a368SSean Nyekjaer 
21756ee6a368SSean Nyekjaer 	return 0;
21766ee6a368SSean Nyekjaer }
21776ee6a368SSean Nyekjaer 
2178f346b16fSLorenzo Bianconi static int st_lsm6dsx_init_regulators(struct device *dev)
2179f346b16fSLorenzo Bianconi {
2180f346b16fSLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev);
2181f346b16fSLorenzo Bianconi 	int err;
2182f346b16fSLorenzo Bianconi 
2183f346b16fSLorenzo Bianconi 	/* vdd-vddio power regulators */
2184f346b16fSLorenzo Bianconi 	hw->regulators[0].supply = "vdd";
2185f346b16fSLorenzo Bianconi 	hw->regulators[1].supply = "vddio";
2186f346b16fSLorenzo Bianconi 	err = devm_regulator_bulk_get(dev, ARRAY_SIZE(hw->regulators),
2187f346b16fSLorenzo Bianconi 				      hw->regulators);
2188f346b16fSLorenzo Bianconi 	if (err)
2189f346b16fSLorenzo Bianconi 		return dev_err_probe(dev, err, "failed to get regulators\n");
2190f346b16fSLorenzo Bianconi 
2191f346b16fSLorenzo Bianconi 	err = regulator_bulk_enable(ARRAY_SIZE(hw->regulators),
2192f346b16fSLorenzo Bianconi 				    hw->regulators);
2193f346b16fSLorenzo Bianconi 	if (err) {
2194f346b16fSLorenzo Bianconi 		dev_err(dev, "failed to enable regulators: %d\n", err);
2195f346b16fSLorenzo Bianconi 		return err;
2196f346b16fSLorenzo Bianconi 	}
2197f346b16fSLorenzo Bianconi 
2198f346b16fSLorenzo Bianconi 	msleep(50);
2199f346b16fSLorenzo Bianconi 
2200f346b16fSLorenzo Bianconi 	return 0;
2201f346b16fSLorenzo Bianconi }
2202f346b16fSLorenzo Bianconi 
2203f346b16fSLorenzo Bianconi static void st_lsm6dsx_chip_uninit(void *data)
2204f346b16fSLorenzo Bianconi {
2205f346b16fSLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = data;
2206f346b16fSLorenzo Bianconi 
2207f346b16fSLorenzo Bianconi 	regulator_bulk_disable(ARRAY_SIZE(hw->regulators), hw->regulators);
2208f346b16fSLorenzo Bianconi }
2209f346b16fSLorenzo Bianconi 
221081956a93SLorenzo Bianconi int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
221151a8b707SLorenzo Bianconi 		     struct regmap *regmap)
2212290a6ce1SLorenzo Bianconi {
2213b7a73b33SLorenzo Bianconi 	struct st_sensors_platform_data *pdata = dev->platform_data;
2214c91c1c84SLorenzo Bianconi 	const struct st_lsm6dsx_shub_settings *hub_settings;
2215290a6ce1SLorenzo Bianconi 	struct st_lsm6dsx_hw *hw;
221681956a93SLorenzo Bianconi 	const char *name = NULL;
2217290a6ce1SLorenzo Bianconi 	int i, err;
2218290a6ce1SLorenzo Bianconi 
2219290a6ce1SLorenzo Bianconi 	hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
2220290a6ce1SLorenzo Bianconi 	if (!hw)
2221290a6ce1SLorenzo Bianconi 		return -ENOMEM;
2222290a6ce1SLorenzo Bianconi 
2223290a6ce1SLorenzo Bianconi 	dev_set_drvdata(dev, (void *)hw);
2224290a6ce1SLorenzo Bianconi 
2225290a6ce1SLorenzo Bianconi 	mutex_init(&hw->fifo_lock);
2226335eaedcSLorenzo Bianconi 	mutex_init(&hw->conf_lock);
2227739aff87SLorenzo Bianconi 	mutex_init(&hw->page_lock);
2228290a6ce1SLorenzo Bianconi 
2229f346b16fSLorenzo Bianconi 	err = st_lsm6dsx_init_regulators(dev);
2230f346b16fSLorenzo Bianconi 	if (err)
2231f346b16fSLorenzo Bianconi 		return err;
2232f346b16fSLorenzo Bianconi 
2233f346b16fSLorenzo Bianconi 	err = devm_add_action_or_reset(dev, st_lsm6dsx_chip_uninit, hw);
2234f346b16fSLorenzo Bianconi 	if (err)
2235f346b16fSLorenzo Bianconi 		return err;
2236f346b16fSLorenzo Bianconi 
223791a6b841SLorenzo Bianconi 	hw->buff = devm_kzalloc(dev, ST_LSM6DSX_BUFF_SIZE, GFP_KERNEL);
223891a6b841SLorenzo Bianconi 	if (!hw->buff)
223991a6b841SLorenzo Bianconi 		return -ENOMEM;
224091a6b841SLorenzo Bianconi 
2241290a6ce1SLorenzo Bianconi 	hw->dev = dev;
2242290a6ce1SLorenzo Bianconi 	hw->irq = irq;
224351a8b707SLorenzo Bianconi 	hw->regmap = regmap;
2244290a6ce1SLorenzo Bianconi 
224581956a93SLorenzo Bianconi 	err = st_lsm6dsx_check_whoami(hw, hw_id, &name);
2246290a6ce1SLorenzo Bianconi 	if (err < 0)
2247290a6ce1SLorenzo Bianconi 		return err;
2248290a6ce1SLorenzo Bianconi 
22496ffb55e5SLorenzo Bianconi 	for (i = 0; i < ST_LSM6DSX_ID_EXT0; i++) {
2250510c0106SLorenzo Bianconi 		hw->iio_devs[i] = st_lsm6dsx_alloc_iiodev(hw, i, name);
2251290a6ce1SLorenzo Bianconi 		if (!hw->iio_devs[i])
2252290a6ce1SLorenzo Bianconi 			return -ENOMEM;
2253290a6ce1SLorenzo Bianconi 	}
2254290a6ce1SLorenzo Bianconi 
2255290a6ce1SLorenzo Bianconi 	err = st_lsm6dsx_init_device(hw);
2256290a6ce1SLorenzo Bianconi 	if (err < 0)
2257290a6ce1SLorenzo Bianconi 		return err;
2258290a6ce1SLorenzo Bianconi 
2259c91c1c84SLorenzo Bianconi 	hub_settings = &hw->settings->shub_settings;
226035619155SLorenzo Bianconi 	if (hub_settings->master_en.addr &&
226135619155SLorenzo Bianconi 	    (!dev_fwnode(dev) ||
226235619155SLorenzo Bianconi 	     !device_property_read_bool(dev, "st,disable-sensor-hub"))) {
2263c91c1c84SLorenzo Bianconi 		err = st_lsm6dsx_shub_probe(hw, name);
2264c91c1c84SLorenzo Bianconi 		if (err < 0)
2265c91c1c84SLorenzo Bianconi 			return err;
2266c91c1c84SLorenzo Bianconi 	}
2267c91c1c84SLorenzo Bianconi 
2268290a6ce1SLorenzo Bianconi 	if (hw->irq > 0) {
22696ee6a368SSean Nyekjaer 		err = st_lsm6dsx_irq_setup(hw);
22706ee6a368SSean Nyekjaer 		if (err < 0)
22716ee6a368SSean Nyekjaer 			return err;
22726ee6a368SSean Nyekjaer 
2273290a6ce1SLorenzo Bianconi 		err = st_lsm6dsx_fifo_setup(hw);
2274290a6ce1SLorenzo Bianconi 		if (err < 0)
2275290a6ce1SLorenzo Bianconi 			return err;
2276290a6ce1SLorenzo Bianconi 	}
2277290a6ce1SLorenzo Bianconi 
2278b892770aSAndy Shevchenko 	err = iio_read_mount_matrix(hw->dev, &hw->orientation);
227904e6fedbSMartin Kepplinger 	if (err)
228004e6fedbSMartin Kepplinger 		return err;
228104e6fedbSMartin Kepplinger 
2282290a6ce1SLorenzo Bianconi 	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
22836ffb55e5SLorenzo Bianconi 		if (!hw->iio_devs[i])
22846ffb55e5SLorenzo Bianconi 			continue;
22856ffb55e5SLorenzo Bianconi 
2286290a6ce1SLorenzo Bianconi 		err = devm_iio_device_register(hw->dev, hw->iio_devs[i]);
2287290a6ce1SLorenzo Bianconi 		if (err)
2288290a6ce1SLorenzo Bianconi 			return err;
2289290a6ce1SLorenzo Bianconi 	}
2290290a6ce1SLorenzo Bianconi 
229103d4c566SAndy Shevchenko 	if ((dev_fwnode(dev) && device_property_read_bool(dev, "wakeup-source")) ||
2292b7a73b33SLorenzo Bianconi 	    (pdata && pdata->wakeup_source))
22934c997dfaSSean Nyekjaer 		device_init_wakeup(dev, true);
22944c997dfaSSean Nyekjaer 
2295290a6ce1SLorenzo Bianconi 	return 0;
2296290a6ce1SLorenzo Bianconi }
22972b059449SJonathan Cameron EXPORT_SYMBOL_NS(st_lsm6dsx_probe, IIO_LSM6DSX);
2298290a6ce1SLorenzo Bianconi 
2299acc416ffSJonathan Cameron static int st_lsm6dsx_suspend(struct device *dev)
2300d3f77058SLorenzo Bianconi {
2301d3f77058SLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev);
2302d3f77058SLorenzo Bianconi 	struct st_lsm6dsx_sensor *sensor;
2303d3f77058SLorenzo Bianconi 	int i, err = 0;
2304d3f77058SLorenzo Bianconi 
2305d3f77058SLorenzo Bianconi 	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
23066ffb55e5SLorenzo Bianconi 		if (!hw->iio_devs[i])
23076ffb55e5SLorenzo Bianconi 			continue;
23086ffb55e5SLorenzo Bianconi 
2309d3f77058SLorenzo Bianconi 		sensor = iio_priv(hw->iio_devs[i]);
2310d3f77058SLorenzo Bianconi 		if (!(hw->enable_mask & BIT(sensor->id)))
2311d3f77058SLorenzo Bianconi 			continue;
2312d3f77058SLorenzo Bianconi 
23134c997dfaSSean Nyekjaer 		if (device_may_wakeup(dev) &&
23144c997dfaSSean Nyekjaer 		    sensor->id == ST_LSM6DSX_ID_ACC && hw->enable_event) {
23154c997dfaSSean Nyekjaer 			/* Enable wake from IRQ */
23164c997dfaSSean Nyekjaer 			enable_irq_wake(hw->irq);
23174c997dfaSSean Nyekjaer 			continue;
23184c997dfaSSean Nyekjaer 		}
23194c997dfaSSean Nyekjaer 
2320*cd83c5c1SLorenzo Bianconi 		err = st_lsm6dsx_device_set_enable(sensor, false);
2321d3f77058SLorenzo Bianconi 		if (err < 0)
2322d3f77058SLorenzo Bianconi 			return err;
2323bce0d57dSLorenzo Bianconi 
2324bce0d57dSLorenzo Bianconi 		hw->suspend_mask |= BIT(sensor->id);
2325d3f77058SLorenzo Bianconi 	}
2326d3f77058SLorenzo Bianconi 
2327c2686eb2SLorenzo Bianconi 	if (hw->fifo_mask)
2328d3f77058SLorenzo Bianconi 		err = st_lsm6dsx_flush_fifo(hw);
2329d3f77058SLorenzo Bianconi 
2330d3f77058SLorenzo Bianconi 	return err;
2331d3f77058SLorenzo Bianconi }
2332d3f77058SLorenzo Bianconi 
2333acc416ffSJonathan Cameron static int st_lsm6dsx_resume(struct device *dev)
2334d3f77058SLorenzo Bianconi {
2335d3f77058SLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev);
2336d3f77058SLorenzo Bianconi 	struct st_lsm6dsx_sensor *sensor;
2337d3f77058SLorenzo Bianconi 	int i, err = 0;
2338d3f77058SLorenzo Bianconi 
2339d3f77058SLorenzo Bianconi 	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
23406ffb55e5SLorenzo Bianconi 		if (!hw->iio_devs[i])
23416ffb55e5SLorenzo Bianconi 			continue;
23426ffb55e5SLorenzo Bianconi 
2343d3f77058SLorenzo Bianconi 		sensor = iio_priv(hw->iio_devs[i]);
23444c997dfaSSean Nyekjaer 		if (device_may_wakeup(dev) &&
23454c997dfaSSean Nyekjaer 		    sensor->id == ST_LSM6DSX_ID_ACC && hw->enable_event)
23464c997dfaSSean Nyekjaer 			disable_irq_wake(hw->irq);
23474c997dfaSSean Nyekjaer 
2348bce0d57dSLorenzo Bianconi 		if (!(hw->suspend_mask & BIT(sensor->id)))
2349d3f77058SLorenzo Bianconi 			continue;
2350d3f77058SLorenzo Bianconi 
2351*cd83c5c1SLorenzo Bianconi 		err = st_lsm6dsx_device_set_enable(sensor, true);
2352d3f77058SLorenzo Bianconi 		if (err < 0)
2353d3f77058SLorenzo Bianconi 			return err;
2354bce0d57dSLorenzo Bianconi 
2355bce0d57dSLorenzo Bianconi 		hw->suspend_mask &= ~BIT(sensor->id);
2356d3f77058SLorenzo Bianconi 	}
2357d3f77058SLorenzo Bianconi 
2358c2686eb2SLorenzo Bianconi 	if (hw->fifo_mask)
2359a1bab939SLorenzo Bianconi 		err = st_lsm6dsx_resume_fifo(hw);
2360d3f77058SLorenzo Bianconi 
2361d3f77058SLorenzo Bianconi 	return err;
2362d3f77058SLorenzo Bianconi }
2363d3f77058SLorenzo Bianconi 
23642b059449SJonathan Cameron EXPORT_NS_SIMPLE_DEV_PM_OPS(st_lsm6dsx_pm_ops, st_lsm6dsx_suspend,
23652b059449SJonathan Cameron 			    st_lsm6dsx_resume, IIO_LSM6DSX);
2366d3f77058SLorenzo Bianconi 
2367290a6ce1SLorenzo Bianconi MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
2368290a6ce1SLorenzo Bianconi MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
2369290a6ce1SLorenzo Bianconi MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx driver");
2370290a6ce1SLorenzo Bianconi MODULE_LICENSE("GPL v2");
2371