1 /* ST Microelectronics ISM330DHCX 6-axis IMU sensor driver
2 *
3 * Copyright (c) 2020 STMicroelectronics
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Datasheet:
8 * https://www.st.com/resource/en/datasheet/ism330dhcx.pdf
9 */
10
11 #define DT_DRV_COMPAT st_ism330dhcx
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/__assert.h>
19 #include <zephyr/sys/util_macro.h>
20 #include <zephyr/logging/log.h>
21
22 #include "ism330dhcx.h"
23
24 LOG_MODULE_REGISTER(ISM330DHCX, CONFIG_SENSOR_LOG_LEVEL);
25
26 static const uint16_t ism330dhcx_odr_map[] = {0, 12, 26, 52, 104, 208, 416, 833,
27 1660, 3330, 6660};
28
ism330dhcx_freq_to_odr_val(uint16_t freq)29 static int ism330dhcx_freq_to_odr_val(uint16_t freq)
30 {
31 size_t i;
32
33 for (i = 0; i < ARRAY_SIZE(ism330dhcx_odr_map); i++) {
34 if (freq <= ism330dhcx_odr_map[i]) {
35 return i;
36 }
37 }
38
39 return -EINVAL;
40 }
41
ism330dhcx_odr_to_freq_val(uint16_t odr)42 static int ism330dhcx_odr_to_freq_val(uint16_t odr)
43 {
44 /* for valid index, return value from map */
45 if (odr < ARRAY_SIZE(ism330dhcx_odr_map)) {
46 return ism330dhcx_odr_map[odr];
47 }
48
49 /* invalid index, return last entry */
50 return ism330dhcx_odr_map[ARRAY_SIZE(ism330dhcx_odr_map) - 1];
51 }
52
53 static const uint16_t ism330dhcx_accel_fs_map[] = {2, 16, 4, 8};
54 static const uint16_t ism330dhcx_accel_fs_sens[] = {1, 8, 2, 4};
55
ism330dhcx_accel_range_to_fs_val(int32_t range)56 static int ism330dhcx_accel_range_to_fs_val(int32_t range)
57 {
58 size_t i;
59
60 for (i = 0; i < ARRAY_SIZE(ism330dhcx_accel_fs_map); i++) {
61 if (range == ism330dhcx_accel_fs_map[i]) {
62 return i;
63 }
64 }
65
66 return -EINVAL;
67 }
68
69 /*
70 * Following arrays are initialized in order to mimic
71 * the ism330dhcx_fs_g_t enum:
72 *
73 * typedef enum
74 * {
75 * ISM330DHCX_125dps = 2,
76 * ISM330DHCX_250dps = 0,
77 * ISM330DHCX_500dps = 4,
78 * ISM330DHCX_1000dps = 8,
79 * ISM330DHCX_2000dps = 12,
80 * ISM330DHCX_4000dps = 1,
81 * } ism330dhcx_fs_g_t;
82 */
83 static const uint16_t ism330dhcx_gyro_fs_map[] = {
84 250, 4000, 125, 0, 500,
85 0, 0, 0, 1000,
86 0, 0, 0, 2000
87 };
88 static const uint16_t ism330dhcx_gyro_fs_sens[] = {
89 2, 32, 1, 0, 4,
90 0, 0, 0, 8,
91 0, 0, 0, 16
92 };
93
ism330dhcx_gyro_range_to_fs_val(int32_t range)94 static int ism330dhcx_gyro_range_to_fs_val(int32_t range)
95 {
96 size_t i;
97
98 for (i = 0; i < ARRAY_SIZE(ism330dhcx_gyro_fs_map); i++) {
99 if (range == ism330dhcx_gyro_fs_map[i]) {
100 return i;
101 }
102 }
103
104 return -EINVAL;
105 }
106
ism330dhcx_reboot(const struct device * dev)107 static inline int ism330dhcx_reboot(const struct device *dev)
108 {
109 struct ism330dhcx_data *data = dev->data;
110
111 if (ism330dhcx_boot_set(data->ctx, 1) < 0) {
112 return -EIO;
113 }
114
115 /* Wait sensor turn-on time as per datasheet */
116 k_busy_wait(35 * USEC_PER_MSEC);
117
118 return 0;
119 }
120
ism330dhcx_accel_set_fs_raw(const struct device * dev,uint8_t fs)121 static int ism330dhcx_accel_set_fs_raw(const struct device *dev, uint8_t fs)
122 {
123 struct ism330dhcx_data *data = dev->data;
124
125 if (ism330dhcx_xl_full_scale_set(data->ctx, fs) < 0) {
126 return -EIO;
127 }
128
129 data->accel_fs = fs;
130
131 return 0;
132 }
133
ism330dhcx_accel_set_odr_raw(const struct device * dev,uint8_t odr)134 static int ism330dhcx_accel_set_odr_raw(const struct device *dev, uint8_t odr)
135 {
136 struct ism330dhcx_data *data = dev->data;
137
138 if (ism330dhcx_xl_data_rate_set(data->ctx, odr) < 0) {
139 return -EIO;
140 }
141
142 data->accel_freq = ism330dhcx_odr_to_freq_val(odr);
143
144 return 0;
145 }
146
ism330dhcx_gyro_set_fs_raw(const struct device * dev,uint8_t fs)147 static int ism330dhcx_gyro_set_fs_raw(const struct device *dev, uint8_t fs)
148 {
149 struct ism330dhcx_data *data = dev->data;
150
151 if (ism330dhcx_gy_full_scale_set(data->ctx, fs) < 0) {
152 return -EIO;
153 }
154
155 return 0;
156 }
157
ism330dhcx_gyro_set_odr_raw(const struct device * dev,uint8_t odr)158 static int ism330dhcx_gyro_set_odr_raw(const struct device *dev, uint8_t odr)
159 {
160 struct ism330dhcx_data *data = dev->data;
161
162 if (ism330dhcx_gy_data_rate_set(data->ctx, odr) < 0) {
163 return -EIO;
164 }
165
166 return 0;
167 }
168
ism330dhcx_accel_odr_set(const struct device * dev,uint16_t freq)169 static int ism330dhcx_accel_odr_set(const struct device *dev, uint16_t freq)
170 {
171 int odr;
172
173 odr = ism330dhcx_freq_to_odr_val(freq);
174 if (odr < 0) {
175 return odr;
176 }
177
178 if (ism330dhcx_accel_set_odr_raw(dev, odr) < 0) {
179 LOG_DBG("failed to set accelerometer sampling rate");
180 return -EIO;
181 }
182
183 return 0;
184 }
185
ism330dhcx_accel_range_set(const struct device * dev,int32_t range)186 static int ism330dhcx_accel_range_set(const struct device *dev, int32_t range)
187 {
188 int fs;
189 struct ism330dhcx_data *data = dev->data;
190
191 fs = ism330dhcx_accel_range_to_fs_val(range);
192 if (fs < 0) {
193 return fs;
194 }
195
196 if (ism330dhcx_accel_set_fs_raw(dev, fs) < 0) {
197 LOG_DBG("failed to set accelerometer full-scale");
198 return -EIO;
199 }
200
201 data->acc_gain = (ism330dhcx_accel_fs_sens[fs] * GAIN_UNIT_XL);
202 return 0;
203 }
204
ism330dhcx_accel_config(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)205 static int ism330dhcx_accel_config(const struct device *dev,
206 enum sensor_channel chan,
207 enum sensor_attribute attr,
208 const struct sensor_value *val)
209 {
210 switch (attr) {
211 case SENSOR_ATTR_FULL_SCALE:
212 return ism330dhcx_accel_range_set(dev, sensor_ms2_to_g(val));
213 case SENSOR_ATTR_SAMPLING_FREQUENCY:
214 return ism330dhcx_accel_odr_set(dev, val->val1);
215 default:
216 LOG_DBG("Accel attribute not supported.");
217 return -ENOTSUP;
218 }
219
220 return 0;
221 }
222
ism330dhcx_gyro_odr_set(const struct device * dev,uint16_t freq)223 static int ism330dhcx_gyro_odr_set(const struct device *dev, uint16_t freq)
224 {
225 int odr;
226
227 odr = ism330dhcx_freq_to_odr_val(freq);
228 if (odr < 0) {
229 return odr;
230 }
231
232 if (ism330dhcx_gyro_set_odr_raw(dev, odr) < 0) {
233 LOG_DBG("failed to set gyroscope sampling rate");
234 return -EIO;
235 }
236
237 return 0;
238 }
239
ism330dhcx_gyro_range_set(const struct device * dev,int32_t range)240 static int ism330dhcx_gyro_range_set(const struct device *dev, int32_t range)
241 {
242 int fs;
243 struct ism330dhcx_data *data = dev->data;
244
245 fs = ism330dhcx_gyro_range_to_fs_val(range);
246 if (fs < 0) {
247 return fs;
248 }
249
250 if (ism330dhcx_gyro_set_fs_raw(dev, fs) < 0) {
251 LOG_DBG("failed to set gyroscope full-scale");
252 return -EIO;
253 }
254
255 data->gyro_gain = (ism330dhcx_gyro_fs_sens[fs] * GAIN_UNIT_G);
256 return 0;
257 }
258
ism330dhcx_gyro_config(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)259 static int ism330dhcx_gyro_config(const struct device *dev,
260 enum sensor_channel chan,
261 enum sensor_attribute attr,
262 const struct sensor_value *val)
263 {
264 switch (attr) {
265 case SENSOR_ATTR_FULL_SCALE:
266 return ism330dhcx_gyro_range_set(dev, sensor_rad_to_degrees(val));
267 case SENSOR_ATTR_SAMPLING_FREQUENCY:
268 return ism330dhcx_gyro_odr_set(dev, val->val1);
269 default:
270 LOG_DBG("Gyro attribute not supported.");
271 return -ENOTSUP;
272 }
273
274 return 0;
275 }
276
ism330dhcx_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)277 static int ism330dhcx_attr_set(const struct device *dev,
278 enum sensor_channel chan,
279 enum sensor_attribute attr,
280 const struct sensor_value *val)
281 {
282 switch (chan) {
283 case SENSOR_CHAN_ACCEL_XYZ:
284 return ism330dhcx_accel_config(dev, chan, attr, val);
285 case SENSOR_CHAN_GYRO_XYZ:
286 return ism330dhcx_gyro_config(dev, chan, attr, val);
287 #if defined(CONFIG_ISM330DHCX_SENSORHUB)
288 case SENSOR_CHAN_MAGN_XYZ:
289 case SENSOR_CHAN_PRESS:
290 case SENSOR_CHAN_HUMIDITY:
291 return ism330dhcx_shub_config(dev, chan, attr, val);
292 #endif /* CONFIG_ISM330DHCX_SENSORHUB */
293 default:
294 LOG_WRN("attr_set() not supported on this channel.");
295 return -ENOTSUP;
296 }
297
298 return 0;
299 }
300
ism330dhcx_sample_fetch_accel(const struct device * dev)301 static int ism330dhcx_sample_fetch_accel(const struct device *dev)
302 {
303 struct ism330dhcx_data *data = dev->data;
304 int16_t buf[3];
305
306 if (ism330dhcx_acceleration_raw_get(data->ctx, buf) < 0) {
307 LOG_DBG("Failed to read sample");
308 return -EIO;
309 }
310
311 data->acc[0] = buf[0];
312 data->acc[1] = buf[1];
313 data->acc[2] = buf[2];
314
315 return 0;
316 }
317
ism330dhcx_sample_fetch_gyro(const struct device * dev)318 static int ism330dhcx_sample_fetch_gyro(const struct device *dev)
319 {
320 struct ism330dhcx_data *data = dev->data;
321 int16_t buf[3];
322
323 if (ism330dhcx_angular_rate_raw_get(data->ctx, buf) < 0) {
324 LOG_DBG("Failed to read sample");
325 return -EIO;
326 }
327
328 data->gyro[0] = buf[0];
329 data->gyro[1] = buf[1];
330 data->gyro[2] = buf[2];
331
332 return 0;
333 }
334
335 #if defined(CONFIG_ISM330DHCX_ENABLE_TEMP)
ism330dhcx_sample_fetch_temp(const struct device * dev)336 static int ism330dhcx_sample_fetch_temp(const struct device *dev)
337 {
338 struct ism330dhcx_data *data = dev->data;
339 int16_t buf;
340
341 if (ism330dhcx_temperature_raw_get(data->ctx, &buf) < 0) {
342 LOG_DBG("Failed to read sample");
343 return -EIO;
344 }
345
346 data->temp_sample = buf;
347
348 return 0;
349 }
350 #endif
351
352 #if defined(CONFIG_ISM330DHCX_SENSORHUB)
ism330dhcx_sample_fetch_shub(const struct device * dev)353 static int ism330dhcx_sample_fetch_shub(const struct device *dev)
354 {
355 if (ism330dhcx_shub_fetch_external_devs(dev) < 0) {
356 LOG_DBG("failed to read ext shub devices");
357 return -EIO;
358 }
359
360 return 0;
361 }
362 #endif /* CONFIG_ISM330DHCX_SENSORHUB */
363
ism330dhcx_sample_fetch(const struct device * dev,enum sensor_channel chan)364 static int ism330dhcx_sample_fetch(const struct device *dev,
365 enum sensor_channel chan)
366 {
367 switch (chan) {
368 case SENSOR_CHAN_ACCEL_XYZ:
369 ism330dhcx_sample_fetch_accel(dev);
370 #if defined(CONFIG_ISM330DHCX_SENSORHUB)
371 ism330dhcx_sample_fetch_shub(dev);
372 #endif
373 break;
374 case SENSOR_CHAN_GYRO_XYZ:
375 ism330dhcx_sample_fetch_gyro(dev);
376 break;
377 #if defined(CONFIG_ISM330DHCX_ENABLE_TEMP)
378 case SENSOR_CHAN_DIE_TEMP:
379 ism330dhcx_sample_fetch_temp(dev);
380 break;
381 #endif
382 case SENSOR_CHAN_ALL:
383 ism330dhcx_sample_fetch_accel(dev);
384 ism330dhcx_sample_fetch_gyro(dev);
385 #if defined(CONFIG_ISM330DHCX_ENABLE_TEMP)
386 ism330dhcx_sample_fetch_temp(dev);
387 #endif
388 #if defined(CONFIG_ISM330DHCX_SENSORHUB)
389 ism330dhcx_sample_fetch_shub(dev);
390 #endif
391 break;
392 default:
393 return -ENOTSUP;
394 }
395
396 return 0;
397 }
398
ism330dhcx_accel_convert(struct sensor_value * val,int raw_val,uint32_t sensitivity)399 static inline void ism330dhcx_accel_convert(struct sensor_value *val, int raw_val,
400 uint32_t sensitivity)
401 {
402 int64_t dval;
403
404 /* Sensitivity is exposed in ug/LSB */
405 /* Convert to m/s^2 */
406 dval = (int64_t)(raw_val) * sensitivity;
407 sensor_ug_to_ms2(dval, val);
408
409 }
410
ism330dhcx_accel_get_channel(const struct device * dev,enum sensor_channel chan,struct sensor_value * val,uint32_t sensitivity)411 static inline int ism330dhcx_accel_get_channel(const struct device *dev, enum sensor_channel chan,
412 struct sensor_value *val, uint32_t sensitivity)
413 {
414 struct ism330dhcx_data *data = dev->data;
415 uint8_t i;
416
417 switch (chan) {
418 case SENSOR_CHAN_ACCEL_X:
419 ism330dhcx_accel_convert(val, data->acc[0], sensitivity);
420 break;
421 case SENSOR_CHAN_ACCEL_Y:
422 ism330dhcx_accel_convert(val, data->acc[1], sensitivity);
423 break;
424 case SENSOR_CHAN_ACCEL_Z:
425 ism330dhcx_accel_convert(val, data->acc[2], sensitivity);
426 break;
427 case SENSOR_CHAN_ACCEL_XYZ:
428 for (i = 0; i < 3; i++) {
429 ism330dhcx_accel_convert(val++, data->acc[i], sensitivity);
430 }
431 break;
432 default:
433 return -ENOTSUP;
434 }
435
436 return 0;
437 }
438
ism330dhcx_accel_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)439 static int ism330dhcx_accel_channel_get(const struct device *dev, enum sensor_channel chan,
440 struct sensor_value *val)
441 {
442 struct ism330dhcx_data *data = dev->data;
443
444 return ism330dhcx_accel_get_channel(dev, chan, val, data->acc_gain);
445 }
446
ism330dhcx_gyro_convert(struct sensor_value * val,int raw_val,uint32_t sensitivity)447 static inline void ism330dhcx_gyro_convert(struct sensor_value *val, int raw_val,
448 uint32_t sensitivity)
449 {
450 int64_t dval;
451
452 /* Sensitivity is exposed in udps/LSB */
453 /* So, calculate value in 10 udps unit and then to rad/s */
454 dval = (int64_t)(raw_val) * sensitivity / 10;
455 sensor_10udegrees_to_rad(dval, val);
456 }
457
ism330dhcx_gyro_get_channel(const struct device * dev,enum sensor_channel chan,struct sensor_value * val,uint32_t sensitivity)458 static inline int ism330dhcx_gyro_get_channel(const struct device *dev, enum sensor_channel chan,
459 struct sensor_value *val, uint32_t sensitivity)
460 {
461 struct ism330dhcx_data *data = dev->data;
462 uint8_t i;
463
464 switch (chan) {
465 case SENSOR_CHAN_GYRO_X:
466 ism330dhcx_gyro_convert(val, data->gyro[0], sensitivity);
467 break;
468 case SENSOR_CHAN_GYRO_Y:
469 ism330dhcx_gyro_convert(val, data->gyro[1], sensitivity);
470 break;
471 case SENSOR_CHAN_GYRO_Z:
472 ism330dhcx_gyro_convert(val, data->gyro[2], sensitivity);
473 break;
474 case SENSOR_CHAN_GYRO_XYZ:
475 for (i = 0; i < 3; i++) {
476 ism330dhcx_gyro_convert(val++, data->gyro[i], sensitivity);
477 }
478 break;
479 default:
480 return -ENOTSUP;
481 }
482
483 return 0;
484 }
485
ism330dhcx_gyro_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)486 static int ism330dhcx_gyro_channel_get(const struct device *dev, enum sensor_channel chan,
487 struct sensor_value *val)
488 {
489 struct ism330dhcx_data *data = dev->data;
490
491 return ism330dhcx_gyro_get_channel(dev, chan, val, data->gyro_gain);
492 }
493
494 #if defined(CONFIG_ISM330DHCX_ENABLE_TEMP)
ism330dhcx_gyro_channel_get_temp(const struct device * dev,struct sensor_value * val)495 static void ism330dhcx_gyro_channel_get_temp(const struct device *dev,
496 struct sensor_value *val)
497 {
498 struct ism330dhcx_data *data = dev->data;
499
500 /* val = temp_sample / 256 + 25 */
501 val->val1 = data->temp_sample / 256 + 25;
502 val->val2 = (data->temp_sample % 256) * (1000000 / 256);
503 }
504 #endif
505
506 #if defined(CONFIG_ISM330DHCX_SENSORHUB)
ism330dhcx_magn_convert(struct sensor_value * val,int raw_val,uint16_t sensitivity)507 static inline void ism330dhcx_magn_convert(struct sensor_value *val, int raw_val,
508 uint16_t sensitivity)
509 {
510 double dval;
511
512 /* Sensitivity is exposed in ugauss/LSB */
513 dval = (double)(raw_val * sensitivity);
514 val->val1 = (int32_t)dval / 1000000;
515 val->val2 = (int32_t)dval % 1000000;
516 }
517
ism330dhcx_magn_get_channel(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)518 static inline int ism330dhcx_magn_get_channel(const struct device *dev, enum sensor_channel chan,
519 struct sensor_value *val)
520 {
521 struct ism330dhcx_data *data = dev->data;
522 int16_t sample[3];
523 int idx;
524
525 idx = ism330dhcx_shub_get_idx(SENSOR_CHAN_MAGN_XYZ);
526 if (idx < 0) {
527 LOG_DBG("external magn not supported");
528 return -ENOTSUP;
529 }
530
531
532 sample[0] = (int16_t)(data->ext_data[idx][0] |
533 (data->ext_data[idx][1] << 8));
534 sample[1] = (int16_t)(data->ext_data[idx][2] |
535 (data->ext_data[idx][3] << 8));
536 sample[2] = (int16_t)(data->ext_data[idx][4] |
537 (data->ext_data[idx][5] << 8));
538
539 switch (chan) {
540 case SENSOR_CHAN_MAGN_X:
541 ism330dhcx_magn_convert(val, sample[0], data->magn_gain);
542 break;
543 case SENSOR_CHAN_MAGN_Y:
544 ism330dhcx_magn_convert(val, sample[1], data->magn_gain);
545 break;
546 case SENSOR_CHAN_MAGN_Z:
547 ism330dhcx_magn_convert(val, sample[2], data->magn_gain);
548 break;
549 case SENSOR_CHAN_MAGN_XYZ:
550 ism330dhcx_magn_convert(val, sample[0], data->magn_gain);
551 ism330dhcx_magn_convert(val + 1, sample[1], data->magn_gain);
552 ism330dhcx_magn_convert(val + 2, sample[2], data->magn_gain);
553 break;
554 default:
555 return -ENOTSUP;
556 }
557
558 return 0;
559 }
560
ism330dhcx_hum_convert(const struct device * dev,struct sensor_value * val)561 static inline void ism330dhcx_hum_convert(const struct device *dev, struct sensor_value *val)
562 {
563 struct ism330dhcx_data *data = dev->data;
564 float rh;
565 int16_t raw_val;
566 struct hts221_data *ht = &data->hts221;
567 int idx;
568
569 idx = ism330dhcx_shub_get_idx(SENSOR_CHAN_HUMIDITY);
570 if (idx < 0) {
571 LOG_DBG("external press/temp not supported");
572 return;
573 }
574
575 raw_val = ((int16_t)(data->ext_data[idx][0] |
576 (data->ext_data[idx][1] << 8)));
577
578 /* find relative humidty by linear interpolation */
579 rh = (ht->y1 - ht->y0) * raw_val + ht->x1 * ht->y0 - ht->x0 * ht->y1;
580 rh /= (ht->x1 - ht->x0);
581
582 /* convert humidity to integer and fractional part */
583 val->val1 = rh;
584 val->val2 = rh * 1000000;
585 }
586
ism330dhcx_press_convert(const struct device * dev,struct sensor_value * val)587 static inline void ism330dhcx_press_convert(const struct device *dev, struct sensor_value *val)
588 {
589 struct ism330dhcx_data *data = dev->data;
590 int32_t raw_val;
591 int idx;
592
593 idx = ism330dhcx_shub_get_idx(SENSOR_CHAN_PRESS);
594 if (idx < 0) {
595 LOG_DBG("external press/temp not supported");
596 return;
597 }
598
599 raw_val = (int32_t)(data->ext_data[idx][0] |
600 (data->ext_data[idx][1] << 8) |
601 (data->ext_data[idx][2] << 16));
602
603 /* Pressure sensitivity is 4096 LSB/hPa */
604 /* Convert raw_val to val in kPa */
605 val->val1 = (raw_val >> 12) / 10;
606 val->val2 = (raw_val >> 12) % 10 * 100000 +
607 (((int32_t)((raw_val) & 0x0FFF) * 100000L) >> 12);
608 }
609
ism330dhcx_temp_convert(const struct device * dev,struct sensor_value * val)610 static inline void ism330dhcx_temp_convert(const struct device *dev, struct sensor_value *val)
611 {
612 struct ism330dhcx_data *data = dev->data;
613 int16_t raw_val;
614 int idx;
615
616 idx = ism330dhcx_shub_get_idx(SENSOR_CHAN_PRESS);
617 if (idx < 0) {
618 LOG_DBG("external press/temp not supported");
619 return;
620 }
621
622 raw_val = (int16_t)(data->ext_data[idx][3] |
623 (data->ext_data[idx][4] << 8));
624
625 /* Temperature sensitivity is 100 LSB/deg C */
626 val->val1 = raw_val / 100;
627 val->val2 = (int32_t)raw_val % 100 * (10000);
628 }
629 #endif
630
ism330dhcx_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)631 static int ism330dhcx_channel_get(const struct device *dev,
632 enum sensor_channel chan,
633 struct sensor_value *val)
634 {
635 switch (chan) {
636 case SENSOR_CHAN_ACCEL_X:
637 case SENSOR_CHAN_ACCEL_Y:
638 case SENSOR_CHAN_ACCEL_Z:
639 case SENSOR_CHAN_ACCEL_XYZ:
640 ism330dhcx_accel_channel_get(dev, chan, val);
641 break;
642 case SENSOR_CHAN_GYRO_X:
643 case SENSOR_CHAN_GYRO_Y:
644 case SENSOR_CHAN_GYRO_Z:
645 case SENSOR_CHAN_GYRO_XYZ:
646 ism330dhcx_gyro_channel_get(dev, chan, val);
647 break;
648 #if defined(CONFIG_ISM330DHCX_ENABLE_TEMP)
649 case SENSOR_CHAN_DIE_TEMP:
650 ism330dhcx_gyro_channel_get_temp(dev, val);
651 break;
652 #endif
653 #if defined(CONFIG_ISM330DHCX_SENSORHUB)
654 case SENSOR_CHAN_MAGN_X:
655 case SENSOR_CHAN_MAGN_Y:
656 case SENSOR_CHAN_MAGN_Z:
657 case SENSOR_CHAN_MAGN_XYZ:
658 ism330dhcx_magn_get_channel(dev, chan, val);
659 break;
660
661 case SENSOR_CHAN_HUMIDITY:
662 ism330dhcx_hum_convert(dev, val);
663 break;
664
665 case SENSOR_CHAN_PRESS:
666 ism330dhcx_press_convert(dev, val);
667 break;
668
669 case SENSOR_CHAN_AMBIENT_TEMP:
670 ism330dhcx_temp_convert(dev, val);
671 break;
672 #endif
673 default:
674 return -ENOTSUP;
675 }
676
677 return 0;
678 }
679
680 static DEVICE_API(sensor, ism330dhcx_api_funcs) = {
681 .attr_set = ism330dhcx_attr_set,
682 #if CONFIG_ISM330DHCX_TRIGGER
683 .trigger_set = ism330dhcx_trigger_set,
684 #endif
685 .sample_fetch = ism330dhcx_sample_fetch,
686 .channel_get = ism330dhcx_channel_get,
687 };
688
ism330dhcx_init_chip(const struct device * dev)689 static int ism330dhcx_init_chip(const struct device *dev)
690 {
691 const struct ism330dhcx_config * const cfg = dev->config;
692 struct ism330dhcx_data *ism330dhcx = dev->data;
693 uint8_t chip_id;
694
695 ism330dhcx->dev = dev;
696
697 if (ism330dhcx_device_id_get(ism330dhcx->ctx, &chip_id) < 0) {
698 LOG_DBG("Failed reading chip id");
699 return -EIO;
700 }
701
702 LOG_INF("chip id 0x%x", chip_id);
703
704 if (chip_id != ISM330DHCX_ID) {
705 LOG_DBG("Invalid chip id 0x%x", chip_id);
706 return -EIO;
707 }
708
709 /* reset device */
710 if (ism330dhcx_reset_set(ism330dhcx->ctx, 1) < 0) {
711 return -EIO;
712 }
713
714 k_busy_wait(100);
715
716 LOG_DBG("accel range is %d", cfg->accel_range);
717 if (ism330dhcx_accel_range_set(dev, cfg->accel_range) < 0) {
718 LOG_DBG("failed to set accelerometer full-scale");
719 return -EIO;
720 }
721
722 LOG_DBG("accel odr is %d", cfg->accel_odr);
723 if (ism330dhcx_accel_set_odr_raw(dev, cfg->accel_odr) < 0) {
724 LOG_DBG("failed to set accelerometer sampling rate");
725 return -EIO;
726 }
727
728 LOG_DBG("gyro range is %d", cfg->gyro_range);
729 if (ism330dhcx_gyro_range_set(dev, cfg->gyro_range) < 0) {
730 LOG_DBG("failed to set gyroscope full-scale");
731 return -EIO;
732 }
733
734 LOG_DBG("gyro odr is %d", cfg->gyro_odr);
735 ism330dhcx->gyro_freq = ism330dhcx_odr_to_freq_val(cfg->gyro_odr);
736 if (ism330dhcx_gyro_set_odr_raw(dev, cfg->gyro_odr) < 0) {
737 LOG_DBG("failed to set gyroscope sampling rate");
738 return -EIO;
739 }
740
741 /* Set FIFO bypass mode */
742 if (ism330dhcx_fifo_mode_set(ism330dhcx->ctx, ISM330DHCX_BYPASS_MODE) < 0) {
743 LOG_DBG("failed to set FIFO mode");
744 return -EIO;
745 }
746
747 if (ism330dhcx_block_data_update_set(ism330dhcx->ctx, 1) < 0) {
748 LOG_DBG("failed to set BDU mode");
749 return -EIO;
750 }
751
752 return 0;
753 }
754
ism330dhcx_init(const struct device * dev)755 static int ism330dhcx_init(const struct device *dev)
756 {
757 const struct ism330dhcx_config * const config = dev->config;
758
759 config->bus_init(dev);
760
761 if (ism330dhcx_init_chip(dev) < 0) {
762 LOG_DBG("failed to initialize chip");
763 return -EIO;
764 }
765
766 #ifdef CONFIG_ISM330DHCX_TRIGGER
767 if (config->drdy_gpio.port) {
768 if (ism330dhcx_init_interrupt(dev) < 0) {
769 LOG_ERR("Failed to initialize interrupt.");
770 return -EIO;
771 }
772 }
773 #endif
774
775 #ifdef CONFIG_ISM330DHCX_SENSORHUB
776 if (ism330dhcx_shub_init(dev) < 0) {
777 LOG_DBG("failed to initialize external chip");
778 return -EIO;
779 }
780 #endif
781
782 return 0;
783 }
784
785 #define ISM330DHCX_DEFINE(inst) \
786 static struct ism330dhcx_data ism330dhcx_data_##inst; \
787 \
788 static const struct ism330dhcx_config ism330dhcx_config_##inst = { \
789 .accel_odr = DT_INST_PROP(inst, accel_odr), \
790 .accel_range = DT_INST_PROP(inst, accel_range), \
791 .gyro_odr = DT_INST_PROP(inst, gyro_odr), \
792 .gyro_range = DT_INST_PROP(inst, gyro_range), \
793 COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
794 (.bus_init = ism330dhcx_spi_init, \
795 .spi = SPI_DT_SPEC_INST_GET(inst, SPI_OP_MODE_MASTER | \
796 SPI_MODE_CPOL | SPI_MODE_CPHA | \
797 SPI_WORD_SET(8), 0),), \
798 ()) \
799 COND_CODE_1(DT_INST_ON_BUS(inst, i2c), \
800 (.bus_init = ism330dhcx_i2c_init, \
801 .i2c = I2C_DT_SPEC_INST_GET(inst),), \
802 ()) \
803 IF_ENABLED(CONFIG_ISM330DHCX_TRIGGER, \
804 (.drdy_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, drdy_gpios, { 0 }), \
805 .int_pin = DT_INST_PROP_OR(inst, int_pin, 0),)) \
806 }; \
807 \
808 SENSOR_DEVICE_DT_INST_DEFINE(inst, ism330dhcx_init, NULL, \
809 &ism330dhcx_data_##inst, &ism330dhcx_config_##inst, POST_KERNEL, \
810 CONFIG_SENSOR_INIT_PRIORITY, &ism330dhcx_api_funcs); \
811
812 DT_INST_FOREACH_STATUS_OKAY(ISM330DHCX_DEFINE)
813