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