drivers: sensor: adxl372: update driver

Handle SPI/I2c interface in the dts.

Support multiple instances.

Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
This commit is contained in:
Antoniu Miclaus 2022-09-14 11:44:54 +03:00 committed by Fabio Baltieri
parent 9293222d25
commit 9dda350e24
10 changed files with 492 additions and 389 deletions

View File

@ -6,4 +6,6 @@
zephyr_library()
zephyr_library_sources(adxl372.c)
zephyr_library_sources(adxl372_spi.c)
zephyr_library_sources(adxl372_i2c.c)
zephyr_library_sources_ifdef(CONFIG_ADXL372_TRIGGER adxl372_trigger.c)

View File

@ -14,23 +14,6 @@ menuconfig ADXL372
if ADXL372
choice ADXL372_BUS_TYPE
prompt "Interface type"
default ADXL372_I2C if $(dt_compat_on_bus,$(DT_COMPAT_ADI_ADXL372),i2c)
default ADXL372_SPI if $(dt_compat_on_bus,$(DT_COMPAT_ADI_ADXL372),spi)
help
Select interface the digital interface type for the ADXL372
config ADXL372_I2C
depends on I2C
bool "I2C Interface"
config ADXL372_SPI
depends on SPI
bool "SPI Interface"
endchoice
choice ADXL372_OP_MODE
prompt "Operating mode"
default ADXL372_PEAK_DETECT_MODE
@ -52,91 +35,6 @@ config ADXL372_MEASUREMENT_MODE
endchoice
choice ADXL372_ODR_FREQ
prompt "Accelerometer sampling frequency (ODR)"
default ADXL372_ODR_6400HZ if ADXL372_PEAK_DETECT_MODE
default ADXL372_ODR_400HZ if ADXL372_MEASUREMENT_MODE
config ADXL372_ODR_400HZ
bool "400 Hz"
config ADXL372_ODR_800HZ
bool "800 Hz"
config ADXL372_ODR_1600HZ
bool "1600 Hz"
config ADXL372_ODR_3200HZ
bool "3200 Hz"
config ADXL372_ODR_6400HZ
bool "6400 Hz"
endchoice
choice ADXL372_BW_FREQ
prompt "Low-Pass (Antialiasing) Filter corner frequency"
default ADXL372_BW_200HZ if ADXL372_ODR_400HZ
default ADXL372_BW_400HZ if ADXL372_ODR_800HZ
default ADXL372_BW_800HZ if ADXL372_ODR_1600HZ
default ADXL372_BW_1600HZ if ADXL372_ODR_3200HZ
default ADXL372_BW_3200HZ if ADXL372_ODR_6400HZ
help
High g events often include acceleration content over a wide range
of frequencies. The ADC of the ADXL372 samples the input acceleration
at the user selected ODR.
In the absence of antialiasing filters, input signals whose frequency
is more than half the ODR alias or fold into the measurement bandwidth
can lead to inaccurate measurements.
config ADXL372_LPF_DISABLE
bool "Disabled"
config ADXL372_BW_200HZ
bool "200 Hz"
config ADXL372_BW_400HZ
bool "400 Hz"
config ADXL372_BW_800HZ
bool "800 Hz"
config ADXL372_BW_1600HZ
bool "1600 Hz"
config ADXL372_BW_3200HZ
bool "3200 Hz"
endchoice
choice ADXL372_HPF_CORNER
prompt "High-Pass Filter corner frequency"
default ADXL372_HPF_CORNER0
help
The ADXL372 offers a one-pole, high-pass filter with a user
selectable 3 dB frequency. Applications that do not require dc
acceleration measurements can use the high-pass filter to minimize
constant or slow varying offset errors including initial bias,
bias drift due to temperature, and bias drift due to supply voltage
config ADXL372_HPF_DISABLE
bool "Disabled"
config ADXL372_HPF_CORNER0
bool "ODR/210"
config ADXL372_HPF_CORNER1
bool "ODR/411"
config ADXL372_HPF_CORNER2
bool "ODR/812"
config ADXL372_HPF_CORNER3
bool "ODR/1616"
endchoice
config ADXL372_ACTIVITY_THRESHOLD
int "Activity threshold in mg"
range 0 200000

View File

