diff --git a/drivers/sensor/st/lis2dux12/CMakeLists.txt b/drivers/sensor/st/lis2dux12/CMakeLists.txt index f22572af1cd..ea8f5c50c69 100644 --- a/drivers/sensor/st/lis2dux12/CMakeLists.txt +++ b/drivers/sensor/st/lis2dux12/CMakeLists.txt @@ -5,5 +5,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_sources_ifdef(CONFIG_DT_HAS_ST_LIS2DUXS12_ENABLED lis2duxs12_api.c ) zephyr_library_include_directories(../stmemsc) diff --git a/drivers/sensor/st/lis2dux12/Kconfig b/drivers/sensor/st/lis2dux12/Kconfig index d27344484a7..e2ed9f710af 100644 --- a/drivers/sensor/st/lis2dux12/Kconfig +++ b/drivers/sensor/st/lis2dux12/Kconfig @@ -6,12 +6,15 @@ menuconfig LIS2DUX12 bool "LIS2DUX12 I2C/SPI accelerometer sensor driver" default y - depends on DT_HAS_ST_LIS2DUX12_ENABLED + depends on DT_HAS_ST_LIS2DUX12_ENABLED || DT_HAS_ST_LIS2DUXS12_ENABLED depends on ZEPHYR_HAL_ST_MODULE - 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 I2C if $(dt_compat_on_bus,$(DT_COMPAT_ST_LIS2DUX12),i2c) || \ + $(dt_compat_on_bus,$(DT_COMPAT_ST_LIS2DUXS12),i2c) + select SPI if $(dt_compat_on_bus,$(DT_COMPAT_ST_LIS2DUX12),spi) || \ + $(dt_compat_on_bus,$(DT_COMPAT_ST_LIS2DUXS12),spi) select HAS_STMEMSC - select USE_STDC_LIS2DUX12 + select USE_STDC_LIS2DUX12 if DT_HAS_ST_LIS2DUX12_ENABLED + select USE_STDC_LIS2DUXS12 if DT_HAS_ST_LIS2DUXS12_ENABLED help Enable driver for LIS2DUX12 accelerometer sensor driver diff --git a/drivers/sensor/st/lis2dux12/lis2dux12.c b/drivers/sensor/st/lis2dux12/lis2dux12.c index 32895857105..cb3c5bee9e3 100644 --- a/drivers/sensor/st/lis2dux12/lis2dux12.c +++ b/drivers/sensor/st/lis2dux12/lis2dux12.c @@ -23,6 +23,10 @@ #include "lis2dux12_api.h" #endif +#if DT_HAS_COMPAT_STATUS_OKAY(st_lis2duxs12) +#include "lis2duxs12_api.h" +#endif + LOG_MODULE_REGISTER(LIS2DUX12, CONFIG_SENSOR_LOG_LEVEL); #define FOREACH_ODR_ENUM(ODR_VAL) \ @@ -305,3 +309,7 @@ static DEVICE_API(sensor, lis2dux12_driver_api) = { #define DT_DRV_COMPAT st_lis2dux12 DT_INST_FOREACH_STATUS_OKAY_VARGS(LIS2DUX12_DEFINE, DT_DRV_COMPAT) #undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT st_lis2duxs12 +DT_INST_FOREACH_STATUS_OKAY_VARGS(LIS2DUX12_DEFINE, DT_DRV_COMPAT) +#undef DT_DRV_COMPAT diff --git a/drivers/sensor/st/lis2dux12/lis2dux12.h b/drivers/sensor/st/lis2dux12/lis2dux12.h index 37f6b5fae5c..57acdb61982 100644 --- a/drivers/sensor/st/lis2dux12/lis2dux12.h +++ b/drivers/sensor/st/lis2dux12/lis2dux12.h @@ -20,11 +20,17 @@ #include "lis2dux12_reg.h" #endif -#if DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lis2dux12, spi) +#if DT_HAS_COMPAT_STATUS_OKAY(st_lis2duxs12) +#include "lis2duxs12_reg.h" +#endif + +#if DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lis2dux12, spi) || \ + DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lis2duxs12, spi) #include #endif -#if DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lis2dux12, i2c) +#if DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lis2dux12, i2c) || \ + DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lis2duxs12, i2c) #include #endif @@ -55,10 +61,12 @@ struct lis2dux12_chip_api { struct lis2dux12_config { stmdev_ctx_t ctx; union { -#if DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lis2dux12, i2c) +#if DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lis2dux12, i2c) || \ + DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lis2duxs12, i2c) const struct i2c_dt_spec i2c; #endif -#if DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lis2dux12, spi) +#if DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lis2dux12, spi) || \ + DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lis2duxs12, spi) const struct spi_dt_spec spi; #endif } stmemsc_cfg; diff --git a/drivers/sensor/st/lis2dux12/lis2dux12_api.h b/drivers/sensor/st/lis2dux12/lis2dux12_api.h index dd7efe35401..fc07c32de92 100644 --- a/drivers/sensor/st/lis2dux12/lis2dux12_api.h +++ b/drivers/sensor/st/lis2dux12/lis2dux12_api.h @@ -14,11 +14,11 @@ #include -#ifndef ZEPHYR_DRIVERS_SENSOR_LIS2DUX12_ST_LIS2DUX12_H_ -#define ZEPHYR_DRIVERS_SENSOR_LIS2DUX12_ST_LIS2DUX12_H_ +#ifndef ZEPHYR_DRIVERS_SENSOR_LIS2DUX12_LIS2DUX12_API_H_ +#define ZEPHYR_DRIVERS_SENSOR_LIS2DUX12_LIS2DUX12_API_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_ */ +#endif /* ZEPHYR_DRIVERS_SENSOR_LIS2DUX12_LIS2DUX12_API_H_ */ diff --git a/drivers/sensor/st/lis2dux12/lis2duxs12_api.c b/drivers/sensor/st/lis2dux12/lis2duxs12_api.c new file mode 100644 index 00000000000..23100aee4b4 --- /dev/null +++ b/drivers/sensor/st/lis2dux12/lis2duxs12_api.c @@ -0,0 +1,237 @@ +/* ST Microelectronics LIS2DUXS12 smart accelerometer APIs + * + * Copyright (c) 2024 STMicroelectronics + * Copyright (c) 2023 PHYTEC Messtechnik GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "lis2dux12.h" +#include "lis2duxs12_api.h" +#include + +LOG_MODULE_DECLARE(LIS2DUX12, CONFIG_SENSOR_LOG_LEVEL); + +static int32_t st_lis2duxs12_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; + lis2duxs12_md_t mode = {.odr = odr, .fs = data->range}; + + data->odr = odr; + return lis2duxs12_mode_set(ctx, &mode); +} + +static int32_t st_lis2duxs12_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; + lis2duxs12_md_t val = { .odr = data->odr, .fs = range }; + + err = lis2duxs12_mode_set(ctx, &val); + if (err) { + return err; + } + + switch (range) { + case LIS2DUX12_DT_FS_2G: + data->gain = lis2duxs12_from_fs2g_to_mg(1); + break; + case LIS2DUX12_DT_FS_4G: + data->gain = lis2duxs12_from_fs4g_to_mg(1); + break; + case LIS2DUX12_DT_FS_8G: + data->gain = lis2duxs12_from_fs8g_to_mg(1); + break; + case LIS2DUX12_DT_FS_16G: + data->gain = lis2duxs12_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_lis2duxs12_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 */ + lis2duxs12_md_t mode = {.fs = data->range}; + lis2duxs12_xl_data_t xzy_data = {0}; + + if (lis2duxs12_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_lis2duxs12_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 */ + lis2duxs12_outt_data_t temp_data = {0}; + + if (lis2duxs12_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_lis2duxs12_handle_interrupt(const struct device *dev) +{ + struct lis2dux12_data *lis2duxs12 = dev->data; + const struct lis2dux12_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lis2duxs12_all_sources_t sources; + int ret; + + lis2duxs12_all_sources_get(ctx, &sources); + + if (sources.drdy == 0) { + goto exit; /* spurious interrupt */ + } + + if (lis2duxs12->data_ready_handler != NULL) { + lis2duxs12->data_ready_handler(dev, lis2duxs12->data_ready_trigger); + } + +exit: + ret = gpio_pin_interrupt_configure_dt(lis2duxs12->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_lis2duxs12_init_interrupt(const struct device *dev) +{ + const struct lis2dux12_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lis2duxs12_pin_int_route_t route; + int err; + + /* Enable pulsed mode */ + err = lis2duxs12_data_ready_mode_set(ctx, LIS2DUXS12_DRDY_PULSED); + if (err < 0) { + return err; + } + + /* route data-ready interrupt on int1 */ + err = lis2duxs12_pin_int1_route_get(ctx, &route); + if (err < 0) { + return err; + } + + route.drdy = 1; + + err = lis2duxs12_pin_int1_route_set(ctx, &route); + if (err < 0) { + return err; + } + + return 0; +} +#endif + +const struct lis2dux12_chip_api st_lis2duxs12_chip_api = { + .set_odr_raw = st_lis2duxs12_set_odr_raw, + .set_range = st_lis2duxs12_set_range, + .sample_fetch_accel = st_lis2duxs12_sample_fetch_accel, +#ifdef CONFIG_LIS2DUX12_ENABLE_TEMP + .sample_fetch_temp = st_lis2duxs12_sample_fetch_temp, +#endif +#ifdef CONFIG_LIS2DUX12_TRIGGER + .handle_interrupt = st_lis2duxs12_handle_interrupt, + .init_interrupt = st_lis2duxs12_init_interrupt, +#endif +}; + +int st_lis2duxs12_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; + + lis2duxs12_exit_deep_power_down(ctx); + k_busy_wait(25000); + + /* check chip ID */ + ret = lis2duxs12_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 != LIS2DUXS12_ID) { + LOG_ERR("%s: Invalid chip ID 0x%02x", dev->name, chip_id); + return -EINVAL; + } + + /* reset device */ + ret = lis2duxs12_init_set(ctx, LIS2DUXS12_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 */ + lis2duxs12_init_set(ctx, LIS2DUXS12_SENSOR_ONLY_ON); + + lis2duxs12_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_lis2duxs12_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_lis2duxs12_set_range(dev, cfg->range); + if (ret < 0) { + LOG_ERR("%s: range init error %d", dev->name, cfg->range); + return ret; + } + + return 0; +} diff --git a/drivers/sensor/st/lis2dux12/lis2duxs12_api.h b/drivers/sensor/st/lis2dux12/lis2duxs12_api.h new file mode 100644 index 00000000000..5932c326261 --- /dev/null +++ b/drivers/sensor/st/lis2dux12/lis2duxs12_api.h @@ -0,0 +1,24 @@ +/* ST Microelectronics LIS2DUXS12 smart accelerometer APIs + * + * Copyright (c) 2024 STMicroelectronics + * Copyright (c) 2023 PHYTEC Messtechnik GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "lis2duxs12_reg.h" +#include + +#include + +#ifndef ZEPHYR_DRIVERS_SENSOR_LIS2DUXS12_LIS2DUXS12_API_H_ +#define ZEPHYR_DRIVERS_SENSOR_LIS2DUXS12_LIS2DUXS12_API_H_ + +extern const struct lis2dux12_chip_api st_lis2duxs12_chip_api; + +int st_lis2duxs12_init(const struct device *dev); + +#endif /* ZEPHYR_DRIVERS_SENSOR_LIS2DUXS12_LIS2DUXS12_API_H_ */ diff --git a/dts/bindings/sensor/st,lis2duxs12-common.yaml b/dts/bindings/sensor/st,lis2duxs12-common.yaml new file mode 100644 index 00000000000..0f428dbb482 --- /dev/null +++ b/dts/bindings/sensor/st,lis2duxs12-common.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + When setting the odr, power-mode, and range properties in a .dts or .dtsi file you may include + st_lis2dux12.h and use the macros defined there. + Example: + #include + lis2duxs12: lis2duxs12@0 { + ... + power-mode = ; + odr = ; + range = ; + }; + +# LIS2DUXS12 is a superset of LIS2DUX12 +include: st,lis2dux12-common.yaml diff --git a/dts/bindings/sensor/st,lis2duxs12-i2c.yaml b/dts/bindings/sensor/st,lis2duxs12-i2c.yaml new file mode 100644 index 00000000000..43b9ae32691 --- /dev/null +++ b/dts/bindings/sensor/st,lis2duxs12-i2c.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: STMicroelectronics LIS2DUXS12 3-axis accelerometer + +compatible: "st,lis2duxs12" + +include: ["i2c-device.yaml", "st,lis2duxs12-common.yaml"] diff --git a/dts/bindings/sensor/st,lis2duxs12-spi.yaml b/dts/bindings/sensor/st,lis2duxs12-spi.yaml new file mode 100644 index 00000000000..11ab371dc3f --- /dev/null +++ b/dts/bindings/sensor/st,lis2duxs12-spi.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STMicroelectronics LIS2DUXS12 3-axis accelerometer accessed through SPI bus + +compatible: "st,lis2duxs12" + +include: ["spi-device.yaml", "st,lis2duxs12-common.yaml"] diff --git a/modules/hal_st/Kconfig b/modules/hal_st/Kconfig index 579f7f7d3f8..43a8320e13b 100644 --- a/modules/hal_st/Kconfig +++ b/modules/hal_st/Kconfig @@ -96,6 +96,9 @@ config USE_STDC_LIS2DU12 config USE_STDC_LIS2DUX12 bool +config USE_STDC_LIS2DUXS12 + bool + config USE_STDC_LIS2DW12 bool diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index 51a7f26bb1d..2f8b412b366 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -1190,3 +1190,14 @@ test_i2c_hs400x: hs400x@a6 { compatible = "renesas,hs400x"; reg = <0xa6>; }; + +test_i2c_lis2duxs12: lis2duxs12@a7 { + compatible = "st,lis2duxs12"; + reg = <0xa7>; + int1-gpios = <&test_gpio 0 0>; + int2-gpios = <&test_gpio 0 0>; + range = ; + odr = ; + power-mode = ; + status = "okay"; +};