1 /* sensor_lsm9ds0_mfd.c - Driver for LSM9DS0 accelerometer, magnetometer
2  * and temperature (MFD) sensor driver
3  */
4 
5 /*
6  * Copyright (c) 2016 Intel Corporation
7  *
8  * SPDX-License-Identifier: Apache-2.0
9  */
10 
11 #define DT_DRV_COMPAT st_lsm9ds0_mfd
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/drivers/i2c.h>
18 #include <zephyr/sys/byteorder.h>
19 #include <zephyr/drivers/gpio.h>
20 #include <zephyr/logging/log.h>
21 
22 #include "lsm9ds0_mfd.h"
23 
24 LOG_MODULE_REGISTER(LSM9DS0_MFD, CONFIG_SENSOR_LOG_LEVEL);
25 
lsm9ds0_mfd_reboot_memory(const struct device * dev)26 static inline int lsm9ds0_mfd_reboot_memory(const struct device *dev)
27 {
28 	const struct lsm9ds0_mfd_config *config = dev->config;
29 
30 	if (i2c_reg_update_byte_dt(&config->i2c, LSM9DS0_MFD_REG_CTRL_REG0_XM,
31 				   LSM9DS0_MFD_MASK_CTRL_REG0_XM_BOOT,
32 				   1 << LSM9DS0_MFD_SHIFT_CTRL_REG0_XM_BOOT) < 0) {
33 		return -EIO;
34 	}
35 
36 	k_busy_wait(USEC_PER_MSEC * 50U);
37 
38 	return 0;
39 }
40 
41 #if !defined(LSM9DS0_MFD_ACCEL_DISABLED)
lsm9ds0_mfd_accel_set_odr_raw(const struct device * dev,uint8_t odr)42 static inline int lsm9ds0_mfd_accel_set_odr_raw(const struct device *dev,
43 						uint8_t odr)
44 {
45 	const struct lsm9ds0_mfd_config *config = dev->config;
46 
47 	return i2c_reg_update_byte_dt(&config->i2c, LSM9DS0_MFD_REG_CTRL_REG1_XM,
48 				      LSM9DS0_MFD_MASK_CTRL_REG1_XM_AODR,
49 				      odr << LSM9DS0_MFD_SHIFT_CTRL_REG1_XM_AODR);
50 }
51 
52 #if defined(CONFIG_LSM9DS0_MFD_ACCEL_SAMPLING_RATE_RUNTIME)
53 static const struct {
54 	int freq_int;
55 	int freq_micro;
56 } lsm9ds0_mfd_accel_odr_map[] = { {0, 0},
57 				  {3, 125000},
58 				  {6, 250000},
59 				  {12, 500000},
60 				  {25, 0},
61 				  {50, 0},
62 				  {100, 0},
63 				  {200, 0},
64 				  {400, 0},
65 				  {800, 0},
66 				  {1600, 0} };
67 
lsm9ds0_mfd_accel_set_odr(const struct device * dev,const struct sensor_value * val)68 static int lsm9ds0_mfd_accel_set_odr(const struct device *dev,
69 				     const struct sensor_value *val)
70 {
71 	uint8_t i;
72 
73 	for (i = 0U; i < ARRAY_SIZE(lsm9ds0_mfd_accel_odr_map); ++i) {
74 		if (val->val1 < lsm9ds0_mfd_accel_odr_map[i].freq_int ||
75 		    (val->val1 == lsm9ds0_mfd_accel_odr_map[i].freq_int &&
76 		     val->val2 <= lsm9ds0_mfd_accel_odr_map[i].freq_micro)) {
77 			return lsm9ds0_mfd_accel_set_odr_raw(dev, i);
78 		}
79 	}
80 
81 	return -ENOTSUP;
82 }
83 #endif
84 
lsm9ds0_mfd_accel_set_fs_raw(const struct device * dev,uint8_t fs)85 static inline int lsm9ds0_mfd_accel_set_fs_raw(const struct device *dev,
86 					       uint8_t fs)
87 {
88 	const struct lsm9ds0_mfd_config *config = dev->config;
89 
90 	if (i2c_reg_update_byte_dt(&config->i2c, LSM9DS0_MFD_REG_CTRL_REG2_XM,
91 				   LSM9DS0_MFD_MASK_CTRL_REG2_XM_AFS,
92 				   fs << LSM9DS0_MFD_SHIFT_CTRL_REG2_XM_AFS) < 0) {
93 		return -EIO;
94 	}
95 
96 #if defined(CONFIG_LSM9DS0_MFD_ACCEL_FULL_SCALE_RUNTIME)
97 	data->accel_fs = fs;
98 #endif
99 
100 	return 0;
101 }
102 
103 #if defined(CONFIG_LSM9DS0_MFD_ACCEL_FULL_SCALE_RUNTIME)
104 static const struct {
105 	int fs;
106 } lsm9ds0_mfd_accel_fs_map[] = { {2},
107 				 {4},
108 				 {6},
109 				 {8},
110 				 {16} };
111 
lsm9ds0_mfd_accel_set_fs(const struct device * dev,int val)112 static int lsm9ds0_mfd_accel_set_fs(const struct device *dev, int val)
113 {
114 	uint8_t i;
115 
116 	for (i = 0U; i < ARRAY_SIZE(lsm9ds0_mfd_accel_fs_map); ++i) {
117 		if (val <= lsm9ds0_mfd_accel_fs_map[i].fs) {
118 			return lsm9ds0_mfd_accel_set_fs_raw(dev, i);
119 		}
120 	}
121 
122 	return -ENOTSUP;
123 }
124 #endif
125 #endif
126 
127 #if !defined(LSM9DS0_MFD_MAGN_DISABLED)
lsm9ds0_mfd_magn_set_odr_raw(const struct device * dev,uint8_t odr)128 static inline int lsm9ds0_mfd_magn_set_odr_raw(const struct device *dev,
129 					       uint8_t odr)
130 {
131 	const struct lsm9ds0_mfd_config *config = dev->config;
132 
133 	return i2c_reg_update_byte_dt(&config->i2c, LSM9DS0_MFD_REG_CTRL_REG5_XM,
134 				      LSM9DS0_MFD_MASK_CTRL_REG5_XM_M_ODR,
135 				      odr << LSM9DS0_MFD_SHIFT_CTRL_REG5_XM_M_ODR);
136 }
137 
138 #if defined(CONFIG_LSM9DS0_MFD_MAGN_SAMPLING_RATE_RUNTIME)
139 static const struct {
140 	int freq_int;
141 	int freq_micro;
142 } lsm9ds0_mfd_magn_odr_map[] = { {0, 0},
143 				 {3, 125000},
144 				 {6, 250000},
145 				 {12, 500000},
146 				 {25, 0},
147 				 {50, 0},
148 				 {100, 0} };
149 
lsm9ds0_mfd_magn_set_odr(const struct device * dev,const struct sensor_value * val)150 static int lsm9ds0_mfd_magn_set_odr(const struct device *dev,
151 				    const struct sensor_value *val)
152 {
153 	uint8_t i;
154 
155 	for (i = 0U; i < ARRAY_SIZE(lsm9ds0_mfd_accel_odr_map); ++i) {
156 		if (val->val1 < lsm9ds0_mfd_accel_odr_map[i].freq_int ||
157 		    (val->val1 == lsm9ds0_mfd_accel_odr_map[i].freq_int &&
158 		     val->val2 <= lsm9ds0_mfd_accel_odr_map[i].freq_micro)) {
159 			return lsm9ds0_mfd_magn_set_odr_raw(dev, i);
160 		}
161 	}
162 
163 	return -ENOTSUP;
164 }
165 #endif
166 
lsm9ds0_mfd_magn_set_fs_raw(const struct device * dev,uint8_t fs)167 static inline int lsm9ds0_mfd_magn_set_fs_raw(const struct device *dev,
168 					      uint8_t fs)
169 {
170 	const struct lsm9ds0_mfd_config *config = dev->config;
171 
172 	if (i2c_reg_update_byte_dt(&config->i2c, LSM9DS0_MFD_REG_CTRL_REG6_XM,
173 				   LSM9DS0_MFD_MASK_CTRL_REG6_XM_MFS,
174 				   fs << LSM9DS0_MFD_SHIFT_CTRL_REG6_XM_MFS) < 0) {
175 		return -EIO;
176 	}
177 
178 #if defined(CONFIG_LSM9DS0_MFD_MAGN_FULL_SCALE_RUNTIME)
179 	data->magn_fs = fs;
180 #endif
181 
182 	return 0;
183 }
184 
185 #if defined(CONFIG_LSM9DS0_MFD_MAGN_FULL_SCALE_RUNTIME)
186 static const struct {
187 	int fs;
188 } lsm9ds0_mfd_magn_fs_map[] = { {2},
189 				{4},
190 				{8},
191 				{12} };
192 
lsm9ds0_mfd_magn_set_fs(const struct device * dev,const struct sensor_value * val)193 static int lsm9ds0_mfd_magn_set_fs(const struct device *dev,
194 				   const struct sensor_value *val)
195 {
196 	uint8_t i;
197 
198 	for (i = 0U; i < ARRAY_SIZE(lsm9ds0_mfd_magn_fs_map); ++i) {
199 		if (val->val1 <= lsm9ds0_mfd_magn_fs_map[i].fs) {
200 			return lsm9ds0_mfd_magn_set_fs_raw(dev, i);
201 		}
202 	}
203 
204 	return -ENOTSUP;
205 }
206 #endif
207 #endif
208 
209 #if !defined(LSM9DS0_MFD_ACCEL_DISABLED)
lsm9ds0_mfd_sample_fetch_accel(const struct device * dev)210 static inline int lsm9ds0_mfd_sample_fetch_accel(const struct device *dev)
211 {
212 	struct lsm9ds0_mfd_data *data = dev->data;
213 	const struct lsm9ds0_mfd_config *config = dev->config;
214 	uint8_t out_l, out_h;
215 
216 #if defined(CONFIG_LSM9DS0_MFD_ACCEL_ENABLE_X)
217 	if (i2c_reg_read_byte_dt(&config->i2c, LSM9DS0_MFD_REG_OUT_X_L_A, &out_l) < 0 ||
218 	    i2c_reg_read_byte_dt(&config->i2c, LSM9DS0_MFD_REG_OUT_X_H_A, &out_h) < 0) {
219 		LOG_DBG("failed to read accel sample (X axis)");
220 		return -EIO;
221 	}
222 
223 	data->sample_accel_x = (int16_t)((uint16_t)(out_l) |
224 			       ((uint16_t)(out_h) << 8));
225 #endif
226 
227 #if defined(CONFIG_LSM9DS0_MFD_ACCEL_ENABLE_Y)
228 	if (i2c_reg_read_byte_dt(&config->i2c, LSM9DS0_MFD_REG_OUT_Y_L_A, &out_l) < 0 ||
229 	    i2c_reg_read_byte_dt(&config->i2c, LSM9DS0_MFD_REG_OUT_Y_H_A, &out_h) < 0) {
230 		LOG_DBG("failed to read accel sample (Y axis)");
231 		return -EIO;
232 	}
233 
234 	data->sample_accel_y = (int16_t)((uint16_t)(out_l) |
235 			       ((uint16_t)(out_h) << 8));
236 #endif
237 
238 #if defined(CONFIG_LSM9DS0_MFD_ACCEL_ENABLE_Z)
239 	if (i2c_reg_read_byte_dt(&config->i2c, LSM9DS0_MFD_REG_OUT_Z_L_A, &out_l) < 0 ||
240 	    i2c_reg_read_byte_dt(&config->i2c, LSM9DS0_MFD_REG_OUT_Z_H_A, &out_h) < 0) {
241 		LOG_DBG("failed to read accel sample (Z axis)");
242 		return -EIO;
243 	}
244 
245 	data->sample_accel_z = (int16_t)((uint16_t)(out_l) |
246 			       ((uint16_t)(out_h) << 8));
247 #endif
248 
249 #if defined(CONFIG_LSM9DS0_MFD_ACCEL_FULL_SCALE_RUNTIME)
250 	data->sample_accel_fs = data->accel_fs;
251 #endif
252 
253 	return 0;
254 }
255 #endif
256 
257 #if !defined(LSM9DS0_MFD_MAGN_DISABLED)
lsm9ds0_mfd_sample_fetch_magn(const struct device * dev)258 static inline int lsm9ds0_mfd_sample_fetch_magn(const struct device *dev)
259 {
260 	struct lsm9ds0_mfd_data *data = dev->data;
261 	const struct lsm9ds0_mfd_config *config = dev->config;
262 	uint8_t out_l, out_h;
263 
264 	if (i2c_reg_read_byte_dt(&config->i2c, LSM9DS0_MFD_REG_OUT_X_L_M, &out_l) < 0 ||
265 	    i2c_reg_read_byte_dt(&config->i2c, LSM9DS0_MFD_REG_OUT_X_H_M, &out_h) < 0) {
266 		LOG_DBG("failed to read magn sample (X axis)");
267 		return -EIO;
268 	}
269 
270 	data->sample_magn_x = (int16_t)((uint16_t)(out_l) |
271 			      ((uint16_t)(out_h) << 8));
272 
273 	if (i2c_reg_read_byte_dt(&config->i2c, LSM9DS0_MFD_REG_OUT_Y_L_M, &out_l) < 0 ||
274 	    i2c_reg_read_byte_dt(&config->i2c, LSM9DS0_MFD_REG_OUT_Y_H_M, &out_h) < 0) {
275 		LOG_DBG("failed to read magn sample (Y axis)");
276 		return -EIO;
277 	}
278 
279 	data->sample_magn_y = (int16_t)((uint16_t)(out_l) |
280 			      ((uint16_t)(out_h) << 8));
281 
282 	if (i2c_reg_read_byte_dt(&config->i2c, LSM9DS0_MFD_REG_OUT_Z_L_M, &out_l) < 0 ||
283 	    i2c_reg_read_byte_dt(&config->i2c, LSM9DS0_MFD_REG_OUT_Z_H_M, &out_h) < 0) {
284 		LOG_DBG("failed to read magn sample (Z axis)");
285 		return -EIO;
286 	}
287 
288 	data->sample_magn_z = (int16_t)((uint16_t)(out_l) |
289 			      ((uint16_t)(out_h) << 8));
290 
291 #if defined(CONFIG_LSM9DS0_MFD_MAGN_FULL_SCALE_RUNTIME)
292 	data->sample_magn_fs = data->magn_fs;
293 #endif
294 
295 	return 0;
296 }
297 #endif
298 
299 #if !defined(LSM9DS0_MFD_TEMP_DISABLED)
lsm9ds0_mfd_sample_fetch_temp(const struct device * dev)300 static inline int lsm9ds0_mfd_sample_fetch_temp(const struct device *dev)
301 {
302 	struct lsm9ds0_mfd_data *data = dev->data;
303 	const struct lsm9ds0_mfd_config *config = dev->config;
304 	uint8_t out_l, out_h;
305 
306 	if (i2c_reg_read_byte_dt(&config->i2c, LSM9DS0_MFD_REG_OUT_TEMP_L_XM, &out_l) < 0 ||
307 	    i2c_reg_read_byte_dt(&config->i2c, LSM9DS0_MFD_REG_OUT_TEMP_H_XM, &out_h) < 0) {
308 		LOG_DBG("failed to read temperature sample\n");
309 		return -EIO;
310 	}
311 
312 	data->sample_temp = (int16_t)((uint16_t)(out_l) |
313 			    ((uint16_t)(out_h) << 8));
314 
315 	return 0;
316 }
317 #endif
318 
lsm9ds0_mfd_sample_fetch_all(const struct device * dev)319 static inline int lsm9ds0_mfd_sample_fetch_all(const struct device *dev)
320 {
321 #if !defined(LSM9DS0_MFD_ACCEL_DISABLED)
322 	if (lsm9ds0_mfd_sample_fetch_accel(dev) < 0) {
323 		return -EIO;
324 	}
325 #endif
326 
327 #if !defined(LSM9DS0_MFD_MAGN_DISABLED)
328 	if (lsm9ds0_mfd_sample_fetch_magn(dev) < 0) {
329 		return -EIO;
330 	}
331 #endif
332 
333 #if !defined(LSM9DS0_MFD_TEMP_DISABLED)
334 	if (lsm9ds0_mfd_sample_fetch_temp(dev) < 0) {
335 		return -EIO;
336 	}
337 #endif
338 
339 	return 0;
340 }
341 
lsm9ds0_mfd_sample_fetch(const struct device * dev,enum sensor_channel chan)342 static int lsm9ds0_mfd_sample_fetch(const struct device *dev,
343 				    enum sensor_channel chan)
344 {
345 	switch (chan) {
346 #if !defined(LSM9DS0_MFD_ACCEL_DISABLED)
347 	case SENSOR_CHAN_ACCEL_XYZ:
348 		return lsm9ds0_mfd_sample_fetch_accel(dev);
349 #endif
350 #if !defined(LSM9DS0_MFD_MAGN_DISABLED)
351 	case SENSOR_CHAN_MAGN_XYZ:
352 		return lsm9ds0_mfd_sample_fetch_magn(dev);
353 #endif
354 #if !defined(LSM9DS0_MFD_TEMP_DISABLED)
355 	case SENSOR_CHAN_DIE_TEMP:
356 		return lsm9ds0_mfd_sample_fetch_temp(dev);
357 #endif
358 	case SENSOR_CHAN_ALL:
359 		return lsm9ds0_mfd_sample_fetch_all(dev);
360 	default:
361 		return -EINVAL;
362 	}
363 
364 	return 0;
365 }
366 
367 #if !defined(LSM9DS0_MFD_ACCEL_DISABLED)
lsm9ds0_mfd_convert_accel(struct sensor_value * val,int raw_val,float scale)368 static inline void lsm9ds0_mfd_convert_accel(struct sensor_value *val,
369 					     int raw_val,
370 					     float scale)
371 {
372 	double dval;
373 
374 	dval = (double)(raw_val) * (double)scale;
375 	val->val1 = (int32_t)dval;
376 	val->val2 = ((int32_t)(dval * 1000000)) % 1000000;
377 }
378 
lsm9ds0_mfd_get_accel_channel(enum sensor_channel chan,struct sensor_value * val,struct lsm9ds0_mfd_data * data,float scale)379 static inline int lsm9ds0_mfd_get_accel_channel(enum sensor_channel chan,
380 						struct sensor_value *val,
381 						struct lsm9ds0_mfd_data *data,
382 						float scale)
383 {
384 	switch (chan) {
385 	case SENSOR_CHAN_ACCEL_X:
386 		lsm9ds0_mfd_convert_accel(val, data->sample_accel_x, scale);
387 		break;
388 	case SENSOR_CHAN_ACCEL_Y:
389 		lsm9ds0_mfd_convert_accel(val, data->sample_accel_y, scale);
390 		break;
391 	case SENSOR_CHAN_ACCEL_Z:
392 		lsm9ds0_mfd_convert_accel(val, data->sample_accel_z, scale);
393 		break;
394 	case SENSOR_CHAN_ACCEL_XYZ:
395 		lsm9ds0_mfd_convert_accel(val, data->sample_accel_x, scale);
396 		lsm9ds0_mfd_convert_accel(val + 1, data->sample_accel_y, scale);
397 		lsm9ds0_mfd_convert_accel(val + 2, data->sample_accel_z, scale);
398 		break;
399 	default:
400 		return -ENOTSUP;
401 	}
402 
403 	return 0;
404 }
405 
lsm9ds0_mfd_get_accel(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)406 static inline int lsm9ds0_mfd_get_accel(const struct device *dev,
407 					enum sensor_channel chan,
408 					struct sensor_value *val)
409 {
410 	struct lsm9ds0_mfd_data *data = dev->data;
411 
412 #if defined(CONFIG_LSM9DS0_MFD_ACCEL_FULL_SCALE_RUNTIME)
413 	switch (data->sample_accel_fs) {
414 	case 0:
415 		return lsm9ds0_mfd_get_accel_channel(chan, val, data,
416 						     2.0 * 9.807 / 32767.0);
417 	case 1:
418 		return lsm9ds0_mfd_get_accel_channel(chan, val, data,
419 						     4.0 * 9.807 / 32767.0);
420 	case 2:
421 		return lsm9ds0_mfd_get_accel_channel(chan, val, data,
422 						     6.0 * 9.807 / 32767.0);
423 	case 3:
424 		return lsm9ds0_mfd_get_accel_channel(chan, val, data,
425 						     8.0 * 9.807 / 32767.0);
426 	case 4:
427 		return lsm9ds0_mfd_get_accel_channel(chan, val, data,
428 						     16.0 * 9.807 / 32767.0);
429 	default:
430 		return -ENOTSUP;
431 	}
432 #elif defined(CONFIG_LSM9DS0_MFD_ACCEL_FULL_SCALE_2)
433 	return lsm9ds0_mfd_get_accel_channel(chan, val, data,
434 					     2.0 * 9.807 / 32767.0);
435 #elif defined(CONFIG_LSM9DS0_MFD_ACCEL_FULL_SCALE_4)
436 	return lsm9ds0_mfd_get_accel_channel(chan, val, data,
437 					     4.0 * 9.807 / 32767.0);
438 #elif defined(CONFIG_LSM9DS0_MFD_ACCEL_FULL_SCALE_6)
439 	return lsm9ds0_mfd_get_accel_channel(chan, val, data,
440 					     6.0 * 9.807 / 32767.0);
441 #elif defined(CONFIG_LSM9DS0_MFD_ACCEL_FULL_SCALE_8)
442 	return lsm9ds0_mfd_get_accel_channel(chan, val, data,
443 					     8.0 * 9.807 / 32767.0);
444 #elif defined(CONFIG_LSM9DS0_MFD_ACCEL_FULL_SCALE_16)
445 	return lsm9ds0_mfd_get_accel_channel(chan, val, data,
446 					     16.0 * 9.807 / 32767.0);
447 #endif
448 
449 	return 0;
450 }
451 #endif
452 
453 #if !defined(LSM9DS0_MFD_MAGN_DISABLED)
lsm9ds0_mfd_convert_magn(struct sensor_value * val,int raw_val,float scale)454 static inline void lsm9ds0_mfd_convert_magn(struct sensor_value *val,
455 					    int raw_val,
456 					    float scale)
457 {
458 	double dval;
459 
460 	dval = (double)(raw_val) * (double)scale;
461 	val->val1 = (int32_t)dval;
462 	val->val2 = ((int32_t)(dval * 1000000)) % 1000000;
463 }
464 
lsm9ds0_mfd_get_magn_channel(enum sensor_channel chan,struct sensor_value * val,struct lsm9ds0_mfd_data * data,float scale)465 static inline int lsm9ds0_mfd_get_magn_channel(enum sensor_channel chan,
466 					       struct sensor_value *val,
467 					       struct lsm9ds0_mfd_data *data,
468 					       float scale)
469 {
470 	switch (chan) {
471 	case SENSOR_CHAN_MAGN_X:
472 		lsm9ds0_mfd_convert_magn(val, data->sample_magn_x, scale);
473 		break;
474 	case SENSOR_CHAN_MAGN_Y:
475 		lsm9ds0_mfd_convert_magn(val, data->sample_magn_y, scale);
476 		break;
477 	case SENSOR_CHAN_MAGN_Z:
478 		lsm9ds0_mfd_convert_magn(val, data->sample_magn_z, scale);
479 		break;
480 	case SENSOR_CHAN_MAGN_XYZ:
481 		lsm9ds0_mfd_convert_magn(val, data->sample_magn_x, scale);
482 		lsm9ds0_mfd_convert_magn(val + 1, data->sample_magn_y, scale);
483 		lsm9ds0_mfd_convert_magn(val + 2, data->sample_magn_z, scale);
484 		break;
485 	default:
486 		return -ENOTSUP;
487 	}
488 
489 	return 0;
490 }
491 
lsm9ds0_mfd_get_magn(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)492 static inline int lsm9ds0_mfd_get_magn(const struct device *dev,
493 				       enum sensor_channel chan,
494 				       struct sensor_value *val)
495 {
496 	struct lsm9ds0_mfd_data *data = dev->data;
497 
498 #if defined(CONFIG_LSM9DS0_MFD_MAGN_FULL_SCALE_RUNTIME)
499 	switch (data->sample_magn_fs) {
500 	case 0:
501 		return lsm9ds0_mfd_get_magn_channel(chan, val, data,
502 						    2.0 / 32767.0);
503 	case 1:
504 		return lsm9ds0_mfd_get_magn_channel(chan, val, data,
505 						    4.0 / 32767.0);
506 	case 2:
507 		return lsm9ds0_mfd_get_magn_channel(chan, val, data,
508 						    8.0 / 32767.0);
509 	case 3:
510 		return lsm9ds0_mfd_get_magn_channel(chan, val, data,
511 						    12.0 / 32767.0);
512 	default:
513 		return -ENOTSUP;
514 	}
515 #elif defined(CONFIG_LSM9DS0_MFD_MAGN_FULL_SCALE_2)
516 	return lsm9ds0_mfd_get_magn_channel(chan, val, data, 2.0 / 32767.0);
517 #elif defined(CONFIG_LSM9DS0_MFD_MAGN_FULL_SCALE_4)
518 	return lsm9ds0_mfd_get_magn_channel(chan, val, data, 4.0 / 32767.0);
519 #elif defined(CONFIG_LSM9DS0_MFD_MAGN_FULL_SCALE_8)
520 	return lsm9ds0_mfd_get_magn_channel(chan, val, data, 8.0 / 32767.0);
521 #elif defined(CONFIG_LSM9DS0_MFD_MAGN_FULL_SCALE_12)
522 	return lsm9ds0_mfd_get_magn_channel(chan, val, data, 12.0 / 32767.0);
523 #endif
524 
525 	return 0;
526 }
527 #endif
528 
lsm9ds0_mfd_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)529 static int lsm9ds0_mfd_channel_get(const struct device *dev,
530 				   enum sensor_channel chan,
531 				   struct sensor_value *val)
532 {
533 #if !defined(LSM9DS0_MFD_TEMP_DISABLED)
534 	struct lsm9ds0_mfd_data *data = dev->data;
535 #endif
536 
537 	switch (chan) {
538 #if !defined(LSM9DS0_MFD_ACCEL_DISABLED)
539 	case SENSOR_CHAN_ACCEL_X:
540 	case SENSOR_CHAN_ACCEL_Y:
541 	case SENSOR_CHAN_ACCEL_Z:
542 	case SENSOR_CHAN_ACCEL_XYZ:
543 		return lsm9ds0_mfd_get_accel(dev, chan, val);
544 #endif
545 #if !defined(LSM9DS0_MFD_MAGN_DISABLED)
546 	case SENSOR_CHAN_MAGN_X:
547 	case SENSOR_CHAN_MAGN_Y:
548 	case SENSOR_CHAN_MAGN_Z:
549 	case SENSOR_CHAN_MAGN_XYZ:
550 		return lsm9ds0_mfd_get_magn(dev, chan, val);
551 #endif
552 #if !defined(LSM9DS0_MFD_TEMP_DISABLED)
553 	case SENSOR_CHAN_DIE_TEMP:
554 		val->val1 = data->sample_temp;
555 		val->val2 = 0;
556 		return 0;
557 #endif
558 	default:
559 		return -ENOTSUP;
560 	}
561 }
562 
563 #if defined(LSM9DS0_MFD_ATTR_SET_ACCEL)
lsm9ds0_mfd_attr_set_accel(const struct device * dev,enum sensor_attribute attr,const struct sensor_value * val)564 static inline int lsm9ds0_mfd_attr_set_accel(const struct device *dev,
565 					     enum sensor_attribute attr,
566 					     const struct sensor_value *val)
567 {
568 	switch (attr) {
569 #if defined(CONFIG_LSM9DS0_MFD_ACCEL_SAMPLING_RATE_RUNTIME)
570 	case SENSOR_ATTR_SAMPLING_FREQUENCY:
571 		return lsm9ds0_mfd_accel_set_odr(dev, val);
572 #endif
573 #if defined(CONFIG_LSM9DS0_MFD_ACCEL_FULL_SCALE_RUNTIME)
574 	case SENSOR_ATTR_FULL_SCALE:
575 		return lsm9ds0_mfd_accel_set_fs(dev, sensor_ms2_to_g(val));
576 #endif
577 	default:
578 		return -ENOTSUP;
579 	}
580 
581 	return 0;
582 }
583 #endif
584 
585 #if defined(LSM9DS0_MFD_ATTR_SET_MAGN)
lsm9ds0_mfd_attr_set_magn(const struct device * dev,enum sensor_attribute attr,const struct sensor_value * val)586 static inline int lsm9ds0_mfd_attr_set_magn(const struct device *dev,
587 					     enum sensor_attribute attr,
588 					     const struct sensor_value *val)
589 {
590 	switch (attr) {
591 #if defined(CONFIG_LSM9DS0_MFD_MAGN_SAMPLING_RATE_RUNTIME)
592 	case SENSOR_ATTR_SAMPLING_FREQUENCY:
593 		return lsm9ds0_mfd_magn_set_odr(dev, val);
594 #endif
595 #if defined(CONFIG_LSM9DS0_MFD_MAGN_FULL_SCALE_RUNTIME)
596 	case SENSOR_ATTR_FULL_SCALE:
597 		return lsm9ds0_mfd_magn_set_fs(dev, val);
598 #endif
599 	default:
600 		return -ENOTSUP;
601 	}
602 
603 	return 0;
604 }
605 #endif
606 
607 #if defined(LSM9DS0_MFD_ATTR_SET)
lsm9ds0_mfd_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)608 static int lsm9ds0_mfd_attr_set(const struct device *dev,
609 				enum sensor_channel chan,
610 				enum sensor_attribute attr,
611 				const struct sensor_value *val)
612 {
613 
614 	switch (chan) {
615 #if defined(LSM9DS0_MFD_ATTR_SET_ACCEL)
616 	case SENSOR_CHAN_ACCEL_X:
617 	case SENSOR_CHAN_ACCEL_Y:
618 	case SENSOR_CHAN_ACCEL_Z:
619 	case SENSOR_CHAN_ACCEL_XYZ:
620 		return lsm9ds0_mfd_attr_set_accel(dev, attr, val);
621 #endif
622 #if defined(LSM9DS0_MFD_ATTR_SET_MAGN)
623 	case SENSOR_CHAN_MAGN_X:
624 	case SENSOR_CHAN_MAGN_Y:
625 	case SENSOR_CHAN_MAGN_Z:
626 	case SENSOR_CHAN_MAGN_XYZ:
627 		return lsm9ds0_mfd_attr_set_magn(dev, attr, val);
628 #endif
629 	default:
630 		return -ENOTSUP;
631 	}
632 
633 	return 0;
634 }
635 #endif
636 
637 static const struct sensor_driver_api lsm9ds0_mfd_api_funcs = {
638 	.sample_fetch = lsm9ds0_mfd_sample_fetch,
639 	.channel_get = lsm9ds0_mfd_channel_get,
640 #if defined(LSM9DS0_MFD_ATTR_SET)
641 	.attr_set = lsm9ds0_mfd_attr_set,
642 #endif
643 };
644 
lsm9ds0_mfd_init_chip(const struct device * dev)645 static int lsm9ds0_mfd_init_chip(const struct device *dev)
646 {
647 	const struct lsm9ds0_mfd_config *config = dev->config;
648 	uint8_t chip_id;
649 
650 	if (lsm9ds0_mfd_reboot_memory(dev) < 0) {
651 		LOG_DBG("failed to reset device");
652 		return -EIO;
653 	}
654 
655 	if (i2c_reg_read_byte_dt(&config->i2c, LSM9DS0_MFD_REG_WHO_AM_I_XM, &chip_id) < 0) {
656 		LOG_DBG("failed reading chip id");
657 		return -EIO;
658 	}
659 
660 	if (chip_id != LSM9DS0_MFD_VAL_WHO_AM_I_XM) {
661 		LOG_DBG("invalid chip id 0x%x", chip_id);
662 		return -EIO;
663 	}
664 
665 	LOG_DBG("chip id 0x%x", chip_id);
666 
667 #if !defined(LSM9DS0_MFD_ACCEL_DISABLED)
668 	if (i2c_reg_update_byte_dt(&config->i2c, LSM9DS0_MFD_REG_CTRL_REG1_XM,
669 				   LSM9DS0_MFD_MASK_CTRL_REG1_XM_BDU |
670 				   LSM9DS0_MFD_MASK_CTRL_REG1_XM_AODR,
671 				   (1 << LSM9DS0_MFD_SHIFT_CTRL_REG1_XM_BDU) |
672 				   (LSM9DS0_MFD_ACCEL_DEFAULT_AODR <<
673 				   LSM9DS0_MFD_SHIFT_CTRL_REG1_XM_AODR))) {
674 		LOG_DBG("failed to set AODR and BDU");
675 		return -EIO;
676 	}
677 
678 	if (lsm9ds0_mfd_accel_set_fs_raw(dev, LSM9DS0_MFD_ACCEL_DEFAULT_FS)) {
679 		LOG_DBG("failed to set accelerometer full-scale");
680 		return -EIO;
681 	}
682 
683 	if (i2c_reg_update_byte_dt(&config->i2c, LSM9DS0_MFD_REG_CTRL_REG1_XM,
684 				   LSM9DS0_MFD_MASK_CTRL_REG1_XM_AXEN |
685 				   LSM9DS0_MFD_MASK_CTRL_REG1_XM_AYEN |
686 				   LSM9DS0_MFD_MASK_CTRL_REG1_XM_AZEN,
687 				   (LSM9DS0_MFD_ACCEL_ENABLE_X <<
688 				   LSM9DS0_MFD_SHIFT_CTRL_REG1_XM_AXEN) |
689 				   (LSM9DS0_MFD_ACCEL_ENABLE_Y <<
690 				   LSM9DS0_MFD_SHIFT_CTRL_REG1_XM_AYEN) |
691 				   (LSM9DS0_MFD_ACCEL_ENABLE_Z <<
692 				   LSM9DS0_MFD_SHIFT_CTRL_REG1_XM_AZEN)) < 0) {
693 		LOG_DBG("failed to set accelerometer axis enable bits\n");
694 		return -EIO;
695 	}
696 
697 #elif !defined(LSM9DS0_MFD_MAGN_DISABLED)
698 	if (i2c_reg_update_byte_dt(&config->i2c, LSM9DS0_MFD_REG_CTRL_REG1_XM,
699 				   LSM9DS0_MFD_MASK_CTRL_REG1_XM_BDU,
700 				   1 << LSM9DS0_MFD_SHIFT_CTRL_REG1_XM_BDU) < 0) {
701 		LOG_DBG("failed to set BDU\n");
702 		return -EIO;
703 	}
704 #endif
705 
706 #if !defined(LSM9DS0_MFD_MAGN_DISABLED)
707 	if (i2c_reg_update_byte_dt(&config->i2c, LSM9DS0_MFD_REG_CTRL_REG7_XM,
708 				   LSM9DS0_MFD_MASK_CTRL_REG7_XM_MD,
709 				   (0 << LSM9DS0_MFD_SHIFT_CTRL_REG7_XM_MD)) < 0) {
710 		LOG_DBG("failed to power on magnetometer");
711 		return -EIO;
712 	}
713 
714 	if (lsm9ds0_mfd_magn_set_odr_raw(dev, LSM9DS0_MFD_MAGN_DEFAULT_M_ODR)) {
715 		LOG_DBG("failed to set magnetometer sampling rate");
716 		return -EIO;
717 	}
718 
719 	if (lsm9ds0_mfd_magn_set_fs_raw(dev, LSM9DS0_MFD_MAGN_DEFAULT_FS)) {
720 		LOG_DBG("failed to set magnetometer full-scale");
721 		return -EIO;
722 	}
723 #endif
724 
725 #if !defined(LSM9DS0_MFD_TEMP_DISABLED)
726 	if (i2c_reg_update_byte_dt(&config->i2c, LSM9DS0_MFD_REG_CTRL_REG5_XM,
727 				   LSM9DS0_MFD_MASK_CTRL_REG5_XM_TEMP_EN,
728 				   1 << LSM9DS0_MFD_SHIFT_CTRL_REG5_XM_TEMP_EN) < 0) {
729 		LOG_DBG("failed to power on temperature sensor");
730 		return -EIO;
731 	}
732 #endif
733 
734 	return 0;
735 }
736 
lsm9ds0_mfd_init(const struct device * dev)737 int lsm9ds0_mfd_init(const struct device *dev)
738 {
739 	const struct lsm9ds0_mfd_config * const config = dev->config;
740 
741 	if (!device_is_ready(config->i2c.bus)) {
742 		LOG_ERR("Bus device is not ready");
743 		return -ENODEV;
744 	}
745 
746 	if (lsm9ds0_mfd_init_chip(dev) < 0) {
747 		LOG_DBG("failed to initialize chip");
748 		return -EIO;
749 	}
750 
751 	return 0;
752 }
753 
754 #define LSM9DS0_MFD_DEFINE(inst)								\
755 	static struct lsm9ds0_mfd_data lsm9ds0_mfd_data_##inst;					\
756 												\
757 	static const struct lsm9ds0_mfd_config lsm9ds0_mfd_config_##inst = {			\
758 		.i2c = I2C_DT_SPEC_INST_GET(inst),						\
759 	};											\
760 												\
761 	SENSOR_DEVICE_DT_INST_DEFINE(inst, lsm9ds0_mfd_init, NULL,				\
762 			      &lsm9ds0_mfd_data_##inst, &lsm9ds0_mfd_config_##inst, POST_KERNEL,\
763 			      CONFIG_SENSOR_INIT_PRIORITY, &lsm9ds0_mfd_api_funcs);		\
764 
765 DT_INST_FOREACH_STATUS_OKAY(LSM9DS0_MFD_DEFINE)
766