@ -6,150 +6,20 @@
#define DT_DRV_COMPAT adi_adxl372
#include <zephyr/kernel.h>
#include <string.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <string.h>
#include <zephyr/init.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/__assert.h>
#include <stdlib.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/logging/log.h>
#include "adxl372.h"
LOG_MODULE_REGISTER(ADXL372, CONFIG_SENSOR_LOG_LEVEL);
static int adxl372_bus_access(const struct device *dev, uint8_t reg,
void *data, size_t length)
{
const struct adxl372_dev_config *config = dev->config;
#ifdef CONFIG_ADXL372_SPI
const struct spi_buf buf[2] = {
{
.buf = &reg,
.len = 1
}, {
.buf = data,
.len = length
}
};
struct spi_buf_set tx = {
.buffers = buf,
};
if (reg & ADXL372_READ) {
const struct spi_buf_set rx = {
.buffers = buf,
.count = 2
};
tx.count = 1;
return spi_transceive_dt(&config->spi, &tx, &rx);
}
tx.count = 2;
return spi_write_dt(&config->spi, &tx);
#elif CONFIG_ADXL372_I2C
if (reg & ADXL372_READ) {
return i2c_burst_read_dt(&config->i2c,
ADXL372_TO_I2C_REG(reg),
(uint8_t *) data, length);
} else {
if (length != 1) {
return -EINVAL;
}
return i2c_reg_write_byte_dt(&config->i2c,
ADXL372_TO_I2C_REG(reg),
*(uint8_t *)data);
}
#endif
}
/**
* Read from device.
* @param dev - The device structure.
* @param reg_addr - The register address.
* @param reg_data - The register data.
* @return 0 in case of success, negative error code otherwise.
*/
static int adxl372_reg_read(const struct device *dev,
uint8_t reg_addr,
uint8_t *reg_data)
{
return adxl372_bus_access(dev, ADXL372_REG_READ(reg_addr), reg_data, 1);
}
/**
* Multibyte read from device. A register read begins with the address
* and autoincrements for each additional byte in the transfer.
* @param dev - The device structure.
* @param reg_addr - The register address.
* @param reg_data - The register data.
* @param count - Number of bytes to read.
* @return 0 in case of success, negative error code otherwise.
*/
static int adxl372_reg_read_multiple(const struct device *dev,
uint8_t reg_addr,
uint8_t *reg_data,
uint16_t count)
{
return adxl372_bus_access(dev, ADXL372_REG_READ(reg_addr),
reg_data, count);
}
/**
* Write to device.
* @param dev - The device structure.
* @param reg_addr - The register address.
* @param reg_data - The register data.
* @return 0 in case of success, negative error code otherwise.
*/
static int adxl372_reg_write(const struct device *dev,
uint8_t reg_addr,
uint8_t reg_data)
{
LOG_DBG("[0x%X] = 0x%X", reg_addr, reg_data);
return adxl372_bus_access(dev, ADXL372_REG_WRITE(reg_addr),
&reg_data, 1);
}
/**
* SPI write to device using a mask.
* @param dev - The device structure.
* @param reg_addr - The register address.
* @param mask - The mask.
* @param data - The register data.
* @return 0 in case of success, negative error code otherwise.
*/
int adxl372_reg_write_mask(const struct device *dev,
uint8_t reg_addr,
uint32_t mask,
uint8_t data)
{
int ret;
uint8_t tmp;
ret = adxl372_reg_read(dev, reg_addr, &tmp);
if (ret) {
return ret;
}
tmp &= ~mask;
tmp |= data;
return adxl372_reg_write(dev, reg_addr, tmp);
}
/**
* Set the threshold for activity detection for a single axis
* @param dev - The device structure.
@ -163,8 +33,9 @@ static int adxl372_set_activity_threshold(const struct device *dev,
{
int ret;
uint8_t val;
struct adxl372_data *data = dev->data;
ret = adxl372_reg_write(dev, axis_reg_h++, act->thresh >> 3);
ret = data->hw_tf->write_reg(dev, axis_reg_h++, act->thresh >> 3);
if (ret) {
return ret;
}
@ -179,7 +50,7 @@ static int adxl372_set_activity_threshold(const struct device *dev,
val = (act->thresh << 5) | act->enable;
}
return adxl372_reg_write(dev, axis_reg_h, val);
return data->hw_tf->write_reg(dev, axis_reg_h, val);
}
/**
@ -219,9 +90,11 @@ static int adxl372_set_activity_threshold_xyz(const struct device *dev,
static int adxl372_set_op_mode(const struct device *dev,
enum adxl372_op_mode op_mode)
{
return adxl372_reg_write_mask(dev, ADXL372_POWER_CTL,
ADXL372_POWER_CTL_MODE_MSK,
ADXL372_POWER_CTL_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));
}
/**
@ -234,9 +107,11 @@ static int adxl372_set_op_mode(const struct device *dev,
*/
static int adxl372_set_autosleep(const struct device *dev, bool enable)
{
return adxl372_reg_write_mask(dev, ADXL372_MEASURE,
ADXL372_MEASURE_AUTOSLEEP_MSK,
ADXL372_MEASURE_AUTOSLEEP_MODE(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));
}
/**
@ -256,6 +131,7 @@ static int adxl372_set_bandwidth(const struct device *dev,
{
int ret;
uint8_t mask;
struct adxl372_data *data = dev->data;
if (bw == ADXL372_BW_LPF_DISABLED) {
mask = ADXL372_POWER_CTL_LPF_DIS_MSK;
@ -263,21 +139,21 @@ static int adxl372_set_bandwidth(const struct device *dev,
mask = 0U;
}
ret = adxl372_reg_write_mask(dev, ADXL372_POWER_CTL,
ADXL372_POWER_CTL_LPF_DIS_MSK, mask);
ret = data->hw_tf->write_reg_mask(dev, ADXL372_POWER_CTL,
ADXL372_POWER_CTL_LPF_DIS_MSK, mask);
if (ret) {
return ret;
}
return adxl372_reg_write_mask(dev, ADXL372_MEASURE,
ADXL372_MEASURE_BANDWIDTH_MSK,
ADXL372_MEASURE_BANDWIDTH_MODE(bw));
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 bw - bandwidth.
* @param c - bandwidth.
* Accepted values: ADXL372_HPF_CORNER_0
* ADXL372_HPF_CORNER_1
* ADXL372_HPF_CORNER_2
@ -291,6 +167,7 @@ static int adxl372_set_hpf_corner(const struct device *dev,
int ret;
uint8_t mask;
struct adxl372_data *data = dev->data;
if (c == ADXL372_HPF_DISABLED) {
mask = ADXL372_POWER_CTL_HPF_DIS_MSK;
@ -298,13 +175,13 @@ static int adxl372_set_hpf_corner(const struct device *dev,
mask = 0U;
}
ret = adxl372_reg_write_mask(dev, ADXL372_POWER_CTL,
ADXL372_POWER_CTL_HPF_DIS_MSK, mask);
ret = data->hw_tf->write_reg_mask(dev, ADXL372_POWER_CTL,
ADXL372_POWER_CTL_HPF_DIS_MSK, mask);
if (ret) {
return ret;
}
return adxl372_reg_write(dev, ADXL372_HPF, ADXL372_HPF_CORNER(c));
return data->hw_tf->write_reg(dev, ADXL372_HPF, ADXL372_HPF_CORNER(c));
}
@ -320,9 +197,11 @@ static int adxl372_set_hpf_corner(const struct device *dev,
static int adxl372_set_act_proc_mode(const struct device *dev,
enum adxl372_act_proc_mode mode)
{
return adxl372_reg_write_mask(dev, ADXL372_MEASURE,
ADXL372_MEASURE_LINKLOOP_MSK,
ADXL372_MEASURE_LINKLOOP_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));
}
/**
@ -338,9 +217,11 @@ static int adxl372_set_act_proc_mode(const struct device *dev,
*/
static int adxl372_set_odr(const struct device *dev, enum adxl372_odr odr)
{
return adxl372_reg_write_mask(dev, ADXL372_TIMING,
ADXL372_TIMING_ODR_MSK,
ADXL372_TIMING_ODR_MODE(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));
}
/**
@ -354,9 +235,11 @@ static int adxl372_set_odr(const struct device *dev, enum adxl372_odr odr)
static int adxl372_set_instant_on_th(const struct device *dev,
enum adxl372_instant_on_th_mode mode)
{
return adxl372_reg_write_mask(dev, ADXL372_POWER_CTL,
ADXL372_POWER_CTL_INSTANT_ON_TH_MSK,
ADXL372_POWER_CTL_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));
}
/**
@ -376,9 +259,11 @@ static int adxl372_set_instant_on_th(const struct device *dev,
static int adxl372_set_wakeup_rate(const struct device *dev,
enum adxl372_wakeup_rate wur)
{
return adxl372_reg_write_mask(dev, ADXL372_TIMING,
ADXL372_TIMING_WAKE_UP_RATE_MSK,
ADXL372_TIMING_WAKE_UP_RATE_MODE(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));
}
/**
@ -389,7 +274,9 @@ static int adxl372_set_wakeup_rate(const struct device *dev,
*/
static int adxl372_set_activity_time(const struct device *dev, uint8_t time)
{
return adxl372_reg_write(dev, ADXL372_TIME_ACT, time);
struct adxl372_data *data = dev->data;
return data->hw_tf->write_reg(dev, ADXL372_TIME_ACT, time);
}
/**
@ -403,13 +290,14 @@ static int adxl372_set_inactivity_time(const struct device *dev,
uint16_t time)
{
int ret;
struct adxl372_data *data = dev->data;
ret = adxl372_reg_write(dev, ADXL372_TIME_INACT_H, time >> 8);
ret = data->hw_tf->write_reg(dev, ADXL372_TIME_INACT_H, time >> 8);
if (ret) {
return ret;
}
return adxl372_reg_write(dev, ADXL372_TIME_INACT_L, time & 0xFF);
return data->hw_tf->write_reg(dev, ADXL372_TIME_INACT_L, time & 0xFF);
}
/**
@ -423,9 +311,11 @@ static int adxl372_set_inactivity_time(const struct device *dev,
static int adxl372_set_filter_settle(const struct device *dev,
enum adxl372_filter_settle mode)
{
return adxl372_reg_write_mask(dev, ADXL372_POWER_CTL,
ADXL372_POWER_CTL_FIL_SETTLE_MSK,
ADXL372_POWER_CTL_FIL_SETTLE_MODE(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));
}
/**
@ -440,13 +330,14 @@ static int adxl372_interrupt_config(const struct device *dev,
uint8_t int2)
{
int ret;
struct adxl372_data *data = dev->data;
ret = adxl372_reg_write(dev, ADXL372_INT1_MAP, int1);
ret = data->hw_tf->write_reg(dev, ADXL372_INT1_MAP, int1);
if (ret) {
return ret;
}
return adxl372_reg_write(dev, ADXL372_INT2_MAP, int2);
return data->hw_tf->write_reg(dev, ADXL372_INT2_MAP, int2);
}
@ -464,6 +355,7 @@ int adxl372_get_status(const struct device *dev,
uint8_t *status2,
uint16_t *fifo_entries)
{
struct adxl372_data *data = dev->data;
uint8_t buf[4], length = 1U;
int ret;
@ -475,7 +367,7 @@ int adxl372_get_status(const struct device *dev,
length += 2U;
}
ret = adxl372_reg_read_multiple(dev, ADXL372_STATUS_1, buf, length);
ret = data->hw_tf->read_reg_multiple(dev, ADXL372_STATUS_1, buf, length);
*status1 = buf[0];
@ -498,13 +390,14 @@ int adxl372_get_status(const struct device *dev,
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 = adxl372_reg_write(dev, ADXL372_RESET, ADXL372_RESET_CODE);
ret = data->hw_tf->write_reg(dev, ADXL372_RESET, ADXL372_RESET_CODE);
k_sleep(K_MSEC(1000));
return ret;
@ -558,11 +451,11 @@ static int adxl372_configure_fifo(const struct device *dev,
ADXL372_FIFO_CTL_MODE_MODE(mode) |
ADXL372_FIFO_CTL_SAMPLES_MODE(fifo_samples));
ret = adxl372_reg_write(dev, ADXL372_FIFO_CTL, fifo_config);
ret = data->hw_tf->write_reg(dev, ADXL372_FIFO_CTL, fifo_config);
if (ret) {
return ret;
}
ret = adxl372_reg_write(dev, ADXL372_FIFO_SAMPLES, fifo_samples & 0xFF);
ret = data->hw_tf->write_reg(dev, ADXL372_FIFO_SAMPLES, fifo_samples & 0xFF);
if (ret) {
return ret;
}
@ -586,6 +479,7 @@ static int adxl372_configure_fifo(const struct device *dev,
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;
@ -596,8 +490,8 @@ static int adxl372_get_accel_data(const struct device *dev, bool maxpeak,
} while (!(ADXL372_STATUS_1_DATA_RDY(status1)));
}
ret = adxl372_reg_read_multiple(dev, maxpeak ? ADXL372_X_MAXPEAK_H :
ADXL372_X_DATA_H, buf, 6);
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);
@ -700,8 +594,8 @@ static int adxl372_attr_set(const struct device *dev,
static int adxl372_sample_fetch(const struct device *dev,
enum sensor_channel chan)
{
struct adxl372_data *data = dev->data;
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);
@ -760,14 +654,15 @@ static const struct sensor_driver_api adxl372_api_funcs = {
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 = adxl372_reg_read(dev, ADXL372_DEVID, &dev_id);
ret = data->hw_tf->read_reg(dev, ADXL372_DEVID, &dev_id);
if (ret) {
return ret;
}
ret = adxl372_reg_read(dev, ADXL372_PARTID, &part_id);
ret = data->hw_tf->read_reg(dev, ADXL372_PARTID, &part_id);
if (ret) {
return ret;
}
@ -777,16 +672,10 @@ static int adxl372_probe(const struct device *dev)
return -ENODEV;
}
#ifdef CONFIG_ADXL372_I2C
/*
* When sharing an SDA bus, the ADXL372 Silcon REV < 3 may prevent
* communication with other devices on that bus.
*/
adxl372_reg_read(dev, ADXL372_REVID, &dev_id);
if (dev_id < 3) {
LOG_WRN("The ADXL372 Rev %u only supports point to point I2C communication!",
dev_id);
}
#ifdef CONFIG_ADXL372_TRIGGER
data->act_proc_mode = ADXL372_LINKED,
#else
data->act_proc_mode = ADXL372_LOOPED,
#endif
/* Device settings */
@ -881,25 +770,19 @@ static int adxl372_probe(const struct device *dev)
return ret;
}
return adxl372_set_act_proc_mode(dev, cfg->act_proc_mode);
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;
#ifdef CONFIG_ADXL372_I2C
if (!device_is_ready(cfg->i2c.bus)) {
LOG_ERR("I2C bus %s not ready!", cfg->i2c.bus->name);
return -EINVAL;
ret = cfg->bus_init(dev);
if (ret < 0) {
LOG_ERR("Failed to initialize sensor bus");
return ret;
}
#endif
#ifdef CONFIG_ADXL372_SPI
if (!spi_is_ready(&cfg->spi)) {
LOG_ERR("SPI bus %s not ready!", cfg->spi.bus->name);
return -EINVAL;
}
#endif /* CONFIG_ADXL372_SPI */
if (adxl372_probe(dev) < 0) {
return -ENODEV;
@ -908,88 +791,102 @@ static int adxl372_init(const struct device *dev)
return 0;
}
static struct adxl372_data adxl372_data;
static const struct adxl372_dev_config adxl372_config = {
#ifdef CONFIG_ADXL372_I2C
.i2c = I2C_DT_SPEC_INST_GET(0),
#endif
#ifdef CONFIG_ADXL372_SPI
.spi = SPI_DT_SPEC_INST_GET(0, SPI_WORD_SET(8) | SPI_TRANSFER_MSB, 0),
#endif
#ifdef CONFIG_ADXL372_TRIGGER
.interrupt = GPIO_DT_SPEC_INST_GET(0, int1_gpios),
#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0
#warning "ADXL372 driver enabled without any devices"
#endif
.max_peak_detect_mode = IS_ENABLED(CONFIG_ADXL372_PEAK_DETECT_MODE),
/*
* Device creation macro, shared by ADXL372_DEFINE_SPI() and
* ADXL372_DEFINE_I2C().
*/
#ifdef CONFIG_ADXL372_ODR_400HZ
.odr = ADXL372_ODR_400HZ,
#elif CONFIG_ADXL372_ODR_800HZ
.odr = ADXL372_ODR_800HZ,
#elif CONFIG_ADXL372_ODR_1600HZ
.odr = ADXL372_ODR_1600HZ,
#elif CONFIG_ADXL372_ODR_3200HZ
.odr = ADXL372_ODR_3200HZ,
#elif CONFIG_ADXL372_ODR_6400HZ
.odr = ADXL372_ODR_6400HZ,
#endif
#define ADXL372_DEVICE_INIT(inst) \
DEVICE_DT_INST_DEFINE(inst, \
adxl372_init, \
NULL, \
&adxl372_data_##inst, \
&adxl372_config_##inst, \
POST_KERNEL, \
CONFIG_SENSOR_INIT_PRIORITY, \
&adxl372_api_funcs);
#ifdef CONFIG_ADXL372_BW_200HZ
.bw = ADXL372_BW_200HZ,
#elif CONFIG_ADXL372_BW_400HZ
.bw = ADXL372_BW_400HZ,
#elif CONFIG_ADXL372_BW_800HZ
.bw = ADXL372_BW_800HZ,
#elif CONFIG_ADXL372_BW_1600HZ
.bw = ADXL372_BW_1600HZ,
#elif CONFIG_ADXL372_BW_3200HZ
.bw = ADXL372_BW_3200HZ,
#elif CONFIG_ADXL372_LPF_DISABLE
.bw = ADXL372_BW_LPF_DISABLED,
#endif
#ifdef CONFIG_ADXL372_HPF_CORNER0
.hpf = ADXL372_HPF_CORNER_0,
#elif CONFIG_ADXL372_HPF_CORNER1
.hpf = ADXL372_HPF_CORNER_1,
#elif CONFIG_ADXL372_HPF_CORNER2
.hpf = ADXL372_HPF_CORNER_2,
#elif CONFIG_ADXL372_HPF_CORNER3
.hpf = ADXL372_HPF_CORNER_3,
#elif CONFIG_ADXL372_HPF_DISABLE
.hpf = ADXL372_HPF_DISABLED,
#endif
/*
* Instantiation macros used when a device is on a SPI bus.
*/
#ifdef CONFIG_ADXL372_TRIGGER
.act_proc_mode = ADXL372_LINKED,
#define ADXL372_CFG_IRQ(inst) \
.interrupt = GPIO_DT_SPEC_INST_GET(inst, int1_gpios),
#else
.act_proc_mode = ADXL372_LOOPED,
#endif
.th_mode = ADXL372_INSTANT_ON_LOW_TH,
.autosleep = false,
.wur = ADXL372_WUR_52ms,
#define ADXL372_CFG_IRQ(inst)
#endif /* CONFIG_ADXL372_TRIGGER */
.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,
#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, \
.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,
#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)), ()) \
}
.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,
#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)
.op_mode = ADXL372_FULL_BW_MEASUREMENT,
};
/*
* Instantiation macros used when a device is on an I2C bus.
*/
DEVICE_DT_INST_DEFINE(0, adxl372_init, NULL,
&adxl372_data, &adxl372_config, POST_KERNEL,
CONFIG_SENSOR_INIT_PRIORITY, &adxl372_api_funcs);
#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)

