1 /* ST Microelectronics LSM6DSV16X 6-axis IMU sensor driver
2  *
3  * Copyright (c) 2023 STMicroelectronics
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  *
7  * Datasheet:
8  * https://www.st.com/resource/en/datasheet/lsm6dsv16x.pdf
9  */
10 
11 #define DT_DRV_COMPAT st_lsm6dsv16x
12 
13 #include <zephyr/drivers/sensor.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/device.h>
16 #include <zephyr/init.h>
17 #include <zephyr/pm/device.h>
18 #include <string.h>
19 #include <zephyr/sys/__assert.h>
20 #include <zephyr/logging/log.h>
21 
22 #include <zephyr/dt-bindings/sensor/lsm6dsv16x.h>
23 #include "lsm6dsv16x.h"
24 #include "lsm6dsv16x_decoder.h"
25 #include "lsm6dsv16x_rtio.h"
26 
27 LOG_MODULE_REGISTER(LSM6DSV16X, CONFIG_SENSOR_LOG_LEVEL);
28 
lsm6dsv16x_is_active(const struct device * dev)29 bool lsm6dsv16x_is_active(const struct device *dev)
30 {
31 #if defined(CONFIG_PM_DEVICE)
32 	enum pm_device_state state;
33 	(void)pm_device_state_get(dev, &state);
34 	return (state == PM_DEVICE_STATE_ACTIVE);
35 #else
36 	return true;
37 #endif /* CONFIG_PM_DEVICE*/
38 }
39 
40 /*
41  * values taken from lsm6dsv16x_data_rate_t in hal/st module. The mode/accuracy
42  * should be selected through accel-odr property in DT
43  */
44 static const float lsm6dsv16x_odr_map[3][13] = {
45 			/* High Accuracy off */
46 			{0.0f, 1.875f, 7.5f, 15.0f, 30.0f, 60.0f,
47 			 120.0f, 240.0f, 480.0f, 960.0f, 1920.0f,
48 			 3840.0f, 7680.0f},
49 
50 			/* High Accuracy 1 */
51 			{0.0f, 1.875f, 7.5f, 15.625f, 31.25f, 62.5f,
52 			 125.0f, 250.0f, 500.0f, 1000.0f, 2000.0f,
53 			 4000.0f, 8000.0f},
54 
55 			/* High Accuracy 2 */
56 			{0.0f, 1.875f, 7.5f, 12.5f, 25.0f, 50.0f,
57 			 100.0f, 200.0f, 400.0f, 800.0f, 1600.0f,
58 			 3200.0f, 6400.0f},
59 		};
60 
lsm6dsv16x_freq_to_odr_val(const struct device * dev,uint16_t freq)61 static int lsm6dsv16x_freq_to_odr_val(const struct device *dev, uint16_t freq)
62 {
63 	const struct lsm6dsv16x_config *cfg = dev->config;
64 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
65 	lsm6dsv16x_data_rate_t odr;
66 	int8_t mode;
67 	size_t i;
68 
69 	if (lsm6dsv16x_xl_data_rate_get(ctx, &odr) < 0) {
70 		return -EINVAL;
71 	}
72 
73 	mode = (odr >> 4) & 0xf;
74 
75 	for (i = 0; i < ARRAY_SIZE(lsm6dsv16x_odr_map[mode]); i++) {
76 		if (freq <= lsm6dsv16x_odr_map[mode][i]) {
77 			LOG_DBG("mode: %d - odr: %d", mode, i);
78 			return i;
79 		}
80 	}
81 
82 	return -EINVAL;
83 }
84 
85 static const uint16_t lsm6dsv16x_accel_fs_map[] = {2, 4, 8, 16};
86 
lsm6dsv16x_accel_range_to_fs_val(int32_t range)87 static int lsm6dsv16x_accel_range_to_fs_val(int32_t range)
88 {
89 	size_t i;
90 
91 	for (i = 0; i < ARRAY_SIZE(lsm6dsv16x_accel_fs_map); i++) {
92 		if (range == lsm6dsv16x_accel_fs_map[i]) {
93 			return i;
94 		}
95 	}
96 
97 	return -EINVAL;
98 }
99 
100 static const uint16_t lsm6dsv16x_gyro_fs_map[] = {125, 250, 500, 1000, 2000, 0,   0,
101 						  0,   0,   0,   0,    0,    4000};
102 static const uint16_t lsm6dsv16x_gyro_fs_sens[] = {1, 2, 4, 8, 16, 0, 0, 0, 0, 0, 0, 0, 32};
103 
lsm6dsv16x_calc_accel_gain(uint8_t fs)104 int lsm6dsv16x_calc_accel_gain(uint8_t fs)
105 {
106 	return lsm6dsv16x_accel_fs_map[fs] * GAIN_UNIT_XL / 2;
107 }
108 
lsm6dsv16x_calc_gyro_gain(uint8_t fs)109 int lsm6dsv16x_calc_gyro_gain(uint8_t fs)
110 {
111 	return lsm6dsv16x_gyro_fs_sens[fs] * GAIN_UNIT_G;
112 }
113 
lsm6dsv16x_gyro_range_to_fs_val(int32_t range)114 static int lsm6dsv16x_gyro_range_to_fs_val(int32_t range)
115 {
116 	size_t i;
117 
118 	for (i = 0; i < ARRAY_SIZE(lsm6dsv16x_gyro_fs_map); i++) {
119 		if (range == lsm6dsv16x_gyro_fs_map[i]) {
120 			return i;
121 		}
122 	}
123 
124 	return -EINVAL;
125 }
126 
lsm6dsv16x_accel_set_fs_raw(const struct device * dev,uint8_t fs)127 static int lsm6dsv16x_accel_set_fs_raw(const struct device *dev, uint8_t fs)
128 {
129 	const struct lsm6dsv16x_config *cfg = dev->config;
130 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
131 	struct lsm6dsv16x_data *data = dev->data;
132 	lsm6dsv16x_xl_full_scale_t val;
133 
134 	switch (fs) {
135 	case 0:
136 		val = LSM6DSV16X_2g;
137 		break;
138 	case 1:
139 		val = LSM6DSV16X_4g;
140 		break;
141 	case 2:
142 		val = LSM6DSV16X_8g;
143 		break;
144 	case 3:
145 		val = LSM6DSV16X_16g;
146 		break;
147 	default:
148 		return -EIO;
149 	}
150 
151 	if (lsm6dsv16x_xl_full_scale_set(ctx, val) < 0) {
152 		return -EIO;
153 	}
154 
155 	data->accel_fs = fs;
156 
157 	return 0;
158 }
159 
lsm6dsv16x_accel_set_odr_raw(const struct device * dev,uint8_t odr)160 static int lsm6dsv16x_accel_set_odr_raw(const struct device *dev, uint8_t odr)
161 {
162 	const struct lsm6dsv16x_config *cfg = dev->config;
163 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
164 	struct lsm6dsv16x_data *data = dev->data;
165 
166 	if (lsm6dsv16x_xl_data_rate_set(ctx, odr) < 0) {
167 		return -EIO;
168 	}
169 
170 	data->accel_freq = odr;
171 
172 	return 0;
173 }
174 
lsm6dsv16x_gyro_set_fs_raw(const struct device * dev,uint8_t fs)175 static int lsm6dsv16x_gyro_set_fs_raw(const struct device *dev, uint8_t fs)
176 {
177 	const struct lsm6dsv16x_config *cfg = dev->config;
178 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
179 	struct lsm6dsv16x_data *data = dev->data;
180 
181 	if (lsm6dsv16x_gy_full_scale_set(ctx, fs) < 0) {
182 		return -EIO;
183 	}
184 
185 	data->gyro_fs = fs;
186 	return 0;
187 }
188 
lsm6dsv16x_gyro_set_odr_raw(const struct device * dev,uint8_t odr)189 static int lsm6dsv16x_gyro_set_odr_raw(const struct device *dev, uint8_t odr)
190 {
191 	const struct lsm6dsv16x_config *cfg = dev->config;
192 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
193 
194 	if (lsm6dsv16x_gy_data_rate_set(ctx, odr) < 0) {
195 		return -EIO;
196 	}
197 
198 	return 0;
199 }
200 
lsm6dsv16x_accel_odr_set(const struct device * dev,uint16_t freq)201 static int lsm6dsv16x_accel_odr_set(const struct device *dev, uint16_t freq)
202 {
203 	int odr;
204 
205 	odr = lsm6dsv16x_freq_to_odr_val(dev, freq);
206 	if (odr < 0) {
207 		return odr;
208 	}
209 
210 	if (lsm6dsv16x_accel_set_odr_raw(dev, odr) < 0) {
211 		LOG_DBG("failed to set accelerometer sampling rate");
212 		return -EIO;
213 	}
214 
215 	return 0;
216 }
217 
lsm6dsv16x_accel_range_set(const struct device * dev,int32_t range)218 static int lsm6dsv16x_accel_range_set(const struct device *dev, int32_t range)
219 {
220 	int fs;
221 	struct lsm6dsv16x_data *data = dev->data;
222 
223 	fs = lsm6dsv16x_accel_range_to_fs_val(range);
224 	if (fs < 0) {
225 		return fs;
226 	}
227 
228 	if (lsm6dsv16x_accel_set_fs_raw(dev, fs) < 0) {
229 		LOG_DBG("failed to set accelerometer full-scale");
230 		return -EIO;
231 	}
232 
233 	data->acc_gain = lsm6dsv16x_calc_accel_gain(fs);
234 	return 0;
235 }
236 
237 #define LSM6DSV16X_WU_INACT_THS_W_MAX 5
238 #define LSM6DSV16X_WAKE_UP_THS_MAX    0x3FU
239 static const float wu_inact_ths_w_lsb[] = {7.8125f, 15.625f, 31.25f, 62.5f, 125.0f, 250.0f};
240 
lsm6dsv16x_accel_wake_threshold_set(const struct device * dev,const struct sensor_value * val)241 static int lsm6dsv16x_accel_wake_threshold_set(const struct device *dev,
242 					       const struct sensor_value *val)
243 {
244 	const struct lsm6dsv16x_config *cfg = dev->config;
245 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
246 	lsm6dsv16x_act_thresholds_t thresholds;
247 
248 	if (lsm6dsv16x_act_thresholds_get(ctx, &thresholds) < 0) {
249 		LOG_DBG("failed to get thresholds");
250 		return -EIO;
251 	}
252 
253 	float val_mg = sensor_ms2_to_ug(val) / 1000.0f;
254 
255 	thresholds.inactivity_cfg.wu_inact_ths_w = LSM6DSV16X_WU_INACT_THS_W_MAX;
256 	thresholds.threshold = LSM6DSV16X_WAKE_UP_THS_MAX;
257 
258 	for (uint8_t i = 0; i <= LSM6DSV16X_WU_INACT_THS_W_MAX; i++) {
259 		if (val_mg < (wu_inact_ths_w_lsb[i] * (float)LSM6DSV16X_WAKE_UP_THS_MAX)) {
260 			thresholds.inactivity_cfg.wu_inact_ths_w = i;
261 			thresholds.threshold = (uint8_t)(val_mg / wu_inact_ths_w_lsb[i]);
262 			break;
263 		}
264 	}
265 
266 	return lsm6dsv16x_act_thresholds_set(ctx, &thresholds);
267 }
268 
lsm6dsv16x_accel_wake_duration_set(const struct device * dev,const struct sensor_value * val)269 static int lsm6dsv16x_accel_wake_duration_set(const struct device *dev,
270 					      const struct sensor_value *val)
271 {
272 	const struct lsm6dsv16x_config *cfg = dev->config;
273 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
274 	lsm6dsv16x_act_thresholds_t thresholds;
275 
276 	if (lsm6dsv16x_act_thresholds_get(ctx, &thresholds) < 0) {
277 		LOG_DBG("failed to get thresholds");
278 		return -EIO;
279 	}
280 
281 	thresholds.duration = MIN(val->val1, 3);
282 
283 	return lsm6dsv16x_act_thresholds_set(ctx, &thresholds);
284 }
285 
lsm6dsv16x_accel_config(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)286 static int lsm6dsv16x_accel_config(const struct device *dev,
287 				enum sensor_channel chan,
288 				enum sensor_attribute attr,
289 				const struct sensor_value *val)
290 {
291 	const struct lsm6dsv16x_config *cfg = dev->config;
292 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
293 	lsm6dsv16x_xl_mode_t mode;
294 
295 	switch (attr) {
296 	case SENSOR_ATTR_FULL_SCALE:
297 		return lsm6dsv16x_accel_range_set(dev, sensor_ms2_to_g(val));
298 	case SENSOR_ATTR_SAMPLING_FREQUENCY:
299 		return lsm6dsv16x_accel_odr_set(dev, val->val1);
300 	case SENSOR_ATTR_SLOPE_TH:
301 		return lsm6dsv16x_accel_wake_threshold_set(dev, val);
302 	case SENSOR_ATTR_SLOPE_DUR:
303 		return lsm6dsv16x_accel_wake_duration_set(dev, val);
304 	case SENSOR_ATTR_CONFIGURATION:
305 		switch (val->val1) {
306 		case 0: /* High Performance */
307 			mode = LSM6DSV16X_XL_HIGH_PERFORMANCE_MD;
308 			break;
309 		case 1: /* High Accuracy */
310 			mode = LSM6DSV16X_XL_HIGH_ACCURACY_ODR_MD;
311 			break;
312 		case 3: /* ODR triggered */
313 			mode = LSM6DSV16X_XL_ODR_TRIGGERED_MD;
314 			break;
315 		case 4: /* Low Power 2 */
316 			mode = LSM6DSV16X_XL_LOW_POWER_2_AVG_MD;
317 			break;
318 		case 5: /* Low Power 4 */
319 			mode = LSM6DSV16X_XL_LOW_POWER_4_AVG_MD;
320 			break;
321 		case 6: /* Low Power 8 */
322 			mode = LSM6DSV16X_XL_LOW_POWER_8_AVG_MD;
323 			break;
324 		case 7: /* Normal */
325 			mode = LSM6DSV16X_XL_NORMAL_MD;
326 			break;
327 		default:
328 			return -EIO;
329 		}
330 
331 		return lsm6dsv16x_xl_mode_set(ctx, mode);
332 	default:
333 		LOG_DBG("Accel attribute not supported.");
334 		return -ENOTSUP;
335 	}
336 
337 	return 0;
338 }
339 
lsm6dsv16x_gyro_odr_set(const struct device * dev,uint16_t freq)340 static int lsm6dsv16x_gyro_odr_set(const struct device *dev, uint16_t freq)
341 {
342 	int odr;
343 
344 	if (freq < 8) {
345 		return -EIO;
346 	}
347 
348 	odr = lsm6dsv16x_freq_to_odr_val(dev, freq);
349 	if (odr < 0) {
350 		return odr;
351 	}
352 
353 	if (lsm6dsv16x_gyro_set_odr_raw(dev, odr) < 0) {
354 		LOG_DBG("failed to set gyroscope sampling rate");
355 		return -EIO;
356 	}
357 
358 	return 0;
359 }
360 
lsm6dsv16x_gyro_range_set(const struct device * dev,int32_t range)361 static int lsm6dsv16x_gyro_range_set(const struct device *dev, int32_t range)
362 {
363 	int fs;
364 	struct lsm6dsv16x_data *data = dev->data;
365 
366 	fs = lsm6dsv16x_gyro_range_to_fs_val(range);
367 	if (fs < 0) {
368 		return fs;
369 	}
370 
371 	if (lsm6dsv16x_gyro_set_fs_raw(dev, fs) < 0) {
372 		LOG_DBG("failed to set gyroscope full-scale");
373 		return -EIO;
374 	}
375 
376 	data->gyro_gain = lsm6dsv16x_calc_gyro_gain(fs);
377 	return 0;
378 }
379 
lsm6dsv16x_gyro_config(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)380 static int lsm6dsv16x_gyro_config(const struct device *dev,
381 			       enum sensor_channel chan,
382 			       enum sensor_attribute attr,
383 			       const struct sensor_value *val)
384 {
385 	const struct lsm6dsv16x_config *cfg = dev->config;
386 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
387 	lsm6dsv16x_gy_mode_t mode;
388 
389 	switch (attr) {
390 	case SENSOR_ATTR_FULL_SCALE:
391 		return lsm6dsv16x_gyro_range_set(dev, sensor_rad_to_degrees(val));
392 	case SENSOR_ATTR_SAMPLING_FREQUENCY:
393 		return lsm6dsv16x_gyro_odr_set(dev, val->val1);
394 	case SENSOR_ATTR_CONFIGURATION:
395 		switch (val->val1) {
396 		case 0: /* High Performance */
397 			mode = LSM6DSV16X_GY_HIGH_PERFORMANCE_MD;
398 			break;
399 		case 1: /* High Accuracy */
400 			mode = LSM6DSV16X_GY_HIGH_ACCURACY_ODR_MD;
401 			break;
402 		case 4: /* Sleep */
403 			mode = LSM6DSV16X_GY_SLEEP_MD;
404 			break;
405 		case 5: /* Low Power */
406 			mode = LSM6DSV16X_GY_LOW_POWER_MD;
407 			break;
408 		default:
409 			return -EIO;
410 		}
411 
412 		return lsm6dsv16x_gy_mode_set(ctx, mode);
413 	default:
414 		LOG_DBG("Gyro attribute not supported.");
415 		return -ENOTSUP;
416 	}
417 
418 	return 0;
419 }
420 
lsm6dsv16x_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)421 static int lsm6dsv16x_attr_set(const struct device *dev,
422 			    enum sensor_channel chan,
423 			    enum sensor_attribute attr,
424 			    const struct sensor_value *val)
425 {
426 #if defined(CONFIG_LSM6DSV16X_SENSORHUB)
427 	struct lsm6dsv16x_data *data = dev->data;
428 #endif /* CONFIG_LSM6DSV16X_SENSORHUB */
429 
430 	if (!lsm6dsv16x_is_active(dev)) {
431 		return -EBUSY;
432 	}
433 
434 	switch (chan) {
435 	case SENSOR_CHAN_ACCEL_XYZ:
436 		return lsm6dsv16x_accel_config(dev, chan, attr, val);
437 	case SENSOR_CHAN_GYRO_XYZ:
438 		return lsm6dsv16x_gyro_config(dev, chan, attr, val);
439 #if defined(CONFIG_LSM6DSV16X_SENSORHUB)
440 	case SENSOR_CHAN_MAGN_XYZ:
441 	case SENSOR_CHAN_PRESS:
442 	case SENSOR_CHAN_HUMIDITY:
443 		if (!data->shub_inited) {
444 			LOG_ERR("shub not inited.");
445 			return -ENOTSUP;
446 		}
447 
448 		return lsm6dsv16x_shub_config(dev, chan, attr, val);
449 #endif /* CONFIG_LSM6DSV16X_SENSORHUB */
450 	default:
451 		LOG_WRN("attr_set() not supported on this channel.");
452 		return -ENOTSUP;
453 	}
454 
455 	return 0;
456 }
457 
lsm6dsv16x_accel_wake_threshold_get(const struct device * dev,struct sensor_value * val)458 static int lsm6dsv16x_accel_wake_threshold_get(const struct device *dev, struct sensor_value *val)
459 {
460 	const struct lsm6dsv16x_config *cfg = dev->config;
461 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
462 	lsm6dsv16x_act_thresholds_t thresholds;
463 	float val_mg;
464 
465 	if (lsm6dsv16x_act_thresholds_get(ctx, &thresholds) < 0) {
466 		LOG_DBG("failed to get thresholds");
467 		return -EIO;
468 	}
469 
470 	val_mg = wu_inact_ths_w_lsb[thresholds.inactivity_cfg.wu_inact_ths_w];
471 	val_mg *= (float)thresholds.threshold;
472 
473 	sensor_ug_to_ms2(1000.0f * val_mg, val);
474 
475 	return 0;
476 }
477 
lsm6dsv16x_accel_wake_duration_get(const struct device * dev,struct sensor_value * val)478 static int lsm6dsv16x_accel_wake_duration_get(const struct device *dev, struct sensor_value *val)
479 {
480 	const struct lsm6dsv16x_config *cfg = dev->config;
481 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
482 	lsm6dsv16x_act_thresholds_t thresholds;
483 
484 	if (lsm6dsv16x_act_thresholds_get(ctx, &thresholds) < 0) {
485 		LOG_DBG("failed to get thresholds");
486 		return -EIO;
487 	}
488 
489 	val->val1 = thresholds.duration;
490 	val->val2 = 0;
491 
492 	return 0;
493 }
494 
lsm6dsv16x_accel_get_config(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,struct sensor_value * val)495 static int lsm6dsv16x_accel_get_config(const struct device *dev,
496 				       enum sensor_channel chan,
497 				       enum sensor_attribute attr,
498 				       struct sensor_value *val)
499 {
500 	const struct lsm6dsv16x_config *cfg = dev->config;
501 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
502 	struct lsm6dsv16x_data *data = dev->data;
503 
504 	switch (attr) {
505 	case SENSOR_ATTR_FULL_SCALE:
506 		sensor_g_to_ms2(lsm6dsv16x_accel_fs_map[data->accel_fs], val);
507 		break;
508 	case SENSOR_ATTR_SAMPLING_FREQUENCY: {
509 		lsm6dsv16x_data_rate_t odr;
510 		int8_t mode;
511 
512 		if (lsm6dsv16x_xl_data_rate_get(ctx, &odr) < 0) {
513 			return -EINVAL;
514 		}
515 
516 		mode = (odr >> 4) & 0xf;
517 
518 		val->val1 = lsm6dsv16x_odr_map[mode][data->accel_freq];
519 		val->val2 = 0;
520 		break;
521 	}
522 	case SENSOR_ATTR_SLOPE_TH:
523 		return lsm6dsv16x_accel_wake_threshold_get(dev, val);
524 	case SENSOR_ATTR_SLOPE_DUR:
525 		return lsm6dsv16x_accel_wake_duration_get(dev, val);
526 	case SENSOR_ATTR_CONFIGURATION: {
527 		lsm6dsv16x_xl_mode_t mode;
528 
529 		lsm6dsv16x_xl_mode_get(ctx, &mode);
530 
531 		switch (mode) {
532 		case LSM6DSV16X_XL_HIGH_PERFORMANCE_MD:
533 			val->val1 = 0;
534 			break;
535 		case LSM6DSV16X_XL_HIGH_ACCURACY_ODR_MD:
536 			val->val1 = 1;
537 			break;
538 		case LSM6DSV16X_XL_ODR_TRIGGERED_MD:
539 			val->val1 = 3;
540 			break;
541 		case LSM6DSV16X_XL_LOW_POWER_2_AVG_MD:
542 			val->val1 = 4;
543 			break;
544 		case LSM6DSV16X_XL_LOW_POWER_4_AVG_MD:
545 			val->val1 = 5;
546 			break;
547 		case LSM6DSV16X_XL_LOW_POWER_8_AVG_MD:
548 			val->val1 = 6;
549 			break;
550 		case LSM6DSV16X_XL_NORMAL_MD:
551 			val->val1 = 7;
552 			break;
553 		default:
554 			return -EIO;
555 		}
556 
557 		break;
558 	}
559 	default:
560 		LOG_DBG("Attr attribute not supported.");
561 		return -ENOTSUP;
562 	}
563 
564 	return 0;
565 }
566 
lsm6dsv16x_gyro_get_config(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,struct sensor_value * val)567 static int lsm6dsv16x_gyro_get_config(const struct device *dev,
568 				      enum sensor_channel chan,
569 				      enum sensor_attribute attr,
570 				      struct sensor_value *val)
571 {
572 	const struct lsm6dsv16x_config *cfg = dev->config;
573 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
574 	struct lsm6dsv16x_data *data = dev->data;
575 
576 	switch (attr) {
577 	case SENSOR_ATTR_FULL_SCALE:
578 		sensor_degrees_to_rad(lsm6dsv16x_gyro_fs_map[data->gyro_fs], val);
579 		break;
580 	case SENSOR_ATTR_SAMPLING_FREQUENCY: {
581 		lsm6dsv16x_data_rate_t odr;
582 		int8_t mode;
583 
584 		if (lsm6dsv16x_gy_data_rate_get(ctx, &odr) < 0) {
585 			return -EINVAL;
586 		}
587 
588 		mode = (odr >> 4) & 0xf;
589 
590 		val->val1 = lsm6dsv16x_odr_map[mode][data->gyro_freq];
591 		val->val2 = 0;
592 		break;
593 	}
594 	case SENSOR_ATTR_CONFIGURATION: {
595 		lsm6dsv16x_gy_mode_t mode;
596 
597 		lsm6dsv16x_gy_mode_get(ctx, &mode);
598 
599 		switch (mode) {
600 		case LSM6DSV16X_GY_HIGH_PERFORMANCE_MD:
601 			val->val1 = 0;
602 			break;
603 		case LSM6DSV16X_GY_HIGH_ACCURACY_ODR_MD:
604 			val->val1 = 1;
605 			break;
606 		case LSM6DSV16X_GY_SLEEP_MD:
607 			val->val1 = 4;
608 			break;
609 		case LSM6DSV16X_GY_LOW_POWER_MD:
610 			val->val1 = 5;
611 			break;
612 		default:
613 			return -EIO;
614 		}
615 
616 		break;
617 	}
618 	default:
619 		LOG_DBG("Gyro attribute not supported.");
620 		return -ENOTSUP;
621 	}
622 
623 	return 0;
624 }
625 
lsm6dsv16x_attr_get(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,struct sensor_value * val)626 static int lsm6dsv16x_attr_get(const struct device *dev, enum sensor_channel chan,
627 			       enum sensor_attribute attr, struct sensor_value *val)
628 {
629 	if (!lsm6dsv16x_is_active(dev)) {
630 		return -EBUSY;
631 	}
632 
633 	switch (chan) {
634 	case SENSOR_CHAN_ACCEL_XYZ:
635 		return lsm6dsv16x_accel_get_config(dev, chan, attr, val);
636 	case SENSOR_CHAN_GYRO_XYZ:
637 		return lsm6dsv16x_gyro_get_config(dev, chan, attr, val);
638 	default:
639 		LOG_WRN("attr_get() not supported on this channel.");
640 		return -ENOTSUP;
641 	}
642 
643 	return 0;
644 }
645 
lsm6dsv16x_sample_fetch_accel(const struct device * dev)646 static int lsm6dsv16x_sample_fetch_accel(const struct device *dev)
647 {
648 	const struct lsm6dsv16x_config *cfg = dev->config;
649 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
650 	struct lsm6dsv16x_data *data = dev->data;
651 
652 	if (lsm6dsv16x_acceleration_raw_get(ctx, data->acc) < 0) {
653 		LOG_DBG("Failed to read sample");
654 		return -EIO;
655 	}
656 
657 	return 0;
658 }
659 
lsm6dsv16x_sample_fetch_gyro(const struct device * dev)660 static int lsm6dsv16x_sample_fetch_gyro(const struct device *dev)
661 {
662 	const struct lsm6dsv16x_config *cfg = dev->config;
663 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
664 	struct lsm6dsv16x_data *data = dev->data;
665 
666 	if (lsm6dsv16x_angular_rate_raw_get(ctx, data->gyro) < 0) {
667 		LOG_DBG("Failed to read sample");
668 		return -EIO;
669 	}
670 
671 	return 0;
672 }
673 
674 #if defined(CONFIG_LSM6DSV16X_ENABLE_TEMP)
lsm6dsv16x_sample_fetch_temp(const struct device * dev)675 static int lsm6dsv16x_sample_fetch_temp(const struct device *dev)
676 {
677 	const struct lsm6dsv16x_config *cfg = dev->config;
678 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
679 	struct lsm6dsv16x_data *data = dev->data;
680 
681 	if (lsm6dsv16x_temperature_raw_get(ctx, &data->temp_sample) < 0) {
682 		LOG_DBG("Failed to read sample");
683 		return -EIO;
684 	}
685 
686 	return 0;
687 }
688 #endif
689 
690 #if defined(CONFIG_LSM6DSV16X_SENSORHUB)
lsm6dsv16x_sample_fetch_shub(const struct device * dev)691 static int lsm6dsv16x_sample_fetch_shub(const struct device *dev)
692 {
693 	if (lsm6dsv16x_shub_fetch_external_devs(dev) < 0) {
694 		LOG_DBG("failed to read ext shub devices");
695 		return -EIO;
696 	}
697 
698 	return 0;
699 }
700 #endif /* CONFIG_LSM6DSV16X_SENSORHUB */
701 
lsm6dsv16x_sample_fetch(const struct device * dev,enum sensor_channel chan)702 static int lsm6dsv16x_sample_fetch(const struct device *dev,
703 				enum sensor_channel chan)
704 {
705 #if defined(CONFIG_LSM6DSV16X_SENSORHUB)
706 	struct lsm6dsv16x_data *data = dev->data;
707 #endif /* CONFIG_LSM6DSV16X_SENSORHUB */
708 
709 	if (!lsm6dsv16x_is_active(dev)) {
710 		return -EBUSY;
711 	}
712 
713 	switch (chan) {
714 	case SENSOR_CHAN_ACCEL_XYZ:
715 		lsm6dsv16x_sample_fetch_accel(dev);
716 		break;
717 	case SENSOR_CHAN_GYRO_XYZ:
718 		lsm6dsv16x_sample_fetch_gyro(dev);
719 		break;
720 #if defined(CONFIG_LSM6DSV16X_ENABLE_TEMP)
721 	case SENSOR_CHAN_DIE_TEMP:
722 		lsm6dsv16x_sample_fetch_temp(dev);
723 		break;
724 #endif
725 	case SENSOR_CHAN_ALL:
726 		lsm6dsv16x_sample_fetch_accel(dev);
727 		lsm6dsv16x_sample_fetch_gyro(dev);
728 #if defined(CONFIG_LSM6DSV16X_ENABLE_TEMP)
729 		lsm6dsv16x_sample_fetch_temp(dev);
730 #endif
731 #if defined(CONFIG_LSM6DSV16X_SENSORHUB)
732 		if (data->shub_inited) {
733 			lsm6dsv16x_sample_fetch_shub(dev);
734 		}
735 #endif
736 		break;
737 	default:
738 		return -ENOTSUP;
739 	}
740 
741 	return 0;
742 }
743 
lsm6dsv16x_accel_convert(struct sensor_value * val,int raw_val,uint32_t sensitivity)744 static inline void lsm6dsv16x_accel_convert(struct sensor_value *val, int raw_val,
745 					 uint32_t sensitivity)
746 {
747 	int64_t dval;
748 
749 	/* Sensitivity is exposed in ug/LSB */
750 	/* Convert to m/s^2 */
751 	dval = (int64_t)(raw_val) * sensitivity;
752 	sensor_ug_to_ms2(dval, val);
753 }
754 
lsm6dsv16x_accel_get_channel(enum sensor_channel chan,struct sensor_value * val,struct lsm6dsv16x_data * data,uint32_t sensitivity)755 static inline int lsm6dsv16x_accel_get_channel(enum sensor_channel chan,
756 					    struct sensor_value *val,
757 					    struct lsm6dsv16x_data *data,
758 					    uint32_t sensitivity)
759 {
760 	uint8_t i;
761 
762 	switch (chan) {
763 	case SENSOR_CHAN_ACCEL_X:
764 		lsm6dsv16x_accel_convert(val, data->acc[0], sensitivity);
765 		break;
766 	case SENSOR_CHAN_ACCEL_Y:
767 		lsm6dsv16x_accel_convert(val, data->acc[1], sensitivity);
768 		break;
769 	case SENSOR_CHAN_ACCEL_Z:
770 		lsm6dsv16x_accel_convert(val, data->acc[2], sensitivity);
771 		break;
772 	case SENSOR_CHAN_ACCEL_XYZ:
773 		for (i = 0; i < 3; i++) {
774 			lsm6dsv16x_accel_convert(val++, data->acc[i], sensitivity);
775 		}
776 		break;
777 	default:
778 		return -ENOTSUP;
779 	}
780 
781 	return 0;
782 }
783 
lsm6dsv16x_accel_channel_get(enum sensor_channel chan,struct sensor_value * val,struct lsm6dsv16x_data * data)784 static int lsm6dsv16x_accel_channel_get(enum sensor_channel chan,
785 				     struct sensor_value *val,
786 				     struct lsm6dsv16x_data *data)
787 {
788 	return lsm6dsv16x_accel_get_channel(chan, val, data, data->acc_gain);
789 }
790 
lsm6dsv16x_gyro_convert(struct sensor_value * val,int raw_val,uint32_t sensitivity)791 static inline void lsm6dsv16x_gyro_convert(struct sensor_value *val, int raw_val,
792 					uint32_t sensitivity)
793 {
794 	int64_t dval;
795 
796 	/* Sensitivity is exposed in udps/LSB */
797 	/* So, calculate value in 10 udps unit and then to rad/s */
798 	dval = (int64_t)(raw_val) * sensitivity / 10;
799 	sensor_10udegrees_to_rad(dval, val);
800 }
801 
lsm6dsv16x_gyro_get_channel(enum sensor_channel chan,struct sensor_value * val,struct lsm6dsv16x_data * data,uint32_t sensitivity)802 static inline int lsm6dsv16x_gyro_get_channel(enum sensor_channel chan,
803 					   struct sensor_value *val,
804 					   struct lsm6dsv16x_data *data,
805 					   uint32_t sensitivity)
806 {
807 	uint8_t i;
808 
809 	switch (chan) {
810 	case SENSOR_CHAN_GYRO_X:
811 		lsm6dsv16x_gyro_convert(val, data->gyro[0], sensitivity);
812 		break;
813 	case SENSOR_CHAN_GYRO_Y:
814 		lsm6dsv16x_gyro_convert(val, data->gyro[1], sensitivity);
815 		break;
816 	case SENSOR_CHAN_GYRO_Z:
817 		lsm6dsv16x_gyro_convert(val, data->gyro[2], sensitivity);
818 		break;
819 	case SENSOR_CHAN_GYRO_XYZ:
820 		for (i = 0; i < 3; i++) {
821 			lsm6dsv16x_gyro_convert(val++, data->gyro[i], sensitivity);
822 		}
823 		break;
824 	default:
825 		return -ENOTSUP;
826 	}
827 
828 	return 0;
829 }
830 
lsm6dsv16x_gyro_channel_get(enum sensor_channel chan,struct sensor_value * val,struct lsm6dsv16x_data * data)831 static int lsm6dsv16x_gyro_channel_get(enum sensor_channel chan,
832 				    struct sensor_value *val,
833 				    struct lsm6dsv16x_data *data)
834 {
835 	return lsm6dsv16x_gyro_get_channel(chan, val, data, data->gyro_gain);
836 }
837 
838 #if defined(CONFIG_LSM6DSV16X_ENABLE_TEMP)
lsm6dsv16x_gyro_channel_get_temp(struct sensor_value * val,struct lsm6dsv16x_data * data)839 static void lsm6dsv16x_gyro_channel_get_temp(struct sensor_value *val,
840 					  struct lsm6dsv16x_data *data)
841 {
842 	/* convert units to micro Celsius. Raw temperature samples are
843 	 * expressed in 256 LSB/deg_C units. And LSB output is 0 at 25 C.
844 	 */
845 	int64_t temp_sample = data->temp_sample;
846 	int64_t micro_c = (temp_sample * 1000000LL) / 256;
847 
848 	val->val1 = (int32_t)(micro_c / 1000000) + 25;
849 	val->val2 = (int32_t)(micro_c % 1000000);
850 }
851 #endif
852 
853 #if defined(CONFIG_LSM6DSV16X_SENSORHUB)
lsm6dsv16x_magn_convert(struct sensor_value * val,int raw_val,uint16_t sensitivity)854 static inline void lsm6dsv16x_magn_convert(struct sensor_value *val, int raw_val,
855 					uint16_t sensitivity)
856 {
857 	double dval;
858 
859 	/* Sensitivity is exposed in ugauss/LSB */
860 	dval = (double)(raw_val * sensitivity);
861 	val->val1 = (int32_t)dval / 1000000;
862 	val->val2 = (int32_t)dval % 1000000;
863 }
864 
lsm6dsv16x_magn_get_channel(enum sensor_channel chan,struct sensor_value * val,struct lsm6dsv16x_data * data)865 static inline int lsm6dsv16x_magn_get_channel(enum sensor_channel chan,
866 					   struct sensor_value *val,
867 					   struct lsm6dsv16x_data *data)
868 {
869 	int16_t sample[3];
870 	int idx;
871 
872 	idx = lsm6dsv16x_shub_get_idx(data->dev, SENSOR_CHAN_MAGN_XYZ);
873 	if (idx < 0) {
874 		LOG_DBG("external magn not supported");
875 		return -ENOTSUP;
876 	}
877 
878 
879 	sample[0] = (int16_t)(data->ext_data[idx][0] |
880 			     (data->ext_data[idx][1] << 8));
881 	sample[1] = (int16_t)(data->ext_data[idx][2] |
882 			     (data->ext_data[idx][3] << 8));
883 	sample[2] = (int16_t)(data->ext_data[idx][4] |
884 			     (data->ext_data[idx][5] << 8));
885 
886 	switch (chan) {
887 	case SENSOR_CHAN_MAGN_X:
888 		lsm6dsv16x_magn_convert(val, sample[0], data->magn_gain);
889 		break;
890 	case SENSOR_CHAN_MAGN_Y:
891 		lsm6dsv16x_magn_convert(val, sample[1], data->magn_gain);
892 		break;
893 	case SENSOR_CHAN_MAGN_Z:
894 		lsm6dsv16x_magn_convert(val, sample[2], data->magn_gain);
895 		break;
896 	case SENSOR_CHAN_MAGN_XYZ:
897 		lsm6dsv16x_magn_convert(val, sample[0], data->magn_gain);
898 		lsm6dsv16x_magn_convert(val + 1, sample[1], data->magn_gain);
899 		lsm6dsv16x_magn_convert(val + 2, sample[2], data->magn_gain);
900 		break;
901 	default:
902 		return -ENOTSUP;
903 	}
904 
905 	return 0;
906 }
907 
lsm6dsv16x_hum_convert(struct sensor_value * val,struct lsm6dsv16x_data * data)908 static inline void lsm6dsv16x_hum_convert(struct sensor_value *val,
909 				       struct lsm6dsv16x_data *data)
910 {
911 	float rh;
912 	int16_t raw_val;
913 	struct hts221_data *ht = &data->hts221;
914 	int idx;
915 
916 	idx = lsm6dsv16x_shub_get_idx(data->dev, SENSOR_CHAN_HUMIDITY);
917 	if (idx < 0) {
918 		LOG_DBG("external press/temp not supported");
919 		return;
920 	}
921 
922 	raw_val = (int16_t)(data->ext_data[idx][0] |
923 			   (data->ext_data[idx][1] << 8));
924 
925 	/* find relative humidty by linear interpolation */
926 	rh = (ht->y1 - ht->y0) * raw_val + ht->x1 * ht->y0 - ht->x0 * ht->y1;
927 	rh /= (ht->x1 - ht->x0);
928 
929 	/* convert humidity to integer and fractional part */
930 	val->val1 = rh;
931 	val->val2 = rh * 1000000;
932 }
933 
lsm6dsv16x_press_convert(struct sensor_value * val,struct lsm6dsv16x_data * data)934 static inline void lsm6dsv16x_press_convert(struct sensor_value *val,
935 					 struct lsm6dsv16x_data *data)
936 {
937 	int32_t raw_val;
938 	int idx;
939 
940 	idx = lsm6dsv16x_shub_get_idx(data->dev, SENSOR_CHAN_PRESS);
941 	if (idx < 0) {
942 		LOG_DBG("external press/temp not supported");
943 		return;
944 	}
945 
946 	raw_val = (int32_t)(data->ext_data[idx][0] |
947 			   (data->ext_data[idx][1] << 8) |
948 			   (data->ext_data[idx][2] << 16));
949 
950 	/* Pressure sensitivity is 4096 LSB/hPa */
951 	/* Convert raw_val to val in kPa */
952 	val->val1 = (raw_val >> 12) / 10;
953 	val->val2 = (raw_val >> 12) % 10 * 100000 +
954 		(((int32_t)((raw_val) & 0x0FFF) * 100000L) >> 12);
955 }
956 
lsm6dsv16x_temp_convert(struct sensor_value * val,struct lsm6dsv16x_data * data)957 static inline void lsm6dsv16x_temp_convert(struct sensor_value *val,
958 					struct lsm6dsv16x_data *data)
959 {
960 	int16_t raw_val;
961 	int idx;
962 
963 	idx = lsm6dsv16x_shub_get_idx(data->dev, SENSOR_CHAN_PRESS);
964 	if (idx < 0) {
965 		LOG_DBG("external press/temp not supported");
966 		return;
967 	}
968 
969 	raw_val = (int16_t)(data->ext_data[idx][3] |
970 			   (data->ext_data[idx][4] << 8));
971 
972 	/* Temperature sensitivity is 100 LSB/deg C */
973 	val->val1 = raw_val / 100;
974 	val->val2 = (int32_t)raw_val % 100 * (10000);
975 }
976 #endif
977 
lsm6dsv16x_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)978 static int lsm6dsv16x_channel_get(const struct device *dev,
979 			       enum sensor_channel chan,
980 			       struct sensor_value *val)
981 {
982 	struct lsm6dsv16x_data *data = dev->data;
983 
984 	if (!lsm6dsv16x_is_active(dev)) {
985 		return -EBUSY;
986 	}
987 
988 	switch (chan) {
989 	case SENSOR_CHAN_ACCEL_X:
990 	case SENSOR_CHAN_ACCEL_Y:
991 	case SENSOR_CHAN_ACCEL_Z:
992 	case SENSOR_CHAN_ACCEL_XYZ:
993 		lsm6dsv16x_accel_channel_get(chan, val, data);
994 		break;
995 	case SENSOR_CHAN_GYRO_X:
996 	case SENSOR_CHAN_GYRO_Y:
997 	case SENSOR_CHAN_GYRO_Z:
998 	case SENSOR_CHAN_GYRO_XYZ:
999 		lsm6dsv16x_gyro_channel_get(chan, val, data);
1000 		break;
1001 #if defined(CONFIG_LSM6DSV16X_ENABLE_TEMP)
1002 	case SENSOR_CHAN_DIE_TEMP:
1003 		lsm6dsv16x_gyro_channel_get_temp(val, data);
1004 		break;
1005 #endif
1006 #if defined(CONFIG_LSM6DSV16X_SENSORHUB)
1007 	case SENSOR_CHAN_MAGN_X:
1008 	case SENSOR_CHAN_MAGN_Y:
1009 	case SENSOR_CHAN_MAGN_Z:
1010 	case SENSOR_CHAN_MAGN_XYZ:
1011 		if (!data->shub_inited) {
1012 			LOG_ERR("attr_set() shub not inited.");
1013 			return -ENOTSUP;
1014 		}
1015 
1016 		lsm6dsv16x_magn_get_channel(chan, val, data);
1017 		break;
1018 
1019 	case SENSOR_CHAN_HUMIDITY:
1020 		if (!data->shub_inited) {
1021 			LOG_ERR("attr_set() shub not inited.");
1022 			return -ENOTSUP;
1023 		}
1024 
1025 		lsm6dsv16x_hum_convert(val, data);
1026 		break;
1027 
1028 	case SENSOR_CHAN_PRESS:
1029 		if (!data->shub_inited) {
1030 			LOG_ERR("attr_set() shub not inited.");
1031 			return -ENOTSUP;
1032 		}
1033 
1034 		lsm6dsv16x_press_convert(val, data);
1035 		break;
1036 
1037 	case SENSOR_CHAN_AMBIENT_TEMP:
1038 		if (!data->shub_inited) {
1039 			LOG_ERR("attr_set() shub not inited.");
1040 			return -ENOTSUP;
1041 		}
1042 
1043 		lsm6dsv16x_temp_convert(val, data);
1044 		break;
1045 #endif
1046 	default:
1047 		return -ENOTSUP;
1048 	}
1049 
1050 	return 0;
1051 }
1052 
1053 static DEVICE_API(sensor, lsm6dsv16x_driver_api) = {
1054 	.attr_set = lsm6dsv16x_attr_set,
1055 	.attr_get = lsm6dsv16x_attr_get,
1056 #if CONFIG_LSM6DSV16X_TRIGGER
1057 	.trigger_set = lsm6dsv16x_trigger_set,
1058 #endif
1059 	.sample_fetch = lsm6dsv16x_sample_fetch,
1060 	.channel_get = lsm6dsv16x_channel_get,
1061 #ifdef CONFIG_SENSOR_ASYNC_API
1062 	.get_decoder = lsm6dsv16x_get_decoder,
1063 	.submit = lsm6dsv16x_submit,
1064 #endif
1065 };
1066 
lsm6dsv16x_init_chip(const struct device * dev)1067 static int lsm6dsv16x_init_chip(const struct device *dev)
1068 {
1069 	const struct lsm6dsv16x_config *cfg = dev->config;
1070 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
1071 	struct lsm6dsv16x_data *lsm6dsv16x = dev->data;
1072 	uint8_t chip_id;
1073 	uint8_t odr, fs;
1074 
1075 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
1076 	if (cfg->i3c.bus != NULL) {
1077 		/*
1078 		 * Need to grab the pointer to the I3C device descriptor
1079 		 * before we can talk to the sensor.
1080 		 */
1081 		lsm6dsv16x->i3c_dev = i3c_device_find(cfg->i3c.bus, &cfg->i3c.dev_id);
1082 		if (lsm6dsv16x->i3c_dev == NULL) {
1083 			LOG_ERR("Cannot find I3C device descriptor");
1084 			return -ENODEV;
1085 		}
1086 	}
1087 #endif
1088 
1089 	/* All registers except 0x01 are different between banks, including the WHO_AM_I
1090 	 * register and the register used for a SW reset.  If the lsm6dsv16x wasn't on the user
1091 	 * bank when it reset, then both the chip id check and the sw reset will fail unless we
1092 	 * set the bank now.
1093 	 */
1094 	if (lsm6dsv16x_mem_bank_set(ctx, LSM6DSV16X_MAIN_MEM_BANK) < 0) {
1095 		LOG_DBG("Failed to set user bank");
1096 		return -EIO;
1097 	}
1098 
1099 	if (lsm6dsv16x_device_id_get(ctx, &chip_id) < 0) {
1100 		LOG_DBG("Failed reading chip id");
1101 		return -EIO;
1102 	}
1103 
1104 	LOG_INF("chip id 0x%x", chip_id);
1105 
1106 	if (chip_id != LSM6DSV16X_ID) {
1107 		LOG_DBG("Invalid chip id 0x%x", chip_id);
1108 		return -EIO;
1109 	}
1110 
1111 	/* Resetting the whole device while using I3C will also reset the DA, therefore perform
1112 	 * only a software reset if the bus is I3C. It should be assumed that the device was
1113 	 * already fully reset by the I3C CCC RSTACT (whole chip) done as apart of the I3C Bus
1114 	 * initialization.
1115 	 */
1116 	if (ON_I3C_BUS(cfg)) {
1117 		/* Restore default configuration */
1118 		lsm6dsv16x_reset_set(ctx, LSM6DSV16X_RESTORE_CAL_PARAM);
1119 
1120 		/* wait 150us as reported in AN5763 */
1121 		k_sleep(K_USEC(150));
1122 	} else {
1123 		/* reset device (sw_por) */
1124 		if (lsm6dsv16x_reset_set(ctx, LSM6DSV16X_GLOBAL_RST) < 0) {
1125 			return -EIO;
1126 		}
1127 
1128 		/* wait 30ms as reported in AN5763 */
1129 		k_sleep(K_MSEC(30));
1130 	}
1131 
1132 	fs = cfg->accel_range;
1133 	LOG_DBG("accel range is %d", fs);
1134 	if (lsm6dsv16x_accel_set_fs_raw(dev, fs) < 0) {
1135 		LOG_ERR("failed to set accelerometer range %d", fs);
1136 		return -EIO;
1137 	}
1138 	lsm6dsv16x->acc_gain = lsm6dsv16x_calc_accel_gain(fs);
1139 
1140 	odr = cfg->accel_odr;
1141 	LOG_DBG("accel odr is %d", odr);
1142 	if (lsm6dsv16x_accel_set_odr_raw(dev, odr) < 0) {
1143 		LOG_ERR("failed to set accelerometer odr %d", odr);
1144 		return -EIO;
1145 	}
1146 
1147 	fs = cfg->gyro_range;
1148 	LOG_DBG("gyro range is %d", fs);
1149 	if (lsm6dsv16x_gyro_set_fs_raw(dev, fs) < 0) {
1150 		LOG_ERR("failed to set gyroscope range %d", fs);
1151 		return -EIO;
1152 	}
1153 	lsm6dsv16x->gyro_gain = lsm6dsv16x_calc_gyro_gain(fs);
1154 
1155 	odr = cfg->gyro_odr;
1156 	LOG_DBG("gyro odr is %d", odr);
1157 	lsm6dsv16x->gyro_freq = odr;
1158 	if (lsm6dsv16x_gyro_set_odr_raw(dev, odr) < 0) {
1159 		LOG_ERR("failed to set gyroscope odr %d", odr);
1160 		return -EIO;
1161 	}
1162 
1163 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
1164 	if (IS_ENABLED(CONFIG_LSM6DSV16X_STREAM) && (ON_I3C_BUS(cfg))) {
1165 		/*
1166 		 * Set MRL to the Max Size of the FIFO so the entire FIFO can be read
1167 		 * out at once
1168 		 */
1169 		struct i3c_ccc_mrl setmrl = {
1170 			.len = 0x0700,
1171 			.ibi_len = lsm6dsv16x->i3c_dev->data_length.max_ibi,
1172 		};
1173 		if (i3c_ccc_do_setmrl(lsm6dsv16x->i3c_dev, &setmrl) < 0) {
1174 			LOG_ERR("failed to set mrl");
1175 			return -EIO;
1176 		}
1177 	}
1178 #endif
1179 
1180 	if (lsm6dsv16x_block_data_update_set(ctx, 1) < 0) {
1181 		LOG_DBG("failed to set BDU mode");
1182 		return -EIO;
1183 	}
1184 
1185 	return 0;
1186 }
1187 
lsm6dsv16x_init(const struct device * dev)1188 static int lsm6dsv16x_init(const struct device *dev)
1189 {
1190 #ifdef CONFIG_LSM6DSV16X_TRIGGER
1191 	const struct lsm6dsv16x_config *cfg = dev->config;
1192 #endif
1193 	struct lsm6dsv16x_data *data = dev->data;
1194 
1195 	LOG_INF("Initialize device %s", dev->name);
1196 	data->dev = dev;
1197 
1198 	if (lsm6dsv16x_init_chip(dev) < 0) {
1199 		LOG_DBG("failed to initialize chip");
1200 		return -EIO;
1201 	}
1202 
1203 #ifdef CONFIG_LSM6DSV16X_TRIGGER
1204 	if (cfg->trig_enabled) {
1205 		if (lsm6dsv16x_init_interrupt(dev) < 0) {
1206 			LOG_ERR("Failed to initialize interrupt.");
1207 			return -EIO;
1208 		}
1209 	}
1210 #endif
1211 
1212 #ifdef CONFIG_LSM6DSV16X_SENSORHUB
1213 	data->shub_inited = true;
1214 	if (lsm6dsv16x_shub_init(dev) < 0) {
1215 		LOG_INF("shub: no external chips found");
1216 		data->shub_inited = false;
1217 	}
1218 #endif
1219 
1220 	return 0;
1221 }
1222 
1223 #if defined(CONFIG_PM_DEVICE)
lsm6dsv16x_pm_action(const struct device * dev,enum pm_device_action action)1224 static int lsm6dsv16x_pm_action(const struct device *dev, enum pm_device_action action)
1225 {
1226 	struct lsm6dsv16x_data *data = dev->data;
1227 	const struct lsm6dsv16x_config *cfg = dev->config;
1228 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
1229 	int ret = 0;
1230 
1231 	LOG_DBG("PM action: %d", (int)action);
1232 
1233 	switch (action) {
1234 	case PM_DEVICE_ACTION_RESUME:
1235 		if (lsm6dsv16x_xl_data_rate_set(ctx, data->accel_freq) < 0) {
1236 			LOG_ERR("failed to set accelerometer odr %d", (int)data->accel_freq);
1237 			ret = -EIO;
1238 		}
1239 		if (lsm6dsv16x_gy_data_rate_set(ctx, data->gyro_freq) < 0) {
1240 			LOG_ERR("failed to set gyroscope odr %d", (int)data->gyro_freq);
1241 			ret = -EIO;
1242 		}
1243 		break;
1244 	case PM_DEVICE_ACTION_SUSPEND:
1245 		if (lsm6dsv16x_xl_data_rate_set(ctx, LSM6DSV16X_DT_ODR_OFF) < 0) {
1246 			LOG_ERR("failed to disable accelerometer");
1247 			ret = -EIO;
1248 		}
1249 		if (lsm6dsv16x_gy_data_rate_set(ctx, LSM6DSV16X_DT_ODR_OFF) < 0) {
1250 			LOG_ERR("failed to disable gyroscope");
1251 			ret = -EIO;
1252 		}
1253 		break;
1254 	default:
1255 		ret = -ENOTSUP;
1256 		break;
1257 	}
1258 
1259 	return ret;
1260 }
1261 #endif /* CONFIG_PM_DEVICE */
1262 
1263 #if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0
1264 #warning "LSM6DSV16X driver enabled without any devices"
1265 #endif
1266 
1267 /*
1268  * Device creation macro, shared by LSM6DSV16X_DEFINE_SPI() and
1269  * LSM6DSV16X_DEFINE_I2C().
1270  */
1271 
1272 #define LSM6DSV16X_DEVICE_INIT(inst)                                                               \
1273 	PM_DEVICE_DT_INST_DEFINE(inst, lsm6dsv16x_pm_action);                                      \
1274 	SENSOR_DEVICE_DT_INST_DEFINE(inst, lsm6dsv16x_init, PM_DEVICE_DT_INST_GET(inst),           \
1275 				     &lsm6dsv16x_data_##inst, &lsm6dsv16x_config_##inst,           \
1276 				     POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,                     \
1277 				     &lsm6dsv16x_driver_api);
1278 
1279 #ifdef CONFIG_LSM6DSV16X_TRIGGER
1280 #define LSM6DSV16X_CFG_IRQ(inst)					\
1281 	.trig_enabled = true,						\
1282 	.int1_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int1_gpios, { 0 }),	\
1283 	.int2_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int2_gpios, { 0 }),	\
1284 	.drdy_pulsed = DT_INST_PROP(inst, drdy_pulsed),                 \
1285 	.drdy_pin = DT_INST_PROP(inst, drdy_pin)
1286 #else
1287 #define LSM6DSV16X_CFG_IRQ(inst)
1288 #endif /* CONFIG_LSM6DSV16X_TRIGGER */
1289 
1290 #define LSM6DSV16X_CONFIG_COMMON(inst)						\
1291 	.accel_odr = DT_INST_PROP(inst, accel_odr),				\
1292 	.accel_range = DT_INST_PROP(inst, accel_range),				\
1293 	.gyro_odr = DT_INST_PROP(inst, gyro_odr),				\
1294 	.gyro_range = DT_INST_PROP(inst, gyro_range),				\
1295 	IF_ENABLED(CONFIG_LSM6DSV16X_STREAM,					\
1296 		   (.fifo_wtm = DT_INST_PROP(inst, fifo_watermark),		\
1297 		    .accel_batch  = DT_INST_PROP(inst, accel_fifo_batch_rate),	\
1298 		    .gyro_batch  = DT_INST_PROP(inst, gyro_fifo_batch_rate),	\
1299 		    .sflp_odr  = DT_INST_PROP(inst, sflp_odr),			\
1300 		    .sflp_fifo_en  = DT_INST_PROP(inst, sflp_fifo_enable),	\
1301 		    .temp_batch  = DT_INST_PROP(inst, temp_fifo_batch_rate),))	\
1302 	IF_ENABLED(UTIL_OR(DT_INST_NODE_HAS_PROP(inst, int1_gpios),		\
1303 			   DT_INST_NODE_HAS_PROP(inst, int2_gpios)),		\
1304 		   (LSM6DSV16X_CFG_IRQ(inst)))
1305 
1306 /*
1307  * Instantiation macros used when a device is on a SPI bus.
1308  */
1309 
1310 #define LSM6DSV16X_SPI_OP  (SPI_WORD_SET(8) |				\
1311 			 SPI_OP_MODE_MASTER |				\
1312 			 SPI_MODE_CPOL |				\
1313 			 SPI_MODE_CPHA)					\
1314 
1315 #define LSM6DSV16X_SPI_RTIO_DEFINE(inst)				\
1316 	SPI_DT_IODEV_DEFINE(lsm6dsv16x_iodev_##inst,			\
1317 		DT_DRV_INST(inst), LSM6DSV16X_SPI_OP, 0U);		\
1318 	RTIO_DEFINE(lsm6dsv16x_rtio_ctx_##inst, 4, 4);
1319 
1320 #define LSM6DSV16X_CONFIG_SPI(inst)					\
1321 	{								\
1322 		STMEMSC_CTX_SPI(&lsm6dsv16x_config_##inst.stmemsc_cfg),	\
1323 		.stmemsc_cfg = {					\
1324 			.spi = SPI_DT_SPEC_INST_GET(inst,		\
1325 					   LSM6DSV16X_SPI_OP,		\
1326 					   0),				\
1327 		},							\
1328 		LSM6DSV16X_CONFIG_COMMON(inst)				\
1329 	}
1330 
1331 #define LSM6DSV16X_DEFINE_SPI(inst)					\
1332 	IF_ENABLED(UTIL_AND(CONFIG_LSM6DSV16X_STREAM,			\
1333 			    CONFIG_SPI_RTIO),				\
1334 		   (LSM6DSV16X_SPI_RTIO_DEFINE(inst)));			\
1335 	static struct lsm6dsv16x_data lsm6dsv16x_data_##inst =	{	\
1336 		IF_ENABLED(UTIL_AND(CONFIG_LSM6DSV16X_STREAM,		\
1337 				    CONFIG_SPI_RTIO),			\
1338 			(.rtio_ctx = &lsm6dsv16x_rtio_ctx_##inst,	\
1339 			 .iodev = &lsm6dsv16x_iodev_##inst,		\
1340 			 .bus_type = BUS_SPI,))				\
1341 	};								\
1342 	static const struct lsm6dsv16x_config lsm6dsv16x_config_##inst = \
1343 		LSM6DSV16X_CONFIG_SPI(inst);				\
1344 
1345 /*
1346  * Instantiation macros used when a device is on an I2C bus.
1347  */
1348 
1349 #define LSM6DSV16X_I2C_RTIO_DEFINE(inst)				\
1350 	I2C_DT_IODEV_DEFINE(lsm6dsv16x_iodev_##inst, DT_DRV_INST(inst));\
1351 	RTIO_DEFINE(lsm6dsv16x_rtio_ctx_##inst, 4, 4);
1352 
1353 #define LSM6DSV16X_CONFIG_I2C(inst)					\
1354 	{								\
1355 		STMEMSC_CTX_I2C(&lsm6dsv16x_config_##inst.stmemsc_cfg),	\
1356 		.stmemsc_cfg = {					\
1357 			.i2c = I2C_DT_SPEC_INST_GET(inst),		\
1358 		},							\
1359 		LSM6DSV16X_CONFIG_COMMON(inst)				\
1360 	}
1361 
1362 
1363 #define LSM6DSV16X_DEFINE_I2C(inst)					\
1364 	IF_ENABLED(UTIL_AND(CONFIG_LSM6DSV16X_STREAM,			\
1365 			    CONFIG_I2C_RTIO),				\
1366 		   (LSM6DSV16X_I2C_RTIO_DEFINE(inst)));			\
1367 	static struct lsm6dsv16x_data lsm6dsv16x_data_##inst =	{	\
1368 		IF_ENABLED(UTIL_AND(CONFIG_LSM6DSV16X_STREAM,		\
1369 				    CONFIG_I2C_RTIO),			\
1370 			(.rtio_ctx = &lsm6dsv16x_rtio_ctx_##inst,	\
1371 			 .iodev = &lsm6dsv16x_iodev_##inst,		\
1372 			 .bus_type = BUS_I2C,))				\
1373 	};								\
1374 	static const struct lsm6dsv16x_config lsm6dsv16x_config_##inst = \
1375 		LSM6DSV16X_CONFIG_I2C(inst);				\
1376 
1377 /*
1378  * Instantiation macros used when a device is on an I3C bus.
1379  */
1380 
1381 #define LSM6DSV16X_I3C_RTIO_DEFINE(inst)                                       \
1382 	I3C_DT_IODEV_DEFINE(lsm6dsv16x_i3c_iodev_##inst, DT_DRV_INST(inst));   \
1383 	RTIO_DEFINE(lsm6dsv16x_rtio_ctx_##inst, 4, 4);
1384 
1385 #define LSM6DSV16X_CONFIG_I3C(inst)					            \
1386 	{								            \
1387 		STMEMSC_CTX_I3C(&lsm6dsv16x_config_##inst.stmemsc_cfg),	            \
1388 		.stmemsc_cfg = {					            \
1389 			.i3c = &lsm6dsv16x_data_##inst.i3c_dev,		            \
1390 		},							            \
1391 		.i3c.bus = DEVICE_DT_GET(DT_INST_BUS(inst)),		            \
1392 		.i3c.dev_id = I3C_DEVICE_ID_DT_INST(inst),		            \
1393 		IF_ENABLED(CONFIG_LSM6DSV16X_TRIGGER,                               \
1394 			  (.int_en_i3c = DT_INST_PROP(inst, int_en_i3c),            \
1395 			   .bus_act_sel = DT_INST_ENUM_IDX(inst, bus_act_sel_us),)) \
1396 		LSM6DSV16X_CONFIG_COMMON(inst)				            \
1397 	}
1398 
1399 #define LSM6DSV16X_DEFINE_I3C(inst)					\
1400 	IF_ENABLED(UTIL_AND(CONFIG_LSM6DSV16X_STREAM,			\
1401 			    CONFIG_I3C_RTIO),				\
1402 		   (LSM6DSV16X_I3C_RTIO_DEFINE(inst)));			\
1403 	static struct lsm6dsv16x_data lsm6dsv16x_data_##inst = {	\
1404 		IF_ENABLED(UNTIL_AND(CONFIG_LSM6DSV16X_STREAM,		\
1405 				     CONFIG_I3C_RTIO),			\
1406 			(.rtio_ctx = &lsm6dsv16x_rtio_ctx_##inst,	\
1407 			 .iodev = &lsm6dsv16x_i3c_iodev_##inst,		\
1408 			 .bus_type = BUS_I3C,))				\
1409 	};								\
1410 	static const struct lsm6dsv16x_config lsm6dsv16x_config_##inst = \
1411 		LSM6DSV16X_CONFIG_I3C(inst);				\
1412 
1413 #define LSM6DSV16X_DEFINE_I3C_OR_I2C(inst)				\
1414 	COND_CODE_0(DT_INST_PROP_BY_IDX(inst, reg, 1),			\
1415 		    (LSM6DSV16X_DEFINE_I2C(inst)),			\
1416 		    (LSM6DSV16X_DEFINE_I3C(inst)))
1417 
1418 /*
1419  * Main instantiation macro. Use of COND_CODE_1() selects the right
1420  * bus-specific macro at preprocessor time.
1421  */
1422 
1423 #define LSM6DSV16X_DEFINE(inst)							\
1424 	COND_CODE_1(DT_INST_ON_BUS(inst, spi),					\
1425 		(LSM6DSV16X_DEFINE_SPI(inst)),					\
1426 		(COND_CODE_1(DT_INST_ON_BUS(inst, i3c),				\
1427 			(LSM6DSV16X_DEFINE_I3C_OR_I2C(inst)),			\
1428 			(LSM6DSV16X_DEFINE_I2C(inst)))));			\
1429 	LSM6DSV16X_DEVICE_INIT(inst)
1430 
1431 DT_INST_FOREACH_STATUS_OKAY(LSM6DSV16X_DEFINE)
1432