1 /* lsm6dsl.c - Driver for LSM6DSL accelerometer, gyroscope and
2  * temperature sensor
3  */
4 
5 /*
6  * Copyright (c) 2017 Linaro Limited
7  *
8  * SPDX-License-Identifier: Apache-2.0
9  */
10 
11 #define DT_DRV_COMPAT st_lsm6dsl
12 
13 #include <zephyr/drivers/sensor.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/device.h>
16 #include <zephyr/init.h>
17 #include <string.h>
18 #include <zephyr/sys/byteorder.h>
19 #include <zephyr/sys/__assert.h>
20 #include <zephyr/logging/log.h>
21 #include <zephyr/pm/device.h>
22 
23 #include "lsm6dsl.h"
24 
25 LOG_MODULE_REGISTER(LSM6DSL, CONFIG_SENSOR_LOG_LEVEL);
26 
27 static const uint16_t lsm6dsl_odr_map[] = {0, 12, 26, 52, 104, 208, 416, 833,
28 					1666, 3332, 6664, 1};
29 
30 #if defined(LSM6DSL_ACCEL_ODR_RUNTIME) || defined(LSM6DSL_GYRO_ODR_RUNTIME) ||\
31 	defined(CONFIG_PM_DEVICE)
lsm6dsl_freq_to_odr_val(uint16_t freq)32 static int lsm6dsl_freq_to_odr_val(uint16_t freq)
33 {
34 	size_t i;
35 
36 	for (i = 0; i < ARRAY_SIZE(lsm6dsl_odr_map); i++) {
37 		if (freq == lsm6dsl_odr_map[i]) {
38 			return i;
39 		}
40 	}
41 
42 	return -EINVAL;
43 }
44 #endif
45 
lsm6dsl_odr_to_freq_val(uint16_t odr)46 static int lsm6dsl_odr_to_freq_val(uint16_t odr)
47 {
48 	/* for valid index, return value from map */
49 	if (odr < ARRAY_SIZE(lsm6dsl_odr_map)) {
50 		return lsm6dsl_odr_map[odr];
51 	}
52 
53 	/* invalid index, return the fastest entry (6.66kHz) */
54 	BUILD_ASSERT(ARRAY_SIZE(lsm6dsl_odr_map) > 10);
55 	return lsm6dsl_odr_map[10];
56 }
57 
58 #ifdef LSM6DSL_ACCEL_FS_RUNTIME
59 static const uint16_t lsm6dsl_accel_fs_map[] = {2, 16, 4, 8};
60 static const uint16_t lsm6dsl_accel_fs_sens[] = {1, 8, 2, 4};
61 
lsm6dsl_accel_range_to_fs_val(int32_t range)62 static int lsm6dsl_accel_range_to_fs_val(int32_t range)
63 {
64 	size_t i;
65 
66 	for (i = 0; i < ARRAY_SIZE(lsm6dsl_accel_fs_map); i++) {
67 		if (range == lsm6dsl_accel_fs_map[i]) {
68 			return i;
69 		}
70 	}
71 
72 	return -EINVAL;
73 }
74 #endif
75 
76 #ifdef LSM6DSL_GYRO_FS_RUNTIME
77 static const uint16_t lsm6dsl_gyro_fs_map[] = {250, 500, 1000, 2000, 125};
78 static const uint16_t lsm6dsl_gyro_fs_sens[] = {2, 4, 8, 16, 1};
79 
lsm6dsl_gyro_range_to_fs_val(int32_t range)80 static int lsm6dsl_gyro_range_to_fs_val(int32_t range)
81 {
82 	size_t i;
83 
84 	for (i = 0; i < ARRAY_SIZE(lsm6dsl_gyro_fs_map); i++) {
85 		if (range == lsm6dsl_gyro_fs_map[i]) {
86 			return i;
87 		}
88 	}
89 
90 	return -EINVAL;
91 }
92 #endif
93 
lsm6dsl_reboot(const struct device * dev)94 static inline int lsm6dsl_reboot(const struct device *dev)
95 {
96 	struct lsm6dsl_data *data = dev->data;
97 
98 	if (data->hw_tf->update_reg(dev, LSM6DSL_REG_CTRL3_C,
99 				    LSM6DSL_MASK_CTRL3_C_BOOT,
100 				    1 << LSM6DSL_SHIFT_CTRL3_C_BOOT) < 0) {
101 		return -EIO;
102 	}
103 
104 	/* Wait sensor turn-on time as per datasheet */
105 	k_busy_wait(USEC_PER_MSEC * 35U);
106 
107 	return 0;
108 }
109 
lsm6dsl_accel_set_fs_raw(const struct device * dev,uint8_t fs)110 static int lsm6dsl_accel_set_fs_raw(const struct device *dev, uint8_t fs)
111 {
112 	struct lsm6dsl_data *data = dev->data;
113 
114 	if (data->hw_tf->update_reg(dev,
115 				    LSM6DSL_REG_CTRL1_XL,
116 				    LSM6DSL_MASK_CTRL1_XL_FS_XL,
117 				    fs << LSM6DSL_SHIFT_CTRL1_XL_FS_XL) < 0) {
118 		return -EIO;
119 	}
120 
121 	return 0;
122 }
123 
lsm6dsl_accel_set_odr_raw(const struct device * dev,uint8_t odr)124 static int lsm6dsl_accel_set_odr_raw(const struct device *dev, uint8_t odr)
125 {
126 	struct lsm6dsl_data *data = dev->data;
127 
128 	if (data->hw_tf->update_reg(dev,
129 				    LSM6DSL_REG_CTRL1_XL,
130 				    LSM6DSL_MASK_CTRL1_XL_ODR_XL,
131 				    odr << LSM6DSL_SHIFT_CTRL1_XL_ODR_XL) < 0) {
132 		return -EIO;
133 	}
134 
135 	data->accel_freq = lsm6dsl_odr_to_freq_val(odr);
136 
137 	return 0;
138 }
139 
lsm6dsl_gyro_set_fs_raw(const struct device * dev,uint8_t fs)140 static int lsm6dsl_gyro_set_fs_raw(const struct device *dev, uint8_t fs)
141 {
142 	struct lsm6dsl_data *data = dev->data;
143 
144 	if (fs == GYRO_FULLSCALE_125) {
145 		if (data->hw_tf->update_reg(dev,
146 					LSM6DSL_REG_CTRL2_G,
147 					LSM6DSL_MASK_CTRL2_FS125 | LSM6DSL_MASK_CTRL2_G_FS_G,
148 					1 << LSM6DSL_SHIFT_CTRL2_FS125) < 0) {
149 			return -EIO;
150 		}
151 	} else {
152 		if (data->hw_tf->update_reg(dev,
153 					LSM6DSL_REG_CTRL2_G,
154 					LSM6DSL_MASK_CTRL2_FS125 | LSM6DSL_MASK_CTRL2_G_FS_G,
155 					fs << LSM6DSL_SHIFT_CTRL2_G_FS_G) < 0) {
156 			return -EIO;
157 		}
158 	}
159 
160 	return 0;
161 }
162 
lsm6dsl_gyro_set_odr_raw(const struct device * dev,uint8_t odr)163 static int lsm6dsl_gyro_set_odr_raw(const struct device *dev, uint8_t odr)
164 {
165 	struct lsm6dsl_data *data = dev->data;
166 
167 	if (data->hw_tf->update_reg(dev,
168 				    LSM6DSL_REG_CTRL2_G,
169 				    LSM6DSL_MASK_CTRL2_G_ODR_G,
170 				    odr << LSM6DSL_SHIFT_CTRL2_G_ODR_G) < 0) {
171 		return -EIO;
172 	}
173 
174 	data->gyro_freq = lsm6dsl_odr_to_freq_val(odr);
175 
176 	return 0;
177 }
178 
179 #ifdef LSM6DSL_ACCEL_ODR_RUNTIME
lsm6dsl_accel_odr_set(const struct device * dev,uint16_t freq)180 static int lsm6dsl_accel_odr_set(const struct device *dev, uint16_t freq)
181 {
182 	int odr;
183 
184 	odr = lsm6dsl_freq_to_odr_val(freq);
185 	if (odr < 0) {
186 		return odr;
187 	}
188 
189 	if (lsm6dsl_accel_set_odr_raw(dev, odr) < 0) {
190 		LOG_DBG("failed to set accelerometer sampling rate");
191 		return -EIO;
192 	}
193 
194 	return 0;
195 }
196 #endif
197 
198 #ifdef LSM6DSL_ACCEL_FS_RUNTIME
lsm6dsl_accel_range_set(const struct device * dev,int32_t range)199 static int lsm6dsl_accel_range_set(const struct device *dev, int32_t range)
200 {
201 	int fs;
202 	struct lsm6dsl_data *data = dev->data;
203 
204 	fs = lsm6dsl_accel_range_to_fs_val(range);
205 	if (fs < 0) {
206 		return fs;
207 	}
208 
209 	if (lsm6dsl_accel_set_fs_raw(dev, fs) < 0) {
210 		LOG_DBG("failed to set accelerometer full-scale");
211 		return -EIO;
212 	}
213 
214 	data->accel_sensitivity = (float)(lsm6dsl_accel_fs_sens[fs]
215 						    * SENSI_GRAIN_XL);
216 	return 0;
217 }
218 #endif
219 
lsm6dsl_accel_config(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)220 static int lsm6dsl_accel_config(const struct device *dev,
221 				enum sensor_channel chan,
222 				enum sensor_attribute attr,
223 				const struct sensor_value *val)
224 {
225 	switch (attr) {
226 #ifdef LSM6DSL_ACCEL_FS_RUNTIME
227 	case SENSOR_ATTR_FULL_SCALE:
228 		return lsm6dsl_accel_range_set(dev, sensor_ms2_to_g(val));
229 #endif
230 #ifdef LSM6DSL_ACCEL_ODR_RUNTIME
231 	case SENSOR_ATTR_SAMPLING_FREQUENCY:
232 		return lsm6dsl_accel_odr_set(dev, val->val1);
233 #endif
234 	default:
235 		LOG_DBG("Accel attribute not supported.");
236 		return -ENOTSUP;
237 	}
238 
239 	return 0;
240 }
241 
242 #ifdef LSM6DSL_GYRO_ODR_RUNTIME
lsm6dsl_gyro_odr_set(const struct device * dev,uint16_t freq)243 static int lsm6dsl_gyro_odr_set(const struct device *dev, uint16_t freq)
244 {
245 	int odr;
246 
247 	odr = lsm6dsl_freq_to_odr_val(freq);
248 	if (odr < 0) {
249 		return odr;
250 	}
251 
252 	if (lsm6dsl_gyro_set_odr_raw(dev, odr) < 0) {
253 		LOG_DBG("failed to set gyroscope sampling rate");
254 		return -EIO;
255 	}
256 
257 	return 0;
258 }
259 #endif
260 
261 #ifdef LSM6DSL_GYRO_FS_RUNTIME
lsm6dsl_gyro_range_set(const struct device * dev,int32_t range)262 static int lsm6dsl_gyro_range_set(const struct device *dev, int32_t range)
263 {
264 	int fs;
265 	struct lsm6dsl_data *data = dev->data;
266 
267 	fs = lsm6dsl_gyro_range_to_fs_val(range);
268 	if (fs < 0) {
269 		return fs;
270 	}
271 
272 	if (lsm6dsl_gyro_set_fs_raw(dev, fs) < 0) {
273 		LOG_DBG("failed to set gyroscope full-scale");
274 		return -EIO;
275 	}
276 
277 	data->gyro_sensitivity = (float)(lsm6dsl_gyro_fs_sens[fs]
278 						    * SENSI_GRAIN_G);
279 	return 0;
280 }
281 #endif
282 
lsm6dsl_gyro_config(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)283 static int lsm6dsl_gyro_config(const struct device *dev,
284 			       enum sensor_channel chan,
285 			       enum sensor_attribute attr,
286 			       const struct sensor_value *val)
287 {
288 	switch (attr) {
289 #ifdef LSM6DSL_GYRO_FS_RUNTIME
290 	case SENSOR_ATTR_FULL_SCALE:
291 		return lsm6dsl_gyro_range_set(dev, sensor_rad_to_degrees(val));
292 #endif
293 #ifdef LSM6DSL_GYRO_ODR_RUNTIME
294 	case SENSOR_ATTR_SAMPLING_FREQUENCY:
295 		return lsm6dsl_gyro_odr_set(dev, val->val1);
296 #endif
297 	default:
298 		LOG_DBG("Gyro attribute not supported.");
299 		return -ENOTSUP;
300 	}
301 
302 	return 0;
303 }
304 
lsm6dsl_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)305 static int lsm6dsl_attr_set(const struct device *dev,
306 			    enum sensor_channel chan,
307 			    enum sensor_attribute attr,
308 			    const struct sensor_value *val)
309 {
310 	switch (chan) {
311 	case SENSOR_CHAN_ACCEL_XYZ:
312 		return lsm6dsl_accel_config(dev, chan, attr, val);
313 	case SENSOR_CHAN_GYRO_XYZ:
314 		return lsm6dsl_gyro_config(dev, chan, attr, val);
315 	default:
316 		LOG_WRN("attr_set() not supported on this channel.");
317 		return -ENOTSUP;
318 	}
319 
320 	return 0;
321 }
322 
lsm6dsl_sample_fetch_accel(const struct device * dev)323 static int lsm6dsl_sample_fetch_accel(const struct device *dev)
324 {
325 	struct lsm6dsl_data *data = dev->data;
326 	uint8_t buf[6];
327 
328 	if (data->hw_tf->read_data(dev, LSM6DSL_REG_OUTX_L_XL,
329 				   buf, sizeof(buf)) < 0) {
330 		LOG_DBG("failed to read sample");
331 		return -EIO;
332 	}
333 
334 	data->accel_sample_x = (int16_t)((uint16_t)(buf[0]) |
335 				((uint16_t)(buf[1]) << 8));
336 	data->accel_sample_y = (int16_t)((uint16_t)(buf[2]) |
337 				((uint16_t)(buf[3]) << 8));
338 	data->accel_sample_z = (int16_t)((uint16_t)(buf[4]) |
339 				((uint16_t)(buf[5]) << 8));
340 
341 	return 0;
342 }
343 
lsm6dsl_sample_fetch_gyro(const struct device * dev)344 static int lsm6dsl_sample_fetch_gyro(const struct device *dev)
345 {
346 	struct lsm6dsl_data *data = dev->data;
347 	uint8_t buf[6];
348 
349 	if (data->hw_tf->read_data(dev, LSM6DSL_REG_OUTX_L_G,
350 				   buf, sizeof(buf)) < 0) {
351 		LOG_DBG("failed to read sample");
352 		return -EIO;
353 	}
354 
355 	data->gyro_sample_x = (int16_t)((uint16_t)(buf[0]) |
356 				((uint16_t)(buf[1]) << 8));
357 	data->gyro_sample_y = (int16_t)((uint16_t)(buf[2]) |
358 				((uint16_t)(buf[3]) << 8));
359 	data->gyro_sample_z = (int16_t)((uint16_t)(buf[4]) |
360 				((uint16_t)(buf[5]) << 8));
361 
362 	return 0;
363 }
364 
365 #if defined(CONFIG_LSM6DSL_ENABLE_TEMP)
lsm6dsl_sample_fetch_temp(const struct device * dev)366 static int lsm6dsl_sample_fetch_temp(const struct device *dev)
367 {
368 	struct lsm6dsl_data *data = dev->data;
369 	uint8_t buf[2];
370 
371 	if (data->hw_tf->read_data(dev, LSM6DSL_REG_OUT_TEMP_L,
372 				   buf, sizeof(buf)) < 0) {
373 		LOG_DBG("failed to read sample");
374 		return -EIO;
375 	}
376 
377 	data->temp_sample = (int16_t)((uint16_t)(buf[0]) |
378 				((uint16_t)(buf[1]) << 8));
379 
380 	return 0;
381 }
382 #endif
383 
384 #if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL) || defined(CONFIG_LSM6DSL_EXT0_LIS3MDL)
lsm6dsl_sample_fetch_magn(const struct device * dev)385 static int lsm6dsl_sample_fetch_magn(const struct device *dev)
386 {
387 	struct lsm6dsl_data *data = dev->data;
388 	uint8_t buf[6];
389 
390 	if (lsm6dsl_shub_read_external_chip(dev, buf, sizeof(buf)) < 0) {
391 		LOG_DBG("failed to read ext mag sample");
392 		return -EIO;
393 	}
394 
395 	data->magn_sample_x = (int16_t)((uint16_t)(buf[0]) |
396 				((uint16_t)(buf[1]) << 8));
397 	data->magn_sample_y = (int16_t)((uint16_t)(buf[2]) |
398 				((uint16_t)(buf[3]) << 8));
399 	data->magn_sample_z = (int16_t)((uint16_t)(buf[4]) |
400 				((uint16_t)(buf[5]) << 8));
401 
402 	return 0;
403 }
404 #endif
405 #if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
lsm6dsl_sample_fetch_press(const struct device * dev)406 static int lsm6dsl_sample_fetch_press(const struct device *dev)
407 {
408 	struct lsm6dsl_data *data = dev->data;
409 	uint8_t buf[5];
410 
411 	if (lsm6dsl_shub_read_external_chip(dev, buf, sizeof(buf)) < 0) {
412 		LOG_DBG("failed to read ext press sample");
413 		return -EIO;
414 	}
415 
416 	data->sample_press = (int32_t)((uint32_t)(buf[0]) |
417 				     ((uint32_t)(buf[1]) << 8) |
418 				     ((uint32_t)(buf[2]) << 16));
419 	data->sample_temp = (int16_t)((uint16_t)(buf[3]) |
420 				     ((uint16_t)(buf[4]) << 8));
421 
422 	return 0;
423 }
424 #endif
425 
lsm6dsl_sample_fetch(const struct device * dev,enum sensor_channel chan)426 static int lsm6dsl_sample_fetch(const struct device *dev,
427 				enum sensor_channel chan)
428 {
429 	switch (chan) {
430 	case SENSOR_CHAN_ACCEL_XYZ:
431 		lsm6dsl_sample_fetch_accel(dev);
432 		break;
433 	case SENSOR_CHAN_GYRO_XYZ:
434 		lsm6dsl_sample_fetch_gyro(dev);
435 		break;
436 #if defined(CONFIG_LSM6DSL_ENABLE_TEMP)
437 	case SENSOR_CHAN_DIE_TEMP:
438 		lsm6dsl_sample_fetch_temp(dev);
439 		break;
440 #endif
441 #if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL) || defined(CONFIG_LSM6DSL_EXT0_LIS3MDL)
442 	case SENSOR_CHAN_MAGN_XYZ:
443 		lsm6dsl_sample_fetch_magn(dev);
444 		break;
445 #endif
446 #if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
447 	case SENSOR_CHAN_AMBIENT_TEMP:
448 	case SENSOR_CHAN_PRESS:
449 		lsm6dsl_sample_fetch_press(dev);
450 		break;
451 #endif
452 	case SENSOR_CHAN_ALL:
453 		lsm6dsl_sample_fetch_accel(dev);
454 		lsm6dsl_sample_fetch_gyro(dev);
455 #if defined(CONFIG_LSM6DSL_ENABLE_TEMP)
456 		lsm6dsl_sample_fetch_temp(dev);
457 #endif
458 #if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL) || defined(CONFIG_LSM6DSL_EXT0_LIS3MDL)
459 		lsm6dsl_sample_fetch_magn(dev);
460 #endif
461 #if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
462 		lsm6dsl_sample_fetch_press(dev);
463 #endif
464 		break;
465 	default:
466 		return -ENOTSUP;
467 	}
468 
469 	return 0;
470 }
471 
lsm6dsl_accel_convert(struct sensor_value * val,int raw_val,float sensitivity)472 static inline void lsm6dsl_accel_convert(struct sensor_value *val, int raw_val,
473 					 float sensitivity)
474 {
475 	double dval;
476 
477 	/* Sensitivity is exposed in mg/LSB */
478 	/* Convert to m/s^2 */
479 	dval = (double)(raw_val) * (double)sensitivity * SENSOR_G_DOUBLE / 1000;
480 	val->val1 = (int32_t)dval;
481 	val->val2 = (((int32_t)(dval * 1000)) % 1000) * 1000;
482 
483 }
484 
lsm6dsl_accel_get_channel(enum sensor_channel chan,struct sensor_value * val,struct lsm6dsl_data * data,float sensitivity)485 static inline int lsm6dsl_accel_get_channel(enum sensor_channel chan,
486 					    struct sensor_value *val,
487 					    struct lsm6dsl_data *data,
488 					    float sensitivity)
489 {
490 	switch (chan) {
491 	case SENSOR_CHAN_ACCEL_X:
492 		lsm6dsl_accel_convert(val, data->accel_sample_x, sensitivity);
493 		break;
494 	case SENSOR_CHAN_ACCEL_Y:
495 		lsm6dsl_accel_convert(val, data->accel_sample_y, sensitivity);
496 		break;
497 	case SENSOR_CHAN_ACCEL_Z:
498 		lsm6dsl_accel_convert(val, data->accel_sample_z, sensitivity);
499 		break;
500 	case SENSOR_CHAN_ACCEL_XYZ:
501 		lsm6dsl_accel_convert(val, data->accel_sample_x, sensitivity);
502 		lsm6dsl_accel_convert(val + 1, data->accel_sample_y,
503 				      sensitivity);
504 		lsm6dsl_accel_convert(val + 2, data->accel_sample_z,
505 				      sensitivity);
506 		break;
507 	default:
508 		return -ENOTSUP;
509 	}
510 
511 	return 0;
512 }
513 
lsm6dsl_accel_channel_get(enum sensor_channel chan,struct sensor_value * val,struct lsm6dsl_data * data)514 static int lsm6dsl_accel_channel_get(enum sensor_channel chan,
515 				     struct sensor_value *val,
516 				     struct lsm6dsl_data *data)
517 {
518 	return lsm6dsl_accel_get_channel(chan, val, data,
519 					data->accel_sensitivity);
520 }
521 
lsm6dsl_gyro_convert(struct sensor_value * val,int raw_val,float sensitivity)522 static inline void lsm6dsl_gyro_convert(struct sensor_value *val, int raw_val,
523 					float sensitivity)
524 {
525 	double dval;
526 
527 	/* Sensitivity is exposed in mdps/LSB */
528 	/* Convert to rad/s */
529 	dval = (double)(raw_val * (double)sensitivity * SENSOR_DEG2RAD_DOUBLE / 1000);
530 	val->val1 = (int32_t)dval;
531 	val->val2 = (((int32_t)(dval * 1000)) % 1000) * 1000;
532 }
533 
lsm6dsl_gyro_get_channel(enum sensor_channel chan,struct sensor_value * val,struct lsm6dsl_data * data,float sensitivity)534 static inline int lsm6dsl_gyro_get_channel(enum sensor_channel chan,
535 					   struct sensor_value *val,
536 					   struct lsm6dsl_data *data,
537 					   float sensitivity)
538 {
539 	switch (chan) {
540 	case SENSOR_CHAN_GYRO_X:
541 		lsm6dsl_gyro_convert(val, data->gyro_sample_x, sensitivity);
542 		break;
543 	case SENSOR_CHAN_GYRO_Y:
544 		lsm6dsl_gyro_convert(val, data->gyro_sample_y, sensitivity);
545 		break;
546 	case SENSOR_CHAN_GYRO_Z:
547 		lsm6dsl_gyro_convert(val, data->gyro_sample_z, sensitivity);
548 		break;
549 	case SENSOR_CHAN_GYRO_XYZ:
550 		lsm6dsl_gyro_convert(val, data->gyro_sample_x, sensitivity);
551 		lsm6dsl_gyro_convert(val + 1, data->gyro_sample_y, sensitivity);
552 		lsm6dsl_gyro_convert(val + 2, data->gyro_sample_z, sensitivity);
553 		break;
554 	default:
555 		return -ENOTSUP;
556 	}
557 
558 	return 0;
559 }
560 
lsm6dsl_gyro_channel_get(enum sensor_channel chan,struct sensor_value * val,struct lsm6dsl_data * data)561 static int lsm6dsl_gyro_channel_get(enum sensor_channel chan,
562 				    struct sensor_value *val,
563 				    struct lsm6dsl_data *data)
564 {
565 	return lsm6dsl_gyro_get_channel(chan, val, data,
566 					data->gyro_sensitivity);
567 }
568 
569 #if defined(CONFIG_LSM6DSL_ENABLE_TEMP)
lsm6dsl_gyro_channel_get_temp(struct sensor_value * val,struct lsm6dsl_data * data)570 static void lsm6dsl_gyro_channel_get_temp(struct sensor_value *val,
571 					  struct lsm6dsl_data *data)
572 {
573 	/* val = temp_sample / 256 + 25 */
574 	val->val1 = data->temp_sample / 256 + 25;
575 	val->val2 = (data->temp_sample % 256) * (1000000 / 256);
576 }
577 #endif
578 
579 #if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL) || defined(CONFIG_LSM6DSL_EXT0_LIS3MDL)
lsm6dsl_magn_convert(struct sensor_value * val,int raw_val,float sensitivity)580 static inline void lsm6dsl_magn_convert(struct sensor_value *val, int raw_val,
581 					float sensitivity)
582 {
583 	double dval;
584 
585 	/* Sensitivity is exposed in mgauss/LSB */
586 	dval = (double)(raw_val * sensitivity);
587 	val->val1 = (int32_t)dval / 1000000;
588 	val->val2 = (int32_t)dval % 1000000;
589 }
590 
lsm6dsl_magn_get_channel(enum sensor_channel chan,struct sensor_value * val,struct lsm6dsl_data * data)591 static inline int lsm6dsl_magn_get_channel(enum sensor_channel chan,
592 					   struct sensor_value *val,
593 					   struct lsm6dsl_data *data)
594 {
595 	switch (chan) {
596 	case SENSOR_CHAN_MAGN_X:
597 		lsm6dsl_magn_convert(val,
598 				     data->magn_sample_x,
599 				     data->magn_sensitivity);
600 		break;
601 	case SENSOR_CHAN_MAGN_Y:
602 		lsm6dsl_magn_convert(val,
603 				     data->magn_sample_y,
604 				     data->magn_sensitivity);
605 		break;
606 	case SENSOR_CHAN_MAGN_Z:
607 		lsm6dsl_magn_convert(val,
608 				     data->magn_sample_z,
609 				     data->magn_sensitivity);
610 		break;
611 	case SENSOR_CHAN_MAGN_XYZ:
612 		lsm6dsl_magn_convert(val,
613 				     data->magn_sample_x,
614 				     data->magn_sensitivity);
615 		lsm6dsl_magn_convert(val + 1,
616 				     data->magn_sample_y,
617 				     data->magn_sensitivity);
618 		lsm6dsl_magn_convert(val + 2,
619 				     data->magn_sample_z,
620 				     data->magn_sensitivity);
621 		break;
622 	default:
623 		return -ENOTSUP;
624 	}
625 
626 	return 0;
627 }
628 
lsm6dsl_magn_channel_get(enum sensor_channel chan,struct sensor_value * val,struct lsm6dsl_data * data)629 static int lsm6dsl_magn_channel_get(enum sensor_channel chan,
630 				    struct sensor_value *val,
631 				    struct lsm6dsl_data *data)
632 {
633 	return lsm6dsl_magn_get_channel(chan, val, data);
634 }
635 #endif
636 
637 #if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
lps22hb_press_convert(struct sensor_value * val,int32_t raw_val)638 static inline void lps22hb_press_convert(struct sensor_value *val,
639 					 int32_t raw_val)
640 {
641 	/* Pressure sensitivity is 4096 LSB/hPa */
642 	/* Convert raw_val to val in kPa */
643 	val->val1 = (raw_val >> 12) / 10;
644 	val->val2 = (raw_val >> 12) % 10 * 100000 +
645 		(((int32_t)((raw_val) & 0x0FFF) * 100000L) >> 12);
646 }
647 
lps22hb_temp_convert(struct sensor_value * val,int16_t raw_val)648 static inline void lps22hb_temp_convert(struct sensor_value *val,
649 					int16_t raw_val)
650 {
651 	/* Temperature sensitivity is 100 LSB/deg C */
652 	val->val1 = raw_val / 100;
653 	val->val2 = (int32_t)raw_val % 100 * (10000);
654 }
655 #endif
656 
lsm6dsl_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)657 static int lsm6dsl_channel_get(const struct device *dev,
658 			       enum sensor_channel chan,
659 			       struct sensor_value *val)
660 {
661 	struct lsm6dsl_data *data = dev->data;
662 
663 	switch (chan) {
664 	case SENSOR_CHAN_ACCEL_X:
665 	case SENSOR_CHAN_ACCEL_Y:
666 	case SENSOR_CHAN_ACCEL_Z:
667 	case SENSOR_CHAN_ACCEL_XYZ:
668 		lsm6dsl_accel_channel_get(chan, val, data);
669 		break;
670 	case SENSOR_CHAN_GYRO_X:
671 	case SENSOR_CHAN_GYRO_Y:
672 	case SENSOR_CHAN_GYRO_Z:
673 	case SENSOR_CHAN_GYRO_XYZ:
674 		lsm6dsl_gyro_channel_get(chan, val, data);
675 		break;
676 #if defined(CONFIG_LSM6DSL_ENABLE_TEMP)
677 	case SENSOR_CHAN_DIE_TEMP:
678 		lsm6dsl_gyro_channel_get_temp(val, data);
679 		break;
680 #endif
681 #if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL) || defined(CONFIG_LSM6DSL_EXT0_LIS3MDL)
682 	case SENSOR_CHAN_MAGN_X:
683 	case SENSOR_CHAN_MAGN_Y:
684 	case SENSOR_CHAN_MAGN_Z:
685 	case SENSOR_CHAN_MAGN_XYZ:
686 		lsm6dsl_magn_channel_get(chan, val, data);
687 		break;
688 #endif
689 #if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
690 	case SENSOR_CHAN_PRESS:
691 		lps22hb_press_convert(val, data->sample_press);
692 		break;
693 
694 	case SENSOR_CHAN_AMBIENT_TEMP:
695 		lps22hb_temp_convert(val, data->sample_temp);
696 		break;
697 #endif
698 	default:
699 		return -ENOTSUP;
700 	}
701 
702 	return 0;
703 }
704 
705 static const struct sensor_driver_api lsm6dsl_driver_api = {
706 	.attr_set = lsm6dsl_attr_set,
707 #if CONFIG_LSM6DSL_TRIGGER
708 	.trigger_set = lsm6dsl_trigger_set,
709 #endif
710 	.sample_fetch = lsm6dsl_sample_fetch,
711 	.channel_get = lsm6dsl_channel_get,
712 };
713 
lsm6dsl_init_chip(const struct device * dev)714 static int lsm6dsl_init_chip(const struct device *dev)
715 {
716 	struct lsm6dsl_data *data = dev->data;
717 	uint8_t chip_id;
718 
719 	if (lsm6dsl_reboot(dev) < 0) {
720 		LOG_DBG("failed to reboot device");
721 		return -EIO;
722 	}
723 
724 	if (data->hw_tf->read_reg(dev, LSM6DSL_REG_WHO_AM_I, &chip_id) < 0) {
725 		LOG_DBG("failed reading chip id");
726 		return -EIO;
727 	}
728 	if (chip_id != LSM6DSL_VAL_WHO_AM_I) {
729 		LOG_DBG("invalid chip id 0x%x", chip_id);
730 		return -EIO;
731 	}
732 
733 	LOG_DBG("chip id 0x%x", chip_id);
734 
735 	if (lsm6dsl_accel_set_fs_raw(dev,
736 				     LSM6DSL_DEFAULT_ACCEL_FULLSCALE) < 0) {
737 		LOG_DBG("failed to set accelerometer full-scale");
738 		return -EIO;
739 	}
740 	data->accel_sensitivity = LSM6DSL_DEFAULT_ACCEL_SENSITIVITY;
741 
742 	if (lsm6dsl_accel_set_odr_raw(dev, CONFIG_LSM6DSL_ACCEL_ODR) < 0) {
743 		LOG_DBG("failed to set accelerometer sampling rate");
744 		return -EIO;
745 	}
746 
747 	if (lsm6dsl_gyro_set_fs_raw(dev, LSM6DSL_DEFAULT_GYRO_FULLSCALE) < 0) {
748 		LOG_DBG("failed to set gyroscope full-scale");
749 		return -EIO;
750 	}
751 	data->gyro_sensitivity = LSM6DSL_DEFAULT_GYRO_SENSITIVITY;
752 
753 	if (lsm6dsl_gyro_set_odr_raw(dev, CONFIG_LSM6DSL_GYRO_ODR) < 0) {
754 		LOG_DBG("failed to set gyroscope sampling rate");
755 		return -EIO;
756 	}
757 
758 	if (data->hw_tf->update_reg(dev,
759 				LSM6DSL_REG_FIFO_CTRL5,
760 				LSM6DSL_MASK_FIFO_CTRL5_FIFO_MODE,
761 				0 << LSM6DSL_SHIFT_FIFO_CTRL5_FIFO_MODE) < 0) {
762 		LOG_DBG("failed to set FIFO mode");
763 		return -EIO;
764 	}
765 
766 	if (data->hw_tf->update_reg(dev,
767 				    LSM6DSL_REG_CTRL3_C,
768 				    LSM6DSL_MASK_CTRL3_C_BDU |
769 				    LSM6DSL_MASK_CTRL3_C_BLE |
770 				    LSM6DSL_MASK_CTRL3_C_IF_INC,
771 				    (1 << LSM6DSL_SHIFT_CTRL3_C_BDU) |
772 				    (0 << LSM6DSL_SHIFT_CTRL3_C_BLE) |
773 				    (1 << LSM6DSL_SHIFT_CTRL3_C_IF_INC)) < 0) {
774 		LOG_DBG("failed to set BDU, BLE and burst");
775 		return -EIO;
776 	}
777 
778 	if (data->hw_tf->update_reg(dev,
779 				    LSM6DSL_REG_CTRL6_C,
780 				    LSM6DSL_MASK_CTRL6_C_XL_HM_MODE,
781 				    (1 << LSM6DSL_SHIFT_CTRL6_C_XL_HM_MODE)) < 0) {
782 		LOG_DBG("failed to disable accelerometer high performance mode");
783 		return -EIO;
784 	}
785 
786 	if (data->hw_tf->update_reg(dev,
787 				    LSM6DSL_REG_CTRL7_G,
788 				    LSM6DSL_MASK_CTRL7_G_HM_MODE,
789 				    (1 << LSM6DSL_SHIFT_CTRL7_G_HM_MODE)) < 0) {
790 		LOG_DBG("failed to disable gyroscope high performance mode");
791 		return -EIO;
792 	}
793 
794 	return 0;
795 }
796 
lsm6dsl_init(const struct device * dev)797 static int lsm6dsl_init(const struct device *dev)
798 {
799 	int ret;
800 	const struct lsm6dsl_config * const config = dev->config;
801 
802 	ret = config->bus_init(dev);
803 	if (ret < 0) {
804 		LOG_ERR("Failed to initialize sensor bus");
805 		return ret;
806 	}
807 
808 	ret = lsm6dsl_init_chip(dev);
809 	if (ret < 0) {
810 		LOG_ERR("Failed to initialize chip");
811 		return ret;
812 	}
813 
814 #ifdef CONFIG_LSM6DSL_TRIGGER
815 	ret = lsm6dsl_init_interrupt(dev);
816 	if (ret < 0) {
817 		LOG_ERR("Failed to initialize interrupt.");
818 		return ret;
819 	}
820 #endif
821 
822 #ifdef CONFIG_LSM6DSL_SENSORHUB
823 	ret = lsm6dsl_shub_init_external_chip(dev);
824 	if (ret < 0) {
825 		LOG_ERR("Failed to initialize external chip");
826 		return ret;
827 	}
828 #endif
829 
830 	return 0;
831 }
832 
833 #ifdef CONFIG_PM_DEVICE
lsm6dsl_pm_action(const struct device * dev,enum pm_device_action action)834 static int lsm6dsl_pm_action(const struct device *dev,
835 			     enum pm_device_action action)
836 {
837 	struct lsm6dsl_data *data = dev->data;
838 	int ret = -EIO;
839 	uint8_t accel_odr = 0;
840 	uint8_t gyro_odr = 0;
841 
842 	switch (action) {
843 	case PM_DEVICE_ACTION_RESUME:
844 		/* Restore saved ODR values */
845 		accel_odr = lsm6dsl_freq_to_odr_val(data->accel_freq);
846 		ret = lsm6dsl_accel_set_odr_raw(dev, accel_odr);
847 		if (ret < 0) {
848 			LOG_ERR("Failed to resume accelerometer");
849 			break;
850 		}
851 		gyro_odr = lsm6dsl_freq_to_odr_val(data->gyro_freq);
852 		ret = lsm6dsl_gyro_set_odr_raw(dev, gyro_odr);
853 		if (ret < 0) {
854 			LOG_ERR("Failed to resume gyro");
855 			break;
856 		}
857 		break;
858 	case PM_DEVICE_ACTION_SUSPEND:
859 		/*
860 		 * Set accelerometer ODR to power-down. Don't use the direct
861 		 * function to not overwrite the saved value
862 		 */
863 		ret = data->hw_tf->update_reg(dev, LSM6DSL_REG_CTRL1_XL,
864 					      LSM6DSL_MASK_CTRL1_XL_ODR_XL, 0);
865 		if (ret < 0) {
866 			LOG_ERR("Failed to suspend accelerometer");
867 			break;
868 		}
869 		/* Set gyro ODR to power-down */
870 		ret = data->hw_tf->update_reg(dev, LSM6DSL_REG_CTRL2_G,
871 					      LSM6DSL_MASK_CTRL2_G_ODR_G, 0);
872 		if (ret < 0) {
873 			LOG_ERR("Failed to suspend gyro");
874 			break;
875 		}
876 
877 		break;
878 	default:
879 		return -ENOTSUP;
880 	}
881 
882 	return ret;
883 }
884 #endif
885 
886 
887 #if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0
888 #warning "LSM6DSL driver enabled without any devices"
889 #endif
890 
891 /*
892  * Device creation macro, shared by LSM6DSL_DEFINE_SPI() and
893  * LSM6DSL_DEFINE_I2C().
894  */
895 
896 #define LSM6DSL_DEVICE_INIT(inst)					\
897 	PM_DEVICE_DT_INST_DEFINE(inst, lsm6dsl_pm_action);		\
898 	SENSOR_DEVICE_DT_INST_DEFINE(inst,				\
899 			    lsm6dsl_init,				\
900 			    PM_DEVICE_DT_INST_GET(inst),		\
901 			    &lsm6dsl_data_##inst,			\
902 			    &lsm6dsl_config_##inst,			\
903 			    POST_KERNEL,				\
904 			    CONFIG_SENSOR_INIT_PRIORITY,		\
905 			    &lsm6dsl_driver_api);
906 
907 /*
908  * Instantiation macros used when a device is on a SPI bus.
909  */
910 
911 #ifdef CONFIG_LSM6DSL_TRIGGER
912 #define LSM6DSL_CFG_IRQ(inst) \
913 		.int_gpio = GPIO_DT_SPEC_INST_GET(inst, irq_gpios),
914 #else
915 #define LSM6DSL_CFG_IRQ(inst)
916 #endif /* CONFIG_LSM6DSL_TRIGGER */
917 
918 #define LSM6DSL_CONFIG_SPI(inst)						\
919 	{									\
920 		.bus_init = lsm6dsl_spi_init,					\
921 		.bus_cfg.spi = SPI_DT_SPEC_INST_GET(inst, SPI_WORD_SET(8) |	\
922 				      SPI_OP_MODE_MASTER |			\
923 				      SPI_MODE_CPOL |				\
924 				      SPI_MODE_CPHA, 0),			\
925 		COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, irq_gpios),		\
926 		(LSM6DSL_CFG_IRQ(inst)), ())					\
927 	}
928 
929 #define LSM6DSL_DEFINE_SPI(inst)					\
930 	static struct lsm6dsl_data lsm6dsl_data_##inst;			\
931 	static const struct lsm6dsl_config lsm6dsl_config_##inst =	\
932 		LSM6DSL_CONFIG_SPI(inst);				\
933 	LSM6DSL_DEVICE_INIT(inst)
934 
935 /*
936  * Instantiation macros used when a device is on an I2C bus.
937  */
938 
939 #define LSM6DSL_CONFIG_I2C(inst)					\
940 	{								\
941 		.bus_init = lsm6dsl_i2c_init,				\
942 		.bus_cfg.i2c = I2C_DT_SPEC_INST_GET(inst),		\
943 		COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, irq_gpios),	\
944 		(LSM6DSL_CFG_IRQ(inst)), ())				\
945 	}
946 
947 #define LSM6DSL_DEFINE_I2C(inst)					\
948 	static struct lsm6dsl_data lsm6dsl_data_##inst;			\
949 	static const struct lsm6dsl_config lsm6dsl_config_##inst =	\
950 		LSM6DSL_CONFIG_I2C(inst);				\
951 	LSM6DSL_DEVICE_INIT(inst)
952 /*
953  * Main instantiation macro. Use of COND_CODE_1() selects the right
954  * bus-specific macro at preprocessor time.
955  */
956 
957 #define LSM6DSL_DEFINE(inst)						\
958 	COND_CODE_1(DT_INST_ON_BUS(inst, spi),				\
959 		    (LSM6DSL_DEFINE_SPI(inst)),				\
960 		    (LSM6DSL_DEFINE_I2C(inst)))
961 
962 DT_INST_FOREACH_STATUS_OKAY(LSM6DSL_DEFINE)
963