drivers/sensor: add support to LPS22DF pressure sensor

The LPS22DF is an ultracompact, piezoresistive, absolute pressure sensor
that functions as a digital output barometer. The LPS22DF provides lower
power consumption, achieving lower pressure noise than its predecessor.
This driver is based on stmemsc HAL i/f v2.3

https://www.st.com/en/datasheet/lps22df.pdf

Signed-off-by: Armando Visconti <armando.visconti@st.com>
This commit is contained in:
Armando Visconti 2023-08-28 16:15:41 +02:00 committed by Fabio Baltieri
commit f1f7e4712c
19 changed files with 909 additions and 1 deletions

View file

@ -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)

View file

@ -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"

View file

@ -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)

View file

@ -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

View file

@ -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 <zephyr/drivers/sensor.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/init.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/__assert.h>
#include <zephyr/logging/log.h>
#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)

View file

@ -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 <stdint.h>
#include <stmemsc.h>
#include "lps22df_reg.h"
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
#include <zephyr/drivers/spi.h>
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) */
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
#include <zephyr/drivers/i2c.h>
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
#include <zephyr/drivers/i3c.h>
#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_ */

View file

@ -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 <zephyr/kernel.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/logging/log.h>
#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);
}

View file

@ -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

View file

@ -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"]

View file

@ -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"]

View file

@ -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"]

View file

@ -115,6 +115,9 @@ config USE_STDC_LIS3DSH
config USE_STDC_LIS3MDL
bool
config USE_STDC_LPS22DF
bool
config USE_STDC_LPS22HB
bool

View file

@ -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"
};

View file

@ -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";
};

View file

@ -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>;
};

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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";
};