drivers/sensor: lis2dux12: re-working to be DUX generic
Prepare the driver to be able to handle other DUX software compatible
devices. Currently the driver handles the st_lis2dux12 compatible only.
Do following major changes:
1. Introduce the lis2dux12_chip_api structure filled with device specific
APIs. At the moment define following callback:
- api_lis2dux12_set_odr_raw()
- api_lis2dux12_set_range()
- api_lis2dux12_sample_fetch_accel()
- api_lis2dux12_sample_fetch_temp()
- api_lis2dux12_handle_interrupt()
- api_lis2dux12_init_interrupt()
2. Prepare specific APIs for st_lis2dux12 device.
3. Make DT instantiation on inst + name basis, and not only by inst. This
commit only use "name = DT_DRV_COMPAT = st_lis2dux12".
Signed-off-by: Armando Visconti <armando.visconti@st.com>
This commit is contained in:
parent
99a503e661
commit
0f76a4e519
6 changed files with 373 additions and 272 deletions
|
|
@ -4,5 +4,6 @@ zephyr_library()
|
|||
|
||||
zephyr_library_sources(lis2dux12.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_LIS2DUX12_TRIGGER lis2dux12_trigger.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_DT_HAS_ST_LIS2DUX12_ENABLED lis2dux12_api.c )
|
||||
|
||||
zephyr_library_include_directories(../stmemsc)
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@
|
|||
* https://www.st.com/resource/en/datasheet/lis2dux12.pdf
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT st_lis2dux12
|
||||
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/device.h>
|
||||
|
|
@ -18,59 +16,15 @@
|
|||
#include <zephyr/sys/__assert.h>
|
||||
#include <zephyr/sys/util_macro.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/dt-bindings/sensor/lis2dux12.h>
|
||||
|
||||
#include "lis2dux12.h"
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_lis2dux12)
|
||||
#include "lis2dux12_api.h"
|
||||
#endif
|
||||
|
||||
LOG_MODULE_REGISTER(LIS2DUX12, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static int lis2dux12_set_odr(const struct device *dev, uint8_t odr)
|
||||
{
|
||||
struct lis2dux12_data *data = dev->data;
|
||||
const struct lis2dux12_config *cfg = dev->config;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
lis2dux12_md_t mode = {.odr = odr, .fs = data->range};
|
||||
|
||||
data->odr = odr;
|
||||
return lis2dux12_mode_set(ctx, &mode);
|
||||
}
|
||||
|
||||
static int lis2dux12_set_range(const struct device *dev, uint8_t range)
|
||||
{
|
||||
int err;
|
||||
struct lis2dux12_data *data = dev->data;
|
||||
const struct lis2dux12_config *cfg = dev->config;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
lis2dux12_md_t val = { .odr = data->odr, .fs = range };
|
||||
|
||||
err = lis2dux12_mode_set(ctx, &val);
|
||||
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
switch (range) {
|
||||
default:
|
||||
LOG_ERR("range [%d] not supported.", range);
|
||||
return -EINVAL;
|
||||
case LIS2DUX12_DT_FS_2G:
|
||||
data->gain = lis2dux12_from_fs2g_to_mg(1);
|
||||
break;
|
||||
case LIS2DUX12_DT_FS_4G:
|
||||
data->gain = lis2dux12_from_fs4g_to_mg(1);
|
||||
break;
|
||||
case LIS2DUX12_DT_FS_8G:
|
||||
data->gain = lis2dux12_from_fs8g_to_mg(1);
|
||||
break;
|
||||
case LIS2DUX12_DT_FS_16G:
|
||||
data->gain = lis2dux12_from_fs16g_to_mg(1);
|
||||
break;
|
||||
}
|
||||
|
||||
data->range = range;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define FOREACH_ODR_ENUM(ODR_VAL) \
|
||||
ODR_VAL(LIS2DUX12_DT_ODR_OFF, 0.0f) \
|
||||
ODR_VAL(LIS2DUX12_DT_ODR_1Hz_ULP, 1.0f) \
|
||||
|
|
@ -113,6 +67,8 @@ static int lis2dux12_set_fs(const struct device *dev, int16_t fs)
|
|||
{
|
||||
int ret;
|
||||
uint8_t range;
|
||||
const struct lis2dux12_config *const cfg = dev->config;
|
||||
const struct lis2dux12_chip_api *chip_api = cfg->chip_api;
|
||||
|
||||
switch (fs) {
|
||||
case 2:
|
||||
|
|
@ -132,7 +88,7 @@ static int lis2dux12_set_fs(const struct device *dev, int16_t fs)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = lis2dux12_set_range(dev, range);
|
||||
ret = chip_api->set_range(dev, range);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("%s: range init error %d", dev->name, range);
|
||||
return ret;
|
||||
|
|
@ -146,6 +102,8 @@ static int lis2dux12_accel_config(const struct device *dev, enum sensor_channel
|
|||
enum sensor_attribute attr, const struct sensor_value *val)
|
||||
{
|
||||
int odr_val;
|
||||
const struct lis2dux12_config *const cfg = dev->config;
|
||||
const struct lis2dux12_chip_api *chip_api = cfg->chip_api;
|
||||
|
||||
switch (attr) {
|
||||
case SENSOR_ATTR_FULL_SCALE:
|
||||
|
|
@ -159,7 +117,7 @@ static int lis2dux12_accel_config(const struct device *dev, enum sensor_channel
|
|||
|
||||
LOG_DBG("%s: set odr to %d Hz", dev->name, val->val1);
|
||||
|
||||
return lis2dux12_set_odr(dev, odr_val);
|
||||
return chip_api->set_odr_raw(dev, odr_val);
|
||||
default:
|
||||
LOG_ERR("Accel attribute not supported.");
|
||||
return -ENOTSUP;
|
||||
|
|
@ -182,71 +140,34 @@ static int lis2dux12_attr_set(const struct device *dev, enum sensor_channel chan
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lis2dux12_sample_fetch_accel(const struct device *dev)
|
||||
{
|
||||
struct lis2dux12_data *data = dev->data;
|
||||
const struct lis2dux12_config *cfg = dev->config;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
|
||||
/* fetch raw data sample */
|
||||
lis2dux12_md_t mode = {.fs = data->range};
|
||||
lis2dux12_xl_data_t xzy_data = {0};
|
||||
|
||||
if (lis2dux12_xl_data_get(ctx, &mode, &xzy_data) < 0) {
|
||||
LOG_ERR("Failed to fetch raw data sample");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
data->sample_x = xzy_data.raw[0];
|
||||
data->sample_y = xzy_data.raw[1];
|
||||
data->sample_z = xzy_data.raw[2];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LIS2DUX12_ENABLE_TEMP
|
||||
static int lis2dux12_sample_fetch_temp(const struct device *dev)
|
||||
{
|
||||
struct lis2dux12_data *data = dev->data;
|
||||
const struct lis2dux12_config *cfg = dev->config;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
|
||||
/* fetch raw data sample */
|
||||
lis2dux12_outt_data_t temp_data = {0};
|
||||
|
||||
if (lis2dux12_outt_data_get(ctx, &temp_data) < 0) {
|
||||
LOG_ERR("Failed to fetch raw temperature data sample");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
data->sample_temp = temp_data.heat.deg_c;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lis2dux12_sample_fetch(const struct device *dev, enum sensor_channel chan)
|
||||
{
|
||||
const struct lis2dux12_config *const cfg = dev->config;
|
||||
const struct lis2dux12_chip_api *chip_api = cfg->chip_api;
|
||||
int ret;
|
||||
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_ACCEL_XYZ:
|
||||
lis2dux12_sample_fetch_accel(dev);
|
||||
ret = chip_api->sample_fetch_accel(dev);
|
||||
break;
|
||||
#if defined(CONFIG_LIS2DUX12_ENABLE_TEMP)
|
||||
case SENSOR_CHAN_DIE_TEMP:
|
||||
lis2dux12_sample_fetch_temp(dev);
|
||||
ret = chip_api->sample_fetch_temp(dev);
|
||||
break;
|
||||
#endif
|
||||
case SENSOR_CHAN_ALL:
|
||||
lis2dux12_sample_fetch_accel(dev);
|
||||
ret = chip_api->sample_fetch_accel(dev);
|
||||
if (ret != 0)
|
||||
break;
|
||||
#if defined(CONFIG_LIS2DUX12_ENABLE_TEMP)
|
||||
lis2dux12_sample_fetch_temp(dev);
|
||||
ret = chip_api->sample_fetch_temp(dev);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void lis2dux12_convert(struct sensor_value *val, int raw_val, float gain)
|
||||
|
|
@ -307,129 +228,59 @@ static DEVICE_API(sensor, lis2dux12_driver_api) = {
|
|||
.channel_get = lis2dux12_channel_get,
|
||||
};
|
||||
|
||||
static int lis2dux12_init(const struct device *dev)
|
||||
{
|
||||
const struct lis2dux12_config *const cfg = dev->config;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
uint8_t chip_id;
|
||||
int ret;
|
||||
|
||||
lis2dux12_exit_deep_power_down(ctx);
|
||||
k_busy_wait(25000);
|
||||
|
||||
/* check chip ID */
|
||||
ret = lis2dux12_device_id_get(ctx, &chip_id);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("%s: Not able to read dev id", dev->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (chip_id != LIS2DUX12_ID) {
|
||||
LOG_ERR("%s: Invalid chip ID 0x%02x", dev->name, chip_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* reset device */
|
||||
ret = lis2dux12_init_set(ctx, LIS2DUX12_RESET);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
k_busy_wait(100);
|
||||
|
||||
LOG_INF("%s: chip id 0x%x", dev->name, chip_id);
|
||||
|
||||
/* Set bdu and if_inc recommended for driver usage */
|
||||
lis2dux12_init_set(ctx, LIS2DUX12_SENSOR_ONLY_ON);
|
||||
|
||||
lis2dux12_timestamp_set(ctx, PROPERTY_ENABLE);
|
||||
|
||||
#ifdef CONFIG_LIS2DUX12_TRIGGER
|
||||
if (cfg->trig_enabled) {
|
||||
ret = lis2dux12_trigger_init(dev);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("%s: Failed to initialize triggers", dev->name);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* set sensor default pm and odr */
|
||||
LOG_DBG("%s: pm: %d, odr: %d", dev->name, cfg->pm, cfg->odr);
|
||||
ret = lis2dux12_set_odr(dev, cfg->odr);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("%s: odr init error (12.5 Hz)", dev->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* set sensor default scale (used to convert sample values) */
|
||||
LOG_DBG("%s: range is %d", dev->name, cfg->range);
|
||||
ret = lis2dux12_set_range(dev, cfg->range);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("%s: range init error %d", dev->name, cfg->range);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Device creation macro, shared by LIS2DUX12_DEFINE_SPI() and
|
||||
* LIS2DUX12_DEFINE_I2C().
|
||||
*/
|
||||
|
||||
#define LIS2DUX12_DEVICE_INIT(inst) \
|
||||
SENSOR_DEVICE_DT_INST_DEFINE(inst, lis2dux12_init, NULL, &lis2dux12_data_##inst, \
|
||||
&lis2dux12_config_##inst, POST_KERNEL, \
|
||||
CONFIG_SENSOR_INIT_PRIORITY, &lis2dux12_driver_api);
|
||||
|
||||
/*
|
||||
* Instantiation macros used when a device is on a SPI bus.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_LIS2DUX12_TRIGGER
|
||||
#define LIS2DUX12_CFG_IRQ(inst) \
|
||||
.trig_enabled = true, \
|
||||
.int1_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int1_gpios, {0}), \
|
||||
.int2_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int2_gpios, {0}), \
|
||||
#define LIS2DUX12_CFG_IRQ(inst) \
|
||||
.trig_enabled = true, \
|
||||
.int1_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int1_gpios, {0}), \
|
||||
.int2_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int2_gpios, {0}), \
|
||||
.drdy_pin = DT_INST_PROP(inst, drdy_pin),
|
||||
#else
|
||||
#define LIS2DUX12_CFG_IRQ(inst)
|
||||
#endif /* CONFIG_LIS2DUX12_TRIGGER */
|
||||
|
||||
#define LIS2DUX12_CONFIG_COMMON(inst, name) \
|
||||
.chip_api = &name##_chip_api, \
|
||||
.range = DT_INST_PROP(inst, range), \
|
||||
.pm = DT_INST_PROP(inst, power_mode), \
|
||||
.odr = DT_INST_PROP(inst, odr), \
|
||||
IF_ENABLED(UTIL_OR(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \
|
||||
DT_INST_NODE_HAS_PROP(inst, int2_gpios)), \
|
||||
(LIS2DUX12_CFG_IRQ(inst))) \
|
||||
|
||||
#define LIS2DUX12_SPI_OPERATION \
|
||||
(SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA)
|
||||
|
||||
#define LIS2DUX12_CONFIG_SPI(inst) \
|
||||
/*
|
||||
* Instantiation macros used when a device is on a SPI bus.
|
||||
*/
|
||||
#define LIS2DUX12_CONFIG_SPI(inst, name) \
|
||||
{ \
|
||||
STMEMSC_CTX_SPI(&lis2dux12_config_##inst.stmemsc_cfg), \
|
||||
STMEMSC_CTX_SPI(&lis2dux12_config_##name##_##inst.stmemsc_cfg), \
|
||||
.stmemsc_cfg = { \
|
||||
.spi = SPI_DT_SPEC_INST_GET(inst, LIS2DUX12_SPI_OPERATION, 0), \
|
||||
}, \
|
||||
.range = DT_INST_PROP(inst, range), \
|
||||
.pm = DT_INST_PROP(inst, power_mode), \
|
||||
.odr = DT_INST_PROP(inst, odr), \
|
||||
IF_ENABLED(UTIL_OR(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \
|
||||
DT_INST_NODE_HAS_PROP(inst, int2_gpios)), \
|
||||
(LIS2DUX12_CFG_IRQ(inst))) \
|
||||
LIS2DUX12_CONFIG_COMMON(inst, name) \
|
||||
}
|
||||
|
||||
/*
|
||||
* Instantiation macros used when a device is on an I2C bus.
|
||||
*/
|
||||
|
||||
#define LIS2DUX12_CONFIG_I2C(inst) \
|
||||
#define LIS2DUX12_CONFIG_I2C(inst, name) \
|
||||
{ \
|
||||
STMEMSC_CTX_I2C(&lis2dux12_config_##inst.stmemsc_cfg), \
|
||||
STMEMSC_CTX_I2C(&lis2dux12_config_##name##_##inst.stmemsc_cfg), \
|
||||
.stmemsc_cfg = { \
|
||||
.i2c = I2C_DT_SPEC_INST_GET(inst), \
|
||||
}, \
|
||||
.range = DT_INST_PROP(inst, range), \
|
||||
.pm = DT_INST_PROP(inst, power_mode), \
|
||||
.odr = DT_INST_PROP(inst, odr), \
|
||||
IF_ENABLED(UTIL_OR(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \
|
||||
DT_INST_NODE_HAS_PROP(inst, int2_gpios)), \
|
||||
(LIS2DUX12_CFG_IRQ(inst))) \
|
||||
LIS2DUX12_CONFIG_COMMON(inst, name) \
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -437,11 +288,20 @@ static int lis2dux12_init(const struct device *dev)
|
|||
* bus-specific macro at preprocessor time.
|
||||
*/
|
||||
|
||||
#define LIS2DUX12_DEFINE(inst) \
|
||||
static struct lis2dux12_data lis2dux12_data_##inst; \
|
||||
static const struct lis2dux12_config lis2dux12_config_##inst = \
|
||||
COND_CODE_1(DT_INST_ON_BUS(inst, spi), (LIS2DUX12_CONFIG_SPI(inst)), \
|
||||
(LIS2DUX12_CONFIG_I2C(inst))); \
|
||||
LIS2DUX12_DEVICE_INIT(inst)
|
||||
#define LIS2DUX12_DEFINE(inst, name) \
|
||||
static struct lis2dux12_data lis2dux12_data_##name##_##inst; \
|
||||
static const struct lis2dux12_config lis2dux12_config_##name##_##inst = \
|
||||
COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
|
||||
(LIS2DUX12_CONFIG_SPI(inst, name)), \
|
||||
(LIS2DUX12_CONFIG_I2C(inst, name))); \
|
||||
\
|
||||
SENSOR_DEVICE_DT_INST_DEFINE(inst, name##_init, NULL, \
|
||||
&lis2dux12_data_##name##_##inst, \
|
||||
&lis2dux12_config_##name##_##inst, POST_KERNEL, \
|
||||
CONFIG_SENSOR_INIT_PRIORITY, \
|
||||
&lis2dux12_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(LIS2DUX12_DEFINE)
|
||||
|
||||
#define DT_DRV_COMPAT st_lis2dux12
|
||||
DT_INST_FOREACH_STATUS_OKAY_VARGS(LIS2DUX12_DEFINE, DT_DRV_COMPAT)
|
||||
#undef DT_DRV_COMPAT
|
||||
|
|
|
|||
|
|
@ -15,23 +15,50 @@
|
|||
#include <zephyr/drivers/sensor.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <stmemsc.h>
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_lis2dux12)
|
||||
#include "lis2dux12_reg.h"
|
||||
#endif
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
|
||||
#if DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lis2dux12, spi)
|
||||
#include <zephyr/drivers/spi.h>
|
||||
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) */
|
||||
#endif
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
|
||||
#if DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lis2dux12, i2c)
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */
|
||||
#endif
|
||||
|
||||
typedef int32_t (*api_lis2dux12_set_odr_raw)(const struct device *dev, uint8_t odr);
|
||||
typedef int32_t (*api_lis2dux12_set_range)(const struct device *dev, uint8_t range);
|
||||
typedef int32_t (*api_lis2dux12_sample_fetch_accel)(const struct device *dev);
|
||||
#ifdef CONFIG_LIS2DUX12_ENABLE_TEMP
|
||||
typedef int32_t (*api_lis2dux12_sample_fetch_temp)(const struct device *dev);
|
||||
#endif
|
||||
#ifdef CONFIG_LIS2DUX12_TRIGGER
|
||||
typedef void (*api_lis2dux12_handle_interrupt)(const struct device *dev);
|
||||
typedef int32_t (*api_lis2dux12_init_interrupt)(const struct device *dev);
|
||||
#endif
|
||||
|
||||
struct lis2dux12_chip_api {
|
||||
api_lis2dux12_set_odr_raw set_odr_raw;
|
||||
api_lis2dux12_set_range set_range;
|
||||
api_lis2dux12_sample_fetch_accel sample_fetch_accel;
|
||||
#ifdef CONFIG_LIS2DUX12_ENABLE_TEMP
|
||||
api_lis2dux12_sample_fetch_temp sample_fetch_temp;
|
||||
#endif
|
||||
#ifdef CONFIG_LIS2DUX12_TRIGGER
|
||||
api_lis2dux12_handle_interrupt handle_interrupt;
|
||||
api_lis2dux12_init_interrupt init_interrupt;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct lis2dux12_config {
|
||||
stmdev_ctx_t ctx;
|
||||
union {
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
|
||||
#if DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lis2dux12, i2c)
|
||||
const struct i2c_dt_spec i2c;
|
||||
#endif
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
|
||||
#if DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lis2dux12, spi)
|
||||
const struct spi_dt_spec spi;
|
||||
#endif
|
||||
} stmemsc_cfg;
|
||||
|
|
@ -44,6 +71,8 @@ struct lis2dux12_config {
|
|||
uint8_t drdy_pin;
|
||||
bool trig_enabled;
|
||||
#endif
|
||||
|
||||
const struct lis2dux12_chip_api *chip_api;
|
||||
};
|
||||
|
||||
struct lis2dux12_data {
|
||||
|
|
|
|||
237
drivers/sensor/st/lis2dux12/lis2dux12_api.c
Normal file
237
drivers/sensor/st/lis2dux12/lis2dux12_api.c
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
/* ST Microelectronics LIS2DUX12 smart accelerometer APIs
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics
|
||||
* Copyright (c) 2023 PHYTEC Messtechnik GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "lis2dux12.h"
|
||||
#include "lis2dux12_api.h"
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
LOG_MODULE_DECLARE(LIS2DUX12, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static int32_t st_lis2dux12_set_odr_raw(const struct device *dev, uint8_t odr)
|
||||
{
|
||||
struct lis2dux12_data *data = dev->data;
|
||||
const struct lis2dux12_config *cfg = dev->config;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
lis2dux12_md_t mode = {.odr = odr, .fs = data->range};
|
||||
|
||||
data->odr = odr;
|
||||
return lis2dux12_mode_set(ctx, &mode);
|
||||
}
|
||||
|
||||
static int32_t st_lis2dux12_set_range(const struct device *dev, uint8_t range)
|
||||
{
|
||||
int err;
|
||||
struct lis2dux12_data *data = dev->data;
|
||||
const struct lis2dux12_config *cfg = dev->config;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
lis2dux12_md_t val = { .odr = data->odr, .fs = range };
|
||||
|
||||
err = lis2dux12_mode_set(ctx, &val);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
switch (range) {
|
||||
case LIS2DUX12_DT_FS_2G:
|
||||
data->gain = lis2dux12_from_fs2g_to_mg(1);
|
||||
break;
|
||||
case LIS2DUX12_DT_FS_4G:
|
||||
data->gain = lis2dux12_from_fs4g_to_mg(1);
|
||||
break;
|
||||
case LIS2DUX12_DT_FS_8G:
|
||||
data->gain = lis2dux12_from_fs8g_to_mg(1);
|
||||
break;
|
||||
case LIS2DUX12_DT_FS_16G:
|
||||
data->gain = lis2dux12_from_fs16g_to_mg(1);
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("range %d not supported.", range);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data->range = range;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t st_lis2dux12_sample_fetch_accel(const struct device *dev)
|
||||
{
|
||||
struct lis2dux12_data *data = dev->data;
|
||||
const struct lis2dux12_config *cfg = dev->config;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
|
||||
/* fetch raw data sample */
|
||||
lis2dux12_md_t mode = {.fs = data->range};
|
||||
lis2dux12_xl_data_t xzy_data = {0};
|
||||
|
||||
if (lis2dux12_xl_data_get(ctx, &mode, &xzy_data) < 0) {
|
||||
LOG_ERR("Failed to fetch raw data sample");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
data->sample_x = xzy_data.raw[0];
|
||||
data->sample_y = xzy_data.raw[1];
|
||||
data->sample_z = xzy_data.raw[2];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LIS2DUX12_ENABLE_TEMP
|
||||
static int32_t st_lis2dux12_sample_fetch_temp(const struct device *dev)
|
||||
{
|
||||
struct lis2dux12_data *data = dev->data;
|
||||
const struct lis2dux12_config *cfg = dev->config;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
|
||||
/* fetch raw data sample */
|
||||
lis2dux12_outt_data_t temp_data = {0};
|
||||
|
||||
if (lis2dux12_outt_data_get(ctx, &temp_data) < 0) {
|
||||
LOG_ERR("Failed to fetch raw temperature data sample");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
data->sample_temp = temp_data.heat.deg_c;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LIS2DUX12_TRIGGER
|
||||
static void st_lis2dux12_handle_interrupt(const struct device *dev)
|
||||
{
|
||||
struct lis2dux12_data *lis2dux12 = dev->data;
|
||||
const struct lis2dux12_config *cfg = dev->config;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
lis2dux12_all_sources_t sources;
|
||||
int ret;
|
||||
|
||||
lis2dux12_all_sources_get(ctx, &sources);
|
||||
|
||||
if (sources.drdy == 0) {
|
||||
goto exit; /* spurious interrupt */
|
||||
}
|
||||
|
||||
if (lis2dux12->data_ready_handler != NULL) {
|
||||
lis2dux12->data_ready_handler(dev, lis2dux12->data_ready_trigger);
|
||||
}
|
||||
|
||||
exit:
|
||||
ret = gpio_pin_interrupt_configure_dt(lis2dux12->drdy_gpio, GPIO_INT_EDGE_TO_ACTIVE);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("%s: Not able to configure pin_int", dev->name);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t st_lis2dux12_init_interrupt(const struct device *dev)
|
||||
{
|
||||
const struct lis2dux12_config *cfg = dev->config;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
lis2dux12_pin_int_route_t route;
|
||||
int err;
|
||||
|
||||
/* Enable pulsed mode */
|
||||
err = lis2dux12_data_ready_mode_set(ctx, LIS2DUX12_DRDY_PULSED);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* route data-ready interrupt on int1 */
|
||||
err = lis2dux12_pin_int1_route_get(ctx, &route);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
route.drdy = 1;
|
||||
|
||||
err = lis2dux12_pin_int1_route_set(ctx, &route);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
const struct lis2dux12_chip_api st_lis2dux12_chip_api = {
|
||||
.set_odr_raw = st_lis2dux12_set_odr_raw,
|
||||
.set_range = st_lis2dux12_set_range,
|
||||
.sample_fetch_accel = st_lis2dux12_sample_fetch_accel,
|
||||
#ifdef CONFIG_LIS2DUX12_ENABLE_TEMP
|
||||
.sample_fetch_temp = st_lis2dux12_sample_fetch_temp,
|
||||
#endif
|
||||
#ifdef CONFIG_LIS2DUX12_TRIGGER
|
||||
.handle_interrupt = st_lis2dux12_handle_interrupt,
|
||||
.init_interrupt = st_lis2dux12_init_interrupt,
|
||||
#endif
|
||||
};
|
||||
|
||||
int st_lis2dux12_init(const struct device *dev)
|
||||
{
|
||||
const struct lis2dux12_config *const cfg = dev->config;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
uint8_t chip_id;
|
||||
int ret;
|
||||
|
||||
lis2dux12_exit_deep_power_down(ctx);
|
||||
k_busy_wait(25000);
|
||||
|
||||
/* check chip ID */
|
||||
ret = lis2dux12_device_id_get(ctx, &chip_id);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("%s: Not able to read dev id", dev->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (chip_id != LIS2DUX12_ID) {
|
||||
LOG_ERR("%s: Invalid chip ID 0x%02x", dev->name, chip_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* reset device */
|
||||
ret = lis2dux12_init_set(ctx, LIS2DUX12_RESET);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
k_busy_wait(100);
|
||||
|
||||
LOG_INF("%s: chip id 0x%x", dev->name, chip_id);
|
||||
|
||||
/* Set bdu and if_inc recommended for driver usage */
|
||||
lis2dux12_init_set(ctx, LIS2DUX12_SENSOR_ONLY_ON);
|
||||
|
||||
lis2dux12_timestamp_set(ctx, PROPERTY_ENABLE);
|
||||
|
||||
#ifdef CONFIG_LIS2DUX12_TRIGGER
|
||||
if (cfg->trig_enabled) {
|
||||
ret = lis2dux12_trigger_init(dev);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("%s: Failed to initialize triggers", dev->name);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* set sensor default pm and odr */
|
||||
LOG_DBG("%s: pm: %d, odr: %d", dev->name, cfg->pm, cfg->odr);
|
||||
ret = st_lis2dux12_set_odr_raw(dev, cfg->odr);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("%s: odr init error (12.5 Hz)", dev->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* set sensor default scale (used to convert sample values) */
|
||||
LOG_DBG("%s: range is %d", dev->name, cfg->range);
|
||||
ret = st_lis2dux12_set_range(dev, cfg->range);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("%s: range init error %d", dev->name, cfg->range);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
24
drivers/sensor/st/lis2dux12/lis2dux12_api.h
Normal file
24
drivers/sensor/st/lis2dux12/lis2dux12_api.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/* ST Microelectronics LIS2DUX12 smart accelerometer APIs
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics
|
||||
* Copyright (c) 2023 PHYTEC Messtechnik GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stmemsc.h>
|
||||
|
||||
#include "lis2dux12_reg.h"
|
||||
#include <zephyr/dt-bindings/sensor/lis2dux12.h>
|
||||
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_SENSOR_LIS2DUX12_ST_LIS2DUX12_H_
|
||||
#define ZEPHYR_DRIVERS_SENSOR_LIS2DUX12_ST_LIS2DUX12_H_
|
||||
|
||||
extern const struct lis2dux12_chip_api st_lis2dux12_chip_api;
|
||||
|
||||
int st_lis2dux12_init(const struct device *dev);
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_SENSOR_LIS2DUX12_ST_LIS2DUX12_H_ */
|
||||
|
|
@ -8,8 +8,6 @@
|
|||
* https://www.st.com/resource/en/datasheet/lis2dux12.pdf
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT st_lis2dux12
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
#include "lis2dux12.h"
|
||||
|
||||
|
|
@ -35,41 +33,16 @@ static void lis2dux12_gpio_callback(const struct device *dev, struct gpio_callba
|
|||
#endif
|
||||
}
|
||||
|
||||
static void lis2dux12_handle_drdy_int(const struct device *dev)
|
||||
{
|
||||
struct lis2dux12_data *data = dev->data;
|
||||
|
||||
if (data->data_ready_handler != NULL) {
|
||||
data->data_ready_handler(dev, data->data_ready_trigger);
|
||||
}
|
||||
}
|
||||
|
||||
static void lis2dux12_handle_int(const struct device *dev)
|
||||
{
|
||||
struct lis2dux12_data *lis2dux12 = dev->data;
|
||||
const struct lis2dux12_config *cfg = dev->config;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
lis2dux12_all_sources_t sources;
|
||||
int ret;
|
||||
|
||||
lis2dux12_all_sources_get(ctx, &sources);
|
||||
|
||||
if (sources.drdy) {
|
||||
lis2dux12_handle_drdy_int(dev);
|
||||
}
|
||||
|
||||
ret = gpio_pin_interrupt_configure_dt(lis2dux12->drdy_gpio, GPIO_INT_EDGE_TO_ACTIVE);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("%s: Not able to configure pin_int", dev->name);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LIS2DUX12_TRIGGER_OWN_THREAD
|
||||
static void lis2dux12_thread(struct lis2dux12_data *data)
|
||||
{
|
||||
const struct device *dev = data->dev;
|
||||
const struct lis2dux12_config *const cfg = dev->config;
|
||||
const struct lis2dux12_chip_api *chip_api = cfg->chip_api;
|
||||
|
||||
while (1) {
|
||||
k_sem_take(&data->trig_sem, K_FOREVER);
|
||||
lis2dux12_handle_int(data->dev);
|
||||
chip_api->handle_interrupt(dev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -78,40 +51,14 @@ static void lis2dux12_thread(struct lis2dux12_data *data)
|
|||
static void lis2dux12_work_cb(struct k_work *work)
|
||||
{
|
||||
struct lis2dux12_data *data = CONTAINER_OF(work, struct lis2dux12_data, work);
|
||||
const struct device *dev = data->dev;
|
||||
const struct lis2dux12_config *const cfg = dev->config;
|
||||
const struct lis2dux12_chip_api *chip_api = cfg->chip_api;
|
||||
|
||||
lis2dux12_handle_int(data->dev);
|
||||
chip_api->handle_interrupt(dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lis2dux12_init_interrupt(const struct device *dev)
|
||||
{
|
||||
const struct lis2dux12_config *cfg = dev->config;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
lis2dux12_pin_int_route_t route;
|
||||
int err;
|
||||
|
||||
/* Enable pulsed mode */
|
||||
err = lis2dux12_data_ready_mode_set(ctx, LIS2DUX12_DRDY_PULSED);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* route data-ready interrupt on int1 */
|
||||
err = lis2dux12_pin_int1_route_get(ctx, &route);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
route.drdy = 1;
|
||||
|
||||
err = lis2dux12_pin_int1_route_set(ctx, &route);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lis2dux12_trigger_init(const struct device *dev)
|
||||
{
|
||||
struct lis2dux12_data *data = dev->data;
|
||||
|
|
@ -162,9 +109,7 @@ int lis2dux12_trigger_set(const struct device *dev, const struct sensor_trigger
|
|||
{
|
||||
struct lis2dux12_data *data = dev->data;
|
||||
const struct lis2dux12_config *cfg = dev->config;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
lis2dux12_xl_data_t xldata;
|
||||
lis2dux12_md_t mode = {.fs = cfg->range};
|
||||
const struct lis2dux12_chip_api *chip_api = cfg->chip_api;
|
||||
int ret;
|
||||
|
||||
if (!cfg->trig_enabled) {
|
||||
|
|
@ -190,10 +135,15 @@ int lis2dux12_trigger_set(const struct device *dev, const struct sensor_trigger
|
|||
}
|
||||
|
||||
/* re-trigger lost interrupt */
|
||||
lis2dux12_xl_data_get(ctx, &mode, &xldata);
|
||||
chip_api->sample_fetch_accel(dev);
|
||||
|
||||
data->data_ready_trigger = trig;
|
||||
|
||||
lis2dux12_init_interrupt(dev);
|
||||
ret = chip_api->init_interrupt(dev);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("%s: Not able to initialize device interrupt", dev->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return gpio_pin_interrupt_configure_dt(data->drdy_gpio, GPIO_INT_EDGE_TO_ACTIVE);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue