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