| /* |
| * Copyright (c) 2018 Analog Devices Inc. |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #define DT_DRV_COMPAT adi_adxl372 |
| |
| #include <zephyr/drivers/sensor.h> |
| #include <zephyr/kernel.h> |
| #include <zephyr/device.h> |
| #include <string.h> |
| #include <zephyr/init.h> |
| #include <zephyr/sys/printk.h> |
| #include <zephyr/sys/__assert.h> |
| #include <stdlib.h> |
| #include <zephyr/logging/log.h> |
| |
| #include "adxl372.h" |
| |
| LOG_MODULE_REGISTER(ADXL372, CONFIG_SENSOR_LOG_LEVEL); |
| |
| /** |
| * Set the threshold for activity detection for a single axis |
| * @param dev - The device structure. |
| * @param axis_reg_h - The high part of the activity register. |
| * @param act - The activity config structure. |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int adxl372_set_activity_threshold(const struct device *dev, |
| uint8_t axis_reg_h, |
| const struct adxl372_activity_threshold *act) |
| { |
| int ret; |
| uint8_t val; |
| struct adxl372_data *data = dev->data; |
| |
| ret = data->hw_tf->write_reg(dev, axis_reg_h++, act->thresh >> 3); |
| if (ret) { |
| return ret; |
| } |
| |
| switch (axis_reg_h) { |
| case ADXL372_X_THRESH_ACT_L: |
| case ADXL372_X_THRESH_INACT_L: |
| case ADXL372_X_THRESH_ACT2_L: |
| val = (act->thresh << 5) | (act->referenced << 1) | act->enable; |
| break; |
| default: |
| val = (act->thresh << 5) | act->enable; |
| } |
| |
| return data->hw_tf->write_reg(dev, axis_reg_h, val); |
| } |
| |
| /** |
| * Set the threshold for activity detection for all 3-axis |
| * @param dev - The device structure. |
| * @param axis_reg_h - The high part of the activity register. |
| * @param act - The activity config structure. |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int adxl372_set_activity_threshold_xyz(const struct device *dev, |
| uint8_t axis_reg_h, |
| const struct adxl372_activity_threshold *act) |
| { |
| int i, ret; |
| |
| for (i = 0; i < 3; i++) { |
| ret = adxl372_set_activity_threshold(dev, axis_reg_h, act); |
| if (ret) { |
| return ret; |
| } |
| axis_reg_h += 2U; |
| } |
| |
| return 0; |
| } |
| |
| /** |
| * Set the mode of operation. |
| * @param dev - The device structure. |
| * @param op_mode - Mode of operation. |
| * Accepted values: ADXL372_STANDBY |
| * ADXL372_WAKE_UP |
| * ADXL372_INSTANT_ON |
| * ADXL372_FULL_BW_MEASUREMENT |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int adxl372_set_op_mode(const struct device *dev, |
| enum adxl372_op_mode op_mode) |
| { |
| struct adxl372_data *data = dev->data; |
| |
| return data->hw_tf->write_reg_mask(dev, ADXL372_POWER_CTL, |
| ADXL372_POWER_CTL_MODE_MSK, |
| ADXL372_POWER_CTL_MODE(op_mode)); |
| } |
| |
| /** |
| * Autosleep. When set to 1, autosleep is enabled, and the device enters |
| * wake-up mode automatically upon detection of inactivity. |
| * @param dev - The device structure. |
| * @param enable - Accepted values: true |
| * false |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int adxl372_set_autosleep(const struct device *dev, bool enable) |
| { |
| struct adxl372_data *data = dev->data; |
| |
| return data->hw_tf->write_reg_mask(dev, ADXL372_MEASURE, |
| ADXL372_MEASURE_AUTOSLEEP_MSK, |
| ADXL372_MEASURE_AUTOSLEEP_MODE(enable)); |
| } |
| |
| /** |
| * Select the desired output signal bandwidth. |
| * @param dev - The device structure. |
| * @param bw - bandwidth. |
| * Accepted values: ADXL372_BW_200HZ |
| * ADXL372_BW_400HZ |
| * ADXL372_BW_800HZ |
| * ADXL372_BW_1600HZ |
| * ADXL372_BW_3200HZ |
| * ADXL372_BW_LPF_DISABLED |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int adxl372_set_bandwidth(const struct device *dev, |
| enum adxl372_bandwidth bw) |
| { |
| int ret; |
| uint8_t mask; |
| struct adxl372_data *data = dev->data; |
| |
| if (bw == ADXL372_BW_LPF_DISABLED) { |
| mask = ADXL372_POWER_CTL_LPF_DIS_MSK; |
| } else { |
| mask = 0U; |
| } |
| |
| ret = data->hw_tf->write_reg_mask(dev, ADXL372_POWER_CTL, |
| ADXL372_POWER_CTL_LPF_DIS_MSK, mask); |
| if (ret) { |
| return ret; |
| } |
| |
| return data->hw_tf->write_reg_mask(dev, ADXL372_MEASURE, |
| ADXL372_MEASURE_BANDWIDTH_MSK, |
| ADXL372_MEASURE_BANDWIDTH_MODE(bw)); |
| } |
| |
| /** |
| * Select the desired high-pass filter corner. |
| * @param dev - The device structure. |
| * @param c - bandwidth. |
| * Accepted values: ADXL372_HPF_CORNER_0 |
| * ADXL372_HPF_CORNER_1 |
| * ADXL372_HPF_CORNER_2 |
| * ADXL372_HPF_CORNER_3 |
| * ADXL372_HPF_DISABLED |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int adxl372_set_hpf_corner(const struct device *dev, |
| enum adxl372_hpf_corner c) |
| { |
| |
| int ret; |
| uint8_t mask; |
| struct adxl372_data *data = dev->data; |
| |
| if (c == ADXL372_HPF_DISABLED) { |
| mask = ADXL372_POWER_CTL_HPF_DIS_MSK; |
| } else { |
| mask = 0U; |
| } |
| |
| ret = data->hw_tf->write_reg_mask(dev, ADXL372_POWER_CTL, |
| ADXL372_POWER_CTL_HPF_DIS_MSK, mask); |
| if (ret) { |
| return ret; |
| } |
| |
| return data->hw_tf->write_reg(dev, ADXL372_HPF, ADXL372_HPF_CORNER(c)); |
| } |
| |
| |
| /** |
| * Link/Loop Activity Processing. |
| * @param dev - The device structure. |
| * @param mode - Mode of operation. |
| * Accepted values: ADXL372_DEFAULT |
| * ADXL372_LINKED |
| * ADXL372_LOOPED |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int adxl372_set_act_proc_mode(const struct device *dev, |
| enum adxl372_act_proc_mode mode) |
| { |
| struct adxl372_data *data = dev->data; |
| |
| return data->hw_tf->write_reg_mask(dev, ADXL372_MEASURE, |
| ADXL372_MEASURE_LINKLOOP_MSK, |
| ADXL372_MEASURE_LINKLOOP_MODE(mode)); |
| } |
| |
| /** |
| * Set Output data rate. |
| * @param dev - The device structure. |
| * @param odr - Output data rate. |
| * Accepted values: ADXL372_ODR_400HZ |
| * ADXL372_ODR_800HZ |
| * ADXL372_ODR_1600HZ |
| * ADXL372_ODR_3200HZ |
| * ADXL372_ODR_6400HZ |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int adxl372_set_odr(const struct device *dev, enum adxl372_odr odr) |
| { |
| struct adxl372_data *data = dev->data; |
| |
| return data->hw_tf->write_reg_mask(dev, ADXL372_TIMING, |
| ADXL372_TIMING_ODR_MSK, |
| ADXL372_TIMING_ODR_MODE(odr)); |
| } |
| |
| /** |
| * Select instant on threshold |
| * @param dev - The device structure. |
| * @param mode - 0 = low threshold, 1 = high threshold. |
| * Accepted values: ADXL372_INSTANT_ON_LOW_TH |
| * ADXL372_INSTANT_ON_HIGH_TH |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int adxl372_set_instant_on_th(const struct device *dev, |
| enum adxl372_instant_on_th_mode mode) |
| { |
| struct adxl372_data *data = dev->data; |
| |
| return data->hw_tf->write_reg_mask(dev, ADXL372_POWER_CTL, |
| ADXL372_POWER_CTL_INSTANT_ON_TH_MSK, |
| ADXL372_POWER_CTL_INSTANT_ON_TH_MODE(mode)); |
| } |
| |
| /** |
| * Set the Timer Rate for Wake-Up Mode. |
| * @param dev - The device structure. |
| * @param wur - wake up mode rate |
| * Accepted values: ADXL372_WUR_52ms |
| * ADXL372_WUR_104ms |
| * ADXL372_WUR_208ms |
| * ADXL372_WUR_512ms |
| * ADXL372_WUR_2048ms |
| * ADXL372_WUR_4096ms |
| * ADXL372_WUR_8192ms |
| * ADXL372_WUR_24576ms |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int adxl372_set_wakeup_rate(const struct device *dev, |
| enum adxl372_wakeup_rate wur) |
| { |
| struct adxl372_data *data = dev->data; |
| |
| return data->hw_tf->write_reg_mask(dev, ADXL372_TIMING, |
| ADXL372_TIMING_WAKE_UP_RATE_MSK, |
| ADXL372_TIMING_WAKE_UP_RATE_MODE(wur)); |
| } |
| |
| /** |
| * Set the activity timer |
| * @param dev - The device structure. |
| * @param time - The value set in this register. |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int adxl372_set_activity_time(const struct device *dev, uint8_t time) |
| { |
| struct adxl372_data *data = dev->data; |
| |
| return data->hw_tf->write_reg(dev, ADXL372_TIME_ACT, time); |
| } |
| |
| /** |
| * Set the inactivity timer |
| * @param dev - The device structure. |
| * @param time - is the 16-bit value set by the TIME_INACT_L register |
| * (eight LSBs) and the TIME_INACT_H register (eight MSBs). |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int adxl372_set_inactivity_time(const struct device *dev, |
| uint16_t time) |
| { |
| int ret; |
| struct adxl372_data *data = dev->data; |
| |
| ret = data->hw_tf->write_reg(dev, ADXL372_TIME_INACT_H, time >> 8); |
| if (ret) { |
| return ret; |
| } |
| |
| return data->hw_tf->write_reg(dev, ADXL372_TIME_INACT_L, time & 0xFF); |
| } |
| |
| /** |
| * Set the filter settling period. |
| * @param dev - The device structure. |
| * @param mode - settle period |
| * Accepted values: ADXL372_FILTER_SETTLE_370 |
| * ADXL372_FILTER_SETTLE_16 |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int adxl372_set_filter_settle(const struct device *dev, |
| enum adxl372_filter_settle mode) |
| { |
| struct adxl372_data *data = dev->data; |
| |
| return data->hw_tf->write_reg_mask(dev, ADXL372_POWER_CTL, |
| ADXL372_POWER_CTL_FIL_SETTLE_MSK, |
| ADXL372_POWER_CTL_FIL_SETTLE_MODE(mode)); |
| } |
| |
| /** |
| * Configure the INT1 and INT2 interrupt pins. |
| * @param dev - The device structure. |
| * @param int1 - INT1 interrupt pins. |
| * @param int2 - INT2 interrupt pins. |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int adxl372_interrupt_config(const struct device *dev, |
| uint8_t int1, |
| uint8_t int2) |
| { |
| int ret; |
| struct adxl372_data *data = dev->data; |
| |
| ret = data->hw_tf->write_reg(dev, ADXL372_INT1_MAP, int1); |
| if (ret) { |
| return ret; |
| } |
| |
| return data->hw_tf->write_reg(dev, ADXL372_INT2_MAP, int2); |
| |
| } |
| |
| /** |
| * Get the STATUS, STATUS2, FIFO_ENTRIES and FIFO_ENTRIES2 registers data |
| * @param dev - The device structure. |
| * @param status1 - Data stored in the STATUS1 register |
| * @param status2 - Data stored in the STATUS2 register |
| * @param fifo_entries - Number of valid data samples present in the |
| * FIFO buffer (0 to 512) |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| int adxl372_get_status(const struct device *dev, |
| uint8_t *status1, |
| uint8_t *status2, |
| uint16_t *fifo_entries) |
| { |
| struct adxl372_data *data = dev->data; |
| uint8_t buf[4], length = 1U; |
| int ret; |
| |
| if (status2) { |
| length++; |
| } |
| |
| if (fifo_entries) { |
| length += 2U; |
| } |
| |
| ret = data->hw_tf->read_reg_multiple(dev, ADXL372_STATUS_1, buf, length); |
| |
| *status1 = buf[0]; |
| |
| if (status2) { |
| *status2 = buf[1]; |
| } |
| |
| if (fifo_entries) { |
| *fifo_entries = ((buf[2] & 0x3) << 8) | buf[3]; |
| } |
| |
| return ret; |
| } |
| |
| /** |
| * Software reset. |
| * @param dev - The device structure. |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int adxl372_reset(const struct device *dev) |
| { |
| int ret; |
| struct adxl372_data *data = dev->data; |
| |
| ret = adxl372_set_op_mode(dev, ADXL372_STANDBY); |
| if (ret) { |
| return ret; |
| } |
| /* Writing code 0x52 resets the device */ |
| ret = data->hw_tf->write_reg(dev, ADXL372_RESET, ADXL372_RESET_CODE); |
| k_sleep(K_MSEC(1000)); |
| |
| return ret; |
| } |
| |
| /** |
| * Configure the operating parameters for the FIFO. |
| * @param dev - The device structure. |
| * @param mode - FIFO Mode. Specifies FIFO operating mode. |
| * Accepted values: ADXL372_FIFO_BYPASSED |
| * ADXL372_FIFO_STREAMED |
| * ADXL372_FIFO_TRIGGERED |
| * ADXL372_FIFO_OLD_SAVED |
| * @param format - FIFO Format. Specifies the data is stored in the FIFO buffer. |
| * Accepted values: ADXL372_XYZ_FIFO |
| * ADXL372_X_FIFO |
| * ADXL372_Y_FIFO |
| * ADXL372_XY_FIFO |
| * ADXL372_Z_FIFO |
| * ADXL372_XZ_FIFO |
| * ADXL372_YZ_FIFO |
| * ADXL372_XYZ_PEAK_FIFO |
| * @param fifo_samples - FIFO Samples. Watermark number of FIFO samples that |
| * triggers a FIFO_FULL condition when reached. |
| * Values range from 0 to 512. |
| |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int adxl372_configure_fifo(const struct device *dev, |
| enum adxl372_fifo_mode mode, |
| enum adxl372_fifo_format format, |
| uint16_t fifo_samples) |
| { |
| struct adxl372_data *data = dev->data; |
| uint8_t fifo_config; |
| int ret; |
| |
| if (fifo_samples > 512) { |
| return -EINVAL; |
| } |
| |
| /* |
| * All FIFO modes must be configured while in standby mode. |
| */ |
| ret = adxl372_set_op_mode(dev, ADXL372_STANDBY); |
| if (ret) { |
| return ret; |
| } |
| |
| fifo_config = (ADXL372_FIFO_CTL_FORMAT_MODE(format) | |
| ADXL372_FIFO_CTL_MODE_MODE(mode) | |
| ADXL372_FIFO_CTL_SAMPLES_MODE(fifo_samples)); |
| |
| ret = data->hw_tf->write_reg(dev, ADXL372_FIFO_CTL, fifo_config); |
| if (ret) { |
| return ret; |
| } |
| ret = data->hw_tf->write_reg(dev, ADXL372_FIFO_SAMPLES, fifo_samples & 0xFF); |
| if (ret) { |
| return ret; |
| } |
| |
| data->fifo_config.fifo_format = format; |
| data->fifo_config.fifo_mode = mode; |
| data->fifo_config.fifo_samples = fifo_samples; |
| |
| return 0; |
| } |
| |
| /** |
| * Retrieve 3-axis acceleration data |
| * @param dev - The device structure. |
| * @param maxpeak - Retrieve the highest magnitude (x, y, z) sample recorded |
| * since the last read of the MAXPEAK registers |
| * @param accel_data - pointer to a variable of type adxl372_xyz_accel_data |
| * where (x, y, z) acceleration data will be stored. |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int adxl372_get_accel_data(const struct device *dev, bool maxpeak, |
| struct adxl372_xyz_accel_data *accel_data) |
| { |
| struct adxl372_data *data = dev->data; |
| uint8_t buf[6]; |
| uint8_t status1; |
| int ret; |
| |
| if (!IS_ENABLED(CONFIG_ADXL372_TRIGGER)) { |
| do { |
| adxl372_get_status(dev, &status1, NULL, NULL); |
| } while (!(ADXL372_STATUS_1_DATA_RDY(status1))); |
| } |
| |
| ret = data->hw_tf->read_reg_multiple(dev, maxpeak ? ADXL372_X_MAXPEAK_H : |
| ADXL372_X_DATA_H, buf, 6); |
| |
| accel_data->x = (buf[0] << 8) | (buf[1] & 0xF0); |
| accel_data->y = (buf[2] << 8) | (buf[3] & 0xF0); |
| accel_data->z = (buf[4] << 8) | (buf[5] & 0xF0); |
| |
| return ret; |
| } |
| |
| static int adxl372_attr_set_odr(const struct device *dev, |
| enum sensor_channel chan, |
| enum sensor_attribute attr, |
| const struct sensor_value *val) |
| { |
| enum adxl372_odr odr; |
| |
| switch (val->val1) { |
| case 400: |
| odr = ADXL372_ODR_400HZ; |
| break; |
| case 800: |
| odr = ADXL372_ODR_800HZ; |
| break; |
| case 1600: |
| odr = ADXL372_ODR_1600HZ; |
| break; |
| case 3200: |
| odr = ADXL372_ODR_3200HZ; |
| break; |
| case 6400: |
| odr = ADXL372_ODR_6400HZ; |
| break; |
| default: |
| return -EINVAL; |
| } |
| |
| return adxl372_set_odr(dev, odr); |
| } |
| |
| static int adxl372_attr_set_thresh(const struct device *dev, |
| enum sensor_channel chan, |
| enum sensor_attribute attr, |
| const struct sensor_value *val) |
| { |
| const struct adxl372_dev_config *cfg = dev->config; |
| struct adxl372_activity_threshold threshold; |
| int64_t llvalue; |
| int32_t value; |
| int64_t micro_ms2 = val->val1 * 1000000LL + val->val2; |
| uint8_t reg; |
| |
| llvalue = llabs((micro_ms2 * 10) / SENSOR_G); |
| |
| if (llvalue > 2047) { |
| return -EINVAL; |
| } |
| |
| value = (int32_t) llvalue; |
| |
| threshold.thresh = value; |
| threshold.enable = cfg->activity_th.enable; |
| threshold.referenced = cfg->activity_th.referenced; |
| |
| if (attr == SENSOR_ATTR_UPPER_THRESH) { |
| reg = ADXL372_X_THRESH_ACT_H; |
| } else { |
| reg = ADXL372_X_THRESH_INACT_H; |
| } |
| |
| switch (chan) { |
| case SENSOR_CHAN_ACCEL_X: |
| return adxl372_set_activity_threshold(dev, reg, &threshold); |
| case SENSOR_CHAN_ACCEL_Y: |
| return adxl372_set_activity_threshold(dev, reg + 2, &threshold); |
| case SENSOR_CHAN_ACCEL_Z: |
| return adxl372_set_activity_threshold(dev, reg + 4, &threshold); |
| case SENSOR_CHAN_ACCEL_XYZ: |
| return adxl372_set_activity_threshold_xyz(dev, reg, &threshold); |
| default: |
| LOG_ERR("attr_set() not supported on this channel"); |
| return -ENOTSUP; |
| } |
| } |
| |
| static int adxl372_attr_set(const struct device *dev, |
| enum sensor_channel chan, |
| enum sensor_attribute attr, |
| const struct sensor_value *val) |
| { |
| switch (attr) { |
| case SENSOR_ATTR_SAMPLING_FREQUENCY: |
| return adxl372_attr_set_odr(dev, chan, attr, val); |
| case SENSOR_ATTR_UPPER_THRESH: |
| case SENSOR_ATTR_LOWER_THRESH: |
| return adxl372_attr_set_thresh(dev, chan, attr, val); |
| default: |
| return -ENOTSUP; |
| } |
| } |
| |
| static int adxl372_sample_fetch(const struct device *dev, |
| enum sensor_channel chan) |
| { |
| const struct adxl372_dev_config *cfg = dev->config; |
| struct adxl372_data *data = dev->data; |
| |
| return adxl372_get_accel_data(dev, cfg->max_peak_detect_mode, |
| &data->sample); |
| } |
| |
| static void adxl372_accel_convert(struct sensor_value *val, int16_t value) |
| { |
| /* |
| * Sensor resolution is 100mg/LSB, 12-bit value needs to be right |
| * shifted by 4 or divided by 16. Overall this results in a scale of 160 |
| */ |
| int32_t micro_ms2 = value * (SENSOR_G / (16 * 1000 / 100)); |
| |
| val->val1 = micro_ms2 / 1000000; |
| val->val2 = micro_ms2 % 1000000; |
| } |
| |
| static int adxl372_channel_get(const struct device *dev, |
| enum sensor_channel chan, |
| struct sensor_value *val) |
| { |
| struct adxl372_data *data = dev->data; |
| |
| switch (chan) { |
| case SENSOR_CHAN_ACCEL_X: |
| adxl372_accel_convert(val, data->sample.x); |
| break; |
| case SENSOR_CHAN_ACCEL_Y: |
| adxl372_accel_convert(val, data->sample.y); |
| break; |
| case SENSOR_CHAN_ACCEL_Z: |
| adxl372_accel_convert(val, data->sample.z); |
| break; |
| case SENSOR_CHAN_ACCEL_XYZ: |
| adxl372_accel_convert(val++, data->sample.x); |
| adxl372_accel_convert(val++, data->sample.y); |
| adxl372_accel_convert(val, data->sample.z); |
| break; |
| default: |
| return -ENOTSUP; |
| } |
| |
| return 0; |
| } |
| |
| static const struct sensor_driver_api adxl372_api_funcs = { |
| .attr_set = adxl372_attr_set, |
| .sample_fetch = adxl372_sample_fetch, |
| .channel_get = adxl372_channel_get, |
| #ifdef CONFIG_ADXL372_TRIGGER |
| .trigger_set = adxl372_trigger_set, |
| #endif |
| |
| }; |
| |
| static int adxl372_probe(const struct device *dev) |
| { |
| const struct adxl372_dev_config *cfg = dev->config; |
| struct adxl372_data *data = dev->data; |
| uint8_t dev_id, part_id; |
| int ret; |
| |
| ret = data->hw_tf->read_reg(dev, ADXL372_DEVID, &dev_id); |
| if (ret) { |
| return ret; |
| } |
| ret = data->hw_tf->read_reg(dev, ADXL372_PARTID, &part_id); |
| if (ret) { |
| return ret; |
| } |
| |
| if (dev_id != ADXL372_DEVID_VAL || part_id != ADXL372_PARTID_VAL) { |
| LOG_ERR("failed to read id (0x%X:0x%X)", dev_id, part_id); |
| return -ENODEV; |
| } |
| |
| #ifdef CONFIG_ADXL372_TRIGGER |
| data->act_proc_mode = ADXL372_LINKED, |
| #else |
| data->act_proc_mode = ADXL372_LOOPED, |
| #endif |
| |
| /* Device settings */ |
| ret = adxl372_set_op_mode(dev, ADXL372_STANDBY); |
| if (ret) { |
| return ret; |
| } |
| |
| ret = adxl372_reset(dev); |
| if (ret) { |
| return ret; |
| } |
| |
| ret = adxl372_set_hpf_corner(dev, cfg->hpf); |
| if (ret) { |
| return ret; |
| } |
| |
| ret = adxl372_set_bandwidth(dev, cfg->bw); |
| if (ret) { |
| return ret; |
| } |
| |
| ret = adxl372_set_odr(dev, cfg->odr); |
| if (ret) { |
| return ret; |
| } |
| |
| ret = adxl372_set_wakeup_rate(dev, cfg->wur); |
| if (ret) { |
| return ret; |
| } |
| |
| ret = adxl372_set_autosleep(dev, cfg->autosleep); |
| if (ret) { |
| return ret; |
| } |
| |
| ret = adxl372_set_instant_on_th(dev, cfg->th_mode); |
| if (ret) { |
| return ret; |
| } |
| |
| ret = adxl372_set_activity_threshold_xyz(dev, ADXL372_X_THRESH_ACT_H, |
| &cfg->activity_th); |
| if (ret) { |
| return ret; |
| } |
| |
| ret = adxl372_set_activity_threshold_xyz(dev, ADXL372_X_THRESH_INACT_H, |
| &cfg->inactivity_th); |
| if (ret) { |
| return ret; |
| } |
| |
| ret = adxl372_set_activity_time(dev, cfg->activity_time); |
| if (ret) { |
| return ret; |
| } |
| |
| ret = adxl372_set_inactivity_time(dev, cfg->inactivity_time); |
| if (ret) { |
| return ret; |
| } |
| |
| ret = adxl372_set_filter_settle(dev, cfg->filter_settle); |
| if (ret) { |
| return ret; |
| } |
| |
| ret = adxl372_configure_fifo(dev, cfg->fifo_config.fifo_mode, |
| cfg->fifo_config.fifo_format, |
| cfg->fifo_config.fifo_samples); |
| if (ret) { |
| return ret; |
| } |
| |
| #ifdef CONFIG_ADXL372_TRIGGER |
| if (adxl372_init_interrupt(dev) < 0) { |
| LOG_ERR("Failed to initialize interrupt!"); |
| return -EIO; |
| } |
| #endif |
| |
| ret = adxl372_interrupt_config(dev, cfg->int1_config, cfg->int2_config); |
| if (ret) { |
| return ret; |
| } |
| |
| ret = adxl372_set_op_mode(dev, cfg->op_mode); |
| if (ret) { |
| return ret; |
| } |
| |
| return adxl372_set_act_proc_mode(dev, data->act_proc_mode); |
| } |
| |
| static int adxl372_init(const struct device *dev) |
| { |
| int ret; |
| const struct adxl372_dev_config *cfg = dev->config; |
| |
| ret = cfg->bus_init(dev); |
| if (ret < 0) { |
| LOG_ERR("Failed to initialize sensor bus"); |
| return ret; |
| } |
| |
| if (adxl372_probe(dev) < 0) { |
| return -ENODEV; |
| } |
| |
| return 0; |
| } |
| |
| #if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0 |
| #warning "ADXL372 driver enabled without any devices" |
| #endif |
| |
| /* |
| * Device creation macro, shared by ADXL372_DEFINE_SPI() and |
| * ADXL372_DEFINE_I2C(). |
| */ |
| |
| #define ADXL372_DEVICE_INIT(inst) \ |
| SENSOR_DEVICE_DT_INST_DEFINE(inst, \ |
| adxl372_init, \ |
| NULL, \ |
| &adxl372_data_##inst, \ |
| &adxl372_config_##inst, \ |
| POST_KERNEL, \ |
| CONFIG_SENSOR_INIT_PRIORITY, \ |
| &adxl372_api_funcs); |
| |
| /* |
| * Instantiation macros used when a device is on a SPI bus. |
| */ |
| |
| #ifdef CONFIG_ADXL372_TRIGGER |
| #define ADXL372_CFG_IRQ(inst) \ |
| .interrupt = GPIO_DT_SPEC_INST_GET(inst, int1_gpios), |
| #else |
| #define ADXL372_CFG_IRQ(inst) |
| #endif /* CONFIG_ADXL372_TRIGGER */ |
| |
| #define ADXL372_CONFIG(inst) \ |
| .bw = DT_INST_PROP(inst, bw), \ |
| .hpf = DT_INST_PROP(inst, hpf), \ |
| .odr = DT_INST_PROP(inst, odr), \ |
| .max_peak_detect_mode = IS_ENABLED(CONFIG_ADXL372_PEAK_DETECT_MODE), \ |
| .th_mode = ADXL372_INSTANT_ON_LOW_TH, \ |
| .autosleep = false, \ |
| .wur = ADXL372_WUR_52ms, \ |
| .activity_th.thresh = CONFIG_ADXL372_ACTIVITY_THRESHOLD / 100, \ |
| .activity_th.referenced = \ |
| IS_ENABLED(CONFIG_ADXL372_REFERENCED_ACTIVITY_DETECTION_MODE), \ |
| .activity_th.enable = 1, \ |
| .activity_time = CONFIG_ADXL372_ACTIVITY_TIME, \ |
| .inactivity_th.thresh = CONFIG_ADXL372_INACTIVITY_THRESHOLD / 100, \ |
| .inactivity_th.referenced = \ |
| IS_ENABLED(CONFIG_ADXL372_REFERENCED_ACTIVITY_DETECTION_MODE), \ |
| .inactivity_th.enable = 1, \ |
| .inactivity_time = CONFIG_ADXL372_INACTIVITY_TIME, \ |
| .filter_settle = ADXL372_FILTER_SETTLE_370, \ |
| .fifo_config.fifo_mode = ADXL372_FIFO_STREAMED, \ |
| .fifo_config.fifo_format = ADXL372_XYZ_PEAK_FIFO, \ |
| .fifo_config.fifo_samples = 128, \ |
| .op_mode = ADXL372_FULL_BW_MEASUREMENT, \ |
| |
| #define ADXL372_CONFIG_SPI(inst) \ |
| { \ |
| .bus_init = adxl372_spi_init, \ |
| .spi = SPI_DT_SPEC_INST_GET(inst, SPI_WORD_SET(8) | \ |
| SPI_TRANSFER_MSB, 0), \ |
| ADXL372_CONFIG(inst) \ |
| COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \ |
| (ADXL372_CFG_IRQ(inst)), ()) \ |
| } |
| |
| #define ADXL372_DEFINE_SPI(inst) \ |
| static struct adxl372_data adxl372_data_##inst; \ |
| static const struct adxl372_dev_config adxl372_config_##inst = \ |
| ADXL372_CONFIG_SPI(inst); \ |
| ADXL372_DEVICE_INIT(inst) |
| |
| /* |
| * Instantiation macros used when a device is on an I2C bus. |
| */ |
| |
| #define ADXL372_CONFIG_I2C(inst) \ |
| { \ |
| .bus_init = adxl372_i2c_init, \ |
| .i2c = I2C_DT_SPEC_INST_GET(inst), \ |
| ADXL372_CONFIG(inst) \ |
| COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \ |
| (ADXL372_CFG_IRQ(inst)), ()) \ |
| } |
| |
| #define ADXL372_DEFINE_I2C(inst) \ |
| static struct adxl372_data adxl372_data_##inst; \ |
| static const struct adxl372_dev_config adxl372_config_##inst = \ |
| ADXL372_CONFIG_I2C(inst); \ |
| ADXL372_DEVICE_INIT(inst) |
| /* |
| * Main instantiation macro. Use of COND_CODE_1() selects the right |
| * bus-specific macro at preprocessor time. |
| */ |
| |
| #define ADXL372_DEFINE(inst) \ |
| COND_CODE_1(DT_INST_ON_BUS(inst, spi), \ |
| (ADXL372_DEFINE_SPI(inst)), \ |
| (ADXL372_DEFINE_I2C(inst))) |
| |
| DT_INST_FOREACH_STATUS_OKAY(ADXL372_DEFINE) |