]>
Commit | Line | Data |
---|---|---|
fda8d26e | 1 | // SPDX-License-Identifier: GPL-2.0-only |
290a6ce1 LB |
2 | /* |
3 | * STMicroelectronics st_lsm6dsx sensor driver | |
4 | * | |
5 | * The ST LSM6DSx IMU MEMS series consists of 3D digital accelerometer | |
6 | * and 3D digital gyroscope system-in-package with a digital I2C/SPI serial | |
7 | * interface standard output. | |
8 | * LSM6DSx IMU MEMS series has a dynamic user-selectable full-scale | |
9 | * acceleration range of +-2/+-4/+-8/+-16 g and an angular rate range of | |
10 | * +-125/+-245/+-500/+-1000/+-2000 dps | |
11 | * LSM6DSx series has an integrated First-In-First-Out (FIFO) buffer | |
12 | * allowing dynamic batching of sensor data. | |
52f4b1f1 MK |
13 | * LSM9DSx series is similar but includes an additional magnetometer, handled |
14 | * by a different driver. | |
290a6ce1 LB |
15 | * |
16 | * Supported sensors: | |
17 | * - LSM6DS3: | |
18 | * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 | |
19 | * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 | |
20 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 | |
21 | * - FIFO size: 8KB | |
22 | * | |
dbcd2088 | 23 | * - LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC/LSM6DS3TR-C: |
290a6ce1 LB |
24 | * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 |
25 | * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 | |
26 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 | |
27 | * - FIFO size: 4KB | |
28 | * | |
db947a79 | 29 | * - LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX: |
801a6e0a LB |
30 | * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 |
31 | * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 | |
32 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 | |
33 | * - FIFO size: 3KB | |
34 | * | |
fa060a3d | 35 | * - LSM9DS1/LSM6DS0: |
52f4b1f1 MK |
36 | * - Accelerometer supported ODR [Hz]: 10, 50, 119, 238, 476, 952 |
37 | * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 | |
38 | * - Gyroscope supported ODR [Hz]: 15, 60, 119, 238, 476, 952 | |
39 | * - Gyroscope supported full-scale [dps]: +-245/+-500/+-2000 | |
40 | * - FIFO size: 32 | |
41 | * | |
290a6ce1 LB |
42 | * Copyright 2016 STMicroelectronics Inc. |
43 | * | |
44 | * Lorenzo Bianconi <lorenzo.bianconi@st.com> | |
45 | * Denis Ciocca <denis.ciocca@st.com> | |
290a6ce1 LB |
46 | */ |
47 | ||
48 | #include <linux/kernel.h> | |
49 | #include <linux/module.h> | |
50 | #include <linux/delay.h> | |
1aabad1f | 51 | #include <linux/iio/events.h> |
290a6ce1 LB |
52 | #include <linux/iio/iio.h> |
53 | #include <linux/iio/sysfs.h> | |
6ee6a368 SN |
54 | #include <linux/interrupt.h> |
55 | #include <linux/irq.h> | |
d3f77058 | 56 | #include <linux/pm.h> |
03d4c566 | 57 | #include <linux/property.h> |
51a8b707 LB |
58 | #include <linux/regmap.h> |
59 | #include <linux/bitfield.h> | |
290a6ce1 | 60 | |
dba32904 LB |
61 | #include <linux/platform_data/st_sensors_pdata.h> |
62 | ||
290a6ce1 LB |
63 | #include "st_lsm6dsx.h" |
64 | ||
290a6ce1 | 65 | #define ST_LSM6DSX_REG_WHOAMI_ADDR 0x0f |
290a6ce1 | 66 | |
cb3b6b8e MT |
67 | #define ST_LSM6DSX_TS_SENSITIVITY 25000UL /* 25us */ |
68 | ||
f48bc49b | 69 | static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { |
b5969abf SN |
70 | ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x28, IIO_MOD_X, 0), |
71 | ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1), | |
72 | ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x2c, IIO_MOD_Z, 2), | |
f48bc49b LB |
73 | IIO_CHAN_SOFT_TIMESTAMP(3), |
74 | }; | |
75 | ||
76 | static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = { | |
77 | ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x22, IIO_MOD_X, 0), | |
78 | ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x24, IIO_MOD_Y, 1), | |
79 | ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x26, IIO_MOD_Z, 2), | |
80 | IIO_CHAN_SOFT_TIMESTAMP(3), | |
81 | }; | |
82 | ||
52f4b1f1 MK |
83 | static const struct iio_chan_spec st_lsm6ds0_gyro_channels[] = { |
84 | ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x18, IIO_MOD_X, 0), | |
85 | ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x1a, IIO_MOD_Y, 1), | |
86 | ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x1c, IIO_MOD_Z, 2), | |
87 | IIO_CHAN_SOFT_TIMESTAMP(3), | |
88 | }; | |
89 | ||
290a6ce1 | 90 | static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { |
52f4b1f1 MK |
91 | { |
92 | .wai = 0x68, | |
66b662a1 LB |
93 | .reset = { |
94 | .addr = 0x22, | |
95 | .mask = BIT(0), | |
96 | }, | |
97 | .boot = { | |
98 | .addr = 0x22, | |
99 | .mask = BIT(7), | |
100 | }, | |
101 | .bdu = { | |
102 | .addr = 0x22, | |
103 | .mask = BIT(6), | |
104 | }, | |
52f4b1f1 MK |
105 | .max_fifo_size = 32, |
106 | .id = { | |
107 | { | |
108 | .hw_id = ST_LSM9DS1_ID, | |
109 | .name = ST_LSM9DS1_DEV_NAME, | |
fa060a3d LB |
110 | }, { |
111 | .hw_id = ST_LSM6DS0_ID, | |
112 | .name = ST_LSM6DS0_DEV_NAME, | |
52f4b1f1 MK |
113 | }, |
114 | }, | |
115 | .channels = { | |
116 | [ST_LSM6DSX_ID_ACC] = { | |
117 | .chan = st_lsm6dsx_acc_channels, | |
118 | .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), | |
119 | }, | |
120 | [ST_LSM6DSX_ID_GYRO] = { | |
121 | .chan = st_lsm6ds0_gyro_channels, | |
122 | .len = ARRAY_SIZE(st_lsm6ds0_gyro_channels), | |
123 | }, | |
124 | }, | |
125 | .odr_table = { | |
126 | [ST_LSM6DSX_ID_ACC] = { | |
127 | .reg = { | |
128 | .addr = 0x20, | |
129 | .mask = GENMASK(7, 5), | |
130 | }, | |
f8710f03 LB |
131 | .odr_avl[0] = { 10000, 0x01 }, |
132 | .odr_avl[1] = { 50000, 0x02 }, | |
133 | .odr_avl[2] = { 119000, 0x03 }, | |
134 | .odr_avl[3] = { 238000, 0x04 }, | |
135 | .odr_avl[4] = { 476000, 0x05 }, | |
136 | .odr_avl[5] = { 952000, 0x06 }, | |
59af4e20 | 137 | .odr_len = 6, |
52f4b1f1 MK |
138 | }, |
139 | [ST_LSM6DSX_ID_GYRO] = { | |
140 | .reg = { | |
141 | .addr = 0x10, | |
142 | .mask = GENMASK(7, 5), | |
143 | }, | |
f8710f03 LB |
144 | .odr_avl[0] = { 14900, 0x01 }, |
145 | .odr_avl[1] = { 59500, 0x02 }, | |
146 | .odr_avl[2] = { 119000, 0x03 }, | |
147 | .odr_avl[3] = { 238000, 0x04 }, | |
148 | .odr_avl[4] = { 476000, 0x05 }, | |
149 | .odr_avl[5] = { 952000, 0x06 }, | |
59af4e20 | 150 | .odr_len = 6, |
52f4b1f1 MK |
151 | }, |
152 | }, | |
153 | .fs_table = { | |
154 | [ST_LSM6DSX_ID_ACC] = { | |
155 | .reg = { | |
156 | .addr = 0x20, | |
157 | .mask = GENMASK(4, 3), | |
158 | }, | |
6fa02948 LB |
159 | .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, |
160 | .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, | |
161 | .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, | |
162 | .fs_avl[3] = { IIO_G_TO_M_S_2(732), 0x1 }, | |
85ae3aee | 163 | .fs_len = 4, |
52f4b1f1 MK |
164 | }, |
165 | [ST_LSM6DSX_ID_GYRO] = { | |
166 | .reg = { | |
167 | .addr = 0x10, | |
168 | .mask = GENMASK(4, 3), | |
169 | }, | |
1b375101 LB |
170 | |
171 | .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, | |
172 | .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, | |
173 | .fs_avl[2] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, | |
85ae3aee | 174 | .fs_len = 3, |
52f4b1f1 MK |
175 | }, |
176 | }, | |
7e906103 LB |
177 | .irq_config = { |
178 | .irq1 = { | |
179 | .addr = 0x0c, | |
180 | .mask = BIT(3), | |
181 | }, | |
182 | .irq2 = { | |
183 | .addr = 0x0d, | |
184 | .mask = BIT(3), | |
185 | }, | |
31fe8d4e LB |
186 | .hla = { |
187 | .addr = 0x22, | |
188 | .mask = BIT(5), | |
189 | }, | |
190 | .od = { | |
191 | .addr = 0x22, | |
192 | .mask = BIT(4), | |
193 | }, | |
7e906103 | 194 | }, |
52f4b1f1 | 195 | }, |
290a6ce1 | 196 | { |
d068e4a0 | 197 | .wai = 0x69, |
66b662a1 LB |
198 | .reset = { |
199 | .addr = 0x12, | |
200 | .mask = BIT(0), | |
201 | }, | |
202 | .boot = { | |
203 | .addr = 0x12, | |
204 | .mask = BIT(7), | |
205 | }, | |
206 | .bdu = { | |
207 | .addr = 0x12, | |
208 | .mask = BIT(6), | |
209 | }, | |
8f2a88a2 | 210 | .max_fifo_size = 1365, |
d068e4a0 | 211 | .id = { |
81956a93 LB |
212 | { |
213 | .hw_id = ST_LSM6DS3_ID, | |
214 | .name = ST_LSM6DS3_DEV_NAME, | |
215 | }, | |
d068e4a0 | 216 | }, |
f48bc49b LB |
217 | .channels = { |
218 | [ST_LSM6DSX_ID_ACC] = { | |
219 | .chan = st_lsm6dsx_acc_channels, | |
220 | .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), | |
221 | }, | |
222 | [ST_LSM6DSX_ID_GYRO] = { | |
223 | .chan = st_lsm6dsx_gyro_channels, | |
224 | .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), | |
225 | }, | |
226 | }, | |
40dd7343 LB |
227 | .odr_table = { |
228 | [ST_LSM6DSX_ID_ACC] = { | |
229 | .reg = { | |
230 | .addr = 0x10, | |
231 | .mask = GENMASK(7, 4), | |
232 | }, | |
f8710f03 LB |
233 | .odr_avl[0] = { 12500, 0x01 }, |
234 | .odr_avl[1] = { 26000, 0x02 }, | |
235 | .odr_avl[2] = { 52000, 0x03 }, | |
236 | .odr_avl[3] = { 104000, 0x04 }, | |
237 | .odr_avl[4] = { 208000, 0x05 }, | |
238 | .odr_avl[5] = { 416000, 0x06 }, | |
59af4e20 | 239 | .odr_len = 6, |
40dd7343 LB |
240 | }, |
241 | [ST_LSM6DSX_ID_GYRO] = { | |
242 | .reg = { | |
243 | .addr = 0x11, | |
244 | .mask = GENMASK(7, 4), | |
245 | }, | |
f8710f03 LB |
246 | .odr_avl[0] = { 12500, 0x01 }, |
247 | .odr_avl[1] = { 26000, 0x02 }, | |
248 | .odr_avl[2] = { 52000, 0x03 }, | |
249 | .odr_avl[3] = { 104000, 0x04 }, | |
250 | .odr_avl[4] = { 208000, 0x05 }, | |
251 | .odr_avl[5] = { 416000, 0x06 }, | |
59af4e20 | 252 | .odr_len = 6, |
40dd7343 LB |
253 | }, |
254 | }, | |
640aca3f LB |
255 | .fs_table = { |
256 | [ST_LSM6DSX_ID_ACC] = { | |
257 | .reg = { | |
258 | .addr = 0x10, | |
259 | .mask = GENMASK(3, 2), | |
260 | }, | |
261 | .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, | |
262 | .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, | |
263 | .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, | |
264 | .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, | |
85ae3aee | 265 | .fs_len = 4, |
640aca3f LB |
266 | }, |
267 | [ST_LSM6DSX_ID_GYRO] = { | |
268 | .reg = { | |
269 | .addr = 0x11, | |
270 | .mask = GENMASK(3, 2), | |
271 | }, | |
272 | .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, | |
273 | .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, | |
274 | .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, | |
275 | .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, | |
85ae3aee | 276 | .fs_len = 4, |
640aca3f LB |
277 | }, |
278 | }, | |
7e906103 LB |
279 | .irq_config = { |
280 | .irq1 = { | |
281 | .addr = 0x0d, | |
282 | .mask = BIT(3), | |
283 | }, | |
284 | .irq2 = { | |
285 | .addr = 0x0e, | |
286 | .mask = BIT(3), | |
287 | }, | |
288 | .lir = { | |
289 | .addr = 0x58, | |
290 | .mask = BIT(0), | |
291 | }, | |
292 | .irq1_func = { | |
293 | .addr = 0x5e, | |
294 | .mask = BIT(5), | |
295 | }, | |
296 | .irq2_func = { | |
297 | .addr = 0x5f, | |
298 | .mask = BIT(5), | |
299 | }, | |
31fe8d4e LB |
300 | .hla = { |
301 | .addr = 0x12, | |
302 | .mask = BIT(5), | |
303 | }, | |
304 | .od = { | |
305 | .addr = 0x12, | |
306 | .mask = BIT(4), | |
307 | }, | |
7e906103 | 308 | }, |
7ca3ac9e LB |
309 | .decimator = { |
310 | [ST_LSM6DSX_ID_ACC] = { | |
311 | .addr = 0x08, | |
312 | .mask = GENMASK(2, 0), | |
313 | }, | |
314 | [ST_LSM6DSX_ID_GYRO] = { | |
315 | .addr = 0x08, | |
316 | .mask = GENMASK(5, 3), | |
317 | }, | |
318 | }, | |
92617c15 | 319 | .fifo_ops = { |
3b72950d | 320 | .update_fifo = st_lsm6dsx_update_fifo, |
50ff457d | 321 | .read_fifo = st_lsm6dsx_read_fifo, |
92617c15 LB |
322 | .fifo_th = { |
323 | .addr = 0x06, | |
324 | .mask = GENMASK(11, 0), | |
325 | }, | |
326 | .fifo_diff = { | |
327 | .addr = 0x3a, | |
328 | .mask = GENMASK(11, 0), | |
329 | }, | |
330 | .th_wl = 3, /* 1LSB = 2B */ | |
331 | }, | |
21345107 LB |
332 | .ts_settings = { |
333 | .timer_en = { | |
334 | .addr = 0x58, | |
335 | .mask = BIT(7), | |
336 | }, | |
337 | .hr_timer = { | |
338 | .addr = 0x5c, | |
339 | .mask = BIT(4), | |
340 | }, | |
341 | .fifo_en = { | |
342 | .addr = 0x07, | |
343 | .mask = BIT(7), | |
344 | }, | |
345 | .decimator = { | |
346 | .addr = 0x09, | |
347 | .mask = GENMASK(5, 3), | |
348 | }, | |
349 | }, | |
b5969abf SN |
350 | .event_settings = { |
351 | .wakeup_reg = { | |
352 | .addr = 0x5B, | |
353 | .mask = GENMASK(5, 0), | |
354 | }, | |
1aabad1f SN |
355 | .wakeup_src_reg = 0x1b, |
356 | .wakeup_src_status_mask = BIT(3), | |
357 | .wakeup_src_z_mask = BIT(0), | |
358 | .wakeup_src_y_mask = BIT(1), | |
359 | .wakeup_src_x_mask = BIT(2), | |
b5969abf | 360 | }, |
290a6ce1 | 361 | }, |
df47710a LB |
362 | { |
363 | .wai = 0x69, | |
66b662a1 LB |
364 | .reset = { |
365 | .addr = 0x12, | |
366 | .mask = BIT(0), | |
367 | }, | |
368 | .boot = { | |
369 | .addr = 0x12, | |
370 | .mask = BIT(7), | |
371 | }, | |
372 | .bdu = { | |
373 | .addr = 0x12, | |
374 | .mask = BIT(6), | |
375 | }, | |
8f2a88a2 | 376 | .max_fifo_size = 682, |
df47710a | 377 | .id = { |
81956a93 LB |
378 | { |
379 | .hw_id = ST_LSM6DS3H_ID, | |
380 | .name = ST_LSM6DS3H_DEV_NAME, | |
381 | }, | |
df47710a | 382 | }, |
f48bc49b LB |
383 | .channels = { |
384 | [ST_LSM6DSX_ID_ACC] = { | |
385 | .chan = st_lsm6dsx_acc_channels, | |
386 | .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), | |
387 | }, | |
388 | [ST_LSM6DSX_ID_GYRO] = { | |
389 | .chan = st_lsm6dsx_gyro_channels, | |
390 | .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), | |
391 | }, | |
392 | }, | |
40dd7343 LB |
393 | .odr_table = { |
394 | [ST_LSM6DSX_ID_ACC] = { | |
395 | .reg = { | |
396 | .addr = 0x10, | |
397 | .mask = GENMASK(7, 4), | |
398 | }, | |
f8710f03 LB |
399 | .odr_avl[0] = { 12500, 0x01 }, |
400 | .odr_avl[1] = { 26000, 0x02 }, | |
401 | .odr_avl[2] = { 52000, 0x03 }, | |
402 | .odr_avl[3] = { 104000, 0x04 }, | |
403 | .odr_avl[4] = { 208000, 0x05 }, | |
404 | .odr_avl[5] = { 416000, 0x06 }, | |
59af4e20 | 405 | .odr_len = 6, |
40dd7343 LB |
406 | }, |
407 | [ST_LSM6DSX_ID_GYRO] = { | |
408 | .reg = { | |
409 | .addr = 0x11, | |
410 | .mask = GENMASK(7, 4), | |
411 | }, | |
f8710f03 LB |
412 | .odr_avl[0] = { 12500, 0x01 }, |
413 | .odr_avl[1] = { 26000, 0x02 }, | |
414 | .odr_avl[2] = { 52000, 0x03 }, | |
415 | .odr_avl[3] = { 104000, 0x04 }, | |
416 | .odr_avl[4] = { 208000, 0x05 }, | |
417 | .odr_avl[5] = { 416000, 0x06 }, | |
59af4e20 | 418 | .odr_len = 6, |
40dd7343 LB |
419 | }, |
420 | }, | |
640aca3f LB |
421 | .fs_table = { |
422 | [ST_LSM6DSX_ID_ACC] = { | |
423 | .reg = { | |
424 | .addr = 0x10, | |
425 | .mask = GENMASK(3, 2), | |
426 | }, | |
427 | .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, | |
428 | .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, | |
429 | .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, | |
430 | .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, | |
85ae3aee | 431 | .fs_len = 4, |
640aca3f LB |
432 | }, |
433 | [ST_LSM6DSX_ID_GYRO] = { | |
434 | .reg = { | |
435 | .addr = 0x11, | |
436 | .mask = GENMASK(3, 2), | |
437 | }, | |
438 | .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, | |
439 | .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, | |
440 | .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, | |
441 | .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, | |
85ae3aee | 442 | .fs_len = 4, |
640aca3f LB |
443 | }, |
444 | }, | |
7e906103 LB |
445 | .irq_config = { |
446 | .irq1 = { | |
447 | .addr = 0x0d, | |
448 | .mask = BIT(3), | |
449 | }, | |
450 | .irq2 = { | |
451 | .addr = 0x0e, | |
452 | .mask = BIT(3), | |
453 | }, | |
454 | .lir = { | |
455 | .addr = 0x58, | |
456 | .mask = BIT(0), | |
457 | }, | |
458 | .irq1_func = { | |
459 | .addr = 0x5e, | |
460 | .mask = BIT(5), | |
461 | }, | |
462 | .irq2_func = { | |
463 | .addr = 0x5f, | |
464 | .mask = BIT(5), | |
465 | }, | |
31fe8d4e LB |
466 | .hla = { |
467 | .addr = 0x12, | |
468 | .mask = BIT(5), | |
469 | }, | |
470 | .od = { | |
471 | .addr = 0x12, | |
472 | .mask = BIT(4), | |
473 | }, | |
7e906103 | 474 | }, |
7ca3ac9e LB |
475 | .decimator = { |
476 | [ST_LSM6DSX_ID_ACC] = { | |
477 | .addr = 0x08, | |
478 | .mask = GENMASK(2, 0), | |
479 | }, | |
480 | [ST_LSM6DSX_ID_GYRO] = { | |
481 | .addr = 0x08, | |
482 | .mask = GENMASK(5, 3), | |
483 | }, | |
484 | }, | |
92617c15 | 485 | .fifo_ops = { |
3b72950d | 486 | .update_fifo = st_lsm6dsx_update_fifo, |
50ff457d | 487 | .read_fifo = st_lsm6dsx_read_fifo, |
92617c15 LB |
488 | .fifo_th = { |
489 | .addr = 0x06, | |
490 | .mask = GENMASK(11, 0), | |
491 | }, | |
492 | .fifo_diff = { | |
493 | .addr = 0x3a, | |
494 | .mask = GENMASK(11, 0), | |
495 | }, | |
496 | .th_wl = 3, /* 1LSB = 2B */ | |
497 | }, | |
21345107 LB |
498 | .ts_settings = { |
499 | .timer_en = { | |
500 | .addr = 0x58, | |
501 | .mask = BIT(7), | |
502 | }, | |
503 | .hr_timer = { | |
504 | .addr = 0x5c, | |
505 | .mask = BIT(4), | |
506 | }, | |
507 | .fifo_en = { | |
508 | .addr = 0x07, | |
509 | .mask = BIT(7), | |
510 | }, | |
511 | .decimator = { | |
512 | .addr = 0x09, | |
513 | .mask = GENMASK(5, 3), | |
514 | }, | |
515 | }, | |
b5969abf SN |
516 | .event_settings = { |
517 | .wakeup_reg = { | |
518 | .addr = 0x5B, | |
519 | .mask = GENMASK(5, 0), | |
520 | }, | |
1aabad1f SN |
521 | .wakeup_src_reg = 0x1b, |
522 | .wakeup_src_status_mask = BIT(3), | |
523 | .wakeup_src_z_mask = BIT(0), | |
524 | .wakeup_src_y_mask = BIT(1), | |
525 | .wakeup_src_x_mask = BIT(2), | |
b5969abf | 526 | }, |
df47710a | 527 | }, |
290a6ce1 | 528 | { |
d068e4a0 | 529 | .wai = 0x6a, |
66b662a1 LB |
530 | .reset = { |
531 | .addr = 0x12, | |
532 | .mask = BIT(0), | |
533 | }, | |
534 | .boot = { | |
535 | .addr = 0x12, | |
536 | .mask = BIT(7), | |
537 | }, | |
538 | .bdu = { | |
539 | .addr = 0x12, | |
540 | .mask = BIT(6), | |
541 | }, | |
8f2a88a2 | 542 | .max_fifo_size = 682, |
d068e4a0 | 543 | .id = { |
81956a93 LB |
544 | { |
545 | .hw_id = ST_LSM6DSL_ID, | |
546 | .name = ST_LSM6DSL_DEV_NAME, | |
547 | }, { | |
548 | .hw_id = ST_LSM6DSM_ID, | |
549 | .name = ST_LSM6DSM_DEV_NAME, | |
550 | }, { | |
551 | .hw_id = ST_ISM330DLC_ID, | |
552 | .name = ST_ISM330DLC_DEV_NAME, | |
dbcd2088 LB |
553 | }, { |
554 | .hw_id = ST_LSM6DS3TRC_ID, | |
555 | .name = ST_LSM6DS3TRC_DEV_NAME, | |
81956a93 | 556 | }, |
d068e4a0 | 557 | }, |
f48bc49b LB |
558 | .channels = { |
559 | [ST_LSM6DSX_ID_ACC] = { | |
560 | .chan = st_lsm6dsx_acc_channels, | |
561 | .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), | |
562 | }, | |
563 | [ST_LSM6DSX_ID_GYRO] = { | |
564 | .chan = st_lsm6dsx_gyro_channels, | |
565 | .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), | |
566 | }, | |
567 | }, | |
40dd7343 LB |
568 | .odr_table = { |
569 | [ST_LSM6DSX_ID_ACC] = { | |
570 | .reg = { | |
571 | .addr = 0x10, | |
572 | .mask = GENMASK(7, 4), | |
573 | }, | |
f8710f03 LB |
574 | .odr_avl[0] = { 12500, 0x01 }, |
575 | .odr_avl[1] = { 26000, 0x02 }, | |
576 | .odr_avl[2] = { 52000, 0x03 }, | |
577 | .odr_avl[3] = { 104000, 0x04 }, | |
578 | .odr_avl[4] = { 208000, 0x05 }, | |
579 | .odr_avl[5] = { 416000, 0x06 }, | |
59af4e20 | 580 | .odr_len = 6, |
40dd7343 LB |
581 | }, |
582 | [ST_LSM6DSX_ID_GYRO] = { | |
583 | .reg = { | |
584 | .addr = 0x11, | |
585 | .mask = GENMASK(7, 4), | |
586 | }, | |
f8710f03 LB |
587 | .odr_avl[0] = { 12500, 0x01 }, |
588 | .odr_avl[1] = { 26000, 0x02 }, | |
589 | .odr_avl[2] = { 52000, 0x03 }, | |
590 | .odr_avl[3] = { 104000, 0x04 }, | |
591 | .odr_avl[4] = { 208000, 0x05 }, | |
592 | .odr_avl[5] = { 416000, 0x06 }, | |
59af4e20 | 593 | .odr_len = 6, |
40dd7343 LB |
594 | }, |
595 | }, | |
640aca3f LB |
596 | .fs_table = { |
597 | [ST_LSM6DSX_ID_ACC] = { | |
598 | .reg = { | |
599 | .addr = 0x10, | |
600 | .mask = GENMASK(3, 2), | |
601 | }, | |
602 | .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, | |
603 | .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, | |
604 | .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, | |
605 | .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, | |
85ae3aee | 606 | .fs_len = 4, |
640aca3f LB |
607 | }, |
608 | [ST_LSM6DSX_ID_GYRO] = { | |
609 | .reg = { | |
610 | .addr = 0x11, | |
611 | .mask = GENMASK(3, 2), | |
612 | }, | |
613 | .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, | |
614 | .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, | |
615 | .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, | |
616 | .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, | |
85ae3aee | 617 | .fs_len = 4, |
640aca3f LB |
618 | }, |
619 | }, | |
7e906103 LB |
620 | .irq_config = { |
621 | .irq1 = { | |
622 | .addr = 0x0d, | |
623 | .mask = BIT(3), | |
624 | }, | |
625 | .irq2 = { | |
626 | .addr = 0x0e, | |
627 | .mask = BIT(3), | |
628 | }, | |
629 | .lir = { | |
630 | .addr = 0x58, | |
631 | .mask = BIT(0), | |
632 | }, | |
633 | .irq1_func = { | |
634 | .addr = 0x5e, | |
635 | .mask = BIT(5), | |
636 | }, | |
637 | .irq2_func = { | |
638 | .addr = 0x5f, | |
639 | .mask = BIT(5), | |
640 | }, | |
31fe8d4e LB |
641 | .hla = { |
642 | .addr = 0x12, | |
643 | .mask = BIT(5), | |
644 | }, | |
645 | .od = { | |
646 | .addr = 0x12, | |
647 | .mask = BIT(4), | |
648 | }, | |
7e906103 | 649 | }, |
7ca3ac9e LB |
650 | .decimator = { |
651 | [ST_LSM6DSX_ID_ACC] = { | |
652 | .addr = 0x08, | |
653 | .mask = GENMASK(2, 0), | |
654 | }, | |
655 | [ST_LSM6DSX_ID_GYRO] = { | |
656 | .addr = 0x08, | |
657 | .mask = GENMASK(5, 3), | |
658 | }, | |
e485e2a2 LB |
659 | [ST_LSM6DSX_ID_EXT0] = { |
660 | .addr = 0x09, | |
661 | .mask = GENMASK(2, 0), | |
662 | }, | |
7ca3ac9e | 663 | }, |
92617c15 | 664 | .fifo_ops = { |
3b72950d | 665 | .update_fifo = st_lsm6dsx_update_fifo, |
50ff457d | 666 | .read_fifo = st_lsm6dsx_read_fifo, |
92617c15 LB |
667 | .fifo_th = { |
668 | .addr = 0x06, | |
be75eb86 | 669 | .mask = GENMASK(10, 0), |
92617c15 LB |
670 | }, |
671 | .fifo_diff = { | |
672 | .addr = 0x3a, | |
be75eb86 | 673 | .mask = GENMASK(10, 0), |
92617c15 LB |
674 | }, |
675 | .th_wl = 3, /* 1LSB = 2B */ | |
676 | }, | |
21345107 LB |
677 | .ts_settings = { |
678 | .timer_en = { | |
679 | .addr = 0x19, | |
680 | .mask = BIT(5), | |
681 | }, | |
682 | .hr_timer = { | |
683 | .addr = 0x5c, | |
684 | .mask = BIT(4), | |
685 | }, | |
686 | .fifo_en = { | |
687 | .addr = 0x07, | |
688 | .mask = BIT(7), | |
689 | }, | |
690 | .decimator = { | |
691 | .addr = 0x09, | |
692 | .mask = GENMASK(5, 3), | |
693 | }, | |
694 | }, | |
e485e2a2 LB |
695 | .shub_settings = { |
696 | .page_mux = { | |
697 | .addr = 0x01, | |
698 | .mask = BIT(7), | |
699 | }, | |
700 | .master_en = { | |
701 | .addr = 0x1a, | |
702 | .mask = BIT(0), | |
703 | }, | |
704 | .pullup_en = { | |
705 | .addr = 0x1a, | |
706 | .mask = BIT(3), | |
707 | }, | |
708 | .aux_sens = { | |
709 | .addr = 0x04, | |
710 | .mask = GENMASK(5, 4), | |
711 | }, | |
712 | .wr_once = { | |
713 | .addr = 0x07, | |
714 | .mask = BIT(5), | |
715 | }, | |
716 | .emb_func = { | |
717 | .addr = 0x19, | |
718 | .mask = BIT(2), | |
719 | }, | |
720 | .num_ext_dev = 1, | |
721 | .shub_out = { | |
722 | .addr = 0x2e, | |
723 | }, | |
724 | .slv0_addr = 0x02, | |
725 | .dw_slv0_addr = 0x0e, | |
726 | .pause = 0x7, | |
727 | }, | |
b5969abf SN |
728 | .event_settings = { |
729 | .enable_reg = { | |
730 | .addr = 0x58, | |
731 | .mask = BIT(7), | |
732 | }, | |
733 | .wakeup_reg = { | |
734 | .addr = 0x5B, | |
735 | .mask = GENMASK(5, 0), | |
736 | }, | |
1aabad1f SN |
737 | .wakeup_src_reg = 0x1b, |
738 | .wakeup_src_status_mask = BIT(3), | |
739 | .wakeup_src_z_mask = BIT(0), | |
740 | .wakeup_src_y_mask = BIT(1), | |
741 | .wakeup_src_x_mask = BIT(2), | |
b5969abf | 742 | }, |
290a6ce1 | 743 | }, |
801a6e0a LB |
744 | { |
745 | .wai = 0x6c, | |
66b662a1 LB |
746 | .reset = { |
747 | .addr = 0x12, | |
748 | .mask = BIT(0), | |
749 | }, | |
750 | .boot = { | |
751 | .addr = 0x12, | |
752 | .mask = BIT(7), | |
753 | }, | |
754 | .bdu = { | |
755 | .addr = 0x12, | |
756 | .mask = BIT(6), | |
757 | }, | |
801a6e0a LB |
758 | .max_fifo_size = 512, |
759 | .id = { | |
81956a93 LB |
760 | { |
761 | .hw_id = ST_LSM6DSO_ID, | |
762 | .name = ST_LSM6DSO_DEV_NAME, | |
763 | }, { | |
764 | .hw_id = ST_LSM6DSOX_ID, | |
765 | .name = ST_LSM6DSOX_DEV_NAME, | |
766 | }, | |
801a6e0a | 767 | }, |
f48bc49b LB |
768 | .channels = { |
769 | [ST_LSM6DSX_ID_ACC] = { | |
770 | .chan = st_lsm6dsx_acc_channels, | |
771 | .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), | |
772 | }, | |
773 | [ST_LSM6DSX_ID_GYRO] = { | |
774 | .chan = st_lsm6dsx_gyro_channels, | |
775 | .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), | |
776 | }, | |
777 | }, | |
960506ed LB |
778 | .drdy_mask = { |
779 | .addr = 0x13, | |
780 | .mask = BIT(3), | |
781 | }, | |
40dd7343 LB |
782 | .odr_table = { |
783 | [ST_LSM6DSX_ID_ACC] = { | |
784 | .reg = { | |
785 | .addr = 0x10, | |
786 | .mask = GENMASK(7, 4), | |
787 | }, | |
f8710f03 LB |
788 | .odr_avl[0] = { 12500, 0x01 }, |
789 | .odr_avl[1] = { 26000, 0x02 }, | |
790 | .odr_avl[2] = { 52000, 0x03 }, | |
791 | .odr_avl[3] = { 104000, 0x04 }, | |
792 | .odr_avl[4] = { 208000, 0x05 }, | |
793 | .odr_avl[5] = { 416000, 0x06 }, | |
59af4e20 | 794 | .odr_len = 6, |
40dd7343 LB |
795 | }, |
796 | [ST_LSM6DSX_ID_GYRO] = { | |
797 | .reg = { | |
798 | .addr = 0x11, | |
799 | .mask = GENMASK(7, 4), | |
800 | }, | |
f8710f03 LB |
801 | .odr_avl[0] = { 12500, 0x01 }, |
802 | .odr_avl[1] = { 26000, 0x02 }, | |
803 | .odr_avl[2] = { 52000, 0x03 }, | |
804 | .odr_avl[3] = { 104000, 0x04 }, | |
805 | .odr_avl[4] = { 208000, 0x05 }, | |
806 | .odr_avl[5] = { 416000, 0x06 }, | |
59af4e20 | 807 | .odr_len = 6, |
40dd7343 LB |
808 | }, |
809 | }, | |
640aca3f LB |
810 | .fs_table = { |
811 | [ST_LSM6DSX_ID_ACC] = { | |
812 | .reg = { | |
813 | .addr = 0x10, | |
814 | .mask = GENMASK(3, 2), | |
815 | }, | |
816 | .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, | |
817 | .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, | |
818 | .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, | |
819 | .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, | |
85ae3aee | 820 | .fs_len = 4, |
640aca3f LB |
821 | }, |
822 | [ST_LSM6DSX_ID_GYRO] = { | |
823 | .reg = { | |
824 | .addr = 0x11, | |
825 | .mask = GENMASK(3, 2), | |
826 | }, | |
827 | .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, | |
828 | .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, | |
829 | .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, | |
830 | .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, | |
85ae3aee | 831 | .fs_len = 4, |
640aca3f LB |
832 | }, |
833 | }, | |
7e906103 LB |
834 | .irq_config = { |
835 | .irq1 = { | |
836 | .addr = 0x0d, | |
837 | .mask = BIT(3), | |
838 | }, | |
839 | .irq2 = { | |
840 | .addr = 0x0e, | |
841 | .mask = BIT(3), | |
842 | }, | |
843 | .lir = { | |
844 | .addr = 0x56, | |
845 | .mask = BIT(0), | |
846 | }, | |
847 | .clear_on_read = { | |
848 | .addr = 0x56, | |
849 | .mask = BIT(6), | |
850 | }, | |
3ea39d61 LB |
851 | .irq1_func = { |
852 | .addr = 0x5e, | |
853 | .mask = BIT(5), | |
854 | }, | |
855 | .irq2_func = { | |
856 | .addr = 0x5f, | |
857 | .mask = BIT(5), | |
858 | }, | |
31fe8d4e LB |
859 | .hla = { |
860 | .addr = 0x12, | |
861 | .mask = BIT(5), | |
862 | }, | |
863 | .od = { | |
864 | .addr = 0x12, | |
865 | .mask = BIT(4), | |
866 | }, | |
7e906103 | 867 | }, |
801a6e0a LB |
868 | .batch = { |
869 | [ST_LSM6DSX_ID_ACC] = { | |
870 | .addr = 0x09, | |
871 | .mask = GENMASK(3, 0), | |
872 | }, | |
873 | [ST_LSM6DSX_ID_GYRO] = { | |
874 | .addr = 0x09, | |
875 | .mask = GENMASK(7, 4), | |
876 | }, | |
877 | }, | |
878 | .fifo_ops = { | |
3b72950d | 879 | .update_fifo = st_lsm6dsx_update_fifo, |
801a6e0a LB |
880 | .read_fifo = st_lsm6dsx_read_tagged_fifo, |
881 | .fifo_th = { | |
882 | .addr = 0x07, | |
883 | .mask = GENMASK(8, 0), | |
884 | }, | |
885 | .fifo_diff = { | |
886 | .addr = 0x3a, | |
70575abe | 887 | .mask = GENMASK(9, 0), |
801a6e0a LB |
888 | }, |
889 | .th_wl = 1, | |
890 | }, | |
891 | .ts_settings = { | |
892 | .timer_en = { | |
893 | .addr = 0x19, | |
894 | .mask = BIT(5), | |
895 | }, | |
896 | .decimator = { | |
897 | .addr = 0x0a, | |
898 | .mask = GENMASK(7, 6), | |
899 | }, | |
cb3b6b8e | 900 | .freq_fine = 0x63, |
801a6e0a | 901 | }, |
c91c1c84 LB |
902 | .shub_settings = { |
903 | .page_mux = { | |
904 | .addr = 0x01, | |
905 | .mask = BIT(6), | |
906 | }, | |
907 | .master_en = { | |
007f2ebb | 908 | .sec_page = true, |
c91c1c84 LB |
909 | .addr = 0x14, |
910 | .mask = BIT(2), | |
911 | }, | |
912 | .pullup_en = { | |
3a431957 | 913 | .sec_page = true, |
c91c1c84 LB |
914 | .addr = 0x14, |
915 | .mask = BIT(3), | |
916 | }, | |
917 | .aux_sens = { | |
918 | .addr = 0x14, | |
919 | .mask = GENMASK(1, 0), | |
920 | }, | |
6d0205fd LB |
921 | .wr_once = { |
922 | .addr = 0x14, | |
923 | .mask = BIT(6), | |
924 | }, | |
ee978bb8 | 925 | .num_ext_dev = 3, |
5b8343e0 LB |
926 | .shub_out = { |
927 | .sec_page = true, | |
928 | .addr = 0x02, | |
929 | }, | |
c91c1c84 LB |
930 | .slv0_addr = 0x15, |
931 | .dw_slv0_addr = 0x21, | |
6d0205fd | 932 | .batch_en = BIT(3), |
3ea39d61 LB |
933 | }, |
934 | .event_settings = { | |
935 | .enable_reg = { | |
936 | .addr = 0x58, | |
937 | .mask = BIT(7), | |
938 | }, | |
939 | .wakeup_reg = { | |
940 | .addr = 0x5b, | |
941 | .mask = GENMASK(5, 0), | |
942 | }, | |
943 | .wakeup_src_reg = 0x1b, | |
944 | .wakeup_src_status_mask = BIT(3), | |
945 | .wakeup_src_z_mask = BIT(0), | |
946 | .wakeup_src_y_mask = BIT(1), | |
947 | .wakeup_src_x_mask = BIT(2), | |
948 | }, | |
801a6e0a | 949 | }, |
3054c4ff LB |
950 | { |
951 | .wai = 0x6b, | |
66b662a1 LB |
952 | .reset = { |
953 | .addr = 0x12, | |
954 | .mask = BIT(0), | |
955 | }, | |
956 | .boot = { | |
957 | .addr = 0x12, | |
958 | .mask = BIT(7), | |
959 | }, | |
960 | .bdu = { | |
961 | .addr = 0x12, | |
962 | .mask = BIT(6), | |
963 | }, | |
3054c4ff LB |
964 | .max_fifo_size = 512, |
965 | .id = { | |
81956a93 LB |
966 | { |
967 | .hw_id = ST_ASM330LHH_ID, | |
968 | .name = ST_ASM330LHH_DEV_NAME, | |
969 | }, | |
3054c4ff | 970 | }, |
f48bc49b LB |
971 | .channels = { |
972 | [ST_LSM6DSX_ID_ACC] = { | |
973 | .chan = st_lsm6dsx_acc_channels, | |
974 | .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), | |
975 | }, | |
976 | [ST_LSM6DSX_ID_GYRO] = { | |
977 | .chan = st_lsm6dsx_gyro_channels, | |
978 | .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), | |
979 | }, | |
980 | }, | |
960506ed LB |
981 | .drdy_mask = { |
982 | .addr = 0x13, | |
983 | .mask = BIT(3), | |
984 | }, | |
40dd7343 LB |
985 | .odr_table = { |
986 | [ST_LSM6DSX_ID_ACC] = { | |
987 | .reg = { | |
988 | .addr = 0x10, | |
989 | .mask = GENMASK(7, 4), | |
990 | }, | |
f8710f03 LB |
991 | .odr_avl[0] = { 12500, 0x01 }, |
992 | .odr_avl[1] = { 26000, 0x02 }, | |
993 | .odr_avl[2] = { 52000, 0x03 }, | |
994 | .odr_avl[3] = { 104000, 0x04 }, | |
995 | .odr_avl[4] = { 208000, 0x05 }, | |
996 | .odr_avl[5] = { 416000, 0x06 }, | |
59af4e20 | 997 | .odr_len = 6, |
40dd7343 LB |
998 | }, |
999 | [ST_LSM6DSX_ID_GYRO] = { | |
1000 | .reg = { | |
1001 | .addr = 0x11, | |
1002 | .mask = GENMASK(7, 4), | |
1003 | }, | |
f8710f03 LB |
1004 | .odr_avl[0] = { 12500, 0x01 }, |
1005 | .odr_avl[1] = { 26000, 0x02 }, | |
1006 | .odr_avl[2] = { 52000, 0x03 }, | |
1007 | .odr_avl[3] = { 104000, 0x04 }, | |
1008 | .odr_avl[4] = { 208000, 0x05 }, | |
1009 | .odr_avl[5] = { 416000, 0x06 }, | |
59af4e20 | 1010 | .odr_len = 6, |
40dd7343 LB |
1011 | }, |
1012 | }, | |
640aca3f LB |
1013 | .fs_table = { |
1014 | [ST_LSM6DSX_ID_ACC] = { | |
1015 | .reg = { | |
1016 | .addr = 0x10, | |
1017 | .mask = GENMASK(3, 2), | |
1018 | }, | |
1019 | .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, | |
1020 | .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, | |
1021 | .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, | |
1022 | .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, | |
85ae3aee | 1023 | .fs_len = 4, |
640aca3f LB |
1024 | }, |
1025 | [ST_LSM6DSX_ID_GYRO] = { | |
1026 | .reg = { | |
1027 | .addr = 0x11, | |
1028 | .mask = GENMASK(3, 2), | |
1029 | }, | |
1030 | .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, | |
1031 | .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, | |
1032 | .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, | |
1033 | .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, | |
85ae3aee | 1034 | .fs_len = 4, |
640aca3f LB |
1035 | }, |
1036 | }, | |
7e906103 LB |
1037 | .irq_config = { |
1038 | .irq1 = { | |
1039 | .addr = 0x0d, | |
1040 | .mask = BIT(3), | |
1041 | }, | |
1042 | .irq2 = { | |
1043 | .addr = 0x0e, | |
1044 | .mask = BIT(3), | |
1045 | }, | |
1046 | .lir = { | |
1047 | .addr = 0x56, | |
1048 | .mask = BIT(0), | |
1049 | }, | |
1050 | .clear_on_read = { | |
1051 | .addr = 0x56, | |
1052 | .mask = BIT(6), | |
1053 | }, | |
1054 | .irq1_func = { | |
1055 | .addr = 0x5e, | |
1056 | .mask = BIT(5), | |
1057 | }, | |
1058 | .irq2_func = { | |
1059 | .addr = 0x5f, | |
1060 | .mask = BIT(5), | |
1061 | }, | |
31fe8d4e LB |
1062 | .hla = { |
1063 | .addr = 0x12, | |
1064 | .mask = BIT(5), | |
1065 | }, | |
1066 | .od = { | |
1067 | .addr = 0x12, | |
1068 | .mask = BIT(4), | |
1069 | }, | |
7e906103 | 1070 | }, |
3054c4ff LB |
1071 | .batch = { |
1072 | [ST_LSM6DSX_ID_ACC] = { | |
1073 | .addr = 0x09, | |
1074 | .mask = GENMASK(3, 0), | |
1075 | }, | |
1076 | [ST_LSM6DSX_ID_GYRO] = { | |
1077 | .addr = 0x09, | |
1078 | .mask = GENMASK(7, 4), | |
1079 | }, | |
1080 | }, | |
1081 | .fifo_ops = { | |
3b72950d | 1082 | .update_fifo = st_lsm6dsx_update_fifo, |
3054c4ff LB |
1083 | .read_fifo = st_lsm6dsx_read_tagged_fifo, |
1084 | .fifo_th = { | |
1085 | .addr = 0x07, | |
1086 | .mask = GENMASK(8, 0), | |
1087 | }, | |
1088 | .fifo_diff = { | |
1089 | .addr = 0x3a, | |
70575abe | 1090 | .mask = GENMASK(9, 0), |
3054c4ff LB |
1091 | }, |
1092 | .th_wl = 1, | |
1093 | }, | |
1094 | .ts_settings = { | |
1095 | .timer_en = { | |
1096 | .addr = 0x19, | |
1097 | .mask = BIT(5), | |
1098 | }, | |
1099 | .decimator = { | |
1100 | .addr = 0x0a, | |
1101 | .mask = GENMASK(7, 6), | |
1102 | }, | |
cb3b6b8e | 1103 | .freq_fine = 0x63, |
3054c4ff | 1104 | }, |
b5969abf SN |
1105 | .event_settings = { |
1106 | .enable_reg = { | |
1107 | .addr = 0x58, | |
1108 | .mask = BIT(7), | |
1109 | }, | |
1110 | .wakeup_reg = { | |
1111 | .addr = 0x5B, | |
1112 | .mask = GENMASK(5, 0), | |
1113 | }, | |
1aabad1f SN |
1114 | .wakeup_src_reg = 0x1b, |
1115 | .wakeup_src_status_mask = BIT(3), | |
1116 | .wakeup_src_z_mask = BIT(0), | |
1117 | .wakeup_src_y_mask = BIT(1), | |
1118 | .wakeup_src_x_mask = BIT(2), | |
b5969abf | 1119 | }, |
3054c4ff | 1120 | }, |
43901008 LB |
1121 | { |
1122 | .wai = 0x6b, | |
66b662a1 LB |
1123 | .reset = { |
1124 | .addr = 0x12, | |
1125 | .mask = BIT(0), | |
1126 | }, | |
1127 | .boot = { | |
1128 | .addr = 0x12, | |
1129 | .mask = BIT(7), | |
1130 | }, | |
1131 | .bdu = { | |
1132 | .addr = 0x12, | |
1133 | .mask = BIT(6), | |
1134 | }, | |
43901008 LB |
1135 | .max_fifo_size = 512, |
1136 | .id = { | |
81956a93 LB |
1137 | { |
1138 | .hw_id = ST_LSM6DSR_ID, | |
1139 | .name = ST_LSM6DSR_DEV_NAME, | |
db947a79 LB |
1140 | }, { |
1141 | .hw_id = ST_ISM330DHCX_ID, | |
1142 | .name = ST_ISM330DHCX_DEV_NAME, | |
cf9c71b3 LB |
1143 | }, { |
1144 | .hw_id = ST_LSM6DSRX_ID, | |
1145 | .name = ST_LSM6DSRX_DEV_NAME, | |
81956a93 | 1146 | }, |
43901008 | 1147 | }, |
f48bc49b LB |
1148 | .channels = { |
1149 | [ST_LSM6DSX_ID_ACC] = { | |
1150 | .chan = st_lsm6dsx_acc_channels, | |
1151 | .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), | |
1152 | }, | |
1153 | [ST_LSM6DSX_ID_GYRO] = { | |
1154 | .chan = st_lsm6dsx_gyro_channels, | |
1155 | .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), | |
1156 | }, | |
1157 | }, | |
960506ed LB |
1158 | .drdy_mask = { |
1159 | .addr = 0x13, | |
1160 | .mask = BIT(3), | |
1161 | }, | |
40dd7343 LB |
1162 | .odr_table = { |
1163 | [ST_LSM6DSX_ID_ACC] = { | |
1164 | .reg = { | |
1165 | .addr = 0x10, | |
1166 | .mask = GENMASK(7, 4), | |
1167 | }, | |
f8710f03 LB |
1168 | .odr_avl[0] = { 12500, 0x01 }, |
1169 | .odr_avl[1] = { 26000, 0x02 }, | |
1170 | .odr_avl[2] = { 52000, 0x03 }, | |
1171 | .odr_avl[3] = { 104000, 0x04 }, | |
1172 | .odr_avl[4] = { 208000, 0x05 }, | |
1173 | .odr_avl[5] = { 416000, 0x06 }, | |
59af4e20 | 1174 | .odr_len = 6, |
40dd7343 LB |
1175 | }, |
1176 | [ST_LSM6DSX_ID_GYRO] = { | |
1177 | .reg = { | |
1178 | .addr = 0x11, | |
1179 | .mask = GENMASK(7, 4), | |
1180 | }, | |
f8710f03 LB |
1181 | .odr_avl[0] = { 12500, 0x01 }, |
1182 | .odr_avl[1] = { 26000, 0x02 }, | |
1183 | .odr_avl[2] = { 52000, 0x03 }, | |
1184 | .odr_avl[3] = { 104000, 0x04 }, | |
1185 | .odr_avl[4] = { 208000, 0x05 }, | |
1186 | .odr_avl[5] = { 416000, 0x06 }, | |
59af4e20 | 1187 | .odr_len = 6, |
40dd7343 LB |
1188 | }, |
1189 | }, | |
640aca3f LB |
1190 | .fs_table = { |
1191 | [ST_LSM6DSX_ID_ACC] = { | |
1192 | .reg = { | |
1193 | .addr = 0x10, | |
1194 | .mask = GENMASK(3, 2), | |
1195 | }, | |
1196 | .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, | |
1197 | .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, | |
1198 | .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, | |
1199 | .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, | |
85ae3aee | 1200 | .fs_len = 4, |
640aca3f LB |
1201 | }, |
1202 | [ST_LSM6DSX_ID_GYRO] = { | |
1203 | .reg = { | |
1204 | .addr = 0x11, | |
1205 | .mask = GENMASK(3, 2), | |
1206 | }, | |
1207 | .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, | |
1208 | .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, | |
1209 | .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, | |
1210 | .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, | |
85ae3aee | 1211 | .fs_len = 4, |
640aca3f LB |
1212 | }, |
1213 | }, | |
7e906103 LB |
1214 | .irq_config = { |
1215 | .irq1 = { | |
1216 | .addr = 0x0d, | |
1217 | .mask = BIT(3), | |
1218 | }, | |
1219 | .irq2 = { | |
1220 | .addr = 0x0e, | |
1221 | .mask = BIT(3), | |
1222 | }, | |
1223 | .lir = { | |
1224 | .addr = 0x56, | |
1225 | .mask = BIT(0), | |
1226 | }, | |
1227 | .clear_on_read = { | |
1228 | .addr = 0x56, | |
1229 | .mask = BIT(6), | |
1230 | }, | |
1231 | .irq1_func = { | |
1232 | .addr = 0x5e, | |
1233 | .mask = BIT(5), | |
1234 | }, | |
1235 | .irq2_func = { | |
1236 | .addr = 0x5f, | |
1237 | .mask = BIT(5), | |
1238 | }, | |
31fe8d4e LB |
1239 | .hla = { |
1240 | .addr = 0x12, | |
1241 | .mask = BIT(5), | |
1242 | }, | |
1243 | .od = { | |
1244 | .addr = 0x12, | |
1245 | .mask = BIT(4), | |
1246 | }, | |
7e906103 | 1247 | }, |
43901008 LB |
1248 | .batch = { |
1249 | [ST_LSM6DSX_ID_ACC] = { | |
1250 | .addr = 0x09, | |
1251 | .mask = GENMASK(3, 0), | |
1252 | }, | |
1253 | [ST_LSM6DSX_ID_GYRO] = { | |
1254 | .addr = 0x09, | |
1255 | .mask = GENMASK(7, 4), | |
1256 | }, | |
1257 | }, | |
1258 | .fifo_ops = { | |
3b72950d | 1259 | .update_fifo = st_lsm6dsx_update_fifo, |
43901008 LB |
1260 | .read_fifo = st_lsm6dsx_read_tagged_fifo, |
1261 | .fifo_th = { | |
1262 | .addr = 0x07, | |
1263 | .mask = GENMASK(8, 0), | |
1264 | }, | |
1265 | .fifo_diff = { | |
1266 | .addr = 0x3a, | |
70575abe | 1267 | .mask = GENMASK(9, 0), |
43901008 LB |
1268 | }, |
1269 | .th_wl = 1, | |
1270 | }, | |
1271 | .ts_settings = { | |
1272 | .timer_en = { | |
1273 | .addr = 0x19, | |
1274 | .mask = BIT(5), | |
1275 | }, | |
1276 | .decimator = { | |
1277 | .addr = 0x0a, | |
1278 | .mask = GENMASK(7, 6), | |
1279 | }, | |
cb3b6b8e | 1280 | .freq_fine = 0x63, |
43901008 LB |
1281 | }, |
1282 | .shub_settings = { | |
1283 | .page_mux = { | |
1284 | .addr = 0x01, | |
1285 | .mask = BIT(6), | |
1286 | }, | |
1287 | .master_en = { | |
007f2ebb | 1288 | .sec_page = true, |
43901008 LB |
1289 | .addr = 0x14, |
1290 | .mask = BIT(2), | |
1291 | }, | |
1292 | .pullup_en = { | |
3a431957 | 1293 | .sec_page = true, |
43901008 LB |
1294 | .addr = 0x14, |
1295 | .mask = BIT(3), | |
1296 | }, | |
1297 | .aux_sens = { | |
1298 | .addr = 0x14, | |
1299 | .mask = GENMASK(1, 0), | |
1300 | }, | |
1301 | .wr_once = { | |
1302 | .addr = 0x14, | |
1303 | .mask = BIT(6), | |
1304 | }, | |
ee978bb8 | 1305 | .num_ext_dev = 3, |
5b8343e0 LB |
1306 | .shub_out = { |
1307 | .sec_page = true, | |
1308 | .addr = 0x02, | |
1309 | }, | |
43901008 LB |
1310 | .slv0_addr = 0x15, |
1311 | .dw_slv0_addr = 0x21, | |
1312 | .batch_en = BIT(3), | |
b5969abf SN |
1313 | }, |
1314 | .event_settings = { | |
1315 | .enable_reg = { | |
1316 | .addr = 0x58, | |
1317 | .mask = BIT(7), | |
1318 | }, | |
1319 | .wakeup_reg = { | |
1320 | .addr = 0x5B, | |
1321 | .mask = GENMASK(5, 0), | |
1322 | }, | |
1aabad1f SN |
1323 | .wakeup_src_reg = 0x1b, |
1324 | .wakeup_src_status_mask = BIT(3), | |
1325 | .wakeup_src_z_mask = BIT(0), | |
1326 | .wakeup_src_y_mask = BIT(1), | |
1327 | .wakeup_src_x_mask = BIT(2), | |
43901008 LB |
1328 | } |
1329 | }, | |
290a6ce1 LB |
1330 | }; |
1331 | ||
c91c1c84 LB |
1332 | int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable) |
1333 | { | |
1334 | const struct st_lsm6dsx_shub_settings *hub_settings; | |
1335 | unsigned int data; | |
1336 | int err; | |
1337 | ||
1338 | hub_settings = &hw->settings->shub_settings; | |
1339 | data = ST_LSM6DSX_SHIFT_VAL(enable, hub_settings->page_mux.mask); | |
1340 | err = regmap_update_bits(hw->regmap, hub_settings->page_mux.addr, | |
1341 | hub_settings->page_mux.mask, data); | |
1342 | usleep_range(100, 150); | |
1343 | ||
1344 | return err; | |
1345 | } | |
1346 | ||
81956a93 LB |
1347 | static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id, |
1348 | const char **name) | |
290a6ce1 | 1349 | { |
51a8b707 | 1350 | int err, i, j, data; |
290a6ce1 LB |
1351 | |
1352 | for (i = 0; i < ARRAY_SIZE(st_lsm6dsx_sensor_settings); i++) { | |
d068e4a0 | 1353 | for (j = 0; j < ST_LSM6DSX_MAX_ID; j++) { |
fb4fbc89 SG |
1354 | if (st_lsm6dsx_sensor_settings[i].id[j].name && |
1355 | id == st_lsm6dsx_sensor_settings[i].id[j].hw_id) | |
d068e4a0 LB |
1356 | break; |
1357 | } | |
1358 | if (j < ST_LSM6DSX_MAX_ID) | |
290a6ce1 LB |
1359 | break; |
1360 | } | |
1361 | ||
1362 | if (i == ARRAY_SIZE(st_lsm6dsx_sensor_settings)) { | |
1363 | dev_err(hw->dev, "unsupported hw id [%02x]\n", id); | |
1364 | return -ENODEV; | |
1365 | } | |
1366 | ||
51a8b707 | 1367 | err = regmap_read(hw->regmap, ST_LSM6DSX_REG_WHOAMI_ADDR, &data); |
290a6ce1 LB |
1368 | if (err < 0) { |
1369 | dev_err(hw->dev, "failed to read whoami register\n"); | |
1370 | return err; | |
1371 | } | |
1372 | ||
1373 | if (data != st_lsm6dsx_sensor_settings[i].wai) { | |
1374 | dev_err(hw->dev, "unsupported whoami [%02x]\n", data); | |
1375 | return -ENODEV; | |
1376 | } | |
1377 | ||
81956a93 | 1378 | *name = st_lsm6dsx_sensor_settings[i].id[j].name; |
290a6ce1 LB |
1379 | hw->settings = &st_lsm6dsx_sensor_settings[i]; |
1380 | ||
1381 | return 0; | |
1382 | } | |
1383 | ||
1384 | static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor, | |
1385 | u32 gain) | |
1386 | { | |
640aca3f | 1387 | const struct st_lsm6dsx_fs_table_entry *fs_table; |
739aff87 | 1388 | unsigned int data; |
290a6ce1 | 1389 | int i, err; |
290a6ce1 | 1390 | |
640aca3f | 1391 | fs_table = &sensor->hw->settings->fs_table[sensor->id]; |
85ae3aee | 1392 | for (i = 0; i < fs_table->fs_len; i++) { |
640aca3f | 1393 | if (fs_table->fs_avl[i].gain == gain) |
290a6ce1 | 1394 | break; |
85ae3aee | 1395 | } |
290a6ce1 | 1396 | |
85ae3aee | 1397 | if (i == fs_table->fs_len) |
290a6ce1 LB |
1398 | return -EINVAL; |
1399 | ||
640aca3f LB |
1400 | data = ST_LSM6DSX_SHIFT_VAL(fs_table->fs_avl[i].val, |
1401 | fs_table->reg.mask); | |
1402 | err = st_lsm6dsx_update_bits_locked(sensor->hw, fs_table->reg.addr, | |
1403 | fs_table->reg.mask, data); | |
290a6ce1 LB |
1404 | if (err < 0) |
1405 | return err; | |
1406 | ||
1407 | sensor->gain = gain; | |
1408 | ||
1409 | return 0; | |
1410 | } | |
1411 | ||
f8710f03 | 1412 | int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u32 odr, u8 *val) |
290a6ce1 | 1413 | { |
40dd7343 | 1414 | const struct st_lsm6dsx_odr_table_entry *odr_table; |
2ccc1503 | 1415 | int i; |
290a6ce1 | 1416 | |
40dd7343 | 1417 | odr_table = &sensor->hw->settings->odr_table[sensor->id]; |
59af4e20 | 1418 | for (i = 0; i < odr_table->odr_len; i++) { |
6ffb55e5 LB |
1419 | /* |
1420 | * ext devices can run at different odr respect to | |
1421 | * accel sensor | |
1422 | */ | |
f8710f03 | 1423 | if (odr_table->odr_avl[i].milli_hz >= odr) |
290a6ce1 | 1424 | break; |
59af4e20 | 1425 | } |
290a6ce1 | 1426 | |
59af4e20 | 1427 | if (i == odr_table->odr_len) |
290a6ce1 LB |
1428 | return -EINVAL; |
1429 | ||
40dd7343 | 1430 | *val = odr_table->odr_avl[i].val; |
f8710f03 | 1431 | return odr_table->odr_avl[i].milli_hz; |
290a6ce1 LB |
1432 | } |
1433 | ||
f8710f03 LB |
1434 | static int |
1435 | st_lsm6dsx_check_odr_dependency(struct st_lsm6dsx_hw *hw, u32 odr, | |
1436 | enum st_lsm6dsx_sensor_id id) | |
2ccc1503 | 1437 | { |
6ffb55e5 LB |
1438 | struct st_lsm6dsx_sensor *ref = iio_priv(hw->iio_devs[id]); |
1439 | ||
1440 | if (odr > 0) { | |
1441 | if (hw->enable_mask & BIT(id)) | |
f8710f03 | 1442 | return max_t(u32, ref->odr, odr); |
6ffb55e5 LB |
1443 | else |
1444 | return odr; | |
1445 | } else { | |
1446 | return (hw->enable_mask & BIT(id)) ? ref->odr : 0; | |
1447 | } | |
1448 | } | |
1449 | ||
f8710f03 LB |
1450 | static int |
1451 | st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u32 req_odr) | |
6ffb55e5 LB |
1452 | { |
1453 | struct st_lsm6dsx_sensor *ref_sensor = sensor; | |
51a8b707 LB |
1454 | struct st_lsm6dsx_hw *hw = sensor->hw; |
1455 | const struct st_lsm6dsx_reg *reg; | |
739aff87 | 1456 | unsigned int data; |
6ffb55e5 | 1457 | u8 val = 0; |
2ccc1503 | 1458 | int err; |
2ccc1503 | 1459 | |
6ffb55e5 LB |
1460 | switch (sensor->id) { |
1461 | case ST_LSM6DSX_ID_EXT0: | |
1462 | case ST_LSM6DSX_ID_EXT1: | |
1463 | case ST_LSM6DSX_ID_EXT2: | |
1464 | case ST_LSM6DSX_ID_ACC: { | |
f8710f03 | 1465 | u32 odr; |
6ffb55e5 LB |
1466 | int i; |
1467 | ||
1468 | /* | |
1469 | * i2c embedded controller relies on the accelerometer sensor as | |
1470 | * bus read/write trigger so we need to enable accel device | |
1471 | * at odr = max(accel_odr, ext_odr) in order to properly | |
1472 | * communicate with i2c slave devices | |
1473 | */ | |
1474 | ref_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]); | |
1475 | for (i = ST_LSM6DSX_ID_ACC; i < ST_LSM6DSX_ID_MAX; i++) { | |
1476 | if (!hw->iio_devs[i] || i == sensor->id) | |
1477 | continue; | |
1478 | ||
1479 | odr = st_lsm6dsx_check_odr_dependency(hw, req_odr, i); | |
1480 | if (odr != req_odr) | |
1481 | /* device already configured */ | |
1482 | return 0; | |
1483 | } | |
1484 | break; | |
1485 | } | |
1486 | default: | |
1487 | break; | |
1488 | } | |
2ccc1503 | 1489 | |
6ffb55e5 LB |
1490 | if (req_odr > 0) { |
1491 | err = st_lsm6dsx_check_odr(ref_sensor, req_odr, &val); | |
1492 | if (err < 0) | |
1493 | return err; | |
1494 | } | |
1495 | ||
40dd7343 | 1496 | reg = &hw->settings->odr_table[ref_sensor->id].reg; |
739aff87 LB |
1497 | data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); |
1498 | return st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data); | |
2ccc1503 LB |
1499 | } |
1500 | ||
bd41c445 LB |
1501 | static int |
1502 | __st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor, | |
1503 | bool enable) | |
290a6ce1 | 1504 | { |
51a8b707 | 1505 | struct st_lsm6dsx_hw *hw = sensor->hw; |
f8710f03 | 1506 | u32 odr = enable ? sensor->odr : 0; |
290a6ce1 LB |
1507 | int err; |
1508 | ||
17750443 | 1509 | err = st_lsm6dsx_set_odr(sensor, odr); |
290a6ce1 LB |
1510 | if (err < 0) |
1511 | return err; | |
1512 | ||
17750443 LB |
1513 | if (enable) |
1514 | hw->enable_mask |= BIT(sensor->id); | |
1515 | else | |
1516 | hw->enable_mask &= ~BIT(sensor->id); | |
290a6ce1 LB |
1517 | |
1518 | return 0; | |
1519 | } | |
1520 | ||
bd41c445 LB |
1521 | static int |
1522 | st_lsm6dsx_check_events(struct st_lsm6dsx_sensor *sensor, bool enable) | |
1523 | { | |
1524 | struct st_lsm6dsx_hw *hw = sensor->hw; | |
1525 | ||
1526 | if (sensor->id == ST_LSM6DSX_ID_GYRO || enable) | |
1527 | return 0; | |
1528 | ||
1529 | return hw->enable_event; | |
1530 | } | |
1531 | ||
1532 | int st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor, | |
1533 | bool enable) | |
1534 | { | |
1535 | if (st_lsm6dsx_check_events(sensor, enable)) | |
1536 | return 0; | |
1537 | ||
1538 | return __st_lsm6dsx_sensor_set_enable(sensor, enable); | |
1539 | } | |
1540 | ||
290a6ce1 LB |
1541 | static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor, |
1542 | u8 addr, int *val) | |
1543 | { | |
51a8b707 | 1544 | struct st_lsm6dsx_hw *hw = sensor->hw; |
290a6ce1 LB |
1545 | int err, delay; |
1546 | __le16 data; | |
1547 | ||
17750443 | 1548 | err = st_lsm6dsx_sensor_set_enable(sensor, true); |
290a6ce1 LB |
1549 | if (err < 0) |
1550 | return err; | |
1551 | ||
f8710f03 | 1552 | delay = 1000000000 / sensor->odr; |
290a6ce1 LB |
1553 | usleep_range(delay, 2 * delay); |
1554 | ||
739aff87 | 1555 | err = st_lsm6dsx_read_locked(hw, addr, &data, sizeof(data)); |
290a6ce1 LB |
1556 | if (err < 0) |
1557 | return err; | |
1558 | ||
a2dd9bd9 LB |
1559 | if (!hw->enable_event) { |
1560 | err = st_lsm6dsx_sensor_set_enable(sensor, false); | |
1561 | if (err < 0) | |
1562 | return err; | |
1563 | } | |
290a6ce1 | 1564 | |
7b9ebe42 | 1565 | *val = (s16)le16_to_cpu(data); |
290a6ce1 LB |
1566 | |
1567 | return IIO_VAL_INT; | |
1568 | } | |
1569 | ||
1570 | static int st_lsm6dsx_read_raw(struct iio_dev *iio_dev, | |
1571 | struct iio_chan_spec const *ch, | |
1572 | int *val, int *val2, long mask) | |
1573 | { | |
1574 | struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); | |
1575 | int ret; | |
1576 | ||
1577 | switch (mask) { | |
1578 | case IIO_CHAN_INFO_RAW: | |
1579 | ret = iio_device_claim_direct_mode(iio_dev); | |
1580 | if (ret) | |
1581 | break; | |
1582 | ||
1583 | ret = st_lsm6dsx_read_oneshot(sensor, ch->address, val); | |
1584 | iio_device_release_direct_mode(iio_dev); | |
1585 | break; | |
1586 | case IIO_CHAN_INFO_SAMP_FREQ: | |
f8710f03 LB |
1587 | *val = sensor->odr / 1000; |
1588 | *val2 = (sensor->odr % 1000) * 1000; | |
1589 | ret = IIO_VAL_INT_PLUS_MICRO; | |
290a6ce1 LB |
1590 | break; |
1591 | case IIO_CHAN_INFO_SCALE: | |
1592 | *val = 0; | |
1593 | *val2 = sensor->gain; | |
1594 | ret = IIO_VAL_INT_PLUS_MICRO; | |
1595 | break; | |
1596 | default: | |
1597 | ret = -EINVAL; | |
1598 | break; | |
1599 | } | |
1600 | ||
1601 | return ret; | |
1602 | } | |
1603 | ||
1604 | static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev, | |
1605 | struct iio_chan_spec const *chan, | |
1606 | int val, int val2, long mask) | |
1607 | { | |
1608 | struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); | |
1609 | int err; | |
1610 | ||
1611 | err = iio_device_claim_direct_mode(iio_dev); | |
1612 | if (err) | |
1613 | return err; | |
1614 | ||
1615 | switch (mask) { | |
1616 | case IIO_CHAN_INFO_SCALE: | |
1617 | err = st_lsm6dsx_set_full_scale(sensor, val2); | |
1618 | break; | |
2ccc1503 LB |
1619 | case IIO_CHAN_INFO_SAMP_FREQ: { |
1620 | u8 data; | |
1621 | ||
f8710f03 | 1622 | val = val * 1000 + val2 / 1000; |
fc3f6ad7 LB |
1623 | val = st_lsm6dsx_check_odr(sensor, val, &data); |
1624 | if (val < 0) | |
1625 | err = val; | |
1626 | else | |
5e3c3e33 | 1627 | sensor->odr = val; |
290a6ce1 | 1628 | break; |
2ccc1503 | 1629 | } |
290a6ce1 LB |
1630 | default: |
1631 | err = -EINVAL; | |
1632 | break; | |
1633 | } | |
1634 | ||
1635 | iio_device_release_direct_mode(iio_dev); | |
1636 | ||
1637 | return err; | |
1638 | } | |
1639 | ||
b5969abf SN |
1640 | static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, int state) |
1641 | { | |
84b2e7c3 | 1642 | const struct st_lsm6dsx_reg *reg; |
04ca37d5 | 1643 | unsigned int data; |
b5969abf | 1644 | int err; |
b5969abf | 1645 | |
7e906103 | 1646 | if (!hw->settings->irq_config.irq1_func.addr) |
b5969abf SN |
1647 | return -ENOTSUPP; |
1648 | ||
84b2e7c3 LB |
1649 | reg = &hw->settings->event_settings.enable_reg; |
1650 | if (reg->addr) { | |
04ca37d5 LB |
1651 | data = ST_LSM6DSX_SHIFT_VAL(state, reg->mask); |
1652 | err = st_lsm6dsx_update_bits_locked(hw, reg->addr, | |
1653 | reg->mask, data); | |
84b2e7c3 LB |
1654 | if (err < 0) |
1655 | return err; | |
1656 | } | |
b5969abf SN |
1657 | |
1658 | /* Enable wakeup interrupt */ | |
04ca37d5 LB |
1659 | data = ST_LSM6DSX_SHIFT_VAL(state, hw->irq_routing->mask); |
1660 | return st_lsm6dsx_update_bits_locked(hw, hw->irq_routing->addr, | |
1661 | hw->irq_routing->mask, data); | |
b5969abf SN |
1662 | } |
1663 | ||
1664 | static int st_lsm6dsx_read_event(struct iio_dev *iio_dev, | |
757b4bca LB |
1665 | const struct iio_chan_spec *chan, |
1666 | enum iio_event_type type, | |
1667 | enum iio_event_direction dir, | |
1668 | enum iio_event_info info, | |
1669 | int *val, int *val2) | |
b5969abf SN |
1670 | { |
1671 | struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); | |
1672 | struct st_lsm6dsx_hw *hw = sensor->hw; | |
1673 | ||
1674 | if (type != IIO_EV_TYPE_THRESH) | |
1675 | return -EINVAL; | |
1676 | ||
1677 | *val2 = 0; | |
1678 | *val = hw->event_threshold; | |
1679 | ||
1680 | return IIO_VAL_INT; | |
1681 | } | |
1682 | ||
b307f495 LB |
1683 | static int |
1684 | st_lsm6dsx_write_event(struct iio_dev *iio_dev, | |
1685 | const struct iio_chan_spec *chan, | |
1686 | enum iio_event_type type, | |
1687 | enum iio_event_direction dir, | |
1688 | enum iio_event_info info, | |
1689 | int val, int val2) | |
b5969abf SN |
1690 | { |
1691 | struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); | |
1692 | struct st_lsm6dsx_hw *hw = sensor->hw; | |
04ca37d5 LB |
1693 | const struct st_lsm6dsx_reg *reg; |
1694 | unsigned int data; | |
b5969abf SN |
1695 | int err; |
1696 | ||
1697 | if (type != IIO_EV_TYPE_THRESH) | |
1698 | return -EINVAL; | |
1699 | ||
1700 | if (val < 0 || val > 31) | |
1701 | return -EINVAL; | |
1702 | ||
04ca37d5 LB |
1703 | reg = &hw->settings->event_settings.wakeup_reg; |
1704 | data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); | |
1705 | err = st_lsm6dsx_update_bits_locked(hw, reg->addr, | |
1706 | reg->mask, data); | |
1707 | if (err < 0) | |
b5969abf SN |
1708 | return -EINVAL; |
1709 | ||
1710 | hw->event_threshold = val; | |
1711 | ||
1712 | return 0; | |
1713 | } | |
1714 | ||
b307f495 LB |
1715 | static int |
1716 | st_lsm6dsx_read_event_config(struct iio_dev *iio_dev, | |
1717 | const struct iio_chan_spec *chan, | |
1718 | enum iio_event_type type, | |
1719 | enum iio_event_direction dir) | |
b5969abf SN |
1720 | { |
1721 | struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); | |
1722 | struct st_lsm6dsx_hw *hw = sensor->hw; | |
1723 | ||
1724 | if (type != IIO_EV_TYPE_THRESH) | |
1725 | return -EINVAL; | |
1726 | ||
1aabad1f | 1727 | return !!(hw->enable_event & BIT(chan->channel2)); |
b5969abf SN |
1728 | } |
1729 | ||
b307f495 LB |
1730 | static int |
1731 | st_lsm6dsx_write_event_config(struct iio_dev *iio_dev, | |
1732 | const struct iio_chan_spec *chan, | |
1733 | enum iio_event_type type, | |
1734 | enum iio_event_direction dir, int state) | |
b5969abf SN |
1735 | { |
1736 | struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); | |
1737 | struct st_lsm6dsx_hw *hw = sensor->hw; | |
1aabad1f | 1738 | u8 enable_event; |
bd41c445 | 1739 | int err; |
b5969abf SN |
1740 | |
1741 | if (type != IIO_EV_TYPE_THRESH) | |
1742 | return -EINVAL; | |
1743 | ||
1aabad1f SN |
1744 | if (state) { |
1745 | enable_event = hw->enable_event | BIT(chan->channel2); | |
1746 | ||
1747 | /* do not enable events if they are already enabled */ | |
1748 | if (hw->enable_event) | |
1749 | goto out; | |
1750 | } else { | |
1751 | enable_event = hw->enable_event & ~BIT(chan->channel2); | |
1752 | ||
1753 | /* only turn off sensor if no events is enabled */ | |
1754 | if (enable_event) | |
1755 | goto out; | |
1756 | } | |
1757 | ||
1758 | /* stop here if no changes have been made */ | |
1759 | if (hw->enable_event == enable_event) | |
b5969abf SN |
1760 | return 0; |
1761 | ||
1762 | err = st_lsm6dsx_event_setup(hw, state); | |
1763 | if (err < 0) | |
1764 | return err; | |
1765 | ||
d278d447 | 1766 | mutex_lock(&hw->conf_lock); |
bd41c445 LB |
1767 | if (enable_event || !(hw->fifo_mask & BIT(sensor->id))) |
1768 | err = __st_lsm6dsx_sensor_set_enable(sensor, state); | |
d278d447 | 1769 | mutex_unlock(&hw->conf_lock); |
b5969abf SN |
1770 | if (err < 0) |
1771 | return err; | |
1772 | ||
1aabad1f SN |
1773 | out: |
1774 | hw->enable_event = enable_event; | |
b5969abf SN |
1775 | |
1776 | return 0; | |
1777 | } | |
1778 | ||
d40464f3 | 1779 | int st_lsm6dsx_set_watermark(struct iio_dev *iio_dev, unsigned int val) |
290a6ce1 LB |
1780 | { |
1781 | struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); | |
1782 | struct st_lsm6dsx_hw *hw = sensor->hw; | |
8f2a88a2 | 1783 | int err; |
290a6ce1 | 1784 | |
8f2a88a2 | 1785 | if (val < 1 || val > hw->settings->max_fifo_size) |
290a6ce1 LB |
1786 | return -EINVAL; |
1787 | ||
335eaedc LB |
1788 | mutex_lock(&hw->conf_lock); |
1789 | ||
290a6ce1 | 1790 | err = st_lsm6dsx_update_watermark(sensor, val); |
335eaedc LB |
1791 | |
1792 | mutex_unlock(&hw->conf_lock); | |
1793 | ||
290a6ce1 LB |
1794 | if (err < 0) |
1795 | return err; | |
1796 | ||
1797 | sensor->watermark = val; | |
1798 | ||
1799 | return 0; | |
1800 | } | |
1801 | ||
1802 | static ssize_t | |
1803 | st_lsm6dsx_sysfs_sampling_frequency_avail(struct device *dev, | |
1804 | struct device_attribute *attr, | |
1805 | char *buf) | |
1806 | { | |
1807 | struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev)); | |
59af4e20 | 1808 | const struct st_lsm6dsx_odr_table_entry *odr_table; |
290a6ce1 LB |
1809 | int i, len = 0; |
1810 | ||
59af4e20 LB |
1811 | odr_table = &sensor->hw->settings->odr_table[sensor->id]; |
1812 | for (i = 0; i < odr_table->odr_len; i++) | |
f8710f03 LB |
1813 | len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%03d ", |
1814 | odr_table->odr_avl[i].milli_hz / 1000, | |
1815 | odr_table->odr_avl[i].milli_hz % 1000); | |
290a6ce1 LB |
1816 | buf[len - 1] = '\n'; |
1817 | ||
1818 | return len; | |
1819 | } | |
1820 | ||
1821 | static ssize_t st_lsm6dsx_sysfs_scale_avail(struct device *dev, | |
1822 | struct device_attribute *attr, | |
1823 | char *buf) | |
1824 | { | |
1825 | struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev)); | |
0f7e1728 | 1826 | const struct st_lsm6dsx_fs_table_entry *fs_table; |
640aca3f | 1827 | struct st_lsm6dsx_hw *hw = sensor->hw; |
290a6ce1 LB |
1828 | int i, len = 0; |
1829 | ||
85ae3aee LB |
1830 | fs_table = &hw->settings->fs_table[sensor->id]; |
1831 | for (i = 0; i < fs_table->fs_len; i++) | |
290a6ce1 | 1832 | len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ", |
0f7e1728 | 1833 | fs_table->fs_avl[i].gain); |
290a6ce1 LB |
1834 | buf[len - 1] = '\n'; |
1835 | ||
1836 | return len; | |
1837 | } | |
1838 | ||
1839 | static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(st_lsm6dsx_sysfs_sampling_frequency_avail); | |
1840 | static IIO_DEVICE_ATTR(in_accel_scale_available, 0444, | |
1841 | st_lsm6dsx_sysfs_scale_avail, NULL, 0); | |
1842 | static IIO_DEVICE_ATTR(in_anglvel_scale_available, 0444, | |
1843 | st_lsm6dsx_sysfs_scale_avail, NULL, 0); | |
1844 | ||
1845 | static struct attribute *st_lsm6dsx_acc_attributes[] = { | |
1846 | &iio_dev_attr_sampling_frequency_available.dev_attr.attr, | |
1847 | &iio_dev_attr_in_accel_scale_available.dev_attr.attr, | |
1848 | NULL, | |
1849 | }; | |
1850 | ||
1851 | static const struct attribute_group st_lsm6dsx_acc_attribute_group = { | |
1852 | .attrs = st_lsm6dsx_acc_attributes, | |
1853 | }; | |
1854 | ||
1855 | static const struct iio_info st_lsm6dsx_acc_info = { | |
290a6ce1 LB |
1856 | .attrs = &st_lsm6dsx_acc_attribute_group, |
1857 | .read_raw = st_lsm6dsx_read_raw, | |
1858 | .write_raw = st_lsm6dsx_write_raw, | |
b5969abf SN |
1859 | .read_event_value = st_lsm6dsx_read_event, |
1860 | .write_event_value = st_lsm6dsx_write_event, | |
1861 | .read_event_config = st_lsm6dsx_read_event_config, | |
1862 | .write_event_config = st_lsm6dsx_write_event_config, | |
290a6ce1 LB |
1863 | .hwfifo_set_watermark = st_lsm6dsx_set_watermark, |
1864 | }; | |
1865 | ||
1866 | static struct attribute *st_lsm6dsx_gyro_attributes[] = { | |
1867 | &iio_dev_attr_sampling_frequency_available.dev_attr.attr, | |
1868 | &iio_dev_attr_in_anglvel_scale_available.dev_attr.attr, | |
1869 | NULL, | |
1870 | }; | |
1871 | ||
1872 | static const struct attribute_group st_lsm6dsx_gyro_attribute_group = { | |
1873 | .attrs = st_lsm6dsx_gyro_attributes, | |
1874 | }; | |
1875 | ||
1876 | static const struct iio_info st_lsm6dsx_gyro_info = { | |
290a6ce1 LB |
1877 | .attrs = &st_lsm6dsx_gyro_attribute_group, |
1878 | .read_raw = st_lsm6dsx_read_raw, | |
1879 | .write_raw = st_lsm6dsx_write_raw, | |
1880 | .hwfifo_set_watermark = st_lsm6dsx_set_watermark, | |
1881 | }; | |
1882 | ||
03d4c566 | 1883 | static int st_lsm6dsx_get_drdy_pin(struct st_lsm6dsx_hw *hw, int *drdy_pin) |
dba32904 | 1884 | { |
03d4c566 | 1885 | struct device *dev = hw->dev; |
dba32904 | 1886 | |
03d4c566 | 1887 | if (!dev_fwnode(dev)) |
dba32904 LB |
1888 | return -EINVAL; |
1889 | ||
03d4c566 | 1890 | return device_property_read_u32(dev, "st,drdy-int-pin", drdy_pin); |
dba32904 LB |
1891 | } |
1892 | ||
7e906103 LB |
1893 | static int |
1894 | st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw, | |
1895 | const struct st_lsm6dsx_reg **drdy_reg) | |
dba32904 LB |
1896 | { |
1897 | int err = 0, drdy_pin; | |
1898 | ||
03d4c566 | 1899 | if (st_lsm6dsx_get_drdy_pin(hw, &drdy_pin) < 0) { |
dba32904 LB |
1900 | struct st_sensors_platform_data *pdata; |
1901 | struct device *dev = hw->dev; | |
1902 | ||
1903 | pdata = (struct st_sensors_platform_data *)dev->platform_data; | |
1904 | drdy_pin = pdata ? pdata->drdy_int_pin : 1; | |
1905 | } | |
1906 | ||
1907 | switch (drdy_pin) { | |
1908 | case 1: | |
7e906103 LB |
1909 | hw->irq_routing = &hw->settings->irq_config.irq1_func; |
1910 | *drdy_reg = &hw->settings->irq_config.irq1; | |
dba32904 LB |
1911 | break; |
1912 | case 2: | |
7e906103 LB |
1913 | hw->irq_routing = &hw->settings->irq_config.irq2_func; |
1914 | *drdy_reg = &hw->settings->irq_config.irq2; | |
dba32904 LB |
1915 | break; |
1916 | default: | |
1917 | dev_err(hw->dev, "unsupported data ready pin\n"); | |
1918 | err = -EINVAL; | |
1919 | break; | |
1920 | } | |
1921 | ||
1922 | return err; | |
1923 | } | |
1924 | ||
c91c1c84 LB |
1925 | static int st_lsm6dsx_init_shub(struct st_lsm6dsx_hw *hw) |
1926 | { | |
1927 | const struct st_lsm6dsx_shub_settings *hub_settings; | |
c91c1c84 | 1928 | struct st_sensors_platform_data *pdata; |
03d4c566 | 1929 | struct device *dev = hw->dev; |
c91c1c84 LB |
1930 | unsigned int data; |
1931 | int err = 0; | |
1932 | ||
1933 | hub_settings = &hw->settings->shub_settings; | |
1934 | ||
03d4c566 AS |
1935 | pdata = (struct st_sensors_platform_data *)dev->platform_data; |
1936 | if ((dev_fwnode(dev) && device_property_read_bool(dev, "st,pullups")) || | |
c91c1c84 | 1937 | (pdata && pdata->pullups)) { |
3a431957 LB |
1938 | if (hub_settings->pullup_en.sec_page) { |
1939 | err = st_lsm6dsx_set_page(hw, true); | |
1940 | if (err < 0) | |
1941 | return err; | |
1942 | } | |
c91c1c84 LB |
1943 | |
1944 | data = ST_LSM6DSX_SHIFT_VAL(1, hub_settings->pullup_en.mask); | |
1945 | err = regmap_update_bits(hw->regmap, | |
1946 | hub_settings->pullup_en.addr, | |
1947 | hub_settings->pullup_en.mask, data); | |
1948 | ||
3a431957 LB |
1949 | if (hub_settings->pullup_en.sec_page) |
1950 | st_lsm6dsx_set_page(hw, false); | |
c91c1c84 LB |
1951 | |
1952 | if (err < 0) | |
1953 | return err; | |
1954 | } | |
1955 | ||
1956 | if (hub_settings->aux_sens.addr) { | |
1957 | /* configure aux sensors */ | |
1958 | err = st_lsm6dsx_set_page(hw, true); | |
1959 | if (err < 0) | |
1960 | return err; | |
1961 | ||
1962 | data = ST_LSM6DSX_SHIFT_VAL(3, hub_settings->aux_sens.mask); | |
1963 | err = regmap_update_bits(hw->regmap, | |
1964 | hub_settings->aux_sens.addr, | |
1965 | hub_settings->aux_sens.mask, data); | |
1966 | ||
1967 | st_lsm6dsx_set_page(hw, false); | |
e485e2a2 LB |
1968 | |
1969 | if (err < 0) | |
1970 | return err; | |
1971 | } | |
1972 | ||
1973 | if (hub_settings->emb_func.addr) { | |
1974 | data = ST_LSM6DSX_SHIFT_VAL(1, hub_settings->emb_func.mask); | |
1975 | err = regmap_update_bits(hw->regmap, | |
1976 | hub_settings->emb_func.addr, | |
1977 | hub_settings->emb_func.mask, data); | |
c91c1c84 LB |
1978 | } |
1979 | ||
1980 | return err; | |
1981 | } | |
1982 | ||
21345107 LB |
1983 | static int st_lsm6dsx_init_hw_timer(struct st_lsm6dsx_hw *hw) |
1984 | { | |
1985 | const struct st_lsm6dsx_hw_ts_settings *ts_settings; | |
1986 | int err, val; | |
1987 | ||
1988 | ts_settings = &hw->settings->ts_settings; | |
1989 | /* enable hw timestamp generation if necessary */ | |
1990 | if (ts_settings->timer_en.addr) { | |
1991 | val = ST_LSM6DSX_SHIFT_VAL(1, ts_settings->timer_en.mask); | |
1992 | err = regmap_update_bits(hw->regmap, | |
1993 | ts_settings->timer_en.addr, | |
1994 | ts_settings->timer_en.mask, val); | |
1995 | if (err < 0) | |
1996 | return err; | |
1997 | } | |
1998 | ||
1999 | /* enable high resolution for hw ts timer if necessary */ | |
2000 | if (ts_settings->hr_timer.addr) { | |
2001 | val = ST_LSM6DSX_SHIFT_VAL(1, ts_settings->hr_timer.mask); | |
2002 | err = regmap_update_bits(hw->regmap, | |
2003 | ts_settings->hr_timer.addr, | |
2004 | ts_settings->hr_timer.mask, val); | |
2005 | if (err < 0) | |
2006 | return err; | |
2007 | } | |
2008 | ||
2009 | /* enable ts queueing in FIFO if necessary */ | |
2010 | if (ts_settings->fifo_en.addr) { | |
2011 | val = ST_LSM6DSX_SHIFT_VAL(1, ts_settings->fifo_en.mask); | |
2012 | err = regmap_update_bits(hw->regmap, | |
2013 | ts_settings->fifo_en.addr, | |
2014 | ts_settings->fifo_en.mask, val); | |
2015 | if (err < 0) | |
2016 | return err; | |
2017 | } | |
cb3b6b8e MT |
2018 | |
2019 | /* calibrate timestamp sensitivity */ | |
2020 | hw->ts_gain = ST_LSM6DSX_TS_SENSITIVITY; | |
2021 | if (ts_settings->freq_fine) { | |
2022 | err = regmap_read(hw->regmap, ts_settings->freq_fine, &val); | |
2023 | if (err < 0) | |
2024 | return err; | |
2025 | ||
2026 | /* | |
2027 | * linearize the AN5192 formula: | |
2028 | * 1 / (1 + x) ~= 1 - x (Taylor’s Series) | |
2029 | * ttrim[s] = 1 / (40000 * (1 + 0.0015 * val)) | |
2030 | * ttrim[ns] ~= 25000 - 37.5 * val | |
2031 | * ttrim[ns] ~= 25000 - (37500 * val) / 1000 | |
2032 | */ | |
2033 | hw->ts_gain -= ((s8)val * 37500) / 1000; | |
2034 | } | |
2035 | ||
21345107 LB |
2036 | return 0; |
2037 | } | |
2038 | ||
3a63da26 | 2039 | static int st_lsm6dsx_reset_device(struct st_lsm6dsx_hw *hw) |
290a6ce1 | 2040 | { |
7e906103 | 2041 | const struct st_lsm6dsx_reg *reg; |
290a6ce1 | 2042 | int err; |
290a6ce1 | 2043 | |
3a63da26 LB |
2044 | /* |
2045 | * flush hw FIFO before device reset in order to avoid | |
2046 | * possible races on interrupt line 1. If the first interrupt | |
2047 | * line is asserted during hw reset the device will work in | |
2048 | * I3C-only mode (if it is supported) | |
2049 | */ | |
2050 | err = st_lsm6dsx_flush_fifo(hw); | |
2051 | if (err < 0 && err != -ENOTSUPP) | |
2052 | return err; | |
2053 | ||
19435425 | 2054 | /* device sw reset */ |
66b662a1 LB |
2055 | reg = &hw->settings->reset; |
2056 | err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, | |
2057 | ST_LSM6DSX_SHIFT_VAL(1, reg->mask)); | |
290a6ce1 LB |
2058 | if (err < 0) |
2059 | return err; | |
2060 | ||
19435425 LB |
2061 | msleep(50); |
2062 | ||
2063 | /* reload trimming parameter */ | |
66b662a1 LB |
2064 | reg = &hw->settings->boot; |
2065 | err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, | |
2066 | ST_LSM6DSX_SHIFT_VAL(1, reg->mask)); | |
19435425 LB |
2067 | if (err < 0) |
2068 | return err; | |
2069 | ||
2070 | msleep(50); | |
290a6ce1 | 2071 | |
3a63da26 LB |
2072 | return 0; |
2073 | } | |
2074 | ||
2075 | static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw) | |
2076 | { | |
2077 | const struct st_lsm6dsx_reg *reg; | |
2078 | int err; | |
2079 | ||
2080 | err = st_lsm6dsx_reset_device(hw); | |
2081 | if (err < 0) | |
2082 | return err; | |
2083 | ||
290a6ce1 | 2084 | /* enable Block Data Update */ |
66b662a1 LB |
2085 | reg = &hw->settings->bdu; |
2086 | err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, | |
2087 | ST_LSM6DSX_SHIFT_VAL(1, reg->mask)); | |
290a6ce1 LB |
2088 | if (err < 0) |
2089 | return err; | |
2090 | ||
290a6ce1 | 2091 | /* enable FIFO watermak interrupt */ |
7e906103 | 2092 | err = st_lsm6dsx_get_drdy_reg(hw, ®); |
290a6ce1 LB |
2093 | if (err < 0) |
2094 | return err; | |
2095 | ||
7e906103 LB |
2096 | err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, |
2097 | ST_LSM6DSX_SHIFT_VAL(1, reg->mask)); | |
21345107 LB |
2098 | if (err < 0) |
2099 | return err; | |
2100 | ||
9db02d32 | 2101 | /* enable Latched interrupts for device events */ |
7e906103 LB |
2102 | if (hw->settings->irq_config.lir.addr) { |
2103 | reg = &hw->settings->irq_config.lir; | |
2104 | err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, | |
2105 | ST_LSM6DSX_SHIFT_VAL(1, reg->mask)); | |
9db02d32 LB |
2106 | if (err < 0) |
2107 | return err; | |
22ea5651 LB |
2108 | |
2109 | /* enable clear on read for latched interrupts */ | |
7e906103 LB |
2110 | if (hw->settings->irq_config.clear_on_read.addr) { |
2111 | reg = &hw->settings->irq_config.clear_on_read; | |
22ea5651 | 2112 | err = regmap_update_bits(hw->regmap, |
7e906103 LB |
2113 | reg->addr, reg->mask, |
2114 | ST_LSM6DSX_SHIFT_VAL(1, reg->mask)); | |
22ea5651 LB |
2115 | if (err < 0) |
2116 | return err; | |
2117 | } | |
9db02d32 LB |
2118 | } |
2119 | ||
960506ed LB |
2120 | /* enable drdy-mas if available */ |
2121 | if (hw->settings->drdy_mask.addr) { | |
2122 | reg = &hw->settings->drdy_mask; | |
2123 | err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, | |
2124 | ST_LSM6DSX_SHIFT_VAL(1, reg->mask)); | |
2125 | if (err < 0) | |
2126 | return err; | |
2127 | } | |
2128 | ||
c91c1c84 LB |
2129 | err = st_lsm6dsx_init_shub(hw); |
2130 | if (err < 0) | |
2131 | return err; | |
2132 | ||
21345107 | 2133 | return st_lsm6dsx_init_hw_timer(hw); |
290a6ce1 LB |
2134 | } |
2135 | ||
2136 | static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw, | |
510c0106 LB |
2137 | enum st_lsm6dsx_sensor_id id, |
2138 | const char *name) | |
290a6ce1 LB |
2139 | { |
2140 | struct st_lsm6dsx_sensor *sensor; | |
2141 | struct iio_dev *iio_dev; | |
2142 | ||
2143 | iio_dev = devm_iio_device_alloc(hw->dev, sizeof(*sensor)); | |
2144 | if (!iio_dev) | |
2145 | return NULL; | |
2146 | ||
2147 | iio_dev->modes = INDIO_DIRECT_MODE; | |
2148 | iio_dev->dev.parent = hw->dev; | |
2149 | iio_dev->available_scan_masks = st_lsm6dsx_available_scan_masks; | |
f48bc49b LB |
2150 | iio_dev->channels = hw->settings->channels[id].chan; |
2151 | iio_dev->num_channels = hw->settings->channels[id].len; | |
290a6ce1 LB |
2152 | |
2153 | sensor = iio_priv(iio_dev); | |
2154 | sensor->id = id; | |
2155 | sensor->hw = hw; | |
f8710f03 | 2156 | sensor->odr = hw->settings->odr_table[id].odr_avl[0].milli_hz; |
640aca3f | 2157 | sensor->gain = hw->settings->fs_table[id].fs_avl[0].gain; |
290a6ce1 LB |
2158 | sensor->watermark = 1; |
2159 | ||
2160 | switch (id) { | |
2161 | case ST_LSM6DSX_ID_ACC: | |
290a6ce1 | 2162 | iio_dev->info = &st_lsm6dsx_acc_info; |
510c0106 LB |
2163 | scnprintf(sensor->name, sizeof(sensor->name), "%s_accel", |
2164 | name); | |
290a6ce1 LB |
2165 | break; |
2166 | case ST_LSM6DSX_ID_GYRO: | |
290a6ce1 | 2167 | iio_dev->info = &st_lsm6dsx_gyro_info; |
510c0106 LB |
2168 | scnprintf(sensor->name, sizeof(sensor->name), "%s_gyro", |
2169 | name); | |
290a6ce1 LB |
2170 | break; |
2171 | default: | |
2172 | return NULL; | |
2173 | } | |
510c0106 | 2174 | iio_dev->name = sensor->name; |
290a6ce1 LB |
2175 | |
2176 | return iio_dev; | |
2177 | } | |
2178 | ||
615bd378 LB |
2179 | static bool |
2180 | st_lsm6dsx_report_motion_event(struct st_lsm6dsx_hw *hw) | |
1aabad1f | 2181 | { |
615bd378 LB |
2182 | const struct st_lsm6dsx_event_settings *event_settings; |
2183 | int err, data; | |
2184 | s64 timestamp; | |
1aabad1f | 2185 | |
615bd378 LB |
2186 | if (!hw->enable_event) |
2187 | return false; | |
2188 | ||
2189 | event_settings = &hw->settings->event_settings; | |
2190 | err = st_lsm6dsx_read_locked(hw, event_settings->wakeup_src_reg, | |
2191 | &data, sizeof(data)); | |
2192 | if (err < 0) | |
2193 | return false; | |
2194 | ||
2195 | timestamp = iio_get_time_ns(hw->iio_devs[ST_LSM6DSX_ID_ACC]); | |
1aabad1f SN |
2196 | if ((data & hw->settings->event_settings.wakeup_src_z_mask) && |
2197 | (hw->enable_event & BIT(IIO_MOD_Z))) | |
2198 | iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC], | |
2199 | IIO_MOD_EVENT_CODE(IIO_ACCEL, | |
2200 | 0, | |
2201 | IIO_MOD_Z, | |
2202 | IIO_EV_TYPE_THRESH, | |
2203 | IIO_EV_DIR_EITHER), | |
2204 | timestamp); | |
2205 | ||
2206 | if ((data & hw->settings->event_settings.wakeup_src_y_mask) && | |
2207 | (hw->enable_event & BIT(IIO_MOD_Y))) | |
2208 | iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC], | |
2209 | IIO_MOD_EVENT_CODE(IIO_ACCEL, | |
2210 | 0, | |
2211 | IIO_MOD_Y, | |
2212 | IIO_EV_TYPE_THRESH, | |
2213 | IIO_EV_DIR_EITHER), | |
2214 | timestamp); | |
2215 | ||
2216 | if ((data & hw->settings->event_settings.wakeup_src_x_mask) && | |
2217 | (hw->enable_event & BIT(IIO_MOD_X))) | |
2218 | iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC], | |
2219 | IIO_MOD_EVENT_CODE(IIO_ACCEL, | |
2220 | 0, | |
2221 | IIO_MOD_X, | |
2222 | IIO_EV_TYPE_THRESH, | |
2223 | IIO_EV_DIR_EITHER), | |
2224 | timestamp); | |
615bd378 LB |
2225 | |
2226 | return data & event_settings->wakeup_src_status_mask; | |
1aabad1f SN |
2227 | } |
2228 | ||
6ee6a368 SN |
2229 | static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private) |
2230 | { | |
2231 | struct st_lsm6dsx_hw *hw = private; | |
615bd378 | 2232 | bool event; |
6ee6a368 | 2233 | int count; |
1aabad1f | 2234 | |
615bd378 | 2235 | event = st_lsm6dsx_report_motion_event(hw); |
6ee6a368 | 2236 | |
a912ee4c LB |
2237 | if (!hw->settings->fifo_ops.read_fifo) |
2238 | return event ? IRQ_HANDLED : IRQ_NONE; | |
2239 | ||
6ee6a368 SN |
2240 | mutex_lock(&hw->fifo_lock); |
2241 | count = hw->settings->fifo_ops.read_fifo(hw); | |
2242 | mutex_unlock(&hw->fifo_lock); | |
2243 | ||
615bd378 | 2244 | return count || event ? IRQ_HANDLED : IRQ_NONE; |
6ee6a368 SN |
2245 | } |
2246 | ||
2247 | static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw) | |
2248 | { | |
31fe8d4e LB |
2249 | struct st_sensors_platform_data *pdata; |
2250 | const struct st_lsm6dsx_reg *reg; | |
03d4c566 | 2251 | struct device *dev = hw->dev; |
6ee6a368 SN |
2252 | unsigned long irq_type; |
2253 | bool irq_active_low; | |
2254 | int err; | |
2255 | ||
2256 | irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq)); | |
2257 | ||
2258 | switch (irq_type) { | |
2259 | case IRQF_TRIGGER_HIGH: | |
2260 | case IRQF_TRIGGER_RISING: | |
2261 | irq_active_low = false; | |
2262 | break; | |
2263 | case IRQF_TRIGGER_LOW: | |
2264 | case IRQF_TRIGGER_FALLING: | |
2265 | irq_active_low = true; | |
2266 | break; | |
2267 | default: | |
2268 | dev_info(hw->dev, "mode %lx unsupported\n", irq_type); | |
2269 | return -EINVAL; | |
2270 | } | |
2271 | ||
31fe8d4e LB |
2272 | reg = &hw->settings->irq_config.hla; |
2273 | err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, | |
2274 | ST_LSM6DSX_SHIFT_VAL(irq_active_low, | |
2275 | reg->mask)); | |
6ee6a368 SN |
2276 | if (err < 0) |
2277 | return err; | |
2278 | ||
03d4c566 AS |
2279 | pdata = (struct st_sensors_platform_data *)dev->platform_data; |
2280 | if ((dev_fwnode(dev) && device_property_read_bool(dev, "drive-open-drain")) || | |
6ee6a368 | 2281 | (pdata && pdata->open_drain)) { |
31fe8d4e LB |
2282 | reg = &hw->settings->irq_config.od; |
2283 | err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, | |
2284 | ST_LSM6DSX_SHIFT_VAL(1, reg->mask)); | |
6ee6a368 SN |
2285 | if (err < 0) |
2286 | return err; | |
2287 | ||
2288 | irq_type |= IRQF_SHARED; | |
2289 | } | |
2290 | ||
2291 | err = devm_request_threaded_irq(hw->dev, hw->irq, | |
a3aa17d4 | 2292 | NULL, |
6ee6a368 SN |
2293 | st_lsm6dsx_handler_thread, |
2294 | irq_type | IRQF_ONESHOT, | |
2295 | "lsm6dsx", hw); | |
2296 | if (err) { | |
2297 | dev_err(hw->dev, "failed to request trigger irq %d\n", | |
2298 | hw->irq); | |
2299 | return err; | |
2300 | } | |
2301 | ||
2302 | return 0; | |
2303 | } | |
2304 | ||
81956a93 | 2305 | int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, |
51a8b707 | 2306 | struct regmap *regmap) |
290a6ce1 | 2307 | { |
b7a73b33 | 2308 | struct st_sensors_platform_data *pdata = dev->platform_data; |
c91c1c84 | 2309 | const struct st_lsm6dsx_shub_settings *hub_settings; |
290a6ce1 | 2310 | struct st_lsm6dsx_hw *hw; |
81956a93 | 2311 | const char *name = NULL; |
290a6ce1 LB |
2312 | int i, err; |
2313 | ||
2314 | hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL); | |
2315 | if (!hw) | |
2316 | return -ENOMEM; | |
2317 | ||
2318 | dev_set_drvdata(dev, (void *)hw); | |
2319 | ||
290a6ce1 | 2320 | mutex_init(&hw->fifo_lock); |
335eaedc | 2321 | mutex_init(&hw->conf_lock); |
739aff87 | 2322 | mutex_init(&hw->page_lock); |
290a6ce1 | 2323 | |
91a6b841 LB |
2324 | hw->buff = devm_kzalloc(dev, ST_LSM6DSX_BUFF_SIZE, GFP_KERNEL); |
2325 | if (!hw->buff) | |
2326 | return -ENOMEM; | |
2327 | ||
290a6ce1 LB |
2328 | hw->dev = dev; |
2329 | hw->irq = irq; | |
51a8b707 | 2330 | hw->regmap = regmap; |
290a6ce1 | 2331 | |
81956a93 | 2332 | err = st_lsm6dsx_check_whoami(hw, hw_id, &name); |
290a6ce1 LB |
2333 | if (err < 0) |
2334 | return err; | |
2335 | ||
6ffb55e5 | 2336 | for (i = 0; i < ST_LSM6DSX_ID_EXT0; i++) { |
510c0106 | 2337 | hw->iio_devs[i] = st_lsm6dsx_alloc_iiodev(hw, i, name); |
290a6ce1 LB |
2338 | if (!hw->iio_devs[i]) |
2339 | return -ENOMEM; | |
2340 | } | |
2341 | ||
2342 | err = st_lsm6dsx_init_device(hw); | |
2343 | if (err < 0) | |
2344 | return err; | |
2345 | ||
c91c1c84 LB |
2346 | hub_settings = &hw->settings->shub_settings; |
2347 | if (hub_settings->master_en.addr) { | |
2348 | err = st_lsm6dsx_shub_probe(hw, name); | |
2349 | if (err < 0) | |
2350 | return err; | |
2351 | } | |
2352 | ||
290a6ce1 | 2353 | if (hw->irq > 0) { |
6ee6a368 SN |
2354 | err = st_lsm6dsx_irq_setup(hw); |
2355 | if (err < 0) | |
2356 | return err; | |
2357 | ||
290a6ce1 LB |
2358 | err = st_lsm6dsx_fifo_setup(hw); |
2359 | if (err < 0) | |
2360 | return err; | |
2361 | } | |
2362 | ||
04e6fedb MK |
2363 | err = iio_read_mount_matrix(hw->dev, "mount-matrix", &hw->orientation); |
2364 | if (err) | |
2365 | return err; | |
2366 | ||
290a6ce1 | 2367 | for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { |
6ffb55e5 LB |
2368 | if (!hw->iio_devs[i]) |
2369 | continue; | |
2370 | ||
290a6ce1 LB |
2371 | err = devm_iio_device_register(hw->dev, hw->iio_devs[i]); |
2372 | if (err) | |
2373 | return err; | |
2374 | } | |
2375 | ||
03d4c566 | 2376 | if ((dev_fwnode(dev) && device_property_read_bool(dev, "wakeup-source")) || |
b7a73b33 | 2377 | (pdata && pdata->wakeup_source)) |
4c997dfa SN |
2378 | device_init_wakeup(dev, true); |
2379 | ||
290a6ce1 LB |
2380 | return 0; |
2381 | } | |
2382 | EXPORT_SYMBOL(st_lsm6dsx_probe); | |
2383 | ||
3cec4850 | 2384 | static int __maybe_unused st_lsm6dsx_suspend(struct device *dev) |
d3f77058 LB |
2385 | { |
2386 | struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev); | |
2387 | struct st_lsm6dsx_sensor *sensor; | |
2388 | int i, err = 0; | |
2389 | ||
2390 | for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { | |
6ffb55e5 LB |
2391 | if (!hw->iio_devs[i]) |
2392 | continue; | |
2393 | ||
d3f77058 LB |
2394 | sensor = iio_priv(hw->iio_devs[i]); |
2395 | if (!(hw->enable_mask & BIT(sensor->id))) | |
2396 | continue; | |
2397 | ||
4c997dfa SN |
2398 | if (device_may_wakeup(dev) && |
2399 | sensor->id == ST_LSM6DSX_ID_ACC && hw->enable_event) { | |
2400 | /* Enable wake from IRQ */ | |
2401 | enable_irq_wake(hw->irq); | |
2402 | continue; | |
2403 | } | |
2404 | ||
bce0d57d LB |
2405 | if (sensor->id == ST_LSM6DSX_ID_EXT0 || |
2406 | sensor->id == ST_LSM6DSX_ID_EXT1 || | |
2407 | sensor->id == ST_LSM6DSX_ID_EXT2) | |
2408 | err = st_lsm6dsx_shub_set_enable(sensor, false); | |
2409 | else | |
2410 | err = st_lsm6dsx_sensor_set_enable(sensor, false); | |
d3f77058 LB |
2411 | if (err < 0) |
2412 | return err; | |
bce0d57d LB |
2413 | |
2414 | hw->suspend_mask |= BIT(sensor->id); | |
d3f77058 LB |
2415 | } |
2416 | ||
c2686eb2 | 2417 | if (hw->fifo_mask) |
d3f77058 LB |
2418 | err = st_lsm6dsx_flush_fifo(hw); |
2419 | ||
2420 | return err; | |
2421 | } | |
2422 | ||
3cec4850 | 2423 | static int __maybe_unused st_lsm6dsx_resume(struct device *dev) |
d3f77058 LB |
2424 | { |
2425 | struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev); | |
2426 | struct st_lsm6dsx_sensor *sensor; | |
2427 | int i, err = 0; | |
2428 | ||
2429 | for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { | |
6ffb55e5 LB |
2430 | if (!hw->iio_devs[i]) |
2431 | continue; | |
2432 | ||
d3f77058 | 2433 | sensor = iio_priv(hw->iio_devs[i]); |
4c997dfa SN |
2434 | if (device_may_wakeup(dev) && |
2435 | sensor->id == ST_LSM6DSX_ID_ACC && hw->enable_event) | |
2436 | disable_irq_wake(hw->irq); | |
2437 | ||
bce0d57d | 2438 | if (!(hw->suspend_mask & BIT(sensor->id))) |
d3f77058 LB |
2439 | continue; |
2440 | ||
bce0d57d LB |
2441 | if (sensor->id == ST_LSM6DSX_ID_EXT0 || |
2442 | sensor->id == ST_LSM6DSX_ID_EXT1 || | |
2443 | sensor->id == ST_LSM6DSX_ID_EXT2) | |
2444 | err = st_lsm6dsx_shub_set_enable(sensor, true); | |
2445 | else | |
2446 | err = st_lsm6dsx_sensor_set_enable(sensor, true); | |
d3f77058 LB |
2447 | if (err < 0) |
2448 | return err; | |
bce0d57d LB |
2449 | |
2450 | hw->suspend_mask &= ~BIT(sensor->id); | |
d3f77058 LB |
2451 | } |
2452 | ||
c2686eb2 | 2453 | if (hw->fifo_mask) |
d3f77058 LB |
2454 | err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT); |
2455 | ||
2456 | return err; | |
2457 | } | |
d3f77058 LB |
2458 | |
2459 | const struct dev_pm_ops st_lsm6dsx_pm_ops = { | |
2460 | SET_SYSTEM_SLEEP_PM_OPS(st_lsm6dsx_suspend, st_lsm6dsx_resume) | |
2461 | }; | |
2462 | EXPORT_SYMBOL(st_lsm6dsx_pm_ops); | |
2463 | ||
290a6ce1 LB |
2464 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>"); |
2465 | MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>"); | |
2466 | MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx driver"); | |
2467 | MODULE_LICENSE("GPL v2"); |