diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index ff1cf9ec4eb449c..658cc42976595f2 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -68,6 +68,7 @@ add_subdirectory_ifdef(CONFIG_ITDS wsen_itds) add_subdirectory_ifdef(CONFIG_LIS2DH lis2dh) add_subdirectory_ifdef(CONFIG_LIS2DS12 lis2ds12) add_subdirectory_ifdef(CONFIG_LIS2DW12 lis2dw12) +add_subdirectory_ifdef(CONFIG_LIS2DUX12 lis2dux12) add_subdirectory_ifdef(CONFIG_LIS2MDL lis2mdl) add_subdirectory_ifdef(CONFIG_LIS3MDL lis3mdl) add_subdirectory_ifdef(CONFIG_LM75 lm75) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 55ef3ffec513643..70cf28230324299 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -141,6 +141,7 @@ source "drivers/sensor/ite_vcmp_it8xxx2/Kconfig" source "drivers/sensor/lis2dh/Kconfig" source "drivers/sensor/lis2ds12/Kconfig" source "drivers/sensor/lis2dw12/Kconfig" +source "drivers/sensor/lis2dux12/Kconfig" source "drivers/sensor/lis2mdl/Kconfig" source "drivers/sensor/lis3mdl/Kconfig" source "drivers/sensor/lm75/Kconfig" diff --git a/drivers/sensor/lis2dux12/CMakeLists.txt b/drivers/sensor/lis2dux12/CMakeLists.txt new file mode 100644 index 000000000000000..3710688b92909f8 --- /dev/null +++ b/drivers/sensor/lis2dux12/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(lis2dux12.c) +zephyr_library_sources_ifdef(CONFIG_LIS2DUX12_TRIGGER lis2dux12_trigger.c) + +zephyr_library_include_directories(../stmemsc) +zephyr_library_include_directories(../../../../modules/hal/st/sensor/stmemsc/lis2dux12_STdC/driver) diff --git a/drivers/sensor/lis2dux12/Kconfig b/drivers/sensor/lis2dux12/Kconfig new file mode 100644 index 000000000000000..fb3d8c768595345 --- /dev/null +++ b/drivers/sensor/lis2dux12/Kconfig @@ -0,0 +1,61 @@ +# ST Microelectronics LIS2DUX12 3-axis accelerometer driver + +# Copyright (c) 2019 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +menuconfig LIS2DUX12 + bool "LIS2DUX12 I2C/SPI accelerometer sensor driver" + default y + depends on DT_HAS_ST_LIS2DUX12_ENABLED + select I2C if $(dt_compat_on_bus,$(DT_COMPAT_ST_LIS2DUX12),i2c) + select SPI if $(dt_compat_on_bus,$(DT_COMPAT_ST_LIS2DUX12),spi) + select HAS_STMEMSC + select USE_STDC_LIS2DUX12 + help + Enable driver for LIS2DUX12 accelerometer sensor driver + +if LIS2DUX12 + +choice LIS2DUX12_TRIGGER_MODE + prompt "Trigger mode" + help + Specify the type of triggering to be used by the driver. + +config LIS2DUX12_TRIGGER_NONE + bool "No trigger" + +config LIS2DUX12_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + depends on GPIO + select LIS2DUX12_TRIGGER + +config LIS2DUX12_TRIGGER_OWN_THREAD + bool "Use own thread" + depends on GPIO + select LIS2DUX12_TRIGGER + +endchoice + +config LIS2DUX12_TRIGGER + bool + +config LIS2DUX12_THREAD_PRIORITY + int "Thread priority" + depends on LIS2DUX12_TRIGGER_OWN_THREAD + default 10 + help + Priority of thread used by the driver to handle interrupts. + +config LIS2DUX12_THREAD_STACK_SIZE + int "Thread stack size" + depends on LIS2DUX12_TRIGGER_OWN_THREAD + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + +config LIS2DUX12_ENABLE_TEMP + bool "Temperature" + help + Enable/disable temperature + +endif # LIS2DUX12 diff --git a/drivers/sensor/lis2dux12/lis2dux12.c b/drivers/sensor/lis2dux12/lis2dux12.c new file mode 100644 index 000000000000000..2b29957c61a3e97 --- /dev/null +++ b/drivers/sensor/lis2dux12/lis2dux12.c @@ -0,0 +1,394 @@ +/* ST Microelectronics LIS2DUX12 3-axis accelerometer driver + * + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/lis2dux12.pdf + */ + +#define DT_DRV_COMPAT st_lis2dux12 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lis2dux12.h" + +LOG_MODULE_REGISTER(LIS2DUX12, CONFIG_SENSOR_LOG_LEVEL); + +static int lis2dux12_set_odr(const struct device *dev, uint8_t odr) +{ + const struct lis2dux12_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lis2dux12_md_t mode = {.odr = odr}; + + return lis2dux12_mode_set(ctx, &mode); +} + +/** + * @brief Accelerometer full-scale selection.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of fs in reg CTRL5 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +static int32_t lis2dux12_full_scale_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lis2dux12_ctrl5_t reg; + int32_t ret; + + ret = lis2dux12_read_reg(ctx, LIS2DUX12_CTRL5, (uint8_t *)®, 1); + + if (ret == 0) { + reg.fs = (uint8_t)val; + ret = lis2dux12_write_reg(ctx, LIS2DUX12_CTRL5, (uint8_t *)®, 1); + } + + return ret; +} + +static int lis2dux12_set_range(const struct device *dev, uint8_t range) +{ + int err = 0; + struct lis2dux12_data *data = dev->data; + + switch (range) { + default: + case 0U: + data->gain = lis2dux12_from_fs2g_to_mg(1); + break; + case 1U: + data->gain = lis2dux12_from_fs4g_to_mg(1); + break; + case 2U: + data->gain = lis2dux12_from_fs8g_to_mg(1); + break; + case 3U: + data->gain = lis2dux12_from_fs16g_to_mg(1); + break; + } + + return err; +} + +static int lis2dux12_accel_config(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + switch (attr) { + case SENSOR_ATTR_FULL_SCALE: + return lis2dux12_set_range(dev, sensor_ms2_to_g(val)); + case SENSOR_ATTR_SAMPLING_FREQUENCY: + LOG_DBG("%s: set odr to %d Hz", dev->name, val->val1); + return lis2dux12_set_odr(dev, LIS2DUX12_ODR_TO_REG(val->val1)); + default: + LOG_DBG("Accel attribute not supported."); + return -ENOTSUP; + } + + return 0; +} + +static int lis2dux12_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + switch (chan) { + case SENSOR_CHAN_ACCEL_XYZ: + return lis2dux12_accel_config(dev, chan, attr, val); + default: + LOG_WRN("attr_set() not supported on this channel."); + return -ENOTSUP; + } + + 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 = cfg->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 = sys_le16_to_cpu(xzy_data.raw[0]); + data->sample_y = sys_le16_to_cpu(xzy_data.raw[1]); + data->sample_z = sys_le16_to_cpu(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; + uint8_t buf[6]; + + /* fetch raw data sample */ + lis2dux12_md_t mode; + lis2dux12_outt_data_t temp_data = {0}; + if (lis2dux12_outt_data_get(ctx, &mode, &temp_data) < 0) { + LOG_ERR("Failed to fetch raw temperature data sample"); + return -EIO; + } + + data->sample_temp = sys_le16_to_cpu(temp_data.raw[0]); + + return 0; +} +#endif + +static int lis2dux12_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + switch (chan) { + case SENSOR_CHAN_ACCEL_XYZ: + lis2dux12_sample_fetch_accel(dev); + break; +#if defined(CONFIG_LIS2DUX12_ENABLE_TEMP) + case SENSOR_CHAN_DIE_TEMP: + lis2dux12_sample_fetch_temp(dev) break; +#endif + case SENSOR_CHAN_ALL: + lis2dux12_sample_fetch_accel(dev); +#if defined(CONFIG_LIS2DUX12_ENABLE_TEMP) + lis2dux12_sample_fetch_temp(dev); +#endif + break; + default: + return -ENOTSUP; + } + + return 0; +} + +static inline void lis2dux12_convert(struct sensor_value *val, int raw_val, float gain) +{ + int64_t dval; + + /* Gain is in mg/LSB */ + /* Convert to m/s^2 */ + dval = ((int64_t)raw_val * gain * SENSOR_G) / 1000; + val->val1 = dval / 1000000LL; + val->val2 = dval % 1000000LL; +} + +static inline int lis2dux12_get_channel(enum sensor_channel chan, struct sensor_value *val, + struct lis2dux12_data *data, float gain) +{ + switch (chan) { + case SENSOR_CHAN_ACCEL_X: + lis2dux12_convert(val, data->sample_x, gain); + break; + case SENSOR_CHAN_ACCEL_Y: + lis2dux12_convert(val, data->sample_y, gain); + break; + case SENSOR_CHAN_ACCEL_Z: + lis2dux12_convert(val, data->sample_z, gain); + break; + case SENSOR_CHAN_ACCEL_XYZ: + lis2dux12_convert(val, data->sample_x, gain); + lis2dux12_convert(val + 1, data->sample_y, gain); + lis2dux12_convert(val + 2, data->sample_z, gain); + break; +#if defined(CONFIG_LIS2DUX12_ENABLE_TEMP) + case SENSOR_CHAN_DIE_TEMP: + sensor_value_from_double(val, data->sample_temp); + break; +#endif + default: + return -ENOTSUP; + } + + return 0; +} + +static int lis2dux12_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct lis2dux12_data *data = dev->data; + + return lis2dux12_get_channel(chan, val, data, data->gain); +} + +static const struct sensor_driver_api lis2dux12_driver_api = { + .attr_set = lis2dux12_attr_set, +#if defined(CONFIG_LIS2DUX12_TRIGGER) + .trigger_set = lis2dux12_trigger_set, +#endif + .sample_fetch = lis2dux12_sample_fetch, + .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); /* 25ms */ + + /* 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_WRN("%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); + + static lis2dux12_fifo_mode_t fifo_mode; + /* Set FIFO watermark to 32 sample(s) */ + fifo_mode.store = LIS2DUX12_FIFO_1X; + fifo_mode.xl_only = 0; + fifo_mode.watermark = 33; /* 32 samples + timestamp */ + fifo_mode.operation = LIS2DUX12_STREAM_MODE; /* old data is automatically overwritten */ + fifo_mode.batch.dec_ts = LIS2DUX12_DEC_TS_OFF; + fifo_mode.batch.bdr_xl = LIS2DUX12_BDR_XL_ODR; + lis2dux12_fifo_mode_set(ctx, fifo_mode); + + lis2dux12_timestamp_set(ctx, PROPERTY_ENABLE); + +#ifdef CONFIG_LIS2DUX12_TRIGGER + 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_WRN("%s: pm: %d, odr: %d", dev->name, cfg->pm, cfg->odr); + lis2dux12_md_t mode = { + .odr = cfg->odr, + .fs = cfg->range, + }; + ret = lis2dux12_mode_set(ctx, &mode); + 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_WRN("%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; +} + +#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0 +#warning "LIS2DUX12 driver enabled without any devices" +#endif + +/* + * 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) .gpio_int = GPIO_DT_SPEC_INST_GET(inst, irq_gpios), +#else +#define LIS2DUX12_CFG_IRQ(inst) +#endif /* CONFIG_LIS2DUX12_TRIGGER */ + +#define LIS2DUX12_SPI_OPERATION \ + (SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA) + +#define LIS2DUX12_CONFIG_SPI(inst) \ + { \ + .ctx = \ + { \ + .read_reg = (stmdev_read_ptr)stmemsc_spi_read, \ + .write_reg = (stmdev_write_ptr)stmemsc_spi_write, \ + .mdelay = (stmdev_mdelay_ptr)stmemsc_mdelay, \ + .handle = (void *)&lis2dux12_config_##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(DT_INST_NODE_HAS_PROP(inst, irq_gpios), (LIS2DUX12_CFG_IRQ(inst)), ()) \ + } + +/* + * Instantiation macros used when a device is on an I2C bus. + */ + +#define LIS2DUX12_CONFIG_I2C(inst) \ + { \ + .ctx = \ + { \ + .read_reg = (stmdev_read_ptr)stmemsc_i2c_read, \ + .write_reg = (stmdev_write_ptr)stmemsc_i2c_write, \ + .mdelay = (stmdev_mdelay_ptr)stmemsc_mdelay, \ + .handle = (void *)&lis2dux12_config_##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(DT_INST_NODE_HAS_PROP(inst, irq_gpios), (LIS2DUX12_CFG_IRQ(inst)), ()) \ + } + +/* + * Main instantiation macro. Use of IF_ENABLED() selects the right + * 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 = \ + IF_ENABLED(DT_INST_ON_BUS(inst, spi), (LIS2DUX12_CONFIG_SPI(inst)), \ + (LIS2DUX12_CONFIG_I2C(inst))); \ + LIS2DUX12_DEVICE_INIT(inst) + +DT_INST_FOREACH_STATUS_OKAY(LIS2DUX12_DEFINE) diff --git a/drivers/sensor/lis2dux12/lis2dux12.h b/drivers/sensor/lis2dux12/lis2dux12.h new file mode 100644 index 000000000000000..37dc80c347572cd --- /dev/null +++ b/drivers/sensor/lis2dux12/lis2dux12.h @@ -0,0 +1,87 @@ +/* ST Microelectronics LIS2DUX12 3-axis accelerometer driver + * + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/lis2dux12.pdf + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_LIS2DUX12_LIS2DUX12_H_ +#define ZEPHYR_DRIVERS_SENSOR_LIS2DUX12_LIS2DUX12_H_ + +#include +#include +#include +#include +#include "lis2dux12_reg.h" + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) +#include +#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) */ + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) +#include +#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */ + +/* Return ODR reg value based on data rate set */ +#define LIS2DUX12_ODR_TO_REG(_odr) \ + ((_odr <= 1) ? 1 : \ + ((31 - __builtin_clz(_odr / 25))) + 3) + +struct lis2dux12_config { + stmdev_ctx_t ctx; + union { +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) + const struct i2c_dt_spec i2c; +#endif +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) + const struct spi_dt_spec spi; +#endif + } stmemsc_cfg; + uint8_t range; + uint8_t pm; + uint8_t odr; +#ifdef CONFIG_LIS2DUX12_TRIGGER + struct gpio_dt_spec gpio_int; +#endif +}; + +struct lis2dux12_data { + int sample_x; + int sample_y; + int sample_z; + float gain; + +#ifdef CONFIG_LIS2DUX12_ENABLE_TEMP + int sample_temp; +#endif + +#ifdef CONFIG_LIS2DUX12_TRIGGER + struct gpio_callback gpio_cb; + + const struct sensor_trigger *data_ready_trigger; + sensor_trigger_handler_t data_ready_handler; + const struct device *dev; + +#if defined(CONFIG_LIS2DUX12_TRIGGER_OWN_THREAD) + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_LIS2DUX12_THREAD_STACK_SIZE); + struct k_thread thread; + struct k_sem trig_sem; +#elif defined(CONFIG_LIS2DUX12_TRIGGER_GLOBAL_THREAD) + struct k_work work; +#endif + +#endif /* CONFIG_LIS2DUX12_TRIGGER */ +}; + +#ifdef CONFIG_LIS2DUX12_TRIGGER +int lis2dux12_trigger_set(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); + +int lis2dux12_trigger_init(const struct device *dev); +#endif + +#endif /* ZEPHYR_DRIVERS_SENSOR_LIS2DUX12_LIS2DUX12_H_ */ diff --git a/drivers/sensor/lis2dux12/lis2dux12_trigger.c b/drivers/sensor/lis2dux12/lis2dux12_trigger.c new file mode 100644 index 000000000000000..5425d4a4e3c2765 --- /dev/null +++ b/drivers/sensor/lis2dux12/lis2dux12_trigger.c @@ -0,0 +1,199 @@ +/* ST Microelectronics LIS2DUX12 3-axis accelerometer driver + * + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/lis2dux12.pdf + */ + +#define DT_DRV_COMPAT st_lis2dux12 + +#include +#include "lis2dux12.h" + +LOG_MODULE_DECLARE(LIS2DUX12, CONFIG_SENSOR_LOG_LEVEL); + +static void lis2dux12_gpio_callback(const struct device *dev, struct gpio_callback *cb, + uint32_t pins) +{ + struct lis2dux12_data *data = CONTAINER_OF(cb, struct lis2dux12_data, gpio_cb); + const struct lis2dux12_config *cfg = data->dev->config; + int ret; + + ARG_UNUSED(pins); + + ret = gpio_pin_interrupt_configure_dt(&cfg->gpio_int, GPIO_INT_DISABLE); + if (ret < 0) { + LOG_ERR("%s: Not able to configure pin_int", dev->name); + } + +#if defined(CONFIG_LIS2DUX12_TRIGGER_OWN_THREAD) + k_sem_give(&data->trig_sem); +#elif defined(CONFIG_LIS2DUX12_TRIGGER_GLOBAL_THREAD) + k_work_submit(&data->work); +#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) +{ + 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(&cfg->gpio_int, 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) +{ + while (1) { + k_sem_take(&data->trig_sem, K_FOREVER); + lis2dux12_handle_int(data->dev); + } +} +#endif + +#ifdef CONFIG_LIS2DUX12_TRIGGER_GLOBAL_THREAD +static void lis2dux12_work_cb(struct k_work *work) +{ + struct lis2dux12_data *data = CONTAINER_OF(work, struct lis2dux12_data, work); + + lis2dux12_handle_int(data->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; + const struct lis2dux12_config *cfg = dev->config; + int ret; + + /* setup data ready gpio interrupt (INT1 or INT2) */ + if (!device_is_ready(cfg->gpio_int.port)) { + if (cfg->gpio_int.port) { + LOG_ERR("%s: device %s is not ready", dev->name, cfg->gpio_int.port->name); + return -ENODEV; + } + + LOG_DBG("%s: gpio_int not defined in DT", dev->name); + return 0; + } + + data->dev = dev; + + ret = gpio_pin_configure_dt(&cfg->gpio_int, GPIO_INPUT); + if (ret < 0) { + LOG_ERR("Could not configure gpio"); + return ret; + } + + LOG_INF("%s: int on %s.%02u", dev->name, cfg->gpio_int.port->name, cfg->gpio_int.pin); + + gpio_init_callback(&data->gpio_cb, lis2dux12_gpio_callback, BIT(cfg->gpio_int.pin)); + + ret = gpio_add_callback(cfg->gpio_int.port, &data->gpio_cb); + if (ret < 0) { + LOG_ERR("Could not set gpio callback"); + return ret; + } + +#if defined(CONFIG_LIS2DUX12_TRIGGER_OWN_THREAD) + k_sem_init(&data->trig_sem, 0, K_SEM_MAX_LIMIT); + + k_thread_create(&data->thread, data->thread_stack, CONFIG_LIS2DUX12_THREAD_STACK_SIZE, + (k_thread_entry_t)lis2dux12_thread, data, NULL, NULL, + K_PRIO_COOP(CONFIG_LIS2DUX12_THREAD_PRIORITY), 0, K_NO_WAIT); +#elif defined(CONFIG_LIS2DUX12_TRIGGER_GLOBAL_THREAD) + data->work.handler = lis2dux12_work_cb; +#endif + + return gpio_pin_interrupt_configure_dt(&cfg->gpio_int, GPIO_INT_EDGE_TO_ACTIVE); +} + +int lis2dux12_trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + 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; + int ret; + + __ASSERT_NO_MSG(trig->type == SENSOR_TRIG_DATA_READY); + + if (cfg->gpio_int.port == NULL) { + LOG_ERR("trigger_set is not supported"); + return -ENOTSUP; + } + + ret = gpio_pin_interrupt_configure_dt(&cfg->gpio_int, GPIO_INT_DISABLE); + if (ret < 0) { + LOG_ERR("%s: Not able to configure pin_int", dev->name); + return ret; + } + + data->data_ready_handler = handler; + if (handler == NULL) { + LOG_WRN("lis2dux12: no handler"); + return 0; + } + + /* re-trigger lost interrupt */ + lis2dux12_xl_data_get(ctx, &mode, &xldata); + + data->data_ready_trigger = trig; + + lis2dux12_init_interrupt(dev); + return gpio_pin_interrupt_configure_dt(&cfg->gpio_int, GPIO_INT_EDGE_TO_ACTIVE); +} diff --git a/dts/bindings/sensor/st,lis2dux12-common.yaml b/dts/bindings/sensor/st,lis2dux12-common.yaml new file mode 100644 index 000000000000000..f7428025b8b0a09 --- /dev/null +++ b/dts/bindings/sensor/st,lis2dux12-common.yaml @@ -0,0 +1,58 @@ +# Copyright (c) 2021 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +include: sensor-device.yaml + +properties: + irq-gpios: + type: phandle-array + description: | + DRDY pin + + This pin defaults to active high when produced by the sensor. + The property value should ensure the flags properly describe + the signal that is presented to the driver. + + range: + type: int + default: 0 + description: | + Range in g. Default is power-up configuration. + + enum: + - 3 # 16g (0.488 mg/LSB) + - 2 # 8g (0.244 mg/LSB) + - 1 # 4g (0.122 mg/LSB) + - 0 # 2g (0.061 mg/LSB) + + power-mode: + type: int + default: 0 + description: | + Specify the sensor power mode. Default is power-down mode + + enum: + - 0 # Power Down (PD) + - 1 # Low Power (LP) + - 2 # High Resolution (HR) + - 3 # High Frequency (HF) + + odr: + type: int + default: 0 + description: | + Specify the default output data rate expressed in samples per second (Hz). + Default is power-down mode + enum: + - 0 # Power-Down + - 1 # 1Hz (ultra low power) + - 2 # 3Hz (ultra low power) + - 3 # 25Hz (ultra low power) + - 4 # 6Hz (available in LP and HP mode) + - 5 # 12.5Hz (available in LP and HP mode) + - 6 # 25Hz (available in LP and HP mode) + - 7 # 50Hz (available in LP and HP mode) + - 8 # 100Hz (available in LP and HP mode) + - 9 # 200Hz (available in LP and HP mode) + - 10 # 400Hz (available in LP and HP mode) + - 11 # 800Hz (available in LP and HP mode) diff --git a/dts/bindings/sensor/st,lis2dux12-i2c.yaml b/dts/bindings/sensor/st,lis2dux12-i2c.yaml new file mode 100644 index 000000000000000..d4b482a0b942ed1 --- /dev/null +++ b/dts/bindings/sensor/st,lis2dux12-i2c.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2019 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: STMicroelectronics LIS2DUX12 3-axis accelerometer + +compatible: "st,lis2dux12" + +include: ["i2c-device.yaml", "st,lis2dux12-common.yaml"] diff --git a/dts/bindings/sensor/st,lis2dux12-spi.yaml b/dts/bindings/sensor/st,lis2dux12-spi.yaml new file mode 100644 index 000000000000000..bf065926f28a1b4 --- /dev/null +++ b/dts/bindings/sensor/st,lis2dux12-spi.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2019 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STMicroelectronics LIS2DUX12 3-axis accelerometer accessed through SPI bus + +compatible: "st,lis2dux12" + +include: ["spi-device.yaml", "st,lis2dux12-common.yaml"] diff --git a/modules/Kconfig.st b/modules/Kconfig.st index fd90aee0b171e44..7d4a152b868a1ac 100644 --- a/modules/Kconfig.st +++ b/modules/Kconfig.st @@ -91,6 +91,9 @@ config USE_STDC_LIS2DTW12 config USE_STDC_LIS2DW12 bool +config USE_STDC_LIS2DUX12 + bool + config USE_STDC_LIS2HH12 bool diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index 42beeab095e6317..2e01f40f10d7513 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -807,3 +807,9 @@ test_i2c_lps22df: lps22df@78 { drdy-gpios = <&test_gpio 0 0>; status = "okay"; }; + +test_i2c_lis2dux12: lis2dux12@80 { + compatible = "st,lis2dux12"; + reg = <0x80>; + irq-gpios = <&test_gpio 0 0>; +}; diff --git a/tests/drivers/build_all/sensor/sensors_trigger_global.conf b/tests/drivers/build_all/sensor/sensors_trigger_global.conf index c42b4fa951e1d3d..94557eef91d05e3 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_global.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_global.conf @@ -34,6 +34,7 @@ CONFIG_ISM330DHCX_TRIGGER_GLOBAL_THREAD=y CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD=y CONFIG_LIS2DS12_TRIGGER_GLOBAL_THREAD=y CONFIG_LIS2DW12_TRIGGER_GLOBAL_THREAD=y +CONFIG_LIS2DUX12_TRIGGER_GLOBAL_THREAD=y CONFIG_LIS2MDL_TRIGGER_GLOBAL_THREAD=y CONFIG_LIS3MDL_TRIGGER_GLOBAL_THREAD=y CONFIG_LPS22DF_TRIGGER_GLOBAL_THREAD=y diff --git a/tests/drivers/build_all/sensor/sensors_trigger_none.conf b/tests/drivers/build_all/sensor/sensors_trigger_none.conf index 9c46cb3637e6e87..1e0412e14d4e9bf 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_none.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_none.conf @@ -34,6 +34,7 @@ CONFIG_ISM330DHCX_TRIGGER_NONE=y CONFIG_LIS2DH_TRIGGER_NONE=y CONFIG_LIS2DS12_TRIGGER_NONE=y CONFIG_LIS2DW12_TRIGGER_NONE=y +CONFIG_LIS2DUX12_TRIGGER_NONE=y CONFIG_LIS2MDL_TRIGGER_NONE=y CONFIG_LIS3MDL_TRIGGER_NONE=y CONFIG_LPS22DF_TRIGGER_NONE=y diff --git a/tests/drivers/build_all/sensor/sensors_trigger_own.conf b/tests/drivers/build_all/sensor/sensors_trigger_own.conf index 5ecacb03d9a85ae..ff46a7cef43ee93 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_own.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_own.conf @@ -32,6 +32,7 @@ CONFIG_ISM330DHCX_TRIGGER_OWN_THREAD=y CONFIG_LIS2DH_TRIGGER_OWN_THREAD=y CONFIG_LIS2DS12_TRIGGER_OWN_THREAD=y CONFIG_LIS2DW12_TRIGGER_OWN_THREAD=y +CONFIG_LIS2DUX12_TRIGGER_OWN_THREAD=y CONFIG_LIS2MDL_TRIGGER_OWN_THREAD=y CONFIG_LIS3MDL_TRIGGER_OWN_THREAD=y CONFIG_LPS22DF_TRIGGER_OWN_THREAD=y diff --git a/tests/drivers/build_all/sensor/spi.dtsi b/tests/drivers/build_all/sensor/spi.dtsi index cd7bf1b66ec5da2..c6155e0021d0c67 100644 --- a/tests/drivers/build_all/sensor/spi.dtsi +++ b/tests/drivers/build_all/sensor/spi.dtsi @@ -312,3 +312,11 @@ test_spi_lps22df: lps22df@27 { drdy-gpios = <&test_gpio 0 0>; status = "okay"; }; + +test_spi_lis2dux12: lis2dux12@28 { + compatible = "st,lis2dux12"; + reg = <0x28>; + spi-max-frequency = <0>; + irq-gpios = <&test_gpio 0 0>; + status = "okay"; +};