View File

@ -7,13 +7,20 @@
#ifndef ZEPHYR_DRIVERS_SENSOR_ADXL372_ADXL372_H_
#define ZEPHYR_DRIVERS_SENSOR_ADXL372_ADXL372_H_
#include <zephyr/drivers/sensor.h>
#include <zephyr/types.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/sys/util.h>
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
#include <zephyr/drivers/spi.h>
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) */
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
#include <zephyr/drivers/i2c.h>
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */
/*
* ADXL372 registers definition
*/
@ -278,10 +285,22 @@ struct adxl372_xyz_accel_data {
int16_t z;
};
struct adxl372_transfer_function {
int (*read_reg_multiple)(const struct device *dev, uint8_t reg_addr,
uint8_t *value, uint16_t len);
int (*write_reg)(const struct device *dev, uint8_t reg_addr,
uint8_t value);
int (*read_reg)(const struct device *dev, uint8_t reg_addr,
uint8_t *value);
int (*write_reg_mask)(const struct device *dev, uint8_t reg_addr,
uint32_t mask, uint8_t value);
};
struct adxl372_data {
struct adxl372_xyz_accel_data sample;
const struct adxl372_transfer_function *hw_tf;
struct adxl372_fifo_config fifo_config;
enum adxl372_act_proc_mode act_proc_mode;
#ifdef CONFIG_ADXL372_TRIGGER
struct gpio_callback gpio_cb;
@ -302,15 +321,21 @@ struct adxl372_data {
};
struct adxl372_dev_config {
#ifdef CONFIG_ADXL372_I2C
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
struct i2c_dt_spec i2c;
#endif
#ifdef CONFIG_ADXL372_SPI
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
struct spi_dt_spec spi;
#endif /* CONFIG_ADXL372_SPI */
#endif
int (*bus_init)(const struct device *dev);
#ifdef CONFIG_ADXL372_TRIGGER
struct gpio_dt_spec interrupt;
#endif
enum adxl372_bandwidth bw;
enum adxl372_hpf_corner hpf;
enum adxl372_odr odr;
bool max_peak_detect_mode;
/* Device Settings */
@ -321,11 +346,7 @@ struct adxl372_dev_config {
struct adxl372_activity_threshold inactivity_th;
struct adxl372_fifo_config fifo_config;
enum adxl372_bandwidth bw;
enum adxl372_hpf_corner hpf;
enum adxl372_odr odr;
enum adxl372_wakeup_rate wur;
enum adxl372_act_proc_mode act_proc_mode;
enum adxl372_instant_on_th_mode th_mode;
enum adxl372_filter_settle filter_settle;
enum adxl372_op_mode op_mode;
@ -336,6 +357,9 @@ struct adxl372_dev_config {
uint8_t int2_config;
};
int adxl372_spi_init(const struct device *dev);
int adxl372_i2c_init(const struct device *dev);
#ifdef CONFIG_ADXL372_TRIGGER
int adxl372_get_status(const struct device *dev,
uint8_t *status1, uint8_t *status2, uint16_t *fifo_entries);

View File

@ -0,0 +1,104 @@
/* adxl372_i2c.c - I2C routines for ADXL372 driver
*/
/*
* Copyright (c) 2018 STMicroelectronics
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT adi_adxl372
#include <string.h>
#include <zephyr/logging/log.h>
#include "adxl372.h"
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
LOG_MODULE_DECLARE(ADXL372, CONFIG_SENSOR_LOG_LEVEL);
static int adxl372_bus_access(const struct device *dev, uint8_t reg,
void *data, size_t length)
{
const struct adxl372_dev_config *config = dev->config;
if (reg & ADXL372_READ) {
return i2c_burst_read_dt(&config->i2c,
ADXL372_TO_I2C_REG(reg),
(uint8_t *) data, length);
} else {
if (length != 1) {
return -EINVAL;
}
return i2c_reg_write_byte_dt(&config->i2c,
ADXL372_TO_I2C_REG(reg),
*(uint8_t *)data);
}
}
static int adxl372_i2c_reg_read(const struct device *dev, uint8_t reg_addr,
uint8_t *reg_data)
{
return adxl372_bus_access(dev, ADXL372_REG_READ(reg_addr), reg_data, 1);
}
static int adxl372_i2c_reg_read_multiple(const struct device *dev,
uint8_t reg_addr,
uint8_t *reg_data,
uint16_t count)
{
return adxl372_bus_access(dev, ADXL372_REG_READ(reg_addr),
reg_data, count);
}
static int adxl372_i2c_reg_write(const struct device *dev,
uint8_t reg_addr,
uint8_t reg_data)
{
return adxl372_bus_access(dev, ADXL372_REG_WRITE(reg_addr),
&reg_data, 1);
}
int adxl372_i2c_reg_write_mask(const struct device *dev,
uint8_t reg_addr,
uint32_t mask,
uint8_t data)
{
int ret;
uint8_t tmp;
ret = adxl372_i2c_reg_read(dev, reg_addr, &tmp);
if (ret) {
return ret;
}
tmp &= ~mask;
tmp |= data;
return adxl372_i2c_reg_write(dev, reg_addr, tmp);
}
static const struct adxl372_transfer_function adxl372_i2c_transfer_fn = {
.read_reg_multiple = adxl372_i2c_reg_read_multiple,
.write_reg = adxl372_i2c_reg_write,
.read_reg = adxl372_i2c_reg_read,
.write_reg_mask = adxl372_i2c_reg_write_mask,
};
int adxl372_i2c_init(const struct device *dev)
{
struct adxl372_data *data = dev->data;
const struct adxl372_dev_config *config = dev->config;
data->hw_tf = &adxl372_i2c_transfer_fn;
if (!device_is_ready(config->i2c.bus)) {
return -ENODEV;
}
return 0;
}
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */

View File

@ -0,0 +1,119 @@
/* adxl372_spi.c - SPI routines for ADXL372 driver
*/
/*
* Copyright (c) 2022 Analog Devices
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT adi_adxl372
#include <string.h>
#include <zephyr/logging/log.h>
#include "adxl372.h"
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
LOG_MODULE_DECLARE(ADXL372, CONFIG_SENSOR_LOG_LEVEL);
static int adxl372_bus_access(const struct device *dev, uint8_t reg,
void *data, size_t length)
{
const struct adxl372_dev_config *config = dev->config;
const struct spi_buf buf[2] = {
{
.buf = &reg,
.len = 1
}, {
.buf = data,
.len = length
}
};
struct spi_buf_set tx = {
.buffers = buf,
};
if (reg & ADXL372_READ) {
const struct spi_buf_set rx = {
.buffers = buf,
.count = 2
};
tx.count = 1;
return spi_transceive_dt(&config->spi, &tx, &rx);
}
tx.count = 2;
return spi_write_dt(&config->spi, &tx);
}
static int adxl372_spi_reg_read(const struct device *dev, uint8_t reg_addr,
uint8_t *reg_data)
{
return adxl372_bus_access(dev, ADXL372_REG_READ(reg_addr), reg_data, 1);
}
static int adxl372_spi_reg_read_multiple(const struct device *dev,
uint8_t reg_addr,
uint8_t *reg_data,
uint16_t count)
{
return adxl372_bus_access(dev, ADXL372_REG_READ(reg_addr),
reg_data, count);
}
static int adxl372_spi_reg_write(const struct device *dev,
uint8_t reg_addr,
uint8_t reg_data)
{
return adxl372_bus_access(dev, ADXL372_REG_WRITE(reg_addr),
&reg_data, 1);
}
int adxl372_spi_reg_write_mask(const struct device *dev,
uint8_t reg_addr,
uint32_t mask,
uint8_t data)
{
int ret;
uint8_t tmp;
ret = adxl372_spi_reg_read(dev, reg_addr, &tmp);
if (ret) {
return ret;
}
tmp &= ~mask;
tmp |= data;
return adxl372_spi_reg_write(dev, reg_addr, tmp);
}
static const struct adxl372_transfer_function adxl372_spi_transfer_fn = {
.read_reg_multiple = adxl372_spi_reg_read_multiple,
.write_reg = adxl372_spi_reg_write,
.read_reg = adxl372_spi_reg_read,
.write_reg_mask = adxl372_spi_reg_write_mask,
};
int adxl372_spi_init(const struct device *dev)
{
struct adxl372_data *data = dev->data;
const struct adxl372_dev_config *config = dev->config;
data->hw_tf = &adxl372_spi_transfer_fn;
if (!spi_is_ready(&config->spi)) {
return -ENODEV;
}
return 0;
}
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) */

View File

@ -125,7 +125,7 @@ int adxl372_trigger_set(const struct device *dev,
int_en = 0U;
}
ret = adxl372_reg_write_mask(dev, ADXL372_INT1_MAP, int_mask, int_en);
ret = drv_data->hw_tf->write_reg_mask(dev, ADXL372_INT1_MAP, int_mask, int_en);
if (ret < 0) {
return ret;
}

View File

@ -0,0 +1,59 @@
# Copyright (c) 2022 Analog Devices Inc.
# SPDX-License-Identifier: Apache-2.0
properties:
odr:
type: int
required: false
default: 0
description: |
Accelerometer sampling frequency (ODR). Default is power on reset value.
0 # 400Hz
1 # 800Hz
2 # 1600Hz
3 # 3200Hz
4 # 6400Hz
enum:
- 0
- 1
- 2
- 3
- 4
bw:
type: int
required: false
default: 12
description: |
Low-Pass (Antialiasing) Filter corner frequency. Default is power on reset value.
0 # 200Hz
1 # 400Hz
2 # 800Hz
3 # 1600Hz
4 # 3200Hz
12 # Disabled
enum:
- 0
- 1
- 2
- 3
- 4
- 12
hpf:
type: int
required: false
default: 4
description: |
High-Pass Filter corner frequency. Default is power on reset value.
0 # ODR/210
1 # ODR/411
2 # ODR/812
3 # ODR/1616
4 # Disabled
enum:
- 0
- 1
- 2
- 3
- 4

View File

@ -5,7 +5,7 @@ description: ADXL372 3-axis high-g I2C/SPI accelerometer
compatible: "adi,adxl372"
include: i2c-device.yaml
include: ["i2c-device.yaml", "adi,adxl372-common.yaml"]
properties:
int1-gpios:

View File

@ -6,7 +6,7 @@ description: ADXL372 3-axis high-g accelerometer, accessed through SPI bus
compatible: "adi,adxl372"
include: spi-device.yaml
include: ["spi-device.yaml", "adi,adxl372-common.yaml"]
properties:
int1-gpios: