1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * STMicroelectronics st_lsm6dsx sensor driver |
4 | * |
5 | * Copyright 2016 STMicroelectronics Inc. |
6 | * |
7 | * Lorenzo Bianconi <lorenzo.bianconi@st.com> |
8 | * Denis Ciocca <denis.ciocca@st.com> |
9 | */ |
10 | |
11 | #ifndef ST_LSM6DSX_H |
12 | #define ST_LSM6DSX_H |
13 | |
14 | #include <linux/device.h> |
15 | #include <linux/iio/iio.h> |
16 | #include <linux/regulator/consumer.h> |
17 | |
18 | #define ST_LSM6DS3_DEV_NAME "lsm6ds3" |
19 | #define ST_LSM6DS3H_DEV_NAME "lsm6ds3h" |
20 | #define ST_LSM6DSL_DEV_NAME "lsm6dsl" |
21 | #define ST_LSM6DSM_DEV_NAME "lsm6dsm" |
22 | #define ST_ISM330DLC_DEV_NAME "ism330dlc" |
23 | #define ST_LSM6DSO_DEV_NAME "lsm6dso" |
24 | #define ST_ASM330LHH_DEV_NAME "asm330lhh" |
25 | #define ST_LSM6DSOX_DEV_NAME "lsm6dsox" |
26 | #define ST_LSM6DSR_DEV_NAME "lsm6dsr" |
27 | #define ST_LSM6DS3TRC_DEV_NAME "lsm6ds3tr-c" |
28 | #define ST_ISM330DHCX_DEV_NAME "ism330dhcx" |
29 | #define ST_LSM9DS1_DEV_NAME "lsm9ds1-imu" |
30 | #define ST_LSM6DS0_DEV_NAME "lsm6ds0" |
31 | #define ST_LSM6DSRX_DEV_NAME "lsm6dsrx" |
32 | #define ST_LSM6DST_DEV_NAME "lsm6dst" |
33 | #define ST_LSM6DSOP_DEV_NAME "lsm6dsop" |
34 | #define ST_ASM330LHHX_DEV_NAME "asm330lhhx" |
35 | #define ST_LSM6DSTX_DEV_NAME "lsm6dstx" |
36 | #define ST_LSM6DSV_DEV_NAME "lsm6dsv" |
37 | #define ST_LSM6DSV16X_DEV_NAME "lsm6dsv16x" |
38 | #define ST_LSM6DSO16IS_DEV_NAME "lsm6dso16is" |
39 | #define ST_ISM330IS_DEV_NAME "ism330is" |
40 | #define ST_ASM330LHB_DEV_NAME "asm330lhb" |
41 | #define ST_ASM330LHHXG1_DEV_NAME "asm330lhhxg1" |
42 | |
43 | enum st_lsm6dsx_hw_id { |
44 | ST_LSM6DS3_ID = 1, |
45 | ST_LSM6DS3H_ID, |
46 | ST_LSM6DSL_ID, |
47 | ST_LSM6DSM_ID, |
48 | ST_ISM330DLC_ID, |
49 | ST_LSM6DSO_ID, |
50 | ST_ASM330LHH_ID, |
51 | ST_LSM6DSOX_ID, |
52 | ST_LSM6DSR_ID, |
53 | ST_LSM6DS3TRC_ID, |
54 | ST_ISM330DHCX_ID, |
55 | ST_LSM9DS1_ID, |
56 | ST_LSM6DS0_ID, |
57 | ST_LSM6DSRX_ID, |
58 | ST_LSM6DST_ID, |
59 | ST_LSM6DSOP_ID, |
60 | ST_ASM330LHHX_ID, |
61 | ST_LSM6DSTX_ID, |
62 | ST_LSM6DSV_ID, |
63 | ST_LSM6DSV16X_ID, |
64 | ST_LSM6DSO16IS_ID, |
65 | ST_ISM330IS_ID, |
66 | ST_ASM330LHB_ID, |
67 | ST_ASM330LHHXG1_ID, |
68 | ST_LSM6DSX_MAX_ID, |
69 | }; |
70 | |
71 | #define ST_LSM6DSX_BUFF_SIZE 512 |
72 | #define ST_LSM6DSX_CHAN_SIZE 2 |
73 | #define ST_LSM6DSX_SAMPLE_SIZE 6 |
74 | #define ST_LSM6DSX_TAG_SIZE 1 |
75 | #define ST_LSM6DSX_TAGGED_SAMPLE_SIZE (ST_LSM6DSX_SAMPLE_SIZE + \ |
76 | ST_LSM6DSX_TAG_SIZE) |
77 | #define ST_LSM6DSX_MAX_WORD_LEN ((32 / ST_LSM6DSX_SAMPLE_SIZE) * \ |
78 | ST_LSM6DSX_SAMPLE_SIZE) |
79 | #define ST_LSM6DSX_MAX_TAGGED_WORD_LEN ((32 / ST_LSM6DSX_TAGGED_SAMPLE_SIZE) \ |
80 | * ST_LSM6DSX_TAGGED_SAMPLE_SIZE) |
81 | #define ST_LSM6DSX_SHIFT_VAL(val, mask) (((val) << __ffs(mask)) & (mask)) |
82 | |
83 | #define ST_LSM6DSX_CHANNEL_ACC(chan_type, addr, mod, scan_idx) \ |
84 | { \ |
85 | .type = chan_type, \ |
86 | .address = addr, \ |
87 | .modified = 1, \ |
88 | .channel2 = mod, \ |
89 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
90 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ |
91 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ |
92 | .scan_index = scan_idx, \ |
93 | .scan_type = { \ |
94 | .sign = 's', \ |
95 | .realbits = 16, \ |
96 | .storagebits = 16, \ |
97 | .endianness = IIO_LE, \ |
98 | }, \ |
99 | .event_spec = &st_lsm6dsx_event, \ |
100 | .ext_info = st_lsm6dsx_ext_info, \ |
101 | .num_event_specs = 1, \ |
102 | } |
103 | |
104 | #define ST_LSM6DSX_CHANNEL(chan_type, addr, mod, scan_idx) \ |
105 | { \ |
106 | .type = chan_type, \ |
107 | .address = addr, \ |
108 | .modified = 1, \ |
109 | .channel2 = mod, \ |
110 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
111 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ |
112 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ |
113 | .scan_index = scan_idx, \ |
114 | .scan_type = { \ |
115 | .sign = 's', \ |
116 | .realbits = 16, \ |
117 | .storagebits = 16, \ |
118 | .endianness = IIO_LE, \ |
119 | }, \ |
120 | .ext_info = st_lsm6dsx_ext_info, \ |
121 | } |
122 | |
123 | struct st_lsm6dsx_reg { |
124 | u8 addr; |
125 | u8 mask; |
126 | }; |
127 | |
128 | struct st_lsm6dsx_sensor; |
129 | struct st_lsm6dsx_hw; |
130 | |
131 | struct st_lsm6dsx_odr { |
132 | u32 milli_hz; |
133 | u8 val; |
134 | }; |
135 | |
136 | #define ST_LSM6DSX_ODR_LIST_SIZE 8 |
137 | struct st_lsm6dsx_odr_table_entry { |
138 | struct st_lsm6dsx_reg reg; |
139 | |
140 | struct st_lsm6dsx_odr odr_avl[ST_LSM6DSX_ODR_LIST_SIZE]; |
141 | int odr_len; |
142 | }; |
143 | |
144 | struct st_lsm6dsx_samples_to_discard { |
145 | struct { |
146 | u32 milli_hz; |
147 | u16 samples; |
148 | } val[ST_LSM6DSX_ODR_LIST_SIZE]; |
149 | }; |
150 | |
151 | struct st_lsm6dsx_fs { |
152 | u32 gain; |
153 | u8 val; |
154 | }; |
155 | |
156 | #define ST_LSM6DSX_FS_LIST_SIZE 4 |
157 | struct st_lsm6dsx_fs_table_entry { |
158 | struct st_lsm6dsx_reg reg; |
159 | |
160 | struct st_lsm6dsx_fs fs_avl[ST_LSM6DSX_FS_LIST_SIZE]; |
161 | int fs_len; |
162 | }; |
163 | |
164 | /** |
165 | * struct st_lsm6dsx_fifo_ops - ST IMU FIFO settings |
166 | * @update_fifo: Update FIFO configuration callback. |
167 | * @read_fifo: Read FIFO callback. |
168 | * @fifo_th: FIFO threshold register info (addr + mask). |
169 | * @fifo_diff: FIFO diff status register info (addr + mask). |
170 | * @max_size: Sensor max fifo length in FIFO words. |
171 | * @th_wl: FIFO threshold word length. |
172 | */ |
173 | struct st_lsm6dsx_fifo_ops { |
174 | int (*update_fifo)(struct st_lsm6dsx_sensor *sensor, bool enable); |
175 | int (*read_fifo)(struct st_lsm6dsx_hw *hw); |
176 | struct { |
177 | u8 addr; |
178 | u16 mask; |
179 | } fifo_th; |
180 | struct { |
181 | u8 addr; |
182 | u16 mask; |
183 | } fifo_diff; |
184 | u16 max_size; |
185 | u8 th_wl; |
186 | }; |
187 | |
188 | /** |
189 | * struct st_lsm6dsx_hw_ts_settings - ST IMU hw timer settings |
190 | * @timer_en: Hw timer enable register info (addr + mask). |
191 | * @hr_timer: Hw timer resolution register info (addr + mask). |
192 | * @fifo_en: Hw timer FIFO enable register info (addr + mask). |
193 | * @decimator: Hw timer FIFO decimator register info (addr + mask). |
194 | * @freq_fine: Difference in % of ODR with respect to the typical. |
195 | */ |
196 | struct st_lsm6dsx_hw_ts_settings { |
197 | struct st_lsm6dsx_reg timer_en; |
198 | struct st_lsm6dsx_reg hr_timer; |
199 | struct st_lsm6dsx_reg fifo_en; |
200 | struct st_lsm6dsx_reg decimator; |
201 | u8 freq_fine; |
202 | }; |
203 | |
204 | /** |
205 | * struct st_lsm6dsx_shub_settings - ST IMU hw i2c controller settings |
206 | * @page_mux: register page mux info (addr + mask). |
207 | * @master_en: master config register info (addr + mask). |
208 | * @pullup_en: i2c controller pull-up register info (addr + mask). |
209 | * @aux_sens: aux sensor register info (addr + mask). |
210 | * @wr_once: write_once register info (addr + mask). |
211 | * @emb_func: embedded function register info (addr + mask). |
212 | * @num_ext_dev: max number of slave devices. |
213 | * @shub_out: sensor hub first output register info. |
214 | * @slv0_addr: slave0 address in secondary page. |
215 | * @dw_slv0_addr: slave0 write register address in secondary page. |
216 | * @batch_en: Enable/disable FIFO batching. |
217 | * @pause: controller pause value. |
218 | */ |
219 | struct st_lsm6dsx_shub_settings { |
220 | struct st_lsm6dsx_reg page_mux; |
221 | struct { |
222 | bool sec_page; |
223 | u8 addr; |
224 | u8 mask; |
225 | } master_en; |
226 | struct { |
227 | bool sec_page; |
228 | u8 addr; |
229 | u8 mask; |
230 | } pullup_en; |
231 | struct st_lsm6dsx_reg aux_sens; |
232 | struct st_lsm6dsx_reg wr_once; |
233 | struct st_lsm6dsx_reg emb_func; |
234 | u8 num_ext_dev; |
235 | struct { |
236 | bool sec_page; |
237 | u8 addr; |
238 | } shub_out; |
239 | u8 slv0_addr; |
240 | u8 dw_slv0_addr; |
241 | u8 batch_en; |
242 | u8 pause; |
243 | }; |
244 | |
245 | struct st_lsm6dsx_event_settings { |
246 | struct st_lsm6dsx_reg enable_reg; |
247 | struct st_lsm6dsx_reg wakeup_reg; |
248 | u8 wakeup_src_reg; |
249 | u8 wakeup_src_status_mask; |
250 | u8 wakeup_src_z_mask; |
251 | u8 wakeup_src_y_mask; |
252 | u8 wakeup_src_x_mask; |
253 | }; |
254 | |
255 | enum st_lsm6dsx_ext_sensor_id { |
256 | ST_LSM6DSX_ID_MAGN, |
257 | }; |
258 | |
259 | /** |
260 | * struct st_lsm6dsx_ext_dev_settings - i2c controller slave settings |
261 | * @i2c_addr: I2c slave address list. |
262 | * @wai: Wai address info. |
263 | * @id: external sensor id. |
264 | * @odr_table: Output data rate of the sensor [Hz]. |
265 | * @fs_table: Configured sensor sensitivity table depending on full scale. |
266 | * @temp_comp: Temperature compensation register info (addr + mask). |
267 | * @pwr_table: Power on register info (addr + mask). |
268 | * @off_canc: Offset cancellation register info (addr + mask). |
269 | * @bdu: Block data update register info (addr + mask). |
270 | * @out: Output register info. |
271 | */ |
272 | struct st_lsm6dsx_ext_dev_settings { |
273 | u8 i2c_addr[2]; |
274 | struct { |
275 | u8 addr; |
276 | u8 val; |
277 | } wai; |
278 | enum st_lsm6dsx_ext_sensor_id id; |
279 | struct st_lsm6dsx_odr_table_entry odr_table; |
280 | struct st_lsm6dsx_fs_table_entry fs_table; |
281 | struct st_lsm6dsx_reg temp_comp; |
282 | struct { |
283 | struct st_lsm6dsx_reg reg; |
284 | u8 off_val; |
285 | u8 on_val; |
286 | } pwr_table; |
287 | struct st_lsm6dsx_reg off_canc; |
288 | struct st_lsm6dsx_reg bdu; |
289 | struct { |
290 | u8 addr; |
291 | u8 len; |
292 | } out; |
293 | }; |
294 | |
295 | /** |
296 | * struct st_lsm6dsx_settings - ST IMU sensor settings |
297 | * @reset: register address for reset. |
298 | * @boot: register address for boot. |
299 | * @bdu: register address for Block Data Update. |
300 | * @id: List of hw id/device name supported by the driver configuration. |
301 | * @channels: IIO channels supported by the device. |
302 | * @irq_config: interrupts related registers. |
303 | * @drdy_mask: register info for data-ready mask (addr + mask). |
304 | * @odr_table: Hw sensors odr table (Hz + val). |
305 | * @samples_to_discard: Number of samples to discard for filters settling time. |
306 | * @fs_table: Hw sensors gain table (gain + val). |
307 | * @decimator: List of decimator register info (addr + mask). |
308 | * @batch: List of FIFO batching register info (addr + mask). |
309 | * @fifo_ops: Sensor hw FIFO parameters. |
310 | * @ts_settings: Hw timer related settings. |
311 | * @shub_settings: i2c controller related settings. |
312 | */ |
313 | struct st_lsm6dsx_settings { |
314 | struct st_lsm6dsx_reg reset; |
315 | struct st_lsm6dsx_reg boot; |
316 | struct st_lsm6dsx_reg bdu; |
317 | struct { |
318 | enum st_lsm6dsx_hw_id hw_id; |
319 | const char *name; |
320 | u8 wai; |
321 | } id[ST_LSM6DSX_MAX_ID]; |
322 | struct { |
323 | const struct iio_chan_spec *chan; |
324 | int len; |
325 | } channels[2]; |
326 | struct { |
327 | struct st_lsm6dsx_reg irq1; |
328 | struct st_lsm6dsx_reg irq2; |
329 | struct st_lsm6dsx_reg irq1_func; |
330 | struct st_lsm6dsx_reg irq2_func; |
331 | struct st_lsm6dsx_reg lir; |
332 | struct st_lsm6dsx_reg clear_on_read; |
333 | struct st_lsm6dsx_reg hla; |
334 | struct st_lsm6dsx_reg od; |
335 | } irq_config; |
336 | struct st_lsm6dsx_reg drdy_mask; |
337 | struct st_lsm6dsx_odr_table_entry odr_table[2]; |
338 | struct st_lsm6dsx_samples_to_discard samples_to_discard[2]; |
339 | struct st_lsm6dsx_fs_table_entry fs_table[2]; |
340 | struct st_lsm6dsx_reg decimator[ST_LSM6DSX_MAX_ID]; |
341 | struct st_lsm6dsx_reg batch[ST_LSM6DSX_MAX_ID]; |
342 | struct st_lsm6dsx_fifo_ops fifo_ops; |
343 | struct st_lsm6dsx_hw_ts_settings ts_settings; |
344 | struct st_lsm6dsx_shub_settings shub_settings; |
345 | struct st_lsm6dsx_event_settings event_settings; |
346 | }; |
347 | |
348 | enum st_lsm6dsx_sensor_id { |
349 | ST_LSM6DSX_ID_GYRO, |
350 | ST_LSM6DSX_ID_ACC, |
351 | ST_LSM6DSX_ID_EXT0, |
352 | ST_LSM6DSX_ID_EXT1, |
353 | ST_LSM6DSX_ID_EXT2, |
354 | ST_LSM6DSX_ID_MAX, |
355 | }; |
356 | |
357 | enum st_lsm6dsx_fifo_mode { |
358 | ST_LSM6DSX_FIFO_BYPASS = 0x0, |
359 | ST_LSM6DSX_FIFO_CONT = 0x6, |
360 | }; |
361 | |
362 | /** |
363 | * struct st_lsm6dsx_sensor - ST IMU sensor instance |
364 | * @name: Sensor name. |
365 | * @id: Sensor identifier. |
366 | * @hw: Pointer to instance of struct st_lsm6dsx_hw. |
367 | * @gain: Configured sensor sensitivity. |
368 | * @odr: Output data rate of the sensor [Hz]. |
369 | * @samples_to_discard: Number of samples to discard for filters settling time. |
370 | * @watermark: Sensor watermark level. |
371 | * @decimator: Sensor decimation factor. |
372 | * @sip: Number of samples in a given pattern. |
373 | * @ts_ref: Sensor timestamp reference for hw one. |
374 | * @ext_info: Sensor settings if it is connected to i2c controller |
375 | */ |
376 | struct st_lsm6dsx_sensor { |
377 | char name[32]; |
378 | enum st_lsm6dsx_sensor_id id; |
379 | struct st_lsm6dsx_hw *hw; |
380 | |
381 | u32 gain; |
382 | u32 odr; |
383 | |
384 | u16 samples_to_discard; |
385 | u16 watermark; |
386 | u8 decimator; |
387 | u8 sip; |
388 | s64 ts_ref; |
389 | |
390 | struct { |
391 | const struct st_lsm6dsx_ext_dev_settings *settings; |
392 | u32 slv_odr; |
393 | u8 addr; |
394 | } ext_info; |
395 | }; |
396 | |
397 | /** |
398 | * struct st_lsm6dsx_hw - ST IMU MEMS hw instance |
399 | * @dev: Pointer to instance of struct device (I2C or SPI). |
400 | * @regmap: Register map of the device. |
401 | * @irq: Device interrupt line (I2C or SPI). |
402 | * @fifo_lock: Mutex to prevent concurrent access to the hw FIFO. |
403 | * @conf_lock: Mutex to prevent concurrent FIFO configuration update. |
404 | * @page_lock: Mutex to prevent concurrent memory page configuration. |
405 | * @suspend_mask: Suspended sensor bitmask. |
406 | * @enable_mask: Enabled sensor bitmask. |
407 | * @fifo_mask: Enabled hw FIFO bitmask. |
408 | * @ts_gain: Hw timestamp rate after internal calibration. |
409 | * @ts_sip: Total number of timestamp samples in a given pattern. |
410 | * @sip: Total number of samples (acc/gyro/ts) in a given pattern. |
411 | * @buff: Device read buffer. |
412 | * @irq_routing: pointer to interrupt routing configuration. |
413 | * @event_threshold: wakeup event threshold. |
414 | * @enable_event: enabled event bitmask. |
415 | * @iio_devs: Pointers to acc/gyro iio_dev instances. |
416 | * @settings: Pointer to the specific sensor settings in use. |
417 | * @orientation: sensor chip orientation relative to main hardware. |
418 | * @scan: Temporary buffers used to align data before iio_push_to_buffers() |
419 | */ |
420 | struct st_lsm6dsx_hw { |
421 | struct device *dev; |
422 | struct regmap *regmap; |
423 | int irq; |
424 | |
425 | struct mutex fifo_lock; |
426 | struct mutex conf_lock; |
427 | struct mutex page_lock; |
428 | |
429 | u8 suspend_mask; |
430 | u8 enable_mask; |
431 | u8 fifo_mask; |
432 | s64 ts_gain; |
433 | u8 ts_sip; |
434 | u8 sip; |
435 | |
436 | const struct st_lsm6dsx_reg *irq_routing; |
437 | u8 event_threshold; |
438 | u8 enable_event; |
439 | |
440 | u8 *buff; |
441 | |
442 | struct iio_dev *iio_devs[ST_LSM6DSX_ID_MAX]; |
443 | |
444 | const struct st_lsm6dsx_settings *settings; |
445 | |
446 | struct iio_mount_matrix orientation; |
447 | /* Ensure natural alignment of buffer elements */ |
448 | struct { |
449 | __le16 channels[3]; |
450 | s64 ts __aligned(8); |
451 | } scan[ST_LSM6DSX_ID_MAX]; |
452 | }; |
453 | |
454 | static __maybe_unused const struct iio_event_spec st_lsm6dsx_event = { |
455 | .type = IIO_EV_TYPE_THRESH, |
456 | .dir = IIO_EV_DIR_EITHER, |
457 | .mask_separate = BIT(IIO_EV_INFO_VALUE) | |
458 | BIT(IIO_EV_INFO_ENABLE) |
459 | }; |
460 | |
461 | static __maybe_unused const unsigned long st_lsm6dsx_available_scan_masks[] = { |
462 | 0x7, 0x0, |
463 | }; |
464 | |
465 | extern const struct dev_pm_ops st_lsm6dsx_pm_ops; |
466 | |
467 | int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, |
468 | struct regmap *regmap); |
469 | int st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor, |
470 | bool enable); |
471 | int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw); |
472 | int st_lsm6dsx_set_watermark(struct iio_dev *iio_dev, unsigned int val); |
473 | int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, |
474 | u16 watermark); |
475 | int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable); |
476 | int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw); |
477 | int st_lsm6dsx_resume_fifo(struct st_lsm6dsx_hw *hw); |
478 | int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw); |
479 | int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw); |
480 | int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u32 odr, u8 *val); |
481 | int st_lsm6dsx_shub_probe(struct st_lsm6dsx_hw *hw, const char *name); |
482 | int st_lsm6dsx_shub_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable); |
483 | int st_lsm6dsx_shub_read_output(struct st_lsm6dsx_hw *hw, u8 *data, int len); |
484 | int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable); |
485 | |
486 | static inline int |
487 | st_lsm6dsx_update_bits_locked(struct st_lsm6dsx_hw *hw, unsigned int addr, |
488 | unsigned int mask, unsigned int val) |
489 | { |
490 | int err; |
491 | |
492 | mutex_lock(&hw->page_lock); |
493 | err = regmap_update_bits(map: hw->regmap, reg: addr, mask, val); |
494 | mutex_unlock(lock: &hw->page_lock); |
495 | |
496 | return err; |
497 | } |
498 | |
499 | static inline int |
500 | st_lsm6dsx_read_locked(struct st_lsm6dsx_hw *hw, unsigned int addr, |
501 | void *val, unsigned int len) |
502 | { |
503 | int err; |
504 | |
505 | mutex_lock(&hw->page_lock); |
506 | err = regmap_bulk_read(map: hw->regmap, reg: addr, val, val_count: len); |
507 | mutex_unlock(lock: &hw->page_lock); |
508 | |
509 | return err; |
510 | } |
511 | |
512 | static inline int |
513 | st_lsm6dsx_write_locked(struct st_lsm6dsx_hw *hw, unsigned int addr, |
514 | unsigned int val) |
515 | { |
516 | int err; |
517 | |
518 | mutex_lock(&hw->page_lock); |
519 | err = regmap_write(map: hw->regmap, reg: addr, val); |
520 | mutex_unlock(lock: &hw->page_lock); |
521 | |
522 | return err; |
523 | } |
524 | |
525 | static inline const struct iio_mount_matrix * |
526 | st_lsm6dsx_get_mount_matrix(const struct iio_dev *iio_dev, |
527 | const struct iio_chan_spec *chan) |
528 | { |
529 | struct st_lsm6dsx_sensor *sensor = iio_priv(indio_dev: iio_dev); |
530 | struct st_lsm6dsx_hw *hw = sensor->hw; |
531 | |
532 | return &hw->orientation; |
533 | } |
534 | |
535 | static inline int |
536 | st_lsm6dsx_device_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable) |
537 | { |
538 | if (sensor->id == ST_LSM6DSX_ID_EXT0 || |
539 | sensor->id == ST_LSM6DSX_ID_EXT1 || |
540 | sensor->id == ST_LSM6DSX_ID_EXT2) |
541 | return st_lsm6dsx_shub_set_enable(sensor, enable); |
542 | |
543 | return st_lsm6dsx_sensor_set_enable(sensor, enable); |
544 | } |
545 | |
546 | static const |
547 | struct iio_chan_spec_ext_info __maybe_unused st_lsm6dsx_ext_info[] = { |
548 | IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_lsm6dsx_get_mount_matrix), |
549 | { } |
550 | }; |
551 | |
552 | #endif /* ST_LSM6DSX_H */ |
553 | |