Commit 5be36eef authored by Armando Visconti's avatar Armando Visconti Committed by Carles Cufi
Browse files

drivers/sensor: lps2xdf: add ilps22qs support

The ILPS22QS is an ultra-compact piezoresistive absolute pressure sensor
which functions as a digital output barometer, supporting dual full-scale
up to user- selectable 4060 hPa. The device delivers ultra-low pressure
noise with very low power consumption and operates over an extended
temperature range from -40 °C to +105 °C.

(https://www.st.com/en/mems-and-sensors/ilps22qs.html)

Signed-off-by: default avatarArmando Visconti <armando.visconti@st.com>
parent 4c3606a3
Loading
Loading
Loading
Loading
+1 −0
Changes for drivers/sensor/st/lps2xdf/CMakeLists.txt: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
zephyr_library()

zephyr_library_sources(lps2xdf.c)
zephyr_library_sources_ifdef(CONFIG_DT_HAS_ST_ILPS22QS_ENABLED ilps22qs.c )
zephyr_library_sources_ifdef(CONFIG_DT_HAS_ST_LPS22DF_ENABLED  lps22df.c )
zephyr_library_sources_ifdef(CONFIG_DT_HAS_ST_LPS28DFW_ENABLED lps28dfw.c )
zephyr_library_sources_ifdef(CONFIG_LPS2XDF_TRIGGER            lps2xdf_trigger.c)
+7 −2
Changes for drivers/sensor/st/lps2xdf/Kconfig: 7 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -7,14 +7,19 @@
menuconfig LPS2XDF
	bool "LPS2xDF pressure and temperature"
	default y
	depends on DT_HAS_ST_LPS22DF_ENABLED || DT_HAS_ST_LPS28DFW_ENABLED
	depends on DT_HAS_ST_LPS22DF_ENABLED || DT_HAS_ST_LPS28DFW_ENABLED ||\
		   DT_HAS_ST_ILPS22QS_ENABLED
	depends on ZEPHYR_HAL_ST_MODULE
	select I2C if $(dt_compat_on_bus,$(DT_COMPAT_ST_LPS22DF),i2c) ||\
		      $(dt_compat_on_bus,$(DT_COMPAT_ST_ILPS22QS),i2c) ||\
		      $(dt_compat_on_bus,$(DT_COMPAT_ST_LPS28DFW),i2c)
	select I3C if $(dt_compat_on_bus,$(DT_COMPAT_ST_LPS22DF),i3c) ||\
		      $(dt_compat_on_bus,$(DT_COMPAT_ST_ILPS22QS),i3c) ||\
		      $(dt_compat_on_bus,$(DT_COMPAT_ST_LPS28DFW),i3c)
	select SPI if $(dt_compat_on_bus,$(DT_COMPAT_ST_LPS22DF),spi)
	select SPI if $(dt_compat_on_bus,$(DT_COMPAT_ST_LPS22DF),spi) ||\
		      $(dt_compat_on_bus,$(DT_COMPAT_ST_ILPS22QS),spi)
	select HAS_STMEMSC
	select USE_STDC_ILPS22QS if DT_HAS_ST_ILPS22QS_ENABLED
	select USE_STDC_LPS22DF if DT_HAS_ST_LPS22DF_ENABLED
	select USE_STDC_LPS28DFW if DT_HAS_ST_LPS28DFW_ENABLED
	help
+175 −0
Changes for drivers/sensor/st/lps2xdf/ilps22qs.c: 175 added lines, 0 removed lines.
Original line number Diff line number Diff line
/* ST Microelectronics ILPS22QS pressure and temperature sensor
 *
 * Copyright (c) 2023-2024 STMicroelectronics
 * Copyright (c) 2023 PHYTEC Messtechnik GmbH
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include "lps2xdf.h"
#include "ilps22qs.h"
#include <zephyr/logging/log.h>

LOG_MODULE_DECLARE(LPS2XDF, CONFIG_SENSOR_LOG_LEVEL);

static inline int ilps22qs_mode_set_odr_raw(const struct device *dev, uint8_t odr)
{
	const struct lps2xdf_config *const cfg = dev->config;
	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
	ilps22qs_md_t md = { 0 };

	md.odr = odr;
	md.avg = cfg->avg;
	md.lpf = cfg->lpf;
	md.fs = cfg->fs;

	return ilps22qs_mode_set(ctx, &md);
}

static int ilps22qs_sample_fetch(const struct device *dev, enum sensor_channel chan)
{
	struct lps2xdf_data *data = dev->data;
	const struct lps2xdf_config *const cfg = dev->config;
	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
	ilps22qs_data_t raw_data;
	ilps22qs_md_t md = { 0 };

	md.fs = cfg->fs;

	if (ilps22qs_data_get(ctx, &md, &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;
}

#ifdef CONFIG_LPS2XDF_TRIGGER
/**
 * ilps22qs_config_interrupt - not supported
 */
static int ilps22qs_config_interrupt(const struct device *dev)
{
	return -ENOTSUP;
}

/**
 * ilps22qs_handle_interrupt - not supported
 */
static void ilps22qs_handle_interrupt(const struct device *dev)
{
}

/**
 * ilps22qs_trigger_set - not supported
 */
static int ilps22qs_trigger_set(const struct device *dev,
				const struct sensor_trigger *trig,
				sensor_trigger_handler_t handler)
{
	return -ENOTSUP;
}
#endif /* CONFIG_LPS2XDF_TRIGGER */

const struct lps2xdf_chip_api st_ilps22qs_chip_api = {
	.mode_set_odr_raw = ilps22qs_mode_set_odr_raw,
	.sample_fetch = ilps22qs_sample_fetch,
#if CONFIG_LPS2XDF_TRIGGER
	.config_interrupt = ilps22qs_config_interrupt,
	.handle_interrupt = ilps22qs_handle_interrupt,
	.trigger_set = ilps22qs_trigger_set,
#endif
};

int st_ilps22qs_init(const struct device *dev)
{
	const struct lps2xdf_config *const cfg = dev->config;
	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
	ilps22qs_id_t id;
	ilps22qs_stat_t status;
	uint8_t tries = 10;
	int ret;

#if DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_ilps22qs, i3c)
	if (cfg->i3c.bus != NULL) {
		struct lps2xdf_data *data = dev->data;
		/*
		 * 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 (ilps22qs_id_get(ctx, &id) < 0) {
		LOG_ERR("%s: Not able to read dev id", dev->name);
		return -EIO;
	}

	if (id.whoami != ILPS22QS_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 (ilps22qs_init_set(ctx, ILPS22QS_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(LPS2XDF_SWRESET_WAIT_TIME_US);

		if (ilps22qs_status_get(ctx, &status) < 0) {
			return -EIO;
		}
	} while (status.sw_reset);

	/* Set bdu and if_inc recommended for driver usage */
	if (ilps22qs_init_set(ctx, ILPS22QS_DRV_RDY) < 0) {
		LOG_ERR("%s: Not able to set device to ready state", dev->name);
		return -EIO;
	}

	if (ON_I3C_BUS(cfg)) {
		ilps22qs_bus_mode_t bus_mode;

		/* Select bus interface */
		ilps22qs_bus_mode_get(ctx, &bus_mode);
		bus_mode.filter = ILPS22QS_AUTO;
		bus_mode.interface = ILPS22QS_SEL_BY_HW;
		ilps22qs_bus_mode_set(ctx, &bus_mode);
	}

	/* set sensor default odr */
	LOG_DBG("%s: odr: %d", dev->name, cfg->odr);
	ret = ilps22qs_mode_set_odr_raw(dev, cfg->odr);
	if (ret < 0) {
		LOG_ERR("%s: Failed to set odr %d", dev->name, cfg->odr);
		return ret;
	}

#ifdef CONFIG_LPS2XDF_TRIGGER
	if (cfg->trig_enabled) {
		if (lps2xdf_init_interrupt(dev, DEVICE_VARIANT_ILPS22QS) < 0) {
			LOG_ERR("Failed to initialize interrupt.");
			return -EIO;
		}
	}
#endif

	return 0;
}
+23 −0
Changes for drivers/sensor/st/lps2xdf/ilps22qs.h: 23 added lines, 0 removed lines.
Original line number Diff line number Diff line
/* ST Microelectronics ILPS22QS pressure and temperature sensor
 *
 * Copyright (c) 2023-2024 STMicroelectronics
 * Copyright (c) 2023 PHYTEC Messtechnik GmbH
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdint.h>
#include <stmemsc.h>

#include "ilps22qs_reg.h"

#include <zephyr/drivers/sensor.h>

#ifndef ZEPHYR_DRIVERS_SENSOR_ILPS22QS_ILPS22QS_H_
#define ZEPHYR_DRIVERS_SENSOR_ILPS22QS_ILPS22QS_H_

extern const struct lps2xdf_chip_api st_ilps22qs_chip_api;

int st_ilps22qs_init(const struct device *dev);

#endif /* ZEPHYR_DRIVERS_SENSOR_ILPS22QS_H_ */
+10 −1
Changes for drivers/sensor/st/lps2xdf/lps2xdf.c: 10 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
 * SPDX-License-Identifier: Apache-2.0
 *
 * Datasheet:
 * https://www.st.com/resource/en/datasheet/ilps22qs.pdf
 * https://www.st.com/resource/en/datasheet/lps22df.pdf
 * https://www.st.com/resource/en/datasheet/lps28df.pdf
 */
@@ -20,6 +21,10 @@

#include "lps2xdf.h"

#if DT_HAS_COMPAT_STATUS_OKAY(st_ilps22qs)
#include "ilps22qs.h"
#endif

#if DT_HAS_COMPAT_STATUS_OKAY(st_lps22df)
#include "lps22df.h"
#endif
@@ -159,7 +164,7 @@ static const struct sensor_driver_api lps2xdf_driver_api = {
	.lpf = DT_INST_PROP(inst, lpf),                                        \
	.avg = DT_INST_PROP(inst, avg),                                        \
	.chip_api = &name##_chip_api,                                          \
	IF_ENABLED(DT_INST_NODE_HAS_COMPAT(inst, st_lps28dfw),                 \
	IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, fs),                            \
		   (.fs = DT_INST_PROP(inst, fs),))                            \
	IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, drdy_gpios),                    \
		   (LPS2XDF_CFG_IRQ(inst)))
@@ -214,6 +219,10 @@ static const struct sensor_driver_api lps2xdf_driver_api = {
				     &lps2xdf_config_##name##_##inst, POST_KERNEL,           \
				     CONFIG_SENSOR_INIT_PRIORITY, &lps2xdf_driver_api);

#define DT_DRV_COMPAT st_ilps22qs
DT_INST_FOREACH_STATUS_OKAY_VARGS(LPS2XDF_DEFINE, DT_DRV_COMPAT)
#undef DT_DRV_COMPAT

#define DT_DRV_COMPAT st_lps22df
DT_INST_FOREACH_STATUS_OKAY_VARGS(LPS2XDF_DEFINE, DT_DRV_COMPAT)
#undef DT_DRV_COMPAT
Loading