diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index 8ac3da6c937..0bace9305b9 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -71,6 +71,7 @@ add_subdirectory_ifdef(CONFIG_LIS2MDL lis2mdl) add_subdirectory_ifdef(CONFIG_LIS3MDL lis3mdl) add_subdirectory_ifdef(CONFIG_LM75 lm75) add_subdirectory_ifdef(CONFIG_LM77 lm77) +add_subdirectory_ifdef(CONFIG_LPS22DF lps22df) add_subdirectory_ifdef(CONFIG_LPS22HB lps22hb) add_subdirectory_ifdef(CONFIG_LPS22HH lps22hh) add_subdirectory_ifdef(CONFIG_LPS25HB lps25hb) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 000c4bb1a35..e334617cf0b 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -144,6 +144,7 @@ source "drivers/sensor/lis2mdl/Kconfig" source "drivers/sensor/lis3mdl/Kconfig" source "drivers/sensor/lm75/Kconfig" source "drivers/sensor/lm77/Kconfig" +source "drivers/sensor/lps22df/Kconfig" source "drivers/sensor/lps22hb/Kconfig" source "drivers/sensor/lps22hh/Kconfig" source "drivers/sensor/lps25hb/Kconfig" diff --git a/drivers/sensor/lps22df/CMakeLists.txt b/drivers/sensor/lps22df/CMakeLists.txt new file mode 100644 index 00000000000..bb5194cf9ba --- /dev/null +++ b/drivers/sensor/lps22df/CMakeLists.txt @@ -0,0 +1,12 @@ +# ST Microelectronics LPS22DF pressure and temperature sensor +# +# Copyright (c) 2023 STMicroelectronics +# +# SPDX-License-Identifier: Apache-2.0 +# +zephyr_library() + +zephyr_library_sources(lps22df.c) +zephyr_library_sources_ifdef(CONFIG_LPS22DF_TRIGGER lps22df_trigger.c) + +zephyr_library_include_directories(../stmemsc) diff --git a/drivers/sensor/lps22df/Kconfig b/drivers/sensor/lps22df/Kconfig new file mode 100644 index 00000000000..843c6e755c4 --- /dev/null +++ b/drivers/sensor/lps22df/Kconfig @@ -0,0 +1,59 @@ +# ST Microelectronics LPS22DF pressure and temperature sensor + +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +menuconfig LPS22DF + bool "LPS22DF pressure and temperature" + default y + depends on DT_HAS_ST_LPS22DF_ENABLED + select I2C if $(dt_compat_on_bus,$(DT_COMPAT_ST_LPS22DF),i2c) + select I3C if $(dt_compat_on_bus,$(DT_COMPAT_ST_LPS22DF),i3c) + select SPI if $(dt_compat_on_bus,$(DT_COMPAT_ST_LPS22DF),spi) + select HAS_STMEMSC + select USE_STDC_LPS22DF + help + Enable driver for LPS22DF I2C-based pressure and temperature + sensor. + +if LPS22DF + +choice LPS22DF_TRIGGER_MODE + prompt "Trigger mode" + default LPS22DF_TRIGGER_GLOBAL_THREAD + help + Specify the type of triggering to be used by the driver. + +config LPS22DF_TRIGGER_NONE + bool "No trigger" + +config LPS22DF_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + depends on GPIO + select LPS22DF_TRIGGER + +config LPS22DF_TRIGGER_OWN_THREAD + bool "Use own thread" + depends on GPIO + select LPS22DF_TRIGGER + +endchoice # LPS22DF_TRIGGER_MODE + +config LPS22DF_TRIGGER + bool + +config LPS22DF_THREAD_PRIORITY + int "Thread priority" + depends on LPS22DF_TRIGGER_OWN_THREAD + default 10 + help + Priority of thread used by the driver to handle interrupts. + +config LPS22DF_THREAD_STACK_SIZE + int "Thread stack size" + depends on LPS22DF_TRIGGER_OWN_THREAD + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + +endif # LPS22DF diff --git a/drivers/sensor/lps22df/lps22df.c b/drivers/sensor/lps22df/lps22df.c new file mode 100644 index 00000000000..a74ef75c245 --- /dev/null +++ b/drivers/sensor/lps22df/lps22df.c @@ -0,0 +1,338 @@ +/* ST Microelectronics LPS22DF pressure and temperature sensor + * + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/lps22df.pdf + */ + +#define DT_DRV_COMPAT st_lps22df + +#include +#include +#include +#include +#include +#include +#include + +#include "lps22df.h" + +#define LPS22DF_SWRESET_WAIT_TIME 50 + +LOG_MODULE_REGISTER(LPS22DF, CONFIG_SENSOR_LOG_LEVEL); + +static inline int lps22df_set_odr_raw(const struct device *dev, uint8_t odr) +{ + const struct lps22df_config * const cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lps22df_md_t md; + + md.odr = odr; + md.avg = cfg->avg; + md.lpf = cfg->lpf; + + return lps22df_mode_set(ctx, &md); +} + +static int lps22df_sample_fetch(const struct device *dev, + enum sensor_channel chan) +{ + struct lps22df_data *data = dev->data; + const struct lps22df_config * const cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lps22df_data_t raw_data; + + __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL); + + if (lps22df_data_get(ctx, &raw_data) < 0) { + LOG_DBG("Failed to read sample"); + return -EIO; + } + + data->sample_press = raw_data.pressure.raw; + data->sample_temp = raw_data.heat.raw; + + return 0; +} + +static inline void lps22df_press_convert(struct sensor_value *val, + int32_t raw_val) +{ + int32_t press_tmp = raw_val >> 8; /* raw value is left aligned (24 msb) */ + + /* Pressure sensitivity is 4096 LSB/hPa */ + /* Also convert hPa into kPa */ + + val->val1 = press_tmp / 40960; + + /* For the decimal part use (3125 / 128) as a factor instead of + * (1000000 / 40960) to avoid int32 overflow + */ + val->val2 = (press_tmp % 40960) * 3125 / 128; +} + +static inline void lps22df_temp_convert(struct sensor_value *val, + int16_t raw_val) +{ + /* Temperature sensitivity is 100 LSB/deg C */ + val->val1 = raw_val / 100; + val->val2 = ((int32_t)raw_val % 100) * 10000; +} + +static int lps22df_channel_get(const struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct lps22df_data *data = dev->data; + + if (chan == SENSOR_CHAN_PRESS) { + lps22df_press_convert(val, data->sample_press); + } else if (chan == SENSOR_CHAN_AMBIENT_TEMP) { + lps22df_temp_convert(val, data->sample_temp); + } else { + return -ENOTSUP; + } + + return 0; +} + +static const uint16_t lps22df_map[] = {0, 1, 4, 10, 25, 50, 75, 100, 200}; + +static int lps22df_odr_set(const struct device *dev, uint16_t freq) +{ + int odr; + + for (odr = 0; odr < ARRAY_SIZE(lps22df_map); odr++) { + if (freq == lps22df_map[odr]) { + break; + } + } + + if (odr == ARRAY_SIZE(lps22df_map)) { + LOG_DBG("bad frequency"); + return -EINVAL; + } + + if (lps22df_set_odr_raw(dev, odr) < 0) { + LOG_DBG("failed to set sampling rate"); + return -EIO; + } + + return 0; +} + +static int lps22df_attr_set(const struct device *dev, + enum sensor_channel chan, + enum sensor_attribute attr, + const struct sensor_value *val) +{ + if (chan != SENSOR_CHAN_ALL) { + LOG_WRN("attr_set() not supported on this channel."); + return -ENOTSUP; + } + + switch (attr) { + case SENSOR_ATTR_SAMPLING_FREQUENCY: + return lps22df_odr_set(dev, val->val1); + default: + LOG_DBG("operation not supported."); + return -ENOTSUP; + } + + return 0; +} + +static const struct sensor_driver_api lps22df_driver_api = { + .attr_set = lps22df_attr_set, + .sample_fetch = lps22df_sample_fetch, + .channel_get = lps22df_channel_get, +#if CONFIG_LPS22DF_TRIGGER + .trigger_set = lps22df_trigger_set, +#endif +}; + +static int lps22df_init_chip(const struct device *dev) +{ + const struct lps22df_config * const cfg = dev->config; + __maybe_unused struct lps22df_data *data = dev->data; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lps22df_id_t id; + lps22df_stat_t status; + uint8_t tries = 10; + int ret; + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) + if (cfg->i3c.bus != NULL) { + /* + * Need to grab the pointer to the I3C device descriptor + * before we can talk to the sensor. + */ + data->i3c_dev = i3c_device_find(cfg->i3c.bus, &cfg->i3c.dev_id); + if (data->i3c_dev == NULL) { + LOG_ERR("Cannot find I3C device descriptor"); + return -ENODEV; + } + } +#endif + + if (lps22df_id_get(ctx, &id) < 0) { + LOG_ERR("%s: Not able to read dev id", dev->name); + return -EIO; + } + + if (id.whoami != LPS22DF_ID) { + LOG_ERR("%s: Invalid chip ID 0x%02x", dev->name, id.whoami); + return -EIO; + } + + LOG_DBG("%s: chip id 0x%x", dev->name, id.whoami); + + /* Restore default configuration */ + if (lps22df_init_set(ctx, LPS22DF_RESET) < 0) { + LOG_ERR("%s: Not able to reset device", dev->name); + return -EIO; + } + + do { + if (!--tries) { + LOG_DBG("sw reset timed out"); + return -ETIMEDOUT; + } + k_usleep(LPS22DF_SWRESET_WAIT_TIME); + + if (lps22df_status_get(ctx, &status) < 0) { + return -EIO; + } + } while (status.sw_reset); + + /* Set bdu and if_inc recommended for driver usage */ + if (lps22df_init_set(ctx, LPS22DF_DRV_RDY) < 0) { + LOG_ERR("%s: Not able to set device to ready state", dev->name); + return -EIO; + } + + if (ON_I3C_BUS(cfg)) { + lps22df_bus_mode_t bus_mode; + + /* Select bus interface */ + bus_mode.filter = LPS22DF_AUTO; + bus_mode.interface = LPS22DF_SEL_BY_HW; + lps22df_bus_mode_set(ctx, &bus_mode); + + } + + /* set sensor default odr */ + LOG_DBG("%s: odr: %d", dev->name, cfg->odr); + ret = lps22df_set_odr_raw(dev, cfg->odr); + if (ret < 0) { + LOG_ERR("%s: Failed to set odr %d", dev->name, cfg->odr); + return ret; + } + + return 0; +} + +static int lps22df_init(const struct device *dev) +{ + if (lps22df_init_chip(dev) < 0) { + LOG_DBG("Failed to initialize chip"); + return -EIO; + } + +#ifdef CONFIG_LPS22DF_TRIGGER + if (lps22df_init_interrupt(dev) < 0) { + LOG_ERR("Failed to initialize interrupt."); + return -EIO; + } +#endif + + return 0; +} + +/* + * Instantiation macros used when a device is on a SPI bus. + */ + +#ifdef CONFIG_LPS22DF_TRIGGER +#define LPS22DF_CFG_IRQ(inst) \ + .gpio_int = GPIO_DT_SPEC_INST_GET(inst, drdy_gpios), +#else +#define LPS22DF_CFG_IRQ(inst) +#endif /* CONFIG_LPS22DF_TRIGGER */ + +#define LPS22DF_CONFIG_COMMON(inst) \ + .odr = DT_INST_PROP(inst, odr), \ + .lpf = DT_INST_PROP(inst, lpf), \ + .avg = DT_INST_PROP(inst, avg), \ + .drdy_pulsed = DT_INST_PROP(inst, drdy_pulsed), \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, drdy_gpios), \ + (LPS22DF_CFG_IRQ(inst)), ()) + +#define LPS22DF_SPI_OPERATION (SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | \ + SPI_MODE_CPOL | SPI_MODE_CPHA) \ + +#define LPS22DF_CONFIG_SPI(inst) \ + { \ + STMEMSC_CTX_SPI(&lps22df_config_##inst.stmemsc_cfg), \ + .stmemsc_cfg = { \ + .spi = SPI_DT_SPEC_INST_GET(inst, \ + LPS22DF_SPI_OPERATION, \ + 0), \ + }, \ + LPS22DF_CONFIG_COMMON(inst) \ + } + +/* + * Instantiation macros used when a device is on an I2C bus. + */ + +#define LPS22DF_CONFIG_I2C(inst) \ + { \ + STMEMSC_CTX_I2C(&lps22df_config_##inst.stmemsc_cfg), \ + .stmemsc_cfg = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }, \ + LPS22DF_CONFIG_COMMON(inst) \ + } + +/* + * Instantiation macros used when a device is on an I#C bus. + */ + +#define LPS22DF_CONFIG_I3C(inst) \ + { \ + STMEMSC_CTX_I3C(&lps22df_config_##inst.stmemsc_cfg), \ + .stmemsc_cfg = { \ + .i3c = &lps22df_data_##inst.i3c_dev, \ + }, \ + .i3c.bus = DEVICE_DT_GET(DT_INST_BUS(inst)), \ + .i3c.dev_id = I3C_DEVICE_ID_DT_INST(inst), \ + LPS22DF_CONFIG_COMMON(inst) \ + } + +#define LPS22DF_CONFIG_I3C_OR_I2C(inst) \ + COND_CODE_0(DT_INST_PROP_BY_IDX(inst, reg, 1), \ + (LPS22DF_CONFIG_I2C(inst)), \ + (LPS22DF_CONFIG_I3C(inst))) + +/* + * Main instantiation macro. Use of COND_CODE_1() selects the right + * bus-specific macro at preprocessor time. + */ + +#define LPS22DF_DEFINE(inst) \ + static struct lps22df_data lps22df_data_##inst; \ + static const struct lps22df_config lps22df_config_##inst = \ + COND_CODE_1(DT_INST_ON_BUS(inst, spi), \ + (LPS22DF_CONFIG_SPI(inst)), \ + (COND_CODE_1(DT_INST_ON_BUS(inst, i3c), \ + (LPS22DF_CONFIG_I3C_OR_I2C(inst)), \ + (LPS22DF_CONFIG_I2C(inst))))); \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, lps22df_init, NULL, &lps22df_data_##inst, \ + &lps22df_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &lps22df_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(LPS22DF_DEFINE) diff --git a/drivers/sensor/lps22df/lps22df.h b/drivers/sensor/lps22df/lps22df.h new file mode 100644 index 00000000000..044c08cbd93 --- /dev/null +++ b/drivers/sensor/lps22df/lps22df.h @@ -0,0 +1,99 @@ +/* ST Microelectronics LPS22DF pressure and temperature sensor + * + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/lps22df.pdf + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_LPS22DF_LPS22DF_H_ +#define ZEPHYR_DRIVERS_SENSOR_LPS22DF_LPS22DF_H_ + +#include +#include +#include "lps22df_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) */ + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) +#include +#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) */ + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) + #define ON_I3C_BUS(cfg) (cfg->i3c.bus != NULL) +#else + #define ON_I3C_BUS(cfg) (false) +#endif + +struct lps22df_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 +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) + struct i3c_device_desc **i3c; +#endif + } stmemsc_cfg; + uint8_t odr; + uint8_t lpf; + uint8_t avg; + uint8_t drdy_pulsed; +#ifdef CONFIG_LPS22DF_TRIGGER + struct gpio_dt_spec gpio_int; +#endif + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) + struct { + const struct device *bus; + const struct i3c_device_id dev_id; + } i3c; +#endif +}; + +struct lps22df_data { + int32_t sample_press; + int16_t sample_temp; + +#ifdef CONFIG_LPS22DF_TRIGGER + struct gpio_callback gpio_cb; + + const struct sensor_trigger *data_ready_trigger; + sensor_trigger_handler_t handler_drdy; + const struct device *dev; + +#if defined(CONFIG_LPS22DF_TRIGGER_OWN_THREAD) + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_LPS22DF_THREAD_STACK_SIZE); + struct k_thread thread; + struct k_sem intr_sem; +#elif defined(CONFIG_LPS22DF_TRIGGER_GLOBAL_THREAD) + struct k_work work; +#endif + +#endif /* CONFIG_LPS22DF_TRIGGER */ + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) + struct i3c_device_desc *i3c_dev; +#endif +}; + +#ifdef CONFIG_LPS22DF_TRIGGER +int lps22df_trigger_set(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); + +int lps22df_init_interrupt(const struct device *dev); +#endif + +#endif /* ZEPHYR_DRIVERS_SENSOR_LPS22DF_LPS22DF_H_ */ diff --git a/drivers/sensor/lps22df/lps22df_trigger.c b/drivers/sensor/lps22df/lps22df_trigger.c new file mode 100644 index 00000000000..c5d6a91dba8 --- /dev/null +++ b/drivers/sensor/lps22df/lps22df_trigger.c @@ -0,0 +1,251 @@ +/* ST Microelectronics LPS22DF pressure and temperature sensor + * + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/lps22df.pdf + */ + +#define DT_DRV_COMPAT st_lps22df + +#include +#include +#include +#include + +#include "lps22df.h" + +LOG_MODULE_DECLARE(LPS22DF, CONFIG_SENSOR_LOG_LEVEL); + +/** + * lps22df_enable_int - enable selected int pin to generate interrupt + */ +static int lps22df_enable_int(const struct device *dev, int enable) +{ + const struct lps22df_config * const cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lps22df_pin_int_route_t int_route; + + /* set interrupt */ + lps22df_pin_int_route_get(ctx, &int_route); + int_route.drdy_pres = enable; + return lps22df_pin_int_route_set(ctx, &int_route); +} + +/** + * lps22df_trigger_set - link external trigger to event data ready + */ +int lps22df_trigger_set(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + struct lps22df_data *lps22df = dev->data; + const struct lps22df_config * const cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lps22df_data_t raw_data; + + if (trig->chan != SENSOR_CHAN_ALL) { + LOG_WRN("trigger set not supported on this channel."); + return -ENOTSUP; + } + + lps22df->handler_drdy = handler; + lps22df->data_ready_trigger = trig; + if (handler) { + /* dummy read: re-trigger interrupt */ + if (lps22df_data_get(ctx, &raw_data) < 0) { + LOG_DBG("Failed to read sample"); + return -EIO; + } + return lps22df_enable_int(dev, 1); + } else { + return lps22df_enable_int(dev, 0); + } + + return -ENOTSUP; +} + +/** + * lps22df_handle_interrupt - handle the drdy event + * read data and call handler if registered any + */ +static void lps22df_handle_interrupt(const struct device *dev) +{ + int ret; + struct lps22df_data *lps22df = dev->data; + const struct lps22df_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lps22df_all_sources_t status; + + if (lps22df_all_sources_get(ctx, &status) < 0) { + LOG_DBG("failed reading status reg"); + goto exit; + } + + if (status.drdy_pres == 0) { + goto exit; /* spurious interrupt */ + } + + if (lps22df->handler_drdy != NULL) { + lps22df->handler_drdy(dev, lps22df->data_ready_trigger); + } + + if (ON_I3C_BUS(cfg)) { + /* + * I3C IBI does not rely on GPIO. + * So no need to enable GPIO pin for interrupt trigger. + */ + return; + } + +exit: + 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); + } +} + +static void lps22df_intr_callback(struct lps22df_data *lps22df) +{ +#if defined(CONFIG_LPS22DF_TRIGGER_OWN_THREAD) + k_sem_give(&lps22df->intr_sem); +#elif defined(CONFIG_LPS22DF_TRIGGER_GLOBAL_THREAD) + k_work_submit(&lps22df->work); +#endif /* CONFIG_LPS22DF_TRIGGER_OWN_THREAD */ +} + +static void lps22df_gpio_callback(const struct device *dev, + struct gpio_callback *cb, uint32_t pins) +{ + struct lps22df_data *lps22df = + CONTAINER_OF(cb, struct lps22df_data, gpio_cb); + + ARG_UNUSED(pins); + const struct lps22df_config *cfg = lps22df->dev->config; + int ret; + + 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); + } + + lps22df_intr_callback(lps22df); +} + +#ifdef CONFIG_LPS22DF_TRIGGER_OWN_THREAD +static void lps22df_thread(struct lps22df_data *lps22df) +{ + while (1) { + k_sem_take(&lps22df->intr_sem, K_FOREVER); + lps22df_handle_interrupt(lps22df->dev); + } +} +#endif /* CONFIG_LPS22DF_TRIGGER_OWN_THREAD */ + +#ifdef CONFIG_LPS22DF_TRIGGER_GLOBAL_THREAD +static void lps22df_work_cb(struct k_work *work) +{ + struct lps22df_data *lps22df = + CONTAINER_OF(work, struct lps22df_data, work); + + lps22df_handle_interrupt(lps22df->dev); +} +#endif /* CONFIG_LPS22DF_TRIGGER_GLOBAL_THREAD */ + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) +static int lps22df_ibi_cb(struct i3c_device_desc *target, + struct i3c_ibi_payload *payload) +{ + const struct device *dev = target->dev; + struct lps22df_data *lps22df = dev->data; + + ARG_UNUSED(payload); + + lps22df_intr_callback(lps22df); + + return 0; +} +#endif + +int lps22df_init_interrupt(const struct device *dev) +{ + struct lps22df_data *lps22df = dev->data; + const struct lps22df_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lps22df_int_mode_t mode; + int ret; + + /* setup data ready gpio interrupt */ + if (!gpio_is_ready_dt(&cfg->gpio_int) && !ON_I3C_BUS(cfg)) { + 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; + } + + lps22df->dev = dev; + +#if defined(CONFIG_LPS22DF_TRIGGER_OWN_THREAD) + k_sem_init(&lps22df->intr_sem, 0, K_SEM_MAX_LIMIT); + + k_thread_create(&lps22df->thread, lps22df->thread_stack, + CONFIG_LPS22DF_THREAD_STACK_SIZE, + (k_thread_entry_t)lps22df_thread, lps22df, + NULL, NULL, K_PRIO_COOP(CONFIG_LPS22DF_THREAD_PRIORITY), + 0, K_NO_WAIT); +#elif defined(CONFIG_LPS22DF_TRIGGER_GLOBAL_THREAD) + lps22df->work.handler = lps22df_work_cb; +#endif /* CONFIG_LPS22DF_TRIGGER_OWN_THREAD */ + + if (!ON_I3C_BUS(cfg)) { + 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(&lps22df->gpio_cb, + lps22df_gpio_callback, + BIT(cfg->gpio_int.pin)); + + ret = gpio_add_callback(cfg->gpio_int.port, &lps22df->gpio_cb); + if (ret < 0) { + LOG_ERR("Could not set gpio callback"); + return ret; + } + } + + /* enable drdy in pulsed/latched mode */ + LOG_DBG("drdy_pulsed is %d", (int)cfg->drdy_pulsed); + mode.drdy_latched = ~cfg->drdy_pulsed; + if (lps22df_interrupt_mode_set(ctx, &mode) < 0) { + return -EIO; + } + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) + if (cfg->i3c.bus != NULL) { + /* I3C IBI does not utilize GPIO interrupt. */ + lps22df->i3c_dev->ibi_cb = lps22df_ibi_cb; + + if (i3c_ibi_enable(lps22df->i3c_dev) != 0) { + LOG_DBG("Could not enable I3C IBI"); + return -EIO; + } + + return 0; + } +#endif + + return gpio_pin_interrupt_configure_dt(&cfg->gpio_int, + GPIO_INT_EDGE_TO_ACTIVE); +} diff --git a/dts/bindings/sensor/st,lps22df-common.yaml b/dts/bindings/sensor/st,lps22df-common.yaml new file mode 100644 index 00000000000..7a1f21573b2 --- /dev/null +++ b/dts/bindings/sensor/st,lps22df-common.yaml @@ -0,0 +1,88 @@ +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +include: sensor-device.yaml + +properties: + drdy-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. + + drdy-pulsed: + type: boolean + description: | + Selects the pulsed mode for data-ready interrupt when enabled, + and the latched mode when disabled. + + odr: + type: int + default: 0 + description: | + Specify the output data rate expressed in samples per second (Hz). + The default is the power-on reset value. + + 0 = Power-Down + 1 = 1Hz + 2 = 4Hz + 3 = 10Hz + 4 = 25Hz + 5 = 50Hz + 6 = 75Hz + 7 = 100Hz + 8 = 200Hz + enum: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 + + lpf: + type: int + default: 0 + description: | + Specify the low pass filter value to be applied to pressure data. + The default is the power-on reset value. + + 0 = Low Pass Filter disabled + 1 = Low Pass Filter set to ODR/4 + 3 = Low Pass Filter set to ODR/9 + enum: + - 0 + - 1 + - 3 + + avg: + type: int + default: 0 + description: | + Specify the average filter value (i.e. number of samples) to be applied + to pressure and temperature data. + The default is the power-on reset value. + + 0 = Average of 4 data samples + 1 = Average of 8 data samples + 2 = Average of 16 data samples + 3 = Average of 32 data samples + 4 = Average of 64 data samples + 5 = Average of 128 data samples + 6 = Average of 256 data samples + 7 = Average of 512 data samples + enum: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 diff --git a/dts/bindings/sensor/st,lps22df-i2c.yaml b/dts/bindings/sensor/st,lps22df-i2c.yaml new file mode 100644 index 00000000000..11074528cf3 --- /dev/null +++ b/dts/bindings/sensor/st,lps22df-i2c.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STMicroelectronics LPS22DF pressure and temperature sensor connected to I2C + bus + +compatible: "st,lps22df" + +include: ["i2c-device.yaml", "st,lps22df-common.yaml"] diff --git a/dts/bindings/sensor/st,lps22df-i3c.yaml b/dts/bindings/sensor/st,lps22df-i3c.yaml new file mode 100644 index 00000000000..6bba397e0be --- /dev/null +++ b/dts/bindings/sensor/st,lps22df-i3c.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STMicroelectronics LPS22DF pressure and temperature sensor connected to I3C + bus + +compatible: "st,lps22df" + +include: ["i3c-device.yaml", "st,lps22df-common.yaml"] diff --git a/dts/bindings/sensor/st,lps22df-spi.yaml b/dts/bindings/sensor/st,lps22df-spi.yaml new file mode 100644 index 00000000000..219738d0e95 --- /dev/null +++ b/dts/bindings/sensor/st,lps22df-spi.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STMicroelectronics LPS22DF pressure and temperature sensor connected to SPI + bus + +compatible: "st,lps22df" + +include: ["spi-device.yaml", "st,lps22df-common.yaml"] diff --git a/modules/Kconfig.st b/modules/Kconfig.st index 2db03e18f77..fd90aee0b17 100644 --- a/modules/Kconfig.st +++ b/modules/Kconfig.st @@ -115,6 +115,9 @@ config USE_STDC_LIS3DSH config USE_STDC_LIS3MDL bool +config USE_STDC_LPS22DF + bool + config USE_STDC_LPS22HB bool diff --git a/tests/drivers/build_all/sensor/app.overlay b/tests/drivers/build_all/sensor/app.overlay index fb039a8ebac..9f7c604bf30 100644 --- a/tests/drivers/build_all/sensor/app.overlay +++ b/tests/drivers/build_all/sensor/app.overlay @@ -121,7 +121,8 @@ <&test_gpio 0 0>, <&test_gpio 0 0>, <&test_gpio 0 0>, /* 0x25 */ - <&test_gpio 0 0>; /* 0x26 */ + <&test_gpio 0 0>, /* 0x26 */ + <&test_gpio 0 0>; /* 0x27 */ #include "spi.dtsi" }; diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index eda5bff0ff7..42beeab095e 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -800,3 +800,10 @@ test_i2c_tsl2561: tsl2561@78 { compatible = "ams,tsl2561"; reg = <0x78>; }; + +test_i2c_lps22df: lps22df@78 { + compatible = "st,lps22df"; + reg = <0x78>; + drdy-gpios = <&test_gpio 0 0>; + status = "okay"; +}; diff --git a/tests/drivers/build_all/sensor/i3c.dtsi b/tests/drivers/build_all/sensor/i3c.dtsi index 005c21fdff2..42adb3fb175 100644 --- a/tests/drivers/build_all/sensor/i3c.dtsi +++ b/tests/drivers/build_all/sensor/i3c.dtsi @@ -16,3 +16,10 @@ test_i3c_lps22hh: lps22hh@100000803E0000001 { assigned-address = <0x1>; drdy-gpios = <&test_gpio 0 0>; }; + +test_i3c_lps22df: lps22df@200000803E0000002 { + compatible = "st,lps22df"; + reg = <0x2 0x00000803 0xE0000002>; + assigned-address = <0x2>; + drdy-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 74ba8f20239..c42b4fa951e 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_global.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_global.conf @@ -36,6 +36,7 @@ CONFIG_LIS2DS12_TRIGGER_GLOBAL_THREAD=y CONFIG_LIS2DW12_TRIGGER_GLOBAL_THREAD=y CONFIG_LIS2MDL_TRIGGER_GLOBAL_THREAD=y CONFIG_LIS3MDL_TRIGGER_GLOBAL_THREAD=y +CONFIG_LPS22DF_TRIGGER_GLOBAL_THREAD=y CONFIG_LPS22HH_TRIGGER_GLOBAL_THREAD=y CONFIG_LSM6DSL_TRIGGER_GLOBAL_THREAD=y CONFIG_LSM6DSO_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 905907928f5..9c46cb3637e 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_none.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_none.conf @@ -36,6 +36,7 @@ CONFIG_LIS2DS12_TRIGGER_NONE=y CONFIG_LIS2DW12_TRIGGER_NONE=y CONFIG_LIS2MDL_TRIGGER_NONE=y CONFIG_LIS3MDL_TRIGGER_NONE=y +CONFIG_LPS22DF_TRIGGER_NONE=y CONFIG_LPS22HH_TRIGGER_NONE=y CONFIG_LSM6DSL_TRIGGER_NONE=y CONFIG_LSM6DSO_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 92504b6c2f4..5ecacb03d9a 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_own.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_own.conf @@ -34,6 +34,7 @@ CONFIG_LIS2DS12_TRIGGER_OWN_THREAD=y CONFIG_LIS2DW12_TRIGGER_OWN_THREAD=y CONFIG_LIS2MDL_TRIGGER_OWN_THREAD=y CONFIG_LIS3MDL_TRIGGER_OWN_THREAD=y +CONFIG_LPS22DF_TRIGGER_OWN_THREAD=y CONFIG_LPS22HH_TRIGGER_OWN_THREAD=y CONFIG_LSM6DSL_TRIGGER_OWN_THREAD=y CONFIG_LSM6DSO_TRIGGER_OWN_THREAD=y diff --git a/tests/drivers/build_all/sensor/spi.dtsi b/tests/drivers/build_all/sensor/spi.dtsi index d026e244f88..cd7bf1b66ec 100644 --- a/tests/drivers/build_all/sensor/spi.dtsi +++ b/tests/drivers/build_all/sensor/spi.dtsi @@ -304,3 +304,11 @@ test_spi_adxl367: adxl367@26 { odr = <4>; int1-gpios = <&test_gpio 0 0>; }; + +test_spi_lps22df: lps22df@27 { + compatible = "st,lps22df"; + reg = <0x27>; + spi-max-frequency = <0>; + drdy-gpios = <&test_gpio 0 0>; + status = "okay"; +};