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  *
29*fdd70d7aSLorenzo Bianconi  * - LSM6DSO/LSM6DSOX/ASM330LHH/ASM330LHHX/LSM6DSR/ISM330DHCX/LSM6DST/LSM6DSOP:
30f7d5c18aSSean Nyekjaer  *   - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416,
318f9a5249SLorenzo Bianconi  *     833
32801a6e0aSLorenzo Bianconi  *   - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
33801a6e0aSLorenzo Bianconi  *   - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
34801a6e0aSLorenzo Bianconi  *   - FIFO size: 3KB
35801a6e0aSLorenzo Bianconi  *
36fa060a3dSLorenzo Bianconi  * - LSM9DS1/LSM6DS0:
3752f4b1f1SMartin Kepplinger  *   - Accelerometer supported ODR [Hz]: 10, 50, 119, 238, 476, 952
3852f4b1f1SMartin Kepplinger  *   - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
3952f4b1f1SMartin Kepplinger  *   - Gyroscope supported ODR [Hz]: 15, 60, 119, 238, 476, 952
4052f4b1f1SMartin Kepplinger  *   - Gyroscope supported full-scale [dps]: +-245/+-500/+-2000
4152f4b1f1SMartin Kepplinger  *   - FIFO size: 32
4252f4b1f1SMartin Kepplinger  *
43290a6ce1SLorenzo Bianconi  * Copyright 2016 STMicroelectronics Inc.
44290a6ce1SLorenzo Bianconi  *
45290a6ce1SLorenzo Bianconi  * Lorenzo Bianconi <lorenzo.bianconi@st.com>
46290a6ce1SLorenzo Bianconi  * Denis Ciocca <denis.ciocca@st.com>
47290a6ce1SLorenzo Bianconi  */
48290a6ce1SLorenzo Bianconi 
49290a6ce1SLorenzo Bianconi #include <linux/kernel.h>
50290a6ce1SLorenzo Bianconi #include <linux/module.h>
51290a6ce1SLorenzo Bianconi #include <linux/delay.h>
521aabad1fSSean Nyekjaer #include <linux/iio/events.h>
53290a6ce1SLorenzo Bianconi #include <linux/iio/iio.h>
54290a6ce1SLorenzo Bianconi #include <linux/iio/sysfs.h>
556ee6a368SSean Nyekjaer #include <linux/interrupt.h>
566ee6a368SSean Nyekjaer #include <linux/irq.h>
57d3f77058SLorenzo Bianconi #include <linux/pm.h>
5803d4c566SAndy Shevchenko #include <linux/property.h>
5951a8b707SLorenzo Bianconi #include <linux/regmap.h>
6051a8b707SLorenzo Bianconi #include <linux/bitfield.h>
61290a6ce1SLorenzo Bianconi 
62dba32904SLorenzo Bianconi #include <linux/platform_data/st_sensors_pdata.h>
63dba32904SLorenzo Bianconi 
64290a6ce1SLorenzo Bianconi #include "st_lsm6dsx.h"
65290a6ce1SLorenzo Bianconi 
66290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_WHOAMI_ADDR		0x0f
67290a6ce1SLorenzo Bianconi 
68cb3b6b8eSMario Tesi #define ST_LSM6DSX_TS_SENSITIVITY		25000UL /* 25us */
69cb3b6b8eSMario Tesi 
70f48bc49bSLorenzo Bianconi static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = {
71b5969abfSSean Nyekjaer 	ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x28, IIO_MOD_X, 0),
72b5969abfSSean Nyekjaer 	ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1),
73b5969abfSSean Nyekjaer 	ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x2c, IIO_MOD_Z, 2),
74f48bc49bSLorenzo Bianconi 	IIO_CHAN_SOFT_TIMESTAMP(3),
75f48bc49bSLorenzo Bianconi };
76f48bc49bSLorenzo Bianconi 
77f48bc49bSLorenzo Bianconi static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = {
78f48bc49bSLorenzo Bianconi 	ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x22, IIO_MOD_X, 0),
79f48bc49bSLorenzo Bianconi 	ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x24, IIO_MOD_Y, 1),
80f48bc49bSLorenzo Bianconi 	ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x26, IIO_MOD_Z, 2),
81f48bc49bSLorenzo Bianconi 	IIO_CHAN_SOFT_TIMESTAMP(3),
82f48bc49bSLorenzo Bianconi };
83f48bc49bSLorenzo Bianconi 
8452f4b1f1SMartin Kepplinger static const struct iio_chan_spec st_lsm6ds0_gyro_channels[] = {
8552f4b1f1SMartin Kepplinger 	ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x18, IIO_MOD_X, 0),
8652f4b1f1SMartin Kepplinger 	ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x1a, IIO_MOD_Y, 1),
8752f4b1f1SMartin Kepplinger 	ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x1c, IIO_MOD_Z, 2),
8852f4b1f1SMartin Kepplinger 	IIO_CHAN_SOFT_TIMESTAMP(3),
8952f4b1f1SMartin Kepplinger };
9052f4b1f1SMartin Kepplinger 
91290a6ce1SLorenzo Bianconi static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
92290a6ce1SLorenzo Bianconi 	{
9366b662a1SLorenzo Bianconi 		.reset = {
9466b662a1SLorenzo Bianconi 			.addr = 0x22,
9566b662a1SLorenzo Bianconi 			.mask = BIT(0),
9666b662a1SLorenzo Bianconi 		},
9766b662a1SLorenzo Bianconi 		.boot = {
9866b662a1SLorenzo Bianconi 			.addr = 0x22,
9966b662a1SLorenzo Bianconi 			.mask = BIT(7),
10066b662a1SLorenzo Bianconi 		},
10166b662a1SLorenzo Bianconi 		.bdu = {
10266b662a1SLorenzo Bianconi 			.addr = 0x22,
10366b662a1SLorenzo Bianconi 			.mask = BIT(6),
10466b662a1SLorenzo Bianconi 		},
10552f4b1f1SMartin Kepplinger 		.id = {
10652f4b1f1SMartin Kepplinger 			{
10752f4b1f1SMartin Kepplinger 				.hw_id = ST_LSM9DS1_ID,
10852f4b1f1SMartin Kepplinger 				.name = ST_LSM9DS1_DEV_NAME,
10998c3544aSLorenzo Bianconi 				.wai = 0x68,
110fa060a3dSLorenzo Bianconi 			}, {
111fa060a3dSLorenzo Bianconi 				.hw_id = ST_LSM6DS0_ID,
112fa060a3dSLorenzo Bianconi 				.name = ST_LSM6DS0_DEV_NAME,
11398c3544aSLorenzo Bianconi 				.wai = 0x68,
11452f4b1f1SMartin Kepplinger 			},
11552f4b1f1SMartin Kepplinger 		},
11652f4b1f1SMartin Kepplinger 		.channels = {
11752f4b1f1SMartin Kepplinger 			[ST_LSM6DSX_ID_ACC] = {
11852f4b1f1SMartin Kepplinger 				.chan = st_lsm6dsx_acc_channels,
11952f4b1f1SMartin Kepplinger 				.len = ARRAY_SIZE(st_lsm6dsx_acc_channels),
12052f4b1f1SMartin Kepplinger 			},
12152f4b1f1SMartin Kepplinger 			[ST_LSM6DSX_ID_GYRO] = {
12252f4b1f1SMartin Kepplinger 				.chan = st_lsm6ds0_gyro_channels,
12352f4b1f1SMartin Kepplinger 				.len = ARRAY_SIZE(st_lsm6ds0_gyro_channels),
12452f4b1f1SMartin Kepplinger 			},
12552f4b1f1SMartin Kepplinger 		},
12652f4b1f1SMartin Kepplinger 		.odr_table = {
12752f4b1f1SMartin Kepplinger 			[ST_LSM6DSX_ID_ACC] = {
12852f4b1f1SMartin Kepplinger 				.reg = {
12952f4b1f1SMartin Kepplinger 					.addr = 0x20,
13052f4b1f1SMartin Kepplinger 					.mask = GENMASK(7, 5),
13152f4b1f1SMartin Kepplinger 				},
132f8710f03SLorenzo Bianconi 				.odr_avl[0] = {  10000, 0x01 },
133f8710f03SLorenzo Bianconi 				.odr_avl[1] = {  50000, 0x02 },
134f8710f03SLorenzo Bianconi 				.odr_avl[2] = { 119000, 0x03 },
135f8710f03SLorenzo Bianconi 				.odr_avl[3] = { 238000, 0x04 },
136f8710f03SLorenzo Bianconi 				.odr_avl[4] = { 476000, 0x05 },
137f8710f03SLorenzo Bianconi 				.odr_avl[5] = { 952000, 0x06 },
13859af4e20SLorenzo Bianconi 				.odr_len = 6,
13952f4b1f1SMartin Kepplinger 			},
14052f4b1f1SMartin Kepplinger 			[ST_LSM6DSX_ID_GYRO] = {
14152f4b1f1SMartin Kepplinger 				.reg = {
14252f4b1f1SMartin Kepplinger 					.addr = 0x10,
14352f4b1f1SMartin Kepplinger 					.mask = GENMASK(7, 5),
14452f4b1f1SMartin Kepplinger 				},
145f8710f03SLorenzo Bianconi 				.odr_avl[0] = {  14900, 0x01 },
146f8710f03SLorenzo Bianconi 				.odr_avl[1] = {  59500, 0x02 },
147f8710f03SLorenzo Bianconi 				.odr_avl[2] = { 119000, 0x03 },
148f8710f03SLorenzo Bianconi 				.odr_avl[3] = { 238000, 0x04 },
149f8710f03SLorenzo Bianconi 				.odr_avl[4] = { 476000, 0x05 },
150f8710f03SLorenzo Bianconi 				.odr_avl[5] = { 952000, 0x06 },
15159af4e20SLorenzo Bianconi 				.odr_len = 6,
15252f4b1f1SMartin Kepplinger 			},
15352f4b1f1SMartin Kepplinger 		},
15452f4b1f1SMartin Kepplinger 		.fs_table = {
15552f4b1f1SMartin Kepplinger 			[ST_LSM6DSX_ID_ACC] = {
15652f4b1f1SMartin Kepplinger 				.reg = {
15752f4b1f1SMartin Kepplinger 					.addr = 0x20,
15852f4b1f1SMartin Kepplinger 					.mask = GENMASK(4, 3),
15952f4b1f1SMartin Kepplinger 				},
16044a76de8SMario Tesi 				.fs_avl[0] = {  IIO_G_TO_M_S_2(61000), 0x0 },
16144a76de8SMario Tesi 				.fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 },
16244a76de8SMario Tesi 				.fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 },
16344a76de8SMario Tesi 				.fs_avl[3] = { IIO_G_TO_M_S_2(732000), 0x1 },
16485ae3aeeSLorenzo Bianconi 				.fs_len = 4,
16552f4b1f1SMartin Kepplinger 			},
16652f4b1f1SMartin Kepplinger 			[ST_LSM6DSX_ID_GYRO] = {
16752f4b1f1SMartin Kepplinger 				.reg = {
16852f4b1f1SMartin Kepplinger 					.addr = 0x10,
16952f4b1f1SMartin Kepplinger 					.mask = GENMASK(4, 3),
17052f4b1f1SMartin Kepplinger 				},
1711b375101SLorenzo Bianconi 
17244a76de8SMario Tesi 				.fs_avl[0] = {  IIO_DEGREE_TO_RAD(8750000), 0x0 },
17344a76de8SMario Tesi 				.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 },
17444a76de8SMario Tesi 				.fs_avl[2] = { IIO_DEGREE_TO_RAD(70000000), 0x3 },
17585ae3aeeSLorenzo Bianconi 				.fs_len = 3,
17652f4b1f1SMartin Kepplinger 			},
17752f4b1f1SMartin Kepplinger 		},
1787e906103SLorenzo Bianconi 		.irq_config = {
1797e906103SLorenzo Bianconi 			.irq1 = {
1807e906103SLorenzo Bianconi 				.addr = 0x0c,
1817e906103SLorenzo Bianconi 				.mask = BIT(3),
1827e906103SLorenzo Bianconi 			},
1837e906103SLorenzo Bianconi 			.irq2 = {
1847e906103SLorenzo Bianconi 				.addr = 0x0d,
1857e906103SLorenzo Bianconi 				.mask = BIT(3),
1867e906103SLorenzo Bianconi 			},
18731fe8d4eSLorenzo Bianconi 			.hla = {
18831fe8d4eSLorenzo Bianconi 				.addr = 0x22,
18931fe8d4eSLorenzo Bianconi 				.mask = BIT(5),
19031fe8d4eSLorenzo Bianconi 			},
19131fe8d4eSLorenzo Bianconi 			.od = {
19231fe8d4eSLorenzo Bianconi 				.addr = 0x22,
19331fe8d4eSLorenzo Bianconi 				.mask = BIT(4),
19431fe8d4eSLorenzo Bianconi 			},
1957e906103SLorenzo Bianconi 		},
1961b7da2faSLorenzo Bianconi 		.fifo_ops = {
1971b7da2faSLorenzo Bianconi 			.max_size = 32,
1981b7da2faSLorenzo Bianconi 		},
19952f4b1f1SMartin Kepplinger 	},
20052f4b1f1SMartin Kepplinger 	{
20166b662a1SLorenzo Bianconi 		.reset = {
20266b662a1SLorenzo Bianconi 			.addr = 0x12,
20366b662a1SLorenzo Bianconi 			.mask = BIT(0),
20466b662a1SLorenzo Bianconi 		},
20566b662a1SLorenzo Bianconi 		.boot = {
20666b662a1SLorenzo Bianconi 			.addr = 0x12,
20766b662a1SLorenzo Bianconi 			.mask = BIT(7),
20866b662a1SLorenzo Bianconi 		},
20966b662a1SLorenzo Bianconi 		.bdu = {
21066b662a1SLorenzo Bianconi 			.addr = 0x12,
21166b662a1SLorenzo Bianconi 			.mask = BIT(6),
21266b662a1SLorenzo Bianconi 		},
213d068e4a0SLorenzo Bianconi 		.id = {
21481956a93SLorenzo Bianconi 			{
21581956a93SLorenzo Bianconi 				.hw_id = ST_LSM6DS3_ID,
21681956a93SLorenzo Bianconi 				.name = ST_LSM6DS3_DEV_NAME,
21798c3544aSLorenzo Bianconi 				.wai = 0x69,
21881956a93SLorenzo Bianconi 			},
219d068e4a0SLorenzo Bianconi 		},
220f48bc49bSLorenzo Bianconi 		.channels = {
221f48bc49bSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
222f48bc49bSLorenzo Bianconi 				.chan = st_lsm6dsx_acc_channels,
223f48bc49bSLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_acc_channels),
224f48bc49bSLorenzo Bianconi 			},
225f48bc49bSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
226f48bc49bSLorenzo Bianconi 				.chan = st_lsm6dsx_gyro_channels,
227f48bc49bSLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_gyro_channels),
228f48bc49bSLorenzo Bianconi 			},
229f48bc49bSLorenzo Bianconi 		},
23040dd7343SLorenzo Bianconi 		.odr_table = {
23140dd7343SLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
23240dd7343SLorenzo Bianconi 				.reg = {
23340dd7343SLorenzo Bianconi 					.addr = 0x10,
23440dd7343SLorenzo Bianconi 					.mask = GENMASK(7, 4),
23540dd7343SLorenzo Bianconi 				},
236f8710f03SLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
237f8710f03SLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
238f8710f03SLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
239f8710f03SLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
240f8710f03SLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
241f8710f03SLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
24259af4e20SLorenzo Bianconi 				.odr_len = 6,
24340dd7343SLorenzo Bianconi 			},
24440dd7343SLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
24540dd7343SLorenzo Bianconi 				.reg = {
24640dd7343SLorenzo Bianconi 					.addr = 0x11,
24740dd7343SLorenzo Bianconi 					.mask = GENMASK(7, 4),
24840dd7343SLorenzo Bianconi 				},
249f8710f03SLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
250f8710f03SLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
251f8710f03SLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
252f8710f03SLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
253f8710f03SLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
254f8710f03SLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
25559af4e20SLorenzo Bianconi 				.odr_len = 6,
25640dd7343SLorenzo Bianconi 			},
25740dd7343SLorenzo Bianconi 		},
258640aca3fSLorenzo Bianconi 		.fs_table = {
259640aca3fSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
260640aca3fSLorenzo Bianconi 				.reg = {
261640aca3fSLorenzo Bianconi 					.addr = 0x10,
262640aca3fSLorenzo Bianconi 					.mask = GENMASK(3, 2),
263640aca3fSLorenzo Bianconi 				},
26444a76de8SMario Tesi 				.fs_avl[0] = {  IIO_G_TO_M_S_2(61000), 0x0 },
26544a76de8SMario Tesi 				.fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 },
26644a76de8SMario Tesi 				.fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 },
26744a76de8SMario Tesi 				.fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 },
26885ae3aeeSLorenzo Bianconi 				.fs_len = 4,
269640aca3fSLorenzo Bianconi 			},
270640aca3fSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
271640aca3fSLorenzo Bianconi 				.reg = {
272640aca3fSLorenzo Bianconi 					.addr = 0x11,
273640aca3fSLorenzo Bianconi 					.mask = GENMASK(3, 2),
274640aca3fSLorenzo Bianconi 				},
27544a76de8SMario Tesi 				.fs_avl[0] = {  IIO_DEGREE_TO_RAD(8750000), 0x0 },
27644a76de8SMario Tesi 				.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 },
27744a76de8SMario Tesi 				.fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 },
27844a76de8SMario Tesi 				.fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 },
27985ae3aeeSLorenzo Bianconi 				.fs_len = 4,
280640aca3fSLorenzo Bianconi 			},
281640aca3fSLorenzo Bianconi 		},
2827e906103SLorenzo Bianconi 		.irq_config = {
2837e906103SLorenzo Bianconi 			.irq1 = {
2847e906103SLorenzo Bianconi 				.addr = 0x0d,
2857e906103SLorenzo Bianconi 				.mask = BIT(3),
2867e906103SLorenzo Bianconi 			},
2877e906103SLorenzo Bianconi 			.irq2 = {
2887e906103SLorenzo Bianconi 				.addr = 0x0e,
2897e906103SLorenzo Bianconi 				.mask = BIT(3),
2907e906103SLorenzo Bianconi 			},
2917e906103SLorenzo Bianconi 			.lir = {
2927e906103SLorenzo Bianconi 				.addr = 0x58,
2937e906103SLorenzo Bianconi 				.mask = BIT(0),
2947e906103SLorenzo Bianconi 			},
2957e906103SLorenzo Bianconi 			.irq1_func = {
2967e906103SLorenzo Bianconi 				.addr = 0x5e,
2977e906103SLorenzo Bianconi 				.mask = BIT(5),
2987e906103SLorenzo Bianconi 			},
2997e906103SLorenzo Bianconi 			.irq2_func = {
3007e906103SLorenzo Bianconi 				.addr = 0x5f,
3017e906103SLorenzo Bianconi 				.mask = BIT(5),
3027e906103SLorenzo Bianconi 			},
30331fe8d4eSLorenzo Bianconi 			.hla = {
30431fe8d4eSLorenzo Bianconi 				.addr = 0x12,
30531fe8d4eSLorenzo Bianconi 				.mask = BIT(5),
30631fe8d4eSLorenzo Bianconi 			},
30731fe8d4eSLorenzo Bianconi 			.od = {
30831fe8d4eSLorenzo Bianconi 				.addr = 0x12,
30931fe8d4eSLorenzo Bianconi 				.mask = BIT(4),
31031fe8d4eSLorenzo Bianconi 			},
3117e906103SLorenzo Bianconi 		},
3127ca3ac9eSLorenzo Bianconi 		.decimator = {
3137ca3ac9eSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
3147ca3ac9eSLorenzo Bianconi 				.addr = 0x08,
3157ca3ac9eSLorenzo Bianconi 				.mask = GENMASK(2, 0),
3167ca3ac9eSLorenzo Bianconi 			},
3177ca3ac9eSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
3187ca3ac9eSLorenzo Bianconi 				.addr = 0x08,
3197ca3ac9eSLorenzo Bianconi 				.mask = GENMASK(5, 3),
3207ca3ac9eSLorenzo Bianconi 			},
3217ca3ac9eSLorenzo Bianconi 		},
32292617c15SLorenzo Bianconi 		.fifo_ops = {
3233b72950dSLorenzo Bianconi 			.update_fifo = st_lsm6dsx_update_fifo,
32450ff457dSLorenzo Bianconi 			.read_fifo = st_lsm6dsx_read_fifo,
32592617c15SLorenzo Bianconi 			.fifo_th = {
32692617c15SLorenzo Bianconi 				.addr = 0x06,
32792617c15SLorenzo Bianconi 				.mask = GENMASK(11, 0),
32892617c15SLorenzo Bianconi 			},
32992617c15SLorenzo Bianconi 			.fifo_diff = {
33092617c15SLorenzo Bianconi 				.addr = 0x3a,
33192617c15SLorenzo Bianconi 				.mask = GENMASK(11, 0),
33292617c15SLorenzo Bianconi 			},
3331b7da2faSLorenzo Bianconi 			.max_size = 1365,
33492617c15SLorenzo Bianconi 			.th_wl = 3, /* 1LSB = 2B */
33592617c15SLorenzo Bianconi 		},
33621345107SLorenzo Bianconi 		.ts_settings = {
33721345107SLorenzo Bianconi 			.timer_en = {
33821345107SLorenzo Bianconi 				.addr = 0x58,
33921345107SLorenzo Bianconi 				.mask = BIT(7),
34021345107SLorenzo Bianconi 			},
34121345107SLorenzo Bianconi 			.hr_timer = {
34221345107SLorenzo Bianconi 				.addr = 0x5c,
34321345107SLorenzo Bianconi 				.mask = BIT(4),
34421345107SLorenzo Bianconi 			},
34521345107SLorenzo Bianconi 			.fifo_en = {
34621345107SLorenzo Bianconi 				.addr = 0x07,
34721345107SLorenzo Bianconi 				.mask = BIT(7),
34821345107SLorenzo Bianconi 			},
34921345107SLorenzo Bianconi 			.decimator = {
35021345107SLorenzo Bianconi 				.addr = 0x09,
35121345107SLorenzo Bianconi 				.mask = GENMASK(5, 3),
35221345107SLorenzo Bianconi 			},
35321345107SLorenzo Bianconi 		},
354b5969abfSSean Nyekjaer 		.event_settings = {
355b5969abfSSean Nyekjaer 			.wakeup_reg = {
356b5969abfSSean Nyekjaer 				.addr = 0x5B,
357b5969abfSSean Nyekjaer 				.mask = GENMASK(5, 0),
358b5969abfSSean Nyekjaer 			},
3591aabad1fSSean Nyekjaer 			.wakeup_src_reg = 0x1b,
3601aabad1fSSean Nyekjaer 			.wakeup_src_status_mask = BIT(3),
3611aabad1fSSean Nyekjaer 			.wakeup_src_z_mask = BIT(0),
3621aabad1fSSean Nyekjaer 			.wakeup_src_y_mask = BIT(1),
3631aabad1fSSean Nyekjaer 			.wakeup_src_x_mask = BIT(2),
364b5969abfSSean Nyekjaer 		},
365290a6ce1SLorenzo Bianconi 	},
366290a6ce1SLorenzo Bianconi 	{
36766b662a1SLorenzo Bianconi 		.reset = {
36866b662a1SLorenzo Bianconi 			.addr = 0x12,
36966b662a1SLorenzo Bianconi 			.mask = BIT(0),
37066b662a1SLorenzo Bianconi 		},
37166b662a1SLorenzo Bianconi 		.boot = {
37266b662a1SLorenzo Bianconi 			.addr = 0x12,
37366b662a1SLorenzo Bianconi 			.mask = BIT(7),
37466b662a1SLorenzo Bianconi 		},
37566b662a1SLorenzo Bianconi 		.bdu = {
37666b662a1SLorenzo Bianconi 			.addr = 0x12,
37766b662a1SLorenzo Bianconi 			.mask = BIT(6),
37866b662a1SLorenzo Bianconi 		},
379df47710aSLorenzo Bianconi 		.id = {
38081956a93SLorenzo Bianconi 			{
38181956a93SLorenzo Bianconi 				.hw_id = ST_LSM6DS3H_ID,
38281956a93SLorenzo Bianconi 				.name = ST_LSM6DS3H_DEV_NAME,
38398c3544aSLorenzo Bianconi 				.wai = 0x69,
38481956a93SLorenzo Bianconi 			},
385df47710aSLorenzo Bianconi 		},
386f48bc49bSLorenzo Bianconi 		.channels = {
387f48bc49bSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
388f48bc49bSLorenzo Bianconi 				.chan = st_lsm6dsx_acc_channels,
389f48bc49bSLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_acc_channels),
390f48bc49bSLorenzo Bianconi 			},
391f48bc49bSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
392f48bc49bSLorenzo Bianconi 				.chan = st_lsm6dsx_gyro_channels,
393f48bc49bSLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_gyro_channels),
394f48bc49bSLorenzo Bianconi 			},
395f48bc49bSLorenzo Bianconi 		},
39640dd7343SLorenzo Bianconi 		.odr_table = {
39740dd7343SLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
39840dd7343SLorenzo Bianconi 				.reg = {
39940dd7343SLorenzo Bianconi 					.addr = 0x10,
40040dd7343SLorenzo Bianconi 					.mask = GENMASK(7, 4),
40140dd7343SLorenzo Bianconi 				},
402f8710f03SLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
403f8710f03SLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
404f8710f03SLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
405f8710f03SLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
406f8710f03SLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
407f8710f03SLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
40859af4e20SLorenzo Bianconi 				.odr_len = 6,
40940dd7343SLorenzo Bianconi 			},
41040dd7343SLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
41140dd7343SLorenzo Bianconi 				.reg = {
41240dd7343SLorenzo Bianconi 					.addr = 0x11,
41340dd7343SLorenzo Bianconi 					.mask = GENMASK(7, 4),
41440dd7343SLorenzo Bianconi 				},
415f8710f03SLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
416f8710f03SLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
417f8710f03SLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
418f8710f03SLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
419f8710f03SLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
420f8710f03SLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
42159af4e20SLorenzo Bianconi 				.odr_len = 6,
42240dd7343SLorenzo Bianconi 			},
42340dd7343SLorenzo Bianconi 		},
424640aca3fSLorenzo Bianconi 		.fs_table = {
425640aca3fSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
426640aca3fSLorenzo Bianconi 				.reg = {
427640aca3fSLorenzo Bianconi 					.addr = 0x10,
428640aca3fSLorenzo Bianconi 					.mask = GENMASK(3, 2),
429640aca3fSLorenzo Bianconi 				},
43044a76de8SMario Tesi 				.fs_avl[0] = {  IIO_G_TO_M_S_2(61000), 0x0 },
43144a76de8SMario Tesi 				.fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 },
43244a76de8SMario Tesi 				.fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 },
43344a76de8SMario Tesi 				.fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 },
43485ae3aeeSLorenzo Bianconi 				.fs_len = 4,
435640aca3fSLorenzo Bianconi 			},
436640aca3fSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
437640aca3fSLorenzo Bianconi 				.reg = {
438640aca3fSLorenzo Bianconi 					.addr = 0x11,
439640aca3fSLorenzo Bianconi 					.mask = GENMASK(3, 2),
440640aca3fSLorenzo Bianconi 				},
44144a76de8SMario Tesi 				.fs_avl[0] = {  IIO_DEGREE_TO_RAD(8750000), 0x0 },
44244a76de8SMario Tesi 				.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 },
44344a76de8SMario Tesi 				.fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 },
44444a76de8SMario Tesi 				.fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 },
44585ae3aeeSLorenzo Bianconi 				.fs_len = 4,
446640aca3fSLorenzo Bianconi 			},
447640aca3fSLorenzo Bianconi 		},
4487e906103SLorenzo Bianconi 		.irq_config = {
4497e906103SLorenzo Bianconi 			.irq1 = {
4507e906103SLorenzo Bianconi 				.addr = 0x0d,
4517e906103SLorenzo Bianconi 				.mask = BIT(3),
4527e906103SLorenzo Bianconi 			},
4537e906103SLorenzo Bianconi 			.irq2 = {
4547e906103SLorenzo Bianconi 				.addr = 0x0e,
4557e906103SLorenzo Bianconi 				.mask = BIT(3),
4567e906103SLorenzo Bianconi 			},
4577e906103SLorenzo Bianconi 			.lir = {
4587e906103SLorenzo Bianconi 				.addr = 0x58,
4597e906103SLorenzo Bianconi 				.mask = BIT(0),
4607e906103SLorenzo Bianconi 			},
4617e906103SLorenzo Bianconi 			.irq1_func = {
4627e906103SLorenzo Bianconi 				.addr = 0x5e,
4637e906103SLorenzo Bianconi 				.mask = BIT(5),
4647e906103SLorenzo Bianconi 			},
4657e906103SLorenzo Bianconi 			.irq2_func = {
4667e906103SLorenzo Bianconi 				.addr = 0x5f,
4677e906103SLorenzo Bianconi 				.mask = BIT(5),
4687e906103SLorenzo Bianconi 			},
46931fe8d4eSLorenzo Bianconi 			.hla = {
47031fe8d4eSLorenzo Bianconi 				.addr = 0x12,
47131fe8d4eSLorenzo Bianconi 				.mask = BIT(5),
47231fe8d4eSLorenzo Bianconi 			},
47331fe8d4eSLorenzo Bianconi 			.od = {
47431fe8d4eSLorenzo Bianconi 				.addr = 0x12,
47531fe8d4eSLorenzo Bianconi 				.mask = BIT(4),
47631fe8d4eSLorenzo Bianconi 			},
4777e906103SLorenzo Bianconi 		},
4787ca3ac9eSLorenzo Bianconi 		.decimator = {
4797ca3ac9eSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
4807ca3ac9eSLorenzo Bianconi 				.addr = 0x08,
4817ca3ac9eSLorenzo Bianconi 				.mask = GENMASK(2, 0),
4827ca3ac9eSLorenzo Bianconi 			},
4837ca3ac9eSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
4847ca3ac9eSLorenzo Bianconi 				.addr = 0x08,
4857ca3ac9eSLorenzo Bianconi 				.mask = GENMASK(5, 3),
4867ca3ac9eSLorenzo Bianconi 			},
4877ca3ac9eSLorenzo Bianconi 		},
48892617c15SLorenzo Bianconi 		.fifo_ops = {
4893b72950dSLorenzo Bianconi 			.update_fifo = st_lsm6dsx_update_fifo,
49050ff457dSLorenzo Bianconi 			.read_fifo = st_lsm6dsx_read_fifo,
49192617c15SLorenzo Bianconi 			.fifo_th = {
49292617c15SLorenzo Bianconi 				.addr = 0x06,
49392617c15SLorenzo Bianconi 				.mask = GENMASK(11, 0),
49492617c15SLorenzo Bianconi 			},
49592617c15SLorenzo Bianconi 			.fifo_diff = {
49692617c15SLorenzo Bianconi 				.addr = 0x3a,
49792617c15SLorenzo Bianconi 				.mask = GENMASK(11, 0),
49892617c15SLorenzo Bianconi 			},
4991b7da2faSLorenzo Bianconi 			.max_size = 682,
50092617c15SLorenzo Bianconi 			.th_wl = 3, /* 1LSB = 2B */
50192617c15SLorenzo Bianconi 		},
50221345107SLorenzo Bianconi 		.ts_settings = {
50321345107SLorenzo Bianconi 			.timer_en = {
50421345107SLorenzo Bianconi 				.addr = 0x58,
50521345107SLorenzo Bianconi 				.mask = BIT(7),
50621345107SLorenzo Bianconi 			},
50721345107SLorenzo Bianconi 			.hr_timer = {
50821345107SLorenzo Bianconi 				.addr = 0x5c,
50921345107SLorenzo Bianconi 				.mask = BIT(4),
51021345107SLorenzo Bianconi 			},
51121345107SLorenzo Bianconi 			.fifo_en = {
51221345107SLorenzo Bianconi 				.addr = 0x07,
51321345107SLorenzo Bianconi 				.mask = BIT(7),
51421345107SLorenzo Bianconi 			},
51521345107SLorenzo Bianconi 			.decimator = {
51621345107SLorenzo Bianconi 				.addr = 0x09,
51721345107SLorenzo Bianconi 				.mask = GENMASK(5, 3),
51821345107SLorenzo Bianconi 			},
51921345107SLorenzo Bianconi 		},
520b5969abfSSean Nyekjaer 		.event_settings = {
521b5969abfSSean Nyekjaer 			.wakeup_reg = {
522b5969abfSSean Nyekjaer 				.addr = 0x5B,
523b5969abfSSean Nyekjaer 				.mask = GENMASK(5, 0),
524b5969abfSSean Nyekjaer 			},
5251aabad1fSSean Nyekjaer 			.wakeup_src_reg = 0x1b,
5261aabad1fSSean Nyekjaer 			.wakeup_src_status_mask = BIT(3),
5271aabad1fSSean Nyekjaer 			.wakeup_src_z_mask = BIT(0),
5281aabad1fSSean Nyekjaer 			.wakeup_src_y_mask = BIT(1),
5291aabad1fSSean Nyekjaer 			.wakeup_src_x_mask = BIT(2),
530b5969abfSSean Nyekjaer 		},
531df47710aSLorenzo Bianconi 	},
532df47710aSLorenzo Bianconi 	{
53366b662a1SLorenzo Bianconi 		.reset = {
53466b662a1SLorenzo Bianconi 			.addr = 0x12,
53566b662a1SLorenzo Bianconi 			.mask = BIT(0),
53666b662a1SLorenzo Bianconi 		},
53766b662a1SLorenzo Bianconi 		.boot = {
53866b662a1SLorenzo Bianconi 			.addr = 0x12,
53966b662a1SLorenzo Bianconi 			.mask = BIT(7),
54066b662a1SLorenzo Bianconi 		},
54166b662a1SLorenzo Bianconi 		.bdu = {
54266b662a1SLorenzo Bianconi 			.addr = 0x12,
54366b662a1SLorenzo Bianconi 			.mask = BIT(6),
54466b662a1SLorenzo Bianconi 		},
545d068e4a0SLorenzo Bianconi 		.id = {
54681956a93SLorenzo Bianconi 			{
54781956a93SLorenzo Bianconi 				.hw_id = ST_LSM6DSL_ID,
54881956a93SLorenzo Bianconi 				.name = ST_LSM6DSL_DEV_NAME,
54998c3544aSLorenzo Bianconi 				.wai = 0x6a,
55081956a93SLorenzo Bianconi 			}, {
55181956a93SLorenzo Bianconi 				.hw_id = ST_LSM6DSM_ID,
55281956a93SLorenzo Bianconi 				.name = ST_LSM6DSM_DEV_NAME,
55398c3544aSLorenzo Bianconi 				.wai = 0x6a,
55481956a93SLorenzo Bianconi 			}, {
55581956a93SLorenzo Bianconi 				.hw_id = ST_ISM330DLC_ID,
55681956a93SLorenzo Bianconi 				.name = ST_ISM330DLC_DEV_NAME,
55798c3544aSLorenzo Bianconi 				.wai = 0x6a,
558dbcd2088SLorenzo Bianconi 			}, {
559dbcd2088SLorenzo Bianconi 				.hw_id = ST_LSM6DS3TRC_ID,
560dbcd2088SLorenzo Bianconi 				.name = ST_LSM6DS3TRC_DEV_NAME,
56198c3544aSLorenzo Bianconi 				.wai = 0x6a,
56281956a93SLorenzo Bianconi 			},
563d068e4a0SLorenzo Bianconi 		},
564f48bc49bSLorenzo Bianconi 		.channels = {
565f48bc49bSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
566f48bc49bSLorenzo Bianconi 				.chan = st_lsm6dsx_acc_channels,
567f48bc49bSLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_acc_channels),
568f48bc49bSLorenzo Bianconi 			},
569f48bc49bSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
570f48bc49bSLorenzo Bianconi 				.chan = st_lsm6dsx_gyro_channels,
571f48bc49bSLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_gyro_channels),
572f48bc49bSLorenzo Bianconi 			},
573f48bc49bSLorenzo Bianconi 		},
57440dd7343SLorenzo Bianconi 		.odr_table = {
57540dd7343SLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
57640dd7343SLorenzo Bianconi 				.reg = {
57740dd7343SLorenzo Bianconi 					.addr = 0x10,
57840dd7343SLorenzo Bianconi 					.mask = GENMASK(7, 4),
57940dd7343SLorenzo Bianconi 				},
580f8710f03SLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
581f8710f03SLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
582f8710f03SLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
583f8710f03SLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
584f8710f03SLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
585f8710f03SLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
58659af4e20SLorenzo Bianconi 				.odr_len = 6,
58740dd7343SLorenzo Bianconi 			},
58840dd7343SLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
58940dd7343SLorenzo Bianconi 				.reg = {
59040dd7343SLorenzo Bianconi 					.addr = 0x11,
59140dd7343SLorenzo Bianconi 					.mask = GENMASK(7, 4),
59240dd7343SLorenzo Bianconi 				},
593f8710f03SLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
594f8710f03SLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
595f8710f03SLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
596f8710f03SLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
597f8710f03SLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
598f8710f03SLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
59959af4e20SLorenzo Bianconi 				.odr_len = 6,
60040dd7343SLorenzo Bianconi 			},
60140dd7343SLorenzo Bianconi 		},
602640aca3fSLorenzo Bianconi 		.fs_table = {
603640aca3fSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
604640aca3fSLorenzo Bianconi 				.reg = {
605640aca3fSLorenzo Bianconi 					.addr = 0x10,
606640aca3fSLorenzo Bianconi 					.mask = GENMASK(3, 2),
607640aca3fSLorenzo Bianconi 				},
60844a76de8SMario Tesi 				.fs_avl[0] = {  IIO_G_TO_M_S_2(61000), 0x0 },
60944a76de8SMario Tesi 				.fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 },
61044a76de8SMario Tesi 				.fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 },
61144a76de8SMario Tesi 				.fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 },
61285ae3aeeSLorenzo Bianconi 				.fs_len = 4,
613640aca3fSLorenzo Bianconi 			},
614640aca3fSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
615640aca3fSLorenzo Bianconi 				.reg = {
616640aca3fSLorenzo Bianconi 					.addr = 0x11,
617640aca3fSLorenzo Bianconi 					.mask = GENMASK(3, 2),
618640aca3fSLorenzo Bianconi 				},
61944a76de8SMario Tesi 				.fs_avl[0] = {  IIO_DEGREE_TO_RAD(8750000), 0x0 },
62044a76de8SMario Tesi 				.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 },
62144a76de8SMario Tesi 				.fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 },
62244a76de8SMario Tesi 				.fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 },
62385ae3aeeSLorenzo Bianconi 				.fs_len = 4,
624640aca3fSLorenzo Bianconi 			},
625640aca3fSLorenzo Bianconi 		},
6267e906103SLorenzo Bianconi 		.irq_config = {
6277e906103SLorenzo Bianconi 			.irq1 = {
6287e906103SLorenzo Bianconi 				.addr = 0x0d,
6297e906103SLorenzo Bianconi 				.mask = BIT(3),
6307e906103SLorenzo Bianconi 			},
6317e906103SLorenzo Bianconi 			.irq2 = {
6327e906103SLorenzo Bianconi 				.addr = 0x0e,
6337e906103SLorenzo Bianconi 				.mask = BIT(3),
6347e906103SLorenzo Bianconi 			},
6357e906103SLorenzo Bianconi 			.lir = {
6367e906103SLorenzo Bianconi 				.addr = 0x58,
6377e906103SLorenzo Bianconi 				.mask = BIT(0),
6387e906103SLorenzo Bianconi 			},
6397e906103SLorenzo Bianconi 			.irq1_func = {
6407e906103SLorenzo Bianconi 				.addr = 0x5e,
6417e906103SLorenzo Bianconi 				.mask = BIT(5),
6427e906103SLorenzo Bianconi 			},
6437e906103SLorenzo Bianconi 			.irq2_func = {
6447e906103SLorenzo Bianconi 				.addr = 0x5f,
6457e906103SLorenzo Bianconi 				.mask = BIT(5),
6467e906103SLorenzo Bianconi 			},
64731fe8d4eSLorenzo Bianconi 			.hla = {
64831fe8d4eSLorenzo Bianconi 				.addr = 0x12,
64931fe8d4eSLorenzo Bianconi 				.mask = BIT(5),
65031fe8d4eSLorenzo Bianconi 			},
65131fe8d4eSLorenzo Bianconi 			.od = {
65231fe8d4eSLorenzo Bianconi 				.addr = 0x12,
65331fe8d4eSLorenzo Bianconi 				.mask = BIT(4),
65431fe8d4eSLorenzo Bianconi 			},
6557e906103SLorenzo Bianconi 		},
6567ca3ac9eSLorenzo Bianconi 		.decimator = {
6577ca3ac9eSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
6587ca3ac9eSLorenzo Bianconi 				.addr = 0x08,
6597ca3ac9eSLorenzo Bianconi 				.mask = GENMASK(2, 0),
6607ca3ac9eSLorenzo Bianconi 			},
6617ca3ac9eSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
6627ca3ac9eSLorenzo Bianconi 				.addr = 0x08,
6637ca3ac9eSLorenzo Bianconi 				.mask = GENMASK(5, 3),
6647ca3ac9eSLorenzo Bianconi 			},
665e485e2a2SLorenzo Bianconi 			[ST_LSM6DSX_ID_EXT0] = {
666e485e2a2SLorenzo Bianconi 				.addr = 0x09,
667e485e2a2SLorenzo Bianconi 				.mask = GENMASK(2, 0),
668e485e2a2SLorenzo Bianconi 			},
6697ca3ac9eSLorenzo Bianconi 		},
67092617c15SLorenzo Bianconi 		.fifo_ops = {
6713b72950dSLorenzo Bianconi 			.update_fifo = st_lsm6dsx_update_fifo,
67250ff457dSLorenzo Bianconi 			.read_fifo = st_lsm6dsx_read_fifo,
67392617c15SLorenzo Bianconi 			.fifo_th = {
67492617c15SLorenzo Bianconi 				.addr = 0x06,
675be75eb86SLorenzo Bianconi 				.mask = GENMASK(10, 0),
67692617c15SLorenzo Bianconi 			},
67792617c15SLorenzo Bianconi 			.fifo_diff = {
67892617c15SLorenzo Bianconi 				.addr = 0x3a,
679be75eb86SLorenzo Bianconi 				.mask = GENMASK(10, 0),
68092617c15SLorenzo Bianconi 			},
6811b7da2faSLorenzo Bianconi 			.max_size = 682,
68292617c15SLorenzo Bianconi 			.th_wl = 3, /* 1LSB = 2B */
68392617c15SLorenzo Bianconi 		},
68421345107SLorenzo Bianconi 		.ts_settings = {
68521345107SLorenzo Bianconi 			.timer_en = {
68621345107SLorenzo Bianconi 				.addr = 0x19,
68721345107SLorenzo Bianconi 				.mask = BIT(5),
68821345107SLorenzo Bianconi 			},
68921345107SLorenzo Bianconi 			.hr_timer = {
69021345107SLorenzo Bianconi 				.addr = 0x5c,
69121345107SLorenzo Bianconi 				.mask = BIT(4),
69221345107SLorenzo Bianconi 			},
69321345107SLorenzo Bianconi 			.fifo_en = {
69421345107SLorenzo Bianconi 				.addr = 0x07,
69521345107SLorenzo Bianconi 				.mask = BIT(7),
69621345107SLorenzo Bianconi 			},
69721345107SLorenzo Bianconi 			.decimator = {
69821345107SLorenzo Bianconi 				.addr = 0x09,
69921345107SLorenzo Bianconi 				.mask = GENMASK(5, 3),
70021345107SLorenzo Bianconi 			},
70121345107SLorenzo Bianconi 		},
702e485e2a2SLorenzo Bianconi 		.shub_settings = {
703e485e2a2SLorenzo Bianconi 			.page_mux = {
704e485e2a2SLorenzo Bianconi 				.addr = 0x01,
705e485e2a2SLorenzo Bianconi 				.mask = BIT(7),
706e485e2a2SLorenzo Bianconi 			},
707e485e2a2SLorenzo Bianconi 			.master_en = {
708e485e2a2SLorenzo Bianconi 				.addr = 0x1a,
709e485e2a2SLorenzo Bianconi 				.mask = BIT(0),
710e485e2a2SLorenzo Bianconi 			},
711e485e2a2SLorenzo Bianconi 			.pullup_en = {
712e485e2a2SLorenzo Bianconi 				.addr = 0x1a,
713e485e2a2SLorenzo Bianconi 				.mask = BIT(3),
714e485e2a2SLorenzo Bianconi 			},
715e485e2a2SLorenzo Bianconi 			.aux_sens = {
716e485e2a2SLorenzo Bianconi 				.addr = 0x04,
717e485e2a2SLorenzo Bianconi 				.mask = GENMASK(5, 4),
718e485e2a2SLorenzo Bianconi 			},
719e485e2a2SLorenzo Bianconi 			.wr_once = {
720e485e2a2SLorenzo Bianconi 				.addr = 0x07,
721e485e2a2SLorenzo Bianconi 				.mask = BIT(5),
722e485e2a2SLorenzo Bianconi 			},
723e485e2a2SLorenzo Bianconi 			.emb_func = {
724e485e2a2SLorenzo Bianconi 				.addr = 0x19,
725e485e2a2SLorenzo Bianconi 				.mask = BIT(2),
726e485e2a2SLorenzo Bianconi 			},
727e485e2a2SLorenzo Bianconi 			.num_ext_dev = 1,
728e485e2a2SLorenzo Bianconi 			.shub_out = {
729e485e2a2SLorenzo Bianconi 				.addr = 0x2e,
730e485e2a2SLorenzo Bianconi 			},
731e485e2a2SLorenzo Bianconi 			.slv0_addr = 0x02,
732e485e2a2SLorenzo Bianconi 			.dw_slv0_addr = 0x0e,
733e485e2a2SLorenzo Bianconi 			.pause = 0x7,
734e485e2a2SLorenzo Bianconi 		},
735b5969abfSSean Nyekjaer 		.event_settings = {
736b5969abfSSean Nyekjaer 			.enable_reg = {
737b5969abfSSean Nyekjaer 				.addr = 0x58,
738b5969abfSSean Nyekjaer 				.mask = BIT(7),
739b5969abfSSean Nyekjaer 			},
740b5969abfSSean Nyekjaer 			.wakeup_reg = {
741b5969abfSSean Nyekjaer 				.addr = 0x5B,
742b5969abfSSean Nyekjaer 				.mask = GENMASK(5, 0),
743b5969abfSSean Nyekjaer 			},
7441aabad1fSSean Nyekjaer 			.wakeup_src_reg = 0x1b,
7451aabad1fSSean Nyekjaer 			.wakeup_src_status_mask = BIT(3),
7461aabad1fSSean Nyekjaer 			.wakeup_src_z_mask = BIT(0),
7471aabad1fSSean Nyekjaer 			.wakeup_src_y_mask = BIT(1),
7481aabad1fSSean Nyekjaer 			.wakeup_src_x_mask = BIT(2),
749b5969abfSSean Nyekjaer 		},
750290a6ce1SLorenzo Bianconi 	},
751801a6e0aSLorenzo Bianconi 	{
75266b662a1SLorenzo Bianconi 		.reset = {
75366b662a1SLorenzo Bianconi 			.addr = 0x12,
75466b662a1SLorenzo Bianconi 			.mask = BIT(0),
75566b662a1SLorenzo Bianconi 		},
75666b662a1SLorenzo Bianconi 		.boot = {
75766b662a1SLorenzo Bianconi 			.addr = 0x12,
75866b662a1SLorenzo Bianconi 			.mask = BIT(7),
75966b662a1SLorenzo Bianconi 		},
76066b662a1SLorenzo Bianconi 		.bdu = {
76166b662a1SLorenzo Bianconi 			.addr = 0x12,
76266b662a1SLorenzo Bianconi 			.mask = BIT(6),
76366b662a1SLorenzo Bianconi 		},
76443901008SLorenzo Bianconi 		.id = {
76581956a93SLorenzo Bianconi 			{
76681956a93SLorenzo Bianconi 				.hw_id = ST_LSM6DSR_ID,
76781956a93SLorenzo Bianconi 				.name = ST_LSM6DSR_DEV_NAME,
76898c3544aSLorenzo Bianconi 				.wai = 0x6b,
769db947a79SLorenzo Bianconi 			}, {
770db947a79SLorenzo Bianconi 				.hw_id = ST_ISM330DHCX_ID,
771db947a79SLorenzo Bianconi 				.name = ST_ISM330DHCX_DEV_NAME,
77298c3544aSLorenzo Bianconi 				.wai = 0x6b,
773cf9c71b3SLorenzo Bianconi 			}, {
774cf9c71b3SLorenzo Bianconi 				.hw_id = ST_LSM6DSRX_ID,
775cf9c71b3SLorenzo Bianconi 				.name = ST_LSM6DSRX_DEV_NAME,
77698c3544aSLorenzo Bianconi 				.wai = 0x6b,
77798c3544aSLorenzo Bianconi 			}, {
77898c3544aSLorenzo Bianconi 				.hw_id = ST_LSM6DSO_ID,
77998c3544aSLorenzo Bianconi 				.name = ST_LSM6DSO_DEV_NAME,
78098c3544aSLorenzo Bianconi 				.wai = 0x6c,
78198c3544aSLorenzo Bianconi 			}, {
78298c3544aSLorenzo Bianconi 				.hw_id = ST_LSM6DSOX_ID,
78398c3544aSLorenzo Bianconi 				.name = ST_LSM6DSOX_DEV_NAME,
78498c3544aSLorenzo Bianconi 				.wai = 0x6c,
78598c3544aSLorenzo Bianconi 			}, {
7864393e4c5SLorenzo Bianconi 				.hw_id = ST_LSM6DST_ID,
7874393e4c5SLorenzo Bianconi 				.name = ST_LSM6DST_DEV_NAME,
78898c3544aSLorenzo Bianconi 				.wai = 0x6d,
789*fdd70d7aSLorenzo Bianconi 			}, {
790*fdd70d7aSLorenzo Bianconi 				.hw_id = ST_ASM330LHHX_ID,
791*fdd70d7aSLorenzo Bianconi 				.name = ST_ASM330LHHX_DEV_NAME,
792*fdd70d7aSLorenzo Bianconi 				.wai = 0x6b,
7934393e4c5SLorenzo Bianconi 			},
7944393e4c5SLorenzo Bianconi 		},
7954393e4c5SLorenzo Bianconi 		.channels = {
7964393e4c5SLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
7974393e4c5SLorenzo Bianconi 				.chan = st_lsm6dsx_acc_channels,
7984393e4c5SLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_acc_channels),
7994393e4c5SLorenzo Bianconi 			},
8004393e4c5SLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
8014393e4c5SLorenzo Bianconi 				.chan = st_lsm6dsx_gyro_channels,
8024393e4c5SLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_gyro_channels),
8034393e4c5SLorenzo Bianconi 			},
8044393e4c5SLorenzo Bianconi 		},
8054393e4c5SLorenzo Bianconi 		.drdy_mask = {
8064393e4c5SLorenzo Bianconi 			.addr = 0x13,
8074393e4c5SLorenzo Bianconi 			.mask = BIT(3),
8084393e4c5SLorenzo Bianconi 		},
8094393e4c5SLorenzo Bianconi 		.odr_table = {
8104393e4c5SLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
8114393e4c5SLorenzo Bianconi 				.reg = {
8124393e4c5SLorenzo Bianconi 					.addr = 0x10,
8134393e4c5SLorenzo Bianconi 					.mask = GENMASK(7, 4),
8144393e4c5SLorenzo Bianconi 				},
8154393e4c5SLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
8164393e4c5SLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
8174393e4c5SLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
8184393e4c5SLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
8194393e4c5SLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
8204393e4c5SLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
8214393e4c5SLorenzo Bianconi 				.odr_avl[6] = { 833000, 0x07 },
8224393e4c5SLorenzo Bianconi 				.odr_len = 7,
8234393e4c5SLorenzo Bianconi 			},
8244393e4c5SLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
8254393e4c5SLorenzo Bianconi 				.reg = {
8264393e4c5SLorenzo Bianconi 					.addr = 0x11,
8274393e4c5SLorenzo Bianconi 					.mask = GENMASK(7, 4),
8284393e4c5SLorenzo Bianconi 				},
8294393e4c5SLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
8304393e4c5SLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
8314393e4c5SLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
8324393e4c5SLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
8334393e4c5SLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
8344393e4c5SLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
8354393e4c5SLorenzo Bianconi 				.odr_avl[6] = { 833000, 0x07 },
8364393e4c5SLorenzo Bianconi 				.odr_len = 7,
8374393e4c5SLorenzo Bianconi 			},
8384393e4c5SLorenzo Bianconi 		},
8394393e4c5SLorenzo Bianconi 		.fs_table = {
8404393e4c5SLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
8414393e4c5SLorenzo Bianconi 				.reg = {
8424393e4c5SLorenzo Bianconi 					.addr = 0x10,
8434393e4c5SLorenzo Bianconi 					.mask = GENMASK(3, 2),
8444393e4c5SLorenzo Bianconi 				},
8454393e4c5SLorenzo Bianconi 				.fs_avl[0] = {  IIO_G_TO_M_S_2(61000), 0x0 },
8464393e4c5SLorenzo Bianconi 				.fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 },
8474393e4c5SLorenzo Bianconi 				.fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 },
8484393e4c5SLorenzo Bianconi 				.fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 },
8494393e4c5SLorenzo Bianconi 				.fs_len = 4,
8504393e4c5SLorenzo Bianconi 			},
8514393e4c5SLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
8524393e4c5SLorenzo Bianconi 				.reg = {
8534393e4c5SLorenzo Bianconi 					.addr = 0x11,
8544393e4c5SLorenzo Bianconi 					.mask = GENMASK(3, 2),
8554393e4c5SLorenzo Bianconi 				},
8564393e4c5SLorenzo Bianconi 				.fs_avl[0] = {  IIO_DEGREE_TO_RAD(8750000), 0x0 },
8574393e4c5SLorenzo Bianconi 				.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 },
8584393e4c5SLorenzo Bianconi 				.fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 },
8594393e4c5SLorenzo Bianconi 				.fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 },
8604393e4c5SLorenzo Bianconi 				.fs_len = 4,
8614393e4c5SLorenzo Bianconi 			},
8624393e4c5SLorenzo Bianconi 		},
8634393e4c5SLorenzo Bianconi 		.irq_config = {
8644393e4c5SLorenzo Bianconi 			.irq1 = {
8654393e4c5SLorenzo Bianconi 				.addr = 0x0d,
8664393e4c5SLorenzo Bianconi 				.mask = BIT(3),
8674393e4c5SLorenzo Bianconi 			},
8684393e4c5SLorenzo Bianconi 			.irq2 = {
8694393e4c5SLorenzo Bianconi 				.addr = 0x0e,
8704393e4c5SLorenzo Bianconi 				.mask = BIT(3),
8714393e4c5SLorenzo Bianconi 			},
8724393e4c5SLorenzo Bianconi 			.lir = {
8734393e4c5SLorenzo Bianconi 				.addr = 0x56,
8744393e4c5SLorenzo Bianconi 				.mask = BIT(0),
8754393e4c5SLorenzo Bianconi 			},
8764393e4c5SLorenzo Bianconi 			.clear_on_read = {
8774393e4c5SLorenzo Bianconi 				.addr = 0x56,
8784393e4c5SLorenzo Bianconi 				.mask = BIT(6),
8794393e4c5SLorenzo Bianconi 			},
8804393e4c5SLorenzo Bianconi 			.irq1_func = {
8814393e4c5SLorenzo Bianconi 				.addr = 0x5e,
8824393e4c5SLorenzo Bianconi 				.mask = BIT(5),
8834393e4c5SLorenzo Bianconi 			},
8844393e4c5SLorenzo Bianconi 			.irq2_func = {
8854393e4c5SLorenzo Bianconi 				.addr = 0x5f,
8864393e4c5SLorenzo Bianconi 				.mask = BIT(5),
8874393e4c5SLorenzo Bianconi 			},
8884393e4c5SLorenzo Bianconi 			.hla = {
8894393e4c5SLorenzo Bianconi 				.addr = 0x12,
8904393e4c5SLorenzo Bianconi 				.mask = BIT(5),
8914393e4c5SLorenzo Bianconi 			},
8924393e4c5SLorenzo Bianconi 			.od = {
8934393e4c5SLorenzo Bianconi 				.addr = 0x12,
8944393e4c5SLorenzo Bianconi 				.mask = BIT(4),
8954393e4c5SLorenzo Bianconi 			},
8964393e4c5SLorenzo Bianconi 		},
8974393e4c5SLorenzo Bianconi 		.batch = {
8984393e4c5SLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
8994393e4c5SLorenzo Bianconi 				.addr = 0x09,
9004393e4c5SLorenzo Bianconi 				.mask = GENMASK(3, 0),
9014393e4c5SLorenzo Bianconi 			},
9024393e4c5SLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
9034393e4c5SLorenzo Bianconi 				.addr = 0x09,
9044393e4c5SLorenzo Bianconi 				.mask = GENMASK(7, 4),
9054393e4c5SLorenzo Bianconi 			},
9064393e4c5SLorenzo Bianconi 		},
9074393e4c5SLorenzo Bianconi 		.fifo_ops = {
9084393e4c5SLorenzo Bianconi 			.update_fifo = st_lsm6dsx_update_fifo,
9094393e4c5SLorenzo Bianconi 			.read_fifo = st_lsm6dsx_read_tagged_fifo,
9104393e4c5SLorenzo Bianconi 			.fifo_th = {
9114393e4c5SLorenzo Bianconi 				.addr = 0x07,
9124393e4c5SLorenzo Bianconi 				.mask = GENMASK(8, 0),
9134393e4c5SLorenzo Bianconi 			},
9144393e4c5SLorenzo Bianconi 			.fifo_diff = {
9154393e4c5SLorenzo Bianconi 				.addr = 0x3a,
9164393e4c5SLorenzo Bianconi 				.mask = GENMASK(9, 0),
9174393e4c5SLorenzo Bianconi 			},
9181b7da2faSLorenzo Bianconi 			.max_size = 512,
9194393e4c5SLorenzo Bianconi 			.th_wl = 1,
9204393e4c5SLorenzo Bianconi 		},
9214393e4c5SLorenzo Bianconi 		.ts_settings = {
9224393e4c5SLorenzo Bianconi 			.timer_en = {
9234393e4c5SLorenzo Bianconi 				.addr = 0x19,
9244393e4c5SLorenzo Bianconi 				.mask = BIT(5),
9254393e4c5SLorenzo Bianconi 			},
9264393e4c5SLorenzo Bianconi 			.decimator = {
9274393e4c5SLorenzo Bianconi 				.addr = 0x0a,
9284393e4c5SLorenzo Bianconi 				.mask = GENMASK(7, 6),
9294393e4c5SLorenzo Bianconi 			},
9304393e4c5SLorenzo Bianconi 			.freq_fine = 0x63,
9314393e4c5SLorenzo Bianconi 		},
9324393e4c5SLorenzo Bianconi 		.shub_settings = {
9334393e4c5SLorenzo Bianconi 			.page_mux = {
9344393e4c5SLorenzo Bianconi 				.addr = 0x01,
9354393e4c5SLorenzo Bianconi 				.mask = BIT(6),
9364393e4c5SLorenzo Bianconi 			},
9374393e4c5SLorenzo Bianconi 			.master_en = {
9384393e4c5SLorenzo Bianconi 				.sec_page = true,
9394393e4c5SLorenzo Bianconi 				.addr = 0x14,
9404393e4c5SLorenzo Bianconi 				.mask = BIT(2),
9414393e4c5SLorenzo Bianconi 			},
9424393e4c5SLorenzo Bianconi 			.pullup_en = {
9434393e4c5SLorenzo Bianconi 				.sec_page = true,
9444393e4c5SLorenzo Bianconi 				.addr = 0x14,
9454393e4c5SLorenzo Bianconi 				.mask = BIT(3),
9464393e4c5SLorenzo Bianconi 			},
9474393e4c5SLorenzo Bianconi 			.aux_sens = {
9484393e4c5SLorenzo Bianconi 				.addr = 0x14,
9494393e4c5SLorenzo Bianconi 				.mask = GENMASK(1, 0),
9504393e4c5SLorenzo Bianconi 			},
9514393e4c5SLorenzo Bianconi 			.wr_once = {
9524393e4c5SLorenzo Bianconi 				.addr = 0x14,
9534393e4c5SLorenzo Bianconi 				.mask = BIT(6),
9544393e4c5SLorenzo Bianconi 			},
9554393e4c5SLorenzo Bianconi 			.num_ext_dev = 3,
9564393e4c5SLorenzo Bianconi 			.shub_out = {
9574393e4c5SLorenzo Bianconi 				.sec_page = true,
9584393e4c5SLorenzo Bianconi 				.addr = 0x02,
9594393e4c5SLorenzo Bianconi 			},
9604393e4c5SLorenzo Bianconi 			.slv0_addr = 0x15,
9614393e4c5SLorenzo Bianconi 			.dw_slv0_addr = 0x21,
9624393e4c5SLorenzo Bianconi 			.batch_en = BIT(3),
9634393e4c5SLorenzo Bianconi 		},
9644393e4c5SLorenzo Bianconi 		.event_settings = {
9654393e4c5SLorenzo Bianconi 			.enable_reg = {
9664393e4c5SLorenzo Bianconi 				.addr = 0x58,
9674393e4c5SLorenzo Bianconi 				.mask = BIT(7),
9684393e4c5SLorenzo Bianconi 			},
9694393e4c5SLorenzo Bianconi 			.wakeup_reg = {
9704393e4c5SLorenzo Bianconi 				.addr = 0x5b,
9714393e4c5SLorenzo Bianconi 				.mask = GENMASK(5, 0),
9724393e4c5SLorenzo Bianconi 			},
9734393e4c5SLorenzo Bianconi 			.wakeup_src_reg = 0x1b,
9744393e4c5SLorenzo Bianconi 			.wakeup_src_status_mask = BIT(3),
9754393e4c5SLorenzo Bianconi 			.wakeup_src_z_mask = BIT(0),
9764393e4c5SLorenzo Bianconi 			.wakeup_src_y_mask = BIT(1),
9774393e4c5SLorenzo Bianconi 			.wakeup_src_x_mask = BIT(2),
9784393e4c5SLorenzo Bianconi 		},
9794393e4c5SLorenzo Bianconi 	},
98098c3544aSLorenzo Bianconi 	{
98198c3544aSLorenzo Bianconi 		.reset = {
98298c3544aSLorenzo Bianconi 			.addr = 0x12,
98398c3544aSLorenzo Bianconi 			.mask = BIT(0),
98498c3544aSLorenzo Bianconi 		},
98598c3544aSLorenzo Bianconi 		.boot = {
98698c3544aSLorenzo Bianconi 			.addr = 0x12,
98798c3544aSLorenzo Bianconi 			.mask = BIT(7),
98898c3544aSLorenzo Bianconi 		},
98998c3544aSLorenzo Bianconi 		.bdu = {
99098c3544aSLorenzo Bianconi 			.addr = 0x12,
99198c3544aSLorenzo Bianconi 			.mask = BIT(6),
99298c3544aSLorenzo Bianconi 		},
99398c3544aSLorenzo Bianconi 		.id = {
99498c3544aSLorenzo Bianconi 			{
99598c3544aSLorenzo Bianconi 				.hw_id = ST_ASM330LHH_ID,
99698c3544aSLorenzo Bianconi 				.name = ST_ASM330LHH_DEV_NAME,
99798c3544aSLorenzo Bianconi 				.wai = 0x6b,
9982c57d265SLorenzo Bianconi 			}, {
9992c57d265SLorenzo Bianconi 				.hw_id = ST_LSM6DSOP_ID,
10002c57d265SLorenzo Bianconi 				.name = ST_LSM6DSOP_DEV_NAME,
10012c57d265SLorenzo Bianconi 				.wai = 0x6c,
100298c3544aSLorenzo Bianconi 			},
100398c3544aSLorenzo Bianconi 		},
100498c3544aSLorenzo Bianconi 		.channels = {
100598c3544aSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
100698c3544aSLorenzo Bianconi 				.chan = st_lsm6dsx_acc_channels,
100798c3544aSLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_acc_channels),
100898c3544aSLorenzo Bianconi 			},
100998c3544aSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
101098c3544aSLorenzo Bianconi 				.chan = st_lsm6dsx_gyro_channels,
101198c3544aSLorenzo Bianconi 				.len = ARRAY_SIZE(st_lsm6dsx_gyro_channels),
101298c3544aSLorenzo Bianconi 			},
101398c3544aSLorenzo Bianconi 		},
101498c3544aSLorenzo Bianconi 		.drdy_mask = {
101598c3544aSLorenzo Bianconi 			.addr = 0x13,
101698c3544aSLorenzo Bianconi 			.mask = BIT(3),
101798c3544aSLorenzo Bianconi 		},
101898c3544aSLorenzo Bianconi 		.odr_table = {
101998c3544aSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
102098c3544aSLorenzo Bianconi 				.reg = {
102198c3544aSLorenzo Bianconi 					.addr = 0x10,
102298c3544aSLorenzo Bianconi 					.mask = GENMASK(7, 4),
102398c3544aSLorenzo Bianconi 				},
102498c3544aSLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
102598c3544aSLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
102698c3544aSLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
102798c3544aSLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
102898c3544aSLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
102998c3544aSLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
103098c3544aSLorenzo Bianconi 				.odr_avl[6] = { 833000, 0x07 },
103198c3544aSLorenzo Bianconi 				.odr_len = 7,
103298c3544aSLorenzo Bianconi 			},
103398c3544aSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
103498c3544aSLorenzo Bianconi 				.reg = {
103598c3544aSLorenzo Bianconi 					.addr = 0x11,
103698c3544aSLorenzo Bianconi 					.mask = GENMASK(7, 4),
103798c3544aSLorenzo Bianconi 				},
103898c3544aSLorenzo Bianconi 				.odr_avl[0] = {  12500, 0x01 },
103998c3544aSLorenzo Bianconi 				.odr_avl[1] = {  26000, 0x02 },
104098c3544aSLorenzo Bianconi 				.odr_avl[2] = {  52000, 0x03 },
104198c3544aSLorenzo Bianconi 				.odr_avl[3] = { 104000, 0x04 },
104298c3544aSLorenzo Bianconi 				.odr_avl[4] = { 208000, 0x05 },
104398c3544aSLorenzo Bianconi 				.odr_avl[5] = { 416000, 0x06 },
104498c3544aSLorenzo Bianconi 				.odr_avl[6] = { 833000, 0x07 },
104598c3544aSLorenzo Bianconi 				.odr_len = 7,
104698c3544aSLorenzo Bianconi 			},
104798c3544aSLorenzo Bianconi 		},
104898c3544aSLorenzo Bianconi 		.fs_table = {
104998c3544aSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
105098c3544aSLorenzo Bianconi 				.reg = {
105198c3544aSLorenzo Bianconi 					.addr = 0x10,
105298c3544aSLorenzo Bianconi 					.mask = GENMASK(3, 2),
105398c3544aSLorenzo Bianconi 				},
105498c3544aSLorenzo Bianconi 				.fs_avl[0] = {  IIO_G_TO_M_S_2(61000), 0x0 },
105598c3544aSLorenzo Bianconi 				.fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 },
105698c3544aSLorenzo Bianconi 				.fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 },
105798c3544aSLorenzo Bianconi 				.fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 },
105898c3544aSLorenzo Bianconi 				.fs_len = 4,
105998c3544aSLorenzo Bianconi 			},
106098c3544aSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
106198c3544aSLorenzo Bianconi 				.reg = {
106298c3544aSLorenzo Bianconi 					.addr = 0x11,
106398c3544aSLorenzo Bianconi 					.mask = GENMASK(3, 2),
106498c3544aSLorenzo Bianconi 				},
106598c3544aSLorenzo Bianconi 				.fs_avl[0] = {  IIO_DEGREE_TO_RAD(8750000), 0x0 },
106698c3544aSLorenzo Bianconi 				.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 },
106798c3544aSLorenzo Bianconi 				.fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 },
106898c3544aSLorenzo Bianconi 				.fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 },
106998c3544aSLorenzo Bianconi 				.fs_len = 4,
107098c3544aSLorenzo Bianconi 			},
107198c3544aSLorenzo Bianconi 		},
107298c3544aSLorenzo Bianconi 		.irq_config = {
107398c3544aSLorenzo Bianconi 			.irq1 = {
107498c3544aSLorenzo Bianconi 				.addr = 0x0d,
107598c3544aSLorenzo Bianconi 				.mask = BIT(3),
107698c3544aSLorenzo Bianconi 			},
107798c3544aSLorenzo Bianconi 			.irq2 = {
107898c3544aSLorenzo Bianconi 				.addr = 0x0e,
107998c3544aSLorenzo Bianconi 				.mask = BIT(3),
108098c3544aSLorenzo Bianconi 			},
108198c3544aSLorenzo Bianconi 			.lir = {
108298c3544aSLorenzo Bianconi 				.addr = 0x56,
108398c3544aSLorenzo Bianconi 				.mask = BIT(0),
108498c3544aSLorenzo Bianconi 			},
108598c3544aSLorenzo Bianconi 			.clear_on_read = {
108698c3544aSLorenzo Bianconi 				.addr = 0x56,
108798c3544aSLorenzo Bianconi 				.mask = BIT(6),
108898c3544aSLorenzo Bianconi 			},
108998c3544aSLorenzo Bianconi 			.irq1_func = {
109098c3544aSLorenzo Bianconi 				.addr = 0x5e,
109198c3544aSLorenzo Bianconi 				.mask = BIT(5),
109298c3544aSLorenzo Bianconi 			},
109398c3544aSLorenzo Bianconi 			.irq2_func = {
109498c3544aSLorenzo Bianconi 				.addr = 0x5f,
109598c3544aSLorenzo Bianconi 				.mask = BIT(5),
109698c3544aSLorenzo Bianconi 			},
109798c3544aSLorenzo Bianconi 			.hla = {
109898c3544aSLorenzo Bianconi 				.addr = 0x12,
109998c3544aSLorenzo Bianconi 				.mask = BIT(5),
110098c3544aSLorenzo Bianconi 			},
110198c3544aSLorenzo Bianconi 			.od = {
110298c3544aSLorenzo Bianconi 				.addr = 0x12,
110398c3544aSLorenzo Bianconi 				.mask = BIT(4),
110498c3544aSLorenzo Bianconi 			},
110598c3544aSLorenzo Bianconi 		},
110698c3544aSLorenzo Bianconi 		.batch = {
110798c3544aSLorenzo Bianconi 			[ST_LSM6DSX_ID_ACC] = {
110898c3544aSLorenzo Bianconi 				.addr = 0x09,
110998c3544aSLorenzo Bianconi 				.mask = GENMASK(3, 0),
111098c3544aSLorenzo Bianconi 			},
111198c3544aSLorenzo Bianconi 			[ST_LSM6DSX_ID_GYRO] = {
111298c3544aSLorenzo Bianconi 				.addr = 0x09,
111398c3544aSLorenzo Bianconi 				.mask = GENMASK(7, 4),
111498c3544aSLorenzo Bianconi 			},
111598c3544aSLorenzo Bianconi 		},
111698c3544aSLorenzo Bianconi 		.fifo_ops = {
111798c3544aSLorenzo Bianconi 			.update_fifo = st_lsm6dsx_update_fifo,
111898c3544aSLorenzo Bianconi 			.read_fifo = st_lsm6dsx_read_tagged_fifo,
111998c3544aSLorenzo Bianconi 			.fifo_th = {
112098c3544aSLorenzo Bianconi 				.addr = 0x07,
112198c3544aSLorenzo Bianconi 				.mask = GENMASK(8, 0),
112298c3544aSLorenzo Bianconi 			},
112398c3544aSLorenzo Bianconi 			.fifo_diff = {
112498c3544aSLorenzo Bianconi 				.addr = 0x3a,
112598c3544aSLorenzo Bianconi 				.mask = GENMASK(9, 0),
112698c3544aSLorenzo Bianconi 			},
11271b7da2faSLorenzo Bianconi 			.max_size = 512,
112898c3544aSLorenzo Bianconi 			.th_wl = 1,
112998c3544aSLorenzo Bianconi 		},
113098c3544aSLorenzo Bianconi 		.ts_settings = {
113198c3544aSLorenzo Bianconi 			.timer_en = {
113298c3544aSLorenzo Bianconi 				.addr = 0x19,
113398c3544aSLorenzo Bianconi 				.mask = BIT(5),
113498c3544aSLorenzo Bianconi 			},
113598c3544aSLorenzo Bianconi 			.decimator = {
113698c3544aSLorenzo Bianconi 				.addr = 0x0a,
113798c3544aSLorenzo Bianconi 				.mask = GENMASK(7, 6),
113898c3544aSLorenzo Bianconi 			},
113998c3544aSLorenzo Bianconi 			.freq_fine = 0x63,
114098c3544aSLorenzo Bianconi 		},
114198c3544aSLorenzo Bianconi 		.event_settings = {
114298c3544aSLorenzo Bianconi 			.enable_reg = {
114398c3544aSLorenzo Bianconi 				.addr = 0x58,
114498c3544aSLorenzo Bianconi 				.mask = BIT(7),
114598c3544aSLorenzo Bianconi 			},
114698c3544aSLorenzo Bianconi 			.wakeup_reg = {
114798c3544aSLorenzo Bianconi 				.addr = 0x5B,
114898c3544aSLorenzo Bianconi 				.mask = GENMASK(5, 0),
114998c3544aSLorenzo Bianconi 			},
115098c3544aSLorenzo Bianconi 			.wakeup_src_reg = 0x1b,
115198c3544aSLorenzo Bianconi 			.wakeup_src_status_mask = BIT(3),
115298c3544aSLorenzo Bianconi 			.wakeup_src_z_mask = BIT(0),
115398c3544aSLorenzo Bianconi 			.wakeup_src_y_mask = BIT(1),
115498c3544aSLorenzo Bianconi 			.wakeup_src_x_mask = BIT(2),
115598c3544aSLorenzo Bianconi 		},
115698c3544aSLorenzo Bianconi 	},
1157290a6ce1SLorenzo Bianconi };
1158290a6ce1SLorenzo Bianconi 
1159c91c1c84SLorenzo Bianconi int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable)
1160c91c1c84SLorenzo Bianconi {
1161c91c1c84SLorenzo Bianconi 	const struct st_lsm6dsx_shub_settings *hub_settings;
1162c91c1c84SLorenzo Bianconi 	unsigned int data;
1163c91c1c84SLorenzo Bianconi 	int err;
1164c91c1c84SLorenzo Bianconi 
1165c91c1c84SLorenzo Bianconi 	hub_settings = &hw->settings->shub_settings;
1166c91c1c84SLorenzo Bianconi 	data = ST_LSM6DSX_SHIFT_VAL(enable, hub_settings->page_mux.mask);
1167c91c1c84SLorenzo Bianconi 	err = regmap_update_bits(hw->regmap, hub_settings->page_mux.addr,
1168c91c1c84SLorenzo Bianconi 				 hub_settings->page_mux.mask, data);
1169c91c1c84SLorenzo Bianconi 	usleep_range(100, 150);
1170c91c1c84SLorenzo Bianconi 
1171c91c1c84SLorenzo Bianconi 	return err;
1172c91c1c84SLorenzo Bianconi }
1173c91c1c84SLorenzo Bianconi 
117481956a93SLorenzo Bianconi static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id,
117581956a93SLorenzo Bianconi 				   const char **name)
1176290a6ce1SLorenzo Bianconi {
117751a8b707SLorenzo Bianconi 	int err, i, j, data;
1178290a6ce1SLorenzo Bianconi 
1179290a6ce1SLorenzo Bianconi 	for (i = 0; i < ARRAY_SIZE(st_lsm6dsx_sensor_settings); i++) {
1180d068e4a0SLorenzo Bianconi 		for (j = 0; j < ST_LSM6DSX_MAX_ID; j++) {
1181fb4fbc89SStephan Gerhold 			if (st_lsm6dsx_sensor_settings[i].id[j].name &&
1182fb4fbc89SStephan Gerhold 			    id == st_lsm6dsx_sensor_settings[i].id[j].hw_id)
1183d068e4a0SLorenzo Bianconi 				break;
1184d068e4a0SLorenzo Bianconi 		}
1185d068e4a0SLorenzo Bianconi 		if (j < ST_LSM6DSX_MAX_ID)
1186290a6ce1SLorenzo Bianconi 			break;
1187290a6ce1SLorenzo Bianconi 	}
1188290a6ce1SLorenzo Bianconi 
1189290a6ce1SLorenzo Bianconi 	if (i == ARRAY_SIZE(st_lsm6dsx_sensor_settings)) {
1190290a6ce1SLorenzo Bianconi 		dev_err(hw->dev, "unsupported hw id [%02x]\n", id);
1191290a6ce1SLorenzo Bianconi 		return -ENODEV;
1192290a6ce1SLorenzo Bianconi 	}
1193290a6ce1SLorenzo Bianconi 
119451a8b707SLorenzo Bianconi 	err = regmap_read(hw->regmap, ST_LSM6DSX_REG_WHOAMI_ADDR, &data);
1195290a6ce1SLorenzo Bianconi 	if (err < 0) {
1196290a6ce1SLorenzo Bianconi 		dev_err(hw->dev, "failed to read whoami register\n");
1197290a6ce1SLorenzo Bianconi 		return err;
1198290a6ce1SLorenzo Bianconi 	}
1199290a6ce1SLorenzo Bianconi 
120098c3544aSLorenzo Bianconi 	if (data != st_lsm6dsx_sensor_settings[i].id[j].wai) {
1201290a6ce1SLorenzo Bianconi 		dev_err(hw->dev, "unsupported whoami [%02x]\n", data);
1202290a6ce1SLorenzo Bianconi 		return -ENODEV;
1203290a6ce1SLorenzo Bianconi 	}
1204290a6ce1SLorenzo Bianconi 
120581956a93SLorenzo Bianconi 	*name = st_lsm6dsx_sensor_settings[i].id[j].name;
1206290a6ce1SLorenzo Bianconi 	hw->settings = &st_lsm6dsx_sensor_settings[i];
1207290a6ce1SLorenzo Bianconi 
1208290a6ce1SLorenzo Bianconi 	return 0;
1209290a6ce1SLorenzo Bianconi }
1210290a6ce1SLorenzo Bianconi 
1211290a6ce1SLorenzo Bianconi static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor,
1212290a6ce1SLorenzo Bianconi 				     u32 gain)
1213290a6ce1SLorenzo Bianconi {
1214640aca3fSLorenzo Bianconi 	const struct st_lsm6dsx_fs_table_entry *fs_table;
1215739aff87SLorenzo Bianconi 	unsigned int data;
1216290a6ce1SLorenzo Bianconi 	int i, err;
1217290a6ce1SLorenzo Bianconi 
1218640aca3fSLorenzo Bianconi 	fs_table = &sensor->hw->settings->fs_table[sensor->id];
121985ae3aeeSLorenzo Bianconi 	for (i = 0; i < fs_table->fs_len; i++) {
1220640aca3fSLorenzo Bianconi 		if (fs_table->fs_avl[i].gain == gain)
1221290a6ce1SLorenzo Bianconi 			break;
122285ae3aeeSLorenzo Bianconi 	}
1223290a6ce1SLorenzo Bianconi 
122485ae3aeeSLorenzo Bianconi 	if (i == fs_table->fs_len)
1225290a6ce1SLorenzo Bianconi 		return -EINVAL;
1226290a6ce1SLorenzo Bianconi 
1227640aca3fSLorenzo Bianconi 	data = ST_LSM6DSX_SHIFT_VAL(fs_table->fs_avl[i].val,
1228640aca3fSLorenzo Bianconi 				    fs_table->reg.mask);
1229640aca3fSLorenzo Bianconi 	err = st_lsm6dsx_update_bits_locked(sensor->hw, fs_table->reg.addr,
1230640aca3fSLorenzo Bianconi 					    fs_table->reg.mask, data);
1231290a6ce1SLorenzo Bianconi 	if (err < 0)
1232290a6ce1SLorenzo Bianconi 		return err;
1233290a6ce1SLorenzo Bianconi 
1234290a6ce1SLorenzo Bianconi 	sensor->gain = gain;
1235290a6ce1SLorenzo Bianconi 
1236290a6ce1SLorenzo Bianconi 	return 0;
1237290a6ce1SLorenzo Bianconi }
1238290a6ce1SLorenzo Bianconi 
1239f8710f03SLorenzo Bianconi int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u32 odr, u8 *val)
1240290a6ce1SLorenzo Bianconi {
124140dd7343SLorenzo Bianconi 	const struct st_lsm6dsx_odr_table_entry *odr_table;
12422ccc1503SLorenzo Bianconi 	int i;
1243290a6ce1SLorenzo Bianconi 
124440dd7343SLorenzo Bianconi 	odr_table = &sensor->hw->settings->odr_table[sensor->id];
124559af4e20SLorenzo Bianconi 	for (i = 0; i < odr_table->odr_len; i++) {
12466ffb55e5SLorenzo Bianconi 		/*
12476ffb55e5SLorenzo Bianconi 		 * ext devices can run at different odr respect to
12486ffb55e5SLorenzo Bianconi 		 * accel sensor
12496ffb55e5SLorenzo Bianconi 		 */
1250f8710f03SLorenzo Bianconi 		if (odr_table->odr_avl[i].milli_hz >= odr)
1251290a6ce1SLorenzo Bianconi 			break;
125259af4e20SLorenzo Bianconi 	}
1253290a6ce1SLorenzo Bianconi 
125459af4e20SLorenzo Bianconi 	if (i == odr_table->odr_len)
1255290a6ce1SLorenzo Bianconi 		return -EINVAL;
1256290a6ce1SLorenzo Bianconi 
125740dd7343SLorenzo Bianconi 	*val = odr_table->odr_avl[i].val;
1258f8710f03SLorenzo Bianconi 	return odr_table->odr_avl[i].milli_hz;
1259290a6ce1SLorenzo Bianconi }
1260290a6ce1SLorenzo Bianconi 
1261f8710f03SLorenzo Bianconi static int
1262f8710f03SLorenzo Bianconi st_lsm6dsx_check_odr_dependency(struct st_lsm6dsx_hw *hw, u32 odr,
12636ffb55e5SLorenzo Bianconi 				enum st_lsm6dsx_sensor_id id)
12642ccc1503SLorenzo Bianconi {
12656ffb55e5SLorenzo Bianconi 	struct st_lsm6dsx_sensor *ref = iio_priv(hw->iio_devs[id]);
12666ffb55e5SLorenzo Bianconi 
12676ffb55e5SLorenzo Bianconi 	if (odr > 0) {
12686ffb55e5SLorenzo Bianconi 		if (hw->enable_mask & BIT(id))
1269f8710f03SLorenzo Bianconi 			return max_t(u32, ref->odr, odr);
12706ffb55e5SLorenzo Bianconi 		else
12716ffb55e5SLorenzo Bianconi 			return odr;
12726ffb55e5SLorenzo Bianconi 	} else {
12736ffb55e5SLorenzo Bianconi 		return (hw->enable_mask & BIT(id)) ? ref->odr : 0;
12746ffb55e5SLorenzo Bianconi 	}
12756ffb55e5SLorenzo Bianconi }
12766ffb55e5SLorenzo Bianconi 
1277f8710f03SLorenzo Bianconi static int
1278f8710f03SLorenzo Bianconi st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u32 req_odr)
12796ffb55e5SLorenzo Bianconi {
12806ffb55e5SLorenzo Bianconi 	struct st_lsm6dsx_sensor *ref_sensor = sensor;
128151a8b707SLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = sensor->hw;
128251a8b707SLorenzo Bianconi 	const struct st_lsm6dsx_reg *reg;
1283739aff87SLorenzo Bianconi 	unsigned int data;
12846ffb55e5SLorenzo Bianconi 	u8 val = 0;
12852ccc1503SLorenzo Bianconi 	int err;
12862ccc1503SLorenzo Bianconi 
12876ffb55e5SLorenzo Bianconi 	switch (sensor->id) {
128894be878cSTeng Qi 	case ST_LSM6DSX_ID_GYRO:
128994be878cSTeng Qi 		break;
12906ffb55e5SLorenzo Bianconi 	case ST_LSM6DSX_ID_EXT0:
12916ffb55e5SLorenzo Bianconi 	case ST_LSM6DSX_ID_EXT1:
12926ffb55e5SLorenzo Bianconi 	case ST_LSM6DSX_ID_EXT2:
12936ffb55e5SLorenzo Bianconi 	case ST_LSM6DSX_ID_ACC: {
1294f8710f03SLorenzo Bianconi 		u32 odr;
12956ffb55e5SLorenzo Bianconi 		int i;
12966ffb55e5SLorenzo Bianconi 
12976ffb55e5SLorenzo Bianconi 		/*
12986ffb55e5SLorenzo Bianconi 		 * i2c embedded controller relies on the accelerometer sensor as
12996ffb55e5SLorenzo Bianconi 		 * bus read/write trigger so we need to enable accel device
13006ffb55e5SLorenzo Bianconi 		 * at odr = max(accel_odr, ext_odr) in order to properly
13016ffb55e5SLorenzo Bianconi 		 * communicate with i2c slave devices
13026ffb55e5SLorenzo Bianconi 		 */
13036ffb55e5SLorenzo Bianconi 		ref_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]);
13046ffb55e5SLorenzo Bianconi 		for (i = ST_LSM6DSX_ID_ACC; i < ST_LSM6DSX_ID_MAX; i++) {
13056ffb55e5SLorenzo Bianconi 			if (!hw->iio_devs[i] || i == sensor->id)
13066ffb55e5SLorenzo Bianconi 				continue;
13076ffb55e5SLorenzo Bianconi 
13086ffb55e5SLorenzo Bianconi 			odr = st_lsm6dsx_check_odr_dependency(hw, req_odr, i);
13096ffb55e5SLorenzo Bianconi 			if (odr != req_odr)
13106ffb55e5SLorenzo Bianconi 				/* device already configured */
13116ffb55e5SLorenzo Bianconi 				return 0;
13126ffb55e5SLorenzo Bianconi 		}
13136ffb55e5SLorenzo Bianconi 		break;
13146ffb55e5SLorenzo Bianconi 	}
131594be878cSTeng Qi 	default: /* should never occur */
131694be878cSTeng Qi 		return -EINVAL;
13176ffb55e5SLorenzo Bianconi 	}
13186ffb55e5SLorenzo Bianconi 
13196ffb55e5SLorenzo Bianconi 	if (req_odr > 0) {
13206ffb55e5SLorenzo Bianconi 		err = st_lsm6dsx_check_odr(ref_sensor, req_odr, &val);
13212ccc1503SLorenzo Bianconi 		if (err < 0)
13222ccc1503SLorenzo Bianconi 			return err;
13236ffb55e5SLorenzo Bianconi 	}
13242ccc1503SLorenzo Bianconi 
132540dd7343SLorenzo Bianconi 	reg = &hw->settings->odr_table[ref_sensor->id].reg;
1326739aff87SLorenzo Bianconi 	data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask);
1327739aff87SLorenzo Bianconi 	return st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data);
13282ccc1503SLorenzo Bianconi }
13292ccc1503SLorenzo Bianconi 
1330bd41c445SLorenzo Bianconi static int
1331bd41c445SLorenzo Bianconi __st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor,
133217750443SLorenzo Bianconi 			       bool enable)
1333290a6ce1SLorenzo Bianconi {
133451a8b707SLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = sensor->hw;
1335f8710f03SLorenzo Bianconi 	u32 odr = enable ? sensor->odr : 0;
1336290a6ce1SLorenzo Bianconi 	int err;
1337290a6ce1SLorenzo Bianconi 
133817750443SLorenzo Bianconi 	err = st_lsm6dsx_set_odr(sensor, odr);
1339290a6ce1SLorenzo Bianconi 	if (err < 0)
1340290a6ce1SLorenzo Bianconi 		return err;
1341290a6ce1SLorenzo Bianconi 
134217750443SLorenzo Bianconi 	if (enable)
134317750443SLorenzo Bianconi 		hw->enable_mask |= BIT(sensor->id);
134417750443SLorenzo Bianconi 	else
134517750443SLorenzo Bianconi 		hw->enable_mask &= ~BIT(sensor->id);
1346290a6ce1SLorenzo Bianconi 
1347290a6ce1SLorenzo Bianconi 	return 0;
1348290a6ce1SLorenzo Bianconi }
1349290a6ce1SLorenzo Bianconi 
1350bd41c445SLorenzo Bianconi static int
1351bd41c445SLorenzo Bianconi st_lsm6dsx_check_events(struct st_lsm6dsx_sensor *sensor, bool enable)
1352bd41c445SLorenzo Bianconi {
1353bd41c445SLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = sensor->hw;
1354bd41c445SLorenzo Bianconi 
1355bd41c445SLorenzo Bianconi 	if (sensor->id == ST_LSM6DSX_ID_GYRO || enable)
1356bd41c445SLorenzo Bianconi 		return 0;
1357bd41c445SLorenzo Bianconi 
1358bd41c445SLorenzo Bianconi 	return hw->enable_event;
1359bd41c445SLorenzo Bianconi }
1360bd41c445SLorenzo Bianconi 
1361bd41c445SLorenzo Bianconi int st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor,
1362bd41c445SLorenzo Bianconi 				 bool enable)
1363bd41c445SLorenzo Bianconi {
1364bd41c445SLorenzo Bianconi 	if (st_lsm6dsx_check_events(sensor, enable))
1365bd41c445SLorenzo Bianconi 		return 0;
1366bd41c445SLorenzo Bianconi 
1367bd41c445SLorenzo Bianconi 	return __st_lsm6dsx_sensor_set_enable(sensor, enable);
1368bd41c445SLorenzo Bianconi }
1369bd41c445SLorenzo Bianconi 
1370290a6ce1SLorenzo Bianconi static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor,
1371290a6ce1SLorenzo Bianconi 				   u8 addr, int *val)
1372290a6ce1SLorenzo Bianconi {
137351a8b707SLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = sensor->hw;
1374290a6ce1SLorenzo Bianconi 	int err, delay;
1375290a6ce1SLorenzo Bianconi 	__le16 data;
1376290a6ce1SLorenzo Bianconi 
137717750443SLorenzo Bianconi 	err = st_lsm6dsx_sensor_set_enable(sensor, true);
1378290a6ce1SLorenzo Bianconi 	if (err < 0)
1379290a6ce1SLorenzo Bianconi 		return err;
1380290a6ce1SLorenzo Bianconi 
1381ea85bf90SLorenzo Bianconi 	/*
1382ea85bf90SLorenzo Bianconi 	 * we need to wait for sensor settling time before
1383ea85bf90SLorenzo Bianconi 	 * reading data in order to avoid corrupted samples
1384ea85bf90SLorenzo Bianconi 	 */
1385f8710f03SLorenzo Bianconi 	delay = 1000000000 / sensor->odr;
1386ea85bf90SLorenzo Bianconi 	usleep_range(3 * delay, 4 * delay);
1387290a6ce1SLorenzo Bianconi 
1388739aff87SLorenzo Bianconi 	err = st_lsm6dsx_read_locked(hw, addr, &data, sizeof(data));
1389290a6ce1SLorenzo Bianconi 	if (err < 0)
1390290a6ce1SLorenzo Bianconi 		return err;
1391290a6ce1SLorenzo Bianconi 
1392a2dd9bd9SLorenzo Bianconi 	if (!hw->enable_event) {
1393a2dd9bd9SLorenzo Bianconi 		err = st_lsm6dsx_sensor_set_enable(sensor, false);
1394a2dd9bd9SLorenzo Bianconi 		if (err < 0)
1395a2dd9bd9SLorenzo Bianconi 			return err;
1396a2dd9bd9SLorenzo Bianconi 	}
1397290a6ce1SLorenzo Bianconi 
13987b9ebe42SLorenzo Bianconi 	*val = (s16)le16_to_cpu(data);
1399290a6ce1SLorenzo Bianconi 
1400290a6ce1SLorenzo Bianconi 	return IIO_VAL_INT;
1401290a6ce1SLorenzo Bianconi }
1402290a6ce1SLorenzo Bianconi 
1403290a6ce1SLorenzo Bianconi static int st_lsm6dsx_read_raw(struct iio_dev *iio_dev,
1404290a6ce1SLorenzo Bianconi 			       struct iio_chan_spec const *ch,
1405290a6ce1SLorenzo Bianconi 			       int *val, int *val2, long mask)
1406290a6ce1SLorenzo Bianconi {
1407290a6ce1SLorenzo Bianconi 	struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
1408290a6ce1SLorenzo Bianconi 	int ret;
1409290a6ce1SLorenzo Bianconi 
1410290a6ce1SLorenzo Bianconi 	switch (mask) {
1411290a6ce1SLorenzo Bianconi 	case IIO_CHAN_INFO_RAW:
1412290a6ce1SLorenzo Bianconi 		ret = iio_device_claim_direct_mode(iio_dev);
1413290a6ce1SLorenzo Bianconi 		if (ret)
1414290a6ce1SLorenzo Bianconi 			break;
1415290a6ce1SLorenzo Bianconi 
1416290a6ce1SLorenzo Bianconi 		ret = st_lsm6dsx_read_oneshot(sensor, ch->address, val);
1417290a6ce1SLorenzo Bianconi 		iio_device_release_direct_mode(iio_dev);
1418290a6ce1SLorenzo Bianconi 		break;
1419290a6ce1SLorenzo Bianconi 	case IIO_CHAN_INFO_SAMP_FREQ:
1420f8710f03SLorenzo Bianconi 		*val = sensor->odr / 1000;
1421f8710f03SLorenzo Bianconi 		*val2 = (sensor->odr % 1000) * 1000;
1422f8710f03SLorenzo Bianconi 		ret = IIO_VAL_INT_PLUS_MICRO;
1423290a6ce1SLorenzo Bianconi 		break;
1424290a6ce1SLorenzo Bianconi 	case IIO_CHAN_INFO_SCALE:
1425290a6ce1SLorenzo Bianconi 		*val = 0;
1426290a6ce1SLorenzo Bianconi 		*val2 = sensor->gain;
142744a76de8SMario Tesi 		ret = IIO_VAL_INT_PLUS_NANO;
1428290a6ce1SLorenzo Bianconi 		break;
1429290a6ce1SLorenzo Bianconi 	default:
1430290a6ce1SLorenzo Bianconi 		ret = -EINVAL;
1431290a6ce1SLorenzo Bianconi 		break;
1432290a6ce1SLorenzo Bianconi 	}
1433290a6ce1SLorenzo Bianconi 
1434290a6ce1SLorenzo Bianconi 	return ret;
1435290a6ce1SLorenzo Bianconi }
1436290a6ce1SLorenzo Bianconi 
1437290a6ce1SLorenzo Bianconi static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev,
1438290a6ce1SLorenzo Bianconi 				struct iio_chan_spec const *chan,
1439290a6ce1SLorenzo Bianconi 				int val, int val2, long mask)
1440290a6ce1SLorenzo Bianconi {
1441290a6ce1SLorenzo Bianconi 	struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
1442290a6ce1SLorenzo Bianconi 	int err;
1443290a6ce1SLorenzo Bianconi 
1444290a6ce1SLorenzo Bianconi 	err = iio_device_claim_direct_mode(iio_dev);
1445290a6ce1SLorenzo Bianconi 	if (err)
1446290a6ce1SLorenzo Bianconi 		return err;
1447290a6ce1SLorenzo Bianconi 
1448290a6ce1SLorenzo Bianconi 	switch (mask) {
1449290a6ce1SLorenzo Bianconi 	case IIO_CHAN_INFO_SCALE:
1450290a6ce1SLorenzo Bianconi 		err = st_lsm6dsx_set_full_scale(sensor, val2);
1451290a6ce1SLorenzo Bianconi 		break;
14522ccc1503SLorenzo Bianconi 	case IIO_CHAN_INFO_SAMP_FREQ: {
14532ccc1503SLorenzo Bianconi 		u8 data;
14542ccc1503SLorenzo Bianconi 
1455f8710f03SLorenzo Bianconi 		val = val * 1000 + val2 / 1000;
1456fc3f6ad7SLorenzo Bianconi 		val = st_lsm6dsx_check_odr(sensor, val, &data);
1457fc3f6ad7SLorenzo Bianconi 		if (val < 0)
1458fc3f6ad7SLorenzo Bianconi 			err = val;
1459fc3f6ad7SLorenzo Bianconi 		else
14605e3c3e33SLorenzo Bianconi 			sensor->odr = val;
1461290a6ce1SLorenzo Bianconi 		break;
14622ccc1503SLorenzo Bianconi 	}
1463290a6ce1SLorenzo Bianconi 	default:
1464290a6ce1SLorenzo Bianconi 		err = -EINVAL;
1465290a6ce1SLorenzo Bianconi 		break;
1466290a6ce1SLorenzo Bianconi 	}
1467290a6ce1SLorenzo Bianconi 
1468290a6ce1SLorenzo Bianconi 	iio_device_release_direct_mode(iio_dev);
1469290a6ce1SLorenzo Bianconi 
1470290a6ce1SLorenzo Bianconi 	return err;
1471290a6ce1SLorenzo Bianconi }
1472290a6ce1SLorenzo Bianconi 
1473b5969abfSSean Nyekjaer static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, int state)
1474b5969abfSSean Nyekjaer {
147584b2e7c3SLorenzo Bianconi 	const struct st_lsm6dsx_reg *reg;
147604ca37d5SLorenzo Bianconi 	unsigned int data;
1477b5969abfSSean Nyekjaer 	int err;
1478b5969abfSSean Nyekjaer 
14797e906103SLorenzo Bianconi 	if (!hw->settings->irq_config.irq1_func.addr)
1480b5969abfSSean Nyekjaer 		return -ENOTSUPP;
1481b5969abfSSean Nyekjaer 
148284b2e7c3SLorenzo Bianconi 	reg = &hw->settings->event_settings.enable_reg;
148384b2e7c3SLorenzo Bianconi 	if (reg->addr) {
148404ca37d5SLorenzo Bianconi 		data = ST_LSM6DSX_SHIFT_VAL(state, reg->mask);
148504ca37d5SLorenzo Bianconi 		err = st_lsm6dsx_update_bits_locked(hw, reg->addr,
148604ca37d5SLorenzo Bianconi 						    reg->mask, data);
1487b5969abfSSean Nyekjaer 		if (err < 0)
1488b5969abfSSean Nyekjaer 			return err;
148984b2e7c3SLorenzo Bianconi 	}
1490b5969abfSSean Nyekjaer 
1491b5969abfSSean Nyekjaer 	/* Enable wakeup interrupt */
149204ca37d5SLorenzo Bianconi 	data = ST_LSM6DSX_SHIFT_VAL(state, hw->irq_routing->mask);
149304ca37d5SLorenzo Bianconi 	return st_lsm6dsx_update_bits_locked(hw, hw->irq_routing->addr,
149404ca37d5SLorenzo Bianconi 					     hw->irq_routing->mask, data);
1495b5969abfSSean Nyekjaer }
1496b5969abfSSean Nyekjaer 
1497b5969abfSSean Nyekjaer static int st_lsm6dsx_read_event(struct iio_dev *iio_dev,
1498b5969abfSSean Nyekjaer 				 const struct iio_chan_spec *chan,
1499b5969abfSSean Nyekjaer 				 enum iio_event_type type,
1500b5969abfSSean Nyekjaer 				 enum iio_event_direction dir,
1501b5969abfSSean Nyekjaer 				 enum iio_event_info info,
1502b5969abfSSean Nyekjaer 				 int *val, int *val2)
1503b5969abfSSean Nyekjaer {
1504b5969abfSSean Nyekjaer 	struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
1505b5969abfSSean Nyekjaer 	struct st_lsm6dsx_hw *hw = sensor->hw;
1506b5969abfSSean Nyekjaer 
1507b5969abfSSean Nyekjaer 	if (type != IIO_EV_TYPE_THRESH)
1508b5969abfSSean Nyekjaer 		return -EINVAL;
1509b5969abfSSean Nyekjaer 
1510b5969abfSSean Nyekjaer 	*val2 = 0;
1511b5969abfSSean Nyekjaer 	*val = hw->event_threshold;
1512b5969abfSSean Nyekjaer 
1513b5969abfSSean Nyekjaer 	return IIO_VAL_INT;
1514b5969abfSSean Nyekjaer }
1515b5969abfSSean Nyekjaer 
1516b307f495SLorenzo Bianconi static int
1517b307f495SLorenzo Bianconi st_lsm6dsx_write_event(struct iio_dev *iio_dev,
1518b5969abfSSean Nyekjaer 		       const struct iio_chan_spec *chan,
1519b5969abfSSean Nyekjaer 		       enum iio_event_type type,
1520b5969abfSSean Nyekjaer 		       enum iio_event_direction dir,
1521b5969abfSSean Nyekjaer 		       enum iio_event_info info,
1522b5969abfSSean Nyekjaer 		       int val, int val2)
1523b5969abfSSean Nyekjaer {
1524b5969abfSSean Nyekjaer 	struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
1525b5969abfSSean Nyekjaer 	struct st_lsm6dsx_hw *hw = sensor->hw;
152604ca37d5SLorenzo Bianconi 	const struct st_lsm6dsx_reg *reg;
152704ca37d5SLorenzo Bianconi 	unsigned int data;
1528b5969abfSSean Nyekjaer 	int err;
1529b5969abfSSean Nyekjaer 
1530b5969abfSSean Nyekjaer 	if (type != IIO_EV_TYPE_THRESH)
1531b5969abfSSean Nyekjaer 		return -EINVAL;
1532b5969abfSSean Nyekjaer 
1533b5969abfSSean Nyekjaer 	if (val < 0 || val > 31)
1534b5969abfSSean Nyekjaer 		return -EINVAL;
1535b5969abfSSean Nyekjaer 
153604ca37d5SLorenzo Bianconi 	reg = &hw->settings->event_settings.wakeup_reg;
153704ca37d5SLorenzo Bianconi 	data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask);
153804ca37d5SLorenzo Bianconi 	err = st_lsm6dsx_update_bits_locked(hw, reg->addr,
153904ca37d5SLorenzo Bianconi 					    reg->mask, data);
154004ca37d5SLorenzo Bianconi 	if (err < 0)
1541b5969abfSSean Nyekjaer 		return -EINVAL;
1542b5969abfSSean Nyekjaer 
1543b5969abfSSean Nyekjaer 	hw->event_threshold = val;
1544b5969abfSSean Nyekjaer 
1545b5969abfSSean Nyekjaer 	return 0;
1546b5969abfSSean Nyekjaer }
1547b5969abfSSean Nyekjaer 
1548b307f495SLorenzo Bianconi static int
1549b307f495SLorenzo Bianconi st_lsm6dsx_read_event_config(struct iio_dev *iio_dev,
1550b5969abfSSean Nyekjaer 			     const struct iio_chan_spec *chan,
1551b5969abfSSean Nyekjaer 			     enum iio_event_type type,
1552b5969abfSSean Nyekjaer 			     enum iio_event_direction dir)
1553b5969abfSSean Nyekjaer {
1554b5969abfSSean Nyekjaer 	struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
1555b5969abfSSean Nyekjaer 	struct st_lsm6dsx_hw *hw = sensor->hw;
1556b5969abfSSean Nyekjaer 
1557b5969abfSSean Nyekjaer 	if (type != IIO_EV_TYPE_THRESH)
1558b5969abfSSean Nyekjaer 		return -EINVAL;
1559b5969abfSSean Nyekjaer 
15601aabad1fSSean Nyekjaer 	return !!(hw->enable_event & BIT(chan->channel2));
1561b5969abfSSean Nyekjaer }
1562b5969abfSSean Nyekjaer 
1563b307f495SLorenzo Bianconi static int
1564b307f495SLorenzo Bianconi st_lsm6dsx_write_event_config(struct iio_dev *iio_dev,
1565b5969abfSSean Nyekjaer 			      const struct iio_chan_spec *chan,
1566b5969abfSSean Nyekjaer 			      enum iio_event_type type,
1567b307f495SLorenzo Bianconi 			      enum iio_event_direction dir, int state)
1568b5969abfSSean Nyekjaer {
1569b5969abfSSean Nyekjaer 	struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
1570b5969abfSSean Nyekjaer 	struct st_lsm6dsx_hw *hw = sensor->hw;
15711aabad1fSSean Nyekjaer 	u8 enable_event;
1572bd41c445SLorenzo Bianconi 	int err;
1573b5969abfSSean Nyekjaer 
1574b5969abfSSean Nyekjaer 	if (type != IIO_EV_TYPE_THRESH)
1575b5969abfSSean Nyekjaer 		return -EINVAL;
1576b5969abfSSean Nyekjaer 
15771aabad1fSSean Nyekjaer 	if (state) {
15781aabad1fSSean Nyekjaer 		enable_event = hw->enable_event | BIT(chan->channel2);
15791aabad1fSSean Nyekjaer 
1580b5969abfSSean Nyekjaer 		/* do not enable events if they are already enabled */
15811aabad1fSSean Nyekjaer 		if (hw->enable_event)
15821aabad1fSSean Nyekjaer 			goto out;
15831aabad1fSSean Nyekjaer 	} else {
15841aabad1fSSean Nyekjaer 		enable_event = hw->enable_event & ~BIT(chan->channel2);
15851aabad1fSSean Nyekjaer 
15861aabad1fSSean Nyekjaer 		/* only turn off sensor if no events is enabled */
15871aabad1fSSean Nyekjaer 		if (enable_event)
15881aabad1fSSean Nyekjaer 			goto out;
15891aabad1fSSean Nyekjaer 	}
15901aabad1fSSean Nyekjaer 
15911aabad1fSSean Nyekjaer 	/* stop here if no changes have been made */
15921aabad1fSSean Nyekjaer 	if (hw->enable_event == enable_event)
1593b5969abfSSean Nyekjaer 		return 0;
1594b5969abfSSean Nyekjaer 
1595b5969abfSSean Nyekjaer 	err = st_lsm6dsx_event_setup(hw, state);
1596b5969abfSSean Nyekjaer 	if (err < 0)
1597b5969abfSSean Nyekjaer 		return err;
1598b5969abfSSean Nyekjaer 
1599d278d447SLorenzo Bianconi 	mutex_lock(&hw->conf_lock);
1600bd41c445SLorenzo Bianconi 	if (enable_event || !(hw->fifo_mask & BIT(sensor->id)))
1601bd41c445SLorenzo Bianconi 		err = __st_lsm6dsx_sensor_set_enable(sensor, state);
1602d278d447SLorenzo Bianconi 	mutex_unlock(&hw->conf_lock);
1603b5969abfSSean Nyekjaer 	if (err < 0)
1604b5969abfSSean Nyekjaer 		return err;
1605b5969abfSSean Nyekjaer 
16061aabad1fSSean Nyekjaer out:
16071aabad1fSSean Nyekjaer 	hw->enable_event = enable_event;
1608b5969abfSSean Nyekjaer 
1609b5969abfSSean Nyekjaer 	return 0;
1610b5969abfSSean Nyekjaer }
1611b5969abfSSean Nyekjaer 
1612d40464f3SLorenzo Bianconi int st_lsm6dsx_set_watermark(struct iio_dev *iio_dev, unsigned int val)
1613290a6ce1SLorenzo Bianconi {
1614290a6ce1SLorenzo Bianconi 	struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
1615290a6ce1SLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = sensor->hw;
16168f2a88a2SLorenzo Bianconi 	int err;
1617290a6ce1SLorenzo Bianconi 
16181b7da2faSLorenzo Bianconi 	if (val < 1 || val > hw->settings->fifo_ops.max_size)
1619290a6ce1SLorenzo Bianconi 		return -EINVAL;
1620290a6ce1SLorenzo Bianconi 
1621335eaedcSLorenzo Bianconi 	mutex_lock(&hw->conf_lock);
1622335eaedcSLorenzo Bianconi 
1623290a6ce1SLorenzo Bianconi 	err = st_lsm6dsx_update_watermark(sensor, val);
1624335eaedcSLorenzo Bianconi 
1625335eaedcSLorenzo Bianconi 	mutex_unlock(&hw->conf_lock);
1626335eaedcSLorenzo Bianconi 
1627290a6ce1SLorenzo Bianconi 	if (err < 0)
1628290a6ce1SLorenzo Bianconi 		return err;
1629290a6ce1SLorenzo Bianconi 
1630290a6ce1SLorenzo Bianconi 	sensor->watermark = val;
1631290a6ce1SLorenzo Bianconi 
1632290a6ce1SLorenzo Bianconi 	return 0;
1633290a6ce1SLorenzo Bianconi }
1634290a6ce1SLorenzo Bianconi 
1635290a6ce1SLorenzo Bianconi static ssize_t
1636290a6ce1SLorenzo Bianconi st_lsm6dsx_sysfs_sampling_frequency_avail(struct device *dev,
1637290a6ce1SLorenzo Bianconi 					  struct device_attribute *attr,
1638290a6ce1SLorenzo Bianconi 					  char *buf)
1639290a6ce1SLorenzo Bianconi {
16406270bf1fSHaibo Chen 	struct st_lsm6dsx_sensor *sensor = iio_priv(dev_to_iio_dev(dev));
164159af4e20SLorenzo Bianconi 	const struct st_lsm6dsx_odr_table_entry *odr_table;
1642290a6ce1SLorenzo Bianconi 	int i, len = 0;
1643290a6ce1SLorenzo Bianconi 
164459af4e20SLorenzo Bianconi 	odr_table = &sensor->hw->settings->odr_table[sensor->id];
164559af4e20SLorenzo Bianconi 	for (i = 0; i < odr_table->odr_len; i++)
1646f8710f03SLorenzo Bianconi 		len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%03d ",
1647f8710f03SLorenzo Bianconi 				 odr_table->odr_avl[i].milli_hz / 1000,
1648f8710f03SLorenzo Bianconi 				 odr_table->odr_avl[i].milli_hz % 1000);
1649290a6ce1SLorenzo Bianconi 	buf[len - 1] = '\n';
1650290a6ce1SLorenzo Bianconi 
1651290a6ce1SLorenzo Bianconi 	return len;
1652290a6ce1SLorenzo Bianconi }
1653290a6ce1SLorenzo Bianconi 
1654290a6ce1SLorenzo Bianconi static ssize_t st_lsm6dsx_sysfs_scale_avail(struct device *dev,
1655290a6ce1SLorenzo Bianconi 					    struct device_attribute *attr,
1656290a6ce1SLorenzo Bianconi 					    char *buf)
1657290a6ce1SLorenzo Bianconi {
16586270bf1fSHaibo Chen 	struct st_lsm6dsx_sensor *sensor = iio_priv(dev_to_iio_dev(dev));
16590f7e1728SLorenzo Bianconi 	const struct st_lsm6dsx_fs_table_entry *fs_table;
1660640aca3fSLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = sensor->hw;
1661290a6ce1SLorenzo Bianconi 	int i, len = 0;
1662290a6ce1SLorenzo Bianconi 
166385ae3aeeSLorenzo Bianconi 	fs_table = &hw->settings->fs_table[sensor->id];
166485ae3aeeSLorenzo Bianconi 	for (i = 0; i < fs_table->fs_len; i++)
166544a76de8SMario Tesi 		len += scnprintf(buf + len, PAGE_SIZE - len, "0.%09u ",
16660f7e1728SLorenzo Bianconi 				 fs_table->fs_avl[i].gain);
1667290a6ce1SLorenzo Bianconi 	buf[len - 1] = '\n';
1668290a6ce1SLorenzo Bianconi 
1669290a6ce1SLorenzo Bianconi 	return len;
1670290a6ce1SLorenzo Bianconi }
1671290a6ce1SLorenzo Bianconi 
167244a76de8SMario Tesi static int st_lsm6dsx_write_raw_get_fmt(struct iio_dev *indio_dev,
167344a76de8SMario Tesi 					struct iio_chan_spec const *chan,
167444a76de8SMario Tesi 					long mask)
167544a76de8SMario Tesi {
167644a76de8SMario Tesi 	switch (mask) {
167744a76de8SMario Tesi 	case IIO_CHAN_INFO_SCALE:
167844a76de8SMario Tesi 		switch (chan->type) {
167944a76de8SMario Tesi 		case IIO_ANGL_VEL:
168044a76de8SMario Tesi 		case IIO_ACCEL:
168144a76de8SMario Tesi 			return IIO_VAL_INT_PLUS_NANO;
168244a76de8SMario Tesi 		default:
168344a76de8SMario Tesi 			return IIO_VAL_INT_PLUS_MICRO;
168444a76de8SMario Tesi 		}
168544a76de8SMario Tesi 	default:
168644a76de8SMario Tesi 		return IIO_VAL_INT_PLUS_MICRO;
168744a76de8SMario Tesi 	}
168844a76de8SMario Tesi }
168944a76de8SMario Tesi 
1690290a6ce1SLorenzo Bianconi static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(st_lsm6dsx_sysfs_sampling_frequency_avail);
1691290a6ce1SLorenzo Bianconi static IIO_DEVICE_ATTR(in_accel_scale_available, 0444,
1692290a6ce1SLorenzo Bianconi 		       st_lsm6dsx_sysfs_scale_avail, NULL, 0);
1693290a6ce1SLorenzo Bianconi static IIO_DEVICE_ATTR(in_anglvel_scale_available, 0444,
1694290a6ce1SLorenzo Bianconi 		       st_lsm6dsx_sysfs_scale_avail, NULL, 0);
1695290a6ce1SLorenzo Bianconi 
1696290a6ce1SLorenzo Bianconi static struct attribute *st_lsm6dsx_acc_attributes[] = {
1697290a6ce1SLorenzo Bianconi 	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
1698290a6ce1SLorenzo Bianconi 	&iio_dev_attr_in_accel_scale_available.dev_attr.attr,
1699290a6ce1SLorenzo Bianconi 	NULL,
1700290a6ce1SLorenzo Bianconi };
1701290a6ce1SLorenzo Bianconi 
1702290a6ce1SLorenzo Bianconi static const struct attribute_group st_lsm6dsx_acc_attribute_group = {
1703290a6ce1SLorenzo Bianconi 	.attrs = st_lsm6dsx_acc_attributes,
1704290a6ce1SLorenzo Bianconi };
1705290a6ce1SLorenzo Bianconi 
1706290a6ce1SLorenzo Bianconi static const struct iio_info st_lsm6dsx_acc_info = {
1707290a6ce1SLorenzo Bianconi 	.attrs = &st_lsm6dsx_acc_attribute_group,
1708290a6ce1SLorenzo Bianconi 	.read_raw = st_lsm6dsx_read_raw,
1709290a6ce1SLorenzo Bianconi 	.write_raw = st_lsm6dsx_write_raw,
1710b5969abfSSean Nyekjaer 	.read_event_value = st_lsm6dsx_read_event,
1711b5969abfSSean Nyekjaer 	.write_event_value = st_lsm6dsx_write_event,
1712b5969abfSSean Nyekjaer 	.read_event_config = st_lsm6dsx_read_event_config,
1713b5969abfSSean Nyekjaer 	.write_event_config = st_lsm6dsx_write_event_config,
1714290a6ce1SLorenzo Bianconi 	.hwfifo_set_watermark = st_lsm6dsx_set_watermark,
171544a76de8SMario Tesi 	.write_raw_get_fmt = st_lsm6dsx_write_raw_get_fmt,
1716290a6ce1SLorenzo Bianconi };
1717290a6ce1SLorenzo Bianconi 
1718290a6ce1SLorenzo Bianconi static struct attribute *st_lsm6dsx_gyro_attributes[] = {
1719290a6ce1SLorenzo Bianconi 	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
1720290a6ce1SLorenzo Bianconi 	&iio_dev_attr_in_anglvel_scale_available.dev_attr.attr,
1721290a6ce1SLorenzo Bianconi 	NULL,
1722290a6ce1SLorenzo Bianconi };
1723290a6ce1SLorenzo Bianconi 
1724290a6ce1SLorenzo Bianconi static const struct attribute_group st_lsm6dsx_gyro_attribute_group = {
1725290a6ce1SLorenzo Bianconi 	.attrs = st_lsm6dsx_gyro_attributes,
1726290a6ce1SLorenzo Bianconi };
1727290a6ce1SLorenzo Bianconi 
1728290a6ce1SLorenzo Bianconi static const struct iio_info st_lsm6dsx_gyro_info = {
1729290a6ce1SLorenzo Bianconi 	.attrs = &st_lsm6dsx_gyro_attribute_group,
1730290a6ce1SLorenzo Bianconi 	.read_raw = st_lsm6dsx_read_raw,
1731290a6ce1SLorenzo Bianconi 	.write_raw = st_lsm6dsx_write_raw,
1732290a6ce1SLorenzo Bianconi 	.hwfifo_set_watermark = st_lsm6dsx_set_watermark,
173344a76de8SMario Tesi 	.write_raw_get_fmt = st_lsm6dsx_write_raw_get_fmt,
1734290a6ce1SLorenzo Bianconi };
1735290a6ce1SLorenzo Bianconi 
173603d4c566SAndy Shevchenko static int st_lsm6dsx_get_drdy_pin(struct st_lsm6dsx_hw *hw, int *drdy_pin)
1737dba32904SLorenzo Bianconi {
173803d4c566SAndy Shevchenko 	struct device *dev = hw->dev;
1739dba32904SLorenzo Bianconi 
174003d4c566SAndy Shevchenko 	if (!dev_fwnode(dev))
1741dba32904SLorenzo Bianconi 		return -EINVAL;
1742dba32904SLorenzo Bianconi 
174303d4c566SAndy Shevchenko 	return device_property_read_u32(dev, "st,drdy-int-pin", drdy_pin);
1744dba32904SLorenzo Bianconi }
1745dba32904SLorenzo Bianconi 
17467e906103SLorenzo Bianconi static int
17477e906103SLorenzo Bianconi st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw,
17487e906103SLorenzo Bianconi 			const struct st_lsm6dsx_reg **drdy_reg)
1749dba32904SLorenzo Bianconi {
1750dba32904SLorenzo Bianconi 	int err = 0, drdy_pin;
1751dba32904SLorenzo Bianconi 
175203d4c566SAndy Shevchenko 	if (st_lsm6dsx_get_drdy_pin(hw, &drdy_pin) < 0) {
1753dba32904SLorenzo Bianconi 		struct st_sensors_platform_data *pdata;
1754dba32904SLorenzo Bianconi 		struct device *dev = hw->dev;
1755dba32904SLorenzo Bianconi 
1756dba32904SLorenzo Bianconi 		pdata = (struct st_sensors_platform_data *)dev->platform_data;
1757dba32904SLorenzo Bianconi 		drdy_pin = pdata ? pdata->drdy_int_pin : 1;
1758dba32904SLorenzo Bianconi 	}
1759dba32904SLorenzo Bianconi 
1760dba32904SLorenzo Bianconi 	switch (drdy_pin) {
1761dba32904SLorenzo Bianconi 	case 1:
17627e906103SLorenzo Bianconi 		hw->irq_routing = &hw->settings->irq_config.irq1_func;
17637e906103SLorenzo Bianconi 		*drdy_reg = &hw->settings->irq_config.irq1;
1764dba32904SLorenzo Bianconi 		break;
1765dba32904SLorenzo Bianconi 	case 2:
17667e906103SLorenzo Bianconi 		hw->irq_routing = &hw->settings->irq_config.irq2_func;
17677e906103SLorenzo Bianconi 		*drdy_reg = &hw->settings->irq_config.irq2;
1768dba32904SLorenzo Bianconi 		break;
1769dba32904SLorenzo Bianconi 	default:
1770dba32904SLorenzo Bianconi 		dev_err(hw->dev, "unsupported data ready pin\n");
1771dba32904SLorenzo Bianconi 		err = -EINVAL;
1772dba32904SLorenzo Bianconi 		break;
1773dba32904SLorenzo Bianconi 	}
1774dba32904SLorenzo Bianconi 
1775dba32904SLorenzo Bianconi 	return err;
1776dba32904SLorenzo Bianconi }
1777dba32904SLorenzo Bianconi 
1778c91c1c84SLorenzo Bianconi static int st_lsm6dsx_init_shub(struct st_lsm6dsx_hw *hw)
1779c91c1c84SLorenzo Bianconi {
1780c91c1c84SLorenzo Bianconi 	const struct st_lsm6dsx_shub_settings *hub_settings;
1781c91c1c84SLorenzo Bianconi 	struct st_sensors_platform_data *pdata;
178203d4c566SAndy Shevchenko 	struct device *dev = hw->dev;
1783c91c1c84SLorenzo Bianconi 	unsigned int data;
1784c91c1c84SLorenzo Bianconi 	int err = 0;
1785c91c1c84SLorenzo Bianconi 
1786c91c1c84SLorenzo Bianconi 	hub_settings = &hw->settings->shub_settings;
1787c91c1c84SLorenzo Bianconi 
178803d4c566SAndy Shevchenko 	pdata = (struct st_sensors_platform_data *)dev->platform_data;
178903d4c566SAndy Shevchenko 	if ((dev_fwnode(dev) && device_property_read_bool(dev, "st,pullups")) ||
1790c91c1c84SLorenzo Bianconi 	    (pdata && pdata->pullups)) {
17913a431957SLorenzo Bianconi 		if (hub_settings->pullup_en.sec_page) {
1792c91c1c84SLorenzo Bianconi 			err = st_lsm6dsx_set_page(hw, true);
1793c91c1c84SLorenzo Bianconi 			if (err < 0)
1794c91c1c84SLorenzo Bianconi 				return err;
17953a431957SLorenzo Bianconi 		}
1796c91c1c84SLorenzo Bianconi 
1797c91c1c84SLorenzo Bianconi 		data = ST_LSM6DSX_SHIFT_VAL(1, hub_settings->pullup_en.mask);
1798c91c1c84SLorenzo Bianconi 		err = regmap_update_bits(hw->regmap,
1799c91c1c84SLorenzo Bianconi 					 hub_settings->pullup_en.addr,
1800c91c1c84SLorenzo Bianconi 					 hub_settings->pullup_en.mask, data);
1801c91c1c84SLorenzo Bianconi 
18023a431957SLorenzo Bianconi 		if (hub_settings->pullup_en.sec_page)
1803c91c1c84SLorenzo Bianconi 			st_lsm6dsx_set_page(hw, false);
1804c91c1c84SLorenzo Bianconi 
1805c91c1c84SLorenzo Bianconi 		if (err < 0)
1806c91c1c84SLorenzo Bianconi 			return err;
1807c91c1c84SLorenzo Bianconi 	}
1808c91c1c84SLorenzo Bianconi 
1809c91c1c84SLorenzo Bianconi 	if (hub_settings->aux_sens.addr) {
1810c91c1c84SLorenzo Bianconi 		/* configure aux sensors */
1811c91c1c84SLorenzo Bianconi 		err = st_lsm6dsx_set_page(hw, true);
1812c91c1c84SLorenzo Bianconi 		if (err < 0)
1813c91c1c84SLorenzo Bianconi 			return err;
1814c91c1c84SLorenzo Bianconi 
1815c91c1c84SLorenzo Bianconi 		data = ST_LSM6DSX_SHIFT_VAL(3, hub_settings->aux_sens.mask);
1816c91c1c84SLorenzo Bianconi 		err = regmap_update_bits(hw->regmap,
1817c91c1c84SLorenzo Bianconi 					 hub_settings->aux_sens.addr,
1818c91c1c84SLorenzo Bianconi 					 hub_settings->aux_sens.mask, data);
1819c91c1c84SLorenzo Bianconi 
1820c91c1c84SLorenzo Bianconi 		st_lsm6dsx_set_page(hw, false);
1821e485e2a2SLorenzo Bianconi 
1822e485e2a2SLorenzo Bianconi 		if (err < 0)
1823e485e2a2SLorenzo Bianconi 			return err;
1824e485e2a2SLorenzo Bianconi 	}
1825e485e2a2SLorenzo Bianconi 
1826e485e2a2SLorenzo Bianconi 	if (hub_settings->emb_func.addr) {
1827e485e2a2SLorenzo Bianconi 		data = ST_LSM6DSX_SHIFT_VAL(1, hub_settings->emb_func.mask);
1828e485e2a2SLorenzo Bianconi 		err = regmap_update_bits(hw->regmap,
1829e485e2a2SLorenzo Bianconi 					 hub_settings->emb_func.addr,
1830e485e2a2SLorenzo Bianconi 					 hub_settings->emb_func.mask, data);
1831c91c1c84SLorenzo Bianconi 	}
1832c91c1c84SLorenzo Bianconi 
1833c91c1c84SLorenzo Bianconi 	return err;
1834c91c1c84SLorenzo Bianconi }
1835c91c1c84SLorenzo Bianconi 
183621345107SLorenzo Bianconi static int st_lsm6dsx_init_hw_timer(struct st_lsm6dsx_hw *hw)
183721345107SLorenzo Bianconi {
183821345107SLorenzo Bianconi 	const struct st_lsm6dsx_hw_ts_settings *ts_settings;
183921345107SLorenzo Bianconi 	int err, val;
184021345107SLorenzo Bianconi 
184121345107SLorenzo Bianconi 	ts_settings = &hw->settings->ts_settings;
184221345107SLorenzo Bianconi 	/* enable hw timestamp generation if necessary */
184321345107SLorenzo Bianconi 	if (ts_settings->timer_en.addr) {
184421345107SLorenzo Bianconi 		val = ST_LSM6DSX_SHIFT_VAL(1, ts_settings->timer_en.mask);
184521345107SLorenzo Bianconi 		err = regmap_update_bits(hw->regmap,
184621345107SLorenzo Bianconi 					 ts_settings->timer_en.addr,
184721345107SLorenzo Bianconi 					 ts_settings->timer_en.mask, val);
184821345107SLorenzo Bianconi 		if (err < 0)
184921345107SLorenzo Bianconi 			return err;
185021345107SLorenzo Bianconi 	}
185121345107SLorenzo Bianconi 
185221345107SLorenzo Bianconi 	/* enable high resolution for hw ts timer if necessary */
185321345107SLorenzo Bianconi 	if (ts_settings->hr_timer.addr) {
185421345107SLorenzo Bianconi 		val = ST_LSM6DSX_SHIFT_VAL(1, ts_settings->hr_timer.mask);
185521345107SLorenzo Bianconi 		err = regmap_update_bits(hw->regmap,
185621345107SLorenzo Bianconi 					 ts_settings->hr_timer.addr,
185721345107SLorenzo Bianconi 					 ts_settings->hr_timer.mask, val);
185821345107SLorenzo Bianconi 		if (err < 0)
185921345107SLorenzo Bianconi 			return err;
186021345107SLorenzo Bianconi 	}
186121345107SLorenzo Bianconi 
186221345107SLorenzo Bianconi 	/* enable ts queueing in FIFO if necessary */
186321345107SLorenzo Bianconi 	if (ts_settings->fifo_en.addr) {
186421345107SLorenzo Bianconi 		val = ST_LSM6DSX_SHIFT_VAL(1, ts_settings->fifo_en.mask);
186521345107SLorenzo Bianconi 		err = regmap_update_bits(hw->regmap,
186621345107SLorenzo Bianconi 					 ts_settings->fifo_en.addr,
186721345107SLorenzo Bianconi 					 ts_settings->fifo_en.mask, val);
186821345107SLorenzo Bianconi 		if (err < 0)
186921345107SLorenzo Bianconi 			return err;
187021345107SLorenzo Bianconi 	}
1871cb3b6b8eSMario Tesi 
1872cb3b6b8eSMario Tesi 	/* calibrate timestamp sensitivity */
1873cb3b6b8eSMario Tesi 	hw->ts_gain = ST_LSM6DSX_TS_SENSITIVITY;
1874cb3b6b8eSMario Tesi 	if (ts_settings->freq_fine) {
1875cb3b6b8eSMario Tesi 		err = regmap_read(hw->regmap, ts_settings->freq_fine, &val);
1876cb3b6b8eSMario Tesi 		if (err < 0)
1877cb3b6b8eSMario Tesi 			return err;
1878cb3b6b8eSMario Tesi 
1879cb3b6b8eSMario Tesi 		/*
1880cb3b6b8eSMario Tesi 		 * linearize the AN5192 formula:
1881cb3b6b8eSMario Tesi 		 * 1 / (1 + x) ~= 1 - x (Taylor’s Series)
1882cb3b6b8eSMario Tesi 		 * ttrim[s] = 1 / (40000 * (1 + 0.0015 * val))
1883cb3b6b8eSMario Tesi 		 * ttrim[ns] ~= 25000 - 37.5 * val
1884cb3b6b8eSMario Tesi 		 * ttrim[ns] ~= 25000 - (37500 * val) / 1000
1885cb3b6b8eSMario Tesi 		 */
1886cb3b6b8eSMario Tesi 		hw->ts_gain -= ((s8)val * 37500) / 1000;
1887cb3b6b8eSMario Tesi 	}
1888cb3b6b8eSMario Tesi 
188921345107SLorenzo Bianconi 	return 0;
189021345107SLorenzo Bianconi }
189121345107SLorenzo Bianconi 
18923a63da26SLorenzo Bianconi static int st_lsm6dsx_reset_device(struct st_lsm6dsx_hw *hw)
1893290a6ce1SLorenzo Bianconi {
18947e906103SLorenzo Bianconi 	const struct st_lsm6dsx_reg *reg;
1895290a6ce1SLorenzo Bianconi 	int err;
1896290a6ce1SLorenzo Bianconi 
18973a63da26SLorenzo Bianconi 	/*
18983a63da26SLorenzo Bianconi 	 * flush hw FIFO before device reset in order to avoid
18993a63da26SLorenzo Bianconi 	 * possible races on interrupt line 1. If the first interrupt
19003a63da26SLorenzo Bianconi 	 * line is asserted during hw reset the device will work in
19013a63da26SLorenzo Bianconi 	 * I3C-only mode (if it is supported)
19023a63da26SLorenzo Bianconi 	 */
19033a63da26SLorenzo Bianconi 	err = st_lsm6dsx_flush_fifo(hw);
19043a63da26SLorenzo Bianconi 	if (err < 0 && err != -ENOTSUPP)
19053a63da26SLorenzo Bianconi 		return err;
19063a63da26SLorenzo Bianconi 
190719435425SLorenzo Bianconi 	/* device sw reset */
190866b662a1SLorenzo Bianconi 	reg = &hw->settings->reset;
190966b662a1SLorenzo Bianconi 	err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
191066b662a1SLorenzo Bianconi 				 ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
1911290a6ce1SLorenzo Bianconi 	if (err < 0)
1912290a6ce1SLorenzo Bianconi 		return err;
1913290a6ce1SLorenzo Bianconi 
191419435425SLorenzo Bianconi 	msleep(50);
191519435425SLorenzo Bianconi 
191619435425SLorenzo Bianconi 	/* reload trimming parameter */
191766b662a1SLorenzo Bianconi 	reg = &hw->settings->boot;
191866b662a1SLorenzo Bianconi 	err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
191966b662a1SLorenzo Bianconi 				 ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
192019435425SLorenzo Bianconi 	if (err < 0)
192119435425SLorenzo Bianconi 		return err;
192219435425SLorenzo Bianconi 
192319435425SLorenzo Bianconi 	msleep(50);
1924290a6ce1SLorenzo Bianconi 
19253a63da26SLorenzo Bianconi 	return 0;
19263a63da26SLorenzo Bianconi }
19273a63da26SLorenzo Bianconi 
19283a63da26SLorenzo Bianconi static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw)
19293a63da26SLorenzo Bianconi {
19303a63da26SLorenzo Bianconi 	const struct st_lsm6dsx_reg *reg;
19313a63da26SLorenzo Bianconi 	int err;
19323a63da26SLorenzo Bianconi 
19333a63da26SLorenzo Bianconi 	err = st_lsm6dsx_reset_device(hw);
19343a63da26SLorenzo Bianconi 	if (err < 0)
19353a63da26SLorenzo Bianconi 		return err;
19363a63da26SLorenzo Bianconi 
1937290a6ce1SLorenzo Bianconi 	/* enable Block Data Update */
193866b662a1SLorenzo Bianconi 	reg = &hw->settings->bdu;
193966b662a1SLorenzo Bianconi 	err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
194066b662a1SLorenzo Bianconi 				 ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
1941290a6ce1SLorenzo Bianconi 	if (err < 0)
1942290a6ce1SLorenzo Bianconi 		return err;
1943290a6ce1SLorenzo Bianconi 
1944290a6ce1SLorenzo Bianconi 	/* enable FIFO watermak interrupt */
19457e906103SLorenzo Bianconi 	err = st_lsm6dsx_get_drdy_reg(hw, &reg);
1946290a6ce1SLorenzo Bianconi 	if (err < 0)
1947290a6ce1SLorenzo Bianconi 		return err;
1948290a6ce1SLorenzo Bianconi 
19497e906103SLorenzo Bianconi 	err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
19507e906103SLorenzo Bianconi 				 ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
195121345107SLorenzo Bianconi 	if (err < 0)
195221345107SLorenzo Bianconi 		return err;
195321345107SLorenzo Bianconi 
19549db02d32SLorenzo Bianconi 	/* enable Latched interrupts for device events */
19557e906103SLorenzo Bianconi 	if (hw->settings->irq_config.lir.addr) {
19567e906103SLorenzo Bianconi 		reg = &hw->settings->irq_config.lir;
19577e906103SLorenzo Bianconi 		err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
19587e906103SLorenzo Bianconi 					 ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
19599db02d32SLorenzo Bianconi 		if (err < 0)
19609db02d32SLorenzo Bianconi 			return err;
196122ea5651SLorenzo Bianconi 
196222ea5651SLorenzo Bianconi 		/* enable clear on read for latched interrupts */
19637e906103SLorenzo Bianconi 		if (hw->settings->irq_config.clear_on_read.addr) {
19647e906103SLorenzo Bianconi 			reg = &hw->settings->irq_config.clear_on_read;
196522ea5651SLorenzo Bianconi 			err = regmap_update_bits(hw->regmap,
19667e906103SLorenzo Bianconi 					reg->addr, reg->mask,
19677e906103SLorenzo Bianconi 					ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
196822ea5651SLorenzo Bianconi 			if (err < 0)
196922ea5651SLorenzo Bianconi 				return err;
197022ea5651SLorenzo Bianconi 		}
19719db02d32SLorenzo Bianconi 	}
19729db02d32SLorenzo Bianconi 
1973960506edSLorenzo Bianconi 	/* enable drdy-mas if available */
1974960506edSLorenzo Bianconi 	if (hw->settings->drdy_mask.addr) {
1975960506edSLorenzo Bianconi 		reg = &hw->settings->drdy_mask;
1976960506edSLorenzo Bianconi 		err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
1977960506edSLorenzo Bianconi 					 ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
1978960506edSLorenzo Bianconi 		if (err < 0)
1979960506edSLorenzo Bianconi 			return err;
1980960506edSLorenzo Bianconi 	}
1981960506edSLorenzo Bianconi 
1982c91c1c84SLorenzo Bianconi 	err = st_lsm6dsx_init_shub(hw);
1983c91c1c84SLorenzo Bianconi 	if (err < 0)
1984c91c1c84SLorenzo Bianconi 		return err;
1985c91c1c84SLorenzo Bianconi 
198621345107SLorenzo Bianconi 	return st_lsm6dsx_init_hw_timer(hw);
1987290a6ce1SLorenzo Bianconi }
1988290a6ce1SLorenzo Bianconi 
1989290a6ce1SLorenzo Bianconi static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw,
1990510c0106SLorenzo Bianconi 					       enum st_lsm6dsx_sensor_id id,
1991510c0106SLorenzo Bianconi 					       const char *name)
1992290a6ce1SLorenzo Bianconi {
1993290a6ce1SLorenzo Bianconi 	struct st_lsm6dsx_sensor *sensor;
1994290a6ce1SLorenzo Bianconi 	struct iio_dev *iio_dev;
1995290a6ce1SLorenzo Bianconi 
1996290a6ce1SLorenzo Bianconi 	iio_dev = devm_iio_device_alloc(hw->dev, sizeof(*sensor));
1997290a6ce1SLorenzo Bianconi 	if (!iio_dev)
1998290a6ce1SLorenzo Bianconi 		return NULL;
1999290a6ce1SLorenzo Bianconi 
2000290a6ce1SLorenzo Bianconi 	iio_dev->modes = INDIO_DIRECT_MODE;
2001290a6ce1SLorenzo Bianconi 	iio_dev->available_scan_masks = st_lsm6dsx_available_scan_masks;
2002f48bc49bSLorenzo Bianconi 	iio_dev->channels = hw->settings->channels[id].chan;
2003f48bc49bSLorenzo Bianconi 	iio_dev->num_channels = hw->settings->channels[id].len;
2004290a6ce1SLorenzo Bianconi 
2005290a6ce1SLorenzo Bianconi 	sensor = iio_priv(iio_dev);
2006290a6ce1SLorenzo Bianconi 	sensor->id = id;
2007290a6ce1SLorenzo Bianconi 	sensor->hw = hw;
2008f8710f03SLorenzo Bianconi 	sensor->odr = hw->settings->odr_table[id].odr_avl[0].milli_hz;
2009640aca3fSLorenzo Bianconi 	sensor->gain = hw->settings->fs_table[id].fs_avl[0].gain;
2010290a6ce1SLorenzo Bianconi 	sensor->watermark = 1;
2011290a6ce1SLorenzo Bianconi 
2012290a6ce1SLorenzo Bianconi 	switch (id) {
2013290a6ce1SLorenzo Bianconi 	case ST_LSM6DSX_ID_ACC:
2014290a6ce1SLorenzo Bianconi 		iio_dev->info = &st_lsm6dsx_acc_info;
2015510c0106SLorenzo Bianconi 		scnprintf(sensor->name, sizeof(sensor->name), "%s_accel",
2016510c0106SLorenzo Bianconi 			  name);
2017290a6ce1SLorenzo Bianconi 		break;
2018290a6ce1SLorenzo Bianconi 	case ST_LSM6DSX_ID_GYRO:
2019290a6ce1SLorenzo Bianconi 		iio_dev->info = &st_lsm6dsx_gyro_info;
2020510c0106SLorenzo Bianconi 		scnprintf(sensor->name, sizeof(sensor->name), "%s_gyro",
2021510c0106SLorenzo Bianconi 			  name);
2022290a6ce1SLorenzo Bianconi 		break;
2023290a6ce1SLorenzo Bianconi 	default:
2024290a6ce1SLorenzo Bianconi 		return NULL;
2025290a6ce1SLorenzo Bianconi 	}
2026510c0106SLorenzo Bianconi 	iio_dev->name = sensor->name;
2027290a6ce1SLorenzo Bianconi 
2028290a6ce1SLorenzo Bianconi 	return iio_dev;
2029290a6ce1SLorenzo Bianconi }
2030290a6ce1SLorenzo Bianconi 
2031615bd378SLorenzo Bianconi static bool
2032615bd378SLorenzo Bianconi st_lsm6dsx_report_motion_event(struct st_lsm6dsx_hw *hw)
20331aabad1fSSean Nyekjaer {
2034615bd378SLorenzo Bianconi 	const struct st_lsm6dsx_event_settings *event_settings;
2035615bd378SLorenzo Bianconi 	int err, data;
2036615bd378SLorenzo Bianconi 	s64 timestamp;
20371aabad1fSSean Nyekjaer 
2038615bd378SLorenzo Bianconi 	if (!hw->enable_event)
2039615bd378SLorenzo Bianconi 		return false;
2040615bd378SLorenzo Bianconi 
2041615bd378SLorenzo Bianconi 	event_settings = &hw->settings->event_settings;
2042615bd378SLorenzo Bianconi 	err = st_lsm6dsx_read_locked(hw, event_settings->wakeup_src_reg,
2043615bd378SLorenzo Bianconi 				     &data, sizeof(data));
2044615bd378SLorenzo Bianconi 	if (err < 0)
2045615bd378SLorenzo Bianconi 		return false;
2046615bd378SLorenzo Bianconi 
2047615bd378SLorenzo Bianconi 	timestamp = iio_get_time_ns(hw->iio_devs[ST_LSM6DSX_ID_ACC]);
20481aabad1fSSean Nyekjaer 	if ((data & hw->settings->event_settings.wakeup_src_z_mask) &&
20491aabad1fSSean Nyekjaer 	    (hw->enable_event & BIT(IIO_MOD_Z)))
20501aabad1fSSean Nyekjaer 		iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC],
20511aabad1fSSean Nyekjaer 			       IIO_MOD_EVENT_CODE(IIO_ACCEL,
20521aabad1fSSean Nyekjaer 						  0,
20531aabad1fSSean Nyekjaer 						  IIO_MOD_Z,
20541aabad1fSSean Nyekjaer 						  IIO_EV_TYPE_THRESH,
20551aabad1fSSean Nyekjaer 						  IIO_EV_DIR_EITHER),
20561aabad1fSSean Nyekjaer 						  timestamp);
20571aabad1fSSean Nyekjaer 
20581aabad1fSSean Nyekjaer 	if ((data & hw->settings->event_settings.wakeup_src_y_mask) &&
20591aabad1fSSean Nyekjaer 	    (hw->enable_event & BIT(IIO_MOD_Y)))
20601aabad1fSSean Nyekjaer 		iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC],
20611aabad1fSSean Nyekjaer 			       IIO_MOD_EVENT_CODE(IIO_ACCEL,
20621aabad1fSSean Nyekjaer 						  0,
20631aabad1fSSean Nyekjaer 						  IIO_MOD_Y,
20641aabad1fSSean Nyekjaer 						  IIO_EV_TYPE_THRESH,
20651aabad1fSSean Nyekjaer 						  IIO_EV_DIR_EITHER),
20661aabad1fSSean Nyekjaer 						  timestamp);
20671aabad1fSSean Nyekjaer 
20681aabad1fSSean Nyekjaer 	if ((data & hw->settings->event_settings.wakeup_src_x_mask) &&
20691aabad1fSSean Nyekjaer 	    (hw->enable_event & BIT(IIO_MOD_X)))
20701aabad1fSSean Nyekjaer 		iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC],
20711aabad1fSSean Nyekjaer 			       IIO_MOD_EVENT_CODE(IIO_ACCEL,
20721aabad1fSSean Nyekjaer 						  0,
20731aabad1fSSean Nyekjaer 						  IIO_MOD_X,
20741aabad1fSSean Nyekjaer 						  IIO_EV_TYPE_THRESH,
20751aabad1fSSean Nyekjaer 						  IIO_EV_DIR_EITHER),
20761aabad1fSSean Nyekjaer 						  timestamp);
2077615bd378SLorenzo Bianconi 
2078615bd378SLorenzo Bianconi 	return data & event_settings->wakeup_src_status_mask;
20791aabad1fSSean Nyekjaer }
20801aabad1fSSean Nyekjaer 
20816ee6a368SSean Nyekjaer static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private)
20826ee6a368SSean Nyekjaer {
20836ee6a368SSean Nyekjaer 	struct st_lsm6dsx_hw *hw = private;
20843f9bce7aSLorenzo Bianconi 	int fifo_len = 0, len;
2085615bd378SLorenzo Bianconi 	bool event;
20861aabad1fSSean Nyekjaer 
2087615bd378SLorenzo Bianconi 	event = st_lsm6dsx_report_motion_event(hw);
20886ee6a368SSean Nyekjaer 
2089a912ee4cSLorenzo Bianconi 	if (!hw->settings->fifo_ops.read_fifo)
2090a912ee4cSLorenzo Bianconi 		return event ? IRQ_HANDLED : IRQ_NONE;
2091a912ee4cSLorenzo Bianconi 
20923f9bce7aSLorenzo Bianconi 	/*
20933f9bce7aSLorenzo Bianconi 	 * If we are using edge IRQs, new samples can arrive while
20943f9bce7aSLorenzo Bianconi 	 * processing current interrupt since there are no hw
20953f9bce7aSLorenzo Bianconi 	 * guarantees the irq line stays "low" long enough to properly
20963f9bce7aSLorenzo Bianconi 	 * detect the new interrupt. In this case the new sample will
20973f9bce7aSLorenzo Bianconi 	 * be missed.
20983f9bce7aSLorenzo Bianconi 	 * Polling FIFO status register allow us to read new
20993f9bce7aSLorenzo Bianconi 	 * samples even if the interrupt arrives while processing
21003f9bce7aSLorenzo Bianconi 	 * previous data and the timeslot where the line is "low" is
21013f9bce7aSLorenzo Bianconi 	 * too short to be properly detected.
21023f9bce7aSLorenzo Bianconi 	 */
21033f9bce7aSLorenzo Bianconi 	do {
21046ee6a368SSean Nyekjaer 		mutex_lock(&hw->fifo_lock);
21053f9bce7aSLorenzo Bianconi 		len = hw->settings->fifo_ops.read_fifo(hw);
21066ee6a368SSean Nyekjaer 		mutex_unlock(&hw->fifo_lock);
21076ee6a368SSean Nyekjaer 
21083f9bce7aSLorenzo Bianconi 		if (len > 0)
21093f9bce7aSLorenzo Bianconi 			fifo_len += len;
21103f9bce7aSLorenzo Bianconi 	} while (len > 0);
21113f9bce7aSLorenzo Bianconi 
21123f9bce7aSLorenzo Bianconi 	return fifo_len || event ? IRQ_HANDLED : IRQ_NONE;
21136ee6a368SSean Nyekjaer }
21146ee6a368SSean Nyekjaer 
21156ee6a368SSean Nyekjaer static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw)
21166ee6a368SSean Nyekjaer {
211731fe8d4eSLorenzo Bianconi 	struct st_sensors_platform_data *pdata;
211831fe8d4eSLorenzo Bianconi 	const struct st_lsm6dsx_reg *reg;
211903d4c566SAndy Shevchenko 	struct device *dev = hw->dev;
21206ee6a368SSean Nyekjaer 	unsigned long irq_type;
21216ee6a368SSean Nyekjaer 	bool irq_active_low;
21226ee6a368SSean Nyekjaer 	int err;
21236ee6a368SSean Nyekjaer 
21246ee6a368SSean Nyekjaer 	irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
21256ee6a368SSean Nyekjaer 
21266ee6a368SSean Nyekjaer 	switch (irq_type) {
21276ee6a368SSean Nyekjaer 	case IRQF_TRIGGER_HIGH:
21286ee6a368SSean Nyekjaer 	case IRQF_TRIGGER_RISING:
21296ee6a368SSean Nyekjaer 		irq_active_low = false;
21306ee6a368SSean Nyekjaer 		break;
21316ee6a368SSean Nyekjaer 	case IRQF_TRIGGER_LOW:
21326ee6a368SSean Nyekjaer 	case IRQF_TRIGGER_FALLING:
21336ee6a368SSean Nyekjaer 		irq_active_low = true;
21346ee6a368SSean Nyekjaer 		break;
21356ee6a368SSean Nyekjaer 	default:
21366ee6a368SSean Nyekjaer 		dev_info(hw->dev, "mode %lx unsupported\n", irq_type);
21376ee6a368SSean Nyekjaer 		return -EINVAL;
21386ee6a368SSean Nyekjaer 	}
21396ee6a368SSean Nyekjaer 
214031fe8d4eSLorenzo Bianconi 	reg = &hw->settings->irq_config.hla;
214131fe8d4eSLorenzo Bianconi 	err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
214231fe8d4eSLorenzo Bianconi 				 ST_LSM6DSX_SHIFT_VAL(irq_active_low,
214331fe8d4eSLorenzo Bianconi 						      reg->mask));
21446ee6a368SSean Nyekjaer 	if (err < 0)
21456ee6a368SSean Nyekjaer 		return err;
21466ee6a368SSean Nyekjaer 
214703d4c566SAndy Shevchenko 	pdata = (struct st_sensors_platform_data *)dev->platform_data;
214803d4c566SAndy Shevchenko 	if ((dev_fwnode(dev) && device_property_read_bool(dev, "drive-open-drain")) ||
21496ee6a368SSean Nyekjaer 	    (pdata && pdata->open_drain)) {
215031fe8d4eSLorenzo Bianconi 		reg = &hw->settings->irq_config.od;
215131fe8d4eSLorenzo Bianconi 		err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
215231fe8d4eSLorenzo Bianconi 					 ST_LSM6DSX_SHIFT_VAL(1, reg->mask));
21536ee6a368SSean Nyekjaer 		if (err < 0)
21546ee6a368SSean Nyekjaer 			return err;
21556ee6a368SSean Nyekjaer 
21566ee6a368SSean Nyekjaer 		irq_type |= IRQF_SHARED;
21576ee6a368SSean Nyekjaer 	}
21586ee6a368SSean Nyekjaer 
21596ee6a368SSean Nyekjaer 	err = devm_request_threaded_irq(hw->dev, hw->irq,
2160a3aa17d4SSean Nyekjaer 					NULL,
21616ee6a368SSean Nyekjaer 					st_lsm6dsx_handler_thread,
21626ee6a368SSean Nyekjaer 					irq_type | IRQF_ONESHOT,
21636ee6a368SSean Nyekjaer 					"lsm6dsx", hw);
21646ee6a368SSean Nyekjaer 	if (err) {
21656ee6a368SSean Nyekjaer 		dev_err(hw->dev, "failed to request trigger irq %d\n",
21666ee6a368SSean Nyekjaer 			hw->irq);
21676ee6a368SSean Nyekjaer 		return err;
21686ee6a368SSean Nyekjaer 	}
21696ee6a368SSean Nyekjaer 
21706ee6a368SSean Nyekjaer 	return 0;
21716ee6a368SSean Nyekjaer }
21726ee6a368SSean Nyekjaer 
2173f346b16fSLorenzo Bianconi static int st_lsm6dsx_init_regulators(struct device *dev)
2174f346b16fSLorenzo Bianconi {
2175f346b16fSLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev);
2176f346b16fSLorenzo Bianconi 	int err;
2177f346b16fSLorenzo Bianconi 
2178f346b16fSLorenzo Bianconi 	/* vdd-vddio power regulators */
2179f346b16fSLorenzo Bianconi 	hw->regulators[0].supply = "vdd";
2180f346b16fSLorenzo Bianconi 	hw->regulators[1].supply = "vddio";
2181f346b16fSLorenzo Bianconi 	err = devm_regulator_bulk_get(dev, ARRAY_SIZE(hw->regulators),
2182f346b16fSLorenzo Bianconi 				      hw->regulators);
2183f346b16fSLorenzo Bianconi 	if (err)
2184f346b16fSLorenzo Bianconi 		return dev_err_probe(dev, err, "failed to get regulators\n");
2185f346b16fSLorenzo Bianconi 
2186f346b16fSLorenzo Bianconi 	err = regulator_bulk_enable(ARRAY_SIZE(hw->regulators),
2187f346b16fSLorenzo Bianconi 				    hw->regulators);
2188f346b16fSLorenzo Bianconi 	if (err) {
2189f346b16fSLorenzo Bianconi 		dev_err(dev, "failed to enable regulators: %d\n", err);
2190f346b16fSLorenzo Bianconi 		return err;
2191f346b16fSLorenzo Bianconi 	}
2192f346b16fSLorenzo Bianconi 
2193f346b16fSLorenzo Bianconi 	msleep(50);
2194f346b16fSLorenzo Bianconi 
2195f346b16fSLorenzo Bianconi 	return 0;
2196f346b16fSLorenzo Bianconi }
2197f346b16fSLorenzo Bianconi 
2198f346b16fSLorenzo Bianconi static void st_lsm6dsx_chip_uninit(void *data)
2199f346b16fSLorenzo Bianconi {
2200f346b16fSLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = data;
2201f346b16fSLorenzo Bianconi 
2202f346b16fSLorenzo Bianconi 	regulator_bulk_disable(ARRAY_SIZE(hw->regulators), hw->regulators);
2203f346b16fSLorenzo Bianconi }
2204f346b16fSLorenzo Bianconi 
220581956a93SLorenzo Bianconi int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
220651a8b707SLorenzo Bianconi 		     struct regmap *regmap)
2207290a6ce1SLorenzo Bianconi {
2208b7a73b33SLorenzo Bianconi 	struct st_sensors_platform_data *pdata = dev->platform_data;
2209c91c1c84SLorenzo Bianconi 	const struct st_lsm6dsx_shub_settings *hub_settings;
2210290a6ce1SLorenzo Bianconi 	struct st_lsm6dsx_hw *hw;
221181956a93SLorenzo Bianconi 	const char *name = NULL;
2212290a6ce1SLorenzo Bianconi 	int i, err;
2213290a6ce1SLorenzo Bianconi 
2214290a6ce1SLorenzo Bianconi 	hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
2215290a6ce1SLorenzo Bianconi 	if (!hw)
2216290a6ce1SLorenzo Bianconi 		return -ENOMEM;
2217290a6ce1SLorenzo Bianconi 
2218290a6ce1SLorenzo Bianconi 	dev_set_drvdata(dev, (void *)hw);
2219290a6ce1SLorenzo Bianconi 
2220290a6ce1SLorenzo Bianconi 	mutex_init(&hw->fifo_lock);
2221335eaedcSLorenzo Bianconi 	mutex_init(&hw->conf_lock);
2222739aff87SLorenzo Bianconi 	mutex_init(&hw->page_lock);
2223290a6ce1SLorenzo Bianconi 
2224f346b16fSLorenzo Bianconi 	err = st_lsm6dsx_init_regulators(dev);
2225f346b16fSLorenzo Bianconi 	if (err)
2226f346b16fSLorenzo Bianconi 		return err;
2227f346b16fSLorenzo Bianconi 
2228f346b16fSLorenzo Bianconi 	err = devm_add_action_or_reset(dev, st_lsm6dsx_chip_uninit, hw);
2229f346b16fSLorenzo Bianconi 	if (err)
2230f346b16fSLorenzo Bianconi 		return err;
2231f346b16fSLorenzo Bianconi 
223291a6b841SLorenzo Bianconi 	hw->buff = devm_kzalloc(dev, ST_LSM6DSX_BUFF_SIZE, GFP_KERNEL);
223391a6b841SLorenzo Bianconi 	if (!hw->buff)
223491a6b841SLorenzo Bianconi 		return -ENOMEM;
223591a6b841SLorenzo Bianconi 
2236290a6ce1SLorenzo Bianconi 	hw->dev = dev;
2237290a6ce1SLorenzo Bianconi 	hw->irq = irq;
223851a8b707SLorenzo Bianconi 	hw->regmap = regmap;
2239290a6ce1SLorenzo Bianconi 
224081956a93SLorenzo Bianconi 	err = st_lsm6dsx_check_whoami(hw, hw_id, &name);
2241290a6ce1SLorenzo Bianconi 	if (err < 0)
2242290a6ce1SLorenzo Bianconi 		return err;
2243290a6ce1SLorenzo Bianconi 
22446ffb55e5SLorenzo Bianconi 	for (i = 0; i < ST_LSM6DSX_ID_EXT0; i++) {
2245510c0106SLorenzo Bianconi 		hw->iio_devs[i] = st_lsm6dsx_alloc_iiodev(hw, i, name);
2246290a6ce1SLorenzo Bianconi 		if (!hw->iio_devs[i])
2247290a6ce1SLorenzo Bianconi 			return -ENOMEM;
2248290a6ce1SLorenzo Bianconi 	}
2249290a6ce1SLorenzo Bianconi 
2250290a6ce1SLorenzo Bianconi 	err = st_lsm6dsx_init_device(hw);
2251290a6ce1SLorenzo Bianconi 	if (err < 0)
2252290a6ce1SLorenzo Bianconi 		return err;
2253290a6ce1SLorenzo Bianconi 
2254c91c1c84SLorenzo Bianconi 	hub_settings = &hw->settings->shub_settings;
225535619155SLorenzo Bianconi 	if (hub_settings->master_en.addr &&
225635619155SLorenzo Bianconi 	    (!dev_fwnode(dev) ||
225735619155SLorenzo Bianconi 	     !device_property_read_bool(dev, "st,disable-sensor-hub"))) {
2258c91c1c84SLorenzo Bianconi 		err = st_lsm6dsx_shub_probe(hw, name);
2259c91c1c84SLorenzo Bianconi 		if (err < 0)
2260c91c1c84SLorenzo Bianconi 			return err;
2261c91c1c84SLorenzo Bianconi 	}
2262c91c1c84SLorenzo Bianconi 
2263290a6ce1SLorenzo Bianconi 	if (hw->irq > 0) {
22646ee6a368SSean Nyekjaer 		err = st_lsm6dsx_irq_setup(hw);
22656ee6a368SSean Nyekjaer 		if (err < 0)
22666ee6a368SSean Nyekjaer 			return err;
22676ee6a368SSean Nyekjaer 
2268290a6ce1SLorenzo Bianconi 		err = st_lsm6dsx_fifo_setup(hw);
2269290a6ce1SLorenzo Bianconi 		if (err < 0)
2270290a6ce1SLorenzo Bianconi 			return err;
2271290a6ce1SLorenzo Bianconi 	}
2272290a6ce1SLorenzo Bianconi 
2273b892770aSAndy Shevchenko 	err = iio_read_mount_matrix(hw->dev, &hw->orientation);
227404e6fedbSMartin Kepplinger 	if (err)
227504e6fedbSMartin Kepplinger 		return err;
227604e6fedbSMartin Kepplinger 
2277290a6ce1SLorenzo Bianconi 	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
22786ffb55e5SLorenzo Bianconi 		if (!hw->iio_devs[i])
22796ffb55e5SLorenzo Bianconi 			continue;
22806ffb55e5SLorenzo Bianconi 
2281290a6ce1SLorenzo Bianconi 		err = devm_iio_device_register(hw->dev, hw->iio_devs[i]);
2282290a6ce1SLorenzo Bianconi 		if (err)
2283290a6ce1SLorenzo Bianconi 			return err;
2284290a6ce1SLorenzo Bianconi 	}
2285290a6ce1SLorenzo Bianconi 
228603d4c566SAndy Shevchenko 	if ((dev_fwnode(dev) && device_property_read_bool(dev, "wakeup-source")) ||
2287b7a73b33SLorenzo Bianconi 	    (pdata && pdata->wakeup_source))
22884c997dfaSSean Nyekjaer 		device_init_wakeup(dev, true);
22894c997dfaSSean Nyekjaer 
2290290a6ce1SLorenzo Bianconi 	return 0;
2291290a6ce1SLorenzo Bianconi }
2292290a6ce1SLorenzo Bianconi EXPORT_SYMBOL(st_lsm6dsx_probe);
2293290a6ce1SLorenzo Bianconi 
22943cec4850SLorenzo Bianconi static int __maybe_unused st_lsm6dsx_suspend(struct device *dev)
2295d3f77058SLorenzo Bianconi {
2296d3f77058SLorenzo Bianconi 	struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev);
2297d3f77058SLorenzo Bianconi 	struct st_lsm6dsx_sensor *sensor;
2298d3f77058SLorenzo Bianconi 	int i, err = 0;
2299d3f77058SLorenzo Bianconi 
2300d3f77058SLorenzo Bianconi 	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
23016ffb55e5SLorenzo Bianconi 		if (!hw->iio_devs[i])
23026ffb55e5SLorenzo Bianconi 			continue;
23036ffb55e5SLorenzo Bianconi 
2304d3f77058SLorenzo Bianconi 		sensor = iio_priv(hw->iio_devs[i]);
2305d3f77058SLorenzo Bianconi 		if (!(hw->enable_mask & BIT(sensor->id)))
2306d3f77058SLorenzo Bianconi 			continue;
2307d3f77058SLorenzo Bianconi 
23084c997dfaSSean Nyekjaer 		if (device_may_wakeup(dev) &&
23094c997dfaSSean Nyekjaer 		    sensor->id == ST_LSM6DSX_ID_ACC && hw->enable_event) {
23104c997dfaSSean Nyekjaer 			/* Enable wake from IRQ */
23114c997dfaSSean Nyekjaer 			enable_irq_wake(hw->irq);
23124c997dfaSSean Nyekjaer 			continue;
23134c997dfaSSean Nyekjaer 		}
23144c997dfaSSean Nyekjaer 
2315bce0d57dSLorenzo Bianconi 		if (sensor->id == ST_LSM6DSX_ID_EXT0 ||
2316bce0d57dSLorenzo Bianconi 		    sensor->id == ST_LSM6DSX_ID_EXT1 ||
2317bce0d57dSLorenzo Bianconi 		    sensor->id == ST_LSM6DSX_ID_EXT2)
2318bce0d57dSLorenzo Bianconi 			err = st_lsm6dsx_shub_set_enable(sensor, false);
2319bce0d57dSLorenzo Bianconi 		else
2320bce0d57dSLorenzo Bianconi 			err = st_lsm6dsx_sensor_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 
23333cec4850SLorenzo Bianconi static int __maybe_unused 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 
2351bce0d57dSLorenzo Bianconi 		if (sensor->id == ST_LSM6DSX_ID_EXT0 ||
2352bce0d57dSLorenzo Bianconi 		    sensor->id == ST_LSM6DSX_ID_EXT1 ||
2353bce0d57dSLorenzo Bianconi 		    sensor->id == ST_LSM6DSX_ID_EXT2)
2354bce0d57dSLorenzo Bianconi 			err = st_lsm6dsx_shub_set_enable(sensor, true);
2355bce0d57dSLorenzo Bianconi 		else
2356bce0d57dSLorenzo Bianconi 			err = st_lsm6dsx_sensor_set_enable(sensor, true);
2357d3f77058SLorenzo Bianconi 		if (err < 0)
2358d3f77058SLorenzo Bianconi 			return err;
2359bce0d57dSLorenzo Bianconi 
2360bce0d57dSLorenzo Bianconi 		hw->suspend_mask &= ~BIT(sensor->id);
2361d3f77058SLorenzo Bianconi 	}
2362d3f77058SLorenzo Bianconi 
2363c2686eb2SLorenzo Bianconi 	if (hw->fifo_mask)
2364a1bab939SLorenzo Bianconi 		err = st_lsm6dsx_resume_fifo(hw);
2365d3f77058SLorenzo Bianconi 
2366d3f77058SLorenzo Bianconi 	return err;
2367d3f77058SLorenzo Bianconi }
2368d3f77058SLorenzo Bianconi 
2369d3f77058SLorenzo Bianconi const struct dev_pm_ops st_lsm6dsx_pm_ops = {
2370d3f77058SLorenzo Bianconi 	SET_SYSTEM_SLEEP_PM_OPS(st_lsm6dsx_suspend, st_lsm6dsx_resume)
2371d3f77058SLorenzo Bianconi };
2372d3f77058SLorenzo Bianconi EXPORT_SYMBOL(st_lsm6dsx_pm_ops);
2373d3f77058SLorenzo Bianconi 
2374290a6ce1SLorenzo Bianconi MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
2375290a6ce1SLorenzo Bianconi MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
2376290a6ce1SLorenzo Bianconi MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx driver");
2377290a6ce1SLorenzo Bianconi MODULE_LICENSE("GPL v2");
2378