1 /*
2 * Copyright (c) 2018 Analog Devices Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT adi_adxl372
8
9 #include <zephyr/drivers/sensor.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/device.h>
12 #include <string.h>
13 #include <zephyr/init.h>
14 #include <zephyr/sys/printk.h>
15 #include <zephyr/sys/__assert.h>
16 #include <stdlib.h>
17 #include <zephyr/logging/log.h>
18
19 #include "adxl372.h"
20
21 LOG_MODULE_REGISTER(ADXL372, CONFIG_SENSOR_LOG_LEVEL);
22
23 /**
24 * Set the threshold for activity detection for a single axis
25 * @param dev - The device structure.
26 * @param axis_reg_h - The high part of the activity register.
27 * @param act - The activity config structure.
28 * @return 0 in case of success, negative error code otherwise.
29 */
adxl372_set_activity_threshold(const struct device * dev,uint8_t axis_reg_h,const struct adxl372_activity_threshold * act)30 static int adxl372_set_activity_threshold(const struct device *dev,
31 uint8_t axis_reg_h,
32 const struct adxl372_activity_threshold *act)
33 {
34 int ret;
35 uint8_t val;
36 struct adxl372_data *data = dev->data;
37
38 ret = data->hw_tf->write_reg(dev, axis_reg_h++, act->thresh >> 3);
39 if (ret) {
40 return ret;
41 }
42
43 switch (axis_reg_h) {
44 case ADXL372_X_THRESH_ACT_L:
45 case ADXL372_X_THRESH_INACT_L:
46 case ADXL372_X_THRESH_ACT2_L:
47 val = (act->thresh << 5) | (act->referenced << 1) | act->enable;
48 break;
49 default:
50 val = (act->thresh << 5) | act->enable;
51 }
52
53 return data->hw_tf->write_reg(dev, axis_reg_h, val);
54 }
55
56 /**
57 * Set the threshold for activity detection for all 3-axis
58 * @param dev - The device structure.
59 * @param axis_reg_h - The high part of the activity register.
60 * @param act - The activity config structure.
61 * @return 0 in case of success, negative error code otherwise.
62 */
adxl372_set_activity_threshold_xyz(const struct device * dev,uint8_t axis_reg_h,const struct adxl372_activity_threshold * act)63 static int adxl372_set_activity_threshold_xyz(const struct device *dev,
64 uint8_t axis_reg_h,
65 const struct adxl372_activity_threshold *act)
66 {
67 int i, ret;
68
69 for (i = 0; i < 3; i++) {
70 ret = adxl372_set_activity_threshold(dev, axis_reg_h, act);
71 if (ret) {
72 return ret;
73 }
74 axis_reg_h += 2U;
75 }
76
77 return 0;
78 }
79
80 /**
81 * Set the mode of operation.
82 * @param dev - The device structure.
83 * @param op_mode - Mode of operation.
84 * Accepted values: ADXL372_STANDBY
85 * ADXL372_WAKE_UP
86 * ADXL372_INSTANT_ON
87 * ADXL372_FULL_BW_MEASUREMENT
88 * @return 0 in case of success, negative error code otherwise.
89 */
adxl372_set_op_mode(const struct device * dev,enum adxl372_op_mode op_mode)90 int adxl372_set_op_mode(const struct device *dev, enum adxl372_op_mode op_mode)
91 {
92 struct adxl372_data *data = dev->data;
93
94 int ret = data->hw_tf->write_reg_mask(dev, ADXL372_POWER_CTL,
95 ADXL372_POWER_CTL_MODE_MSK,
96 ADXL372_POWER_CTL_MODE(op_mode));
97
98 #ifdef CONFIG_ADXL372_STREAM
99 if (ret == 0) {
100 data->pwr_reg &= ~ADXL372_POWER_CTL_MODE_MSK;
101 data->pwr_reg |= ADXL372_POWER_CTL_MODE(op_mode);
102 }
103 #endif /* CONFIG_ADXL372_STREAM */
104
105 return ret;
106 }
107
108 /**
109 * Autosleep. When set to 1, autosleep is enabled, and the device enters
110 * wake-up mode automatically upon detection of inactivity.
111 * @param dev - The device structure.
112 * @param enable - Accepted values: true
113 * false
114 * @return 0 in case of success, negative error code otherwise.
115 */
adxl372_set_autosleep(const struct device * dev,bool enable)116 static int adxl372_set_autosleep(const struct device *dev, bool enable)
117 {
118 struct adxl372_data *data = dev->data;
119
120 return data->hw_tf->write_reg_mask(dev, ADXL372_MEASURE,
121 ADXL372_MEASURE_AUTOSLEEP_MSK,
122 ADXL372_MEASURE_AUTOSLEEP_MODE(enable));
123 }
124
125 /**
126 * Select the desired output signal bandwidth.
127 * @param dev - The device structure.
128 * @param bw - bandwidth.
129 * Accepted values: ADXL372_BW_200HZ
130 * ADXL372_BW_400HZ
131 * ADXL372_BW_800HZ
132 * ADXL372_BW_1600HZ
133 * ADXL372_BW_3200HZ
134 * ADXL372_BW_LPF_DISABLED
135 * @return 0 in case of success, negative error code otherwise.
136 */
adxl372_set_bandwidth(const struct device * dev,enum adxl372_bandwidth bw)137 static int adxl372_set_bandwidth(const struct device *dev,
138 enum adxl372_bandwidth bw)
139 {
140 int ret;
141 uint8_t mask;
142 struct adxl372_data *data = dev->data;
143
144 if (bw == ADXL372_BW_LPF_DISABLED) {
145 mask = ADXL372_POWER_CTL_LPF_DIS_MSK;
146 } else {
147 mask = 0U;
148 }
149
150 ret = data->hw_tf->write_reg_mask(dev, ADXL372_POWER_CTL,
151 ADXL372_POWER_CTL_LPF_DIS_MSK, mask);
152 if (ret) {
153 return ret;
154 }
155
156 #ifdef CONFIG_ADXL372_STREAM
157 data->pwr_reg &= ~ADXL372_POWER_CTL_LPF_DIS_MSK;
158 data->pwr_reg |= mask;
159 #endif /* CONFIG_ADXL372_STREAM */
160
161 return data->hw_tf->write_reg_mask(dev, ADXL372_MEASURE,
162 ADXL372_MEASURE_BANDWIDTH_MSK,
163 ADXL372_MEASURE_BANDWIDTH_MODE(bw));
164 }
165
166 /**
167 * Select the desired high-pass filter corner.
168 * @param dev - The device structure.
169 * @param c - bandwidth.
170 * Accepted values: ADXL372_HPF_CORNER_0
171 * ADXL372_HPF_CORNER_1
172 * ADXL372_HPF_CORNER_2
173 * ADXL372_HPF_CORNER_3
174 * ADXL372_HPF_DISABLED
175 * @return 0 in case of success, negative error code otherwise.
176 */
adxl372_set_hpf_corner(const struct device * dev,enum adxl372_hpf_corner c)177 static int adxl372_set_hpf_corner(const struct device *dev,
178 enum adxl372_hpf_corner c)
179 {
180
181 int ret;
182 uint8_t mask;
183 struct adxl372_data *data = dev->data;
184
185 if (c == ADXL372_HPF_DISABLED) {
186 mask = ADXL372_POWER_CTL_HPF_DIS_MSK;
187 } else {
188 mask = 0U;
189 }
190
191 ret = data->hw_tf->write_reg_mask(dev, ADXL372_POWER_CTL,
192 ADXL372_POWER_CTL_HPF_DIS_MSK, mask);
193 if (ret) {
194 return ret;
195 }
196
197 #ifdef CONFIG_ADXL372_STREAM
198 data->pwr_reg &= ~ADXL372_POWER_CTL_HPF_DIS_MSK;
199 data->pwr_reg |= mask;
200 #endif /* CONFIG_ADXL372_STREAM */
201
202 return data->hw_tf->write_reg(dev, ADXL372_HPF, ADXL372_HPF_CORNER(c));
203 }
204
205
206 /**
207 * Link/Loop Activity Processing.
208 * @param dev - The device structure.
209 * @param mode - Mode of operation.
210 * Accepted values: ADXL372_DEFAULT
211 * ADXL372_LINKED
212 * ADXL372_LOOPED
213 * @return 0 in case of success, negative error code otherwise.
214 */
adxl372_set_act_proc_mode(const struct device * dev,enum adxl372_act_proc_mode mode)215 static int adxl372_set_act_proc_mode(const struct device *dev,
216 enum adxl372_act_proc_mode mode)
217 {
218 struct adxl372_data *data = dev->data;
219
220 return data->hw_tf->write_reg_mask(dev, ADXL372_MEASURE,
221 ADXL372_MEASURE_LINKLOOP_MSK,
222 ADXL372_MEASURE_LINKLOOP_MODE(mode));
223 }
224
225 /**
226 * Set Output data rate.
227 * @param dev - The device structure.
228 * @param odr - Output data rate.
229 * Accepted values: ADXL372_ODR_400HZ
230 * ADXL372_ODR_800HZ
231 * ADXL372_ODR_1600HZ
232 * ADXL372_ODR_3200HZ
233 * ADXL372_ODR_6400HZ
234 * @return 0 in case of success, negative error code otherwise.
235 */
adxl372_set_odr(const struct device * dev,enum adxl372_odr odr)236 static int adxl372_set_odr(const struct device *dev, enum adxl372_odr odr)
237 {
238 struct adxl372_data *data = dev->data;
239
240 return data->hw_tf->write_reg_mask(dev, ADXL372_TIMING,
241 ADXL372_TIMING_ODR_MSK,
242 ADXL372_TIMING_ODR_MODE(odr));
243 }
244
245 /**
246 * Select instant on threshold
247 * @param dev - The device structure.
248 * @param mode - 0 = low threshold, 1 = high threshold.
249 * Accepted values: ADXL372_INSTANT_ON_LOW_TH
250 * ADXL372_INSTANT_ON_HIGH_TH
251 * @return 0 in case of success, negative error code otherwise.
252 */
adxl372_set_instant_on_th(const struct device * dev,enum adxl372_instant_on_th_mode mode)253 static int adxl372_set_instant_on_th(const struct device *dev,
254 enum adxl372_instant_on_th_mode mode)
255 {
256 struct adxl372_data *data = dev->data;
257
258 int ret = data->hw_tf->write_reg_mask(dev, ADXL372_POWER_CTL,
259 ADXL372_POWER_CTL_INSTANT_ON_TH_MSK,
260 ADXL372_POWER_CTL_INSTANT_ON_TH_MODE(mode));
261
262 #ifdef CONFIG_ADXL372_STREAM
263 if (ret == 0) {
264 data->pwr_reg &= ~ADXL372_POWER_CTL_INSTANT_ON_TH_MSK;
265 data->pwr_reg |= ADXL372_POWER_CTL_INSTANT_ON_TH_MODE(mode);
266 }
267 #endif /* CONFIG_ADXL372_STREAM */
268
269 return ret;
270 }
271
272 /**
273 * Set the Timer Rate for Wake-Up Mode.
274 * @param dev - The device structure.
275 * @param wur - wake up mode rate
276 * Accepted values: ADXL372_WUR_52ms
277 * ADXL372_WUR_104ms
278 * ADXL372_WUR_208ms
279 * ADXL372_WUR_512ms
280 * ADXL372_WUR_2048ms
281 * ADXL372_WUR_4096ms
282 * ADXL372_WUR_8192ms
283 * ADXL372_WUR_24576ms
284 * @return 0 in case of success, negative error code otherwise.
285 */
adxl372_set_wakeup_rate(const struct device * dev,enum adxl372_wakeup_rate wur)286 static int adxl372_set_wakeup_rate(const struct device *dev,
287 enum adxl372_wakeup_rate wur)
288 {
289 struct adxl372_data *data = dev->data;
290
291 return data->hw_tf->write_reg_mask(dev, ADXL372_TIMING,
292 ADXL372_TIMING_WAKE_UP_RATE_MSK,
293 ADXL372_TIMING_WAKE_UP_RATE_MODE(wur));
294 }
295
296 /**
297 * Set the activity timer
298 * @param dev - The device structure.
299 * @param time - The value set in this register.
300 * @return 0 in case of success, negative error code otherwise.
301 */
adxl372_set_activity_time(const struct device * dev,uint8_t time)302 static int adxl372_set_activity_time(const struct device *dev, uint8_t time)
303 {
304 struct adxl372_data *data = dev->data;
305
306 return data->hw_tf->write_reg(dev, ADXL372_TIME_ACT, time);
307 }
308
309 /**
310 * Set the inactivity timer
311 * @param dev - The device structure.
312 * @param time - is the 16-bit value set by the TIME_INACT_L register
313 * (eight LSBs) and the TIME_INACT_H register (eight MSBs).
314 * @return 0 in case of success, negative error code otherwise.
315 */
adxl372_set_inactivity_time(const struct device * dev,uint16_t time)316 static int adxl372_set_inactivity_time(const struct device *dev,
317 uint16_t time)
318 {
319 int ret;
320 struct adxl372_data *data = dev->data;
321
322 ret = data->hw_tf->write_reg(dev, ADXL372_TIME_INACT_H, time >> 8);
323 if (ret) {
324 return ret;
325 }
326
327 return data->hw_tf->write_reg(dev, ADXL372_TIME_INACT_L, time & 0xFF);
328 }
329
330 /**
331 * Set the filter settling period.
332 * @param dev - The device structure.
333 * @param mode - settle period
334 * Accepted values: ADXL372_FILTER_SETTLE_370
335 * ADXL372_FILTER_SETTLE_16
336 * @return 0 in case of success, negative error code otherwise.
337 */
adxl372_set_filter_settle(const struct device * dev,enum adxl372_filter_settle mode)338 static int adxl372_set_filter_settle(const struct device *dev,
339 enum adxl372_filter_settle mode)
340 {
341 struct adxl372_data *data = dev->data;
342
343 int ret = data->hw_tf->write_reg_mask(dev, ADXL372_POWER_CTL,
344 ADXL372_POWER_CTL_FIL_SETTLE_MSK,
345 ADXL372_POWER_CTL_FIL_SETTLE_MODE(mode));
346
347 #ifdef CONFIG_ADXL372_STREAM
348 if (ret == 0) {
349 data->pwr_reg &= ~ADXL372_POWER_CTL_FIL_SETTLE_MSK;
350 data->pwr_reg |= ADXL372_POWER_CTL_FIL_SETTLE_MODE(mode);
351 }
352 #endif /* CONFIG_ADXL372_STREAM */
353
354 return ret;
355 }
356
357 /**
358 * Configure the INT1 and INT2 interrupt pins.
359 * @param dev - The device structure.
360 * @param int1 - INT1 interrupt pins.
361 * @param int2 - INT2 interrupt pins.
362 * @return 0 in case of success, negative error code otherwise.
363 */
adxl372_interrupt_config(const struct device * dev,uint8_t int1,uint8_t int2)364 static int adxl372_interrupt_config(const struct device *dev,
365 uint8_t int1,
366 uint8_t int2)
367 {
368 int ret;
369 struct adxl372_data *data = dev->data;
370
371 ret = data->hw_tf->write_reg(dev, ADXL372_INT1_MAP, int1);
372 if (ret) {
373 return ret;
374 }
375
376 return data->hw_tf->write_reg(dev, ADXL372_INT2_MAP, int2);
377
378 }
379
380 /**
381 * Get the STATUS, STATUS2, FIFO_ENTRIES and FIFO_ENTRIES2 registers data
382 * @param dev - The device structure.
383 * @param status1 - Data stored in the STATUS1 register
384 * @param status2 - Data stored in the STATUS2 register
385 * @param fifo_entries - Number of valid data samples present in the
386 * FIFO buffer (0 to 512)
387 * @return 0 in case of success, negative error code otherwise.
388 */
adxl372_get_status(const struct device * dev,uint8_t * status1,uint8_t * status2,uint16_t * fifo_entries)389 int adxl372_get_status(const struct device *dev,
390 uint8_t *status1,
391 uint8_t *status2,
392 uint16_t *fifo_entries)
393 {
394 struct adxl372_data *data = dev->data;
395 uint8_t buf[4], length = 1U;
396 int ret;
397
398 if (status2) {
399 length++;
400 }
401
402 if (fifo_entries) {
403 if (status2) {
404 length += 2U;
405 } else {
406 /* Registers STATUS1, STATUS2, FIFO_ENTRIES2 and FIFO_ENTRIES1
407 * are one after the other. If user wants fifo_entries and
408 * not status2, to get the correct values, STATUS2 register
409 * also must be read but read value will be ignored.
410 */
411 length += 3U;
412 }
413 }
414
415 ret = data->hw_tf->read_reg_multiple(dev, ADXL372_STATUS_1, buf, length);
416
417 *status1 = buf[0];
418
419 if (status2) {
420 *status2 = buf[1];
421 }
422
423 if (fifo_entries) {
424 *fifo_entries = ((buf[2] & 0x3) << 8) | buf[3];
425 }
426
427 return ret;
428 }
429
430 /**
431 * Software reset.
432 * @param dev - The device structure.
433 * @return 0 in case of success, negative error code otherwise.
434 */
adxl372_reset(const struct device * dev)435 static int adxl372_reset(const struct device *dev)
436 {
437 int ret;
438 struct adxl372_data *data = dev->data;
439
440 ret = adxl372_set_op_mode(dev, ADXL372_STANDBY);
441 if (ret) {
442 return ret;
443 }
444 /* Writing code 0x52 resets the device */
445 ret = data->hw_tf->write_reg(dev, ADXL372_RESET, ADXL372_RESET_CODE);
446 k_sleep(K_MSEC(1));
447
448 return ret;
449 }
450
451 /**
452 * Configure the operating parameters for the FIFO.
453 * @param dev - The device structure.
454 * @param mode - FIFO Mode. Specifies FIFO operating mode.
455 * Accepted values: ADXL372_FIFO_BYPASSED
456 * ADXL372_FIFO_STREAMED
457 * ADXL372_FIFO_TRIGGERED
458 * ADXL372_FIFO_OLD_SAVED
459 * @param format - FIFO Format. Specifies the data is stored in the FIFO buffer.
460 * Accepted values: ADXL372_XYZ_FIFO
461 * ADXL372_X_FIFO
462 * ADXL372_Y_FIFO
463 * ADXL372_XY_FIFO
464 * ADXL372_Z_FIFO
465 * ADXL372_XZ_FIFO
466 * ADXL372_YZ_FIFO
467 * ADXL372_XYZ_PEAK_FIFO
468 * @param fifo_samples - FIFO Samples. Watermark number of FIFO samples that
469 * triggers a FIFO_FULL condition when reached.
470 * Values range from 0 to 512.
471 * @return 0 in case of success, negative error code otherwise.
472 */
adxl372_configure_fifo(const struct device * dev,enum adxl372_fifo_mode mode,enum adxl372_fifo_format format,uint16_t fifo_samples)473 int adxl372_configure_fifo(const struct device *dev, enum adxl372_fifo_mode mode,
474 enum adxl372_fifo_format format, uint16_t fifo_samples)
475 {
476 struct adxl372_data *data = dev->data;
477 uint8_t fifo_config;
478 int ret;
479
480 if (fifo_samples > 512) {
481 return -EINVAL;
482 }
483
484 /*
485 * All FIFO modes must be configured while in standby mode.
486 */
487 ret = adxl372_set_op_mode(dev, ADXL372_STANDBY);
488 if (ret) {
489 return ret;
490 }
491
492 fifo_config = (ADXL372_FIFO_CTL_FORMAT_MODE(format) |
493 ADXL372_FIFO_CTL_MODE_MODE(mode) |
494 ADXL372_FIFO_CTL_SAMPLES_MODE(fifo_samples));
495
496 ret = data->hw_tf->write_reg(dev, ADXL372_FIFO_CTL, fifo_config);
497 if (ret) {
498 return ret;
499 }
500 ret = data->hw_tf->write_reg(dev, ADXL372_FIFO_SAMPLES, fifo_samples & 0xFF);
501 if (ret) {
502 return ret;
503 }
504
505 data->fifo_config.fifo_format = format;
506 data->fifo_config.fifo_mode = mode;
507 data->fifo_config.fifo_samples = fifo_samples;
508
509 return 0;
510 }
511
512 /**
513 * Retrieve 3-axis acceleration data
514 * @param dev - The device structure.
515 * @param maxpeak - Retrieve the highest magnitude (x, y, z) sample recorded
516 * since the last read of the MAXPEAK registers
517 * @param accel_data - pointer to a variable of type adxl372_xyz_accel_data
518 * where (x, y, z) acceleration data will be stored.
519 * @return 0 in case of success, negative error code otherwise.
520 */
adxl372_get_accel_data(const struct device * dev,bool maxpeak,struct adxl372_xyz_accel_data * accel_data)521 int adxl372_get_accel_data(const struct device *dev, bool maxpeak,
522 struct adxl372_xyz_accel_data *accel_data)
523 {
524 struct adxl372_data *data = dev->data;
525 uint8_t buf[6];
526 uint8_t status1;
527 int ret;
528
529 if (!IS_ENABLED(CONFIG_ADXL372_TRIGGER)) {
530 do {
531 adxl372_get_status(dev, &status1, NULL, NULL);
532 } while (!(ADXL372_STATUS_1_DATA_RDY(status1)));
533 }
534
535 ret = data->hw_tf->read_reg_multiple(dev, maxpeak ? ADXL372_X_MAXPEAK_H :
536 ADXL372_X_DATA_H, buf, 6);
537 #ifdef CONFIG_ADXL372_STREAM
538 accel_data->is_fifo = 0;
539 #endif /* CONFIG_ADXL372_STREAM */
540 accel_data->x = (buf[0] << 8) | (buf[1] & 0xF0);
541 accel_data->y = (buf[2] << 8) | (buf[3] & 0xF0);
542 accel_data->z = (buf[4] << 8) | (buf[5] & 0xF0);
543
544 return ret;
545 }
546
adxl372_attr_set_odr(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)547 static int adxl372_attr_set_odr(const struct device *dev,
548 enum sensor_channel chan,
549 enum sensor_attribute attr,
550 const struct sensor_value *val)
551 {
552 enum adxl372_odr odr;
553 struct adxl372_dev_config *cfg = (struct adxl372_dev_config *)dev->config;
554
555 switch (val->val1) {
556 case 400:
557 odr = ADXL372_ODR_400HZ;
558 break;
559 case 800:
560 odr = ADXL372_ODR_800HZ;
561 break;
562 case 1600:
563 odr = ADXL372_ODR_1600HZ;
564 break;
565 case 3200:
566 odr = ADXL372_ODR_3200HZ;
567 break;
568 case 6400:
569 odr = ADXL372_ODR_6400HZ;
570 break;
571 default:
572 return -EINVAL;
573 }
574
575 int ret = adxl372_set_odr(dev, odr);
576
577 if (ret == 0) {
578 cfg->odr = odr;
579 }
580
581 return ret;
582 }
583
adxl372_attr_set_thresh(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)584 static int adxl372_attr_set_thresh(const struct device *dev,
585 enum sensor_channel chan,
586 enum sensor_attribute attr,
587 const struct sensor_value *val)
588 {
589 const struct adxl372_dev_config *cfg = dev->config;
590 struct adxl372_activity_threshold threshold;
591 int64_t llvalue;
592 int32_t value;
593 int64_t micro_ms2 = val->val1 * 1000000LL + val->val2;
594 uint8_t reg;
595
596 llvalue = llabs((micro_ms2 * 10) / SENSOR_G);
597
598 if (llvalue > 2047) {
599 return -EINVAL;
600 }
601
602 value = (int32_t) llvalue;
603
604 threshold.thresh = value;
605 threshold.enable = cfg->activity_th.enable;
606 threshold.referenced = cfg->activity_th.referenced;
607
608 if (attr == SENSOR_ATTR_UPPER_THRESH) {
609 reg = ADXL372_X_THRESH_ACT_H;
610 } else {
611 reg = ADXL372_X_THRESH_INACT_H;
612 }
613
614 switch (chan) {
615 case SENSOR_CHAN_ACCEL_X:
616 return adxl372_set_activity_threshold(dev, reg, &threshold);
617 case SENSOR_CHAN_ACCEL_Y:
618 return adxl372_set_activity_threshold(dev, reg + 2, &threshold);
619 case SENSOR_CHAN_ACCEL_Z:
620 return adxl372_set_activity_threshold(dev, reg + 4, &threshold);
621 case SENSOR_CHAN_ACCEL_XYZ:
622 return adxl372_set_activity_threshold_xyz(dev, reg, &threshold);
623 default:
624 LOG_ERR("attr_set() not supported on this channel");
625 return -ENOTSUP;
626 }
627 }
628
adxl372_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)629 static int adxl372_attr_set(const struct device *dev,
630 enum sensor_channel chan,
631 enum sensor_attribute attr,
632 const struct sensor_value *val)
633 {
634 switch (attr) {
635 case SENSOR_ATTR_SAMPLING_FREQUENCY:
636 return adxl372_attr_set_odr(dev, chan, attr, val);
637 case SENSOR_ATTR_UPPER_THRESH:
638 case SENSOR_ATTR_LOWER_THRESH:
639 return adxl372_attr_set_thresh(dev, chan, attr, val);
640 default:
641 return -ENOTSUP;
642 }
643 }
644
adxl372_sample_fetch(const struct device * dev,enum sensor_channel chan)645 static int adxl372_sample_fetch(const struct device *dev,
646 enum sensor_channel chan)
647 {
648 const struct adxl372_dev_config *cfg = dev->config;
649 struct adxl372_data *data = dev->data;
650
651 return adxl372_get_accel_data(dev, cfg->max_peak_detect_mode,
652 &data->sample);
653 }
654
adxl372_accel_convert(struct sensor_value * val,int16_t value)655 void adxl372_accel_convert(struct sensor_value *val, int16_t value)
656 {
657 /*
658 * Sensor resolution is 100mg/LSB, 12-bit value needs to be right
659 * shifted by 4 or divided by 16. Overall this results in a scale of 160
660 */
661 int32_t micro_ms2 = value * (SENSOR_G / (16 * 1000 / 100));
662
663 val->val1 = micro_ms2 / 1000000;
664 val->val2 = micro_ms2 % 1000000;
665 }
666
adxl372_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)667 static int adxl372_channel_get(const struct device *dev,
668 enum sensor_channel chan,
669 struct sensor_value *val)
670 {
671 struct adxl372_data *data = dev->data;
672
673 switch (chan) {
674 case SENSOR_CHAN_ACCEL_X:
675 adxl372_accel_convert(val, data->sample.x);
676 break;
677 case SENSOR_CHAN_ACCEL_Y:
678 adxl372_accel_convert(val, data->sample.y);
679 break;
680 case SENSOR_CHAN_ACCEL_Z:
681 adxl372_accel_convert(val, data->sample.z);
682 break;
683 case SENSOR_CHAN_ACCEL_XYZ:
684 adxl372_accel_convert(val++, data->sample.x);
685 adxl372_accel_convert(val++, data->sample.y);
686 adxl372_accel_convert(val, data->sample.z);
687 break;
688 default:
689 return -ENOTSUP;
690 }
691
692 return 0;
693 }
694
695 static DEVICE_API(sensor, adxl372_api_funcs) = {
696 .attr_set = adxl372_attr_set,
697 .sample_fetch = adxl372_sample_fetch,
698 .channel_get = adxl372_channel_get,
699 #ifdef CONFIG_ADXL372_TRIGGER
700 .trigger_set = adxl372_trigger_set,
701 #endif
702 #ifdef CONFIG_SENSOR_ASYNC_API
703 .submit = adxl372_submit,
704 .get_decoder = adxl372_get_decoder,
705 #endif /* CONFIG_SENSOR_ASYNC_API */
706
707 };
708
adxl372_probe(const struct device * dev)709 static int adxl372_probe(const struct device *dev)
710 {
711 const struct adxl372_dev_config *cfg = dev->config;
712 struct adxl372_data *data = dev->data;
713 uint8_t dev_id, part_id;
714 int ret;
715
716 ret = data->hw_tf->read_reg(dev, ADXL372_DEVID, &dev_id);
717 if (ret) {
718 return ret;
719 }
720 ret = data->hw_tf->read_reg(dev, ADXL372_PARTID, &part_id);
721 if (ret) {
722 return ret;
723 }
724
725 if (dev_id != ADXL372_DEVID_VAL || part_id != ADXL372_PARTID_VAL) {
726 LOG_ERR("failed to read id (0x%X:0x%X)", dev_id, part_id);
727 return -ENODEV;
728 }
729
730 #ifdef CONFIG_ADXL372_TRIGGER
731 data->act_proc_mode = ADXL372_LINKED,
732 #else
733 data->act_proc_mode = ADXL372_LOOPED,
734 #endif
735
736 /* Device settings */
737 ret = adxl372_set_op_mode(dev, ADXL372_STANDBY);
738 if (ret) {
739 return ret;
740 }
741
742 ret = adxl372_reset(dev);
743 if (ret) {
744 return ret;
745 }
746
747 ret = adxl372_set_hpf_corner(dev, cfg->hpf);
748 if (ret) {
749 return ret;
750 }
751
752 ret = adxl372_set_bandwidth(dev, cfg->bw);
753 if (ret) {
754 return ret;
755 }
756
757 ret = adxl372_set_odr(dev, cfg->odr);
758 if (ret) {
759 return ret;
760 }
761
762 ret = adxl372_set_wakeup_rate(dev, cfg->wur);
763 if (ret) {
764 return ret;
765 }
766
767 ret = adxl372_set_autosleep(dev, cfg->autosleep);
768 if (ret) {
769 return ret;
770 }
771
772 ret = adxl372_set_instant_on_th(dev, cfg->th_mode);
773 if (ret) {
774 return ret;
775 }
776
777 ret = adxl372_set_activity_threshold_xyz(dev, ADXL372_X_THRESH_ACT_H,
778 &cfg->activity_th);
779 if (ret) {
780 return ret;
781 }
782
783 ret = adxl372_set_activity_threshold_xyz(dev, ADXL372_X_THRESH_INACT_H,
784 &cfg->inactivity_th);
785 if (ret) {
786 return ret;
787 }
788
789 ret = adxl372_set_activity_time(dev, cfg->activity_time);
790 if (ret) {
791 return ret;
792 }
793
794 ret = adxl372_set_inactivity_time(dev, cfg->inactivity_time);
795 if (ret) {
796 return ret;
797 }
798
799 ret = adxl372_set_filter_settle(dev, cfg->filter_settle);
800 if (ret) {
801 return ret;
802 }
803
804 ret = adxl372_configure_fifo(dev, cfg->fifo_config.fifo_mode,
805 cfg->fifo_config.fifo_format,
806 cfg->fifo_config.fifo_samples);
807 if (ret) {
808 return ret;
809 }
810
811 #ifdef CONFIG_ADXL372_TRIGGER
812 if (adxl372_init_interrupt(dev) < 0) {
813 LOG_ERR("Failed to initialize interrupt!");
814 return -EIO;
815 }
816 #endif
817
818 ret = adxl372_interrupt_config(dev, cfg->int1_config, cfg->int2_config);
819 if (ret) {
820 return ret;
821 }
822
823 ret = adxl372_set_op_mode(dev, cfg->op_mode);
824 if (ret) {
825 return ret;
826 }
827
828 return adxl372_set_act_proc_mode(dev, data->act_proc_mode);
829 }
830
adxl372_init(const struct device * dev)831 static int adxl372_init(const struct device *dev)
832 {
833 int ret;
834 const struct adxl372_dev_config *cfg = dev->config;
835
836 ret = cfg->bus_init(dev);
837 if (ret < 0) {
838 LOG_ERR("Failed to initialize sensor bus");
839 return ret;
840 }
841
842 if (adxl372_probe(dev) < 0) {
843 return -ENODEV;
844 }
845
846 return 0;
847 }
848
849 #if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0
850 #warning "ADXL372 driver enabled without any devices"
851 #endif
852
853 /*
854 * Device creation macro, shared by ADXL372_DEFINE_SPI() and
855 * ADXL372_DEFINE_I2C().
856 */
857
858 #define ADXL372_DEVICE_INIT(inst) \
859 SENSOR_DEVICE_DT_INST_DEFINE(inst, \
860 adxl372_init, \
861 NULL, \
862 &adxl372_data_##inst, \
863 &adxl372_config_##inst, \
864 POST_KERNEL, \
865 CONFIG_SENSOR_INIT_PRIORITY, \
866 &adxl372_api_funcs);
867
868 /*
869 * Instantiation macros used when a device is on a SPI bus.
870 */
871 #define ADXL372_SPI_CFG SPI_WORD_SET(8) | SPI_TRANSFER_MSB
872
873 #define ADXL372_RTIO_DEFINE(inst) \
874 SPI_DT_IODEV_DEFINE(adxl372_iodev_##inst, DT_DRV_INST(inst), ADXL372_SPI_CFG, 0U); \
875 RTIO_DEFINE(adxl372_rtio_ctx_##inst, 16, 16);
876
877 #ifdef CONFIG_ADXL372_TRIGGER
878 #define ADXL372_CFG_IRQ(inst) \
879 .interrupt = GPIO_DT_SPEC_INST_GET(inst, int1_gpios),
880 #else
881 #define ADXL372_CFG_IRQ(inst)
882 #endif /* CONFIG_ADXL372_TRIGGER */
883
884 #define ADXL372_CONFIG(inst) \
885 .bw = DT_INST_PROP(inst, bw), \
886 .hpf = DT_INST_PROP(inst, hpf), \
887 .odr = DT_INST_PROP(inst, odr), \
888 .max_peak_detect_mode = IS_ENABLED(CONFIG_ADXL372_PEAK_DETECT_MODE), \
889 .th_mode = ADXL372_INSTANT_ON_LOW_TH, \
890 .autosleep = false, \
891 .wur = ADXL372_WUR_52ms, \
892 .activity_th.thresh = CONFIG_ADXL372_ACTIVITY_THRESHOLD / 100, \
893 .activity_th.referenced = \
894 IS_ENABLED(CONFIG_ADXL372_REFERENCED_ACTIVITY_DETECTION_MODE), \
895 .activity_th.enable = 1, \
896 .activity_time = CONFIG_ADXL372_ACTIVITY_TIME, \
897 .inactivity_th.thresh = CONFIG_ADXL372_INACTIVITY_THRESHOLD / 100, \
898 .inactivity_th.referenced = \
899 IS_ENABLED(CONFIG_ADXL372_REFERENCED_ACTIVITY_DETECTION_MODE), \
900 .inactivity_th.enable = 1, \
901 .inactivity_time = CONFIG_ADXL372_INACTIVITY_TIME, \
902 .filter_settle = ADXL372_FILTER_SETTLE_370, \
903 .fifo_config.fifo_mode = ADXL372_FIFO_STREAMED, \
904 .fifo_config.fifo_format = ADXL372_XYZ_PEAK_FIFO, \
905 .fifo_config.fifo_samples = 128, \
906 .op_mode = ADXL372_FULL_BW_MEASUREMENT, \
907
908 #define ADXL372_CONFIG_SPI(inst) \
909 { \
910 .bus_init = adxl372_spi_init, \
911 .spi = SPI_DT_SPEC_INST_GET(inst, ADXL372_SPI_CFG, 0), \
912 ADXL372_CONFIG(inst) \
913 COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \
914 (ADXL372_CFG_IRQ(inst)), ()) \
915 }
916
917 #define ADXL372_DEFINE_SPI(inst) \
918 IF_ENABLED(CONFIG_ADXL372_STREAM, (ADXL372_RTIO_DEFINE(inst))); \
919 static struct adxl372_data adxl372_data_##inst = { \
920 IF_ENABLED(CONFIG_ADXL372_STREAM, (.rtio_ctx = &adxl372_rtio_ctx_##inst, \
921 .iodev = &adxl372_iodev_##inst,)) \
922 }; \
923 static const struct adxl372_dev_config adxl372_config_##inst = \
924 ADXL372_CONFIG_SPI(inst); \
925 ADXL372_DEVICE_INIT(inst)
926
927 /*
928 * Instantiation macros used when a device is on an I2C bus.
929 */
930
931 #define ADXL372_CONFIG_I2C(inst) \
932 { \
933 .bus_init = adxl372_i2c_init, \
934 .i2c = I2C_DT_SPEC_INST_GET(inst), \
935 ADXL372_CONFIG(inst) \
936 COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \
937 (ADXL372_CFG_IRQ(inst)), ()) \
938 }
939
940 #define ADXL372_DEFINE_I2C(inst) \
941 static struct adxl372_data adxl372_data_##inst; \
942 static const struct adxl372_dev_config adxl372_config_##inst = \
943 ADXL372_CONFIG_I2C(inst); \
944 ADXL372_DEVICE_INIT(inst)
945 /*
946 * Main instantiation macro. Use of COND_CODE_1() selects the right
947 * bus-specific macro at preprocessor time.
948 */
949
950 #define ADXL372_DEFINE(inst) \
951 COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
952 (ADXL372_DEFINE_SPI(inst)), \
953 (ADXL372_DEFINE_I2C(inst)))
954
955 DT_INST_FOREACH_STATUS_OKAY(ADXL372_DEFINE)
956