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