From a5c2331d814775d997677974ace66eb50e8f139e Mon Sep 17 00:00:00 2001 From: Wajdi ELMuhtadi Date: Fri, 1 Sep 2023 10:27:34 +0200 Subject: [PATCH 01/14] drivers: sensor: wsen_itds: remove wsen_itds driver Remove wsen_itds driver since the hal update is no longer compatible with this version. Signed-off-by: Wajdi ELMuhtadi --- drivers/sensor/wsen/CMakeLists.txt | 1 - drivers/sensor/wsen/Kconfig | 1 - drivers/sensor/wsen/wsen_itds/CMakeLists.txt | 6 - drivers/sensor/wsen/wsen_itds/Kconfig | 22 - drivers/sensor/wsen/wsen_itds/itds.c | 415 ------------------- drivers/sensor/wsen/wsen_itds/itds.h | 125 ------ drivers/sensor/wsen/wsen_itds/itds_trigger.c | 130 ------ dts/bindings/sensor/we,wsen-itds.yaml | 40 -- tests/drivers/build_all/sensor/i2c.dtsi | 8 - 9 files changed, 748 deletions(-) delete mode 100644 drivers/sensor/wsen/wsen_itds/CMakeLists.txt delete mode 100644 drivers/sensor/wsen/wsen_itds/Kconfig delete mode 100644 drivers/sensor/wsen/wsen_itds/itds.c delete mode 100644 drivers/sensor/wsen/wsen_itds/itds.h delete mode 100644 drivers/sensor/wsen/wsen_itds/itds_trigger.c delete mode 100644 dts/bindings/sensor/we,wsen-itds.yaml diff --git a/drivers/sensor/wsen/CMakeLists.txt b/drivers/sensor/wsen/CMakeLists.txt index 6be986250365..155ac77eeeb6 100644 --- a/drivers/sensor/wsen/CMakeLists.txt +++ b/drivers/sensor/wsen/CMakeLists.txt @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start -add_subdirectory_ifdef(CONFIG_ITDS wsen_itds) add_subdirectory_ifdef(CONFIG_WSEN_HIDS wsen_hids) add_subdirectory_ifdef(CONFIG_WSEN_PADS wsen_pads) add_subdirectory_ifdef(CONFIG_WSEN_PDUS wsen_pdus) diff --git a/drivers/sensor/wsen/Kconfig b/drivers/sensor/wsen/Kconfig index 4e96bd525887..664c8a31f1b7 100644 --- a/drivers/sensor/wsen/Kconfig +++ b/drivers/sensor/wsen/Kconfig @@ -3,7 +3,6 @@ # zephyr-keep-sorted-start source "drivers/sensor/wsen/wsen_hids/Kconfig" -source "drivers/sensor/wsen/wsen_itds/Kconfig" source "drivers/sensor/wsen/wsen_pads/Kconfig" source "drivers/sensor/wsen/wsen_pdus/Kconfig" source "drivers/sensor/wsen/wsen_tids/Kconfig" diff --git a/drivers/sensor/wsen/wsen_itds/CMakeLists.txt b/drivers/sensor/wsen/wsen_itds/CMakeLists.txt deleted file mode 100644 index c1466fc879b8..000000000000 --- a/drivers/sensor/wsen/wsen_itds/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library() - -zephyr_library_sources(itds.c) -zephyr_library_sources_ifdef(CONFIG_ITDS_TRIGGER itds_trigger.c) diff --git a/drivers/sensor/wsen/wsen_itds/Kconfig b/drivers/sensor/wsen/wsen_itds/Kconfig deleted file mode 100644 index 17493a4e6988..000000000000 --- a/drivers/sensor/wsen/wsen_itds/Kconfig +++ /dev/null @@ -1,22 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 -# -# Copyright (c) 2020 Linumiz - -config ITDS - bool "WSEN-ITDS 3-axis accel sensor" - default y - depends on DT_HAS_WE_WSEN_ITDS_ENABLED - select I2C - help - Enable Wurth Elektronik WSEN-ITDS 3-axis acceleration sensor - provides acceleration and die temperature measurement. - -if ITDS - -config ITDS_TRIGGER - bool "Trigger mode" - help - Set to enable trigger mode using gpio interrupt, interrupts are - configured to line INT0. - -endif # ITDS diff --git a/drivers/sensor/wsen/wsen_itds/itds.c b/drivers/sensor/wsen/wsen_itds/itds.c deleted file mode 100644 index 8c2120f79b7f..000000000000 --- a/drivers/sensor/wsen/wsen_itds/itds.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * Würth Elektronic WSEN-ITDS 3-axis accel sensor driver - * - * Copyright (c) 2020 Linumiz - * Author: Saravanan Sekar - */ - -#include -#include -#include -#include -#include -#include -#include "itds.h" - -#define DT_DRV_COMPAT we_wsen_itds -#define ITDS_TEMP_CONST 62500 - -LOG_MODULE_REGISTER(ITDS, CONFIG_SENSOR_LOG_LEVEL); - -static const struct itds_odr itds_odr_map[ITDS_ODR_MAX] = { - {0}, {1, 600}, {12, 500}, {25}, {50}, {100}, {200}, - {400}, {800}, {1600} -}; - -static const int16_t itds_sensitivity_scale[][ITDS_ACCL_RANGE_END] = { - {976, 1952, 3904, 7808}, - - /* high performance mode */ - {244, 488, 976, 1952} -}; - -static int itds_get_odr_for_index(const struct device *dev, - enum itds_odr_const idx, - uint16_t *freq, uint16_t *mfreq) -{ - struct itds_device_data *ddata = dev->data; - int start, end; - bool hp_mode; - - hp_mode = !!(ddata->op_mode & ITDS_OP_MODE_HIGH_PERF); - if (hp_mode) { - start = ITDS_ODR_12_5; - end = ITDS_ODR_1600; - } else { - start = ITDS_ODR_1_6; - end = ITDS_ODR_200; - } - - if (idx < start || idx > end) { - LOG_ERR("invalid odr for the operating mode"); - return -EINVAL; - } - - *freq = itds_odr_map[idx].freq; - *mfreq = itds_odr_map[idx].mfreq; - - return 0; -} - -static int itds_accl_odr_set(const struct device *dev, uint16_t freq, - uint16_t mfreq) -{ - struct itds_device_data *ddata = dev->data; - const struct itds_device_config *cfg = dev->config; - int start, end, i; - bool hp_mode; - - hp_mode = !!(ddata->op_mode & ITDS_OP_MODE_HIGH_PERF); - if (hp_mode) { - start = ITDS_ODR_12_5; - end = ITDS_ODR_1600; - } else { - start = ITDS_ODR_1_6; - end = ITDS_ODR_200; - } - - for (i = start; i <= end; i++) { - if ((freq == itds_odr_map[i].freq) && - (mfreq == itds_odr_map[i].mfreq)) { - - return i2c_reg_update_byte_dt(&cfg->i2c, - ITDS_REG_CTRL1, ITDS_MASK_ODR, i << 4); - } - } - - LOG_ERR("invalid odr, not in range"); - return -EINVAL; -} - -static int itds_accl_range_set(const struct device *dev, int32_t range) -{ - struct itds_device_data *ddata = dev->data; - const struct itds_device_config *cfg = dev->config; - int i, ret; - bool hp_mode; - - for (i = 0; i < ITDS_ACCL_RANGE_END; i++) { - if (range <= (2 << i)) { - break; - } - } - - if (i == ITDS_ACCL_RANGE_END) { - LOG_ERR("Accl out of range"); - return -EINVAL; - } - - ret = i2c_reg_update_byte_dt(&cfg->i2c, ITDS_REG_CTRL6, - ITDS_MASK_SCALE, i << 4); - if (ret) { - LOG_ERR("Accl set full scale failed %d", ret); - return ret; - } - - hp_mode = !!(ddata->op_mode & ITDS_OP_MODE_HIGH_PERF); - ddata->scale = itds_sensitivity_scale[hp_mode][i]; - - return 0; -} - -static int itds_attr_set(const struct device *dev, enum sensor_channel chan, - enum sensor_attribute attr, - const struct sensor_value *val) -{ - if (chan != SENSOR_CHAN_ACCEL_X && - chan != SENSOR_CHAN_ACCEL_Y && - chan != SENSOR_CHAN_ACCEL_Z && - chan != SENSOR_CHAN_ACCEL_XYZ) { - LOG_ERR("attr_set() not supported on this channel."); - return -ENOTSUP; - } - - switch (attr) { - case SENSOR_ATTR_FULL_SCALE: - return itds_accl_range_set(dev, sensor_ms2_to_g(val)); - - case SENSOR_ATTR_SAMPLING_FREQUENCY: - return itds_accl_odr_set(dev, val->val1, val->val2 / 1000); - - default: - LOG_ERR("Accel attribute not supported."); - return -ENOTSUP; - } -} - -static int itds_fetch_temperature(struct itds_device_data *ddata, - const struct itds_device_config *cfg) -{ - uint8_t rval; - int16_t temp_raw = 0; - int ret; - - ret = i2c_reg_read_byte_dt(&cfg->i2c, - ITDS_REG_STATUS_DETECT, &rval); - if (ret) { - return ret; - } - - if (!(rval & ITDS_EVENT_DRDY_T)) { - return -EAGAIN; - } - - ret = i2c_burst_read_dt(&cfg->i2c, ITDS_REG_TEMP_L, - (uint8_t *)&temp_raw, sizeof(uint16_t)); - if (ret) { - return ret; - } - - ddata->temperature = sys_le16_to_cpu(temp_raw); - - return 0; -} - -static int itds_fetch_accel(struct itds_device_data *ddata, - const struct itds_device_config *cfg) -{ - size_t i, ret; - uint8_t rval; - - ret = i2c_reg_read_byte_dt(&cfg->i2c, - ITDS_REG_STATUS, &rval); - if (ret) { - return ret; - } - - if (!(rval & ITDS_EVENT_DRDY)) { - return -EAGAIN; - } - - ret = i2c_burst_read_dt(&cfg->i2c, ITDS_REG_X_OUT_L, - (uint8_t *)ddata->samples, - sizeof(uint16_t) * ITDS_SAMPLE_SIZE); - if (ret) { - return ret; - } - - /* convert samples to cpu endianness */ - for (i = 0; i < ITDS_SAMPLE_SIZE; i += 2) { - int16_t *sample = (int16_t *) &ddata->samples[i]; - - *sample = sys_le16_to_cpu(*sample); - if (ddata->op_mode & ITDS_OP_MODE_NORMAL || - ddata->op_mode & ITDS_OP_MODE_HIGH_PERF) { - *sample = *sample >> 2; - } else { - *sample = *sample >> 4; - } - LOG_DBG("itds sample %d %X\n", i, *sample); - } - - return 0; -} - -static int itds_sample_fetch(const struct device *dev, - enum sensor_channel chan) -{ - struct itds_device_data *ddata = dev->data; - const struct itds_device_config *cfg = dev->config; - - switch (chan) { - case SENSOR_CHAN_ACCEL_XYZ: - case SENSOR_CHAN_ACCEL_X: - case SENSOR_CHAN_ACCEL_Y: - case SENSOR_CHAN_ACCEL_Z: - return itds_fetch_accel(ddata, cfg); - - case SENSOR_CHAN_DIE_TEMP: - return itds_fetch_temperature(ddata, cfg); - - case SENSOR_CHAN_ALL: - return itds_fetch_accel(ddata, cfg) || - itds_fetch_temperature(ddata, cfg); - - default: - return -EINVAL; - } -} - -static inline void itds_accl_channel_get(const struct device *dev, - enum sensor_channel chan, - struct sensor_value *val) -{ - int i; - struct itds_device_data *ddata = dev->data; - uint8_t ofs_start, ofs_stop; - - switch (chan) { - case SENSOR_CHAN_ACCEL_X: - ofs_start = ofs_stop = 0U; - break; - case SENSOR_CHAN_ACCEL_Y: - ofs_start = ofs_stop = 1U; - break; - case SENSOR_CHAN_ACCEL_Z: - ofs_start = ofs_stop = 2U; - break; - default: - ofs_start = 0U; ofs_stop = 2U; - break; - } - - for (i = ofs_start; i <= ofs_stop ; i++, val++) { - int64_t dval; - - /* Sensitivity is exposed in ug/LSB */ - /* Convert to m/s^2 */ - dval = (int64_t)((ddata->samples[i] * ddata->scale * SENSOR_G) / - 1000000LL); - val->val1 = (int32_t)(dval / 1000000); - val->val2 = (int32_t)(dval % 1000000); - } -} - -static int itds_temp_channel_get(const struct device *dev, - struct sensor_value *val) -{ - int32_t temp_processed; - struct itds_device_data *ddata = dev->data; - - temp_processed = (ddata->temperature >> 4) * ITDS_TEMP_CONST; - - val->val1 = ITDS_TEMP_OFFSET; - val->val2 = temp_processed; - - return 0; -} - -static int itds_channel_get(const struct device *dev, - enum sensor_channel chan, - struct sensor_value *val) -{ - switch (chan) { - case SENSOR_CHAN_ACCEL_X: - case SENSOR_CHAN_ACCEL_Y: - case SENSOR_CHAN_ACCEL_Z: - case SENSOR_CHAN_ACCEL_XYZ: - itds_accl_channel_get(dev, chan, val); - return 0; - - case SENSOR_CHAN_DIE_TEMP: - return itds_temp_channel_get(dev, val); - - default: - LOG_ERR("Channel not supported."); - return -ENOTSUP; - } - - return 0; -} - -static int itds_init(const struct device *dev) -{ - struct itds_device_data *ddata = dev->data; - const struct itds_device_config *cfg = dev->config; - int ret; - uint16_t freq, mfreq; - uint8_t rval; - - if (!device_is_ready(cfg->i2c.bus)) { - LOG_ERR("Bus device is not ready"); - return -ENODEV; - } - - ret = i2c_reg_read_byte_dt(&cfg->i2c, - ITDS_REG_DEV_ID, &rval); - if (ret) { - LOG_ERR("device init fail: %d", ret); - return ret; - } - - if (rval != ITDS_DEVICE_ID) { - LOG_ERR("device ID mismatch: %x", rval); - return -EIO; - } - - ret = i2c_reg_update_byte_dt(&cfg->i2c, ITDS_REG_CTRL2, - ITDS_MASK_BDU_INC_ADD, ITDS_MASK_BDU_INC_ADD); - if (ret) { - LOG_ERR("unable to set block data update %d", ret); - return ret; - } - - ret = i2c_reg_write_byte_dt(&cfg->i2c, ITDS_REG_WAKEUP_EVENT, 0); - if (ret) { - LOG_ERR("disable wakeup event fail %d", ret); - return ret; - } - - ret = i2c_reg_update_byte_dt(&cfg->i2c, ITDS_REG_CTRL1, - ITDS_MASK_MODE, 1 << cfg->def_op_mode); - if (ret) { - LOG_ERR("set operating mode fail %d", ret); - return ret; - } - - ddata->op_mode = 1 << cfg->def_op_mode; - - ret = itds_get_odr_for_index(dev, cfg->def_odr, &freq, &mfreq); - if (ret) { - LOG_ERR("odr not in range for operating mode %d", ret); - return ret; - } - - ret = itds_accl_odr_set(dev, freq, mfreq); - if (ret) { - LOG_ERR("odr not in range for operating mode %d", ret); - return ret; - } - -#ifdef CONFIG_ITDS_TRIGGER - ret = itds_trigger_mode_init(dev); - if (ret) { - LOG_ERR("trigger mode init failed %d", ret); - return ret; - } -#endif - return 0; -} - -static const struct sensor_driver_api itds_api = { - .attr_set = itds_attr_set, -#ifdef CONFIG_ITDS_TRIGGER - .trigger_set = itds_trigger_set, -#endif - .sample_fetch = itds_sample_fetch, - .channel_get = itds_channel_get, -}; - -#ifdef CONFIG_ITDS_TRIGGER -#define WSEN_ITDS_CFG_IRQ(inst) \ - .int_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, { 0 }), -#else -#define WSEN_ITDS_CFG_IRQ(inst) -#endif - -#define WSEN_ITDS_INIT(idx) \ - \ -static struct itds_device_data itds_data_##idx; \ - \ -static const struct itds_device_config itds_config_##idx = { \ - .i2c = I2C_DT_SPEC_INST_GET(idx), \ - .def_odr = DT_INST_ENUM_IDX(idx, odr), \ - .def_op_mode = DT_INST_ENUM_IDX(idx, op_mode), \ - WSEN_ITDS_CFG_IRQ(idx) \ -}; \ - \ -SENSOR_DEVICE_DT_INST_DEFINE(idx, itds_init, NULL, \ - &itds_data_##idx, &itds_config_##idx, \ - POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ - &itds_api); \ - -DT_INST_FOREACH_STATUS_OKAY(WSEN_ITDS_INIT) diff --git a/drivers/sensor/wsen/wsen_itds/itds.h b/drivers/sensor/wsen/wsen_itds/itds.h deleted file mode 100644 index b37bed384c84..000000000000 --- a/drivers/sensor/wsen/wsen_itds/itds.h +++ /dev/null @@ -1,125 +0,0 @@ -/* Würth Elektronic WSEN-ITDS 3-axis Accel sensor driver - * - * Copyright (c) 2020 Linumiz - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_DRIVERS_SENSOR_ITDS_H_ -#define ZEPHYR_DRIVERS_SENSOR_ITDS_H_ - -#include -#include -#include - -/* registers */ -#define ITDS_REG_TEMP_L 0x0d -#define ITDS_REG_DEV_ID 0x0f -#define ITDS_REG_CTRL1 0x20 -#define ITDS_REG_CTRL2 0x21 -#define ITDS_REG_CTRL3 0x22 -#define ITDS_REG_CTRL4 0x23 -#define ITDS_REG_CTRL5 0x24 -#define ITDS_REG_CTRL6 0x25 -#define ITDS_REG_STATUS 0x27 -#define ITDS_REG_X_OUT_L 0x28 -#define ITDS_REG_Y_OUT_L 0x2a -#define ITDS_REG_Z_OUT_L 0x2c -#define ITDS_REG_FIFO_CTRL 0x2e -#define ITDS_REG_FIFO_SAMPLES 0x2f -#define ITDS_REG_STATUS_DETECT 0x37 -#define ITDS_REG_WAKEUP_EVENT 0x38 -#define ITDS_REG_CTRL7 0x3f - -/* bitfields */ -#define ITDS_MASK_SCALE GENMASK(5, 4) -#define ITDS_MASK_BDU_INC_ADD GENMASK(3, 2) -#define ITDS_MASK_FIFOTH GENMASK(4, 0) -#define ITDS_MASK_FIFOMODE GENMASK(7, 5) -#define ITDS_MASK_MODE GENMASK(3, 0) -#define ITDS_MASK_SAMPLES_COUNT GENMASK(5, 0) -#define ITDS_MASK_ODR GENMASK(7, 4) -#define ITDS_MASK_INT_DRDY BIT(0) -#define ITDS_MASK_INT_FIFOTH BIT(1) -#define ITDS_MASK_INT_EN BIT(5) - -#define ITDS_EVENT_DRDY BIT(0) -#define ITDS_EVENT_DRDY_T BIT(6) -#define ITDS_EVENT_FIFO_TH BIT(7) -#define ITDS_FIFO_MODE_BYPASS 0 -#define ITDS_FIFO_MODE_FIFO BIT(5) -#define ITDS_DEVICE_ID 0x44 -#define ITDS_ACCL_FIFO_SIZE 32 -#define ITDS_TEMP_OFFSET 25 - -enum operation_mode { - ITDS_OP_MODE_LOW_POWER = BIT(0), - ITDS_OP_MODE_NORMAL = BIT(1), - ITDS_OP_MODE_HIGH_PERF = BIT(2), -}; - -enum itds_accel_range_const { - ITDS_ACCL_RANGE_2G, - ITDS_ACCL_RANGE_4G, - ITDS_ACCL_RANGE_8G, - ITDS_ACCL_RANGE_16G, - ITDS_ACCL_RANGE_END -}; - -enum itds_odr_const { - ITDS_ODR_0, - ITDS_ODR_1_6, - ITDS_ODR_12_5, - ITDS_ODR_25, - ITDS_ODR_50, - ITDS_ODR_100, - ITDS_ODR_200, - ITDS_ODR_400, - ITDS_ODR_800, - ITDS_ODR_1600, - ITDS_ODR_MAX -}; - -struct itds_odr { - uint16_t freq; - uint16_t mfreq; -}; - -struct itds_accel_range { - uint16_t range; - uint8_t reg_val; -}; - -struct itds_device_config { - struct i2c_dt_spec i2c; -#ifdef CONFIG_ITDS_TRIGGER - struct gpio_dt_spec int_gpio; -#endif - int def_odr; - int def_op_mode; -}; - -#define ITDS_SAMPLE_SIZE 3 -struct itds_device_data { -#ifdef CONFIG_ITDS_TRIGGER - struct gpio_callback gpio_cb; - struct k_work work; -#endif - int16_t samples[ITDS_SAMPLE_SIZE]; - int16_t temperature; - int16_t scale; - enum operation_mode op_mode; - const struct device *dev; - -#ifdef CONFIG_ITDS_TRIGGER - sensor_trigger_handler_t handler_drdy; - const struct sensor_trigger *trigger_drdy; -#endif /* CONFIG_ITDS_TRIGGER */ -}; - -int itds_trigger_mode_init(const struct device *dev); -int itds_trigger_set(const struct device *dev, - const struct sensor_trigger *trig, - sensor_trigger_handler_t handler); - -#endif /* ZEPHYR_DRIVERS_SENSOR_ITDS_H_*/ diff --git a/drivers/sensor/wsen/wsen_itds/itds_trigger.c b/drivers/sensor/wsen/wsen_itds/itds_trigger.c deleted file mode 100644 index afbf55d8b864..000000000000 --- a/drivers/sensor/wsen/wsen_itds/itds_trigger.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * Würth Elektronic WSEN-ITDS 3-axis accel sensor driver - * - * Copyright (c) 2020 Linumiz - * Author: Saravanan Sekar - */ - -#include -#include -#include -#include - -#include "itds.h" -LOG_MODULE_DECLARE(ITDS, CONFIG_SENSOR_LOG_LEVEL); - -static int itds_trigger_drdy_set(const struct device *dev, - enum sensor_channel chan, - const struct sensor_trigger *trig, - sensor_trigger_handler_t handler) -{ - struct itds_device_data *ddata = dev->data; - const struct itds_device_config *cfg = dev->config; - uint8_t drdy_en = 0U; - int ret; - - ddata->handler_drdy = handler; - ddata->trigger_drdy = trig; - if (ddata->handler_drdy) { - drdy_en = ITDS_MASK_INT_DRDY; - } - - ret = i2c_reg_update_byte_dt(&cfg->i2c, ITDS_REG_CTRL4, - ITDS_MASK_INT_DRDY, drdy_en); - if (ret) { - return ret; - } - - return 0; -} - -int itds_trigger_set(const struct device *dev, - const struct sensor_trigger *trig, - sensor_trigger_handler_t handler) -{ - const struct itds_device_config *cfg = dev->config; - - if (!cfg->int_gpio.port) { - return -ENOTSUP; - } - - if (trig->chan != SENSOR_CHAN_ACCEL_XYZ) { - return -ENOTSUP; - } - - switch (trig->type) { - case SENSOR_TRIG_DATA_READY: - return itds_trigger_drdy_set(dev, trig->chan, trig, handler); - - default: - return -ENOTSUP; - } -} - -static void itds_work_handler(struct k_work *work) -{ - struct itds_device_data *ddata = - CONTAINER_OF(work, struct itds_device_data, work); - const struct device *dev = (const struct device *)ddata->dev; - const struct itds_device_config *cfg = dev->config; - uint8_t status; - - if (i2c_reg_read_byte_dt(&cfg->i2c, ITDS_REG_STATUS, - &status) < 0) { - return; - } - - if (status & ITDS_EVENT_DRDY) { - if (ddata->handler_drdy) { - ddata->handler_drdy(dev, ddata->trigger_drdy); - } - } -} - -static void itds_gpio_callback(const struct device *port, - struct gpio_callback *cb, uint32_t pin) -{ - struct itds_device_data *ddata = - CONTAINER_OF(cb, struct itds_device_data, gpio_cb); - - ARG_UNUSED(port); - ARG_UNUSED(pin); - - k_work_submit(&ddata->work); -} - -int itds_trigger_mode_init(const struct device *dev) -{ - struct itds_device_data *ddata = dev->data; - const struct itds_device_config *cfg = dev->config; - - /* dts doesn't have GPIO int pin set, so we dont support - * trigger mode for this instance - */ - if (!cfg->int_gpio.port) { - return 0; - } - - if (!gpio_is_ready_dt(&cfg->int_gpio)) { - LOG_ERR("%s: device %s is not ready", dev->name, - cfg->int_gpio.port->name); - return -ENODEV; - } - - ddata->work.handler = itds_work_handler; - ddata->dev = dev; - - gpio_pin_configure_dt(&cfg->int_gpio, GPIO_INPUT); - - gpio_init_callback(&ddata->gpio_cb, itds_gpio_callback, - BIT(cfg->int_gpio.pin)); - - gpio_add_callback(cfg->int_gpio.port, &ddata->gpio_cb); - gpio_pin_interrupt_configure_dt(&cfg->int_gpio, GPIO_INT_EDGE_TO_ACTIVE); - - /* enable global interrupt */ - return i2c_reg_update_byte_dt(&cfg->i2c, ITDS_REG_CTRL7, - ITDS_MASK_INT_EN, ITDS_MASK_INT_EN); -} diff --git a/dts/bindings/sensor/we,wsen-itds.yaml b/dts/bindings/sensor/we,wsen-itds.yaml deleted file mode 100644 index 5f73ed018678..000000000000 --- a/dts/bindings/sensor/we,wsen-itds.yaml +++ /dev/null @@ -1,40 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 -# Copyright (c) 2020 Linumiz - -description: WSEN-ITDS 3-axis accel sensor - -compatible: "we,wsen-itds" - -include: [sensor-device.yaml, i2c-device.yaml] - -properties: - int-gpios: - type: phandle-array - description: | - This property specifies the connection for INT0, the driver maps - all interrupts to INT0 as default. The signal to output high when - data produced by the sensor. - - odr: - type: string - required: true - description: Output data rate in Hz - enum: - - "1.6" - - "12.5" - - "25" - - "50" - - "100" - - "200" - - "400" - - "800" - - "1600" - - op-mode: - type: string - required: true - description: Operating mode of sensor - enum: - - "low-power" - - "normal" - - "high-perf" diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index 3494540d7883..0b33109eb013 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -521,14 +521,6 @@ test_i2c_wsen_hids: wsen_hids@4d { odr = "1"; }; -test_i2c_itds: itds@4e { - compatible = "we,wsen-itds"; - reg = <0x4e>; - int-gpios = <&test_gpio 0 0>; - odr = "800"; - op-mode = "high-perf"; -}; - test_i2c_max17055: max17055@4f { compatible = "maxim,max17055"; reg = <0x4f>; From d087179220cbd5ddbf8eb2b371b8d532a62c1e91 Mon Sep 17 00:00:00 2001 From: Wajdi ELMuhtadi Date: Fri, 1 Sep 2023 10:30:54 +0200 Subject: [PATCH 02/14] drivers: sensor: wsen_hids: remove wsen_hids driver Remove wsen_hids since the hal update is no longer compatible with this version. Signed-off-by: Wajdi ELMuhtadi --- drivers/sensor/wsen/CMakeLists.txt | 1 - drivers/sensor/wsen/Kconfig | 1 - drivers/sensor/wsen/wsen_hids/CMakeLists.txt | 7 - drivers/sensor/wsen/wsen_hids/Kconfig | 55 ---- drivers/sensor/wsen/wsen_hids/wsen_hids.c | 279 ------------------ drivers/sensor/wsen/wsen_hids/wsen_hids.h | 81 ----- .../sensor/wsen/wsen_hids/wsen_hids_trigger.c | 168 ----------- dts/bindings/sensor/we,wsen-hids-common.yaml | 22 -- dts/bindings/sensor/we,wsen-hids-i2c.yaml | 9 - dts/bindings/sensor/we,wsen-hids-spi.yaml | 9 - tests/drivers/build_all/sensor/i2c.dtsi | 7 - .../sensor/sensors_trigger_global.conf | 1 - .../sensor/sensors_trigger_none.conf | 1 - .../build_all/sensor/sensors_trigger_own.conf | 1 - 14 files changed, 642 deletions(-) delete mode 100644 drivers/sensor/wsen/wsen_hids/CMakeLists.txt delete mode 100644 drivers/sensor/wsen/wsen_hids/Kconfig delete mode 100644 drivers/sensor/wsen/wsen_hids/wsen_hids.c delete mode 100644 drivers/sensor/wsen/wsen_hids/wsen_hids.h delete mode 100644 drivers/sensor/wsen/wsen_hids/wsen_hids_trigger.c delete mode 100644 dts/bindings/sensor/we,wsen-hids-common.yaml delete mode 100644 dts/bindings/sensor/we,wsen-hids-i2c.yaml delete mode 100644 dts/bindings/sensor/we,wsen-hids-spi.yaml diff --git a/drivers/sensor/wsen/CMakeLists.txt b/drivers/sensor/wsen/CMakeLists.txt index 155ac77eeeb6..e3ce57897393 100644 --- a/drivers/sensor/wsen/CMakeLists.txt +++ b/drivers/sensor/wsen/CMakeLists.txt @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start -add_subdirectory_ifdef(CONFIG_WSEN_HIDS wsen_hids) add_subdirectory_ifdef(CONFIG_WSEN_PADS wsen_pads) add_subdirectory_ifdef(CONFIG_WSEN_PDUS wsen_pdus) add_subdirectory_ifdef(CONFIG_WSEN_TIDS wsen_tids) diff --git a/drivers/sensor/wsen/Kconfig b/drivers/sensor/wsen/Kconfig index 664c8a31f1b7..a8b4fd6ddeb1 100644 --- a/drivers/sensor/wsen/Kconfig +++ b/drivers/sensor/wsen/Kconfig @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start -source "drivers/sensor/wsen/wsen_hids/Kconfig" source "drivers/sensor/wsen/wsen_pads/Kconfig" source "drivers/sensor/wsen/wsen_pdus/Kconfig" source "drivers/sensor/wsen/wsen_tids/Kconfig" diff --git a/drivers/sensor/wsen/wsen_hids/CMakeLists.txt b/drivers/sensor/wsen/wsen_hids/CMakeLists.txt deleted file mode 100644 index 8c172aed581e..000000000000 --- a/drivers/sensor/wsen/wsen_hids/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library() - -zephyr_library_sources(wsen_hids.c) -zephyr_library_sources_ifdef(CONFIG_WSEN_HIDS_TRIGGER wsen_hids_trigger.c) diff --git a/drivers/sensor/wsen/wsen_hids/Kconfig b/drivers/sensor/wsen/wsen_hids/Kconfig deleted file mode 100644 index 0e7d4f8e6d55..000000000000 --- a/drivers/sensor/wsen/wsen_hids/Kconfig +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG -# SPDX-License-Identifier: Apache-2.0 - -menuconfig WSEN_HIDS - bool "WSEN-HIDS humidity and temperature sensor" - default y - depends on DT_HAS_WE_WSEN_HIDS_ENABLED - select I2C if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_HIDS),i2c) - select SPI if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_HIDS),spi) - select HAS_WESENSORS - help - Enable driver for the WSEN-HIDS I2C/SPI-based humidity sensor with integrated - temperature sensor. - -if WSEN_HIDS - -choice WSEN_HIDS_TRIGGER_MODE - prompt "Trigger mode" - default WSEN_HIDS_TRIGGER_NONE - help - Specify the type of triggering to be used by the driver. - -config WSEN_HIDS_TRIGGER_NONE - bool "No trigger" - -config WSEN_HIDS_TRIGGER_GLOBAL_THREAD - bool "Use global thread" - depends on GPIO - select WSEN_HIDS_TRIGGER - -config WSEN_HIDS_TRIGGER_OWN_THREAD - bool "Use own thread" - depends on GPIO - select WSEN_HIDS_TRIGGER - -endchoice # WSEN_HIDS_TRIGGER_MODE - -config WSEN_HIDS_TRIGGER - bool - -config WSEN_HIDS_THREAD_PRIORITY - int "Thread priority" - depends on WSEN_HIDS_TRIGGER_OWN_THREAD - default 10 - help - Priority of thread used by the driver to handle interrupts. - -config WSEN_HIDS_THREAD_STACK_SIZE - int "Thread stack size" - depends on WSEN_HIDS_TRIGGER_OWN_THREAD - default 1024 - help - Stack size of thread used by the driver to handle interrupts. - -endif # WSEN_HIDS diff --git a/drivers/sensor/wsen/wsen_hids/wsen_hids.c b/drivers/sensor/wsen/wsen_hids/wsen_hids.c deleted file mode 100644 index 74c296430d4c..000000000000 --- a/drivers/sensor/wsen/wsen_hids/wsen_hids.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT we_wsen_hids - -#include - -#include -#include -#include - -#include "wsen_hids.h" - -LOG_MODULE_REGISTER(WSEN_HIDS, CONFIG_SENSOR_LOG_LEVEL); - -/* - * List of supported output data rates (sensor_value struct, input to - * sensor_attr_set()). Index into this list is used as argument for - * HIDS_setOutputDataRate(). - */ -static const struct sensor_value hids_odr_list[] = { - {.val1 = 0, .val2 = 0}, - {.val1 = 1, .val2 = 0}, - {.val1 = 7, .val2 = 0}, - {.val1 = 12, .val2 = 5 * 100000}, -}; - -static int hids_sample_fetch(const struct device *dev, enum sensor_channel channel) -{ - struct hids_data *data = dev->data; - int16_t raw_humidity; - int16_t raw_temp; - - __ASSERT_NO_MSG(channel == SENSOR_CHAN_ALL); - - if (HIDS_getRawValues(&data->sensor_interface, &raw_humidity, &raw_temp) != WE_SUCCESS) { - LOG_ERR("Failed to %s sample.", "fetch data"); - return -EIO; - } - - if (HIDS_convertHumidity_uint16(&data->sensor_interface, raw_humidity, &data->humidity) != - WE_SUCCESS) { - LOG_ERR("Failed to %s sample.", "convert humidity"); - return -EIO; - } - - if (HIDS_convertTemperature_int16(&data->sensor_interface, raw_temp, &data->temperature) != - WE_SUCCESS) { - LOG_ERR("Failed to %s sample.", "convert temperature"); - return -EIO; - } - - return 0; -} - -static int hids_channel_get(const struct device *dev, enum sensor_channel channel, - struct sensor_value *value) -{ - struct hids_data *data = dev->data; - int32_t value_converted; - - if (channel == SENSOR_CHAN_AMBIENT_TEMP) { - value_converted = (int32_t)data->temperature; - - /* Convert temperature from 0.01 degrees Celsius to degrees Celsius */ - value->val1 = value_converted / 100; - value->val2 = (value_converted % 100) * (1000000 / 100); - } else if (channel == SENSOR_CHAN_HUMIDITY) { - value_converted = (int32_t)data->humidity; - - /* Convert humidity from 0.01 percent to percent */ - value->val1 = value_converted / 100; - value->val2 = (value_converted % 100) * (1000000 / 100); - } else { - return -ENOTSUP; - } - - return 0; -} - -/* Set output data rate. See hids_odr_list for allowed values. */ -static int hids_odr_set(const struct device *dev, const struct sensor_value *odr) -{ - struct hids_data *data = dev->data; - int odr_index; - - for (odr_index = 0; odr_index < ARRAY_SIZE(hids_odr_list); odr_index++) { - if (odr->val1 == hids_odr_list[odr_index].val1 && - odr->val2 == hids_odr_list[odr_index].val2) { - break; - } - } - - if (odr_index == ARRAY_SIZE(hids_odr_list)) { - /* ODR not allowed (was not found in hids_odr_list) */ - LOG_ERR("Bad sampling frequency %d.%d", odr->val1, odr->val2); - return -EINVAL; - } - - if (HIDS_setOutputDataRate(&data->sensor_interface, (HIDS_outputDataRate_t)odr_index) != - WE_SUCCESS) { - LOG_ERR("Failed to set output data rate"); - return -EIO; - } - - return 0; -} - -static int hids_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() is not supported on channel %d.", chan); - return -ENOTSUP; - } - - if (attr == SENSOR_ATTR_SAMPLING_FREQUENCY) { - return hids_odr_set(dev, val); - } else { - return -ENOTSUP; - } -} - -static const struct sensor_driver_api hids_driver_api = { - .attr_set = hids_attr_set, -#if CONFIG_WSEN_HIDS_TRIGGER - .trigger_set = hids_trigger_set, -#endif - .sample_fetch = hids_sample_fetch, - .channel_get = hids_channel_get, -}; - -static int hids_init(const struct device *dev) -{ - const struct hids_config *config = dev->config; - struct hids_data *data = dev->data; - uint8_t device_id; - - /* Initialize WE sensor interface */ - WE_sensorInterfaceType_t interface_type = data->sensor_interface.interfaceType; - - HIDS_getDefaultInterface(&data->sensor_interface); - data->sensor_interface.interfaceType = interface_type; - - switch (data->sensor_interface.interfaceType) { -#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) - case WE_i2c: - data->sensor_interface.handle = (void *)&config->bus_cfg.i2c; - break; -#endif -#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) - case WE_spi: - data->sensor_interface.handle = (void *)&config->bus_cfg.spi; - break; -#endif - default: - LOG_ERR("Invalid interface type"); - return -EINVAL; - } - - /* First communication test - check device ID */ - if (HIDS_getDeviceID(&data->sensor_interface, &device_id) != WE_SUCCESS) { - LOG_ERR("Failed to read device ID."); - return -EIO; - } - - if (device_id != HIDS_DEVICE_ID_VALUE) { - LOG_ERR("Invalid device ID 0x%x.", device_id); - return -EINVAL; - } - - if (HIDS_setOutputDataRate(&data->sensor_interface, config->odr) != WE_SUCCESS) { - LOG_ERR("Failed to set output data rate."); - return -EIO; - } - - if (HIDS_enableBlockDataUpdate(&data->sensor_interface, HIDS_enable) != WE_SUCCESS) { - LOG_ERR("Failed to enable block data update."); - return -EIO; - } - - if (HIDS_setPowerMode(&data->sensor_interface, HIDS_activeMode) != WE_SUCCESS) { - LOG_ERR("Failed to set power mode."); - return -EIO; - } - - if (HIDS_readCalibrationData(&data->sensor_interface) != WE_SUCCESS) { - LOG_ERR("Failed to read calibration data."); - return -EIO; - } - -#if CONFIG_WSEN_HIDS_TRIGGER - int status = hids_init_interrupt(dev); - - if (status < 0) { - LOG_ERR("Failed to initialize data-ready interrupt."); - return status; - } -#endif - - return 0; -} - -#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0 -#warning "HIDS driver enabled without any devices" -#endif - -/* - * Device creation macros - */ - -#define HIDS_DEVICE_INIT(inst) \ - SENSOR_DEVICE_DT_INST_DEFINE(inst, \ - hids_init, \ - NULL, \ - &hids_data_##inst, \ - &hids_config_##inst, \ - POST_KERNEL, \ - CONFIG_SENSOR_INIT_PRIORITY, \ - &hids_driver_api); - -#ifdef CONFIG_WSEN_HIDS_TRIGGER -#define HIDS_CFG_IRQ(inst) .gpio_drdy = GPIO_DT_SPEC_INST_GET(inst, drdy_gpios) -#else -#define HIDS_CFG_IRQ(inst) -#endif /* CONFIG_WSEN_HIDS_TRIGGER */ - -#define HIDS_CONFIG_COMMON(inst) \ - .odr = (HIDS_outputDataRate_t)(DT_INST_ENUM_IDX(inst, odr) + 1), \ - COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, drdy_gpios), \ - (HIDS_CFG_IRQ(inst)), ()) - -/* - * Instantiation macros used when device is on SPI bus. - */ - -#define HIDS_SPI_OPERATION (SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA) - -#define HIDS_CONFIG_SPI(inst) \ - { \ - .bus_cfg = { \ - .spi = SPI_DT_SPEC_INST_GET(inst, \ - HIDS_SPI_OPERATION, \ - 0), \ - }, \ - HIDS_CONFIG_COMMON(inst) \ - } - -/* - * Instantiation macros used when device is on I2C bus. - */ - -#define HIDS_CONFIG_I2C(inst) \ - { \ - .bus_cfg = { \ - .i2c = I2C_DT_SPEC_INST_GET(inst), \ - }, \ - HIDS_CONFIG_COMMON(inst) \ - } - -/* - * Main instantiation macro. Use of COND_CODE_1() selects the right - * bus-specific macro at preprocessor time. - */ -#define HIDS_DEFINE(inst) \ - static struct hids_data hids_data_##inst = \ - COND_CODE_1(DT_INST_ON_BUS(inst, i2c), \ - ({ .sensor_interface = { .interfaceType = WE_i2c } }), ()) \ - COND_CODE_1(DT_INST_ON_BUS(inst, spi), \ - ({ .sensor_interface = { .interfaceType = WE_spi } }), ());\ - static const struct hids_config hids_config_##inst = \ - COND_CODE_1(DT_INST_ON_BUS(inst, i2c), (HIDS_CONFIG_I2C(inst)), ()) \ - COND_CODE_1(DT_INST_ON_BUS(inst, spi), (HIDS_CONFIG_SPI(inst)), ()); \ - HIDS_DEVICE_INIT(inst) - -DT_INST_FOREACH_STATUS_OKAY(HIDS_DEFINE) diff --git a/drivers/sensor/wsen/wsen_hids/wsen_hids.h b/drivers/sensor/wsen/wsen_hids/wsen_hids.h deleted file mode 100644 index a75e243bf653..000000000000 --- a/drivers/sensor/wsen/wsen_hids/wsen_hids.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_DRIVERS_SENSOR_WSEN_HIDS_WSEN_HIDS_H_ -#define ZEPHYR_DRIVERS_SENSOR_WSEN_HIDS_WSEN_HIDS_H_ - -#include -#include - -#include - -#include "WSEN_HIDS_2523020210001.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) */ - -struct hids_data { - /* WE sensor interface configuration */ - WE_sensorInterface_t sensor_interface; - - /* Last humidity sample */ - uint16_t humidity; - - /* Last temperature sample */ - int16_t temperature; - -#ifdef CONFIG_WSEN_HIDS_TRIGGER - const struct device *dev; - struct gpio_callback data_ready_cb; - - const struct sensor_trigger *data_ready_trigger; - sensor_trigger_handler_t data_ready_handler; - -#if defined(CONFIG_WSEN_HIDS_TRIGGER_OWN_THREAD) - K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_WSEN_HIDS_THREAD_STACK_SIZE); - struct k_thread thread; - struct k_sem drdy_sem; -#elif defined(CONFIG_WSEN_HIDS_TRIGGER_GLOBAL_THREAD) - struct k_work work; -#endif -#endif /* CONFIG_WSEN_HIDS_TRIGGER */ -}; - -struct hids_config { - 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 - } bus_cfg; - - /* Output data rate */ - HIDS_outputDataRate_t odr; - -#ifdef CONFIG_WSEN_HIDS_TRIGGER - /* Data-ready interrupt pin */ - const struct gpio_dt_spec gpio_drdy; -#endif /* CONFIG_WSEN_HIDS_TRIGGER */ -}; - -#ifdef CONFIG_WSEN_HIDS_TRIGGER -int hids_trigger_set(const struct device *dev, const struct sensor_trigger *trig, - sensor_trigger_handler_t handler); - -int hids_init_interrupt(const struct device *dev); -#endif /* CONFIG_WSEN_HIDS_TRIGGER */ - -int hids_spi_init(const struct device *dev); -int hids_i2c_init(const struct device *dev); - -#endif /* ZEPHYR_DRIVERS_SENSOR_WSEN_HIDS_WSEN_HIDS_H_ */ diff --git a/drivers/sensor/wsen/wsen_hids/wsen_hids_trigger.c b/drivers/sensor/wsen/wsen_hids/wsen_hids_trigger.c deleted file mode 100644 index e8c9472f5cd2..000000000000 --- a/drivers/sensor/wsen/wsen_hids/wsen_hids_trigger.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT we_wsen_hids - -#include - -#include "wsen_hids.h" - -LOG_MODULE_DECLARE(WSEN_HIDS, CONFIG_SENSOR_LOG_LEVEL); - -static inline void hids_setup_drdy_interrupt(const struct device *dev, bool enable) -{ - const struct hids_config *cfg = dev->config; - unsigned int flags = enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE; - - gpio_pin_interrupt_configure_dt(&cfg->gpio_drdy, flags); -} - -static inline void hids_handle_drdy_interrupt(const struct device *dev) -{ - struct hids_data *data = dev->data; - - hids_setup_drdy_interrupt(dev, false); - -#if defined(CONFIG_WSEN_HIDS_TRIGGER_OWN_THREAD) - k_sem_give(&data->drdy_sem); -#elif defined(CONFIG_WSEN_HIDS_TRIGGER_GLOBAL_THREAD) - k_work_submit(&data->work); -#endif -} - -static void hids_process_drdy_interrupt(const struct device *dev) -{ - struct hids_data *data = dev->data; - - if (data->data_ready_handler != NULL) { - data->data_ready_handler(dev, data->data_ready_trigger); - } - - if (data->data_ready_handler != NULL) { - hids_setup_drdy_interrupt(dev, true); - } -} - -int hids_trigger_set(const struct device *dev, const struct sensor_trigger *trig, - sensor_trigger_handler_t handler) -{ - struct hids_data *data = dev->data; - const struct hids_config *cfg = dev->config; - - if (trig->type != SENSOR_TRIG_DATA_READY) { - LOG_ERR("Unsupported sensor trigger"); - return -ENOTSUP; - } - - hids_setup_drdy_interrupt(dev, false); - - data->data_ready_handler = handler; - if (handler == NULL) { - return 0; - } - - data->data_ready_trigger = trig; - - hids_setup_drdy_interrupt(dev, true); - - /* - * If DRDY is active we probably won't get the rising edge, so - * invoke the callback manually. - */ - if (gpio_pin_get_dt(&cfg->gpio_drdy) > 0) { - hids_handle_drdy_interrupt(dev); - } - - return 0; -} - -static void hids_drdy_callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins) -{ - struct hids_data *data = CONTAINER_OF(cb, struct hids_data, data_ready_cb); - - ARG_UNUSED(pins); - - hids_handle_drdy_interrupt(data->dev); -} - -#ifdef CONFIG_WSEN_HIDS_TRIGGER_OWN_THREAD -static void hids_thread(void *p1, void *p2, void *p3) -{ - ARG_UNUSED(p2); - ARG_UNUSED(p3); - - struct hids_data *data = p1; - - while (true) { - k_sem_take(&data->drdy_sem, K_FOREVER); - hids_process_drdy_interrupt(data->dev); - } -} -#endif /* CONFIG_WSEN_HIDS_TRIGGER_OWN_THREAD */ - -#ifdef CONFIG_WSEN_HIDS_TRIGGER_GLOBAL_THREAD -static void hids_work_cb(struct k_work *work) -{ - struct hids_data *data = CONTAINER_OF(work, struct hids_data, work); - - hids_process_drdy_interrupt(data->dev); -} -#endif /* CONFIG_WSEN_HIDS_TRIGGER_GLOBAL_THREAD */ - -int hids_init_interrupt(const struct device *dev) -{ - struct hids_data *data = dev->data; - const struct hids_config *cfg = dev->config; - int status; - - data->dev = dev; - - if (cfg->gpio_drdy.port == NULL) { - LOG_ERR("drdy-gpios is not defined in the device tree."); - return -EINVAL; - } - - if (!gpio_is_ready_dt(&cfg->gpio_drdy)) { - LOG_ERR("Device %s is not ready", cfg->gpio_drdy.port->name); - return -ENODEV; - } - - /* Setup data-ready gpio interrupt */ - status = gpio_pin_configure_dt(&cfg->gpio_drdy, GPIO_INPUT); - if (status < 0) { - LOG_ERR("Could not configure %s.%02u", cfg->gpio_drdy.port->name, - cfg->gpio_drdy.pin); - return status; - } - - gpio_init_callback(&data->data_ready_cb, hids_drdy_callback, BIT(cfg->gpio_drdy.pin)); - - status = gpio_add_callback(cfg->gpio_drdy.port, &data->data_ready_cb); - if (status < 0) { - LOG_ERR("Could not set gpio callback."); - return status; - } - - /* Enable data-ready interrupt */ - if (HIDS_enableDataReadyInterrupt(&data->sensor_interface, HIDS_enable) != WE_SUCCESS) { - LOG_ERR("Could not enable data-ready interrupt."); - return -EIO; - } - -#if defined(CONFIG_WSEN_HIDS_TRIGGER_OWN_THREAD) - k_sem_init(&data->drdy_sem, 0, K_SEM_MAX_LIMIT); - - k_thread_create(&data->thread, data->thread_stack, CONFIG_WSEN_HIDS_THREAD_STACK_SIZE, - hids_thread, data, NULL, NULL, - K_PRIO_COOP(CONFIG_WSEN_HIDS_THREAD_PRIORITY), 0, K_NO_WAIT); -#elif defined(CONFIG_WSEN_HIDS_TRIGGER_GLOBAL_THREAD) - data->work.handler = hids_work_cb; -#endif - - hids_setup_drdy_interrupt(dev, true); - - return 0; -} diff --git a/dts/bindings/sensor/we,wsen-hids-common.yaml b/dts/bindings/sensor/we,wsen-hids-common.yaml deleted file mode 100644 index be3c5906e4c0..000000000000 --- a/dts/bindings/sensor/we,wsen-hids-common.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG -# SPDX-License-Identifier: Apache-2.0 - -include: sensor-device.yaml - -properties: - drdy-gpios: - type: phandle-array - description: | - Data-ready interrupt pin. - Interrupt is active high by default. - - odr: - type: string - required: true - enum: - - "1" - - "7" - - "12.5" - description: | - Sensor output data rate expressed in samples per second. - Data rates supported by the chip are "1", "7" and "12.5". diff --git a/dts/bindings/sensor/we,wsen-hids-i2c.yaml b/dts/bindings/sensor/we,wsen-hids-i2c.yaml deleted file mode 100644 index 6552fe26dc53..000000000000 --- a/dts/bindings/sensor/we,wsen-hids-i2c.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG -# SPDX-License-Identifier: Apache-2.0 - -description: | - Würth Elektronik WSEN-HIDS humidity sensor with integrated temperature sensor (I2C bus) - -compatible: "we,wsen-hids" - -include: ["i2c-device.yaml", "we,wsen-hids-common.yaml"] diff --git a/dts/bindings/sensor/we,wsen-hids-spi.yaml b/dts/bindings/sensor/we,wsen-hids-spi.yaml deleted file mode 100644 index fcbdf9f6cf34..000000000000 --- a/dts/bindings/sensor/we,wsen-hids-spi.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG -# SPDX-License-Identifier: Apache-2.0 - -description: | - Würth Elektronik WSEN-HIDS humidity sensor with integrated temperature sensor (SPI bus) - -compatible: "we,wsen-hids" - -include: ["spi-device.yaml", "we,wsen-hids-common.yaml"] diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index 0b33109eb013..6cc81e4d2ce7 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -514,13 +514,6 @@ test_i2c_iis2iclx: iis2iclx@4c { odr = ; }; -test_i2c_wsen_hids: wsen_hids@4d { - compatible = "we,wsen-hids"; - reg = <0x4d>; - drdy-gpios = <&test_gpio 0 0>; - odr = "1"; -}; - test_i2c_max17055: max17055@4f { compatible = "maxim,max17055"; reg = <0x4f>; diff --git a/tests/drivers/build_all/sensor/sensors_trigger_global.conf b/tests/drivers/build_all/sensor/sensors_trigger_global.conf index 3a36a350e6a8..57ed749751d4 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_global.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_global.conf @@ -63,5 +63,4 @@ CONFIG_TMP007_TRIGGER_GLOBAL_THREAD=y CONFIG_TSL2540_TRIGGER_GLOBAL_THREAD=y CONFIG_TSL2591_TRIGGER_GLOBAL_THREAD=y CONFIG_VCNL4040_TRIGGER_GLOBAL_THREAD=y -CONFIG_WSEN_HIDS_TRIGGER_GLOBAL_THREAD=y CONFIG_WSEN_TIDS_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 805347a11a78..87a6bed1e25d 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_none.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_none.conf @@ -63,5 +63,4 @@ CONFIG_TMP007_TRIGGER_NONE=y CONFIG_TSL2540_TRIGGER_NONE=y CONFIG_TSL2591_TRIGGER_NONE=y CONFIG_VCNL4040_TRIGGER_NONE=y -CONFIG_WSEN_HIDS_TRIGGER_NONE=y CONFIG_WSEN_TIDS_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 ef31101c3c19..0a21780626c1 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_own.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_own.conf @@ -60,5 +60,4 @@ CONFIG_TMP007_TRIGGER_OWN_THREAD=y CONFIG_TSL2540_TRIGGER_OWN_THREAD=y CONFIG_TSL2591_TRIGGER_OWN_THREAD=y CONFIG_VCNL4040_TRIGGER_OWN_THREAD=y -CONFIG_WSEN_HIDS_TRIGGER_OWN_THREAD=y CONFIG_WSEN_TIDS_TRIGGER_OWN_THREAD=y From 51b281deac6bff35fc6f9d9e1e2308d6349c8049 Mon Sep 17 00:00:00 2001 From: Wajdi ELMuhtadi Date: Fri, 1 Sep 2023 11:34:04 +0200 Subject: [PATCH 03/14] drivers: sensor: wsen_pads: remove wsen_pads driver Remove wsen_pads since the hal update is no longer compatible with this version. Signed-off-by: Wajdi ELMuhtadi --- drivers/sensor/wsen/CMakeLists.txt | 1 - drivers/sensor/wsen/Kconfig | 1 - drivers/sensor/wsen/wsen_pads/CMakeLists.txt | 7 - drivers/sensor/wsen/wsen_pads/Kconfig | 55 ---- drivers/sensor/wsen/wsen_pads/wsen_pads.c | 273 ------------------ drivers/sensor/wsen/wsen_pads/wsen_pads.h | 82 ------ .../sensor/wsen/wsen_pads/wsen_pads_trigger.c | 183 ------------ dts/bindings/sensor/we,wsen-pads-common.yaml | 28 -- dts/bindings/sensor/we,wsen-pads-i2c.yaml | 9 - dts/bindings/sensor/we,wsen-pads-spi.yaml | 9 - tests/drivers/build_all/sensor/i2c.dtsi | 7 - 11 files changed, 655 deletions(-) delete mode 100644 drivers/sensor/wsen/wsen_pads/CMakeLists.txt delete mode 100644 drivers/sensor/wsen/wsen_pads/Kconfig delete mode 100644 drivers/sensor/wsen/wsen_pads/wsen_pads.c delete mode 100644 drivers/sensor/wsen/wsen_pads/wsen_pads.h delete mode 100644 drivers/sensor/wsen/wsen_pads/wsen_pads_trigger.c delete mode 100644 dts/bindings/sensor/we,wsen-pads-common.yaml delete mode 100644 dts/bindings/sensor/we,wsen-pads-i2c.yaml delete mode 100644 dts/bindings/sensor/we,wsen-pads-spi.yaml diff --git a/drivers/sensor/wsen/CMakeLists.txt b/drivers/sensor/wsen/CMakeLists.txt index e3ce57897393..af425b59742f 100644 --- a/drivers/sensor/wsen/CMakeLists.txt +++ b/drivers/sensor/wsen/CMakeLists.txt @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start -add_subdirectory_ifdef(CONFIG_WSEN_PADS wsen_pads) add_subdirectory_ifdef(CONFIG_WSEN_PDUS wsen_pdus) add_subdirectory_ifdef(CONFIG_WSEN_TIDS wsen_tids) # zephyr-keep-sorted-stop diff --git a/drivers/sensor/wsen/Kconfig b/drivers/sensor/wsen/Kconfig index a8b4fd6ddeb1..f8c6091ac992 100644 --- a/drivers/sensor/wsen/Kconfig +++ b/drivers/sensor/wsen/Kconfig @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start -source "drivers/sensor/wsen/wsen_pads/Kconfig" source "drivers/sensor/wsen/wsen_pdus/Kconfig" source "drivers/sensor/wsen/wsen_tids/Kconfig" # zephyr-keep-sorted-stop diff --git a/drivers/sensor/wsen/wsen_pads/CMakeLists.txt b/drivers/sensor/wsen/wsen_pads/CMakeLists.txt deleted file mode 100644 index d14de10d075d..000000000000 --- a/drivers/sensor/wsen/wsen_pads/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library() - -zephyr_library_sources(wsen_pads.c) -zephyr_library_sources_ifdef(CONFIG_WSEN_PADS_TRIGGER wsen_pads_trigger.c) diff --git a/drivers/sensor/wsen/wsen_pads/Kconfig b/drivers/sensor/wsen/wsen_pads/Kconfig deleted file mode 100644 index 906e471866b9..000000000000 --- a/drivers/sensor/wsen/wsen_pads/Kconfig +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG -# SPDX-License-Identifier: Apache-2.0 - -menuconfig WSEN_PADS - bool "WSEN-PADS absolute pressure and temperature sensor" - default y - depends on DT_HAS_WE_WSEN_PADS_ENABLED - select I2C if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_PADS),i2c) - select SPI if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_PADS),spi) - select HAS_WESENSORS - help - Enable driver for the WSEN-PADS I2C/SPI-based absolute pressure sensor with integrated - temperature sensor. - -if WSEN_PADS - -choice WSEN_PADS_TRIGGER_MODE - prompt "Trigger mode" - default WSEN_PADS_TRIGGER_NONE - help - Specify the type of triggering to be used by the driver. - -config WSEN_PADS_TRIGGER_NONE - bool "No trigger" - -config WSEN_PADS_TRIGGER_GLOBAL_THREAD - bool "Use global thread" - depends on GPIO - select WSEN_PADS_TRIGGER - -config WSEN_PADS_TRIGGER_OWN_THREAD - bool "Use own thread" - depends on GPIO - select WSEN_PADS_TRIGGER - -endchoice # WSEN_PADS_TRIGGER_MODE - -config WSEN_PADS_TRIGGER - bool - -config WSEN_PADS_THREAD_PRIORITY - int "Thread priority" - depends on WSEN_PADS_TRIGGER_OWN_THREAD - default 10 - help - Priority of thread used by the driver to handle interrupts. - -config WSEN_PADS_THREAD_STACK_SIZE - int "Thread stack size" - depends on WSEN_PADS_TRIGGER_OWN_THREAD - default 1024 - help - Stack size of thread used by the driver to handle interrupts. - -endif # WSEN_PADS diff --git a/drivers/sensor/wsen/wsen_pads/wsen_pads.c b/drivers/sensor/wsen/wsen_pads/wsen_pads.c deleted file mode 100644 index 4fd7ddb5d354..000000000000 --- a/drivers/sensor/wsen/wsen_pads/wsen_pads.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT we_wsen_pads - -#include - -#include -#include -#include - -#include "wsen_pads.h" - -LOG_MODULE_REGISTER(WSEN_PADS, CONFIG_SENSOR_LOG_LEVEL); - -/* - * List of supported output data rates. Index into this list is used as - * argument for PADS_setOutputDataRate() - */ -static const int32_t pads_odr_list[] = { - 0, 1, 10, 25, 50, 75, 100, 200, -}; - -static int pads_sample_fetch(const struct device *dev, enum sensor_channel channel) -{ - struct pads_data *data = dev->data; - - __ASSERT_NO_MSG(channel == SENSOR_CHAN_ALL); - - if (PADS_getPressure_int(&data->sensor_interface, &data->pressure) != WE_SUCCESS) { - LOG_ERR("Failed to fetch %s sample.", "pressure"); - return -EIO; - } - - if (PADS_getTemperature_int(&data->sensor_interface, &data->temperature) != WE_SUCCESS) { - LOG_ERR("Failed to fetch %s sample.", "temperature"); - return -EIO; - } - - return 0; -} - -static int pads_channel_get(const struct device *dev, enum sensor_channel channel, - struct sensor_value *value) -{ - struct pads_data *data = dev->data; - int32_t value_converted; - - if (channel == SENSOR_CHAN_AMBIENT_TEMP) { - value_converted = (int32_t)data->temperature; - - /* Convert temperature from 0.01 degrees Celsius to degrees Celsius */ - value->val1 = value_converted / 100; - value->val2 = (value_converted % 100) * (1000000 / 100); - } else if (channel == SENSOR_CHAN_PRESS) { - value_converted = (int32_t)data->pressure; - - /* Convert pressure from Pa to kPa */ - value->val1 = value_converted / 1000; - value->val2 = (value_converted % 1000) * (1000000 / 1000); - } else { - return -ENOTSUP; - } - - return 0; -} - -/* Set output data rate. See pads_odr_list for allowed values. */ -static int pads_odr_set(const struct device *dev, const struct sensor_value *odr) -{ - struct pads_data *data = dev->data; - int odr_index; - - for (odr_index = 0; odr_index < ARRAY_SIZE(pads_odr_list); odr_index++) { - if (odr->val1 == pads_odr_list[odr_index] && odr->val2 == 0) { - break; - } - } - - if (odr_index == ARRAY_SIZE(pads_odr_list)) { - /* ODR not allowed (was not found in pads_odr_list) */ - LOG_ERR("Bad sampling frequency %d.%d", odr->val1, odr->val2); - return -EINVAL; - } - - if (PADS_setOutputDataRate(&data->sensor_interface, (PADS_outputDataRate_t)odr_index) != - WE_SUCCESS) { - LOG_ERR("Failed to set output data rate"); - return -EIO; - } - - return 0; -} - -static int pads_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() is not supported on channel %d.", chan); - return -ENOTSUP; - } - - if (attr == SENSOR_ATTR_SAMPLING_FREQUENCY) { - return pads_odr_set(dev, val); - } else { - return -ENOTSUP; - } -} - -static const struct sensor_driver_api pads_driver_api = { - .attr_set = pads_attr_set, -#if CONFIG_WSEN_PADS_TRIGGER - .trigger_set = pads_trigger_set, -#endif - .sample_fetch = pads_sample_fetch, - .channel_get = pads_channel_get, -}; - -static int pads_init(const struct device *dev) -{ - const struct pads_config *config = dev->config; - struct pads_data *data = dev->data; - struct sensor_value odr; - int status; - uint8_t device_id; - - /* Initialize WE sensor interface */ - WE_sensorInterfaceType_t interface_type = data->sensor_interface.interfaceType; - - PADS_getDefaultInterface(&data->sensor_interface); - data->sensor_interface.interfaceType = interface_type; - - switch (data->sensor_interface.interfaceType) { -#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) - case WE_i2c: - data->sensor_interface.handle = (void *)&config->bus_cfg.i2c; - break; -#endif -#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) - case WE_spi: - data->sensor_interface.handle = (void *)&config->bus_cfg.spi; - break; -#endif - default: - LOG_ERR("Invalid interface type"); - return -EINVAL; - } - - /* First communication test - check device ID */ - if (PADS_getDeviceID(&data->sensor_interface, &device_id) != WE_SUCCESS) { - LOG_ERR("Failed to read device ID."); - return -EIO; - } - - if (device_id != PADS_DEVICE_ID_VALUE) { - LOG_ERR("Invalid device ID 0x%x.", device_id); - return -EINVAL; - } - - /* Reset sensor */ - PADS_softReset(&data->sensor_interface, PADS_enable); - - k_sleep(K_USEC(50)); - - PADS_state_t swReset; - - do { - if (PADS_getSoftResetState(&data->sensor_interface, &swReset) != WE_SUCCESS) { - LOG_ERR("Failed to get sensor reset state."); - return -EIO; - } - } while (PADS_enable == swReset); - - if (PADS_enableBlockDataUpdate(&data->sensor_interface, PADS_enable) != WE_SUCCESS) { - LOG_ERR("Failed to enable block data update."); - return -EIO; - } - -#if CONFIG_WSEN_PADS_TRIGGER - status = pads_init_interrupt(dev); - if (status < 0) { - LOG_ERR("Failed to initialize data-ready interrupt."); - return status; - } -#endif - - odr.val1 = pads_odr_list[config->odr]; - odr.val2 = 0; - status = pads_odr_set(dev, &odr); - if (status < 0) { - LOG_ERR("Failed to set output data rate."); - return status; - } - - return 0; -} - -#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0 -#warning "PADS driver enabled without any devices" -#endif - -/* - * Device creation macros - */ - -#define PADS_DEVICE_INIT(inst) \ - SENSOR_DEVICE_DT_INST_DEFINE(inst, \ - pads_init, \ - NULL, \ - &pads_data_##inst, \ - &pads_config_##inst, \ - POST_KERNEL, \ - CONFIG_SENSOR_INIT_PRIORITY, \ - &pads_driver_api); - -#ifdef CONFIG_WSEN_PADS_TRIGGER -#define PADS_CFG_IRQ(inst) .gpio_drdy = GPIO_DT_SPEC_INST_GET(inst, drdy_gpios) -#else -#define PADS_CFG_IRQ(inst) -#endif /* CONFIG_WSEN_PADS_TRIGGER */ - -#define PADS_CONFIG_COMMON(inst) \ - .odr = (PADS_outputDataRate_t)(DT_INST_ENUM_IDX(inst, odr)), \ - COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, drdy_gpios), \ - (PADS_CFG_IRQ(inst)), ()) - -/* - * Instantiation macros used when device is on SPI bus. - */ - -#define PADS_SPI_OPERATION (SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA) - -#define PADS_CONFIG_SPI(inst) \ - { \ - .bus_cfg = { \ - .spi = SPI_DT_SPEC_INST_GET(inst, \ - PADS_SPI_OPERATION, \ - 0), \ - }, \ - PADS_CONFIG_COMMON(inst) \ - } - -/* - * Instantiation macros used when device is on I2C bus. - */ - -#define PADS_CONFIG_I2C(inst) \ - { \ - .bus_cfg = { \ - .i2c = I2C_DT_SPEC_INST_GET(inst), \ - }, \ - PADS_CONFIG_COMMON(inst) \ - } - -/* - * Main instantiation macro. Use of COND_CODE_1() selects the right - * bus-specific macro at preprocessor time. - */ -#define PADS_DEFINE(inst) \ - static struct pads_data pads_data_##inst = \ - COND_CODE_1(DT_INST_ON_BUS(inst, i2c), \ - ({ .sensor_interface = { .interfaceType = WE_i2c } }), ()) \ - COND_CODE_1(DT_INST_ON_BUS(inst, spi), \ - ({ .sensor_interface = { .interfaceType = WE_spi } }), ()); \ - static const struct pads_config pads_config_##inst = \ - COND_CODE_1(DT_INST_ON_BUS(inst, i2c), (PADS_CONFIG_I2C(inst)), ()) \ - COND_CODE_1(DT_INST_ON_BUS(inst, spi), (PADS_CONFIG_SPI(inst)), ()); \ - PADS_DEVICE_INIT(inst) - -DT_INST_FOREACH_STATUS_OKAY(PADS_DEFINE) diff --git a/drivers/sensor/wsen/wsen_pads/wsen_pads.h b/drivers/sensor/wsen/wsen_pads/wsen_pads.h deleted file mode 100644 index a4efc51a0436..000000000000 --- a/drivers/sensor/wsen/wsen_pads/wsen_pads.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_DRIVERS_SENSOR_WSEN_PADS_WSEN_PADS_H_ -#define ZEPHYR_DRIVERS_SENSOR_WSEN_PADS_WSEN_PADS_H_ - -#include -#include - -#include - -#include "WSEN_PADS_2511020213301.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) */ - -struct pads_data { - /* WE sensor interface configuration */ - WE_sensorInterface_t sensor_interface; - - /* Last pressure sample */ - int32_t pressure; - - /* Last temperature sample */ - int16_t temperature; - -#ifdef CONFIG_WSEN_PADS_TRIGGER - const struct device *dev; - - struct gpio_callback data_ready_cb; - - struct sensor_trigger *data_ready_triggerP; - sensor_trigger_handler_t data_ready_handler; - -#if defined(CONFIG_WSEN_PADS_TRIGGER_OWN_THREAD) - K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_WSEN_PADS_THREAD_STACK_SIZE); - struct k_thread thread; - struct k_sem drdy_sem; -#elif defined(CONFIG_WSEN_PADS_TRIGGER_GLOBAL_THREAD) - struct k_work work; -#endif -#endif /* CONFIG_WSEN_PADS_TRIGGER */ -}; - -struct pads_config { - 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 - } bus_cfg; - - /* Output data rate */ - const PADS_outputDataRate_t odr; - -#ifdef CONFIG_WSEN_PADS_TRIGGER - /* Interrupt pin used for data-ready */ - const struct gpio_dt_spec gpio_drdy; -#endif /* CONFIG_WSEN_PADS_TRIGGER */ -}; - -#ifdef CONFIG_WSEN_PADS_TRIGGER -int pads_trigger_set(const struct device *dev, const struct sensor_trigger *trig, - sensor_trigger_handler_t handler); - -int pads_init_interrupt(const struct device *dev); -#endif /* CONFIG_WSEN_PADS_TRIGGER */ - -int pads_spi_init(const struct device *dev); -int pads_i2c_init(const struct device *dev); - -#endif /* ZEPHYR_DRIVERS_SENSOR_WSEN_PADS_WSEN_PADS_H_ */ diff --git a/drivers/sensor/wsen/wsen_pads/wsen_pads_trigger.c b/drivers/sensor/wsen/wsen_pads/wsen_pads_trigger.c deleted file mode 100644 index 13394e23d9ad..000000000000 --- a/drivers/sensor/wsen/wsen_pads/wsen_pads_trigger.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT we_wsen_pads - -#include - -#include "wsen_pads.h" - -LOG_MODULE_DECLARE(WSEN_PADS, CONFIG_SENSOR_LOG_LEVEL); - -/* Enable/disable data-ready interrupt handling */ -static inline int pads_setup_drdy_interrupt(const struct device *dev, bool enable) -{ - const struct pads_config *cfg = dev->config; - unsigned int flags = enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE; - - return gpio_pin_interrupt_configure_dt(&cfg->gpio_drdy, flags); -} - -/* - * Is called when a data-ready interrupt has occurred. Triggers - * asynchronous processing of the interrupt in pads_process_drdy_interrupt(). - */ -static inline void pads_handle_drdy_interrupt(const struct device *dev) -{ - struct pads_data *data = dev->data; - - /* Disable interrupt handling until the interrupt has been processed */ - pads_setup_drdy_interrupt(dev, false); - -#if defined(CONFIG_WSEN_PADS_TRIGGER_OWN_THREAD) - k_sem_give(&data->drdy_sem); -#elif defined(CONFIG_WSEN_PADS_TRIGGER_GLOBAL_THREAD) - k_work_submit(&data->work); -#endif -} - -/* Calls data-ready trigger handler (if any) */ -static void pads_process_drdy_interrupt(const struct device *dev) -{ - struct pads_data *data = dev->data; - - if (data->data_ready_handler != NULL) { - data->data_ready_handler(dev, data->data_ready_triggerP); - pads_setup_drdy_interrupt(dev, true); - } -} - -int pads_trigger_set(const struct device *dev, const struct sensor_trigger *trig, - sensor_trigger_handler_t handler) -{ - struct pads_data *data = dev->data; - const struct pads_config *cfg = dev->config; - int32_t pressure_dummy; - - if (trig->type != SENSOR_TRIG_DATA_READY) { - LOG_ERR("Unsupported sensor trigger"); - return -ENOTSUP; - } - - pads_setup_drdy_interrupt(dev, false); - - data->data_ready_handler = handler; - if (handler == NULL) { - /* Disable data-ready interrupt */ - if (PADS_enableDataReadyInterrupt(&data->sensor_interface, PADS_disable) != - WE_SUCCESS) { - LOG_ERR("Failed to disable data-ready interrupt."); - return -EIO; - } - return 0; - } - - data->data_ready_triggerP = trig; - - pads_setup_drdy_interrupt(dev, true); - - /* Read pressure to retrigger interrupt */ - if (PADS_getPressure_int(&data->sensor_interface, &pressure_dummy) != WE_SUCCESS) { - LOG_ERR("Failed to read sample"); - return -EIO; - } - - /* Enable data-ready interrupt */ - if (PADS_enableDataReadyInterrupt(&data->sensor_interface, PADS_enable) != WE_SUCCESS) { - LOG_ERR("Failed to enable data-ready interrupt."); - return -EIO; - } - - /* - * If data-ready is active we probably won't get the rising edge, so - * invoke the handler manually. - */ - if (gpio_pin_get_dt(&cfg->gpio_drdy) > 0) { - pads_handle_drdy_interrupt(dev); - } - - return 0; -} - -static void pads_drdy_callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins) -{ - struct pads_data *data = CONTAINER_OF(cb, struct pads_data, data_ready_cb); - - ARG_UNUSED(pins); - - pads_handle_drdy_interrupt(data->dev); -} - -#ifdef CONFIG_WSEN_PADS_TRIGGER_OWN_THREAD -static void pads_thread(void *p1, void *p2, void *p3) -{ - ARG_UNUSED(p2); - ARG_UNUSED(p3); - - struct pads_data *data = p1; - - while (true) { - k_sem_take(&data->drdy_sem, K_FOREVER); - pads_process_drdy_interrupt(data->dev); - } -} -#endif /* CONFIG_WSEN_PADS_TRIGGER_OWN_THREAD */ - -#ifdef CONFIG_WSEN_PADS_TRIGGER_GLOBAL_THREAD -static void pads_work_cb(struct k_work *work) -{ - struct pads_data *data = CONTAINER_OF(work, struct pads_data, work); - - pads_process_drdy_interrupt(data->dev); -} -#endif /* CONFIG_WSEN_PADS_TRIGGER_GLOBAL_THREAD */ - -int pads_init_interrupt(const struct device *dev) -{ - struct pads_data *data = dev->data; - const struct pads_config *cfg = dev->config; - int status; - - data->dev = dev; - - if (cfg->gpio_drdy.port == NULL) { - LOG_ERR("drdy-gpios is not defined in the device tree."); - return -EINVAL; - } - - if (!gpio_is_ready_dt(cfg->gpio_drdy.port)) { - LOG_ERR("Device %s is not ready", cfg->gpio_drdy.port->name); - return -ENODEV; - } - - /* Setup data-ready gpio interrupt */ - status = gpio_pin_configure_dt(&cfg->gpio_drdy, GPIO_INPUT); - if (status < 0) { - LOG_ERR("Failed to configure %s.%02u", cfg->gpio_drdy.port->name, - cfg->gpio_drdy.pin); - return status; - } - - gpio_init_callback(&data->data_ready_cb, pads_drdy_callback, BIT(cfg->gpio_drdy.pin)); - - status = gpio_add_callback(cfg->gpio_drdy.port, &data->data_ready_cb); - if (status < 0) { - LOG_ERR("Failed to set gpio callback."); - return status; - } - -#if defined(CONFIG_WSEN_PADS_TRIGGER_OWN_THREAD) - k_sem_init(&data->drdy_sem, 0, K_SEM_MAX_LIMIT); - - k_thread_create(&data->thread, data->thread_stack, CONFIG_WSEN_PADS_THREAD_STACK_SIZE, - pads_thread, data, NULL, NULL, - K_PRIO_COOP(CONFIG_WSEN_PADS_THREAD_PRIORITY), 0, K_NO_WAIT); -#elif defined(CONFIG_WSEN_PADS_TRIGGER_GLOBAL_THREAD) - data->work.handler = pads_work_cb; -#endif - - return pads_setup_drdy_interrupt(dev, true); -} diff --git a/dts/bindings/sensor/we,wsen-pads-common.yaml b/dts/bindings/sensor/we,wsen-pads-common.yaml deleted file mode 100644 index 31b0dedd45cd..000000000000 --- a/dts/bindings/sensor/we,wsen-pads-common.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG -# SPDX-License-Identifier: Apache-2.0 - -include: sensor-device.yaml - -properties: - drdy-gpios: - type: phandle-array - description: | - Data-ready interrupt pin. - Interrupt is active high by default. - - odr: - type: int - required: true - enum: - - 0 - - 1 - - 10 - - 25 - - 50 - - 75 - - 100 - - 200 - description: | - Sensor output data rate expressed in samples per second. - Data rates supported by the chip are 0 (power down), 1, - 10, 25, 50, 75, 100 and 200. diff --git a/dts/bindings/sensor/we,wsen-pads-i2c.yaml b/dts/bindings/sensor/we,wsen-pads-i2c.yaml deleted file mode 100644 index 108a2953d820..000000000000 --- a/dts/bindings/sensor/we,wsen-pads-i2c.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG -# SPDX-License-Identifier: Apache-2.0 - -description: | - Würth Elektronik WSEN-PADS absolute pressure sensor (I2C bus) - -compatible: "we,wsen-pads" - -include: ["i2c-device.yaml", "we,wsen-pads-common.yaml"] diff --git a/dts/bindings/sensor/we,wsen-pads-spi.yaml b/dts/bindings/sensor/we,wsen-pads-spi.yaml deleted file mode 100644 index e7b61f248fbb..000000000000 --- a/dts/bindings/sensor/we,wsen-pads-spi.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG -# SPDX-License-Identifier: Apache-2.0 - -description: | - Würth Elektronik WSEN-PADS absolute pressure sensor (SPI bus) - -compatible: "we,wsen-pads" - -include: ["spi-device.yaml", "we,wsen-pads-common.yaml"] diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index 6cc81e4d2ce7..0d11cae24a4e 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -677,13 +677,6 @@ test_i2c_tmd2620: tmd2620@62 { wait-time-factor = <0>; }; -test_i2c_wsen_pads: wsen_pads@63 { - compatible = "we,wsen-pads"; - reg = <0x63>; - drdy-gpios = <&test_gpio 0 0>; - odr = <1>; -}; - test_i2c_s11059: s11059@64 { compatible = "hamamatsu,s11059"; reg = <0x64>; From e50f23d6f52af35707225e6ddc909f5171dcf0ca Mon Sep 17 00:00:00 2001 From: Wajdi ELMuhtadi Date: Fri, 1 Sep 2023 11:35:12 +0200 Subject: [PATCH 04/14] drivers: sensor: wsen_pdus: remove wsen_pdus driver Remove wsen_pdus since the hal update is no longer compatible with this version. Signed-off-by: Wajdi ELMuhtadi --- drivers/sensor/wsen/CMakeLists.txt | 1 - drivers/sensor/wsen/Kconfig | 1 - drivers/sensor/wsen/wsen_pdus/CMakeLists.txt | 6 - drivers/sensor/wsen/wsen_pdus/Kconfig | 11 -- drivers/sensor/wsen/wsen_pdus/wsen_pdus.c | 111 ------------------- drivers/sensor/wsen/wsen_pdus/wsen_pdus.h | 44 -------- dts/bindings/sensor/we,wsen-pdus.yaml | 21 ---- tests/drivers/build_all/sensor/i2c.dtsi | 6 - 8 files changed, 201 deletions(-) delete mode 100644 drivers/sensor/wsen/wsen_pdus/CMakeLists.txt delete mode 100644 drivers/sensor/wsen/wsen_pdus/Kconfig delete mode 100644 drivers/sensor/wsen/wsen_pdus/wsen_pdus.c delete mode 100644 drivers/sensor/wsen/wsen_pdus/wsen_pdus.h delete mode 100644 dts/bindings/sensor/we,wsen-pdus.yaml diff --git a/drivers/sensor/wsen/CMakeLists.txt b/drivers/sensor/wsen/CMakeLists.txt index af425b59742f..58d9868e47b9 100644 --- a/drivers/sensor/wsen/CMakeLists.txt +++ b/drivers/sensor/wsen/CMakeLists.txt @@ -2,6 +2,5 @@ # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start -add_subdirectory_ifdef(CONFIG_WSEN_PDUS wsen_pdus) add_subdirectory_ifdef(CONFIG_WSEN_TIDS wsen_tids) # zephyr-keep-sorted-stop diff --git a/drivers/sensor/wsen/Kconfig b/drivers/sensor/wsen/Kconfig index f8c6091ac992..ac443e731134 100644 --- a/drivers/sensor/wsen/Kconfig +++ b/drivers/sensor/wsen/Kconfig @@ -2,6 +2,5 @@ # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start -source "drivers/sensor/wsen/wsen_pdus/Kconfig" source "drivers/sensor/wsen/wsen_tids/Kconfig" # zephyr-keep-sorted-stop diff --git a/drivers/sensor/wsen/wsen_pdus/CMakeLists.txt b/drivers/sensor/wsen/wsen_pdus/CMakeLists.txt deleted file mode 100644 index ab0d66fb23a0..000000000000 --- a/drivers/sensor/wsen/wsen_pdus/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library() - -zephyr_library_sources(wsen_pdus.c) diff --git a/drivers/sensor/wsen/wsen_pdus/Kconfig b/drivers/sensor/wsen/wsen_pdus/Kconfig deleted file mode 100644 index a43cbe41144a..000000000000 --- a/drivers/sensor/wsen/wsen_pdus/Kconfig +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG -# SPDX-License-Identifier: Apache-2.0 - -config WSEN_PDUS - bool "WSEN-PDUS differential pressure sensor" - default y - depends on DT_HAS_WE_WSEN_PDUS_ENABLED - select I2C if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_PDUS),i2c) - select HAS_WESENSORS - help - Enable driver for the WSEN-PDUS I2C-based differential pressure sensor. diff --git a/drivers/sensor/wsen/wsen_pdus/wsen_pdus.c b/drivers/sensor/wsen/wsen_pdus/wsen_pdus.c deleted file mode 100644 index 70e319602d04..000000000000 --- a/drivers/sensor/wsen/wsen_pdus/wsen_pdus.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT we_wsen_pdus - -#include - -#include -#include -#include - -#include "wsen_pdus.h" - -LOG_MODULE_REGISTER(WSEN_PDUS, CONFIG_SENSOR_LOG_LEVEL); - -static int pdus_sample_fetch(const struct device *dev, enum sensor_channel chan) -{ - const struct pdus_config *const config = dev->config; - struct pdus_data *data = dev->data; - float pressure; - float temperature; - - __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL); - - if (PDUS_getPressureAndTemperature_float(&data->sensor_interface, - config->sensor_type, &pressure, - &temperature) != WE_SUCCESS) { - LOG_ERR("Failed to fetch data sample"); - return -EIO; - } - - data->pressure_k_pa = pressure; - data->temperature_deg_c = temperature; - - return 0; -} - -static int pdus_channel_get(const struct device *dev, enum sensor_channel chan, - struct sensor_value *value) -{ - struct pdus_data *data = dev->data; - - if (chan == SENSOR_CHAN_PRESS) { - value->val1 = (int32_t)data->pressure_k_pa; - value->val2 = (((int32_t)(data->pressure_k_pa * 1000)) % 1000) * 1000; - } else if (chan == SENSOR_CHAN_AMBIENT_TEMP) { - value->val1 = (int32_t)data->temperature_deg_c; - value->val2 = - (((int32_t)(data->temperature_deg_c * 1000)) % 1000) * 1000; - } else { - return -ENOTSUP; - } - - return 0; -} - -static const struct sensor_driver_api pdus_driver_api = { .sample_fetch = pdus_sample_fetch, - .channel_get = pdus_channel_get }; - -static int pdus_init(const struct device *dev) -{ - const struct pdus_config *const config = dev->config; - struct pdus_data *data = dev->data; - - /* Initialize WE sensor interface */ - PDUS_getDefaultInterface(&data->sensor_interface); - data->sensor_interface.interfaceType = WE_i2c; - - switch (data->sensor_interface.interfaceType) { -#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) - case WE_i2c: - data->sensor_interface.handle = (void *)&config->bus_cfg.i2c; - break; -#endif - default: - LOG_ERR("Invalid interface type"); - return -EINVAL; - } - - return 0; -} - -#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0 -#warning "PDUS driver enabled without any devices" -#endif - -/* - * Main instantiation macro. - */ -#define PDUS_DEFINE(inst) \ - static struct pdus_data pdus_data_##inst; \ - static const struct pdus_config pdus_config_##inst = \ - { \ - .bus_cfg = { \ - .i2c = I2C_DT_SPEC_INST_GET(inst), \ - }, \ - .sensor_type = (PDUS_SensorType_t) DT_INST_ENUM_IDX(inst, sensor_type) \ - }; \ - SENSOR_DEVICE_DT_INST_DEFINE(inst, \ - pdus_init, \ - NULL, \ - &pdus_data_##inst, \ - &pdus_config_##inst, \ - POST_KERNEL, \ - CONFIG_SENSOR_INIT_PRIORITY, \ - &pdus_driver_api); - -DT_INST_FOREACH_STATUS_OKAY(PDUS_DEFINE) diff --git a/drivers/sensor/wsen/wsen_pdus/wsen_pdus.h b/drivers/sensor/wsen/wsen_pdus/wsen_pdus.h deleted file mode 100644 index 6fb9f1f05952..000000000000 --- a/drivers/sensor/wsen/wsen_pdus/wsen_pdus.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_DRIVERS_SENSOR_WSEN_PDUS_WSEN_PDUS_H_ -#define ZEPHYR_DRIVERS_SENSOR_WSEN_PDUS_WSEN_PDUS_H_ - -#include -#include - -#include - -#include "WSEN_PDUS_25131308XXX01.h" - -#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) -#include -#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */ - -struct pdus_data { - /* WE sensor interface configuration */ - WE_sensorInterface_t sensor_interface; - - /* Last pressure sample */ - float pressure_k_pa; - - /* Last temperature sample */ - float temperature_deg_c; -}; - -struct pdus_config { - union { -#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) - const struct i2c_dt_spec i2c; -#endif - } bus_cfg; - - PDUS_SensorType_t sensor_type; -}; - -int pdus_i2c_init(const struct device *dev); - -#endif /* ZEPHYR_DRIVERS_SENSOR_WSEN_PDUS_WSEN_PDUS_H_ */ diff --git a/dts/bindings/sensor/we,wsen-pdus.yaml b/dts/bindings/sensor/we,wsen-pdus.yaml deleted file mode 100644 index 526f1fa450f3..000000000000 --- a/dts/bindings/sensor/we,wsen-pdus.yaml +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG -# SPDX-License-Identifier: Apache-2.0 - -description: | - Würth Elektronik WSEN-PDUS differential pressure sensor - -compatible: "we,wsen-pdus" - -include: [sensor-device.yaml, i2c-device.yaml] - -properties: - sensor-type: - type: int - required: true - enum: - - 0 # order code 2513130810001, range = -0.1 to +0.1 kPa - - 1 # order code 2513130810101, range = -1 to +1 kPa - - 2 # order code 2513130810201, range = -10 to +10 kPa - - 3 # order code 2513130810301, range = 0 to 100 kPa - - 4 # order code 2513130810401, range = -100 to +1000 kPa - description: PDUS sensor product variant (pressure measurement range). diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index 0d11cae24a4e..853e3c722f84 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -683,12 +683,6 @@ test_i2c_s11059: s11059@64 { integration-time = <546000>; }; -test_i2c_wsen_pdus: wsen_pdus@65 { - compatible = "we,wsen-pdus"; - reg = <0x65>; - sensor-type = <3>; -}; - test_i2c_veml7700: veml7700@66 { compatible = "vishay,veml7700"; reg = <0x66>; From 6085fbdd6fa48d1aa0d27d046734b6f7b42ee3ae Mon Sep 17 00:00:00 2001 From: Wajdi ELMuhtadi Date: Fri, 1 Sep 2023 11:35:50 +0200 Subject: [PATCH 05/14] drivers: sensor: wsen_tids: remove wsen_tids driver Remove wsen_tids since the hal update is no longer compatible with this version. Signed-off-by: Wajdi ELMuhtadi --- drivers/sensor/wsen/CMakeLists.txt | 1 - drivers/sensor/wsen/Kconfig | 1 - drivers/sensor/wsen/wsen_tids/CMakeLists.txt | 7 - drivers/sensor/wsen/wsen_tids/Kconfig | 53 ---- drivers/sensor/wsen/wsen_tids/wsen_tids.c | 229 ----------------- drivers/sensor/wsen/wsen_tids/wsen_tids.h | 77 ------ .../sensor/wsen/wsen_tids/wsen_tids_trigger.c | 243 ------------------ dts/bindings/sensor/we,wsen-tids.yaml | 37 --- tests/drivers/build_all/sensor/i2c.dtsi | 9 - .../sensor/sensors_trigger_global.conf | 1 - .../sensor/sensors_trigger_none.conf | 1 - .../build_all/sensor/sensors_trigger_own.conf | 1 - 12 files changed, 660 deletions(-) delete mode 100644 drivers/sensor/wsen/wsen_tids/CMakeLists.txt delete mode 100644 drivers/sensor/wsen/wsen_tids/Kconfig delete mode 100644 drivers/sensor/wsen/wsen_tids/wsen_tids.c delete mode 100644 drivers/sensor/wsen/wsen_tids/wsen_tids.h delete mode 100644 drivers/sensor/wsen/wsen_tids/wsen_tids_trigger.c delete mode 100644 dts/bindings/sensor/we,wsen-tids.yaml diff --git a/drivers/sensor/wsen/CMakeLists.txt b/drivers/sensor/wsen/CMakeLists.txt index 58d9868e47b9..eadffcbb2bfd 100644 --- a/drivers/sensor/wsen/CMakeLists.txt +++ b/drivers/sensor/wsen/CMakeLists.txt @@ -2,5 +2,4 @@ # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start -add_subdirectory_ifdef(CONFIG_WSEN_TIDS wsen_tids) # zephyr-keep-sorted-stop diff --git a/drivers/sensor/wsen/Kconfig b/drivers/sensor/wsen/Kconfig index ac443e731134..eadffcbb2bfd 100644 --- a/drivers/sensor/wsen/Kconfig +++ b/drivers/sensor/wsen/Kconfig @@ -2,5 +2,4 @@ # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start -source "drivers/sensor/wsen/wsen_tids/Kconfig" # zephyr-keep-sorted-stop diff --git a/drivers/sensor/wsen/wsen_tids/CMakeLists.txt b/drivers/sensor/wsen/wsen_tids/CMakeLists.txt deleted file mode 100644 index 52019917bd48..000000000000 --- a/drivers/sensor/wsen/wsen_tids/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library() - -zephyr_library_sources(wsen_tids.c) -zephyr_library_sources_ifdef(CONFIG_WSEN_TIDS_TRIGGER wsen_tids_trigger.c) diff --git a/drivers/sensor/wsen/wsen_tids/Kconfig b/drivers/sensor/wsen/wsen_tids/Kconfig deleted file mode 100644 index 764352fb7bcc..000000000000 --- a/drivers/sensor/wsen/wsen_tids/Kconfig +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG -# SPDX-License-Identifier: Apache-2.0 - -menuconfig WSEN_TIDS - bool "WSEN-TIDS temperature sensor" - default y - depends on DT_HAS_WE_WSEN_TIDS_ENABLED - select I2C if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_TIDS),i2c) - select HAS_WESENSORS - help - Enable driver for the WSEN-TIDS I2C-based temperature sensor. - -if WSEN_TIDS - -choice WSEN_TIDS_TRIGGER_MODE - prompt "Trigger mode" - default WSEN_TIDS_TRIGGER_NONE - help - Specify the type of triggering to be used by the driver. - -config WSEN_TIDS_TRIGGER_NONE - bool "No trigger" - -config WSEN_TIDS_TRIGGER_GLOBAL_THREAD - bool "Use global thread" - depends on GPIO - select WSEN_TIDS_TRIGGER - -config WSEN_TIDS_TRIGGER_OWN_THREAD - bool "Use own thread" - depends on GPIO - select WSEN_TIDS_TRIGGER - -endchoice # WSEN_TIDS_TRIGGER_MODE - -config WSEN_TIDS_TRIGGER - bool - -config WSEN_TIDS_THREAD_PRIORITY - int "Thread priority" - depends on WSEN_TIDS_TRIGGER_OWN_THREAD - default 10 - help - Priority of thread used by the driver to handle interrupts. - -config WSEN_TIDS_THREAD_STACK_SIZE - int "Thread stack size" - depends on WSEN_TIDS_TRIGGER_OWN_THREAD - default 1024 - help - Stack size of thread used by the driver to handle interrupts. - -endif # WSEN_TIDS diff --git a/drivers/sensor/wsen/wsen_tids/wsen_tids.c b/drivers/sensor/wsen/wsen_tids/wsen_tids.c deleted file mode 100644 index ad397706e741..000000000000 --- a/drivers/sensor/wsen/wsen_tids/wsen_tids.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT we_wsen_tids - -#include - -#include -#include -#include - -#include "wsen_tids.h" - -LOG_MODULE_REGISTER(WSEN_TIDS, CONFIG_SENSOR_LOG_LEVEL); - -/* - * List of supported output data rates. Index into this list is used as - * argument for TIDS_setOutputDataRate() - */ -static const int32_t tids_odr_list[] = { - 25, - 50, - 100, - 200, -}; - -static int tids_sample_fetch(const struct device *dev, enum sensor_channel chan) -{ - struct tids_data *data = dev->data; - int16_t raw_temperature; - - if ((chan != SENSOR_CHAN_ALL) && (chan != SENSOR_CHAN_AMBIENT_TEMP)) { - LOG_ERR("Fetching is not supported on channel %d.", chan); - return -EINVAL; - } - - if (TIDS_getRawTemperature(&data->sensor_interface, &raw_temperature) != WE_SUCCESS) { - LOG_ERR("Failed to fetch data sample"); - return -EIO; - } - - data->temperature = raw_temperature; - - return 0; -} - -static int tids_channel_get(const struct device *dev, enum sensor_channel chan, - struct sensor_value *val) -{ - struct tids_data *data = dev->data; - - if (chan == SENSOR_CHAN_AMBIENT_TEMP) { - /* Convert temperature from 0.01 degrees Celsius to degrees Celsius */ - val->val1 = data->temperature / 100; - val->val2 = ((int32_t)data->temperature % 100) * (1000000 / 100); - } else { - return -ENOTSUP; - } - - return 0; -} - -/* Set output data rate. See tids_odr_list for allowed values. */ -static int tids_odr_set(const struct device *dev, const struct sensor_value *odr) -{ - struct tids_data *data = dev->data; - int odr_index; - - for (odr_index = 0; odr_index < ARRAY_SIZE(tids_odr_list); odr_index++) { - if (odr->val1 == tids_odr_list[odr_index] && odr->val2 == 0) { - break; - } - } - - if (odr_index == ARRAY_SIZE(tids_odr_list)) { - /* ODR not allowed (was not found in tids_odr_list) */ - LOG_ERR("Bad sampling frequency %d.%d", odr->val1, abs(odr->val2)); - return -EINVAL; - } - - if (TIDS_setOutputDataRate(&data->sensor_interface, (TIDS_outputDataRate_t)odr_index) != - WE_SUCCESS) { - LOG_ERR("Failed to set output data rate"); - return -EIO; - } - - return 0; -} - -static int tids_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() is not supported on channel %d.", chan); - return -ENOTSUP; - } - - switch (attr) { - case SENSOR_ATTR_SAMPLING_FREQUENCY: - return tids_odr_set(dev, val); - -#ifdef CONFIG_WSEN_TIDS_TRIGGER - case SENSOR_ATTR_LOWER_THRESH: - return tids_threshold_set(dev, val, false); - - case SENSOR_ATTR_UPPER_THRESH: - return tids_threshold_set(dev, val, true); -#endif /* CONFIG_WSEN_TIDS_TRIGGER */ - - default: - LOG_ERR("Operation not supported."); - return -ENOTSUP; - } -} - -static const struct sensor_driver_api tids_driver_api = { - .attr_set = tids_attr_set, -#if CONFIG_WSEN_TIDS_TRIGGER - .trigger_set = tids_trigger_set, -#endif - .sample_fetch = tids_sample_fetch, - .channel_get = tids_channel_get, -}; - -static int tids_init(const struct device *dev) -{ - const struct tids_config *const config = dev->config; - struct tids_data *data = dev->data; - int status; - uint8_t device_id; - struct sensor_value odr; - - /* Initialize WE sensor interface */ - TIDS_getDefaultInterface(&data->sensor_interface); - data->sensor_interface.interfaceType = WE_i2c; - data->sensor_interface.handle = (void *)&config->bus_cfg.i2c; - - /* First communication test - check device ID */ - if (TIDS_getDeviceID(&data->sensor_interface, &device_id) != WE_SUCCESS) { - LOG_ERR("Failed to read device ID."); - return -EIO; - } - - if (device_id != TIDS_DEVICE_ID_VALUE) { - LOG_ERR("Invalid device ID 0x%x.", device_id); - return -EIO; - } - - /* Reset the sensor with an arbitrary off time of 5 us */ - TIDS_softReset(&data->sensor_interface, TIDS_enable); - k_sleep(K_USEC(5)); - TIDS_softReset(&data->sensor_interface, TIDS_disable); - - odr.val1 = tids_odr_list[config->odr]; - odr.val2 = 0; - status = tids_odr_set(dev, &odr); - if (status < 0) { - LOG_ERR("Failed to set output data rate."); - return status; - } - - if (TIDS_enableBlockDataUpdate(&data->sensor_interface, TIDS_enable) != WE_SUCCESS) { - LOG_ERR("Failed to enable block data update."); - return -EIO; - } - - if (TIDS_enableContinuousMode(&data->sensor_interface, TIDS_enable) != WE_SUCCESS) { - LOG_ERR("Failed to enable continuous mode."); - return -EIO; - } - -#ifdef CONFIG_WSEN_TIDS_TRIGGER - status = tids_init_interrupt(dev); - if (status < 0) { - LOG_ERR("Failed to initialize threshold interrupt."); - return status; - } -#endif - - return 0; -} - -#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0 -#warning "TIDS driver enabled without any devices" -#endif - -/* - * Device creation macros - */ - -#define TIDS_DEVICE_INIT(inst) \ - SENSOR_DEVICE_DT_INST_DEFINE(inst, \ - tids_init, \ - NULL, \ - &tids_data_##inst, \ - &tids_config_##inst, \ - POST_KERNEL, \ - CONFIG_SENSOR_INIT_PRIORITY, \ - &tids_driver_api); - -#ifdef CONFIG_WSEN_TIDS_TRIGGER -#define TIDS_CFG_IRQ(inst) \ - .gpio_threshold = GPIO_DT_SPEC_INST_GET(inst, int_gpios), \ - .high_threshold = DT_INST_PROP(inst, temp_high_threshold), \ - .low_threshold = DT_INST_PROP(inst, temp_low_threshold) -#else -#define TIDS_CFG_IRQ(inst) -#endif /* CONFIG_WSEN_TIDS_TRIGGER */ - -/* - * Main instantiation macro. - */ -#define TIDS_DEFINE(inst) \ - static struct tids_data tids_data_##inst; \ - static const struct tids_config tids_config_##inst = \ - { \ - .bus_cfg = { \ - .i2c = I2C_DT_SPEC_INST_GET(inst), \ - }, \ - .odr = (TIDS_outputDataRate_t)(DT_INST_ENUM_IDX(inst, odr)), \ - COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, int_gpios), \ - (TIDS_CFG_IRQ(inst)), ()) \ - }; \ - TIDS_DEVICE_INIT(inst) - -DT_INST_FOREACH_STATUS_OKAY(TIDS_DEFINE) diff --git a/drivers/sensor/wsen/wsen_tids/wsen_tids.h b/drivers/sensor/wsen/wsen_tids/wsen_tids.h deleted file mode 100644 index eae6c465ca25..000000000000 --- a/drivers/sensor/wsen/wsen_tids/wsen_tids.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_DRIVERS_SENSOR_WSEN_TIDS_WSEN_TIDS_H_ -#define ZEPHYR_DRIVERS_SENSOR_WSEN_TIDS_WSEN_TIDS_H_ - -#include -#include - -#include - -#include "WSEN_TIDS_2521020222501.h" - -#include - -struct tids_data { - /* WE sensor interface configuration */ - WE_sensorInterface_t sensor_interface; - - /* Last temperature sample */ - int16_t temperature; - -#ifdef CONFIG_WSEN_TIDS_TRIGGER - const struct device *dev; - - /* Callback for high/low limit interrupts */ - struct gpio_callback threshold_cb; - - const struct sensor_trigger *threshold_trigger; - sensor_trigger_handler_t threshold_handler; - -#if defined(CONFIG_WSEN_TIDS_TRIGGER_OWN_THREAD) - K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_WSEN_TIDS_THREAD_STACK_SIZE); - struct k_thread thread; - struct k_sem threshold_sem; -#elif defined(CONFIG_WSEN_TIDS_TRIGGER_GLOBAL_THREAD) - struct k_work work; -#endif -#endif /* CONFIG_WSEN_TIDS_TRIGGER */ -}; - -struct tids_config { - union { - const struct i2c_dt_spec i2c; - } bus_cfg; - - /* Output data rate */ - const TIDS_outputDataRate_t odr; - -#ifdef CONFIG_WSEN_TIDS_TRIGGER - /* Interrupt pin used for high and low limit interrupt events */ - const struct gpio_dt_spec gpio_threshold; - - /* High temperature interrupt threshold */ - const int high_threshold; - - /* Low temperature interrupt threshold */ - const int low_threshold; -#endif -}; - -#ifdef CONFIG_WSEN_TIDS_TRIGGER -int tids_trigger_set(const struct device *dev, const struct sensor_trigger *trig, - sensor_trigger_handler_t handler); - -int tids_threshold_set(const struct device *dev, const struct sensor_value *thresh_value, - bool upper); - -int tids_init_interrupt(const struct device *dev); -#endif - -int tids_i2c_init(const struct device *dev); - -#endif /* ZEPHYR_DRIVERS_SENSOR_WSEN_TIDS_WSEN_TIDS_H_ */ diff --git a/drivers/sensor/wsen/wsen_tids/wsen_tids_trigger.c b/drivers/sensor/wsen/wsen_tids/wsen_tids_trigger.c deleted file mode 100644 index d2ed4d91fefc..000000000000 --- a/drivers/sensor/wsen/wsen_tids/wsen_tids_trigger.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT we_wsen_tids - -#include - -#include - -#include "wsen_tids.h" - -LOG_MODULE_DECLARE(WSEN_TIDS, CONFIG_SENSOR_LOG_LEVEL); - -#define THRESHOLD_TEMPERATURE2REGISTER_OFFSET (double)63. -#define THRESHOLD_TEMPERATURE2REGISTER_STEP (double)0.64 - -/* Enable/disable threshold interrupt handling */ -static inline void tids_setup_threshold_interrupt(const struct device *dev, bool enable) -{ - const struct tids_config *cfg = dev->config; - unsigned int flags = enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE; - - gpio_pin_interrupt_configure_dt(&cfg->gpio_threshold, flags); -} - -/* - * Is called when a "threshold exceeded" interrupt occurred. Triggers - * asynchronous processing of the interrupt in tids_process_threshold_interrupt(). - */ -static void tids_handle_threshold_interrupt(const struct device *dev) -{ - struct tids_data *data = dev->data; - - /* Disable interrupt handling until the interrupt has been processed */ - tids_setup_threshold_interrupt(dev, false); - -#if defined(CONFIG_WSEN_TIDS_TRIGGER_OWN_THREAD) - k_sem_give(&data->threshold_sem); -#elif defined(CONFIG_WSEN_TIDS_TRIGGER_GLOBAL_THREAD) - k_work_submit(&data->work); -#endif -} - -/* - * Is called after a "threshold exceeded" interrupt occurred. - * Checks the sensor's status register for the limit exceeded flags and - * calls the trigger handler if one of the flags is set. - */ -static void tids_process_threshold_interrupt(const struct device *dev) -{ - struct tids_data *data = dev->data; - TIDS_status_t status; - - /* - * Read the sensor's status register - this also causes the interrupt pin - * to be de-asserted - */ - if (TIDS_getStatusRegister(&data->sensor_interface, &status) != WE_SUCCESS) { - LOG_ERR("Failed to read status register"); - return; - } - - if (data->threshold_handler != NULL && - (status.upperLimitExceeded != 0 || status.lowerLimitExceeded != 0)) { - data->threshold_handler(dev, data->threshold_trigger); - } - - if (data->threshold_handler != NULL) { - tids_setup_threshold_interrupt(dev, true); - } -} - -/* Enables/disables processing of the "threshold exceeded" interrupt. */ -int tids_trigger_set(const struct device *dev, const struct sensor_trigger *trig, - sensor_trigger_handler_t handler) -{ - struct tids_data *data = dev->data; - const struct tids_config *cfg = dev->config; - - if (trig->type != SENSOR_TRIG_THRESHOLD) { - LOG_ERR("Unsupported sensor trigger"); - return -ENOTSUP; - } - - tids_setup_threshold_interrupt(dev, false); - - data->threshold_handler = handler; - if (handler == NULL) { - return 0; - } - - data->threshold_trigger = trig; - - tids_setup_threshold_interrupt(dev, true); - - /* - * If threshold interrupt is active we probably won't get the rising edge, so - * invoke the callback manually. - */ - if (gpio_pin_get_dt(&cfg->gpio_threshold) > 0) { - tids_handle_threshold_interrupt(dev); - } - - return 0; -} - -static void tids_threshold_callback(const struct device *dev, struct gpio_callback *cb, - uint32_t pins) -{ - struct tids_data *data = CONTAINER_OF(cb, struct tids_data, threshold_cb); - - ARG_UNUSED(pins); - - tids_handle_threshold_interrupt(data->dev); -} - -#ifdef CONFIG_WSEN_TIDS_TRIGGER_OWN_THREAD -static void tids_thread(void *p1, void *p2, void *p3) -{ - ARG_UNUSED(p2); - ARG_UNUSED(p3); - - struct tids_data *tids = p1; - - while (true) { - k_sem_take(&tids->threshold_sem, K_FOREVER); - tids_process_threshold_interrupt(tids->dev); - } -} -#endif /* CONFIG_WSEN_TIDS_TRIGGER_OWN_THREAD */ - -#ifdef CONFIG_WSEN_TIDS_TRIGGER_GLOBAL_THREAD -static void tids_work_cb(struct k_work *work) -{ - struct tids_data *tids = CONTAINER_OF(work, struct tids_data, work); - - tids_process_threshold_interrupt(tids->dev); -} -#endif /* CONFIG_WSEN_TIDS_TRIGGER_GLOBAL_THREAD */ - -int tids_threshold_set(const struct device *dev, const struct sensor_value *thresh_value, - bool upper) -{ - struct tids_data *data = dev->data; - double thresh = (sensor_value_to_double(thresh_value) / THRESHOLD_TEMPERATURE2REGISTER_STEP) - + THRESHOLD_TEMPERATURE2REGISTER_OFFSET; - - if (thresh < 0) { - thresh = 0; - } else if (thresh > 255) { - thresh = 255; - } - - if (upper) { - if (TIDS_setTempHighLimit(&data->sensor_interface, (uint8_t)thresh) != WE_SUCCESS) { - LOG_ERR("Failed to set high temperature threshold to %d.%d (%d).", - thresh_value->val1, abs(thresh_value->val2), (uint8_t)thresh); - return -EIO; - } - } else { - if (TIDS_setTempLowLimit(&data->sensor_interface, (uint8_t)thresh) != WE_SUCCESS) { - LOG_ERR("Failed to set low temperature threshold to %d.%d (%d).", - thresh_value->val1, abs(thresh_value->val2), (uint8_t)thresh); - return -EIO; - } - } - - return 0; -} - -int tids_init_interrupt(const struct device *dev) -{ - struct tids_data *data = dev->data; - const struct tids_config *cfg = dev->config; - int status; - struct sensor_value upper_limit; - struct sensor_value lower_limit; - - if (cfg->gpio_threshold.port == NULL) { - LOG_ERR("int-gpios is not defined in the device tree."); - return -EINVAL; - } - - if (!gpio_is_ready_dt(&cfg->gpio_threshold)) { - LOG_ERR("Device %s is not ready", cfg->gpio_threshold.port->name); - return -ENODEV; - } - - data->dev = dev; - - /* Setup threshold gpio interrupt */ - status = gpio_pin_configure_dt(&cfg->gpio_threshold, GPIO_INPUT); - if (status < 0) { - LOG_ERR("Failed to configure %s.%02u", cfg->gpio_threshold.port->name, - cfg->gpio_threshold.pin); - return status; - } - - gpio_init_callback(&data->threshold_cb, tids_threshold_callback, - BIT(cfg->gpio_threshold.pin)); - - status = gpio_add_callback(cfg->gpio_threshold.port, &data->threshold_cb); - if (status < 0) { - LOG_ERR("Failed to set gpio callback."); - return status; - } - - /* - * Enable interrupt on high/low temperature (interrupt generation is enabled if at - * least one threshold is non-zero) - */ - upper_limit.val1 = cfg->high_threshold; - upper_limit.val2 = 0; - lower_limit.val1 = cfg->low_threshold; - lower_limit.val2 = 0; - - status = tids_threshold_set(dev, &upper_limit, true); - if (status < 0) { - return status; - } - - status = tids_threshold_set(dev, &lower_limit, false); - if (status < 0) { - return status; - } - -#if defined(CONFIG_WSEN_TIDS_TRIGGER_OWN_THREAD) - k_sem_init(&data->threshold_sem, 0, K_SEM_MAX_LIMIT); - - k_thread_create(&data->thread, data->thread_stack, CONFIG_WSEN_TIDS_THREAD_STACK_SIZE, - tids_thread, data, NULL, NULL, - K_PRIO_COOP(CONFIG_WSEN_TIDS_THREAD_PRIORITY), 0, K_NO_WAIT); -#elif defined(CONFIG_WSEN_TIDS_TRIGGER_GLOBAL_THREAD) - data->work.handler = tids_work_cb; -#endif - - tids_setup_threshold_interrupt(dev, true); - - return 0; -} diff --git a/dts/bindings/sensor/we,wsen-tids.yaml b/dts/bindings/sensor/we,wsen-tids.yaml deleted file mode 100644 index 202ff994597b..000000000000 --- a/dts/bindings/sensor/we,wsen-tids.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG -# SPDX-License-Identifier: Apache-2.0 - -description: | - Würth Elektronik WSEN-TIDS temperature sensor - -compatible: "we,wsen-tids" - -include: [sensor-device.yaml, i2c-device.yaml] - -properties: - int-gpios: - type: phandle-array - description: Threshold interrupt pin. - Interrupt is active low by default. - - odr: - type: int - required: true - enum: - - 25 - - 50 - - 100 - - 200 - description: | - Sensor output data rate expressed in samples per second. - Data rates supported by the chip are 25, 50, 100 and 200. - - temp-high-threshold: - type: int - description: | - Threshold for temperature high limit interrupt event. - - temp-low-threshold: - type: int - description: | - Threshold for temperature low limit interrupt event. diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index 853e3c722f84..5fa516d018f1 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -647,15 +647,6 @@ test_i2c_akm09918c: akm09918c@5f { reg = <0x5f>; }; -test_i2c_wsen_tids: wsen_tids@60 { - compatible = "we,wsen-tids"; - reg = <0x60>; - int-gpios = <&test_gpio 0 0>; - odr = <25>; - temp-high-threshold = <0>; - temp-low-threshold = <0>; -}; - test_i2c_vl53l1x: vl53l1x@61 { compatible = "st,vl53l1x"; reg = <0x61>; diff --git a/tests/drivers/build_all/sensor/sensors_trigger_global.conf b/tests/drivers/build_all/sensor/sensors_trigger_global.conf index 57ed749751d4..5a2164c327bd 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_global.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_global.conf @@ -63,4 +63,3 @@ CONFIG_TMP007_TRIGGER_GLOBAL_THREAD=y CONFIG_TSL2540_TRIGGER_GLOBAL_THREAD=y CONFIG_TSL2591_TRIGGER_GLOBAL_THREAD=y CONFIG_VCNL4040_TRIGGER_GLOBAL_THREAD=y -CONFIG_WSEN_TIDS_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 87a6bed1e25d..3edefcd9640b 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_none.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_none.conf @@ -63,4 +63,3 @@ CONFIG_TMP007_TRIGGER_NONE=y CONFIG_TSL2540_TRIGGER_NONE=y CONFIG_TSL2591_TRIGGER_NONE=y CONFIG_VCNL4040_TRIGGER_NONE=y -CONFIG_WSEN_TIDS_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 0a21780626c1..7c7eb4bde5cb 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_own.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_own.conf @@ -60,4 +60,3 @@ CONFIG_TMP007_TRIGGER_OWN_THREAD=y CONFIG_TSL2540_TRIGGER_OWN_THREAD=y CONFIG_TSL2591_TRIGGER_OWN_THREAD=y CONFIG_VCNL4040_TRIGGER_OWN_THREAD=y -CONFIG_WSEN_TIDS_TRIGGER_OWN_THREAD=y From 2d4ed3f24e178a22201ed8a67906ce9c1515a3ef Mon Sep 17 00:00:00 2001 From: Wajdi ELMuhtadi Date: Thu, 7 Sep 2023 15:22:37 +0200 Subject: [PATCH 06/14] manifest: hal_wurthelektronik: update to latest Update hal_wurthelektronik to include latest sensor core drivers. Signed-off-by: Wajdi ELMuhtadi --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index cd470ea0ea3a..7832cd71c8e4 100644 --- a/west.yml +++ b/west.yml @@ -248,7 +248,7 @@ manifest: groups: - hal - name: hal_wurthelektronik - revision: e5bcb2eac1bb9639ce13b4dafc78eb254e014342 + revision: e3e2797b224fc48fdef1bc3e5a12a7c73108bba2 path: modules/hal/wurthelektronik groups: - hal From 00887bbbffc24be00931dd182fff88335003a68c Mon Sep 17 00:00:00 2001 From: Wajdi ELMuhtadi Date: Mon, 4 Sep 2023 09:09:53 +0200 Subject: [PATCH 07/14] drivers: sensor: wsen_hids_2525020210002: add sensor driver Add wsen_hids_2525020210002 driver with the corrected name and compatibility with the hal update as well as added new features. Signed-off-by: Wajdi ELMuhtadi --- drivers/sensor/wsen/CMakeLists.txt | 1 + drivers/sensor/wsen/Kconfig | 1 + .../wsen_hids_2525020210002/CMakeLists.txt | 6 + .../wsen/wsen_hids_2525020210002/Kconfig | 11 + .../wsen_hids_2525020210002.c | 252 ++++++++++++++++++ .../wsen_hids_2525020210002.h | 47 ++++ .../sensor/we,wsen-hids-2525020210002.yaml | 41 +++ .../drivers/sensor/wsen_hids_2525020210002.h | 47 ++++ tests/drivers/build_all/sensor/i2c.dtsi | 6 + 9 files changed, 412 insertions(+) create mode 100644 drivers/sensor/wsen/wsen_hids_2525020210002/CMakeLists.txt create mode 100644 drivers/sensor/wsen/wsen_hids_2525020210002/Kconfig create mode 100644 drivers/sensor/wsen/wsen_hids_2525020210002/wsen_hids_2525020210002.c create mode 100644 drivers/sensor/wsen/wsen_hids_2525020210002/wsen_hids_2525020210002.h create mode 100644 dts/bindings/sensor/we,wsen-hids-2525020210002.yaml create mode 100644 include/zephyr/drivers/sensor/wsen_hids_2525020210002.h diff --git a/drivers/sensor/wsen/CMakeLists.txt b/drivers/sensor/wsen/CMakeLists.txt index eadffcbb2bfd..5429320954de 100644 --- a/drivers/sensor/wsen/CMakeLists.txt +++ b/drivers/sensor/wsen/CMakeLists.txt @@ -2,4 +2,5 @@ # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start +add_subdirectory_ifdef(CONFIG_WSEN_HIDS_2525020210002 wsen_hids_2525020210002) # zephyr-keep-sorted-stop diff --git a/drivers/sensor/wsen/Kconfig b/drivers/sensor/wsen/Kconfig index eadffcbb2bfd..727a995af6b6 100644 --- a/drivers/sensor/wsen/Kconfig +++ b/drivers/sensor/wsen/Kconfig @@ -2,4 +2,5 @@ # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start +source "drivers/sensor/wsen/wsen_hids_2525020210002/Kconfig" # zephyr-keep-sorted-stop diff --git a/drivers/sensor/wsen/wsen_hids_2525020210002/CMakeLists.txt b/drivers/sensor/wsen/wsen_hids_2525020210002/CMakeLists.txt new file mode 100644 index 000000000000..904b9ef5aa3a --- /dev/null +++ b/drivers/sensor/wsen/wsen_hids_2525020210002/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(wsen_hids_2525020210002.c) diff --git a/drivers/sensor/wsen/wsen_hids_2525020210002/Kconfig b/drivers/sensor/wsen/wsen_hids_2525020210002/Kconfig new file mode 100644 index 000000000000..92b8a66c55bc --- /dev/null +++ b/drivers/sensor/wsen/wsen_hids_2525020210002/Kconfig @@ -0,0 +1,11 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +config WSEN_HIDS_2525020210002 + bool "WSEN-HIDS-2525020210002 humidity sensor" + default y + depends on DT_HAS_WE_WSEN_HIDS_2525020210002_ENABLED + select I2C + select HAS_WESENSORS + help + Enable driver for the WSEN-HIDS-2525020210002 I2C-based humidity sensor. diff --git a/drivers/sensor/wsen/wsen_hids_2525020210002/wsen_hids_2525020210002.c b/drivers/sensor/wsen/wsen_hids_2525020210002/wsen_hids_2525020210002.c new file mode 100644 index 000000000000..a0c3d59ec619 --- /dev/null +++ b/drivers/sensor/wsen/wsen_hids_2525020210002/wsen_hids_2525020210002.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT we_wsen_hids_2525020210002 + +#include + +#include +#include +#include + +#include "wsen_hids_2525020210002.h" + +LOG_MODULE_REGISTER(WSEN_HIDS_2525020210002, CONFIG_SENSOR_LOG_LEVEL); + +static const hids_measureCmd_t precision_cmds[] = {HIDS_MEASURE_LPM, HIDS_MEASURE_MPM, + HIDS_MEASURE_HPM}; + +static const hids_measureCmd_t heater_cmds[] = {HIDS_HEATER_200_MW_01_S, HIDS_HEATER_200_MW_100_MS, + HIDS_HEATER_110_MW_01_S, HIDS_HEATER_110_MW_100_MS, + HIDS_HEATER_20_MW_01_S, HIDS_HEATER_20_MW_100_MS}; + +static int hids_2525020210002_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + struct hids_2525020210002_data *data = dev->data; + + hids_measureCmd_t cmd; + + int32_t raw_temperature; + int32_t raw_humidity; + + switch (chan) { + case SENSOR_CHAN_ALL: + case SENSOR_CHAN_AMBIENT_TEMP: + case SENSOR_CHAN_HUMIDITY: + break; + default: + LOG_ERR("Fetching is not supported on channel %d.", chan); + return -ENOTSUP; + } + + if (data->sensor_precision == hids_2525020210002_precision_High && + data->sensor_heater != hids_2525020210002_heater_Off) { + cmd = heater_cmds[data->sensor_heater - 1]; + } else { + cmd = precision_cmds[data->sensor_precision]; + } + + if (HIDS_Sensor_Measure_Raw(&data->sensor_interface, cmd, &raw_temperature, + &raw_humidity) != WE_SUCCESS) { + LOG_ERR("Failed to fetch data sample"); + return -EIO; + } + + switch (chan) { + case SENSOR_CHAN_ALL: + data->temperature = raw_temperature; + data->humidity = raw_humidity; + break; + case SENSOR_CHAN_AMBIENT_TEMP: + data->temperature = raw_temperature; + break; + case SENSOR_CHAN_HUMIDITY: + data->humidity = raw_humidity; + break; + default: + return -ENOTSUP; + } + + return 0; +} + +static int hids_2525020210002_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct hids_2525020210002_data *data = dev->data; + + switch (chan) { + case SENSOR_CHAN_AMBIENT_TEMP: + val->val1 = data->temperature / 1000; + val->val2 = ((int32_t)data->temperature % 1000) * (1000000 / 1000); + break; + case SENSOR_CHAN_HUMIDITY: + val->val1 = data->humidity / 1000; + val->val2 = ((int32_t)data->humidity % 1000) * (1000000 / 1000); + break; + default: + LOG_ERR("Channel not supported %d", chan); + return -ENOTSUP; + } + + return 0; +} + +/* Set precision configuration. */ +static int hids_2525020210002_precision_set(const struct device *dev, + const struct sensor_value *precision) +{ + struct hids_2525020210002_data *data = dev->data; + + if (precision->val1 < hids_2525020210002_precision_Low || + precision->val1 > hids_2525020210002_precision_High || precision->val2 != 0) { + LOG_ERR("Bad precision configuration %d", precision->val1); + return -EINVAL; + } + + data->sensor_precision = (hids_2525020210002_precision_t)precision->val1; + + return 0; +} + +/* Set heater option. */ +static int hids_2525020210002_heater_set(const struct device *dev, + const struct sensor_value *heater) +{ + struct hids_2525020210002_data *data = dev->data; + + if (heater->val1 < hids_2525020210002_heater_Off || + heater->val1 > hids_2525020210002_heater_On_20mW_100ms || heater->val2 != 0) { + LOG_ERR("Bad heater option %d", heater->val1); + return -EINVAL; + } + + data->sensor_heater = (hids_2525020210002_heater_t)heater->val1; + + return 0; +} + +static int hids_2525020210002_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() is not supported on channel %d.", chan); + return -ENOTSUP; + } + + switch ((int)attr) { + case SENSOR_ATTR_WSEN_HIDS_2525020210002_PRECISION: + return hids_2525020210002_precision_set(dev, val); + case SENSOR_ATTR_WSEN_HIDS_2525020210002_HEATER: + return hids_2525020210002_heater_set(dev, val); + default: + LOG_ERR("Operation not supported."); + return -ENOTSUP; + } + + return 0; +} + +static int hids_2525020210002_attr_get(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, struct sensor_value *val) +{ + struct hids_2525020210002_data *data = dev->data; + + if (chan != SENSOR_CHAN_ALL) { + LOG_WRN("attr_get() is not supported on channel %d.", chan); + return -ENOTSUP; + } + + if (val == NULL) { + LOG_WRN("address of passed value is NULL."); + return -EFAULT; + } + + switch ((int)attr) { + case SENSOR_ATTR_WSEN_HIDS_2525020210002_PRECISION: + val->val1 = data->sensor_precision; + val->val2 = 0; + break; + case SENSOR_ATTR_WSEN_HIDS_2525020210002_HEATER: + val->val1 = data->sensor_heater; + val->val2 = 0; + break; + default: + LOG_ERR("Operation not supported."); + return -ENOTSUP; + } + + return 0; +} + +static const struct sensor_driver_api hids_2525020210002_driver_api = { + .attr_set = hids_2525020210002_attr_set, + .attr_get = hids_2525020210002_attr_get, + .sample_fetch = hids_2525020210002_sample_fetch, + .channel_get = hids_2525020210002_channel_get, +}; + +static int hids_2525020210002_init(const struct device *dev) +{ + const struct hids_2525020210002_config *const config = dev->config; + struct hids_2525020210002_data *data = dev->data; + struct sensor_value precision, heater; + + /* Initialize WE sensor interface */ + HIDS_Get_Default_Interface(&data->sensor_interface); + data->sensor_interface.interfaceType = WE_i2c; + if (!i2c_is_ready_dt(&config->bus_cfg.i2c)) { + LOG_ERR("I2C bus device not ready"); + return -ENODEV; + } + data->sensor_interface.handle = (void *)&config->bus_cfg.i2c; + + /* First communication test - check device ID */ + if (HIDS_Sensor_Init(&data->sensor_interface) != WE_SUCCESS) { + LOG_ERR("Failed to read device ID."); + return -EIO; + } + + precision.val1 = config->precision; + precision.val2 = 0; + + if (hids_2525020210002_precision_set(dev, &precision) < 0) { + LOG_ERR("Failed to set precision configuration."); + return -EIO; + } + + heater.val1 = config->heater; + heater.val2 = 0; + + if (hids_2525020210002_heater_set(dev, &heater) < 0) { + LOG_ERR("Failed to set heater option."); + return -EIO; + } + + return 0; +} + +#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0 +#warning "HIDS-2525020210002 driver enabled without any devices" +#endif + +/* + * Main instantiation macro. + */ +#define HIDS_2525020210002_DEFINE(inst) \ + static struct hids_2525020210002_data hids_2525020210002_data_##inst; \ + static const struct hids_2525020210002_config hids_2525020210002_config_##inst = { \ + .bus_cfg = {.i2c = I2C_DT_SPEC_INST_GET(inst)}, \ + .precision = (hids_2525020210002_precision_t)(DT_INST_ENUM_IDX(inst, precision)), \ + .heater = (hids_2525020210002_heater_t)(DT_INST_ENUM_IDX(inst, heater)), \ + }; \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, hids_2525020210002_init, NULL, \ + &hids_2525020210002_data_##inst, \ + &hids_2525020210002_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &hids_2525020210002_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(HIDS_2525020210002_DEFINE) diff --git a/drivers/sensor/wsen/wsen_hids_2525020210002/wsen_hids_2525020210002.h b/drivers/sensor/wsen/wsen_hids_2525020210002/wsen_hids_2525020210002.h new file mode 100644 index 000000000000..9e88d1b13258 --- /dev/null +++ b/drivers/sensor/wsen/wsen_hids_2525020210002/wsen_hids_2525020210002.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_WSEN_HIDS_2525020210002_WSEN_HIDS_2525020210002_H_ +#define ZEPHYR_DRIVERS_SENSOR_WSEN_HIDS_2525020210002_WSEN_HIDS_2525020210002_H_ + +#include +#include + +#include + +#include "WSEN_HIDS_2525020210002_hal.h" + +#include +#include + +struct hids_2525020210002_data { + /* WE sensor interface configuration */ + WE_sensorInterface_t sensor_interface; + + /* Last humidity sample */ + int32_t humidity; + + /* Last temperature sample */ + int32_t temperature; + + hids_2525020210002_precision_t sensor_precision; + + hids_2525020210002_heater_t sensor_heater; +}; + +struct hids_2525020210002_config { + union { + const struct i2c_dt_spec i2c; + } bus_cfg; + + const hids_2525020210002_precision_t precision; + + const hids_2525020210002_heater_t heater; +}; + +int hids_2525020210002_i2c_init(const struct device *dev); + +#endif /* ZEPHYR_DRIVERS_SENSOR_WSEN_HIDS_2525020210002_WSEN_HIDS_2525020210002_H_ */ diff --git a/dts/bindings/sensor/we,wsen-hids-2525020210002.yaml b/dts/bindings/sensor/we,wsen-hids-2525020210002.yaml new file mode 100644 index 000000000000..059a61888442 --- /dev/null +++ b/dts/bindings/sensor/we,wsen-hids-2525020210002.yaml @@ -0,0 +1,41 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +description: | + Würth Elektronik WSEN-HIDS-2525020210002 humidity sensor + +compatible: "we,wsen-hids-2525020210002" + +include: [sensor-device.yaml, i2c-device.yaml] + +properties: + + precision: + type: string + default: "Medium" + enum: + - "Low" + - "Medium" + - "High" + description: | + Sensor measurement precision for temperature and humidity. + Supported precision options are Low, Medium or High. + Defaults to Medium, which is a good compromise between + current usage and precision. + + heater: + type: string + default: "Off" + enum: + - "Off" + - "On_200mW_1s" + - "On_200mW_100ms" + - "On_110mW_1s" + - "On_110mW_100ms" + - "On_20mW_1s" + - "On_20mW_100ms" + description: | + Activate the heater when fetching a sample for the specified amount of time. + This is only possible when the precison is set to high. + Defaults to Off, since this option is valid for high precision + and the default precision is medium. diff --git a/include/zephyr/drivers/sensor/wsen_hids_2525020210002.h b/include/zephyr/drivers/sensor/wsen_hids_2525020210002.h new file mode 100644 index 000000000000..c8d227bdda03 --- /dev/null +++ b/include/zephyr/drivers/sensor/wsen_hids_2525020210002.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Extended public API for WSEN-HIDS-2525020210002 Sensor + * + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_WSEN_HIDS_2525020210002_H_ +#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_WSEN_HIDS_2525020210002_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +enum sensor_attribute_wsen_hids_2525020210002 { + SENSOR_ATTR_WSEN_HIDS_2525020210002_PRECISION = SENSOR_ATTR_PRIV_START, + SENSOR_ATTR_WSEN_HIDS_2525020210002_HEATER +}; + +typedef enum { + hids_2525020210002_precision_Low = 0x0, + hids_2525020210002_precision_Medium = 0x1, + hids_2525020210002_precision_High = 0x2 +} hids_2525020210002_precision_t; + +typedef enum { + hids_2525020210002_heater_Off = 0x0, + hids_2525020210002_heater_On_200mW_1s = 0x1, + hids_2525020210002_heater_On_200mW_100ms = 0x2, + hids_2525020210002_heater_On_110mW_1s = 0x3, + hids_2525020210002_heater_On_110mW_100ms = 0x4, + hids_2525020210002_heater_On_20mW_1s = 0x5, + hids_2525020210002_heater_On_20mW_100ms = 0x6, +} hids_2525020210002_heater_t; + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_WSEN_HIDS_2525020210002_H_ */ diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index 5fa516d018f1..78002740937a 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -1053,3 +1053,9 @@ test_i2c_fxls8974: fxls8974@93 { int1-gpios = <&test_gpio 0 0>; int2-gpios = <&test_gpio 0 0>; }; + +test_i2c_wsen_hids_2525020210002: wsen_hids_2525020210002@94 { + compatible = "we,wsen-hids-2525020210002"; + reg = <0x94>; + precision = "High"; +}; From 67a316034c24bd14b8b2a73484d6ea5b0eda8433 Mon Sep 17 00:00:00 2001 From: Wajdi ELMuhtadi Date: Mon, 4 Sep 2023 09:34:22 +0200 Subject: [PATCH 08/14] drivers: sensor: wsen_pdus_25131308XXXXX: add sensor driver Add wsen_pdus_25131308XXXXX driver with the corrected name and compatibility with the hal update as well as added new features.. Signed-off-by: Wajdi ELMuhtadi --- drivers/sensor/wsen/CMakeLists.txt | 1 + drivers/sensor/wsen/Kconfig | 1 + .../wsen_pdus_25131308XXXXX/CMakeLists.txt | 6 + .../wsen/wsen_pdus_25131308XXXXX/Kconfig | 11 ++ .../wsen_pdus_25131308XXXXX.c | 160 ++++++++++++++++++ .../wsen_pdus_25131308XXXXX.h | 39 +++++ .../sensor/we,wsen-pdus-25131308XXXXX.yaml | 22 +++ tests/drivers/build_all/sensor/i2c.dtsi | 6 + 8 files changed, 246 insertions(+) create mode 100644 drivers/sensor/wsen/wsen_pdus_25131308XXXXX/CMakeLists.txt create mode 100644 drivers/sensor/wsen/wsen_pdus_25131308XXXXX/Kconfig create mode 100644 drivers/sensor/wsen/wsen_pdus_25131308XXXXX/wsen_pdus_25131308XXXXX.c create mode 100644 drivers/sensor/wsen/wsen_pdus_25131308XXXXX/wsen_pdus_25131308XXXXX.h create mode 100644 dts/bindings/sensor/we,wsen-pdus-25131308XXXXX.yaml diff --git a/drivers/sensor/wsen/CMakeLists.txt b/drivers/sensor/wsen/CMakeLists.txt index 5429320954de..3f359c704d8a 100644 --- a/drivers/sensor/wsen/CMakeLists.txt +++ b/drivers/sensor/wsen/CMakeLists.txt @@ -3,4 +3,5 @@ # zephyr-keep-sorted-start add_subdirectory_ifdef(CONFIG_WSEN_HIDS_2525020210002 wsen_hids_2525020210002) +add_subdirectory_ifdef(CONFIG_WSEN_PDUS_25131308XXXXX wsen_pdus_25131308XXXXX) # zephyr-keep-sorted-stop diff --git a/drivers/sensor/wsen/Kconfig b/drivers/sensor/wsen/Kconfig index 727a995af6b6..f945068fd19a 100644 --- a/drivers/sensor/wsen/Kconfig +++ b/drivers/sensor/wsen/Kconfig @@ -3,4 +3,5 @@ # zephyr-keep-sorted-start source "drivers/sensor/wsen/wsen_hids_2525020210002/Kconfig" +source "drivers/sensor/wsen/wsen_pdus_25131308XXXXX/Kconfig" # zephyr-keep-sorted-stop diff --git a/drivers/sensor/wsen/wsen_pdus_25131308XXXXX/CMakeLists.txt b/drivers/sensor/wsen/wsen_pdus_25131308XXXXX/CMakeLists.txt new file mode 100644 index 000000000000..a16a55e0bf2f --- /dev/null +++ b/drivers/sensor/wsen/wsen_pdus_25131308XXXXX/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(wsen_pdus_25131308XXXXX.c) diff --git a/drivers/sensor/wsen/wsen_pdus_25131308XXXXX/Kconfig b/drivers/sensor/wsen/wsen_pdus_25131308XXXXX/Kconfig new file mode 100644 index 000000000000..8119d90d5041 --- /dev/null +++ b/drivers/sensor/wsen/wsen_pdus_25131308XXXXX/Kconfig @@ -0,0 +1,11 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +config WSEN_PDUS_25131308XXXXX + bool "WSEN-PDUS-25131308XXXXX differential pressure sensor" + default y + depends on DT_HAS_WE_WSEN_PDUS_25131308XXXXX_ENABLED + select I2C if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_PDUS_25131308XXXXX),i2c) + select HAS_WESENSORS + help + Enable driver for the WSEN-PDUS-25131308XXXXX I2C-based differential pressure sensor. diff --git a/drivers/sensor/wsen/wsen_pdus_25131308XXXXX/wsen_pdus_25131308XXXXX.c b/drivers/sensor/wsen/wsen_pdus_25131308XXXXX/wsen_pdus_25131308XXXXX.c new file mode 100644 index 000000000000..d1ae1c56856d --- /dev/null +++ b/drivers/sensor/wsen/wsen_pdus_25131308XXXXX/wsen_pdus_25131308XXXXX.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT we_wsen_pdus_25131308xxxxx + +#include + +#include +#include +#include + +#include "wsen_pdus_25131308XXXXX.h" + +LOG_MODULE_REGISTER(WSEN_PDUS_25131308XXXXX, CONFIG_SENSOR_LOG_LEVEL); + +static int pdus_25131308XXXXX_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + struct pdus_25131308XXXXX_data *data = dev->data; + uint16_t pressure_dummy; + + switch (chan) { + case SENSOR_CHAN_ALL: { + if (PDUS_getRawPressureAndTemperature(&data->sensor_interface, &data->pressure, + &data->temperature) != WE_SUCCESS) { + LOG_ERR("Failed to fetch data sample"); + return -EIO; + } + break; + } + case SENSOR_CHAN_AMBIENT_TEMP: { + if (PDUS_getRawPressureAndTemperature(&data->sensor_interface, &pressure_dummy, + &data->temperature) != WE_SUCCESS) { + LOG_ERR("Failed to fetch data sample"); + return -EIO; + } + break; + } + case SENSOR_CHAN_PRESS: { + if (PDUS_getRawPressure(&data->sensor_interface, &data->pressure) != WE_SUCCESS) { + LOG_ERR("Failed to fetch data sample"); + return -EIO; + } + break; + } + default: + LOG_ERR("Fetching is not supported on channel %d.", chan); + return -ENOTSUP; + } + + return 0; +} + +static int pdus_25131308XXXXX_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *value) +{ + struct pdus_25131308XXXXX_data *data = dev->data; + const struct pdus_25131308XXXXX_config *config = dev->config; + + switch (chan) { + case SENSOR_CHAN_AMBIENT_TEMP: { + int32_t temperature_mega = ((int32_t)(data->temperature - T_MIN_VAL_PDUS)) * 4272; + + value->val1 = temperature_mega / 1000000; + value->val2 = temperature_mega % 1000000; + break; + } + case SENSOR_CHAN_PRESS: { + int32_t pressure_temp = ((int32_t)(data->pressure - P_MIN_VAL_PDUS)); + + /* + * these values are conversion factors based on the sensor type defined in the user + * manual of the respective sensor + */ + switch (config->sensor_type) { + case PDUS_pdus0: + value->val1 = ((pressure_temp * 763) - 10000000) / 100000000; + value->val2 = (((pressure_temp * 763) - 10000000) % 100000000) / 100; + break; + case PDUS_pdus1: + value->val1 = ((pressure_temp * 763) - 10000000) / 10000000; + value->val2 = (((pressure_temp * 763) - 10000000) % 10000000) / 10; + break; + case PDUS_pdus2: + value->val1 = ((pressure_temp * 763) - 10000000) / 1000000; + value->val2 = ((pressure_temp * 763) - 10000000) % 1000000; + break; + case PDUS_pdus3: + value->val1 = (pressure_temp * 3815) / 1000000; + value->val2 = (pressure_temp * 3815) % 1000000; + break; + case PDUS_pdus4: + value->val1 = ((pressure_temp * 4196) - 10000000) / 100000; + value->val2 = + ((pressure_temp * 4196) - 10000000) % 100000 * (1000000 / 100000); + break; + case PDUS_pdus5: + value->val1 = (pressure_temp * 5722) / 100000; + value->val2 = (pressure_temp * 5722) % 100000 * (1000000 / 100000); + break; + default: + LOG_ERR("Sensor type doesn't exist"); + return -ENOTSUP; + } + break; + } + default: + LOG_ERR("Channel not supported %d", chan); + return -ENOTSUP; + } + + return 0; +} + +static const struct sensor_driver_api pdus_25131308XXXXX_driver_api = { + .sample_fetch = pdus_25131308XXXXX_sample_fetch, + .channel_get = pdus_25131308XXXXX_channel_get}; + +static int pdus_25131308XXXXX_init(const struct device *dev) +{ + struct pdus_25131308XXXXX_data *data = dev->data; + const struct pdus_25131308XXXXX_config *config = dev->config; + + /* Initialize WE sensor interface */ + PDUS_getDefaultInterface(&data->sensor_interface); + data->sensor_interface.interfaceType = WE_i2c; + + if (!i2c_is_ready_dt(&config->bus_cfg.i2c)) { + LOG_ERR("I2C bus device not ready"); + return -ENODEV; + } + + data->sensor_interface.handle = (void *)&config->bus_cfg.i2c; + + return 0; +} + +#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0 +#warning "PDUS driver enabled without any devices" +#endif + +/* + * Main instantiation macro. + */ +#define PDUS_25131308XXXXX_DEFINE(inst) \ + static struct pdus_25131308XXXXX_data pdus_25131308XXXXX_data_##inst; \ + static const struct pdus_25131308XXXXX_config pdus_25131308XXXXX_config_##inst = { \ + .bus_cfg = \ + { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }, \ + .sensor_type = (PDUS_SensorType_t)DT_INST_ENUM_IDX(inst, sensor_type)}; \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, pdus_25131308XXXXX_init, NULL, \ + &pdus_25131308XXXXX_data_##inst, \ + &pdus_25131308XXXXX_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &pdus_25131308XXXXX_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(PDUS_25131308XXXXX_DEFINE) diff --git a/drivers/sensor/wsen/wsen_pdus_25131308XXXXX/wsen_pdus_25131308XXXXX.h b/drivers/sensor/wsen/wsen_pdus_25131308XXXXX/wsen_pdus_25131308XXXXX.h new file mode 100644 index 000000000000..6d811502cec2 --- /dev/null +++ b/drivers/sensor/wsen/wsen_pdus_25131308XXXXX/wsen_pdus_25131308XXXXX.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_WSEN_PDUS_25131308XXXXX_WSEN_PDUS_25131308XXXXX_H_ +#define ZEPHYR_DRIVERS_SENSOR_WSEN_PDUS_25131308XXXXX_WSEN_PDUS_25131308XXXXX_H_ + +#include +#include + +#include + +#include "WSEN_PDUS_25131308XXX01_hal.h" +#include + +struct pdus_25131308XXXXX_data { + /* WE sensor interface configuration */ + WE_sensorInterface_t sensor_interface; + + /* Last pressure sample */ + uint16_t pressure; + + /* Last temperature sample */ + uint16_t temperature; +}; + +struct pdus_25131308XXXXX_config { + union { + const struct i2c_dt_spec i2c; + } bus_cfg; + + PDUS_SensorType_t sensor_type; +}; + +int pdus_25131308XXXXX_i2c_init(const struct device *dev); + +#endif /* ZEPHYR_DRIVERS_SENSOR_WSEN_PDUS_25131308XXXXX_WSEN_PDUS_25131308XXXXX_H_ */ diff --git a/dts/bindings/sensor/we,wsen-pdus-25131308XXXXX.yaml b/dts/bindings/sensor/we,wsen-pdus-25131308XXXXX.yaml new file mode 100644 index 000000000000..400014b30db5 --- /dev/null +++ b/dts/bindings/sensor/we,wsen-pdus-25131308XXXXX.yaml @@ -0,0 +1,22 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +description: | + Würth Elektronik WSEN-PDUS-25131308XXXXX differential pressure sensor + +compatible: "we,wsen-pdus-25131308XXXXX" + +include: [sensor-device.yaml, i2c-device.yaml] + +properties: + sensor-type: + type: int + required: true + enum: + - 0 # order code 2513130810001, range = -0.1 to +0.1 kPa + - 1 # order code 2513130810101 (5V VCC) + 2513130810102 (3.3V VCC), range = -1 to +1 kPa + - 2 # order code 2513130810201, range = -10 to +10 kPa + - 3 # order code 2513130810301, range = 0 to 100 kPa + - 4 # order code 2513130810401 (5V VCC) + 2513130810402 (3.3V VCC), range = -100 to +1000 kPa + - 5 # order code 2513130815401, range = 0 to +1500 kPa + description: PDUS sensor product variant (pressure measurement range). diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index 78002740937a..c7f8b732b816 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -674,6 +674,12 @@ test_i2c_s11059: s11059@64 { integration-time = <546000>; }; +test_i2c_wsen_pdus_25131308XXXXX: wsen_pdus_25131308XXXXX@65 { + compatible = "we,wsen-pdus-25131308XXXXX"; + reg = <0x65>; + sensor-type = < 4 >; +}; + test_i2c_veml7700: veml7700@66 { compatible = "vishay,veml7700"; reg = <0x66>; From 059d1932c036036ef2e20be9f61e9a4a7410cfb9 Mon Sep 17 00:00:00 2001 From: Wajdi ELMuhtadi Date: Tue, 5 Sep 2023 11:36:14 +0200 Subject: [PATCH 09/14] drivers: sensor: wsen_tids_2521020222501: add sensor driver Add wsen_tids_2521020222501 driver with the corrected name and compatibility with the hal update as well as added new features. Signed-off-by: Wajdi ELMuhtadi --- drivers/sensor/wsen/CMakeLists.txt | 1 + drivers/sensor/wsen/Kconfig | 1 + .../wsen_tids_2521020222501/CMakeLists.txt | 7 + .../wsen/wsen_tids_2521020222501/Kconfig | 53 +++ .../wsen_tids_2521020222501.c | 334 ++++++++++++++++++ .../wsen_tids_2521020222501.h | 95 +++++ .../wsen_tids_2521020222501_trigger.c | 303 ++++++++++++++++ .../sensor/we,wsen-tids-2521020222501.yaml | 42 +++ .../drivers/sensor/wsen_tids_2521020222501.h | 31 ++ tests/drivers/build_all/sensor/i2c.dtsi | 7 + .../sensor/sensors_trigger_global.conf | 1 + .../sensor/sensors_trigger_none.conf | 1 + .../build_all/sensor/sensors_trigger_own.conf | 1 + 13 files changed, 877 insertions(+) create mode 100644 drivers/sensor/wsen/wsen_tids_2521020222501/CMakeLists.txt create mode 100644 drivers/sensor/wsen/wsen_tids_2521020222501/Kconfig create mode 100644 drivers/sensor/wsen/wsen_tids_2521020222501/wsen_tids_2521020222501.c create mode 100644 drivers/sensor/wsen/wsen_tids_2521020222501/wsen_tids_2521020222501.h create mode 100644 drivers/sensor/wsen/wsen_tids_2521020222501/wsen_tids_2521020222501_trigger.c create mode 100644 dts/bindings/sensor/we,wsen-tids-2521020222501.yaml create mode 100644 include/zephyr/drivers/sensor/wsen_tids_2521020222501.h diff --git a/drivers/sensor/wsen/CMakeLists.txt b/drivers/sensor/wsen/CMakeLists.txt index 3f359c704d8a..adb266ff7592 100644 --- a/drivers/sensor/wsen/CMakeLists.txt +++ b/drivers/sensor/wsen/CMakeLists.txt @@ -4,4 +4,5 @@ # zephyr-keep-sorted-start add_subdirectory_ifdef(CONFIG_WSEN_HIDS_2525020210002 wsen_hids_2525020210002) add_subdirectory_ifdef(CONFIG_WSEN_PDUS_25131308XXXXX wsen_pdus_25131308XXXXX) +add_subdirectory_ifdef(CONFIG_WSEN_TIDS_2521020222501 wsen_tids_2521020222501) # zephyr-keep-sorted-stop diff --git a/drivers/sensor/wsen/Kconfig b/drivers/sensor/wsen/Kconfig index f945068fd19a..6a83428477e6 100644 --- a/drivers/sensor/wsen/Kconfig +++ b/drivers/sensor/wsen/Kconfig @@ -4,4 +4,5 @@ # zephyr-keep-sorted-start source "drivers/sensor/wsen/wsen_hids_2525020210002/Kconfig" source "drivers/sensor/wsen/wsen_pdus_25131308XXXXX/Kconfig" +source "drivers/sensor/wsen/wsen_tids_2521020222501/Kconfig" # zephyr-keep-sorted-stop diff --git a/drivers/sensor/wsen/wsen_tids_2521020222501/CMakeLists.txt b/drivers/sensor/wsen/wsen_tids_2521020222501/CMakeLists.txt new file mode 100644 index 000000000000..0334889482d9 --- /dev/null +++ b/drivers/sensor/wsen/wsen_tids_2521020222501/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(wsen_tids_2521020222501.c) +zephyr_library_sources_ifdef(CONFIG_WSEN_TIDS_2521020222501_TRIGGER wsen_tids_2521020222501_trigger.c) diff --git a/drivers/sensor/wsen/wsen_tids_2521020222501/Kconfig b/drivers/sensor/wsen/wsen_tids_2521020222501/Kconfig new file mode 100644 index 000000000000..b73a8bf0acaf --- /dev/null +++ b/drivers/sensor/wsen/wsen_tids_2521020222501/Kconfig @@ -0,0 +1,53 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +menuconfig WSEN_TIDS_2521020222501 + bool "WSEN-TIDS-2521020222501 temperature sensor" + default y + depends on DT_HAS_WE_WSEN_TIDS_2521020222501_ENABLED + select I2C if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_TIDS_2521020222501),i2c) + select HAS_WESENSORS + help + Enable driver for the WSEN-TIDS-2521020222501 I2C-based temperature sensor. + +if WSEN_TIDS_2521020222501 + +choice WSEN_TIDS_2521020222501_TRIGGER_MODE + prompt "Trigger mode" + default WSEN_TIDS_2521020222501_TRIGGER_NONE + help + Specify the type of triggering to be used by the driver. + +config WSEN_TIDS_2521020222501_TRIGGER_NONE + bool "No trigger" + +config WSEN_TIDS_2521020222501_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + depends on GPIO + select WSEN_TIDS_2521020222501_TRIGGER + +config WSEN_TIDS_2521020222501_TRIGGER_OWN_THREAD + bool "Use own thread" + depends on GPIO + select WSEN_TIDS_2521020222501_TRIGGER + +endchoice # WSEN_TIDS_2521020222501_TRIGGER_MODE + +config WSEN_TIDS_2521020222501_TRIGGER + bool + +config WSEN_TIDS_2521020222501_THREAD_PRIORITY + int "Thread priority" + depends on WSEN_TIDS_2521020222501_TRIGGER_OWN_THREAD + default 10 + help + Priority of thread used by the driver to handle interrupts. + +config WSEN_TIDS_2521020222501_THREAD_STACK_SIZE + int "Thread stack size" + depends on WSEN_TIDS_2521020222501_TRIGGER_OWN_THREAD + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + +endif # WSEN_TIDS_2521020222501 diff --git a/drivers/sensor/wsen/wsen_tids_2521020222501/wsen_tids_2521020222501.c b/drivers/sensor/wsen/wsen_tids_2521020222501/wsen_tids_2521020222501.c new file mode 100644 index 000000000000..029ba5feeef5 --- /dev/null +++ b/drivers/sensor/wsen/wsen_tids_2521020222501/wsen_tids_2521020222501.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT we_wsen_tids_2521020222501 + +#include + +#include +#include +#include + +#include "wsen_tids_2521020222501.h" + +LOG_MODULE_REGISTER(WSEN_TIDS_2521020222501, CONFIG_SENSOR_LOG_LEVEL); + +static const struct sensor_value tids_2521020222501_odr_list[] = {{.val1 = 0, .val2 = 0}, + {.val1 = 25, .val2 = 0}, + {.val1 = 50, .val2 = 0}, + {.val1 = 100, .val2 = 0}, + {.val1 = 200, .val2 = 0}}; + +static int tids_2521020222501_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + struct tids_2521020222501_data *data = dev->data; + int16_t raw_temperature; + + switch (chan) { + case SENSOR_CHAN_ALL: + case SENSOR_CHAN_AMBIENT_TEMP: + break; + default: + LOG_ERR("Fetching is not supported on channel %d.", chan); + return -ENOTSUP; + } + if (data->sensor_odr == ((uint8_t)tids_2521020222501_odr_list[0].val1)) { + + TIDS_softReset(&data->sensor_interface, TIDS_enable); + + k_sleep(K_USEC(5)); + + TIDS_softReset(&data->sensor_interface, TIDS_disable); + + if (TIDS_enableOneShot(&data->sensor_interface, TIDS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable one shot"); + return -EIO; + } + + TIDS_state_t busy = TIDS_enable; + + do { + if (TIDS_isBusy(&data->sensor_interface, &busy) != WE_SUCCESS) { + LOG_ERR("Failed to check for data ready"); + return -EIO; + } + } while (TIDS_enable == busy); + } + + if (TIDS_getRawTemperature(&data->sensor_interface, &raw_temperature) != WE_SUCCESS) { + LOG_ERR("Failed to fetch data sample"); + return -EIO; + } + + data->temperature = raw_temperature; + + return 0; +} + +static int tids_2521020222501_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct tids_2521020222501_data *data = dev->data; + + switch (chan) { + case SENSOR_CHAN_AMBIENT_TEMP: + /* Convert temperature from 0.01 degrees Celsius to degrees Celsius */ + val->val1 = data->temperature / 100; + val->val2 = ((int32_t)data->temperature % 100) * (1000000 / 100); + break; + default: + LOG_ERR("Channel not supported %d", chan); + return -ENOTSUP; + } + + return 0; +} + +/* Set output data rate. See tids_2521020222501_odr_list for allowed values. */ +static int tids_2521020222501_odr_set(const struct device *dev, const struct sensor_value *odr) +{ + struct tids_2521020222501_data *data = dev->data; + + int odr_index; + + for (odr_index = 0; odr_index < ARRAY_SIZE(tids_2521020222501_odr_list); odr_index++) { + if (odr->val1 == tids_2521020222501_odr_list[odr_index].val1 && + odr->val2 == tids_2521020222501_odr_list[odr_index].val2) { + break; + } + } + + if (odr_index == ARRAY_SIZE(tids_2521020222501_odr_list)) { + /* ODR not allowed (was not found in tids_2521020222501_odr_list) */ + LOG_ERR("Bad sampling frequency %d.%d", odr->val1, odr->val2); + return -EINVAL; + } + + if (odr->val1 == tids_2521020222501_odr_list[0].val1) { + if (TIDS_enableBlockDataUpdate(&data->sensor_interface, TIDS_disable) != + WE_SUCCESS) { + LOG_ERR("Failed to enable block data update."); + return -EIO; + } + + if (TIDS_enableContinuousMode(&data->sensor_interface, TIDS_disable) != + WE_SUCCESS) { + LOG_ERR("Failed to enable continuous mode."); + return -EIO; + } + } else { + if (TIDS_setOutputDataRate(&data->sensor_interface, + (TIDS_outputDataRate_t)(odr->val1 - 1)) != WE_SUCCESS) { + LOG_ERR("Failed to set output data rate"); + return -EIO; + } + + if (TIDS_enableBlockDataUpdate(&data->sensor_interface, TIDS_enable) != + WE_SUCCESS) { + LOG_ERR("Failed to enable block data update."); + return -EIO; + } + + if (TIDS_enableContinuousMode(&data->sensor_interface, TIDS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable continuous mode."); + return -EIO; + } + } + + data->sensor_odr = (uint8_t)odr->val1; + + return 0; +} + +/* Get output data rate. */ +static int tids_2521020222501_odr_get(const struct device *dev, struct sensor_value *odr) +{ + + struct tids_2521020222501_data *data = dev->data; + + TIDS_state_t continuous_mode_state; + + if (TIDS_isContinuousModeEnabled(&data->sensor_interface, &continuous_mode_state) != + WE_SUCCESS) { + LOG_ERR("Failed to get continuous mode."); + return -EIO; + } + + if (continuous_mode_state == TIDS_disable) { + odr->val1 = tids_2521020222501_odr_list[0].val1; + } else { + TIDS_outputDataRate_t odrIndex; + + if (TIDS_getOutputDataRate(&data->sensor_interface, &odrIndex) != WE_SUCCESS) { + LOG_ERR("Failed to get output data rate"); + return -EIO; + } + + odr->val1 = tids_2521020222501_odr_list[odrIndex + 1].val1; + } + + data->sensor_odr = (uint8_t)odr->val1; + + odr->val2 = 0; + + return 0; +} + +static int tids_2521020222501_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + + switch (chan) { + case SENSOR_CHAN_ALL: + case SENSOR_CHAN_AMBIENT_TEMP: + break; + default: + LOG_ERR("attr_set() is not supported on channel %d.", chan); + return -ENOTSUP; + } + + switch (attr) { + case SENSOR_ATTR_SAMPLING_FREQUENCY: + return tids_2521020222501_odr_set(dev, val); +#ifdef CONFIG_WSEN_TIDS_2521020222501_TRIGGER + case SENSOR_ATTR_LOWER_THRESH: + return tids_2521020222501_threshold_lower_set(dev, val); + case SENSOR_ATTR_UPPER_THRESH: + return tids_2521020222501_threshold_upper_set(dev, val); +#endif /* CONFIG_WSEN_TIDS_2521020222501_TRIGGER */ + + default: + LOG_ERR("Operation not supported."); + return -ENOTSUP; + } +} + +static int tids_2521020222501_attr_get(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, struct sensor_value *val) +{ + + if (val == NULL) { + LOG_WRN("address of passed value is NULL."); + return -EFAULT; + } + + switch (chan) { + case SENSOR_CHAN_ALL: + case SENSOR_CHAN_AMBIENT_TEMP: + break; + default: + LOG_ERR("attr_get() is not supported on channel %d.", chan); + return -ENOTSUP; + } + + switch (attr) { + case SENSOR_ATTR_SAMPLING_FREQUENCY: + return tids_2521020222501_odr_get(dev, val); +#ifdef CONFIG_WSEN_TIDS_2521020222501_TRIGGER + case SENSOR_ATTR_LOWER_THRESH: + return tids_2521020222501_threshold_lower_get(dev, val); + case SENSOR_ATTR_UPPER_THRESH: + return tids_2521020222501_threshold_upper_get(dev, val); +#endif /* CONFIG_WSEN_TIDS_2521020222501_TRIGGER */ + default: + LOG_ERR("Operation not supported."); + return -ENOTSUP; + } + + return 0; +} + +static const struct sensor_driver_api tids_2521020222501_driver_api = { + .attr_set = tids_2521020222501_attr_set, +#if CONFIG_WSEN_TIDS_2521020222501_TRIGGER + .trigger_set = tids_2521020222501_trigger_set, +#endif + .attr_get = tids_2521020222501_attr_get, + .sample_fetch = tids_2521020222501_sample_fetch, + .channel_get = tids_2521020222501_channel_get, +}; + +static int tids_2521020222501_init(const struct device *dev) +{ + const struct tids_2521020222501_config *const config = dev->config; + struct tids_2521020222501_data *data = dev->data; + uint8_t device_id; + + /* Initialize WE sensor interface */ + TIDS_getDefaultInterface(&data->sensor_interface); + data->sensor_interface.interfaceType = WE_i2c; + if (!i2c_is_ready_dt(&config->bus_cfg.i2c)) { + LOG_ERR("I2C bus device not ready"); + return -ENODEV; + } + data->sensor_interface.handle = (void *)&config->bus_cfg.i2c; + + /* Needed after power up */ + k_sleep(K_MSEC(12)); + + /* First communication test - check device ID */ + if (TIDS_getDeviceID(&data->sensor_interface, &device_id) != WE_SUCCESS) { + LOG_ERR("Failed to read device ID."); + return -EIO; + } + + if (device_id != TIDS_DEVICE_ID_VALUE) { + LOG_ERR("Invalid device ID 0x%x.", device_id); + return -EIO; + } + + /* Reset the sensor with an arbitrary off time of 5 us */ + TIDS_softReset(&data->sensor_interface, TIDS_enable); + k_sleep(K_USEC(5)); + TIDS_softReset(&data->sensor_interface, TIDS_disable); + + if (tids_2521020222501_odr_set(dev, &tids_2521020222501_odr_list[config->odr]) < 0) { + LOG_ERR("Failed to set output data rate."); + return -EIO; + } + +#ifdef CONFIG_WSEN_TIDS_2521020222501_TRIGGER + if (tids_2521020222501_init_interrupt(dev) < 0) { + LOG_ERR("Failed to initialize interrupt."); + return -EIO; + } +#endif + + return 0; +} + +#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0 +#warning "TIDS_2521020222501 driver enabled without any devices" +#endif + +#ifdef CONFIG_WSEN_TIDS_2521020222501_TRIGGER +#define TIDS_2521020222501_CFG_IRQ(inst) \ + .interrupt_gpio = GPIO_DT_SPEC_INST_GET(inst, interrupt_gpios), \ + .high_threshold = DT_INST_PROP(inst, temp_high_threshold), \ + .low_threshold = DT_INST_PROP(inst, temp_low_threshold) +#else +#define TIDS_2521020222501_CFG_IRQ(inst) +#endif /* CONFIG_WSEN_TIDS_2521020222501_TRIGGER */ + +/* + * Main instantiation macro. + */ +#define TIDS_2521020222501_DEFINE(inst) \ + static struct tids_2521020222501_data tids_2521020222501_data_##inst; \ + static const struct tids_2521020222501_config tids_2521020222501_config_##inst = { \ + .bus_cfg = \ + { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }, \ + .odr = (uint8_t)(DT_INST_ENUM_IDX(inst, odr)), \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, interrupt_gpios), \ + (TIDS_2521020222501_CFG_IRQ(inst)), ())}; \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, tids_2521020222501_init, NULL, \ + &tids_2521020222501_data_##inst, \ + &tids_2521020222501_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &tids_2521020222501_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(TIDS_2521020222501_DEFINE) diff --git a/drivers/sensor/wsen/wsen_tids_2521020222501/wsen_tids_2521020222501.h b/drivers/sensor/wsen/wsen_tids_2521020222501/wsen_tids_2521020222501.h new file mode 100644 index 000000000000..cd2a41f75517 --- /dev/null +++ b/drivers/sensor/wsen/wsen_tids_2521020222501/wsen_tids_2521020222501.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_WSEN_TIDS_2521020222501_WSEN_TIDS_2521020222501_H_ +#define ZEPHYR_DRIVERS_SENSOR_WSEN_TIDS_2521020222501_WSEN_TIDS_2521020222501_H_ + +#include +#include + +#include + +#include "WSEN_TIDS_2521020222501_hal.h" +#include + +#include + +struct tids_2521020222501_data { + /* WE sensor interface configuration */ + WE_sensorInterface_t sensor_interface; + + /* Last temperature sample */ + int16_t temperature; + + uint8_t sensor_odr; + +#ifdef CONFIG_WSEN_TIDS_2521020222501_TRIGGER + const struct device *dev; + + /* Callback for high/low limit interrupts */ + struct gpio_callback interrupt_cb; + + int32_t sensor_high_threshold; + int32_t sensor_low_threshold; + + sensor_trigger_handler_t temperature_high_handler; + sensor_trigger_handler_t temperature_low_handler; + + const struct sensor_trigger *temperature_high_trigger; + const struct sensor_trigger *temperature_low_trigger; + +#if defined(CONFIG_WSEN_TIDS_2521020222501_TRIGGER_OWN_THREAD) + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_WSEN_TIDS_2521020222501_THREAD_STACK_SIZE); + struct k_thread thread; + struct k_sem sem; +#elif defined(CONFIG_WSEN_TIDS_2521020222501_TRIGGER_GLOBAL_THREAD) + struct k_work work; +#endif +#endif /* CONFIG_WSEN_TIDS_2521020222501_TRIGGER */ +}; + +struct tids_2521020222501_config { + union { + const struct i2c_dt_spec i2c; + } bus_cfg; + + /* Output data rate */ + const uint8_t odr; + +#ifdef CONFIG_WSEN_TIDS_2521020222501_TRIGGER + /* Interrupt pin used for high and low limit interrupt events */ + const struct gpio_dt_spec interrupt_gpio; + + /* High temperature interrupt threshold */ + const int32_t high_threshold; + + /* Low temperature interrupt threshold */ + const int32_t low_threshold; +#endif +}; + +#ifdef CONFIG_WSEN_TIDS_2521020222501_TRIGGER +int tids_2521020222501_trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); + +int tids_2521020222501_threshold_upper_set(const struct device *dev, + const struct sensor_value *thresh_value); + +int tids_2521020222501_threshold_upper_get(const struct device *dev, + struct sensor_value *thresh_value); + +int tids_2521020222501_threshold_lower_set(const struct device *dev, + const struct sensor_value *thresh_value); + +int tids_2521020222501_threshold_lower_get(const struct device *dev, + struct sensor_value *thresh_value); + +int tids_2521020222501_init_interrupt(const struct device *dev); +#endif + +int tids_2521020222501_i2c_init(const struct device *dev); + +#endif /* ZEPHYR_DRIVERS_SENSOR_WSEN_TIDS_2521020222501_WSEN_TIDS_2521020222501_H_ */ diff --git a/drivers/sensor/wsen/wsen_tids_2521020222501/wsen_tids_2521020222501_trigger.c b/drivers/sensor/wsen/wsen_tids_2521020222501/wsen_tids_2521020222501_trigger.c new file mode 100644 index 000000000000..acd4afde2417 --- /dev/null +++ b/drivers/sensor/wsen/wsen_tids_2521020222501/wsen_tids_2521020222501_trigger.c @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT we_wsen_tids_2521020222501 + +#include + +#include + +#include "wsen_tids_2521020222501.h" + +LOG_MODULE_DECLARE(WSEN_TIDS_2521020222501, CONFIG_SENSOR_LOG_LEVEL); + +/* Enable/disable interrupt handling */ +static inline void tids_2521020222501_setup_interrupt(const struct device *dev, bool enable) +{ + const struct tids_2521020222501_config *cfg = dev->config; + unsigned int flags = enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE; + + gpio_pin_interrupt_configure_dt(&cfg->interrupt_gpio, flags); +} + +/* + * Is called when an interrupt has occurred. + */ +static void tids_2521020222501_handle_interrupt(const struct device *dev) +{ + struct tids_2521020222501_data *data = dev->data; + + /* Disable interrupt handling until the interrupt has been processed */ + tids_2521020222501_setup_interrupt(dev, false); + +#if defined(CONFIG_WSEN_TIDS_2521020222501_TRIGGER_OWN_THREAD) + k_sem_give(&data->sem); +#elif defined(CONFIG_WSEN_TIDS_2521020222501_TRIGGER_GLOBAL_THREAD) + k_work_submit(&data->work); +#endif +} + +/* + * Calls trigger handles. + */ +static void tids_2521020222501_process_interrupt(const struct device *dev) +{ + struct tids_2521020222501_data *data = dev->data; + + if (data->temperature_high_handler != NULL || data->temperature_low_handler != NULL) { + /* + * Read the sensor's status register - this also causes the interrupt pin + * to be de-asserted + */ + TIDS_status_t status; + + if (TIDS_getStatusRegister(&data->sensor_interface, &status) != WE_SUCCESS) { + LOG_ERR("Failed to read status register"); + return; + } + + if (data->temperature_high_handler != NULL && + status.upperLimitExceeded == TIDS_enable) { + data->temperature_high_handler(dev, data->temperature_high_trigger); + } else if (data->temperature_low_handler != NULL && + status.lowerLimitExceeded == TIDS_enable) { + data->temperature_low_handler(dev, data->temperature_low_trigger); + } + } + + tids_2521020222501_setup_interrupt(dev, true); +} + +/* Enables/disables processing of the "threshold exceeded" interrupt. */ +int tids_2521020222501_trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + struct tids_2521020222501_data *data = dev->data; + const struct tids_2521020222501_config *cfg = dev->config; + + switch (trig->chan) { + case SENSOR_CHAN_ALL: + case SENSOR_CHAN_AMBIENT_TEMP: + break; + default: + LOG_ERR("Unsupported sensor trigger"); + return -ENOTSUP; + } + + struct sensor_value interruptOFF = {.val1 = -40, .val2 = -320000}; + struct sensor_value threshold; + + switch ((int)trig->type) { + case SENSOR_TRIG_WSEN_TIDS_2521020222501_THRESHOLD_LOWER: { + + threshold.val1 = data->sensor_low_threshold / 1000; + threshold.val2 = ((int32_t)data->sensor_low_threshold % 1000) * (1000000 / 1000); + + if (tids_2521020222501_threshold_lower_set( + dev, (handler == NULL) ? &interruptOFF : &threshold) < 0) { + LOG_ERR("Failed to set low temp threshold"); + } + data->temperature_low_handler = handler; + data->temperature_low_trigger = trig; + break; + } + case SENSOR_TRIG_WSEN_TIDS_2521020222501_THRESHOLD_UPPER: { + + threshold.val1 = data->sensor_high_threshold / 1000; + threshold.val2 = ((int32_t)data->sensor_high_threshold % 1000) * (1000000 / 1000); + + if (tids_2521020222501_threshold_upper_set( + dev, (handler == NULL) ? &interruptOFF : &threshold) < 0) { + LOG_ERR("Failed to set high temp threshold"); + } + data->temperature_high_handler = handler; + data->temperature_high_trigger = trig; + break; + } + default: + LOG_ERR("Unsupported sensor trigger"); + return -ENOTSUP; + } + + tids_2521020222501_setup_interrupt(dev, data->temperature_high_handler || + data->temperature_low_handler); + + if (gpio_pin_get_dt(&cfg->interrupt_gpio) > 0) { + tids_2521020222501_handle_interrupt(dev); + } + + return 0; +} + +static void tids_2521020222501_callback(const struct device *dev, struct gpio_callback *cb, + uint32_t pins) +{ + struct tids_2521020222501_data *data = + CONTAINER_OF(cb, struct tids_2521020222501_data, interrupt_cb); + + ARG_UNUSED(pins); + + tids_2521020222501_handle_interrupt(data->dev); +} + +#ifdef CONFIG_WSEN_TIDS_2521020222501_TRIGGER_OWN_THREAD +static void tids_2521020222501_thread(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct tids_2521020222501_data *tids_2521020222501 = p1; + + while (true) { + k_sem_take(&tids_2521020222501->sem, K_FOREVER); + tids_2521020222501_process_interrupt(tids_2521020222501->dev); + } +} +#endif /* CONFIG_WSEN_TIDS_2521020222501_TRIGGER_OWN_THREAD */ + +#ifdef CONFIG_WSEN_TIDS_2521020222501_TRIGGER_GLOBAL_THREAD +static void tids_2521020222501_work_cb(struct k_work *work) +{ + struct tids_2521020222501_data *tids_2521020222501 = + CONTAINER_OF(work, struct tids_2521020222501_data, work); + + tids_2521020222501_process_interrupt(tids_2521020222501->dev); +} +#endif /* CONFIG_WSEN_TIDS_2521020222501_TRIGGER_GLOBAL_THREAD */ + +int tids_2521020222501_threshold_upper_set(const struct device *dev, + const struct sensor_value *thresh_value) +{ + struct tids_2521020222501_data *data = dev->data; + int32_t thresh = thresh_value->val1 * 1000 + thresh_value->val2 / 1000; + + if (TIDS_setTempHighLimit(&data->sensor_interface, thresh) != WE_SUCCESS) { + LOG_ERR("Failed to set high temperature threshold."); + return -EIO; + } + + data->sensor_high_threshold = thresh; + + return 0; +} + +int tids_2521020222501_threshold_upper_get(const struct device *dev, + struct sensor_value *thresh_value) +{ + struct tids_2521020222501_data *data = dev->data; + int32_t thresh; + + if (TIDS_getTempHighLimit(&data->sensor_interface, &thresh) != WE_SUCCESS) { + LOG_ERR("Failed to get high temperature threshold."); + return -EIO; + } + + thresh_value->val1 = thresh / 1000; + thresh_value->val2 = (thresh % 1000) * (1000000 / 1000); + + return 0; +} + +int tids_2521020222501_threshold_lower_set(const struct device *dev, + const struct sensor_value *thresh_value) +{ + struct tids_2521020222501_data *data = dev->data; + int32_t thresh = thresh_value->val1 * 1000 + thresh_value->val2 / 1000; + + if (TIDS_setTempLowLimit(&data->sensor_interface, thresh) != WE_SUCCESS) { + LOG_ERR("Failed to set low temperature threshold."); + return -EIO; + } + + data->sensor_low_threshold = thresh; + + return 0; +} + +int tids_2521020222501_threshold_lower_get(const struct device *dev, + struct sensor_value *thresh_value) +{ + struct tids_2521020222501_data *data = dev->data; + int32_t thresh; + + if (TIDS_getTempLowLimit(&data->sensor_interface, &thresh) != WE_SUCCESS) { + LOG_ERR("Failed to get low temperature threshold."); + return -EIO; + } + + thresh_value->val1 = thresh / 1000; + thresh_value->val2 = (thresh % 1000) * (1000000 / 1000); + + return 0; +} + +int tids_2521020222501_init_interrupt(const struct device *dev) +{ + struct tids_2521020222501_data *data = dev->data; + const struct tids_2521020222501_config *cfg = dev->config; + struct sensor_value upper_limit, lower_limit; + + if (cfg->interrupt_gpio.port == NULL) { + LOG_ERR("interrupt-gpios is not defined in the device tree."); + return -EINVAL; + } + + if (!gpio_is_ready_dt(&cfg->interrupt_gpio)) { + LOG_ERR("Device %s is not ready", cfg->interrupt_gpio.port->name); + return -ENODEV; + } + + data->dev = dev; + + /* Setup threshold gpio interrupt */ + if (gpio_pin_configure_dt(&cfg->interrupt_gpio, GPIO_INPUT) < 0) { + LOG_ERR("Failed to configure %s.%02u", cfg->interrupt_gpio.port->name, + cfg->interrupt_gpio.pin); + return -EIO; + } + + gpio_init_callback(&data->interrupt_cb, tids_2521020222501_callback, + BIT(cfg->interrupt_gpio.pin)); + + if (gpio_add_callback(cfg->interrupt_gpio.port, &data->interrupt_cb) < 0) { + LOG_ERR("Failed to set gpio callback."); + return -EIO; + } + + /* + * Enable interrupt on high/low temperature (interrupt generation is enabled if at + * least one threshold is non-zero) + */ + + upper_limit.val1 = cfg->high_threshold / 1000; + upper_limit.val2 = ((int32_t)cfg->high_threshold % 1000) * (1000000 / 1000); + + lower_limit.val1 = cfg->low_threshold / 1000; + lower_limit.val2 = ((int32_t)cfg->low_threshold % 1000) * (1000000 / 1000); + + if (tids_2521020222501_threshold_upper_set(dev, &upper_limit) < 0) { + LOG_ERR("Failed to set upper threshold"); + return -EIO; + } + + if (tids_2521020222501_threshold_lower_set(dev, &lower_limit) < 0) { + LOG_ERR("Failed to set lower threshold"); + return -EIO; + } + +#if defined(CONFIG_WSEN_TIDS_2521020222501_TRIGGER_OWN_THREAD) + k_sem_init(&data->sem, 0, K_SEM_MAX_LIMIT); + + k_thread_create(&data->thread, data->thread_stack, + CONFIG_WSEN_TIDS_2521020222501_THREAD_STACK_SIZE, tids_2521020222501_thread, + data, NULL, NULL, + K_PRIO_COOP(CONFIG_WSEN_TIDS_2521020222501_THREAD_PRIORITY), 0, K_NO_WAIT); +#elif defined(CONFIG_WSEN_TIDS_2521020222501_TRIGGER_GLOBAL_THREAD) + data->work.handler = tids_2521020222501_work_cb; +#endif + + return 0; +} diff --git a/dts/bindings/sensor/we,wsen-tids-2521020222501.yaml b/dts/bindings/sensor/we,wsen-tids-2521020222501.yaml new file mode 100644 index 000000000000..5cdaa9793856 --- /dev/null +++ b/dts/bindings/sensor/we,wsen-tids-2521020222501.yaml @@ -0,0 +1,42 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +description: | + Würth Elektronik WSEN-TIDS-2521020222501 temperature sensor + +compatible: "we,wsen-tids-2521020222501" + +include: [sensor-device.yaml, i2c-device.yaml] + +properties: + interrupt-gpios: + type: phandle-array + description: Threshold interrupt pin. + Interrupt is active low by default. + + odr: + type: int + required: true + enum: + - 0 + - 25 + - 50 + - 100 + - 200 + description: | + Sensor output data rate expressed in samples per second. + Data rates supported by the chip are 0 (power down), 25, 50, 100 and 200. + + temp-high-threshold: + type: int + default: -40320 + description: | + Threshold for temperature high limit interrupt event in millidegree Celsius. + Defaults to -40320, which is the configuration at power-up. + + temp-low-threshold: + type: int + default: -40320 + description: | + Threshold for temperature low limit interrupt event in millidegree Celsius. + Defaults to -40320, which is the configuration at power-up. diff --git a/include/zephyr/drivers/sensor/wsen_tids_2521020222501.h b/include/zephyr/drivers/sensor/wsen_tids_2521020222501.h new file mode 100644 index 000000000000..51ccfbb0a022 --- /dev/null +++ b/include/zephyr/drivers/sensor/wsen_tids_2521020222501.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Extended public API for WSEN-TIDS-2521020222501 Sensor + * + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_WSEN_TIDS_2521020222501_H_ +#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_WSEN_TIDS_2521020222501_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +enum sensor_trigger_wsen_tids_2521020222501 { + SENSOR_TRIG_WSEN_TIDS_2521020222501_THRESHOLD_UPPER = SENSOR_TRIG_PRIV_START, + SENSOR_TRIG_WSEN_TIDS_2521020222501_THRESHOLD_LOWER, +}; + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_WSEN_TIDS_2521020222501_H_ */ diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index c7f8b732b816..ffcad2a8bdac 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -647,6 +647,13 @@ test_i2c_akm09918c: akm09918c@5f { reg = <0x5f>; }; +test_i2c_wsen_tids_2521020222501: wsen_tids_2521020222501@60 { + compatible = "we,wsen-tids-2521020222501"; + reg = <0x60>; + interrupt-gpios = <&test_gpio 0 0>; + odr = <25>; +}; + test_i2c_vl53l1x: vl53l1x@61 { compatible = "st,vl53l1x"; reg = <0x61>; diff --git a/tests/drivers/build_all/sensor/sensors_trigger_global.conf b/tests/drivers/build_all/sensor/sensors_trigger_global.conf index 5a2164c327bd..19b3129e46ac 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_global.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_global.conf @@ -63,3 +63,4 @@ CONFIG_TMP007_TRIGGER_GLOBAL_THREAD=y CONFIG_TSL2540_TRIGGER_GLOBAL_THREAD=y CONFIG_TSL2591_TRIGGER_GLOBAL_THREAD=y CONFIG_VCNL4040_TRIGGER_GLOBAL_THREAD=y +CONFIG_WSEN_TIDS_2521020222501_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 3edefcd9640b..848175999fc7 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_none.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_none.conf @@ -63,3 +63,4 @@ CONFIG_TMP007_TRIGGER_NONE=y CONFIG_TSL2540_TRIGGER_NONE=y CONFIG_TSL2591_TRIGGER_NONE=y CONFIG_VCNL4040_TRIGGER_NONE=y +CONFIG_WSEN_TIDS_2521020222501_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 7c7eb4bde5cb..83487c77030b 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_own.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_own.conf @@ -60,3 +60,4 @@ CONFIG_TMP007_TRIGGER_OWN_THREAD=y CONFIG_TSL2540_TRIGGER_OWN_THREAD=y CONFIG_TSL2591_TRIGGER_OWN_THREAD=y CONFIG_VCNL4040_TRIGGER_OWN_THREAD=y +CONFIG_WSEN_TIDS_2521020222501_TRIGGER_OWN_THREAD=y From 0967e377eea627cd0899cc7ca3bf28f67489c9e9 Mon Sep 17 00:00:00 2001 From: Wajdi ELMuhtadi Date: Tue, 5 Sep 2023 13:28:16 +0200 Subject: [PATCH 10/14] drivers: sensor: wsen_hids_2525020210001: add sensor driver Add wsen_hids_2525020210001 driver with the corrected name and compatibility with the hal update as well as added new features. Signed-off-by: Wajdi ELMuhtadi --- drivers/sensor/wsen/CMakeLists.txt | 1 + drivers/sensor/wsen/Kconfig | 1 + .../wsen_hids_2525020210001/CMakeLists.txt | 7 + .../wsen/wsen_hids_2525020210001/Kconfig | 55 ++++ .../wsen_hids_2525020210001.c | 278 ++++++++++++++++++ .../wsen_hids_2525020210001.h | 81 +++++ .../wsen_hids_2525020210001_trigger.c | 173 +++++++++++ .../we,wsen-hids-2525020210001-common.yaml | 22 ++ .../we,wsen-hids-2525020210001-i2c.yaml | 10 + .../we,wsen-hids-2525020210001-spi.yaml | 10 + tests/drivers/build_all/sensor/i2c.dtsi | 7 + .../sensor/sensors_trigger_global.conf | 1 + .../sensor/sensors_trigger_none.conf | 1 + .../build_all/sensor/sensors_trigger_own.conf | 1 + 14 files changed, 648 insertions(+) create mode 100644 drivers/sensor/wsen/wsen_hids_2525020210001/CMakeLists.txt create mode 100644 drivers/sensor/wsen/wsen_hids_2525020210001/Kconfig create mode 100644 drivers/sensor/wsen/wsen_hids_2525020210001/wsen_hids_2525020210001.c create mode 100644 drivers/sensor/wsen/wsen_hids_2525020210001/wsen_hids_2525020210001.h create mode 100644 drivers/sensor/wsen/wsen_hids_2525020210001/wsen_hids_2525020210001_trigger.c create mode 100644 dts/bindings/sensor/we,wsen-hids-2525020210001/we,wsen-hids-2525020210001-common.yaml create mode 100644 dts/bindings/sensor/we,wsen-hids-2525020210001/we,wsen-hids-2525020210001-i2c.yaml create mode 100644 dts/bindings/sensor/we,wsen-hids-2525020210001/we,wsen-hids-2525020210001-spi.yaml diff --git a/drivers/sensor/wsen/CMakeLists.txt b/drivers/sensor/wsen/CMakeLists.txt index adb266ff7592..4cc07953f781 100644 --- a/drivers/sensor/wsen/CMakeLists.txt +++ b/drivers/sensor/wsen/CMakeLists.txt @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start +add_subdirectory_ifdef(CONFIG_WSEN_HIDS_2525020210001 wsen_hids_2525020210001) add_subdirectory_ifdef(CONFIG_WSEN_HIDS_2525020210002 wsen_hids_2525020210002) add_subdirectory_ifdef(CONFIG_WSEN_PDUS_25131308XXXXX wsen_pdus_25131308XXXXX) add_subdirectory_ifdef(CONFIG_WSEN_TIDS_2521020222501 wsen_tids_2521020222501) diff --git a/drivers/sensor/wsen/Kconfig b/drivers/sensor/wsen/Kconfig index 6a83428477e6..d64d687f0f75 100644 --- a/drivers/sensor/wsen/Kconfig +++ b/drivers/sensor/wsen/Kconfig @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start +source "drivers/sensor/wsen/wsen_hids_2525020210001/Kconfig" source "drivers/sensor/wsen/wsen_hids_2525020210002/Kconfig" source "drivers/sensor/wsen/wsen_pdus_25131308XXXXX/Kconfig" source "drivers/sensor/wsen/wsen_tids_2521020222501/Kconfig" diff --git a/drivers/sensor/wsen/wsen_hids_2525020210001/CMakeLists.txt b/drivers/sensor/wsen/wsen_hids_2525020210001/CMakeLists.txt new file mode 100644 index 000000000000..0688a21b72b6 --- /dev/null +++ b/drivers/sensor/wsen/wsen_hids_2525020210001/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(wsen_hids_2525020210001.c) +zephyr_library_sources_ifdef(CONFIG_WSEN_HIDS_2525020210001_TRIGGER wsen_hids_2525020210001_trigger.c) diff --git a/drivers/sensor/wsen/wsen_hids_2525020210001/Kconfig b/drivers/sensor/wsen/wsen_hids_2525020210001/Kconfig new file mode 100644 index 000000000000..692e700a3aac --- /dev/null +++ b/drivers/sensor/wsen/wsen_hids_2525020210001/Kconfig @@ -0,0 +1,55 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +menuconfig WSEN_HIDS_2525020210001 + bool "WSEN-HIDS-2525020210001 humidity and temperature sensor" + default y + depends on DT_HAS_WE_WSEN_HIDS_2525020210001_ENABLED + select I2C if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_HIDS_2525020210001),i2c) + select SPI if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_HIDS_2525020210001),spi) + select HAS_WESENSORS + help + Enable driver for the WSEN-HIDS I2C/SPI-based humidity sensor with integrated + temperature sensor. + +if WSEN_HIDS_2525020210001 + +choice WSEN_HIDS_2525020210001_TRIGGER_MODE + prompt "Trigger mode" + default WSEN_HIDS_2525020210001_TRIGGER_NONE + help + Specify the type of triggering to be used by the driver. + +config WSEN_HIDS_2525020210001_TRIGGER_NONE + bool "No trigger" + +config WSEN_HIDS_2525020210001_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + depends on GPIO + select WSEN_HIDS_2525020210001_TRIGGER + +config WSEN_HIDS_2525020210001_TRIGGER_OWN_THREAD + bool "Use own thread" + depends on GPIO + select WSEN_HIDS_2525020210001_TRIGGER + +endchoice # WSEN_HIDS_2525020210001_TRIGGER_MODE + +config WSEN_HIDS_2525020210001_TRIGGER + bool + +config WSEN_HIDS_2525020210001_THREAD_PRIORITY + int "Thread priority" + depends on WSEN_HIDS_2525020210001_TRIGGER_OWN_THREAD + default 10 + help + Priority of thread used by the driver to handle interrupts. + +config WSEN_HIDS_2525020210001_THREAD_STACK_SIZE + int "Thread stack size" + depends on WSEN_HIDS_2525020210001_TRIGGER_OWN_THREAD + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + +endif # WSEN_HIDS_2525020210001 diff --git a/drivers/sensor/wsen/wsen_hids_2525020210001/wsen_hids_2525020210001.c b/drivers/sensor/wsen/wsen_hids_2525020210001/wsen_hids_2525020210001.c new file mode 100644 index 000000000000..1b52d2a8d920 --- /dev/null +++ b/drivers/sensor/wsen/wsen_hids_2525020210001/wsen_hids_2525020210001.c @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT we_wsen_hids_2525020210001 + +#include + +#include +#include +#include + +#include "wsen_hids_2525020210001.h" + +LOG_MODULE_REGISTER(WSEN_HIDS_2525020210001, CONFIG_SENSOR_LOG_LEVEL); + +/* + * List of supported output data rates (sensor_value struct, input to + * sensor_attr_set()). Index into this list is used as argument for + * HIDS_2525020210001_setOutputDataRate(). + */ +static const struct sensor_value hids_2525020210001_odr_list[] = { + {.val1 = 0, .val2 = 0}, + {.val1 = 1, .val2 = 0}, + {.val1 = 7, .val2 = 0}, + {.val1 = 12, .val2 = 5 * 100000}, +}; + +static int hids_2525020210001_sample_fetch(const struct device *dev, enum sensor_channel channel) +{ + struct hids_2525020210001_data *data = dev->data; + int16_t raw_humidity; + int16_t raw_temp; + + __ASSERT_NO_MSG(channel == SENSOR_CHAN_ALL); + + if (HIDS_getRawValues(&data->sensor_interface, &raw_humidity, &raw_temp) != WE_SUCCESS) { + LOG_ERR("Failed to %s sample.", "fetch data"); + return -EIO; + } + + if (HIDS_convertHumidity_uint16(&data->sensor_interface, raw_humidity, &data->humidity) != + WE_SUCCESS) { + LOG_ERR("Failed to %s sample.", "convert humidity"); + return -EIO; + } + + if (HIDS_convertTemperature_int16(&data->sensor_interface, raw_temp, &data->temperature) != + WE_SUCCESS) { + LOG_ERR("Failed to %s sample.", "convert temperature"); + return -EIO; + } + + return 0; +} + +static int hids_2525020210001_channel_get(const struct device *dev, enum sensor_channel channel, + struct sensor_value *value) +{ + struct hids_2525020210001_data *data = dev->data; + int32_t value_converted; + + if (channel == SENSOR_CHAN_AMBIENT_TEMP) { + value_converted = (int32_t)data->temperature; + + /* Convert temperature from 0.01 degrees Celsius to degrees Celsius */ + value->val1 = value_converted / 100; + value->val2 = (value_converted % 100) * (1000000 / 100); + } else if (channel == SENSOR_CHAN_HUMIDITY) { + value_converted = (int32_t)data->humidity; + + /* Convert humidity from 0.01 percent to percent */ + value->val1 = value_converted / 100; + value->val2 = (value_converted % 100) * (1000000 / 100); + } else { + return -ENOTSUP; + } + + return 0; +} + +/* Set output data rate. See hids_2525020210001_odr_list for allowed values. */ +static int hids_2525020210001_odr_set(const struct device *dev, const struct sensor_value *odr) +{ + struct hids_2525020210001_data *data = dev->data; + int odr_index; + + for (odr_index = 0; odr_index < ARRAY_SIZE(hids_2525020210001_odr_list); odr_index++) { + if (odr->val1 == hids_2525020210001_odr_list[odr_index].val1 && + odr->val2 == hids_2525020210001_odr_list[odr_index].val2) { + break; + } + } + + if (odr_index == ARRAY_SIZE(hids_2525020210001_odr_list)) { + /* ODR not allowed (was not found in hids_2525020210001_odr_list) */ + LOG_ERR("Bad sampling frequency %d.%d", odr->val1, odr->val2); + return -EINVAL; + } + + if (HIDS_setOutputDataRate(&data->sensor_interface, (HIDS_outputDataRate_t)odr_index) != + WE_SUCCESS) { + LOG_ERR("Failed to set output data rate"); + return -EIO; + } + + return 0; +} + +static int hids_2525020210001_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() is not supported on channel %d.", chan); + return -ENOTSUP; + } + + if (attr == SENSOR_ATTR_SAMPLING_FREQUENCY) { + return hids_2525020210001_odr_set(dev, val); + } else { + return -ENOTSUP; + } +} + +static const struct sensor_driver_api hids_2525020210001_driver_api = { + .attr_set = hids_2525020210001_attr_set, +#if CONFIG_WSEN_HIDS_2525020210001_TRIGGER + .trigger_set = hids_2525020210001_trigger_set, +#endif + .sample_fetch = hids_2525020210001_sample_fetch, + .channel_get = hids_2525020210001_channel_get, +}; + +static int hids_2525020210001_init(const struct device *dev) +{ + const struct hids_2525020210001_config *config = dev->config; + struct hids_2525020210001_data *data = dev->data; + uint8_t device_id; + + /* Initialize WE sensor interface */ + WE_sensorInterfaceType_t interface_type = data->sensor_interface.interfaceType; + + HIDS_getDefaultInterface(&data->sensor_interface); + data->sensor_interface.interfaceType = interface_type; + + switch (data->sensor_interface.interfaceType) { +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) + case WE_i2c: + if (!i2c_is_ready_dt(&config->bus_cfg.i2c)) { + LOG_ERR("I2C bus device not ready"); + return -ENODEV; + } + data->sensor_interface.handle = (void *)&config->bus_cfg.i2c; + break; +#endif +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) + case WE_spi: + if (!spi_is_ready_dt(&config->bus_cfg.spi)) { + LOG_ERR("SPI bus device not ready"); + return -ENODEV; + } + data->sensor_interface.handle = (void *)&config->bus_cfg.spi; + break; +#endif + default: + LOG_ERR("Invalid interface type"); + return -EINVAL; + } + + /* First communication test - check device ID */ + if (HIDS_getDeviceID(&data->sensor_interface, &device_id) != WE_SUCCESS) { + LOG_ERR("Failed to read device ID."); + return -EIO; + } + + if (device_id != HIDS_DEVICE_ID_VALUE) { + LOG_ERR("Invalid device ID 0x%x.", device_id); + return -EINVAL; + } + + if (HIDS_setOutputDataRate(&data->sensor_interface, config->odr) != WE_SUCCESS) { + LOG_ERR("Failed to set output data rate."); + return -EIO; + } + + if (HIDS_enableBlockDataUpdate(&data->sensor_interface, HIDS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable block data update."); + return -EIO; + } + + if (HIDS_setPowerMode(&data->sensor_interface, HIDS_activeMode) != WE_SUCCESS) { + LOG_ERR("Failed to set power mode."); + return -EIO; + } + + if (HIDS_readCalibrationData(&data->sensor_interface) != WE_SUCCESS) { + LOG_ERR("Failed to read calibration data."); + return -EIO; + } + +#if CONFIG_WSEN_HIDS_2525020210001_TRIGGER + int status = hids_2525020210001_init_interrupt(dev); + + if (status < 0) { + LOG_ERR("Failed to initialize data-ready interrupt."); + return status; + } +#endif + + return 0; +} + +#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0 +#warning "HIDS driver enabled without any devices" +#endif + +#ifdef CONFIG_WSEN_HIDS_2525020210001_TRIGGER +#define HIDS_2525020210001_CFG_IRQ(inst) .gpio_drdy = GPIO_DT_SPEC_INST_GET(inst, drdy_gpios) +#else +#define HIDS_2525020210001_CFG_IRQ(inst) +#endif /* CONFIG_WSEN_HIDS_2525020210001_TRIGGER */ + +#define HIDS_2525020210001_CONFIG_COMMON(inst) \ + .odr = (HIDS_outputDataRate_t)(DT_INST_ENUM_IDX(inst, odr) + 1), \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, drdy_gpios), (HIDS_2525020210001_CFG_IRQ(inst)), \ + ()) + +/* + * Instantiation macros used when device is on SPI bus. + */ + +#define HIDS_2525020210001_SPI_OPERATION \ + (SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA) + +#define HIDS_2525020210001_CONFIG_SPI(inst) \ + { \ + .bus_cfg = \ + { \ + .spi = SPI_DT_SPEC_INST_GET(inst, \ + HIDS_2525020210001_SPI_OPERATION, 0), \ + }, \ + HIDS_2525020210001_CONFIG_COMMON(inst) \ + } + +/* + * Instantiation macros used when device is on I2C bus. + */ + +#define HIDS_2525020210001_CONFIG_I2C(inst) \ + { \ + .bus_cfg = \ + { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }, \ + HIDS_2525020210001_CONFIG_COMMON(inst) \ + } + +/* + * Main instantiation macro. Use of COND_CODE_1() selects the right + * bus-specific macro at preprocessor time. + */ +#define HIDS_2525020210001_DEFINE(inst) \ + static struct hids_2525020210001_data hids_2525020210001_data_##inst = COND_CODE_1( \ + DT_INST_ON_BUS(inst, i2c), ({.sensor_interface = {.interfaceType = WE_i2c}}), ()) \ + COND_CODE_1(DT_INST_ON_BUS(inst, spi), \ + ({.sensor_interface = {.interfaceType = WE_spi}}), ()); \ + static const struct hids_2525020210001_config hids_2525020210001_config_##inst = \ + COND_CODE_1(DT_INST_ON_BUS(inst, i2c), (HIDS_2525020210001_CONFIG_I2C(inst)), ()) \ + COND_CODE_1(DT_INST_ON_BUS(inst, spi), \ + (HIDS_2525020210001_CONFIG_SPI(inst)), ()); \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, hids_2525020210001_init, NULL, \ + &hids_2525020210001_data_##inst, \ + &hids_2525020210001_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &hids_2525020210001_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(HIDS_2525020210001_DEFINE) diff --git a/drivers/sensor/wsen/wsen_hids_2525020210001/wsen_hids_2525020210001.h b/drivers/sensor/wsen/wsen_hids_2525020210001/wsen_hids_2525020210001.h new file mode 100644 index 000000000000..431acb1986ab --- /dev/null +++ b/drivers/sensor/wsen/wsen_hids_2525020210001/wsen_hids_2525020210001.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_WSEN_HIDS_2525020210001_WSEN_HIDS_2525020210001_H_ +#define ZEPHYR_DRIVERS_SENSOR_WSEN_HIDS_2525020210001_WSEN_HIDS_2525020210001_H_ + +#include +#include + +#include + +#include "WSEN_HIDS_2525020210001_hal.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) */ + +struct hids_2525020210001_data { + /* WE sensor interface configuration */ + WE_sensorInterface_t sensor_interface; + + /* Last humidity sample */ + uint16_t humidity; + + /* Last temperature sample */ + int16_t temperature; + +#ifdef CONFIG_WSEN_HIDS_2525020210001_TRIGGER + const struct device *dev; + struct gpio_callback data_ready_cb; + + const struct sensor_trigger *data_ready_trigger; + sensor_trigger_handler_t data_ready_handler; + +#if defined(CONFIG_WSEN_HIDS_2525020210001_TRIGGER_OWN_THREAD) + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_WSEN_HIDS_2525020210001_THREAD_STACK_SIZE); + struct k_thread thread; + struct k_sem drdy_sem; +#elif defined(CONFIG_WSEN_HIDS_2525020210001_TRIGGER_GLOBAL_THREAD) + struct k_work work; +#endif +#endif /* CONFIG_WSEN_HIDS_2525020210001_TRIGGER */ +}; + +struct hids_2525020210001_config { + 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 + } bus_cfg; + + /* Output data rate */ + HIDS_outputDataRate_t odr; + +#ifdef CONFIG_WSEN_HIDS_2525020210001_TRIGGER + /* Data-ready interrupt pin */ + const struct gpio_dt_spec gpio_drdy; +#endif /* CONFIG_WSEN_HIDS_2525020210001_TRIGGER */ +}; + +#ifdef CONFIG_WSEN_HIDS_2525020210001_TRIGGER +int hids_2525020210001_trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); + +int hids_2525020210001_init_interrupt(const struct device *dev); +#endif /* CONFIG_WSEN_HIDS_2525020210001_TRIGGER */ + +int hids_2525020210001_spi_init(const struct device *dev); +int hids_2525020210001_i2c_init(const struct device *dev); + +#endif /* ZEPHYR_DRIVERS_SENSOR_WSEN_HIDS_2525020210001_WSEN_HIDS_2525020210001_H_ */ diff --git a/drivers/sensor/wsen/wsen_hids_2525020210001/wsen_hids_2525020210001_trigger.c b/drivers/sensor/wsen/wsen_hids_2525020210001/wsen_hids_2525020210001_trigger.c new file mode 100644 index 000000000000..09ac0c4e7b65 --- /dev/null +++ b/drivers/sensor/wsen/wsen_hids_2525020210001/wsen_hids_2525020210001_trigger.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT we_wsen_hids_2525020210001 + +#include + +#include "wsen_hids_2525020210001.h" + +LOG_MODULE_DECLARE(WSEN_HIDS_2525020210001, CONFIG_SENSOR_LOG_LEVEL); + +static inline void hids_2525020210001_setup_drdy_interrupt(const struct device *dev, bool enable) +{ + const struct hids_2525020210001_config *cfg = dev->config; + unsigned int flags = enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE; + + gpio_pin_interrupt_configure_dt(&cfg->gpio_drdy, flags); +} + +static inline void hids_2525020210001_handle_drdy_interrupt(const struct device *dev) +{ + struct hids_2525020210001_data *data = dev->data; + + hids_2525020210001_setup_drdy_interrupt(dev, false); + +#if defined(CONFIG_WSEN_HIDS_2525020210001_TRIGGER_OWN_THREAD) + k_sem_give(&data->drdy_sem); +#elif defined(CONFIG_WSEN_HIDS_2525020210001_TRIGGER_GLOBAL_THREAD) + k_work_submit(&data->work); +#endif +} + +static void hids_2525020210001_process_drdy_interrupt(const struct device *dev) +{ + struct hids_2525020210001_data *data = dev->data; + + if (data->data_ready_handler != NULL) { + data->data_ready_handler(dev, data->data_ready_trigger); + } + + if (data->data_ready_handler != NULL) { + hids_2525020210001_setup_drdy_interrupt(dev, true); + } +} + +int hids_2525020210001_trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + struct hids_2525020210001_data *data = dev->data; + const struct hids_2525020210001_config *cfg = dev->config; + + if (trig->type != SENSOR_TRIG_DATA_READY) { + LOG_ERR("Unsupported sensor trigger"); + return -ENOTSUP; + } + + hids_2525020210001_setup_drdy_interrupt(dev, false); + + data->data_ready_handler = handler; + if (handler == NULL) { + return 0; + } + + data->data_ready_trigger = trig; + + hids_2525020210001_setup_drdy_interrupt(dev, true); + + /* + * If DRDY is active we probably won't get the rising edge, so + * invoke the callback manually. + */ + if (gpio_pin_get_dt(&cfg->gpio_drdy) > 0) { + hids_2525020210001_handle_drdy_interrupt(dev); + } + + return 0; +} + +static void hids_2525020210001_drdy_callback(const struct device *dev, struct gpio_callback *cb, + uint32_t pins) +{ + struct hids_2525020210001_data *data = + CONTAINER_OF(cb, struct hids_2525020210001_data, data_ready_cb); + + ARG_UNUSED(pins); + + hids_2525020210001_handle_drdy_interrupt(data->dev); +} + +#ifdef CONFIG_WSEN_HIDS_2525020210001_TRIGGER_OWN_THREAD +static void hids_2525020210001_thread(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct hids_2525020210001_data *data = p1; + + while (true) { + k_sem_take(&data->drdy_sem, K_FOREVER); + hids_2525020210001_process_drdy_interrupt(data->dev); + } +} +#endif /* CONFIG_WSEN_HIDS_2525020210001_TRIGGER_OWN_THREAD */ + +#ifdef CONFIG_WSEN_HIDS_2525020210001_TRIGGER_GLOBAL_THREAD +static void hids_2525020210001_work_cb(struct k_work *work) +{ + struct hids_2525020210001_data *data = + CONTAINER_OF(work, struct hids_2525020210001_data, work); + + hids_2525020210001_process_drdy_interrupt(data->dev); +} +#endif /* CONFIG_WSEN_HIDS_2525020210001_TRIGGER_GLOBAL_THREAD */ + +int hids_2525020210001_init_interrupt(const struct device *dev) +{ + struct hids_2525020210001_data *data = dev->data; + const struct hids_2525020210001_config *cfg = dev->config; + int status; + + data->dev = dev; + + if (cfg->gpio_drdy.port == NULL) { + LOG_ERR("drdy-gpios is not defined in the device tree."); + return -EINVAL; + } + + if (!device_is_ready(cfg->gpio_drdy.port)) { + LOG_ERR("Device %s is not ready", cfg->gpio_drdy.port->name); + return -ENODEV; + } + + /* Setup data-ready gpio interrupt */ + status = gpio_pin_configure_dt(&cfg->gpio_drdy, GPIO_INPUT); + if (status < 0) { + LOG_ERR("Could not configure %s.%02u", cfg->gpio_drdy.port->name, + cfg->gpio_drdy.pin); + return status; + } + + gpio_init_callback(&data->data_ready_cb, hids_2525020210001_drdy_callback, + BIT(cfg->gpio_drdy.pin)); + + status = gpio_add_callback(cfg->gpio_drdy.port, &data->data_ready_cb); + if (status < 0) { + LOG_ERR("Could not set gpio callback."); + return status; + } + + /* Enable data-ready interrupt */ + if (HIDS_enableDataReadyInterrupt(&data->sensor_interface, HIDS_enable) != WE_SUCCESS) { + LOG_ERR("Could not enable data-ready interrupt."); + return -EIO; + } + +#if defined(CONFIG_WSEN_HIDS_2525020210001_TRIGGER_OWN_THREAD) + k_sem_init(&data->drdy_sem, 0, K_SEM_MAX_LIMIT); + + k_thread_create(&data->thread, data->thread_stack, + CONFIG_WSEN_HIDS_2525020210001_THREAD_STACK_SIZE, hids_2525020210001_thread, + data, NULL, NULL, + K_PRIO_COOP(CONFIG_WSEN_HIDS_2525020210001_THREAD_PRIORITY), 0, K_NO_WAIT); +#elif defined(CONFIG_WSEN_HIDS_2525020210001_TRIGGER_GLOBAL_THREAD) + data->work.handler = hids_2525020210001_work_cb; +#endif + + hids_2525020210001_setup_drdy_interrupt(dev, true); + + return 0; +} diff --git a/dts/bindings/sensor/we,wsen-hids-2525020210001/we,wsen-hids-2525020210001-common.yaml b/dts/bindings/sensor/we,wsen-hids-2525020210001/we,wsen-hids-2525020210001-common.yaml new file mode 100644 index 000000000000..42fc3c37f607 --- /dev/null +++ b/dts/bindings/sensor/we,wsen-hids-2525020210001/we,wsen-hids-2525020210001-common.yaml @@ -0,0 +1,22 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +include: sensor-device.yaml + +properties: + drdy-gpios: + type: phandle-array + description: | + Data-ready interrupt pin. + Interrupt is active high by default. + + odr: + type: string + required: true + enum: + - "1" + - "7" + - "12.5" + description: | + Sensor output data rate expressed in samples per second. + Data rates supported by the chip are "1", "7" and "12.5". diff --git a/dts/bindings/sensor/we,wsen-hids-2525020210001/we,wsen-hids-2525020210001-i2c.yaml b/dts/bindings/sensor/we,wsen-hids-2525020210001/we,wsen-hids-2525020210001-i2c.yaml new file mode 100644 index 000000000000..0bd59b6d02ca --- /dev/null +++ b/dts/bindings/sensor/we,wsen-hids-2525020210001/we,wsen-hids-2525020210001-i2c.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +description: | + Würth Elektronik WSEN-HIDS-2525020210001 humidity sensor with + integrated temperature sensor (I2C bus) + +compatible: "we,wsen-hids-2525020210001" + +include: ["i2c-device.yaml", "we,wsen-hids-2525020210001-common.yaml"] diff --git a/dts/bindings/sensor/we,wsen-hids-2525020210001/we,wsen-hids-2525020210001-spi.yaml b/dts/bindings/sensor/we,wsen-hids-2525020210001/we,wsen-hids-2525020210001-spi.yaml new file mode 100644 index 000000000000..97e9b3ed21d9 --- /dev/null +++ b/dts/bindings/sensor/we,wsen-hids-2525020210001/we,wsen-hids-2525020210001-spi.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +description: | + Würth Elektronik WSEN-HIDS-2525020210001 humidity sensor with + integrated temperature sensor (SPI bus) + +compatible: "we,wsen-hids-2525020210001" + +include: ["spi-device.yaml", "we,wsen-hids-2525020210001-common.yaml"] diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index ffcad2a8bdac..9c16300ee8b1 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -514,6 +514,13 @@ test_i2c_iis2iclx: iis2iclx@4c { odr = ; }; +test_i2c_wsen_hids_2525020210001: wsen_hids_2525020210001@4d { + compatible = "we,wsen-hids-2525020210001"; + reg = <0x4d>; + drdy-gpios = <&test_gpio 0 0>; + odr = "1"; +}; + test_i2c_max17055: max17055@4f { compatible = "maxim,max17055"; reg = <0x4f>; diff --git a/tests/drivers/build_all/sensor/sensors_trigger_global.conf b/tests/drivers/build_all/sensor/sensors_trigger_global.conf index 19b3129e46ac..22c3204d0bf3 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_global.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_global.conf @@ -63,4 +63,5 @@ CONFIG_TMP007_TRIGGER_GLOBAL_THREAD=y CONFIG_TSL2540_TRIGGER_GLOBAL_THREAD=y CONFIG_TSL2591_TRIGGER_GLOBAL_THREAD=y CONFIG_VCNL4040_TRIGGER_GLOBAL_THREAD=y +CONFIG_WSEN_HIDS_2525020210001_TRIGGER_GLOBAL_THREAD=y CONFIG_WSEN_TIDS_2521020222501_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 848175999fc7..4a0cd6ff3161 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_none.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_none.conf @@ -63,4 +63,5 @@ CONFIG_TMP007_TRIGGER_NONE=y CONFIG_TSL2540_TRIGGER_NONE=y CONFIG_TSL2591_TRIGGER_NONE=y CONFIG_VCNL4040_TRIGGER_NONE=y +CONFIG_WSEN_HIDS_2525020210001_TRIGGER_NONE=y CONFIG_WSEN_TIDS_2521020222501_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 83487c77030b..9e1786d6066a 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_own.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_own.conf @@ -60,4 +60,5 @@ CONFIG_TMP007_TRIGGER_OWN_THREAD=y CONFIG_TSL2540_TRIGGER_OWN_THREAD=y CONFIG_TSL2591_TRIGGER_OWN_THREAD=y CONFIG_VCNL4040_TRIGGER_OWN_THREAD=y +CONFIG_WSEN_HIDS_2525020210001_TRIGGER_OWN_THREAD=y CONFIG_WSEN_TIDS_2521020222501_TRIGGER_OWN_THREAD=y From 41620c0bbd5b97c6f82fe38a8b998477ad29bb5b Mon Sep 17 00:00:00 2001 From: Wajdi ELMuhtadi Date: Tue, 5 Sep 2023 19:10:13 +0200 Subject: [PATCH 11/14] drivers: sensor: wsen_pads_2511020213301: add sensor driver Add wsen_pads_2511020213301 driver with the corrected name and compatibility with the hal update as well as added new features. Signed-off-by: Wajdi ELMuhtadi --- drivers/sensor/wsen/CMakeLists.txt | 1 + drivers/sensor/wsen/Kconfig | 1 + .../wsen_pads_2511020213301/CMakeLists.txt | 7 + .../wsen/wsen_pads_2511020213301/Kconfig | 62 +++ .../wsen_pads_2511020213301.c | 524 ++++++++++++++++++ .../wsen_pads_2511020213301.h | 114 ++++ .../wsen_pads_2511020213301_trigger.c | 341 ++++++++++++ .../we,wsen-pads-2511020213301-common.yaml | 59 ++ .../we,wsen-pads-2511020213301-i2c.yaml | 9 + .../we,wsen-pads-2511020213301-spi.yaml | 9 + .../drivers/sensor/wsen_pads_2511020213301.h | 37 ++ tests/drivers/build_all/sensor/i2c.dtsi | 7 + .../sensor/sensors_trigger_global.conf | 1 + .../sensor/sensors_trigger_none.conf | 1 + .../build_all/sensor/sensors_trigger_own.conf | 1 + 15 files changed, 1174 insertions(+) create mode 100644 drivers/sensor/wsen/wsen_pads_2511020213301/CMakeLists.txt create mode 100644 drivers/sensor/wsen/wsen_pads_2511020213301/Kconfig create mode 100644 drivers/sensor/wsen/wsen_pads_2511020213301/wsen_pads_2511020213301.c create mode 100644 drivers/sensor/wsen/wsen_pads_2511020213301/wsen_pads_2511020213301.h create mode 100644 drivers/sensor/wsen/wsen_pads_2511020213301/wsen_pads_2511020213301_trigger.c create mode 100644 dts/bindings/sensor/we,wsen-pads-2511020213301/we,wsen-pads-2511020213301-common.yaml create mode 100644 dts/bindings/sensor/we,wsen-pads-2511020213301/we,wsen-pads-2511020213301-i2c.yaml create mode 100644 dts/bindings/sensor/we,wsen-pads-2511020213301/we,wsen-pads-2511020213301-spi.yaml create mode 100644 include/zephyr/drivers/sensor/wsen_pads_2511020213301.h diff --git a/drivers/sensor/wsen/CMakeLists.txt b/drivers/sensor/wsen/CMakeLists.txt index 4cc07953f781..ffcb71adc039 100644 --- a/drivers/sensor/wsen/CMakeLists.txt +++ b/drivers/sensor/wsen/CMakeLists.txt @@ -4,6 +4,7 @@ # zephyr-keep-sorted-start add_subdirectory_ifdef(CONFIG_WSEN_HIDS_2525020210001 wsen_hids_2525020210001) add_subdirectory_ifdef(CONFIG_WSEN_HIDS_2525020210002 wsen_hids_2525020210002) +add_subdirectory_ifdef(CONFIG_WSEN_PADS_2511020213301 wsen_pads_2511020213301) add_subdirectory_ifdef(CONFIG_WSEN_PDUS_25131308XXXXX wsen_pdus_25131308XXXXX) add_subdirectory_ifdef(CONFIG_WSEN_TIDS_2521020222501 wsen_tids_2521020222501) # zephyr-keep-sorted-stop diff --git a/drivers/sensor/wsen/Kconfig b/drivers/sensor/wsen/Kconfig index d64d687f0f75..108a13adcee9 100644 --- a/drivers/sensor/wsen/Kconfig +++ b/drivers/sensor/wsen/Kconfig @@ -4,6 +4,7 @@ # zephyr-keep-sorted-start source "drivers/sensor/wsen/wsen_hids_2525020210001/Kconfig" source "drivers/sensor/wsen/wsen_hids_2525020210002/Kconfig" +source "drivers/sensor/wsen/wsen_pads_2511020213301/Kconfig" source "drivers/sensor/wsen/wsen_pdus_25131308XXXXX/Kconfig" source "drivers/sensor/wsen/wsen_tids_2521020222501/Kconfig" # zephyr-keep-sorted-stop diff --git a/drivers/sensor/wsen/wsen_pads_2511020213301/CMakeLists.txt b/drivers/sensor/wsen/wsen_pads_2511020213301/CMakeLists.txt new file mode 100644 index 000000000000..8d4c8682fc94 --- /dev/null +++ b/drivers/sensor/wsen/wsen_pads_2511020213301/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(wsen_pads_2511020213301.c) +zephyr_library_sources_ifdef(CONFIG_WSEN_PADS_2511020213301_TRIGGER wsen_pads_2511020213301_trigger.c) diff --git a/drivers/sensor/wsen/wsen_pads_2511020213301/Kconfig b/drivers/sensor/wsen/wsen_pads_2511020213301/Kconfig new file mode 100644 index 000000000000..7c13c591bf82 --- /dev/null +++ b/drivers/sensor/wsen/wsen_pads_2511020213301/Kconfig @@ -0,0 +1,62 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +menuconfig WSEN_PADS_2511020213301 + bool "WSEN-PADS-2511020213301 absolute pressure and temperature sensor" + default y + depends on DT_HAS_WE_WSEN_PADS_2511020213301_ENABLED + select I2C if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_PADS),i2c) + select SPI if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_PADS),spi) + select HAS_WESENSORS + help + Enable driver for the WSEN-PADS-2511020213301 I2C/SPI-based absolute pressure sensor with integrated + temperature sensor. + +if WSEN_PADS_2511020213301 + +choice WSEN_PADS_2511020213301_TRIGGER_MODE + prompt "Trigger mode" + default WSEN_PADS_2511020213301_TRIGGER_NONE + help + Specify the type of triggering to be used by the driver. + +config WSEN_PADS_2511020213301_TRIGGER_NONE + bool "No trigger" + +config WSEN_PADS_2511020213301_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + depends on GPIO + select WSEN_PADS_2511020213301_TRIGGER + +config WSEN_PADS_2511020213301_TRIGGER_OWN_THREAD + bool "Use own thread" + depends on GPIO + select WSEN_PADS_2511020213301_TRIGGER + +endchoice # WSEN_PADS_2511020213301_TRIGGER_MODE + +config WSEN_PADS_2511020213301_TRIGGER + bool + +config WSEN_PADS_2511020213301_THREAD_PRIORITY + int "Thread priority" + depends on WSEN_PADS_2511020213301_TRIGGER_OWN_THREAD + default 10 + help + Priority of thread used by the driver to handle interrupts. + +config WSEN_PADS_2511020213301_THREAD_STACK_SIZE + int "Thread stack size" + depends on WSEN_PADS_2511020213301_TRIGGER_OWN_THREAD + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + +config WSEN_PADS_2511020213301_PRESSURE_THRESHOLD + bool "Pressure threshold triggers" + depends on WSEN_PADS_2511020213301_TRIGGER + help + Allows you to set up triggers for high and/or low pressure thresholds. + if activated then data ready trigger can't be set up. + +endif # WSEN_PADS_2511020213301 diff --git a/drivers/sensor/wsen/wsen_pads_2511020213301/wsen_pads_2511020213301.c b/drivers/sensor/wsen/wsen_pads_2511020213301/wsen_pads_2511020213301.c new file mode 100644 index 000000000000..030a50268934 --- /dev/null +++ b/drivers/sensor/wsen/wsen_pads_2511020213301/wsen_pads_2511020213301.c @@ -0,0 +1,524 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT we_wsen_pads_2511020213301 + +#include + +#include +#include +#include + +#include "wsen_pads_2511020213301.h" + +LOG_MODULE_REGISTER(WSEN_PADS_2511020213301, CONFIG_SENSOR_LOG_LEVEL); + +/* + * List of supported output data rates. Index into this list is used as + * argument for PADS_setOutputDataRate() + */ +static const int32_t pads_2511020213301_odr_list[] = { + 0, 1, 10, 25, 50, 75, 100, 200, +}; + +#define SAMPLES_TO_DISCARD (uint8_t)2 + +#define MAX_POLL_STEP_COUNT 10 + +static int pads_2511020213301_sample_fetch(const struct device *dev, enum sensor_channel channel) +{ + struct pads_2511020213301_data *data = dev->data; + const struct pads_2511020213301_config *cfg = dev->config; + + switch (channel) { + case SENSOR_CHAN_ALL: + case SENSOR_CHAN_AMBIENT_TEMP: + case SENSOR_CHAN_PRESS: + break; + default: + LOG_ERR("Fetching is not supported on channel %d.", channel); + return -ENOTSUP; + } + + if (data->sensor_odr == PADS_outputDataRatePowerDown) { + if (PADS_enableOneShot(&data->sensor_interface, PADS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "pressure"); + return -EIO; + } + + switch (cfg->configuration) { + case PADS_lowPower: + k_sleep(K_USEC(4700)); + break; + case PADS_lowNoise: + k_sleep(K_USEC(13200)); + break; + default: + LOG_ERR("Invalid sensor configuration"); + return -EIO; + } + + PADS_state_t one_shot_state; + + do { + if (PADS_isOneShotEnabled(&data->sensor_interface, &one_shot_state) != + WE_SUCCESS) { + LOG_ERR("Failed to check for data ready"); + return -EIO; + } + } while (PADS_enable == one_shot_state); + } else { + + bool data_ready = false; + int step_count = 0; + uint32_t step_sleep_duration = + ((uint32_t)1000000000 / + (pads_2511020213301_odr_list[data->sensor_odr] * 1000)) / + MAX_POLL_STEP_COUNT; + + while (1) { + PADS_state_t pressure_state, temp_state; + + pressure_state = temp_state = PADS_disable; + + if (PADS_isDataAvailable(&data->sensor_interface, &temp_state, + &pressure_state) != WE_SUCCESS) { + LOG_ERR("Failed to check for data available"); + return -EIO; + } + + switch (channel) { + case SENSOR_CHAN_ALL: + data_ready = (pressure_state == PADS_enable && + temp_state == PADS_enable); + break; + case SENSOR_CHAN_AMBIENT_TEMP: + data_ready = (temp_state == PADS_enable); + break; + case SENSOR_CHAN_PRESS: + data_ready = (pressure_state == PADS_enable); + break; + default: + break; + } + + if (data_ready) { + break; + } else if (step_count >= MAX_POLL_STEP_COUNT) { + return -EIO; + } + + step_count++; + k_sleep(K_USEC(step_sleep_duration)); + } + } + + switch (channel) { + case SENSOR_CHAN_ALL: { + + if (PADS_getPressure_int(&data->sensor_interface, &data->pressure) != WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "pressure"); + return -EIO; + } + + if (PADS_getTemperature_int(&data->sensor_interface, &data->temperature) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "temperature"); + return -EIO; + } + + break; + } + case SENSOR_CHAN_AMBIENT_TEMP: { + + if (PADS_getTemperature_int(&data->sensor_interface, &data->temperature) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "temperature"); + return -EIO; + } + + break; + } + case SENSOR_CHAN_PRESS: { + + if (PADS_getPressure_int(&data->sensor_interface, &data->pressure) != WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "pressure"); + return -EIO; + } + + break; + } + default: + break; + } + + return 0; +} + +static int pads_2511020213301_channel_get(const struct device *dev, enum sensor_channel channel, + struct sensor_value *value) +{ + struct pads_2511020213301_data *data = dev->data; + + switch (channel) { + case SENSOR_CHAN_AMBIENT_TEMP: + /* Convert temperature from 0.01 degrees Celsius to degrees Celsius */ + value->val1 = data->temperature / 100; + value->val2 = ((int32_t)data->temperature % 100) * (1000000 / 100); + break; + case SENSOR_CHAN_PRESS: + /* Convert pressure from Pa to kPa */ + value->val1 = data->pressure / 1000; + value->val2 = ((int32_t)data->pressure % 1000) * (1000000 / 1000); + break; + default: + LOG_ERR("Channel not supported %d", channel); + return -ENOTSUP; + } + + return 0; +} + +/* Set output data rate. See pads_2511020213301_odr_list for allowed values. */ +static int pads_2511020213301_odr_set(const struct device *dev, const struct sensor_value *odr) +{ + struct pads_2511020213301_data *data = dev->data; + const struct pads_2511020213301_config *cfg = dev->config; + int odr_index; + + for (odr_index = 0; odr_index < ARRAY_SIZE(pads_2511020213301_odr_list); odr_index++) { + if (odr->val1 == pads_2511020213301_odr_list[odr_index] && odr->val2 == 0) { + break; + } + } + + if (odr_index == ARRAY_SIZE(pads_2511020213301_odr_list)) { + /* ODR not allowed (was not found in pads_2511020213301_odr_list) */ + LOG_ERR("Bad sampling frequency %d.%d", odr->val1, odr->val2); + return -EINVAL; + } + + if (cfg->configuration == PADS_lowNoise && + (PADS_outputDataRate_t)odr_index > PADS_outputDataRate75Hz) { + LOG_ERR("Failed to set ODR > 75Hz is not possible with low noise sensor " + "configuration."); + return -EIO; + } + + if (PADS_setOutputDataRate(&data->sensor_interface, (PADS_outputDataRate_t)odr_index) != + WE_SUCCESS) { + LOG_ERR("Failed to set output data rate"); + return -EIO; + } + + if (PADS_enableBlockDataUpdate(&data->sensor_interface, + (PADS_outputDataRate_t)odr_index != + PADS_outputDataRatePowerDown + ? PADS_enable + : PADS_disable) != WE_SUCCESS) { + LOG_ERR("Failed to enable block data update."); + return -EIO; + } + + data->sensor_odr = (PADS_outputDataRate_t)odr_index; + + return 0; +} + +/* Get output data rate. */ +static int pads_2511020213301_odr_get(const struct device *dev, struct sensor_value *odr) +{ + + struct pads_2511020213301_data *data = dev->data; + + PADS_outputDataRate_t odr_index; + + if (PADS_getOutputDataRate(&data->sensor_interface, &odr_index) != WE_SUCCESS) { + LOG_ERR("Failed to get output data rate"); + return -EIO; + } + + data->sensor_odr = odr_index; + + odr->val1 = pads_2511020213301_odr_list[odr_index]; + odr->val2 = 0; + + return 0; +} + +static int pads_2511020213301_attr_get(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, struct sensor_value *val) +{ + + if (val == NULL) { + LOG_WRN("address of passed value is NULL."); + return -EFAULT; + } + + switch ((int)attr) { + case SENSOR_ATTR_SAMPLING_FREQUENCY: + if (chan != SENSOR_CHAN_ALL) { + LOG_ERR("attr_get() is not supported on channel %d.", chan); + return -ENOTSUP; + } + return pads_2511020213301_odr_get(dev, val); +#ifdef CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD + case SENSOR_ATTR_WSEN_PADS_2511020213301_REFERENCE_POINT: + if (chan != SENSOR_CHAN_PRESS) { + LOG_ERR("attr_get() is not supported on channel %d.", chan); + return -ENOTSUP; + } + return pads_2511020213301_reference_point_get(dev, val); + case SENSOR_ATTR_UPPER_THRESH: + case SENSOR_ATTR_LOWER_THRESH: + if (chan != SENSOR_CHAN_PRESS) { + LOG_ERR("attr_get() is not supported on channel %d.", chan); + return -ENOTSUP; + } + return pads_2511020213301_threshold_get(dev, val); +#endif + default: + LOG_ERR("Operation not supported."); + return -ENOTSUP; + } + + return 0; +} + +static int pads_2511020213301_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + switch ((int)attr) { + case SENSOR_ATTR_SAMPLING_FREQUENCY: + if (chan != SENSOR_CHAN_ALL) { + LOG_ERR("attr_set() is not supported on channel %d.", chan); + return -ENOTSUP; + } + return pads_2511020213301_odr_set(dev, val); +#ifdef CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD + case SENSOR_ATTR_WSEN_PADS_2511020213301_REFERENCE_POINT: + if (chan != SENSOR_CHAN_PRESS) { + LOG_ERR("attr_set() is not supported on channel %d.", chan); + return -ENOTSUP; + } + return pads_2511020213301_reference_point_set(dev, val); + case SENSOR_ATTR_UPPER_THRESH: + case SENSOR_ATTR_LOWER_THRESH: + if (chan != SENSOR_CHAN_PRESS) { + LOG_ERR("attr_set() is not supported on channel %d.", chan); + return -ENOTSUP; + } + return pads_2511020213301_threshold_set(dev, val); +#endif + default: + LOG_ERR("Operation not supported."); + return -ENOTSUP; + } +} + +static const struct sensor_driver_api pads_2511020213301_driver_api = { + .attr_set = pads_2511020213301_attr_set, +#if CONFIG_WSEN_PADS_2511020213301_TRIGGER + .trigger_set = pads_2511020213301_trigger_set, +#endif + .attr_get = pads_2511020213301_attr_get, + .sample_fetch = pads_2511020213301_sample_fetch, + .channel_get = pads_2511020213301_channel_get, +}; + +static int pads_2511020213301_init(const struct device *dev) +{ + const struct pads_2511020213301_config *config = dev->config; + struct pads_2511020213301_data *data = dev->data; + struct sensor_value odr; + uint8_t device_id; + + /* Initialize WE sensor interface */ + WE_sensorInterfaceType_t interface_type = data->sensor_interface.interfaceType; + + PADS_getDefaultInterface(&data->sensor_interface); + data->sensor_interface.interfaceType = interface_type; + + switch (data->sensor_interface.interfaceType) { +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) + case WE_i2c: + if (!i2c_is_ready_dt(&config->bus_cfg.i2c)) { + LOG_ERR("I2C bus device not ready"); + return -ENODEV; + } + data->sensor_interface.handle = (void *)&config->bus_cfg.i2c; + break; +#endif +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) + case WE_spi: + if (!spi_is_ready_dt(&config->bus_cfg.spi)) { + LOG_ERR("SPI bus device not ready"); + return -ENODEV; + } + data->sensor_interface.handle = (void *)&config->bus_cfg.spi; + break; +#endif + default: + LOG_ERR("Invalid interface type"); + return -EINVAL; + } + + /* needed after power up */ + k_sleep(K_USEC(4500)); + + PADS_state_t boot_state = PADS_enable; + + do { + if (PADS_getBootStatus(&data->sensor_interface, &boot_state) != WE_SUCCESS) { + LOG_ERR("Failed to get sensor reset state."); + return -EIO; + } + } while (PADS_enable == boot_state); + + /* First communication test - check device ID */ + if (PADS_getDeviceID(&data->sensor_interface, &device_id) != WE_SUCCESS) { + LOG_ERR("Failed to read device ID."); + return -EIO; + } + + if (device_id != PADS_DEVICE_ID_VALUE) { + LOG_ERR("Invalid device ID 0x%x.", device_id); + return -EINVAL; + } + + /* Reset sensor */ + PADS_softReset(&data->sensor_interface, PADS_enable); + k_sleep(K_USEC(50)); + + PADS_state_t sw_reset; + + do { + if (PADS_getSoftResetState(&data->sensor_interface, &sw_reset) != WE_SUCCESS) { + LOG_ERR("Failed to get sensor reset state."); + return -EIO; + } + } while (PADS_enable == sw_reset); + + if (PADS_setPowerMode(&data->sensor_interface, config->configuration) != WE_SUCCESS) { + LOG_ERR("Failed to set sensor configuration."); + return -EIO; + } + + odr.val1 = pads_2511020213301_odr_list[config->odr]; + odr.val2 = 0; + + if (pads_2511020213301_odr_set(dev, &odr) < 0) { + LOG_ERR("Failed to set output data rate."); + return -EIO; + } + + if (PADS_enableLowPassFilter(&data->sensor_interface, config->alpf) != WE_SUCCESS) { + LOG_ERR("Failed to set additional low pass filter."); + return -EIO; + } + + if (config->alpf == PADS_enable) { + if (PADS_setLowPassFilterConfig(&data->sensor_interface, + config->alpf_configuration) != WE_SUCCESS) { + LOG_ERR("Failed to set additional low pass filter configuration."); + return -EIO; + } + + for (uint8_t i = 0; i < SAMPLES_TO_DISCARD; i++) { + pads_2511020213301_sample_fetch(dev, SENSOR_CHAN_ALL); + } + + data->pressure = 0; + data->temperature = 0; + } + +#if CONFIG_WSEN_PADS_2511020213301_TRIGGER + if (pads_2511020213301_init_interrupt(dev) < 0) { + LOG_ERR("Failed to initialize interrupt."); + return -EIO; + } +#endif + + return 0; +} + +#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0 +#warning "PADS driver enabled without any devices" +#endif + +#ifdef CONFIG_WSEN_PADS_2511020213301_TRIGGER +#define PADS_2511020213301_CFG_IRQ(inst) \ + .interrupt_gpio = GPIO_DT_SPEC_INST_GET(inst, interrupt_gpios) +#else +#define PADS_2511020213301_CFG_IRQ(inst) +#endif /* CONFIG_WSEN_PADS_2511020213301_TRIGGER */ + +#ifdef CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD +#define PADS_2511020213301_CFG_THRESHOLD(inst) \ + .threshold = (uint16_t)DT_INST_PROP_OR(inst, threshold, 0), +#else +#define PADS_2511020213301_CFG_THRESHOLD(inst) +#endif /* CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD */ + +#define PADS_2511020213301_CONFIG_COMMON(inst) \ + .odr = (PADS_outputDataRate_t)(DT_INST_ENUM_IDX(inst, odr)), \ + .configuration = (PADS_powerMode_t)(DT_INST_ENUM_IDX(inst, configuration)), \ + PADS_2511020213301_CFG_THRESHOLD(inst).alpf_configuration = \ + (PADS_filterConf_t)DT_INST_PROP(inst, additional_low_pass_filter_configuration), \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, additional_low_pass_filter), \ + (.alpf = PADS_enable), (.alpf = PADS_disable)), \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, interrupt_gpios), \ + (PADS_2511020213301_CFG_IRQ(inst)), ()) + +/* + * Instantiation macros used when device is on SPI bus. + */ + +#define PADS_2511020213301_SPI_OPERATION \ + (SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA) + +#define PADS_2511020213301_CONFIG_SPI(inst) \ + { \ + .bus_cfg = \ + { \ + .spi = SPI_DT_SPEC_INST_GET(inst, \ + PADS_2511020213301_SPI_OPERATION, 0), \ + }, \ + PADS_2511020213301_CONFIG_COMMON(inst) \ + } + +/* + * Instantiation macros used when device is on I2C bus. + */ + +#define PADS_2511020213301_CONFIG_I2C(inst) \ + { \ + .bus_cfg = \ + { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }, \ + PADS_2511020213301_CONFIG_COMMON(inst) \ + } + +/* + * Main instantiation macro. Use of COND_CODE_1() selects the right + * bus-specific macro at preprocessor time. + */ +#define PADS_2511020213301_DEFINE(inst) \ + static struct pads_2511020213301_data pads_2511020213301_data_##inst = COND_CODE_1( \ + DT_INST_ON_BUS(inst, i2c), ({.sensor_interface = {.interfaceType = WE_i2c}}), ()) \ + COND_CODE_1(DT_INST_ON_BUS(inst, spi), \ + ({.sensor_interface = {.interfaceType = WE_spi}}), ()); \ + static const struct pads_2511020213301_config pads_2511020213301_config_##inst = \ + COND_CODE_1(DT_INST_ON_BUS(inst, i2c), (PADS_2511020213301_CONFIG_I2C(inst)), ()) \ + COND_CODE_1(DT_INST_ON_BUS(inst, spi), \ + (PADS_2511020213301_CONFIG_SPI(inst)), ()); \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, pads_2511020213301_init, NULL, \ + &pads_2511020213301_data_##inst, \ + &pads_2511020213301_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &pads_2511020213301_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(PADS_2511020213301_DEFINE) diff --git a/drivers/sensor/wsen/wsen_pads_2511020213301/wsen_pads_2511020213301.h b/drivers/sensor/wsen/wsen_pads_2511020213301/wsen_pads_2511020213301.h new file mode 100644 index 000000000000..3eb9971cd05e --- /dev/null +++ b/drivers/sensor/wsen/wsen_pads_2511020213301/wsen_pads_2511020213301.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_WSEN_PADS_2511020213301_WSEN_PADS_2511020213301_H_ +#define ZEPHYR_DRIVERS_SENSOR_WSEN_PADS_2511020213301_WSEN_PADS_2511020213301_H_ + +#include +#include + +#include + +#include "WSEN_PADS_2511020213301_hal.h" +#include + +#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) */ + +struct pads_2511020213301_data { + /* WE sensor interface configuration */ + WE_sensorInterface_t sensor_interface; + + /* Last pressure sample */ + int32_t pressure; + + /* Last temperature sample */ + int16_t temperature; + + PADS_outputDataRate_t sensor_odr; + +#ifdef CONFIG_WSEN_PADS_2511020213301_TRIGGER + const struct device *dev; + + struct gpio_callback interrupt_cb; + +#ifdef CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD + sensor_trigger_handler_t pressure_high_trigger_handler; + sensor_trigger_handler_t pressure_low_trigger_handler; + const struct sensor_trigger *pressure_high_trigger; + const struct sensor_trigger *pressure_low_trigger; +#else + sensor_trigger_handler_t data_ready_trigger_handler; + const struct sensor_trigger *data_ready_trigger; +#endif /* CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD */ + +#if defined(CONFIG_WSEN_PADS_2511020213301_TRIGGER_OWN_THREAD) + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_WSEN_PADS_2511020213301_THREAD_STACK_SIZE); + struct k_thread thread; + struct k_sem sem; +#elif defined(CONFIG_WSEN_PADS_2511020213301_TRIGGER_GLOBAL_THREAD) + struct k_work work; +#endif +#endif /* CONFIG_WSEN_PADS_2511020213301_TRIGGER */ +}; + +struct pads_2511020213301_config { + 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 + } bus_cfg; + + /* Output data rate */ + const PADS_outputDataRate_t odr; + + const PADS_powerMode_t configuration; + + const PADS_state_t alpf; + + const PADS_filterConf_t alpf_configuration; +#ifdef CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD + const uint16_t threshold; +#endif /* CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD */ +#ifdef CONFIG_WSEN_PADS_2511020213301_TRIGGER + /* Interrupt pin */ + const struct gpio_dt_spec interrupt_gpio; +#endif /* CONFIG_WSEN_PADS_2511020213301_TRIGGER */ +}; + +#ifdef CONFIG_WSEN_PADS_2511020213301_TRIGGER +int pads_2511020213301_trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); + +int pads_2511020213301_init_interrupt(const struct device *dev); + +#ifdef CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD +int pads_2511020213301_threshold_set(const struct device *dev, + const struct sensor_value *threshold); + +int pads_2511020213301_threshold_get(const struct device *dev, struct sensor_value *threshold); + +int pads_2511020213301_reference_point_set(const struct device *dev, + const struct sensor_value *reference_point); + +int pads_2511020213301_reference_point_get(const struct device *dev, + struct sensor_value *reference_point); + +#endif /* CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD */ +#endif /* CONFIG_WSEN_PADS_2511020213301_TRIGGER */ + +int pads_2511020213301_spi_init(const struct device *dev); +int pads_2511020213301_i2c_init(const struct device *dev); + +#endif /* ZEPHYR_DRIVERS_SENSOR_WSEN_PADS_2511020213301_WSEN_PADS_2511020213301_H_ */ diff --git a/drivers/sensor/wsen/wsen_pads_2511020213301/wsen_pads_2511020213301_trigger.c b/drivers/sensor/wsen/wsen_pads_2511020213301/wsen_pads_2511020213301_trigger.c new file mode 100644 index 000000000000..f90afaa2716b --- /dev/null +++ b/drivers/sensor/wsen/wsen_pads_2511020213301/wsen_pads_2511020213301_trigger.c @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT we_wsen_pads_2511020213301 + +#include + +#include "wsen_pads_2511020213301.h" + +LOG_MODULE_DECLARE(WSEN_PADS_2511020213301, CONFIG_SENSOR_LOG_LEVEL); + +/* Enable/disable data-ready interrupt handling */ +static inline int pads_2511020213301_setup_interrupt(const struct device *dev, bool enable) +{ + const struct pads_2511020213301_config *cfg = dev->config; + unsigned int flags = enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE; + + return gpio_pin_interrupt_configure_dt(&cfg->interrupt_gpio, flags); +} + +/* + * Is called when an interrupt has occurred. + */ +static inline void pads_2511020213301_handle_interrupt(const struct device *dev) +{ + struct pads_2511020213301_data *data = dev->data; + + /* Disable interrupt handling until the interrupt has been processed */ + pads_2511020213301_setup_interrupt(dev, false); + +#if defined(CONFIG_WSEN_PADS_2511020213301_TRIGGER_OWN_THREAD) + k_sem_give(&data->sem); +#elif defined(CONFIG_WSEN_PADS_2511020213301_TRIGGER_GLOBAL_THREAD) + k_work_submit(&data->work); +#endif +} + +/* Calls data-ready trigger handler (if any) */ +static void pads_2511020213301_process_interrupt(const struct device *dev) +{ + struct pads_2511020213301_data *data = dev->data; + +#ifdef CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD + if (data->pressure_low_trigger_handler != NULL || + data->pressure_high_trigger_handler != NULL) { + PADS_state_t pressure_high_state, pressure_low_state; + + if (PADS_getHighPressureInterruptStatus(&data->sensor_interface, + &pressure_high_state) != WE_SUCCESS) { + LOG_ERR("Failed to read pressure high state"); + return; + } + + if (PADS_getLowPressureInterruptStatus(&data->sensor_interface, + &pressure_low_state) != WE_SUCCESS) { + LOG_ERR("Failed to read pressure high state"); + return; + } + + if (data->pressure_high_trigger_handler != NULL && + pressure_high_state == PADS_enable) { + data->pressure_high_trigger_handler(dev, data->pressure_high_trigger); + } else if (data->pressure_low_trigger_handler != NULL && + pressure_low_state == PADS_enable) { + data->pressure_low_trigger_handler(dev, data->pressure_low_trigger); + } + } +#else + if (data->data_ready_trigger_handler != NULL) { + data->data_ready_trigger_handler(dev, data->data_ready_trigger); + } +#endif /* CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD */ + + pads_2511020213301_setup_interrupt(dev, true); +} + +int pads_2511020213301_trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + struct pads_2511020213301_data *data = dev->data; + const struct pads_2511020213301_config *cfg = dev->config; + + if (trig->chan != SENSOR_CHAN_PRESS) { + LOG_ERR("Unsupported sensor trigger"); + return -ENOTSUP; + } + + switch ((int)trig->type) { +#ifdef CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD + case SENSOR_TRIG_WSEN_PADS_2511020213301_THRESHOLD_LOWER: + case SENSOR_TRIG_WSEN_PADS_2511020213301_THRESHOLD_UPPER: { + switch ((int)trig->type) { + case SENSOR_TRIG_WSEN_PADS_2511020213301_THRESHOLD_LOWER: + data->pressure_low_trigger_handler = handler; + data->pressure_low_trigger = trig; + break; + case SENSOR_TRIG_WSEN_PADS_2511020213301_THRESHOLD_UPPER: + data->pressure_high_trigger_handler = handler; + data->pressure_high_trigger = trig; + break; + default: + break; + } + + if (PADS_setInterruptEventControl(&data->sensor_interface, + PADS_pressureHighOrLow) != WE_SUCCESS) { + LOG_ERR("Failed to set interrupt event control to pressure high or low"); + return -EIO; + } + + if (PADS_enableDiffPressureInterrupt(&data->sensor_interface, + (data->pressure_high_trigger_handler || + data->pressure_low_trigger_handler) + ? PADS_enable + : PADS_disable) != WE_SUCCESS) { + LOG_ERR("Failed to enable pressure diff interrupt."); + return -EIO; + } + + if (PADS_enableLowPressureInterrupt(&data->sensor_interface, + (data->pressure_low_trigger_handler == NULL) + ? PADS_disable + : PADS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable low pressure interrupt."); + return -EIO; + } + if (PADS_enableHighPressureInterrupt(&data->sensor_interface, + (data->pressure_high_trigger_handler == NULL) + ? PADS_disable + : PADS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable high pressure interrupt."); + return -EIO; + } + + pads_2511020213301_setup_interrupt(dev, data->pressure_high_trigger_handler || + data->pressure_low_trigger_handler); + break; + } +#else + case SENSOR_TRIG_DATA_READY: { + int32_t pressure_dummy; + /* Read pressure to retrigger interrupt */ + if (PADS_getPressure_int(&data->sensor_interface, &pressure_dummy) != WE_SUCCESS) { + LOG_ERR("Failed to read sample"); + return -EIO; + } + + if (PADS_setInterruptEventControl(&data->sensor_interface, PADS_dataReady)) { + LOG_ERR("Failed to set interrupt event control to data ready"); + return -EIO; + } + + /* Enable data-ready interrupt */ + if (PADS_enableDataReadyInterrupt(&data->sensor_interface, + (handler == NULL) ? PADS_disable : PADS_enable) != + WE_SUCCESS) { + LOG_ERR("Failed to enable data-ready interrupt."); + return -EIO; + } + + data->data_ready_trigger_handler = handler; + data->data_ready_trigger = trig; + + pads_2511020213301_setup_interrupt(dev, data->data_ready_trigger_handler); + + break; + } +#endif /* CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD */ + default: + LOG_ERR("Unsupported sensor trigger"); + return -ENOTSUP; + } + + if (gpio_pin_get_dt(&cfg->interrupt_gpio) > 0) { + pads_2511020213301_handle_interrupt(dev); + } + + return 0; +} + +static void pads_2511020213301_callback(const struct device *dev, struct gpio_callback *cb, + uint32_t pins) +{ + struct pads_2511020213301_data *data = + CONTAINER_OF(cb, struct pads_2511020213301_data, interrupt_cb); + + ARG_UNUSED(pins); + + pads_2511020213301_handle_interrupt(data->dev); +} + +#ifdef CONFIG_WSEN_PADS_2511020213301_TRIGGER_OWN_THREAD +static void pads_2511020213301_thread(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct pads_2511020213301_data *data = p1; + + while (true) { + k_sem_take(&data->sem, K_FOREVER); + pads_2511020213301_process_interrupt(data->dev); + } +} +#endif /* CONFIG_WSEN_PADS_2511020213301_TRIGGER_OWN_THREAD */ + +#ifdef CONFIG_WSEN_PADS_2511020213301_TRIGGER_GLOBAL_THREAD +static void pads_2511020213301_work_cb(struct k_work *work) +{ + struct pads_2511020213301_data *data = + CONTAINER_OF(work, struct pads_2511020213301_data, work); + + pads_2511020213301_process_interrupt(data->dev); +} +#endif /* CONFIG_WSEN_PADS_2511020213301_TRIGGER_GLOBAL_THREAD */ + +#ifdef CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD +/* Set threshold for the differential pressure interrupt. */ +int pads_2511020213301_threshold_set(const struct device *dev, const struct sensor_value *threshold) +{ + struct pads_2511020213301_data *data = dev->data; + + if (PADS_setPressureThreshold(&data->sensor_interface, (uint32_t)threshold->val1) != + WE_SUCCESS) { + LOG_ERR("Failed to set threshold"); + return -EIO; + } + + return 0; +} + +/* Get threshold for the differential pressure interrupt. */ +int pads_2511020213301_threshold_get(const struct device *dev, struct sensor_value *threshold) +{ + + struct pads_2511020213301_data *data = dev->data; + + if (PADS_getPressureThreshold(&data->sensor_interface, (uint32_t *)&threshold->val1) != + WE_SUCCESS) { + LOG_ERR("Failed to get threshold"); + return -EIO; + } + + return 0; +} + +/* Set reference point to current measured pressure state. */ +int pads_2511020213301_reference_point_set(const struct device *dev, + const struct sensor_value *reference_point) +{ + struct pads_2511020213301_data *data = dev->data; + + if (reference_point != NULL) { + LOG_ERR("Sensor value should be null"); + return -EIO; + } + + if (PADS_enableAutoRefp(&data->sensor_interface, PADS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to set additional low pass filter"); + return -EIO; + } + + return 0; +} + +/* Get reference point from registers. */ +int pads_2511020213301_reference_point_get(const struct device *dev, + struct sensor_value *reference_point) +{ + + struct pads_2511020213301_data *data = dev->data; + + if (PADS_getReferencePressure(&data->sensor_interface, + (uint32_t *)&reference_point->val1) != WE_SUCCESS) { + LOG_ERR("Failed to get reference point"); + return -EIO; + } + + return 0; +} +#endif /* CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD */ + +int pads_2511020213301_init_interrupt(const struct device *dev) +{ + struct pads_2511020213301_data *data = dev->data; + const struct pads_2511020213301_config *cfg = dev->config; + + data->dev = dev; + + if (cfg->interrupt_gpio.port == NULL) { + LOG_ERR("interrupt-gpio is not defined in the device tree."); + return -EINVAL; + } + + if (!gpio_is_ready_dt(&cfg->interrupt_gpio)) { + LOG_ERR("Device %s is not ready", cfg->interrupt_gpio.port->name); + return -ENODEV; + } + + if (gpio_pin_configure_dt(&cfg->interrupt_gpio, GPIO_INPUT) < 0) { + LOG_ERR("Failed to configure %s.%02u", cfg->interrupt_gpio.port->name, + cfg->interrupt_gpio.pin); + return -EIO; + } + + gpio_init_callback(&data->interrupt_cb, pads_2511020213301_callback, + BIT(cfg->interrupt_gpio.pin)); + + if (gpio_add_callback(cfg->interrupt_gpio.port, &data->interrupt_cb) < 0) { + LOG_ERR("Failed to set gpio callback."); + return -EIO; + } +#ifdef CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD + + struct sensor_value threshold; + + threshold.val1 = cfg->threshold; + threshold.val2 = 0; + if (pads_2511020213301_threshold_set(dev, &threshold) < 0) { + LOG_ERR("Failed to set threshold."); + return -EIO; + } + +#endif /* CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD */ + +#if defined(CONFIG_WSEN_PADS_2511020213301_TRIGGER_OWN_THREAD) + k_sem_init(&data->sem, 0, K_SEM_MAX_LIMIT); + + k_thread_create(&data->thread, data->thread_stack, + CONFIG_WSEN_PADS_2511020213301_THREAD_STACK_SIZE, pads_2511020213301_thread, + data, NULL, NULL, + K_PRIO_COOP(CONFIG_WSEN_PADS_2511020213301_THREAD_PRIORITY), 0, K_NO_WAIT); +#elif defined(CONFIG_WSEN_PADS_2511020213301_TRIGGER_GLOBAL_THREAD) + data->work.handler = pads_2511020213301_work_cb; +#endif + + return 0; +} diff --git a/dts/bindings/sensor/we,wsen-pads-2511020213301/we,wsen-pads-2511020213301-common.yaml b/dts/bindings/sensor/we,wsen-pads-2511020213301/we,wsen-pads-2511020213301-common.yaml new file mode 100644 index 000000000000..016a3a3b4d53 --- /dev/null +++ b/dts/bindings/sensor/we,wsen-pads-2511020213301/we,wsen-pads-2511020213301-common.yaml @@ -0,0 +1,59 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +include: sensor-device.yaml + +properties: + interrupt-gpios: + type: phandle-array + description: | + Interrupt pin. + Interrupt is active high by default. + + odr: + type: int + required: true + enum: + - 0 + - 1 + - 10 + - 25 + - 50 + - 75 + - 100 + - 200 + description: | + Sensor output data rate expressed in samples per second. + Data rates supported by the chip are 0 (power down), 1, + 10, 25, 50, 75, 100 and 200. + + configuration: + type: string + default: "Low_Power" + enum: + - "Low_Power" + - "Low_Noise" + description: | + Configuration of sensor to either be low power or low noise. + Maximum ODR in Low Noise configuration is 75Hz. + Defaults to Low_Power, which is the configuration at power-up. + + additional-low-pass-filter: + type: boolean + description: | + Enable or disable the addtional low pass filter of the sensor. + + additional-low-pass-filter-configuration: + type: int + default: 0 + enum: + - 0 + - 1 + description: | + Configuration of the addtional low pass filter of the sensor. + Defaults to 0, which is the configuration at power-up. + + threshold: + type: int + description: | + Threshold for the differential pressure interrupt in Pa. diff --git a/dts/bindings/sensor/we,wsen-pads-2511020213301/we,wsen-pads-2511020213301-i2c.yaml b/dts/bindings/sensor/we,wsen-pads-2511020213301/we,wsen-pads-2511020213301-i2c.yaml new file mode 100644 index 000000000000..dd5cad4e7fde --- /dev/null +++ b/dts/bindings/sensor/we,wsen-pads-2511020213301/we,wsen-pads-2511020213301-i2c.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +description: | + Würth Elektronik WSEN-PADS-2511020213301 absolute pressure sensor (I2C bus) + +compatible: "we,wsen-pads-2511020213301" + +include: ["i2c-device.yaml", "we,wsen-pads-2511020213301-common.yaml"] diff --git a/dts/bindings/sensor/we,wsen-pads-2511020213301/we,wsen-pads-2511020213301-spi.yaml b/dts/bindings/sensor/we,wsen-pads-2511020213301/we,wsen-pads-2511020213301-spi.yaml new file mode 100644 index 000000000000..b585f60cb6da --- /dev/null +++ b/dts/bindings/sensor/we,wsen-pads-2511020213301/we,wsen-pads-2511020213301-spi.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +description: | + Würth Elektronik WSEN-PADS-2511020213301 absolute pressure sensor (SPI bus) + +compatible: "we,wsen-pads-2511020213301" + +include: ["spi-device.yaml", "we,wsen-pads-2511020213301-common.yaml"] diff --git a/include/zephyr/drivers/sensor/wsen_pads_2511020213301.h b/include/zephyr/drivers/sensor/wsen_pads_2511020213301.h new file mode 100644 index 000000000000..3926de95982b --- /dev/null +++ b/include/zephyr/drivers/sensor/wsen_pads_2511020213301.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Extended public API for WSEN-PADS-2511020213301 Sensor + * + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_WSEN_PADS_2511020213301_H_ +#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_WSEN_PADS_2511020213301_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +enum sensor_attribute_wsen_pads_2511020213301 { + SENSOR_ATTR_WSEN_PADS_2511020213301_REFERENCE_POINT = SENSOR_ATTR_PRIV_START, +}; + +#ifdef CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD +enum sensor_trigger_wsen_pads_2511020213301 { + SENSOR_TRIG_WSEN_PADS_2511020213301_THRESHOLD_UPPER = SENSOR_TRIG_PRIV_START, + SENSOR_TRIG_WSEN_PADS_2511020213301_THRESHOLD_LOWER, +}; +#endif /* CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_WSEN_PADS_2511020213301_H_ */ diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index 9c16300ee8b1..db19c89f5d64 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -682,6 +682,13 @@ test_i2c_tmd2620: tmd2620@62 { wait-time-factor = <0>; }; +test_i2c_wsen_pads_2511020213301: wsen_pads_2511020213301@63 { + compatible = "we,wsen-pads-2511020213301"; + reg = <0x63>; + interrupt-gpios = <&test_gpio 0 0>; + odr = <10>; +}; + test_i2c_s11059: s11059@64 { compatible = "hamamatsu,s11059"; reg = <0x64>; diff --git a/tests/drivers/build_all/sensor/sensors_trigger_global.conf b/tests/drivers/build_all/sensor/sensors_trigger_global.conf index 22c3204d0bf3..f31f3073c685 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_global.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_global.conf @@ -64,4 +64,5 @@ CONFIG_TSL2540_TRIGGER_GLOBAL_THREAD=y CONFIG_TSL2591_TRIGGER_GLOBAL_THREAD=y CONFIG_VCNL4040_TRIGGER_GLOBAL_THREAD=y CONFIG_WSEN_HIDS_2525020210001_TRIGGER_GLOBAL_THREAD=y +CONFIG_WSEN_PADS_2511020213301_TRIGGER_GLOBAL_THREAD=y CONFIG_WSEN_TIDS_2521020222501_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 4a0cd6ff3161..c9b52a04c5c5 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_none.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_none.conf @@ -64,4 +64,5 @@ CONFIG_TSL2540_TRIGGER_NONE=y CONFIG_TSL2591_TRIGGER_NONE=y CONFIG_VCNL4040_TRIGGER_NONE=y CONFIG_WSEN_HIDS_2525020210001_TRIGGER_NONE=y +CONFIG_WSEN_PADS_2511020213301_TRIGGER_NONE=y CONFIG_WSEN_TIDS_2521020222501_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 9e1786d6066a..8e37d4eff9c0 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_own.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_own.conf @@ -61,4 +61,5 @@ CONFIG_TSL2540_TRIGGER_OWN_THREAD=y CONFIG_TSL2591_TRIGGER_OWN_THREAD=y CONFIG_VCNL4040_TRIGGER_OWN_THREAD=y CONFIG_WSEN_HIDS_2525020210001_TRIGGER_OWN_THREAD=y +CONFIG_WSEN_PADS_2511020213301_TRIGGER_OWN_THREAD=y CONFIG_WSEN_TIDS_2521020222501_TRIGGER_OWN_THREAD=y From 9b847bb3c33a7c640c53b78e68e2a8660f4fc22f Mon Sep 17 00:00:00 2001 From: Wajdi ELMuhtadi Date: Wed, 6 Sep 2023 14:15:21 +0200 Subject: [PATCH 12/14] drivers: sensor: wsen_itds_2533020201601: add sensor driver Add wsen_itds_2533020201601 driver with the corrected name and compatibility with the hal update as well as added new features. Signed-off-by: Wajdi ELMuhtadi --- drivers/sensor/wsen/CMakeLists.txt | 1 + drivers/sensor/wsen/Kconfig | 1 + .../wsen_itds_2533020201601/CMakeLists.txt | 7 + .../wsen/wsen_itds_2533020201601/Kconfig | 80 ++ .../wsen_itds_2533020201601.c | 704 ++++++++++++++++++ .../wsen_itds_2533020201601.h | 144 ++++ .../wsen_itds_2533020201601_trigger.c | 563 ++++++++++++++ .../we,wsen-itds-2533020201601-common.yaml | 209 ++++++ .../we,wsen-itds-2533020201601-i2c.yaml | 10 + .../we,wsen-itds-2533020201601-spi.yaml | 10 + tests/drivers/build_all/sensor/i2c.dtsi | 19 + .../sensor/sensors_trigger_global.conf | 1 + .../sensor/sensors_trigger_none.conf | 1 + .../build_all/sensor/sensors_trigger_own.conf | 1 + 14 files changed, 1751 insertions(+) create mode 100644 drivers/sensor/wsen/wsen_itds_2533020201601/CMakeLists.txt create mode 100644 drivers/sensor/wsen/wsen_itds_2533020201601/Kconfig create mode 100644 drivers/sensor/wsen/wsen_itds_2533020201601/wsen_itds_2533020201601.c create mode 100644 drivers/sensor/wsen/wsen_itds_2533020201601/wsen_itds_2533020201601.h create mode 100644 drivers/sensor/wsen/wsen_itds_2533020201601/wsen_itds_2533020201601_trigger.c create mode 100644 dts/bindings/sensor/we,wsen-itds-2533020201601/we,wsen-itds-2533020201601-common.yaml create mode 100644 dts/bindings/sensor/we,wsen-itds-2533020201601/we,wsen-itds-2533020201601-i2c.yaml create mode 100644 dts/bindings/sensor/we,wsen-itds-2533020201601/we,wsen-itds-2533020201601-spi.yaml diff --git a/drivers/sensor/wsen/CMakeLists.txt b/drivers/sensor/wsen/CMakeLists.txt index ffcb71adc039..072a55fd05e5 100644 --- a/drivers/sensor/wsen/CMakeLists.txt +++ b/drivers/sensor/wsen/CMakeLists.txt @@ -4,6 +4,7 @@ # zephyr-keep-sorted-start add_subdirectory_ifdef(CONFIG_WSEN_HIDS_2525020210001 wsen_hids_2525020210001) add_subdirectory_ifdef(CONFIG_WSEN_HIDS_2525020210002 wsen_hids_2525020210002) +add_subdirectory_ifdef(CONFIG_WSEN_ITDS_2533020201601 wsen_itds_2533020201601) add_subdirectory_ifdef(CONFIG_WSEN_PADS_2511020213301 wsen_pads_2511020213301) add_subdirectory_ifdef(CONFIG_WSEN_PDUS_25131308XXXXX wsen_pdus_25131308XXXXX) add_subdirectory_ifdef(CONFIG_WSEN_TIDS_2521020222501 wsen_tids_2521020222501) diff --git a/drivers/sensor/wsen/Kconfig b/drivers/sensor/wsen/Kconfig index 108a13adcee9..47af84023fd1 100644 --- a/drivers/sensor/wsen/Kconfig +++ b/drivers/sensor/wsen/Kconfig @@ -4,6 +4,7 @@ # zephyr-keep-sorted-start source "drivers/sensor/wsen/wsen_hids_2525020210001/Kconfig" source "drivers/sensor/wsen/wsen_hids_2525020210002/Kconfig" +source "drivers/sensor/wsen/wsen_itds_2533020201601/Kconfig" source "drivers/sensor/wsen/wsen_pads_2511020213301/Kconfig" source "drivers/sensor/wsen/wsen_pdus_25131308XXXXX/Kconfig" source "drivers/sensor/wsen/wsen_tids_2521020222501/Kconfig" diff --git a/drivers/sensor/wsen/wsen_itds_2533020201601/CMakeLists.txt b/drivers/sensor/wsen/wsen_itds_2533020201601/CMakeLists.txt new file mode 100644 index 000000000000..bef2c49125b1 --- /dev/null +++ b/drivers/sensor/wsen/wsen_itds_2533020201601/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(wsen_itds_2533020201601.c) +zephyr_library_sources_ifdef(CONFIG_WSEN_ITDS_2533020201601_TRIGGER wsen_itds_2533020201601_trigger.c) diff --git a/drivers/sensor/wsen/wsen_itds_2533020201601/Kconfig b/drivers/sensor/wsen/wsen_itds_2533020201601/Kconfig new file mode 100644 index 000000000000..3d0c50a7ab62 --- /dev/null +++ b/drivers/sensor/wsen/wsen_itds_2533020201601/Kconfig @@ -0,0 +1,80 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +menuconfig WSEN_ITDS_2533020201601 + bool "WSEN-ITDS-2533020201601 3-axis acceleration sensor" + default y + depends on DT_HAS_WE_WSEN_ITDS_2533020201601_ENABLED + select I2C if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_ITDS_2533020201601),i2c) + select SPI if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_ITDS_2533020201601),spi) + select HAS_WESENSORS + help + Enable driver for the WSEN-ITDS I2C/SPI-based acceleration sensor with integrated + temperature sensor. + +if WSEN_ITDS_2533020201601 + +choice WSEN_ITDS_2533020201601_TRIGGER_MODE + prompt "Trigger mode" + default WSEN_ITDS_2533020201601_TRIGGER_NONE + help + Specify the type of triggering to be used by the driver. + +config WSEN_ITDS_2533020201601_TRIGGER_NONE + bool "No trigger" + +config WSEN_ITDS_2533020201601_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + depends on GPIO + select WSEN_ITDS_2533020201601_TRIGGER + +config WSEN_ITDS_2533020201601_TRIGGER_OWN_THREAD + bool "Use own thread" + depends on GPIO + select WSEN_ITDS_2533020201601_TRIGGER + +endchoice # WSEN_ITDS_2533020201601_TRIGGER_MODE + +config WSEN_ITDS_2533020201601_TRIGGER + bool + +config WSEN_ITDS_2533020201601_EVENTS + bool + +config WSEN_ITDS_2533020201601_THREAD_PRIORITY + int "Thread priority" + depends on WSEN_ITDS_2533020201601_TRIGGER_OWN_THREAD + default 10 + help + Priority of thread used by the driver to handle interrupts. + +config WSEN_ITDS_2533020201601_THREAD_STACK_SIZE + int "Thread stack size" + depends on WSEN_ITDS_2533020201601_TRIGGER_OWN_THREAD + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + +config WSEN_ITDS_2533020201601_TAP + bool "Tap and double tap detection" + depends on WSEN_ITDS_2533020201601_TRIGGER + select WSEN_ITDS_2533020201601_EVENTS + help + Enable tap (single/double) detection + Note that the minimum ODR required for using the tap recognition functionality is 400 Hz. + +config WSEN_ITDS_2533020201601_FREEFALL + bool "Free-fall detection" + depends on WSEN_ITDS_2533020201601_TRIGGER + select WSEN_ITDS_2533020201601_EVENTS + help + Enable free-fall detection + +config WSEN_ITDS_2533020201601_DELTA + bool "Wake-up detection (SENSOR_TRIG_DELTA)" + depends on WSEN_ITDS_2533020201601_TRIGGER + select WSEN_ITDS_2533020201601_EVENTS + help + Enable wake-up detection (SENSOR_TRIG_DELTA) + +endif # WSEN_ITDS_2533020201601 diff --git a/drivers/sensor/wsen/wsen_itds_2533020201601/wsen_itds_2533020201601.c b/drivers/sensor/wsen/wsen_itds_2533020201601/wsen_itds_2533020201601.c new file mode 100644 index 000000000000..06198a35c545 --- /dev/null +++ b/drivers/sensor/wsen/wsen_itds_2533020201601/wsen_itds_2533020201601.c @@ -0,0 +1,704 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT we_wsen_itds_2533020201601 + +#include + +#include +#include +#include + +#include "wsen_itds_2533020201601.h" + +LOG_MODULE_REGISTER(WSEN_ITDS_2533020201601, CONFIG_SENSOR_LOG_LEVEL); + +/* + * List of supported output data rates (sensor_value struct, input to + * sensor_attr_set()). Index into this list is used as argument for + * ITDS_setOutputDataRate(). + */ +static const struct sensor_value itds_2533020201601_odr_list[] = { + {.val1 = 0, .val2 = 0}, {.val1 = 1, .val2 = 6 * 100000}, + {.val1 = 12, .val2 = 5 * 100000}, {.val1 = 25, .val2 = 0}, + {.val1 = 50, .val2 = 0}, {.val1 = 100, .val2 = 0}, + {.val1 = 200, .val2 = 0}, {.val1 = 400, .val2 = 0}, + {.val1 = 800, .val2 = 0}, {.val1 = 1600, .val2 = 0}, +}; + +/* + * List of supported full scale values (i.e. measurement ranges, in g). + * Index into this list is used as input for ITDS_setFullScale(). + */ +static const int itds_2533020201601_full_scale_list[] = { + 2, + 4, + 8, + 16, +}; + +#define MAX_POLL_STEP_COUNT 10 + +/* convert raw temperature to celsius */ +static inline int16_t itds_2533020201601_raw_temp_to_celsius(int16_t raw_temp) +{ + return ((raw_temp * 100) / 16) + 2500; +} + +static int itds_2533020201601_sample_fetch(const struct device *dev, enum sensor_channel channel) +{ + struct itds_2533020201601_data *data = dev->data; + const struct itds_2533020201601_config *cfg = dev->config; + int16_t temperature, acceleration_x, acceleration_y, acceleration_z; + + switch (channel) { + case SENSOR_CHAN_ALL: + case SENSOR_CHAN_AMBIENT_TEMP: + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: + break; + default: + LOG_ERR("Fetching is not supported on channel %d.", channel); + return -ENOTSUP; + } + + if (cfg->op_mode == ITDS_singleConversion) { + if (ITDS_startSingleDataConversion(&data->sensor_interface, ITDS_enable) != + WE_SUCCESS) { + LOG_ERR("Failed to start single data conversion."); + return -EIO; + } + + k_sleep(K_MSEC(5)); + } + + ITDS_state_t acceleration_data_ready, temp_data_ready; + + acceleration_data_ready = temp_data_ready = ITDS_disable; + + bool data_ready = false; + int step_count = 0; + uint32_t step_sleep_duration = + ((uint32_t)1000000000 / + (uint32_t)sensor_value_to_milli(&itds_2533020201601_odr_list[data->sensor_odr]) / + MAX_POLL_STEP_COUNT); + + while (1) { + + switch (channel) { + case SENSOR_CHAN_ALL: { + if (ITDS_isAccelerationDataReady(&data->sensor_interface, + &acceleration_data_ready) != WE_SUCCESS) { + LOG_ERR("Failed to check if acceleration data is ready."); + return -EIO; + } + + if (ITDS_isTemperatureDataReady(&data->sensor_interface, + &temp_data_ready) != WE_SUCCESS) { + LOG_ERR("Failed to check if temperature data is ready."); + return -EIO; + } + + data_ready = (acceleration_data_ready == ITDS_enable && + temp_data_ready == ITDS_enable); + + break; + } + case SENSOR_CHAN_AMBIENT_TEMP: { + if (ITDS_isTemperatureDataReady(&data->sensor_interface, + &temp_data_ready) != WE_SUCCESS) { + LOG_ERR("Failed to check if temperature data is ready."); + return -EIO; + } + + data_ready = (temp_data_ready == ITDS_enable); + + break; + } + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: { + if (ITDS_isAccelerationDataReady(&data->sensor_interface, + &acceleration_data_ready) != WE_SUCCESS) { + LOG_ERR("Failed to check if acceleration data is ready."); + return -EIO; + } + + data_ready = (acceleration_data_ready == ITDS_enable); + + break; + } + default: + break; + } + + if (data_ready) { + break; + } else if (step_count >= MAX_POLL_STEP_COUNT) { + return -EIO; + } + + step_count++; + k_sleep(K_USEC(step_sleep_duration)); + } + + switch (channel) { + case SENSOR_CHAN_ALL: { + if (ITDS_getRawAccelerationX(&data->sensor_interface, &acceleration_x) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "acceleration"); + return -EIO; + } + + if (ITDS_getRawAccelerationY(&data->sensor_interface, &acceleration_y) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "acceleration"); + return -EIO; + } + + if (ITDS_getRawAccelerationZ(&data->sensor_interface, &acceleration_z) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "acceleration"); + return -EIO; + } + + data->acceleration_x = + ITDS_convertAcceleration_int(acceleration_x, data->sensor_range); + data->acceleration_y = + ITDS_convertAcceleration_int(acceleration_y, data->sensor_range); + data->acceleration_z = + ITDS_convertAcceleration_int(acceleration_z, data->sensor_range); + + if (ITDS_getRawTemperature12bit(&data->sensor_interface, &temperature) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "temperature"); + return -EIO; + } + data->temperature = itds_2533020201601_raw_temp_to_celsius(temperature); + break; + } + case SENSOR_CHAN_AMBIENT_TEMP: { + if (ITDS_getRawTemperature12bit(&data->sensor_interface, &temperature) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "temperature"); + return -EIO; + } + data->temperature = itds_2533020201601_raw_temp_to_celsius(temperature); + break; + } + case SENSOR_CHAN_ACCEL_X: { + if (ITDS_getRawAccelerationX(&data->sensor_interface, &acceleration_x) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "acceleration"); + return -EIO; + } + data->acceleration_x = + ITDS_convertAcceleration_int(acceleration_x, data->sensor_range); + break; + } + case SENSOR_CHAN_ACCEL_Y: { + if (ITDS_getRawAccelerationY(&data->sensor_interface, &acceleration_y) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "acceleration"); + return -EIO; + } + data->acceleration_y = + ITDS_convertAcceleration_int(acceleration_y, data->sensor_range); + break; + } + case SENSOR_CHAN_ACCEL_Z: { + if (ITDS_getRawAccelerationZ(&data->sensor_interface, &acceleration_z) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "acceleration"); + return -EIO; + } + data->acceleration_z = + ITDS_convertAcceleration_int(acceleration_z, data->sensor_range); + break; + } + case SENSOR_CHAN_ACCEL_XYZ: { + if (ITDS_getRawAccelerationX(&data->sensor_interface, &acceleration_x) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "acceleration"); + return -EIO; + } + + if (ITDS_getRawAccelerationY(&data->sensor_interface, &acceleration_y) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "acceleration"); + return -EIO; + } + + if (ITDS_getRawAccelerationZ(&data->sensor_interface, &acceleration_z) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "acceleration"); + return -EIO; + } + + data->acceleration_x = + ITDS_convertAcceleration_int(acceleration_x, data->sensor_range); + data->acceleration_y = + ITDS_convertAcceleration_int(acceleration_y, data->sensor_range); + data->acceleration_z = + ITDS_convertAcceleration_int(acceleration_z, data->sensor_range); + break; + } + default: + break; + } + + return 0; +} + +/* Convert acceleration value from mg (int16) to m/s^2 (sensor_value). */ +static inline void itds_2533020201601_convert_acceleration(struct sensor_value *val, + int16_t raw_val) +{ + int64_t dval; + /* Convert to m/s^2 */ + dval = (((int64_t)raw_val) * SENSOR_G) / 1000000LL; + val->val1 = dval / 1000LL; + val->val2 = (dval % 1000LL) * 1000; +} + +static int itds_2533020201601_channel_get(const struct device *dev, enum sensor_channel channel, + struct sensor_value *value) +{ + struct itds_2533020201601_data *data = dev->data; + + switch (channel) { + case SENSOR_CHAN_AMBIENT_TEMP: + value->val1 = (int32_t)data->temperature / 100; + value->val2 = ((int32_t)data->temperature % 100) * (1000000 / 100); + break; + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: + /* Convert requested acceleration(s) */ + if (channel == SENSOR_CHAN_ACCEL_X || channel == SENSOR_CHAN_ACCEL_XYZ) { + itds_2533020201601_convert_acceleration(value, data->acceleration_x); + value++; + } + if (channel == SENSOR_CHAN_ACCEL_Y || channel == SENSOR_CHAN_ACCEL_XYZ) { + itds_2533020201601_convert_acceleration(value, data->acceleration_y); + value++; + } + if (channel == SENSOR_CHAN_ACCEL_Z || channel == SENSOR_CHAN_ACCEL_XYZ) { + itds_2533020201601_convert_acceleration(value, data->acceleration_z); + value++; + } + break; + default: + LOG_ERR("Channel not supported %d", channel); + return -ENOTSUP; + } + + return 0; +} + +/* Set full scale (measurement range). See itds_2533020201601_full_scale_list for allowed values. */ +static int itds_2533020201601_full_scale_set(const struct device *dev, + const struct sensor_value *fs) +{ + struct itds_2533020201601_data *data = dev->data; + + uint8_t scaleg = (uint8_t)sensor_ms2_to_g(fs); + + uint8_t idx; + + for (idx = 0; idx < ARRAY_SIZE(itds_2533020201601_full_scale_list); idx++) { + if (itds_2533020201601_full_scale_list[idx] == scaleg) { + break; + } + } + + if (idx == ARRAY_SIZE(itds_2533020201601_full_scale_list)) { + /* ODR not allowed (was not found in itds_2533020201601_full_scale_list) */ + LOG_ERR("Bad scale %d", scaleg); + return -EINVAL; + } + + if (ITDS_setFullScale(&data->sensor_interface, (ITDS_fullScale_t)idx) != WE_SUCCESS) { + LOG_ERR("Failed to set full scale."); + return -EIO; + } + + data->sensor_range = idx; + + return 0; +} + +/* Get full scale (measurement range). See itds_2533020201601_full_scale_list for allowed values. */ +static int itds_2533020201601_full_scale_get(const struct device *dev, struct sensor_value *fs) +{ + struct itds_2533020201601_data *data = dev->data; + + ITDS_fullScale_t full_scale; + + if (ITDS_getFullScale(&data->sensor_interface, &full_scale) != WE_SUCCESS) { + LOG_ERR("Failed to get full scale"); + return -EIO; + } + + data->sensor_range = full_scale; + + fs->val1 = itds_2533020201601_full_scale_list[full_scale]; + fs->val2 = 0; + + return 0; +} + +/* Set output data rate. See itds_2533020201601_odr_list for allowed values. */ +static int itds_2533020201601_odr_set(const struct device *dev, const struct sensor_value *odr) +{ + struct itds_2533020201601_data *data = dev->data; + int odr_index; + + for (odr_index = 0; odr_index < ARRAY_SIZE(itds_2533020201601_odr_list); odr_index++) { + if (odr->val1 == itds_2533020201601_odr_list[odr_index].val1 && + odr->val2 == itds_2533020201601_odr_list[odr_index].val2) { + break; + } + } + + if (odr_index == ARRAY_SIZE(itds_2533020201601_odr_list)) { + /* ODR not allowed (was not found in itds_2533020201601_odr_list) */ + LOG_ERR("Bad sampling frequency %d.%d", odr->val1, odr->val2); + return -EINVAL; + } + + ITDS_outputDataRate_t odr_enum = (ITDS_outputDataRate_t)odr_index; + + if (ITDS_setOutputDataRate(&data->sensor_interface, odr_enum) != WE_SUCCESS) { + LOG_ERR("Failed to set output data rate"); + return -EIO; + } + + data->sensor_odr = odr_enum; + + return 0; +} + +/* Get output data rate. See itds_2533020201601_odr_list for allowed values. */ +static int itds_2533020201601_odr_get(const struct device *dev, struct sensor_value *odr) +{ + struct itds_2533020201601_data *data = dev->data; + + ITDS_outputDataRate_t odr_index; + + if (ITDS_getOutputDataRate(&data->sensor_interface, &odr_index) != WE_SUCCESS) { + LOG_ERR("Failed to get output data rate"); + return -EIO; + } + + data->sensor_odr = odr_index; + + odr->val1 = itds_2533020201601_odr_list[odr_index].val1; + odr->val2 = itds_2533020201601_odr_list[odr_index].val2; + + return 0; +} + +static int itds_2533020201601_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + switch ((int)attr) { + case SENSOR_ATTR_SAMPLING_FREQUENCY: + if (chan != SENSOR_CHAN_ALL) { + break; + } + return itds_2533020201601_odr_set(dev, val); + case SENSOR_ATTR_FULL_SCALE: + switch (chan) { + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: + return itds_2533020201601_full_scale_set(dev, val); + default: + break; + } + break; + default: + break; + } + + LOG_ERR("attr_set() is not supported on channel %d.", chan); + return -ENOTSUP; +} + +static int itds_2533020201601_attr_get(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, struct sensor_value *val) +{ + + if (val == NULL) { + LOG_WRN("address of passed value is NULL."); + return -EFAULT; + } + + switch ((int)attr) { + case SENSOR_ATTR_SAMPLING_FREQUENCY: + if (chan != SENSOR_CHAN_ALL) { + break; + } + return itds_2533020201601_odr_get(dev, val); + case SENSOR_ATTR_FULL_SCALE: + switch (chan) { + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: + return itds_2533020201601_full_scale_get(dev, val); + default: + break; + } + break; + default: + break; + } + + LOG_ERR("attr_get() is not supported on channel %d.", chan); + return -ENOTSUP; +} + +static const struct sensor_driver_api itds_2533020201601_driver_api = { + .attr_set = itds_2533020201601_attr_set, +#if CONFIG_WSEN_ITDS_2533020201601_TRIGGER + .trigger_set = itds_2533020201601_trigger_set, +#endif + .attr_get = itds_2533020201601_attr_get, + .sample_fetch = itds_2533020201601_sample_fetch, + .channel_get = itds_2533020201601_channel_get, +}; + +int itds_2533020201601_init(const struct device *dev) +{ + const struct itds_2533020201601_config *config = dev->config; + struct itds_2533020201601_data *data = dev->data; + struct sensor_value fs; + uint8_t device_id; + ITDS_state_t sw_reset; + + /* Initialize WE sensor interface */ + WE_sensorInterfaceType_t interface_type = data->sensor_interface.interfaceType; + + ITDS_getDefaultInterface(&data->sensor_interface); + data->sensor_interface.interfaceType = interface_type; + + switch (data->sensor_interface.interfaceType) { +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) + case WE_i2c: + if (!i2c_is_ready_dt(&config->bus_cfg.i2c)) { + LOG_ERR("I2C bus device not ready"); + return -ENODEV; + } + data->sensor_interface.handle = (void *)&config->bus_cfg.i2c; + break; +#endif +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) + case WE_spi: + if (!spi_is_ready_dt(&config->bus_cfg.spi)) { + LOG_ERR("SPI bus device not ready"); + return -ENODEV; + } + data->sensor_interface.handle = (void *)&config->bus_cfg.spi; + break; +#endif + default: + LOG_ERR("Invalid interface type"); + return -EINVAL; + } + + /* First communication test - check device ID */ + if (ITDS_getDeviceID(&data->sensor_interface, &device_id) != WE_SUCCESS) { + LOG_ERR("Failed to read device ID."); + return -EIO; + } + + if (device_id != ITDS_DEVICE_ID_VALUE) { + LOG_ERR("Invalid device ID 0x%x.", device_id); + return -EINVAL; + } + + /* Perform soft reset of the sensor */ + ITDS_softReset(&data->sensor_interface, ITDS_enable); + + k_sleep(K_USEC(5)); + + do { + if (ITDS_getSoftResetState(&data->sensor_interface, &sw_reset) != WE_SUCCESS) { + LOG_ERR("Failed to get sensor reset state."); + return -EIO; + } + } while (sw_reset); + + if (ITDS_setOperatingMode(&data->sensor_interface, config->op_mode) != WE_SUCCESS) { + LOG_ERR("Failed to set operating mode."); + return -EIO; + } + + if (ITDS_setPowerMode(&data->sensor_interface, config->power_mode) != WE_SUCCESS) { + LOG_ERR("Failed to set power mode."); + return -EIO; + } + + if (itds_2533020201601_odr_set(dev, &itds_2533020201601_odr_list[config->odr]) < 0) { + LOG_ERR("Failed to set output data rate."); + return -EIO; + } + + if (ITDS_enableLowNoise(&data->sensor_interface, config->low_noise) != WE_SUCCESS) { + LOG_ERR("Failed to set low-noise mode."); + return -EIO; + } + + sensor_g_to_ms2((int32_t)config->range, &fs); + + if (itds_2533020201601_full_scale_set(dev, &fs) < 0) { + LOG_ERR("Failed to set full scale"); + return -EIO; + } + + if (ITDS_enableAutoIncrement(&data->sensor_interface, ITDS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable auto increment."); + return -EIO; + } + + if (ITDS_enableBlockDataUpdate(&data->sensor_interface, ITDS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable block data update."); + return -EIO; + } + + if (config->op_mode == ITDS_singleConversion) { + if (ITDS_setSingleDataConversionTrigger(&data->sensor_interface, + ITDS_registerTrigger) != WE_SUCCESS) { + LOG_ERR("Failed to set single data conversion trigger."); + return -EIO; + } + } + +#if CONFIG_WSEN_ITDS_2533020201601_TRIGGER + if (itds_2533020201601_init_interrupt(dev) < 0) { + LOG_ERR("Failed to initialize interrupt(s)."); + return -EIO; + } +#endif + + return 0; +} + +#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0 +#warning "ITDS driver enabled without any devices" +#endif + +#ifdef CONFIG_WSEN_ITDS_2533020201601_TRIGGER +#define ITDS_2533020201601_CFG_EVENTS_IRQ(inst) \ + .events_interrupt_gpio = GPIO_DT_SPEC_INST_GET(inst, events_interrupt_gpios), +#define ITDS_2533020201601_CFG_DRDY_IRQ(inst) \ + .drdy_interrupt_gpio = GPIO_DT_SPEC_INST_GET(inst, drdy_interrupt_gpios), +#else +#define ITDS_2533020201601_CFG_EVENTS_IRQ(inst) +#define ITDS_2533020201601_CFG_DRDY_IRQ(inst) +#endif /* CONFIG_WSEN_ITDS_2533020201601_TRIGGER */ + +#ifdef CONFIG_WSEN_ITDS_2533020201601_TAP +#define ITDS_2533020201601_CONFIG_TAP(inst) \ + .tap_mode = DT_INST_PROP(inst, tap_mode), \ + .tap_threshold = DT_INST_PROP(inst, tap_threshold), \ + .tap_shock = DT_INST_PROP(inst, tap_shock), \ + .tap_latency = DT_INST_PROP(inst, tap_latency), \ + .tap_quiet = DT_INST_PROP(inst, tap_quiet), +#else +#define ITDS_2533020201601_CONFIG_TAP(inst) +#endif /* CONFIG_WSEN_ITDS_2533020201601_TAP */ + +#ifdef CONFIG_WSEN_ITDS_2533020201601_FREEFALL +#define ITDS_2533020201601_CONFIG_FREEFALL(inst) \ + .freefall_duration = DT_INST_PROP(inst, freefall_duration), \ + .freefall_threshold = \ + (ITDS_FreeFallThreshold_t)DT_INST_ENUM_IDX(inst, freefall_threshold), +#else +#define ITDS_2533020201601_CONFIG_FREEFALL(inst) +#endif /* CONFIG_WSEN_ITDS_2533020201601_FREEFALL */ + +#ifdef CONFIG_WSEN_ITDS_2533020201601_DELTA +#define ITDS_2533020201601_CONFIG_DELTA(inst) \ + .delta_threshold = DT_INST_PROP(inst, delta_threshold), \ + .delta_duration = DT_INST_PROP(inst, delta_duration), \ + .delta_offsets = DT_INST_PROP(inst, delta_offsets), \ + .delta_offset_weight = DT_INST_PROP(inst, delta_offset_weight), +#else +#define ITDS_2533020201601_CONFIG_DELTA(inst) +#endif /* CONFIG_WSEN_ITDS_2533020201601_DELTA */ + +#define ITDS_2533020201601_CONFIG_COMMON(inst) \ + .odr = (ITDS_outputDataRate_t)(DT_INST_ENUM_IDX(inst, odr) + 1), \ + .op_mode = (ITDS_operatingMode_t)DT_INST_ENUM_IDX(inst, op_mode), \ + .power_mode = (ITDS_powerMode_t)DT_INST_ENUM_IDX(inst, power_mode), \ + .range = DT_INST_PROP(inst, range), \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, low_noise), \ + (.low_noise = (ITDS_state_t)ITDS_enable), \ + (.low_noise = (ITDS_state_t)ITDS_disable)), \ + ITDS_2533020201601_CONFIG_TAP(inst) ITDS_2533020201601_CONFIG_FREEFALL(inst) \ + ITDS_2533020201601_CONFIG_DELTA(inst) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, events_interrupt_gpios), \ + (ITDS_2533020201601_CFG_EVENTS_IRQ(inst)), ()) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, drdy_interrupt_gpios), \ + (ITDS_2533020201601_CFG_DRDY_IRQ(inst)), ()) + +/* + * Instantiation macros used when device is on SPI bus. + */ + +#define ITDS_2533020201601_SPI_OPERATION \ + (SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA) + +#define ITDS_2533020201601_CONFIG_SPI(inst) \ + { \ + .bus_cfg = \ + { \ + .spi = SPI_DT_SPEC_INST_GET(inst, \ + ITDS_2533020201601_SPI_OPERATION, 0), \ + }, \ + ITDS_2533020201601_CONFIG_COMMON(inst) \ + } + +/* + * Instantiation macros used when device is on I2C bus. + */ + +#define ITDS_2533020201601_CONFIG_I2C(inst) \ + { \ + .bus_cfg = \ + { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }, \ + ITDS_2533020201601_CONFIG_COMMON(inst) \ + } + +/* + * Main instantiation macro. Use of COND_CODE_1() selects the right + * bus-specific macro at preprocessor time. + */ +#define ITDS_2533020201601_DEFINE(inst) \ + static struct itds_2533020201601_data itds_2533020201601_data_##inst = COND_CODE_1( \ + DT_INST_ON_BUS(inst, i2c), ({.sensor_interface = {.interfaceType = WE_i2c}}), ()) \ + COND_CODE_1(DT_INST_ON_BUS(inst, spi), \ + ({.sensor_interface = {.interfaceType = WE_spi}}), ()); \ + static const struct itds_2533020201601_config itds_2533020201601_config_##inst = \ + COND_CODE_1(DT_INST_ON_BUS(inst, i2c), (ITDS_2533020201601_CONFIG_I2C(inst)), ()) \ + COND_CODE_1(DT_INST_ON_BUS(inst, spi), \ + (ITDS_2533020201601_CONFIG_SPI(inst)), ()); \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, itds_2533020201601_init, NULL, \ + &itds_2533020201601_data_##inst, \ + &itds_2533020201601_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &itds_2533020201601_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(ITDS_2533020201601_DEFINE) diff --git a/drivers/sensor/wsen/wsen_itds_2533020201601/wsen_itds_2533020201601.h b/drivers/sensor/wsen/wsen_itds_2533020201601/wsen_itds_2533020201601.h new file mode 100644 index 000000000000..a5f8ced1ba6c --- /dev/null +++ b/drivers/sensor/wsen/wsen_itds_2533020201601/wsen_itds_2533020201601.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_WSEN_ITDS_2533020201601_WSEN_ITDS_2533020201601_H_ +#define ZEPHYR_DRIVERS_SENSOR_WSEN_ITDS_2533020201601_WSEN_ITDS_2533020201601_H_ + +#include +#include + +#include + +#include "WSEN_ITDS_2533020201601_hal.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) */ + +struct itds_2533020201601_data { + /* WE sensor interface configuration */ + WE_sensorInterface_t sensor_interface; + + /* Last acceleration samples */ + int16_t acceleration_x; + int16_t acceleration_y; + int16_t acceleration_z; + + /* Last temperature sample */ + int16_t temperature; + + ITDS_outputDataRate_t sensor_odr; + + ITDS_fullScale_t sensor_range; + +#ifdef CONFIG_WSEN_ITDS_2533020201601_TRIGGER + const struct device *dev; + /* Callback for interrupts */ + struct gpio_callback drdy_interrupt_cb; + +#ifdef CONFIG_WSEN_ITDS_2533020201601_EVENTS + struct gpio_callback events_interrupt_cb; +#endif + + /* Registered trigger handlers */ + sensor_trigger_handler_t accel_data_ready_handler; + sensor_trigger_handler_t temp_data_ready_handler; + sensor_trigger_handler_t single_tap_handler; + sensor_trigger_handler_t double_tap_handler; + sensor_trigger_handler_t freefall_handler; + sensor_trigger_handler_t delta_handler; + + const struct sensor_trigger *accel_data_ready_trigger; + const struct sensor_trigger *temp_data_ready_trigger; + const struct sensor_trigger *single_tap_trigger; + const struct sensor_trigger *double_tap_trigger; + const struct sensor_trigger *freefall_trigger; + const struct sensor_trigger *delta_trigger; + +#if defined(CONFIG_WSEN_ITDS_2533020201601_TRIGGER_OWN_THREAD) + K_KERNEL_STACK_MEMBER(drdy_thread_stack, CONFIG_WSEN_ITDS_2533020201601_THREAD_STACK_SIZE); + struct k_thread drdy_thread; + struct k_sem drdy_sem; +#ifdef CONFIG_WSEN_ITDS_2533020201601_EVENTS + K_KERNEL_STACK_MEMBER(events_thread_stack, + CONFIG_WSEN_ITDS_2533020201601_THREAD_STACK_SIZE); + struct k_thread events_thread; + struct k_sem events_sem; +#endif +#elif defined(CONFIG_WSEN_ITDS_2533020201601_TRIGGER_GLOBAL_THREAD) + struct k_work drdy_work; +#ifdef CONFIG_WSEN_ITDS_2533020201601_EVENTS + struct k_work events_work; +#endif +#endif +#endif /* CONFIG_WSEN_ITDS_2533020201601_TRIGGER */ +}; + +struct itds_2533020201601_config { + 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 + } bus_cfg; + + /* Output data rate */ + const ITDS_outputDataRate_t odr; + + /* Operation mode */ + const ITDS_operatingMode_t op_mode; + + /* Power mode */ + const ITDS_powerMode_t power_mode; + + /* Measurement range (full scale) */ + const uint8_t range; + + /* Low-noise mode */ + const ITDS_state_t low_noise; + +#ifdef CONFIG_WSEN_ITDS_2533020201601_TRIGGER + /* Interrupt pins */ + const struct gpio_dt_spec events_interrupt_gpio; + const struct gpio_dt_spec drdy_interrupt_gpio; + +#ifdef CONFIG_WSEN_ITDS_2533020201601_TAP + const uint8_t tap_mode; + const uint8_t tap_threshold[3]; + const uint8_t tap_shock; + const uint8_t tap_latency; + const uint8_t tap_quiet; +#endif /* CONFIG_WSEN_ITDS_2533020201601_TAP */ +#ifdef CONFIG_WSEN_ITDS_2533020201601_FREEFALL + const uint8_t freefall_duration; + const ITDS_FreeFallThreshold_t freefall_threshold; +#endif /* CONFIG_WSEN_ITDS_2533020201601_FREEFALL */ +#ifdef CONFIG_WSEN_ITDS_2533020201601_DELTA + const uint8_t delta_threshold; + const uint8_t delta_duration; + const int8_t delta_offsets[3]; + const uint8_t delta_offset_weight; +#endif /* CONFIG_WSEN_ITDS_2533020201601_DELTA */ +#endif /* CONFIG_WSEN_ITDS_2533020201601_TRIGGER */ +}; + +#ifdef CONFIG_WSEN_ITDS_2533020201601_TRIGGER +int itds_2533020201601_trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); + +int itds_2533020201601_init_interrupt(const struct device *dev); +#endif /* CONFIG_WSEN_ITDS_2533020201601_TRIGGER */ + +int itds_2533020201601_spi_init(const struct device *dev); +int itds_2533020201601_i2c_init(const struct device *dev); + +#endif /* ZEPHYR_DRIVERS_SENSOR_WSEN_ITDS_2533020201601_WSEN_ITDS_2533020201601_H_ */ diff --git a/drivers/sensor/wsen/wsen_itds_2533020201601/wsen_itds_2533020201601_trigger.c b/drivers/sensor/wsen/wsen_itds_2533020201601/wsen_itds_2533020201601_trigger.c new file mode 100644 index 000000000000..421db3beb861 --- /dev/null +++ b/drivers/sensor/wsen/wsen_itds_2533020201601/wsen_itds_2533020201601_trigger.c @@ -0,0 +1,563 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT we_wsen_itds_2533020201601 + +#include + +#include "wsen_itds_2533020201601.h" + +LOG_MODULE_DECLARE(WSEN_ITDS_2533020201601, CONFIG_SENSOR_LOG_LEVEL); + +/* Enable/disable interrupt handling for tap, free-fall, delta/wake-up */ +static inline int itds_2533020201601_setup_interrupt(const struct device *dev, + const struct gpio_dt_spec *pin, bool enable) +{ + unsigned int flags = enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE; + + return gpio_pin_interrupt_configure_dt(pin, flags); +} + +static inline void itds_2533020201601_handle_interrupt_1(const struct device *dev) +{ + struct itds_2533020201601_data *data = dev->data; + const struct itds_2533020201601_config *cfg = dev->config; + + /* Disable interrupt handling until the interrupt has been processed */ + itds_2533020201601_setup_interrupt(data->dev, &cfg->drdy_interrupt_gpio, false); + +#if defined(CONFIG_WSEN_ITDS_2533020201601_TRIGGER_OWN_THREAD) + k_sem_give(&data->drdy_sem); +#elif defined(CONFIG_WSEN_ITDS_2533020201601_TRIGGER_GLOBAL_THREAD) + k_work_submit(&data->drdy_work); +#endif +} + +#ifdef CONFIG_WSEN_ITDS_2533020201601_EVENTS +static inline void itds_2533020201601_handle_interrupt_0(const struct device *dev) +{ + struct itds_2533020201601_data *data = dev->data; + const struct itds_2533020201601_config *cfg = dev->config; + + /* Disable interrupt handling until the interrupt has been processed */ + itds_2533020201601_setup_interrupt(data->dev, &cfg->events_interrupt_gpio, false); + +#if defined(CONFIG_WSEN_ITDS_2533020201601_TRIGGER_OWN_THREAD) + k_sem_give(&data->events_sem); +#elif defined(CONFIG_WSEN_ITDS_2533020201601_TRIGGER_GLOBAL_THREAD) + k_work_submit(&data->events_work); +#endif +} + +/* Asynchronous handling of interrupt triggered in itds_2533020201601_gpio_callback() */ +static void itds_2533020201601_process_interrupt_0(const struct device *dev) +{ + struct itds_2533020201601_data *data = dev->data; + const struct itds_2533020201601_config *cfg = dev->config; + ITDS_status_t itds_2533020201601_status; + + /* Read status register to check for data-ready - if not using soft trigger, the + * status register is also used to find out which interrupt occurred. + */ + if (ITDS_getStatusRegister(&data->sensor_interface, &itds_2533020201601_status) != + WE_SUCCESS) { + LOG_ERR("Failed to read status register"); + return; + } + +#ifdef CONFIG_WSEN_ITDS_2533020201601_TAP + + if (data->single_tap_handler && itds_2533020201601_status.singleTap) { + data->single_tap_handler(dev, data->single_tap_trigger); + } + + if (data->double_tap_handler && itds_2533020201601_status.doubleTap) { + data->double_tap_handler(dev, data->double_tap_trigger); + } +#endif /* CONFIG_WSEN_ITDS_2533020201601_TAP */ + +#ifdef CONFIG_WSEN_ITDS_2533020201601_FREEFALL + if (data->freefall_handler && itds_2533020201601_status.freeFall) { + data->freefall_handler(dev, data->freefall_trigger); + } +#endif /* CONFIG_WSEN_ITDS_2533020201601_FREEFALL */ + +#ifdef CONFIG_WSEN_ITDS_2533020201601_DELTA + if (data->delta_handler && itds_2533020201601_status.wakeUp) { + data->delta_handler(dev, data->delta_trigger); + } +#endif /* CONFIG_WSEN_ITDS_2533020201601_DELTA */ + + /* Re-enable interrupt handling */ + itds_2533020201601_setup_interrupt(dev, &cfg->events_interrupt_gpio, true); +} + +#endif /* CONFIG_WSEN_ITDS_2533020201601_EVENTS */ + +static void itds_2533020201601_process_interrupt_1(const struct device *dev) +{ + struct itds_2533020201601_data *data = dev->data; + const struct itds_2533020201601_config *cfg = dev->config; + ITDS_statusDetect_t status_detect; + + /* Read status register to check for data-ready - if not using soft trigger, the + * status register is also used to find out which interrupt occurred. + */ + if (ITDS_getStatusDetectRegister(&data->sensor_interface, &status_detect) != WE_SUCCESS) { + LOG_ERR("Failed to read status register"); + return; + } + + if (data->accel_data_ready_handler && status_detect.dataReady) { + data->accel_data_ready_handler(dev, data->accel_data_ready_trigger); + } + + if (data->temp_data_ready_handler && status_detect.temperatureDataReady) { + data->temp_data_ready_handler(dev, data->temp_data_ready_trigger); + } + + /* Re-enable interrupt handling */ + itds_2533020201601_setup_interrupt(dev, &cfg->drdy_interrupt_gpio, true); +} + +/* + * Is called when interrupt on INT1. + * Triggers asynchronous handling of interrupt in itds_2533020201601_process_interrupt(). + */ +static void itds_2533020201601_interrupt_1_gpio_callback(const struct device *dev, + struct gpio_callback *cb, uint32_t pins) +{ + struct itds_2533020201601_data *data = + CONTAINER_OF(cb, struct itds_2533020201601_data, drdy_interrupt_cb); + + ARG_UNUSED(pins); + + itds_2533020201601_handle_interrupt_1(data->dev); +} + +#ifdef CONFIG_WSEN_ITDS_2533020201601_EVENTS +/* + * Is called when interrupt on INT0. + * Triggers asynchronous handling of interrupt in itds_2533020201601_process_interrupt(). + */ +static void itds_2533020201601_interrupt_0_gpio_callback(const struct device *dev, + struct gpio_callback *cb, uint32_t pins) +{ + struct itds_2533020201601_data *data = + CONTAINER_OF(cb, struct itds_2533020201601_data, events_interrupt_cb); + + ARG_UNUSED(pins); + + itds_2533020201601_handle_interrupt_0(data->dev); +} +#endif + +#ifdef CONFIG_WSEN_ITDS_2533020201601_TRIGGER_OWN_THREAD +static void itds_2533020201601_drdy_thread(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct itds_2533020201601_data *data = p1; + + while (true) { + k_sem_take(&data->drdy_sem, K_FOREVER); + itds_2533020201601_process_interrupt_1(data->dev); + } +} +#ifdef CONFIG_WSEN_ITDS_2533020201601_EVENTS +static void itds_2533020201601_events_thread(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct itds_2533020201601_data *data = p1; + + while (true) { + k_sem_take(&data->events_sem, K_FOREVER); + itds_2533020201601_process_interrupt_0(data->dev); + } +} +#endif /* CONFIG_WSEN_ITDS_2533020201601_EVENTS */ +#endif /* CONFIG_WSEN_ITDS_2533020201601_TRIGGER_OWN_THREAD */ + +#ifdef CONFIG_WSEN_ITDS_2533020201601_TRIGGER_GLOBAL_THREAD +static void itds_2533020201601_drdy_work_cb(struct k_work *work) +{ + struct itds_2533020201601_data *itds_2533020201601 = + CONTAINER_OF(work, struct itds_2533020201601_data, drdy_work); + + itds_2533020201601_process_interrupt_1(itds_2533020201601->dev); +} +#ifdef CONFIG_WSEN_ITDS_2533020201601_EVENTS +static void itds_2533020201601_events_work_cb(struct k_work *work) +{ + struct itds_2533020201601_data *itds_2533020201601 = + CONTAINER_OF(work, struct itds_2533020201601_data, events_work); + + itds_2533020201601_process_interrupt_0(itds_2533020201601->dev); +} +#endif /* CONFIG_WSEN_ITDS_2533020201601_EVENTS */ +#endif /* CONFIG_WSEN_ITDS_2533020201601_TRIGGER_GLOBAL_THREAD */ + +/* (Un)register trigger handler and enable/disable the corresponding sensor interrupt */ +int itds_2533020201601_trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + struct itds_2533020201601_data *data = dev->data; + const struct itds_2533020201601_config *cfg = dev->config; + + ITDS_state_t state = (handler != NULL) ? ITDS_enable : ITDS_disable; + + switch (trig->type) { + case SENSOR_TRIG_DATA_READY: { + int16_t x, y, z; + + switch (trig->chan) { + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: { + data->accel_data_ready_handler = handler; + data->accel_data_ready_trigger = trig; + itds_2533020201601_setup_interrupt(dev, &cfg->drdy_interrupt_gpio, + data->accel_data_ready_handler || + data->temp_data_ready_handler); + if (state) { + /* Dummy read: re-trigger interrupt */ + ITDS_getRawAccelerationX(&data->sensor_interface, &x); + ITDS_getRawAccelerationY(&data->sensor_interface, &y); + ITDS_getRawAccelerationZ(&data->sensor_interface, &z); + } + if (ITDS_enableDataReadyINT1(&data->sensor_interface, state) != + WE_SUCCESS) { + return -EIO; + } + break; + } + case SENSOR_CHAN_AMBIENT_TEMP: { + data->temp_data_ready_handler = handler; + data->temp_data_ready_trigger = trig; + itds_2533020201601_setup_interrupt(dev, &cfg->drdy_interrupt_gpio, + data->accel_data_ready_handler || + data->temp_data_ready_handler); + if (state) { + /* Dummy read: re-trigger interrupt */ + ITDS_getRawTemperature12bit(&data->sensor_interface, &x); + } + if (ITDS_enableTempDataReadyINT1(&data->sensor_interface, state) != + WE_SUCCESS) { + return -EIO; + } + break; + } + default: + goto error; + } + return 0; + } +#ifdef CONFIG_WSEN_ITDS_2533020201601_TAP + case SENSOR_TRIG_TAP: + if (trig->chan != SENSOR_CHAN_ALL) { + break; + } + data->single_tap_handler = handler; + data->single_tap_trigger = trig; + itds_2533020201601_setup_interrupt( + dev, &cfg->events_interrupt_gpio, + data->single_tap_handler || data->double_tap_handler || + data->freefall_handler || data->delta_handler); + if (ITDS_enableSingleTapINT0(&data->sensor_interface, state) != WE_SUCCESS) { + return -EIO; + } + return 0; + case SENSOR_TRIG_DOUBLE_TAP: + if (trig->chan != SENSOR_CHAN_ALL) { + break; + } + data->double_tap_handler = handler; + data->double_tap_trigger = trig; + itds_2533020201601_setup_interrupt( + dev, &cfg->events_interrupt_gpio, + data->single_tap_handler || data->double_tap_handler || + data->freefall_handler || data->delta_handler); + if (ITDS_enableDoubleTapINT0(&data->sensor_interface, state) != WE_SUCCESS) { + return -EIO; + } + return 0; +#endif /* CONFIG_WSEN_ITDS_2533020201601_TAP */ + +#ifdef CONFIG_WSEN_ITDS_2533020201601_FREEFALL + case SENSOR_TRIG_FREEFALL: + if (trig->chan != SENSOR_CHAN_ALL) { + break; + } + data->freefall_handler = handler; + data->freefall_trigger = trig; + itds_2533020201601_setup_interrupt( + dev, &cfg->events_interrupt_gpio, + data->single_tap_handler || data->double_tap_handler || + data->freefall_handler || data->delta_handler); + if (ITDS_enableFreeFallINT0(&data->sensor_interface, state) != WE_SUCCESS) { + return -EIO; + } + return 0; +#endif /* CONFIG_WSEN_ITDS_2533020201601_FREEFALL */ + +#ifdef CONFIG_WSEN_ITDS_2533020201601_DELTA + case SENSOR_TRIG_DELTA: + if (trig->chan != SENSOR_CHAN_ALL) { + break; + } + data->delta_handler = handler; + data->delta_trigger = trig; + itds_2533020201601_setup_interrupt( + dev, &cfg->events_interrupt_gpio, + data->single_tap_handler || data->double_tap_handler || + data->freefall_handler || data->delta_handler); + if (ITDS_enableWakeUpOnINT0(&data->sensor_interface, state) != WE_SUCCESS) { + return -EIO; + } + return 0; +#endif /* CONFIG_WSEN_ITDS_2533020201601_DELTA */ + default: + break; + } + +error: + LOG_ERR("Unsupported sensor trigger"); + return -ENOTSUP; +} + +int itds_2533020201601_init_interrupt(const struct device *dev) +{ + struct itds_2533020201601_data *data = dev->data; + const struct itds_2533020201601_config *cfg = dev->config; + + data->dev = dev; + + if (cfg->drdy_interrupt_gpio.port == NULL) { + LOG_DBG("drdy-interrupt-gpios is not defined in the device tree."); + return -EINVAL; + } + + if (!gpio_is_ready_dt(&cfg->drdy_interrupt_gpio)) { + LOG_ERR("Device %s is not ready", cfg->drdy_interrupt_gpio.port->name); + return -ENODEV; + } + + /* Setup interrupt gpio */ + if (gpio_pin_configure_dt(&cfg->drdy_interrupt_gpio, GPIO_INPUT) < 0) { + LOG_ERR("Failed to configure %s.%02u", cfg->drdy_interrupt_gpio.port->name, + cfg->drdy_interrupt_gpio.pin); + return -EIO; + } + + gpio_init_callback(&data->drdy_interrupt_cb, itds_2533020201601_interrupt_1_gpio_callback, + BIT(cfg->drdy_interrupt_gpio.pin)); + + if (gpio_add_callback(cfg->drdy_interrupt_gpio.port, &data->drdy_interrupt_cb) < 0) { + LOG_ERR("Failed to set gpio callback"); + return -EIO; + } + +#if defined(CONFIG_WSEN_ITDS_2533020201601_EVENTS) + + if (cfg->events_interrupt_gpio.port == NULL) { + LOG_DBG("events-interrupt-gpios is not defined in the device tree."); + return -EINVAL; + } + + if (!gpio_is_ready_dt(&cfg->events_interrupt_gpio)) { + LOG_ERR("Device %s is not ready", cfg->events_interrupt_gpio.port->name); + return -ENODEV; + } + + /* Setup interrupt gpio */ + if (gpio_pin_configure_dt(&cfg->events_interrupt_gpio, GPIO_INPUT) < 0) { + LOG_ERR("Failed to configure %s.%02u", cfg->events_interrupt_gpio.port->name, + cfg->events_interrupt_gpio.pin); + return -EIO; + } + + gpio_init_callback(&data->events_interrupt_cb, itds_2533020201601_interrupt_0_gpio_callback, + BIT(cfg->events_interrupt_gpio.pin)); + + if (gpio_add_callback(cfg->events_interrupt_gpio.port, &data->events_interrupt_cb) < 0) { + LOG_ERR("Failed to set gpio callback"); + return -EIO; + } + +#endif + +#if defined(CONFIG_WSEN_ITDS_2533020201601_TRIGGER_OWN_THREAD) + k_sem_init(&data->drdy_sem, 0, K_SEM_MAX_LIMIT); + + k_thread_create(&data->drdy_thread, data->drdy_thread_stack, + CONFIG_WSEN_ITDS_2533020201601_THREAD_STACK_SIZE, + itds_2533020201601_drdy_thread, data, NULL, NULL, + K_PRIO_COOP(CONFIG_WSEN_ITDS_2533020201601_THREAD_PRIORITY), 0, K_NO_WAIT); +#if defined(CONFIG_WSEN_ITDS_2533020201601_EVENTS) + k_sem_init(&data->events_sem, 0, K_SEM_MAX_LIMIT); + + k_thread_create(&data->events_thread, data->events_thread_stack, + CONFIG_WSEN_ITDS_2533020201601_THREAD_STACK_SIZE, + itds_2533020201601_events_thread, data, NULL, NULL, + K_PRIO_COOP(CONFIG_WSEN_ITDS_2533020201601_THREAD_PRIORITY), 0, K_NO_WAIT); +#endif +#elif defined(CONFIG_WSEN_ITDS_2533020201601_TRIGGER_GLOBAL_THREAD) + data->drdy_work.handler = itds_2533020201601_drdy_work_cb; +#if defined(CONFIG_WSEN_ITDS_2533020201601_EVENTS) + data->events_work.handler = itds_2533020201601_events_work_cb; + +#endif +#endif + + /* Enable interrupt in pulsed mode */ + if (ITDS_enableLatchedInterrupt(&data->sensor_interface, ITDS_disable) != WE_SUCCESS) { + LOG_ERR("Failed to disable latched mode"); + return -EIO; + } + + /* Enable data-ready in pulsed mode */ + if (ITDS_setDataReadyPulsed(&data->sensor_interface, ITDS_pulsed) != WE_SUCCESS) { + LOG_ERR("Failed to enable data-ready pulsed mode"); + return -EIO; + } + + if (ITDS_enableInterrupts(&data->sensor_interface, ITDS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable interrupts"); + return -EIO; + } + +#ifdef CONFIG_WSEN_ITDS_2533020201601_TAP + if (!(cfg->op_mode == ITDS_highPerformance && cfg->odr >= ITDS_odr7)) { + LOG_WRN("A minimum output data rate of 400 Hz is recommended when using the tap " + "recognition feature"); + } + + if (ITDS_enableDoubleTapEvent(&data->sensor_interface, + (cfg->tap_mode == 1) ? ITDS_enable : ITDS_disable) != + WE_SUCCESS) { + LOG_ERR("Failed to enable/disable double tap event"); + return -EIO; + } + + if (ITDS_setTapThresholdX(&data->sensor_interface, cfg->tap_threshold[0]) != WE_SUCCESS) { + LOG_ERR("Failed to set X axis tap threshold"); + return -EIO; + } + + if (ITDS_setTapThresholdY(&data->sensor_interface, cfg->tap_threshold[1]) != WE_SUCCESS) { + LOG_ERR("Failed to set Y axis tap threshold"); + return -EIO; + } + + if (ITDS_setTapThresholdZ(&data->sensor_interface, cfg->tap_threshold[2]) != WE_SUCCESS) { + LOG_ERR("Failed to set Z axis tap threshold"); + return -EIO; + } + + if (cfg->tap_threshold[0] > 0) { + if (ITDS_enableTapX(&data->sensor_interface, ITDS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable tap recognition in X direction"); + return -EIO; + } + } + + if (cfg->tap_threshold[1] > 0) { + if (ITDS_enableTapY(&data->sensor_interface, ITDS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable tap recognition in Y direction"); + return -EIO; + } + } + + if (cfg->tap_threshold[2] > 0) { + if (ITDS_enableTapZ(&data->sensor_interface, ITDS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable tap recognition in Z direction"); + return -EIO; + } + } + + if (ITDS_setTapShockTime(&data->sensor_interface, cfg->tap_shock) != WE_SUCCESS) { + LOG_ERR("Failed to set tap shock duration"); + return -EIO; + } + + if (ITDS_setTapLatencyTime(&data->sensor_interface, cfg->tap_latency) != WE_SUCCESS) { + LOG_ERR("Failed to set tap latency"); + return -EIO; + } + + if (ITDS_setTapQuietTime(&data->sensor_interface, cfg->tap_quiet) != WE_SUCCESS) { + LOG_ERR("Failed to set tap quiet time"); + return -EIO; + } +#endif /* CONFIG_WSEN_ITDS_2533020201601_TAP */ + +#ifdef CONFIG_WSEN_ITDS_2533020201601_FREEFALL + if (ITDS_setFreeFallDuration(&data->sensor_interface, cfg->freefall_duration) != + WE_SUCCESS) { + LOG_ERR("Failed to set free-fall duration"); + return -EIO; + } + + if (ITDS_setFreeFallThreshold(&data->sensor_interface, cfg->freefall_threshold) != + WE_SUCCESS) { + LOG_ERR("Failed to set free-fall threshold"); + return -EIO; + } +#endif /* CONFIG_WSEN_ITDS_2533020201601_FREEFALL */ + +#ifdef CONFIG_WSEN_ITDS_2533020201601_DELTA + if (ITDS_setWakeUpDuration(&data->sensor_interface, cfg->delta_duration) != WE_SUCCESS) { + LOG_ERR("Failed to set wake-up duration"); + return -EIO; + } + + if (ITDS_setWakeUpThreshold(&data->sensor_interface, cfg->delta_threshold) != WE_SUCCESS) { + LOG_ERR("Failed to set wake-up threshold"); + return -EIO; + } + + if (cfg->delta_offsets[0] != 0 || cfg->delta_offsets[1] != 0 || + cfg->delta_offsets[2] != 0) { + if (ITDS_setOffsetWeight(&data->sensor_interface, (cfg->delta_offset_weight) != 0 + ? ITDS_enable + : ITDS_disable) != + WE_SUCCESS) { + LOG_ERR("Failed to set wake-up offset weight"); + return -EIO; + } + + if (ITDS_setOffsetValueX(&data->sensor_interface, cfg->delta_offsets[0]) != + WE_SUCCESS) { + LOG_ERR("Failed to set wake-up X offset"); + return -EIO; + } + + if (ITDS_setOffsetValueY(&data->sensor_interface, cfg->delta_offsets[1]) != + WE_SUCCESS) { + LOG_ERR("Failed to set wake-up Y offset"); + return -EIO; + } + + if (ITDS_setOffsetValueZ(&data->sensor_interface, cfg->delta_offsets[2]) != + WE_SUCCESS) { + LOG_ERR("Failed to set wake-up Z offset"); + return -EIO; + } + + if (ITDS_enableApplyWakeUpOffset(&data->sensor_interface, ITDS_enable) != + WE_SUCCESS) { + LOG_ERR("Failed to enable wake-up offsets"); + return -EIO; + } + } +#endif /* CONFIG_WSEN_ITDS_2533020201601_DELTA */ + + return 0; +} diff --git a/dts/bindings/sensor/we,wsen-itds-2533020201601/we,wsen-itds-2533020201601-common.yaml b/dts/bindings/sensor/we,wsen-itds-2533020201601/we,wsen-itds-2533020201601-common.yaml new file mode 100644 index 000000000000..fe2a8c39bd33 --- /dev/null +++ b/dts/bindings/sensor/we,wsen-itds-2533020201601/we,wsen-itds-2533020201601-common.yaml @@ -0,0 +1,209 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +properties: + events-interrupt-gpios: + type: phandle-array + description: | + Events Interrupt pin (Tap, Freefall, .. etc) (INT0 Pin). + Interrupts are active high by default. + + drdy-interrupt-gpios: + type: phandle-array + description: | + DRDY Interrupt pin (INT1 Pin). + Interrupts are active high by default. + + odr: + type: string + required: true + enum: + - "1.6" + - "12.5" + - "25" + - "50" + - "100" + - "200" + - "400" + - "800" + - "1600" + description: Output data rate in Hz + Note that the available output data rates depend on the selected operating mode. In + high performance mode the output data rate of the sensor can be configured between + 12.5 Hz and 1600 Hz. In normal/low power mode the output data rate of the sensor can + be configured between 1.6 Hz and 200 Hz. Consult the ITDS user manual for more + information. + Also note that the minimum ODR required for using the tap recognition functionality + is 400 Hz. + + op-mode: + type: string + required: true + enum: + - "low-power/normal" # Low power or Normal mode + - "high-perf" # High performance mode + - "single-conversion" # Single Conversion mode + description: Operating mode of the sensor. + + power-mode: + type: string + required: true + enum: + - "low-power" # Low power mode + - "normal" # Normal mode + description: Power mode of the sensor. + + range: + type: int + default: 2 + enum: + - 16 # 16g (1.952 mg/LSB) + - 8 # 8g (0.976 mg/LSB) + - 4 # 4g (0.488 mg/LSB) + - 2 # 2g (0.244 mg/LSB) + description: Range (full scale) in g. Defaults to 2, which is + the configuration at power-up. + + low-noise: + type: boolean + description: Enables low-noise mode. + + tap-mode: + type: int + default: 0 + enum: + - 0 # Only single tap + - 1 # Single and double tap + description: Tap mode (only single tap or single and double tap). + Defaults to 0, which is the configuration at power-up. + + tap-threshold: + type: array + default: [0, 0, 0] + description: | + Tap X/Y/Z axis thresholds (unsigned 5-bit, ranging from 0x00 to 0x1F). + Defaults to "<0>, <0>, <0>", which is the configuration at power-up. + + Thresholds for tap recognition on the X/Y/Z axes corresponding to a + 2g full-scale range. Setting a threshold to zero disables tap + detection on the corresponding axis. + + Example: + + tap-threshold = <0>, <6>, <10> + + This disables tap recognition on X axis and sets thresholds for Y and Z + as follows: Y = 6 \* 2g/32 = 375mg and Z = 10 \* 2g/32 = 625mg. + + tap-shock: + type: int + default: 0x0 + description: | + Maximum duration of over-threshold event when detecting taps (unsigned + 2-bit, ranging from 0x0 to 0x3). Defaults to zero, which is the + configuration at power-up. + + A value of 0 corresponds to 4 \* 1/ODR and 1 LSB = 8 \* 1/ODR. + + tap-latency: + type: int + default: 0x0 + description: | + Maximum duration time gap for double-tap recognition (unsigned 4-bit, + ranging from 0x0 to 0xF). Defaults to zero, which is the + configuration at power-up. + + A value of 0 corresponds to 16 \* 1/ODR and 1 LSB = 32 \* 1/ODR. + + tap-quiet: + type: int + default: 0x0 + description: | + Expected quiet time for double-tap recognition (unsigned 2-bit, ranging + from 0x0 to 0x3). This defines the time after the first detected tap in + which there must not be any over-threshold event. Defaults to zero, which + is the configuration at power-up. + + A value of 0 corresponds to 2 \* 1/ODR and 1 LSB = 4 \* 1/ODR. + + freefall-duration: + type: int + default: 0x0 + description: | + Minimum duration of free-fall event (unsigned 6-bit, ranging from 0x0 + to 0x3F). Defaults to 0, which is the configuration at power-up. + + 1 LSB = 1 \* 1/ODR. + + freefall-threshold: + type: int + default: 0x5 + enum: + - 5 # 156.50 mg + - 7 # 218.75 mg + - 8 # 250.00 mg + - 10 # 312.50 mg + - 11 # 343.75 mg + - 13 # 406.25 mg + - 15 # 468.75 mg + - 16 # 500.00 mg + description: | + Free-fall threshold (amplitude of the "free-fall zone" around zero-g + level where the accelerations of all axes are small enough to generate + the free-fall interrupt). Defaults to 0x5, which is the configuration + at power-up. + + Multiply by 31.25mg to get the used threshold. + + delta-duration: + type: int + default: 0x0 + enum: + - 0 + - 1 + - 2 + - 3 + description: | + Wake-up duration, i.e. minimum duration of wake-up event to be + recognized (unsigned 2-bit, ranging from 0x0 to 0x3). + Defaults to 0, which is the configuration at power-up. + + 1 LSB = 1 \* 1/ODR + + delta-threshold: + type: int + default: 0x0 + description: | + Wake-up threshold (unsigned 6-bit, ranging from 0x0 to 0x3F). + The threshold value is applicable to both positive and negative + acceleration data. A wake-up event is recognized, if at least + one of the acceleration axis values exceeds the threshold value. + + Defaults to 0, which is the configuration at power-up. + + 1 LSB = 1/64 of measurement range (full scale). + + delta-offsets: + type: array + default: [0, 0, 0] + description: | + Wake-up X/Y/Z axis offsets (signed 8-bit, ranging from -128 to 127). + Defaults to "<0>, <0>, <0>", which is the configuration at power-up. + + The weight of the offsets depends on the delta-offset-weight property. + E.g. for delta-offset-weight=<1>, an offset value of 0x40 corresponds + to approximately 1g. + + delta-offset-weight: + type: int + default: 0x0 + enum: + - 0 # 0.977 mg/LSB + - 1 # 15.6 mg/LSB + description: | + Wake-up offset weight (0 or 1). + Weight of the offsets specified in the delta-offsets property. + Defaults to 0, which is the configuration at power-up. + + A value of 0 corresponds to 0.977 mg/LSB, a value of 1 + corresponds to 15.6 mg/LSB. diff --git a/dts/bindings/sensor/we,wsen-itds-2533020201601/we,wsen-itds-2533020201601-i2c.yaml b/dts/bindings/sensor/we,wsen-itds-2533020201601/we,wsen-itds-2533020201601-i2c.yaml new file mode 100644 index 000000000000..f26314a34c58 --- /dev/null +++ b/dts/bindings/sensor/we,wsen-itds-2533020201601/we,wsen-itds-2533020201601-i2c.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +description: | + Würth Elektronik WSEN-ITDS-2533020201601 acceleration sensor with + integrated temperature sensor (I2C bus) + +compatible: "we,wsen-itds-2533020201601" + +include: ["i2c-device.yaml", "we,wsen-itds-2533020201601-common.yaml"] diff --git a/dts/bindings/sensor/we,wsen-itds-2533020201601/we,wsen-itds-2533020201601-spi.yaml b/dts/bindings/sensor/we,wsen-itds-2533020201601/we,wsen-itds-2533020201601-spi.yaml new file mode 100644 index 000000000000..9357a672aedd --- /dev/null +++ b/dts/bindings/sensor/we,wsen-itds-2533020201601/we,wsen-itds-2533020201601-spi.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +description: | + Würth Elektronik WSEN-ITDS-2533020201601 acceleration sensor with + integrated temperature sensor (SPI bus) + +compatible: "we,wsen-itds-2533020201601" + +include: ["spi-device.yaml", "we,wsen-itds-2533020201601-common.yaml"] diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index db19c89f5d64..8cf2b6a8216a 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -521,6 +521,25 @@ test_i2c_wsen_hids_2525020210001: wsen_hids_2525020210001@4d { odr = "1"; }; +test_i2c_itds_2533020201601: wsen_itds_2533020201601@4e { + compatible = "we,wsen-itds-2533020201601"; + reg = <0x4e>; + events-interrupt-gpios = <&test_gpio 0 0>; + drdy-interrupt-gpios = <&test_gpio 0 0>; + odr = "400"; + tap-threshold = <0>, <0>, <6>; + tap-latency = < 5 >; + tap-shock = < 2 >; + tap-quiet = < 1 >; + tap-mode = < 1 >; + freefall-duration = < 6 >; + freefall-threshold = < 10 >; + delta-duration = < 1 >; + delta-threshold = < 4 >; + op-mode = "high-perf"; + power-mode = "normal"; +}; + test_i2c_max17055: max17055@4f { compatible = "maxim,max17055"; reg = <0x4f>; diff --git a/tests/drivers/build_all/sensor/sensors_trigger_global.conf b/tests/drivers/build_all/sensor/sensors_trigger_global.conf index f31f3073c685..c4b53ea2a6e7 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_global.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_global.conf @@ -64,5 +64,6 @@ CONFIG_TSL2540_TRIGGER_GLOBAL_THREAD=y CONFIG_TSL2591_TRIGGER_GLOBAL_THREAD=y CONFIG_VCNL4040_TRIGGER_GLOBAL_THREAD=y CONFIG_WSEN_HIDS_2525020210001_TRIGGER_GLOBAL_THREAD=y +CONFIG_WSEN_ITDS_2533020201601_TRIGGER_GLOBAL_THREAD=y CONFIG_WSEN_PADS_2511020213301_TRIGGER_GLOBAL_THREAD=y CONFIG_WSEN_TIDS_2521020222501_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 c9b52a04c5c5..a51eda8b88eb 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_none.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_none.conf @@ -64,5 +64,6 @@ CONFIG_TSL2540_TRIGGER_NONE=y CONFIG_TSL2591_TRIGGER_NONE=y CONFIG_VCNL4040_TRIGGER_NONE=y CONFIG_WSEN_HIDS_2525020210001_TRIGGER_NONE=y +CONFIG_WSEN_ITDS_2533020201601_TRIGGER_NONE=y CONFIG_WSEN_PADS_2511020213301_TRIGGER_NONE=y CONFIG_WSEN_TIDS_2521020222501_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 8e37d4eff9c0..b618c6da3d0d 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_own.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_own.conf @@ -61,5 +61,6 @@ CONFIG_TSL2540_TRIGGER_OWN_THREAD=y CONFIG_TSL2591_TRIGGER_OWN_THREAD=y CONFIG_VCNL4040_TRIGGER_OWN_THREAD=y CONFIG_WSEN_HIDS_2525020210001_TRIGGER_OWN_THREAD=y +CONFIG_WSEN_ITDS_2533020201601_TRIGGER_OWN_THREAD=y CONFIG_WSEN_PADS_2511020213301_TRIGGER_OWN_THREAD=y CONFIG_WSEN_TIDS_2521020222501_TRIGGER_OWN_THREAD=y From 95a4944b854e22024b90e5cf8d633c744147a1b1 Mon Sep 17 00:00:00 2001 From: Wajdi ELMuhtadi Date: Thu, 7 Sep 2023 14:29:04 +0200 Subject: [PATCH 13/14] drivers: sensor: wsen_isds_2536030320001: add sensor driver Add wsen_isds_2536030320001 driver with the corrected name and compatibility with the hal update as well as added new features. Signed-off-by: Wajdi ELMuhtadi --- drivers/sensor/wsen/CMakeLists.txt | 1 + drivers/sensor/wsen/Kconfig | 1 + .../wsen_isds_2536030320001/CMakeLists.txt | 7 + .../wsen/wsen_isds_2536030320001/Kconfig | 98 ++ .../wsen_isds_2536030320001.c | 931 ++++++++++++++++++ .../wsen_isds_2536030320001.h | 146 +++ .../wsen_isds_2536030320001_trigger.c | 544 ++++++++++ .../we,wsen-isds-2536030320001-common.yaml | 194 ++++ .../we,wsen-isds-2536030320001-i2c.yaml | 10 + .../we,wsen-isds-2536030320001-spi.yaml | 10 + tests/drivers/build_all/sensor/i2c.dtsi | 15 + .../sensor/sensors_trigger_global.conf | 1 + .../sensor/sensors_trigger_none.conf | 1 + .../build_all/sensor/sensors_trigger_own.conf | 1 + 14 files changed, 1960 insertions(+) create mode 100644 drivers/sensor/wsen/wsen_isds_2536030320001/CMakeLists.txt create mode 100644 drivers/sensor/wsen/wsen_isds_2536030320001/Kconfig create mode 100644 drivers/sensor/wsen/wsen_isds_2536030320001/wsen_isds_2536030320001.c create mode 100644 drivers/sensor/wsen/wsen_isds_2536030320001/wsen_isds_2536030320001.h create mode 100644 drivers/sensor/wsen/wsen_isds_2536030320001/wsen_isds_2536030320001_trigger.c create mode 100644 dts/bindings/sensor/we,wsen-isds-2536030320001/we,wsen-isds-2536030320001-common.yaml create mode 100644 dts/bindings/sensor/we,wsen-isds-2536030320001/we,wsen-isds-2536030320001-i2c.yaml create mode 100644 dts/bindings/sensor/we,wsen-isds-2536030320001/we,wsen-isds-2536030320001-spi.yaml diff --git a/drivers/sensor/wsen/CMakeLists.txt b/drivers/sensor/wsen/CMakeLists.txt index 072a55fd05e5..6035e09489be 100644 --- a/drivers/sensor/wsen/CMakeLists.txt +++ b/drivers/sensor/wsen/CMakeLists.txt @@ -4,6 +4,7 @@ # zephyr-keep-sorted-start add_subdirectory_ifdef(CONFIG_WSEN_HIDS_2525020210001 wsen_hids_2525020210001) add_subdirectory_ifdef(CONFIG_WSEN_HIDS_2525020210002 wsen_hids_2525020210002) +add_subdirectory_ifdef(CONFIG_WSEN_ISDS_2536030320001 wsen_isds_2536030320001) add_subdirectory_ifdef(CONFIG_WSEN_ITDS_2533020201601 wsen_itds_2533020201601) add_subdirectory_ifdef(CONFIG_WSEN_PADS_2511020213301 wsen_pads_2511020213301) add_subdirectory_ifdef(CONFIG_WSEN_PDUS_25131308XXXXX wsen_pdus_25131308XXXXX) diff --git a/drivers/sensor/wsen/Kconfig b/drivers/sensor/wsen/Kconfig index 47af84023fd1..89de575c921e 100644 --- a/drivers/sensor/wsen/Kconfig +++ b/drivers/sensor/wsen/Kconfig @@ -4,6 +4,7 @@ # zephyr-keep-sorted-start source "drivers/sensor/wsen/wsen_hids_2525020210001/Kconfig" source "drivers/sensor/wsen/wsen_hids_2525020210002/Kconfig" +source "drivers/sensor/wsen/wsen_isds_2536030320001/Kconfig" source "drivers/sensor/wsen/wsen_itds_2533020201601/Kconfig" source "drivers/sensor/wsen/wsen_pads_2511020213301/Kconfig" source "drivers/sensor/wsen/wsen_pdus_25131308XXXXX/Kconfig" diff --git a/drivers/sensor/wsen/wsen_isds_2536030320001/CMakeLists.txt b/drivers/sensor/wsen/wsen_isds_2536030320001/CMakeLists.txt new file mode 100644 index 000000000000..0dd1e1cd5b13 --- /dev/null +++ b/drivers/sensor/wsen/wsen_isds_2536030320001/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(wsen_isds_2536030320001.c) +zephyr_library_sources_ifdef(CONFIG_WSEN_ISDS_2536030320001_TRIGGER wsen_isds_2536030320001_trigger.c) diff --git a/drivers/sensor/wsen/wsen_isds_2536030320001/Kconfig b/drivers/sensor/wsen/wsen_isds_2536030320001/Kconfig new file mode 100644 index 000000000000..ecd6b3cf4ec7 --- /dev/null +++ b/drivers/sensor/wsen/wsen_isds_2536030320001/Kconfig @@ -0,0 +1,98 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +menuconfig WSEN_ISDS_2536030320001 + bool "WSEN-ISDS 3D accelerometer and 3D gyroscope sensor" + default y + depends on DT_HAS_WE_WSEN_ISDS_2536030320001_ENABLED + select I2C if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_ISDS_2536030320001),i2c) + select SPI if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_ISDS_2536030320001),spi) + select HAS_WESENSORS + help + Enable driver for the WSEN-ISDS I2C/SPI-based 3D accelerometer and 3D gyroscope sensor + with integrated temperature sensor. + +if WSEN_ISDS_2536030320001 + +config WSEN_ISDS_2536030320001_DISABLE_ACCEL_HIGH_PERFORMANCE_MODE + bool "Disable accelerometer high performance mode" + help + Disables accelerometer high performance mode. If high performance mode is disabled, + the ODR is used to switch between power modes as follows: + - 1.6 Hz - 52 Hz Low power mode + - 104 Hz - 208 Hz Normal power mode + - 416 Hz - 6.66 kHz High performance mode + +config WSEN_ISDS_2536030320001_DISABLE_GYRO_HIGH_PERFORMANCE_MODE + bool "Disable gyroscope high performance mode" + help + Disables gyroscope high performance mode. If high performance mode is disabled, + the ODR is used to switch between power modes as follows: + - 12.5 Hz - 52 Hz Low power mode + - 104 Hz - 208 Hz Normal power mode + - 416 Hz - 6.66 kHz High performance mode + +choice WSEN_ISDS_2536030320001_TRIGGER_MODE + prompt "Trigger mode" + default WSEN_ISDS_2536030320001_TRIGGER_NONE + help + Specify the type of triggering to be used by the driver. + +config WSEN_ISDS_2536030320001_TRIGGER_NONE + bool "No trigger" + +config WSEN_ISDS_2536030320001_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + depends on GPIO + select WSEN_ISDS_2536030320001_TRIGGER + +config WSEN_ISDS_2536030320001_TRIGGER_OWN_THREAD + bool "Use own thread" + depends on GPIO + select WSEN_ISDS_2536030320001_TRIGGER + +endchoice # WSEN_ISDS_2536030320001_TRIGGER_MODE + +config WSEN_ISDS_2536030320001_TRIGGER + bool + +config WSEN_ISDS_2536030320001_EVENTS + bool + +config WSEN_ISDS_2536030320001_THREAD_PRIORITY + int "Thread priority" + depends on WSEN_ISDS_2536030320001_TRIGGER_OWN_THREAD + default 10 + help + Priority of thread used by the driver to handle interrupts. + +config WSEN_ISDS_2536030320001_THREAD_STACK_SIZE + int "Thread stack size" + depends on WSEN_ISDS_2536030320001_TRIGGER_OWN_THREAD + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + +config WSEN_ISDS_2536030320001_TAP + bool "Tap and double tap detection" + depends on WSEN_ISDS_2536030320001_TRIGGER + select WSEN_ISDS_2536030320001_EVENTS + help + Enable tap (single/double) detection + Note that the recommended ODRs for tap recognition are 416 Hz and 833 Hz. + +config WSEN_ISDS_2536030320001_FREEFALL + bool "Free-fall detection" + depends on WSEN_ISDS_2536030320001_TRIGGER + select WSEN_ISDS_2536030320001_EVENTS + help + Enable free-fall detection + +config WSEN_ISDS_2536030320001_DELTA + bool "Wake-up detection (SENSOR_TRIG_DELTA)" + depends on WSEN_ISDS_2536030320001_TRIGGER + select WSEN_ISDS_2536030320001_EVENTS + help + Enable wake-up detection (SENSOR_TRIG_DELTA) + +endif # WSEN_ISDS_2536030320001 diff --git a/drivers/sensor/wsen/wsen_isds_2536030320001/wsen_isds_2536030320001.c b/drivers/sensor/wsen/wsen_isds_2536030320001/wsen_isds_2536030320001.c new file mode 100644 index 000000000000..574e19e7d3a1 --- /dev/null +++ b/drivers/sensor/wsen/wsen_isds_2536030320001/wsen_isds_2536030320001.c @@ -0,0 +1,931 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT we_wsen_isds_2536030320001 + +#include + +#include +#include +#include + +#include "wsen_isds_2536030320001.h" + +LOG_MODULE_REGISTER(WSEN_ISDS_2536030320001, CONFIG_SENSOR_LOG_LEVEL); + +/* + * List of supported accelerometer output data rates (sensor_value struct, input to + * sensor_attr_set()). Index into this list is used as argument for + * ISDS_setAccOutputDataRate(). + */ +static const struct sensor_value isds_2536030320001_accel_odr_list[] = { + {.val1 = 0, .val2 = 0}, {.val1 = 12, .val2 = 5 * 100000}, + {.val1 = 26, .val2 = 0}, {.val1 = 52, .val2 = 0}, + {.val1 = 104, .val2 = 0}, {.val1 = 208, .val2 = 0}, + {.val1 = 416, .val2 = 0}, {.val1 = 833, .val2 = 0}, + {.val1 = 1660, .val2 = 0}, {.val1 = 3330, .val2 = 0}, + {.val1 = 6660, .val2 = 0}, {.val1 = 1, .val2 = 6 * 100000}, +}; + +/* + * List of supported gyroscope output data rates (sensor_value struct, input to + * sensor_attr_set()). Index into this list is used as argument for + * ISDS_setGyroOutputDataRate(). + */ +static const struct sensor_value isds_2536030320001_gyro_odr_list[] = { + {.val1 = 0, .val2 = 0}, {.val1 = 12, .val2 = 5 * 100000}, {.val1 = 26, .val2 = 0}, + {.val1 = 52, .val2 = 0}, {.val1 = 104, .val2 = 0}, {.val1 = 208, .val2 = 0}, + {.val1 = 416, .val2 = 0}, {.val1 = 833, .val2 = 0}, {.val1 = 1660, .val2 = 0}, + {.val1 = 3330, .val2 = 0}, {.val1 = 6660, .val2 = 0}, +}; + +/* + * List of supported accelerometer full scale values (i.e. measurement ranges, in g). + * Index into this list is used as input for ISDS_setAccFullScale(). + */ +static const uint8_t isds_2536030320001_accel_full_scale_list[] = { + 2, + 16, + 4, + 8, +}; + +/* + * List of supported gyroscope full scale values (i.e. measurement ranges, in dps). + * Index into this list is used as input for ISDS_setGyroFullScale(). + */ +static const uint16_t isds_2536030320001_gyro_full_scale_list[] = { + 250, 125, 500, 0, 1000, 0, 2000, +}; + +#define MAX_POLL_STEP_COUNT 10 + +static int isds_2536030320001_sample_fetch(const struct device *dev, enum sensor_channel channel) +{ + struct isds_2536030320001_data *data = dev->data; + + uint32_t accel_step_sleep_duration, gyro_step_sleep_duration, step_sleep_duration; + + switch (channel) { + case SENSOR_CHAN_ALL: + case SENSOR_CHAN_AMBIENT_TEMP: + accel_step_sleep_duration = + ((uint32_t)1000000000 / + (uint32_t)sensor_value_to_milli( + &isds_2536030320001_accel_odr_list[data->accel_odr]) / + MAX_POLL_STEP_COUNT); + gyro_step_sleep_duration = + ((uint32_t)1000000000 / + (uint32_t)sensor_value_to_milli( + &isds_2536030320001_gyro_odr_list[data->gyro_odr]) / + MAX_POLL_STEP_COUNT); + step_sleep_duration = accel_step_sleep_duration < gyro_step_sleep_duration + ? gyro_step_sleep_duration + : accel_step_sleep_duration; + break; + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: + step_sleep_duration = + ((uint32_t)1000000000 / + (uint32_t)sensor_value_to_milli( + &isds_2536030320001_accel_odr_list[data->accel_odr]) / + MAX_POLL_STEP_COUNT); + break; + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + case SENSOR_CHAN_GYRO_XYZ: + step_sleep_duration = ((uint32_t)1000000000 / + (uint32_t)sensor_value_to_milli( + &isds_2536030320001_gyro_odr_list[data->gyro_odr]) / + MAX_POLL_STEP_COUNT); + break; + default: + LOG_ERR("Fetching is not supported on channel %d.", channel); + return -ENOTSUP; + } + + ISDS_state_t acceleration_data_ready, gyro_data_ready, temp_data_ready; + + acceleration_data_ready = gyro_data_ready = temp_data_ready = ISDS_disable; + + bool data_ready = false; + int step_count = 0; + + while (1) { + switch (channel) { + case SENSOR_CHAN_ALL: { + if (ISDS_isAccelerationDataReady(&data->sensor_interface, + &acceleration_data_ready) != WE_SUCCESS) { + LOG_ERR("Failed to check if acceleration data is ready."); + return -EIO; + } + + if (ISDS_isGyroscopeDataReady(&data->sensor_interface, &gyro_data_ready) != + WE_SUCCESS) { + LOG_ERR("Failed to check if gyroscope data is ready."); + return -EIO; + } + + if (ISDS_isTemperatureDataReady(&data->sensor_interface, + &temp_data_ready) != WE_SUCCESS) { + LOG_ERR("Failed to check if temperature data is ready."); + return -EIO; + } + + data_ready = + (acceleration_data_ready == ISDS_enable && + gyro_data_ready == ISDS_enable && temp_data_ready == ISDS_enable); + break; + } + case SENSOR_CHAN_AMBIENT_TEMP: { + if (ISDS_isTemperatureDataReady(&data->sensor_interface, + &temp_data_ready) != WE_SUCCESS) { + LOG_ERR("Failed to check if temperature data is ready."); + return -EIO; + } + data_ready = (temp_data_ready == ISDS_enable); + break; + } + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: { + if (ISDS_isAccelerationDataReady(&data->sensor_interface, + &acceleration_data_ready) != WE_SUCCESS) { + LOG_ERR("Failed to check if acceleration data is ready."); + return -EIO; + } + + data_ready = (acceleration_data_ready == ISDS_enable); + break; + } + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + case SENSOR_CHAN_GYRO_XYZ: { + if (ISDS_isGyroscopeDataReady(&data->sensor_interface, &gyro_data_ready) != + WE_SUCCESS) { + LOG_ERR("Failed to check if gyroscope data is ready."); + return -EIO; + } + + data_ready = (gyro_data_ready == ISDS_enable); + break; + } + default: + break; + } + + if (data_ready) { + break; + } else if (step_count >= MAX_POLL_STEP_COUNT) { + return -EIO; + } + + step_count++; + k_sleep(K_USEC(step_sleep_duration)); + } + + int16_t temperature, acceleration_x, acceleration_y, acceleration_z, gyro_x, gyro_y, gyro_z; + + switch (channel) { + case SENSOR_CHAN_ALL: { + + if (ISDS_getRawAccelerations(&data->sensor_interface, &acceleration_x, + &acceleration_y, &acceleration_z) != WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "acceleration"); + return -EIO; + } + + if (ISDS_getRawAngularRates(&data->sensor_interface, &gyro_x, &gyro_y, &gyro_z) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "gyro"); + return -EIO; + } + + if (ISDS_getRawTemperature(&data->sensor_interface, &temperature) != WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "temperature"); + return -EIO; + } + + data->acceleration_x = + ISDS_convertAcceleration_int(acceleration_x, data->accel_range); + data->acceleration_y = + ISDS_convertAcceleration_int(acceleration_y, data->accel_range); + data->acceleration_z = + ISDS_convertAcceleration_int(acceleration_z, data->accel_range); + + data->rate_x = ISDS_convertAngularRate_int(gyro_x, data->gyro_range); + data->rate_y = ISDS_convertAngularRate_int(gyro_y, data->gyro_range); + data->rate_z = ISDS_convertAngularRate_int(gyro_z, data->gyro_range); + + data->temperature = ISDS_convertTemperature_int(temperature); + break; + } + case SENSOR_CHAN_AMBIENT_TEMP: { + if (ISDS_getRawTemperature(&data->sensor_interface, &temperature) != WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "temperature"); + return -EIO; + } + data->temperature = ISDS_convertTemperature_int(temperature); + break; + } + case SENSOR_CHAN_ACCEL_X: { + if (ISDS_getRawAccelerationX(&data->sensor_interface, &acceleration_x) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "acceleration"); + return -EIO; + } + data->acceleration_x = + ISDS_convertAcceleration_int(acceleration_x, data->accel_range); + break; + } + case SENSOR_CHAN_ACCEL_Y: { + if (ISDS_getRawAccelerationY(&data->sensor_interface, &acceleration_y) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "acceleration"); + return -EIO; + } + data->acceleration_y = + ISDS_convertAcceleration_int(acceleration_y, data->accel_range); + break; + } + case SENSOR_CHAN_ACCEL_Z: { + if (ISDS_getRawAccelerationZ(&data->sensor_interface, &acceleration_z) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "acceleration"); + return -EIO; + } + data->acceleration_z = + ISDS_convertAcceleration_int(acceleration_z, data->accel_range); + break; + } + case SENSOR_CHAN_ACCEL_XYZ: { + if (ISDS_getRawAccelerations(&data->sensor_interface, &acceleration_x, + &acceleration_y, &acceleration_z) != WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "acceleration"); + return -EIO; + } + + data->acceleration_x = + ISDS_convertAcceleration_int(acceleration_x, data->accel_range); + data->acceleration_y = + ISDS_convertAcceleration_int(acceleration_y, data->accel_range); + data->acceleration_z = + ISDS_convertAcceleration_int(acceleration_z, data->accel_range); + break; + } + case SENSOR_CHAN_GYRO_X: { + if (ISDS_getRawAngularRateX(&data->sensor_interface, &gyro_x) != WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "gyro"); + return -EIO; + } + data->rate_x = ISDS_convertAngularRate_int(gyro_x, data->gyro_range); + break; + } + case SENSOR_CHAN_GYRO_Y: { + if (ISDS_getRawAngularRateY(&data->sensor_interface, &gyro_y) != WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "gyro"); + return -EIO; + } + data->rate_y = ISDS_convertAngularRate_int(gyro_y, data->gyro_range); + break; + } + case SENSOR_CHAN_GYRO_Z: { + if (ISDS_getRawAngularRateZ(&data->sensor_interface, &gyro_z) != WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "gyro"); + return -EIO; + } + data->rate_z = ISDS_convertAngularRate_int(gyro_z, data->gyro_range); + break; + } + case SENSOR_CHAN_GYRO_XYZ: { + if (ISDS_getRawAngularRates(&data->sensor_interface, &gyro_x, &gyro_y, &gyro_z) != + WE_SUCCESS) { + LOG_ERR("Failed to fetch %s sample.", "gyro"); + return -EIO; + } + + data->rate_x = ISDS_convertAngularRate_int(gyro_x, data->gyro_range); + data->rate_y = ISDS_convertAngularRate_int(gyro_y, data->gyro_range); + data->rate_z = ISDS_convertAngularRate_int(gyro_z, data->gyro_range); + break; + } + default: + break; + } + + return 0; +} + +/* Convert acceleration value from mg (int16) to m/s^2 (sensor_value). */ +static inline void isds_2536030320001_convert_acceleration(struct sensor_value *val, + int16_t raw_val) +{ + int64_t dval; + + /* Convert to m/s^2 */ + dval = (((int64_t)raw_val) * SENSOR_G) / 1000000LL; + val->val1 = dval / 1000LL; + val->val2 = (dval % 1000LL) * 1000; +} + +/* Convert angular rate value from mdps (int32) to radians/s (sensor_value). */ +static inline void isds_2536030320001_convert_angular_rate(struct sensor_value *val, + int32_t raw_val) +{ + int64_t dval; + + /* Convert to radians/s */ + dval = ((((int64_t)raw_val) * SENSOR_PI) / 180000000LL); + val->val1 = dval / 1000LL; + val->val2 = (dval % 1000LL) * 1000; +} + +static int isds_2536030320001_channel_get(const struct device *dev, enum sensor_channel channel, + struct sensor_value *value) +{ + struct isds_2536030320001_data *data = dev->data; + + switch (channel) { + case SENSOR_CHAN_AMBIENT_TEMP: + /* Convert temperature from 0.01 degrees Celsius to degrees Celsius */ + value->val1 = (int32_t)data->temperature / 100; + value->val2 = ((int32_t)data->temperature % 100) * (1000000 / 100); + break; + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: + /* Convert requested acceleration(s) */ + if (channel == SENSOR_CHAN_ACCEL_X || channel == SENSOR_CHAN_ACCEL_XYZ) { + isds_2536030320001_convert_acceleration(value, data->acceleration_x); + value++; + } + if (channel == SENSOR_CHAN_ACCEL_Y || channel == SENSOR_CHAN_ACCEL_XYZ) { + isds_2536030320001_convert_acceleration(value, data->acceleration_y); + value++; + } + if (channel == SENSOR_CHAN_ACCEL_Z || channel == SENSOR_CHAN_ACCEL_XYZ) { + isds_2536030320001_convert_acceleration(value, data->acceleration_z); + value++; + } + break; + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + case SENSOR_CHAN_GYRO_XYZ: + if (channel == SENSOR_CHAN_GYRO_X || channel == SENSOR_CHAN_GYRO_XYZ) { + isds_2536030320001_convert_angular_rate(value, data->rate_x); + value++; + } + if (channel == SENSOR_CHAN_GYRO_Y || channel == SENSOR_CHAN_GYRO_XYZ) { + isds_2536030320001_convert_angular_rate(value, data->rate_y); + value++; + } + if (channel == SENSOR_CHAN_GYRO_Z || channel == SENSOR_CHAN_GYRO_XYZ) { + isds_2536030320001_convert_angular_rate(value, data->rate_z); + value++; + } + break; + default: + LOG_ERR("Channel not supported %d", channel); + return -ENOTSUP; + } + + return 0; +} + +/* Set accelerometer output data rate. See isds_2536030320001_accel_odr_list for allowed values. */ +static int isds_2536030320001_accel_odr_set(const struct device *dev, + const struct sensor_value *odr) +{ + struct isds_2536030320001_data *data = dev->data; + int odr_index; + + for (odr_index = 0; odr_index < ARRAY_SIZE(isds_2536030320001_accel_odr_list); + odr_index++) { + if (odr->val1 == isds_2536030320001_accel_odr_list[odr_index].val1 && + odr->val2 == isds_2536030320001_accel_odr_list[odr_index].val2) { + break; + } + } + + if (odr_index == ARRAY_SIZE(isds_2536030320001_accel_odr_list)) { + /* ODR not allowed (was not found in isds_2536030320001_accel_odr_list) */ + LOG_ERR("Bad sampling frequency %d.%d", odr->val1, odr->val2); + return -EINVAL; + } + + if (ISDS_setAccOutputDataRate(&data->sensor_interface, + (ISDS_accOutputDataRate_t)odr_index) != WE_SUCCESS) { + LOG_ERR("Failed to set accelerometer output data rate"); + return -EIO; + } + + data->accel_odr = (ISDS_accOutputDataRate_t)odr_index; + + return 0; +} + +/* Get accelerometer output data rate. See isds_2536030320001_accel_odr_list for allowed values. */ +static int isds_2536030320001_accel_odr_get(const struct device *dev, struct sensor_value *odr) +{ + struct isds_2536030320001_data *data = dev->data; + ISDS_accOutputDataRate_t odr_index; + + if (ISDS_getAccOutputDataRate(&data->sensor_interface, &odr_index) != WE_SUCCESS) { + LOG_ERR("Failed to get output data rate"); + return -EIO; + } + + data->accel_odr = odr_index; + + odr->val1 = isds_2536030320001_accel_odr_list[odr_index].val1; + odr->val2 = isds_2536030320001_accel_odr_list[odr_index].val2; + + return 0; +} + +/* Set gyroscope output data rate. See isds_2536030320001_gyro_odr_list for allowed values. */ +static int isds_2536030320001_gyro_odr_set(const struct device *dev, const struct sensor_value *odr) +{ + struct isds_2536030320001_data *data = dev->data; + int odr_index; + + for (odr_index = 0; odr_index < ARRAY_SIZE(isds_2536030320001_gyro_odr_list); odr_index++) { + if (odr->val1 == isds_2536030320001_gyro_odr_list[odr_index].val1 && + odr->val2 == isds_2536030320001_gyro_odr_list[odr_index].val2) { + break; + } + } + + if (odr_index == ARRAY_SIZE(isds_2536030320001_gyro_odr_list)) { + /* ODR not allowed (was not found in isds_2536030320001_gyro_odr_list) */ + LOG_ERR("Bad sampling frequency %d.%d", odr->val1, odr->val2); + return -EINVAL; + } + + if (ISDS_setGyroOutputDataRate(&data->sensor_interface, + (ISDS_gyroOutputDataRate_t)odr_index) != WE_SUCCESS) { + LOG_ERR("Failed to set gyroscope output data rate"); + return -EIO; + } + + data->gyro_odr = (ISDS_gyroOutputDataRate_t)odr_index; + + return 0; +} + +/* Get gyroscope output data rate. See isds_2536030320001_gyro_odr_list for allowed values. */ +static int isds_2536030320001_gyro_odr_get(const struct device *dev, struct sensor_value *odr) +{ + struct isds_2536030320001_data *data = dev->data; + ISDS_gyroOutputDataRate_t odr_index; + + if (ISDS_getGyroOutputDataRate(&data->sensor_interface, &odr_index) != WE_SUCCESS) { + LOG_ERR("Failed to get output data rate"); + return -EIO; + } + + data->gyro_odr = odr_index; + + odr->val1 = isds_2536030320001_gyro_odr_list[odr_index].val1; + odr->val2 = isds_2536030320001_gyro_odr_list[odr_index].val2; + + return 0; +} + +/* + * Set accelerometer full scale (measurement range). See isds_2536030320001_accel_full_scale_list + * for allowed values. + */ +static int isds_2536030320001_accel_full_scale_set(const struct device *dev, + const struct sensor_value *fs) +{ + struct isds_2536030320001_data *data = dev->data; + + uint8_t scaleg = (uint8_t)sensor_ms2_to_g(fs); + + uint8_t idx; + + for (idx = 0; idx < ARRAY_SIZE(isds_2536030320001_accel_full_scale_list); idx++) { + if (isds_2536030320001_accel_full_scale_list[idx] == scaleg) { + break; + } + } + + if (idx == ARRAY_SIZE(isds_2536030320001_accel_full_scale_list)) { + /* fullscale not allowed (was not found in isds_2536030320001_accel_full_scale_list) + */ + LOG_ERR("Bad scale %d", scaleg); + return -EINVAL; + } + + if (ISDS_setAccFullScale(&data->sensor_interface, (ISDS_accFullScale_t)idx) != WE_SUCCESS) { + LOG_ERR("Failed to set accelerometer full scale."); + return -EIO; + } + + data->accel_range = (ISDS_accFullScale_t)idx; + + return 0; +} + +/* + * Get accelerometer full scale (measurement range). See isds_2536030320001_accel_full_scale_list + * for allowed values. + */ +static int isds_2536030320001_accel_full_scale_get(const struct device *dev, + struct sensor_value *fs) +{ + struct isds_2536030320001_data *data = dev->data; + + ISDS_accFullScale_t accel_fs; + + if (ISDS_getAccFullScale(&data->sensor_interface, &accel_fs) != WE_SUCCESS) { + LOG_ERR("Failed to get full scale"); + return -EIO; + } + + data->accel_range = accel_fs; + + fs->val1 = isds_2536030320001_accel_full_scale_list[accel_fs]; + fs->val2 = 0; + + return 0; +} + +/* + * Set gyroscope full scale (measurement range). See isds_2536030320001_gyro_full_scale_list for + * allowed values. + */ +static int isds_2536030320001_gyro_full_scale_set(const struct device *dev, + const struct sensor_value *fs) +{ + struct isds_2536030320001_data *data = dev->data; + + uint16_t scale_dps = (uint16_t)sensor_rad_to_degrees(fs); + + uint8_t idx; + + for (idx = 0; idx < ARRAY_SIZE(isds_2536030320001_gyro_full_scale_list); idx++) { + if (isds_2536030320001_gyro_full_scale_list[idx] == scale_dps) { + break; + } + } + + if (idx == ARRAY_SIZE(isds_2536030320001_gyro_full_scale_list)) { + /* fullscale not allowed (was not found in isds_2536030320001_accel_full_scale_list) + */ + LOG_ERR("Bad scale %d", scale_dps); + return -EINVAL; + } + + if (ISDS_setGyroFullScale(&data->sensor_interface, (ISDS_gyroFullScale_t)idx) != + WE_SUCCESS) { + LOG_ERR("Failed to set gyroscope full scale."); + return -EIO; + } + + data->gyro_range = (ISDS_gyroFullScale_t)idx; + + return 0; +} + +/* + * Get gyroscope full scale (measurement range). See isds_2536030320001_gyro_full_scale_list for + * allowed values. + */ +static int isds_2536030320001_gyro_full_scale_get(const struct device *dev, struct sensor_value *fs) +{ + struct isds_2536030320001_data *data = dev->data; + + ISDS_gyroFullScale_t gyro_fs; + + if (ISDS_getGyroFullScale(&data->sensor_interface, &gyro_fs) != WE_SUCCESS) { + LOG_ERR("Failed to get full scale"); + return -EIO; + } + + data->gyro_range = gyro_fs; + + fs->val1 = isds_2536030320001_gyro_full_scale_list[gyro_fs]; + fs->val2 = 0; + + return 0; +} + +static int isds_2536030320001_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + switch (attr) { + case SENSOR_ATTR_SAMPLING_FREQUENCY: + switch (chan) { + case SENSOR_CHAN_ACCEL_XYZ: + return isds_2536030320001_accel_odr_set(dev, val); + case SENSOR_CHAN_GYRO_XYZ: + return isds_2536030320001_gyro_odr_set(dev, val); + default: + break; + } + break; + case SENSOR_ATTR_FULL_SCALE: + switch (chan) { + case SENSOR_CHAN_ACCEL_XYZ: + return isds_2536030320001_accel_full_scale_set(dev, val); + case SENSOR_CHAN_GYRO_XYZ: + return isds_2536030320001_gyro_full_scale_set(dev, val); + default: + break; + } + break; + default: + break; + } + + LOG_ERR("attr_set() is not supported on channel %d.", chan); + return -ENOTSUP; +} + +static int isds_2536030320001_attr_get(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, struct sensor_value *val) +{ + + if (val == NULL) { + LOG_WRN("address of passed value is NULL."); + return -EFAULT; + } + + switch (attr) { + case SENSOR_ATTR_SAMPLING_FREQUENCY: + switch (chan) { + case SENSOR_CHAN_ACCEL_XYZ: + return isds_2536030320001_accel_odr_get(dev, val); + case SENSOR_CHAN_GYRO_XYZ: + return isds_2536030320001_gyro_odr_get(dev, val); + default: + break; + } + break; + case SENSOR_ATTR_FULL_SCALE: + switch (chan) { + case SENSOR_CHAN_ACCEL_XYZ: + return isds_2536030320001_accel_full_scale_get(dev, val); + case SENSOR_CHAN_GYRO_XYZ: + return isds_2536030320001_gyro_full_scale_get(dev, val); + default: + break; + } + break; + default: + break; + } + + LOG_ERR("attr_get() is not supported on channel %d.", chan); + return -ENOTSUP; +} + +static const struct sensor_driver_api isds_2536030320001_driver_api = { + .attr_set = isds_2536030320001_attr_set, + .attr_get = isds_2536030320001_attr_get, +#if CONFIG_WSEN_ISDS_2536030320001_TRIGGER + .trigger_set = isds_2536030320001_trigger_set, +#endif + .sample_fetch = isds_2536030320001_sample_fetch, + .channel_get = isds_2536030320001_channel_get, +}; + +static int isds_2536030320001_init(const struct device *dev) +{ + const struct isds_2536030320001_config *config = dev->config; + struct isds_2536030320001_data *data = dev->data; + struct sensor_value accel_range, gyro_range; + uint8_t device_id; + ISDS_state_t sw_reset; + + /* Initialize WE sensor interface */ + WE_sensorInterfaceType_t interface_type = data->sensor_interface.interfaceType; + + ISDS_getDefaultInterface(&data->sensor_interface); + data->sensor_interface.interfaceType = interface_type; + + switch (data->sensor_interface.interfaceType) { +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) + case WE_i2c: + if (!i2c_is_ready_dt(&config->bus_cfg.i2c)) { + LOG_ERR("I2C bus device not ready"); + return -ENODEV; + } + data->sensor_interface.handle = (void *)&config->bus_cfg.i2c; + break; +#endif +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) + case WE_spi: + if (!spi_is_ready_dt(&config->bus_cfg.spi)) { + LOG_ERR("SPI bus device not ready"); + return -ENODEV; + } + data->sensor_interface.handle = (void *)&config->bus_cfg.spi; + break; +#endif + default: + LOG_ERR("Invalid interface type"); + return -EINVAL; + } + + /* First communication test - check device ID */ + if (ISDS_getDeviceID(&data->sensor_interface, &device_id) != WE_SUCCESS) { + LOG_ERR("Failed to read device ID."); + return -EIO; + } + + if (device_id != ISDS_DEVICE_ID_VALUE) { + LOG_ERR("Invalid device ID 0x%x.", device_id); + return -EINVAL; + } + + /* Perform soft reset of the sensor */ + ISDS_softReset(&data->sensor_interface, ISDS_enable); + + k_sleep(K_USEC(5)); + + do { + if (ISDS_getSoftResetState(&data->sensor_interface, &sw_reset) != WE_SUCCESS) { + LOG_ERR("Failed to get sensor reset state."); + return -EIO; + } + } while (sw_reset); + + if (isds_2536030320001_accel_odr_set( + dev, &isds_2536030320001_accel_odr_list[config->accel_odr]) < 0) { + LOG_ERR("Failed to set odr"); + return -EIO; + } + + if (isds_2536030320001_gyro_odr_set( + dev, &isds_2536030320001_gyro_odr_list[config->gyro_odr]) < 0) { + LOG_ERR("Failed to set odr"); + return -EIO; + } + + if (ISDS_enableAutoIncrement(&data->sensor_interface, ISDS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable auto increment."); + return -EIO; + } + + if (ISDS_enableBlockDataUpdate(&data->sensor_interface, ISDS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable block data update."); + return -EIO; + } + + sensor_g_to_ms2((int32_t)config->accel_range, &accel_range); + + if (isds_2536030320001_accel_full_scale_set(dev, &accel_range) < 0) { + LOG_ERR("Failed to set full scale"); + return -EIO; + } + + sensor_degrees_to_rad((int32_t)config->gyro_range, &gyro_range); + + if (isds_2536030320001_gyro_full_scale_set(dev, &gyro_range) < 0) { + LOG_ERR("Failed to set full scale"); + return -EIO; + } + +#if CONFIG_WSEN_ISDS_2536030320001_DISABLE_ACCEL_HIGH_PERFORMANCE_MODE + if (ISDS_disableAccHighPerformanceMode(&data->sensor_interface, ISDS_enable) != + WE_SUCCESS) { + LOG_ERR("Failed to disable accelerometer high performance mode."); + return -EIO; + } +#endif /* CONFIG_WSEN_ISDS_2536030320001_DISABLE_ACCEL_HIGH_PERFORMANCE_MODE */ + +#if CONFIG_WSEN_ISDS_2536030320001_DISABLE_GYRO_HIGH_PERFORMANCE_MODE + if (ISDS_disableGyroHighPerformanceMode(&data->sensor_interface, ISDS_enable) != + WE_SUCCESS) { + LOG_ERR("Failed to disable gyroscope high performance mode."); + return -EIO; + } +#endif /* CONFIG_WSEN_ISDS_2536030320001_DISABLE_GYRO_HIGH_PERFORMANCE_MODE */ + +#if CONFIG_WSEN_ISDS_2536030320001_TRIGGER + if (isds_2536030320001_init_interrupt(dev) < 0) { + LOG_ERR("Failed to initialize interrupt(s)."); + return -EIO; + } +#endif + + return 0; +} + +#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0 +#warning "ISDS driver enabled without any devices" +#endif + +#ifdef CONFIG_WSEN_ISDS_2536030320001_TRIGGER +#define ISDS_2536030320001_CFG_EVENTS_IRQ(inst) \ + .events_interrupt_gpio = GPIO_DT_SPEC_INST_GET(inst, events_interrupt_gpios), +#define ISDS_2536030320001_CFG_DRDY_IRQ(inst) \ + .drdy_interrupt_gpio = GPIO_DT_SPEC_INST_GET(inst, drdy_interrupt_gpios), +#else +#define ISDS_2536030320001_CFG_EVENTS_IRQ(inst) +#define ISDS_2536030320001_CFG_DRDY_IRQ(inst) +#endif /* CONFIG_WSEN_ISDS_2536030320001_TRIGGER */ + +#ifdef CONFIG_WSEN_ISDS_2536030320001_TAP +#define ISDS_2536030320001_CONFIG_TAP(inst) \ + .tap_mode = DT_INST_PROP(inst, tap_mode), \ + .tap_threshold = DT_INST_PROP(inst, tap_threshold), \ + .tap_axis_enable = DT_INST_PROP(inst, tap_axis_enable), \ + .tap_shock = DT_INST_PROP(inst, tap_shock), \ + .tap_latency = DT_INST_PROP(inst, tap_latency), \ + .tap_quiet = DT_INST_PROP(inst, tap_quiet), +#else +#define ISDS_2536030320001_CONFIG_TAP(inst) +#endif /* CONFIG_WSEN_ISDS_2536030320001_TAP */ + +#ifdef CONFIG_WSEN_ISDS_2536030320001_FREEFALL +#define ISDS_2536030320001_CONFIG_FREEFALL(inst) \ + .freefall_duration = DT_INST_PROP(inst, freefall_duration), \ + .freefall_threshold = \ + (ISDS_freeFallThreshold_t)DT_INST_ENUM_IDX(inst, freefall_threshold), +#else +#define ISDS_2536030320001_CONFIG_FREEFALL(inst) +#endif /* CONFIG_WSEN_ISDS_2536030320001_FREEFALL */ + +#ifdef CONFIG_WSEN_ISDS_2536030320001_DELTA +#define ISDS_2536030320001_CONFIG_DELTA(inst) \ + .delta_threshold = DT_INST_PROP(inst, delta_threshold), \ + .delta_duration = DT_INST_PROP(inst, delta_duration), +#else +#define ISDS_2536030320001_CONFIG_DELTA(inst) +#endif /* CONFIG_WSEN_ISDS_2536030320001_DELTA */ + +#define ISDS_2536030320001_CONFIG_COMMON(inst) \ + .accel_odr = (ISDS_accOutputDataRate_t)(DT_INST_ENUM_IDX(inst, accel_odr)), \ + .gyro_odr = (ISDS_gyroOutputDataRate_t)(DT_INST_ENUM_IDX(inst, gyro_odr)), \ + .accel_range = DT_INST_PROP(inst, accel_range), \ + .gyro_range = DT_INST_PROP(inst, gyro_range), \ + ISDS_2536030320001_CONFIG_TAP(inst) ISDS_2536030320001_CONFIG_FREEFALL(inst) \ + ISDS_2536030320001_CONFIG_DELTA(inst) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, events_interrupt_gpios), \ + (ISDS_2536030320001_CFG_EVENTS_IRQ(inst)), ()) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, drdy_interrupt_gpios), \ + (ISDS_2536030320001_CFG_DRDY_IRQ(inst)), ()) + +/* + * Instantiation macros used when device is on SPI bus. + */ + +#define ISDS_2536030320001_SPI_OPERATION \ + (SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA) + +#define ISDS_2536030320001_CONFIG_SPI(inst) \ + { \ + .bus_cfg = \ + { \ + .spi = SPI_DT_SPEC_INST_GET(inst, \ + ISDS_2536030320001_SPI_OPERATION, 0), \ + }, \ + ISDS_2536030320001_CONFIG_COMMON(inst) \ + } + +/* + * Instantiation macros used when device is on I2C bus. + */ + +#define ISDS_2536030320001_CONFIG_I2C(inst) \ + { \ + .bus_cfg = \ + { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }, \ + ISDS_2536030320001_CONFIG_COMMON(inst) \ + } + +/* + * Main instantiation macro. Use of COND_CODE_1() selects the right + * bus-specific macro at preprocessor time. + */ +#define ISDS_2536030320001_DEFINE(inst) \ + static struct isds_2536030320001_data isds_2536030320001_data_##inst = COND_CODE_1( \ + DT_INST_ON_BUS(inst, i2c), ({.sensor_interface = {.interfaceType = WE_i2c}}), ()) \ + COND_CODE_1(DT_INST_ON_BUS(inst, spi), \ + ({.sensor_interface = {.interfaceType = WE_spi}}), ()); \ + static const struct isds_2536030320001_config isds_2536030320001_config_##inst = \ + COND_CODE_1(DT_INST_ON_BUS(inst, i2c), (ISDS_2536030320001_CONFIG_I2C(inst)), ()) \ + COND_CODE_1(DT_INST_ON_BUS(inst, spi), \ + (ISDS_2536030320001_CONFIG_SPI(inst)), ()); \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, isds_2536030320001_init, NULL, \ + &isds_2536030320001_data_##inst, \ + &isds_2536030320001_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &isds_2536030320001_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(ISDS_2536030320001_DEFINE) diff --git a/drivers/sensor/wsen/wsen_isds_2536030320001/wsen_isds_2536030320001.h b/drivers/sensor/wsen/wsen_isds_2536030320001/wsen_isds_2536030320001.h new file mode 100644 index 000000000000..09b412c472bb --- /dev/null +++ b/drivers/sensor/wsen/wsen_isds_2536030320001/wsen_isds_2536030320001.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_WSEN_ISDS_2536030320001_WSEN_ISDS_2536030320001_H_ +#define ZEPHYR_DRIVERS_SENSOR_WSEN_ISDS_2536030320001_WSEN_ISDS_2536030320001_H_ + +#include +#include + +#include + +#include "WSEN_ISDS_2536030320001_hal.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) */ + +struct isds_2536030320001_data { + /* WE sensor interface configuration */ + WE_sensorInterface_t sensor_interface; + + /* Last acceleration samples */ + int16_t acceleration_x; + int16_t acceleration_y; + int16_t acceleration_z; + + /* Last angular rate samples */ + int32_t rate_x; + int32_t rate_y; + int32_t rate_z; + + /* Last temperature sample */ + int16_t temperature; + + ISDS_accOutputDataRate_t accel_odr; + ISDS_gyroOutputDataRate_t gyro_odr; + + ISDS_accFullScale_t accel_range; + ISDS_gyroFullScale_t gyro_range; + +#ifdef CONFIG_WSEN_ISDS_2536030320001_TRIGGER + const struct device *dev; + + /* Callback for interrupts */ + struct gpio_callback drdy_interrupt_cb; + +#ifdef CONFIG_WSEN_ISDS_2536030320001_EVENTS + struct gpio_callback events_interrupt_cb; +#endif + + /* Registered trigger handlers */ + sensor_trigger_handler_t accel_data_ready_handler; + sensor_trigger_handler_t gyro_data_ready_handler; + sensor_trigger_handler_t temp_data_ready_handler; + sensor_trigger_handler_t single_tap_handler; + sensor_trigger_handler_t double_tap_handler; + sensor_trigger_handler_t freefall_handler; + sensor_trigger_handler_t delta_handler; + + const struct sensor_trigger *accel_data_ready_trigger; + const struct sensor_trigger *gyro_data_ready_trigger; + const struct sensor_trigger *temp_data_ready_trigger; + const struct sensor_trigger *single_tap_trigger; + const struct sensor_trigger *double_tap_trigger; + const struct sensor_trigger *freefall_trigger; + const struct sensor_trigger *delta_trigger; + +#if defined(CONFIG_WSEN_ISDS_2536030320001_TRIGGER_OWN_THREAD) + K_KERNEL_STACK_MEMBER(drdy_thread_stack, CONFIG_WSEN_ISDS_2536030320001_THREAD_STACK_SIZE); + struct k_thread drdy_thread; + struct k_sem drdy_sem; +#ifdef CONFIG_WSEN_ISDS_2536030320001_EVENTS + K_KERNEL_STACK_MEMBER(events_thread_stack, + CONFIG_WSEN_ISDS_2536030320001_THREAD_STACK_SIZE); + struct k_thread events_thread; + struct k_sem events_sem; +#endif +#elif defined(CONFIG_WSEN_ISDS_2536030320001_TRIGGER_GLOBAL_THREAD) + struct k_work drdy_work; +#ifdef CONFIG_WSEN_ISDS_2536030320001_EVENTS + struct k_work events_work; +#endif +#endif +#endif /* CONFIG_WSEN_ISDS_2536030320001_TRIGGER */ +}; + +struct isds_2536030320001_config { + 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 + } bus_cfg; + + /* Output data rates */ + ISDS_accOutputDataRate_t accel_odr; + ISDS_gyroOutputDataRate_t gyro_odr; + + /* Measurement ranges (full scale) */ + uint8_t accel_range; + uint16_t gyro_range; + +#ifdef CONFIG_WSEN_ISDS_2536030320001_TRIGGER + /* Interrupt pin (used for data-ready, tap, free-fall, delta/wake-up) */ + const struct gpio_dt_spec events_interrupt_gpio; + const struct gpio_dt_spec drdy_interrupt_gpio; + +#ifdef CONFIG_WSEN_ISDS_2536030320001_TAP + uint8_t tap_mode; + uint8_t tap_threshold; + uint8_t tap_axis_enable[3]; + uint8_t tap_shock; + uint8_t tap_latency; + uint8_t tap_quiet; +#endif /* CONFIG_WSEN_ISDS_2536030320001_TAP */ +#ifdef CONFIG_WSEN_ISDS_2536030320001_FREEFALL + uint8_t freefall_duration; + ISDS_freeFallThreshold_t freefall_threshold; +#endif /* CONFIG_WSEN_ISDS_2536030320001_FREEFALL */ +#ifdef CONFIG_WSEN_ISDS_2536030320001_DELTA + uint8_t delta_threshold; + uint8_t delta_duration; +#endif /* CONFIG_WSEN_ISDS_2536030320001_DELTA */ +#endif /* CONFIG_WSEN_ISDS_2536030320001_TRIGGER */ +}; + +#ifdef CONFIG_WSEN_ISDS_2536030320001_TRIGGER +int isds_2536030320001_trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); + +int isds_2536030320001_init_interrupt(const struct device *dev); +#endif /* CONFIG_WSEN_ISDS_2536030320001_TRIGGER */ + +int isds_2536030320001_spi_init(const struct device *dev); +int isds_2536030320001_i2c_init(const struct device *dev); + +#endif /* ZEPHYR_DRIVERS_SENSOR_WSEN_ISDS_2536030320001_WSEN_ISDS_2536030320001_H_ */ diff --git a/drivers/sensor/wsen/wsen_isds_2536030320001/wsen_isds_2536030320001_trigger.c b/drivers/sensor/wsen/wsen_isds_2536030320001/wsen_isds_2536030320001_trigger.c new file mode 100644 index 000000000000..98bbdbafc5a0 --- /dev/null +++ b/drivers/sensor/wsen/wsen_isds_2536030320001/wsen_isds_2536030320001_trigger.c @@ -0,0 +1,544 @@ +/* + * Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT we_wsen_isds_2536030320001 + +#include + +#include "wsen_isds_2536030320001.h" + +LOG_MODULE_DECLARE(WSEN_ISDS_2536030320001, CONFIG_SENSOR_LOG_LEVEL); + +/* Enable/disable interrupt handling for data-ready, tap, free-fall, delta/wake-up */ +static inline int isds_2536030320001_setup_interrupt(const struct device *dev, + const struct gpio_dt_spec *pin, bool enable) +{ + unsigned int flags = enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE; + + return gpio_pin_interrupt_configure_dt(pin, flags); +} + +static inline void isds_2536030320001_handle_interrupt_1(const struct device *dev) +{ + struct isds_2536030320001_data *data = dev->data; + const struct isds_2536030320001_config *cfg = dev->config; + + /* Disable interrupt handling until the interrupt has been processed */ + isds_2536030320001_setup_interrupt(data->dev, &cfg->drdy_interrupt_gpio, false); + +#if defined(CONFIG_WSEN_ISDS_2536030320001_TRIGGER_OWN_THREAD) + k_sem_give(&data->drdy_sem); +#elif defined(CONFIG_WSEN_ISDS_2536030320001_TRIGGER_GLOBAL_THREAD) + k_work_submit(&data->drdy_work); +#endif +} + +static void isds_2536030320001_process_interrupt_1(const struct device *dev) +{ + struct isds_2536030320001_data *data = dev->data; + const struct isds_2536030320001_config *cfg = dev->config; + ISDS_status_t status_reg; + + if (ISDS_getStatusRegister(&data->sensor_interface, &status_reg) != WE_SUCCESS) { + LOG_ERR("Failed to read status register"); + return; + } + + if (data->accel_data_ready_handler && status_reg.accDataReady) { + data->accel_data_ready_handler(dev, data->accel_data_ready_trigger); + } + + if (data->gyro_data_ready_handler && status_reg.gyroDataReady) { + data->gyro_data_ready_handler(dev, data->gyro_data_ready_trigger); + } + + if (data->temp_data_ready_handler && status_reg.tempDataReady) { + data->temp_data_ready_handler(dev, data->temp_data_ready_trigger); + } + + /* Re-enable interrupt handling */ + isds_2536030320001_setup_interrupt(dev, &cfg->drdy_interrupt_gpio, true); +} + +/* + * Is called when interrupt on INT1. + * Triggers asynchronous handling of interrupt in isds_2536030320001_process_interrupt(). + */ +static void isds_2536030320001_interrupt_1_gpio_callback(const struct device *dev, + struct gpio_callback *cb, uint32_t pins) +{ + struct isds_2536030320001_data *data = + CONTAINER_OF(cb, struct isds_2536030320001_data, drdy_interrupt_cb); + + ARG_UNUSED(pins); + + isds_2536030320001_handle_interrupt_1(data->dev); +} + +#ifdef CONFIG_WSEN_ISDS_2536030320001_EVENTS +static inline void isds_2536030320001_handle_interrupt_0(const struct device *dev) +{ + struct isds_2536030320001_data *data = dev->data; + const struct isds_2536030320001_config *cfg = dev->config; + + /* Disable interrupt handling until the interrupt has been processed */ + isds_2536030320001_setup_interrupt(data->dev, &cfg->events_interrupt_gpio, false); + +#if defined(CONFIG_WSEN_ISDS_2536030320001_TRIGGER_OWN_THREAD) + k_sem_give(&data->events_sem); +#elif defined(CONFIG_WSEN_ISDS_2536030320001_TRIGGER_GLOBAL_THREAD) + k_work_submit(&data->events_work); +#endif +} + +/* Asynchronous handling of interrupt triggered in isds_2536030320001_gpio_callback() */ +static void isds_2536030320001_process_interrupt_0(const struct device *dev) +{ + struct isds_2536030320001_data *data = dev->data; + const struct isds_2536030320001_config *cfg = dev->config; + +#ifdef CONFIG_WSEN_ISDS_2536030320001_TAP + ISDS_tapEvent_t tap_event; + /* Read tap event register to find out if a tap event interrupt occurred. */ + if (ISDS_getTapEventRegister(&data->sensor_interface, &tap_event) != WE_SUCCESS) { + LOG_ERR("Failed to read tap event register"); + return; + } + + if (data->single_tap_handler && tap_event.singleState) { + data->single_tap_handler(dev, data->single_tap_trigger); + } + + if (data->double_tap_handler && tap_event.doubleState) { + data->double_tap_handler(dev, data->double_tap_trigger); + } +#endif /* CONFIG_WSEN_ISDS_2536030320001_TAP */ + +#if defined(CONFIG_WSEN_ISDS_2536030320001_FREEFALL) || \ + defined(CONFIG_WSEN_ISDS_2536030320001_DELTA) + + ISDS_wakeUpEvent_t wake_up_event; + /* Read wake-up event register to find out if freefall or wake-up interrupt occurred. */ + if (ISDS_getWakeUpEventRegister(&data->sensor_interface, &wake_up_event) != WE_SUCCESS) { + LOG_ERR("Failed to read wake-up event register"); + return; + } +#endif /* CONFIG_WSEN_ISDS_2536030320001_FREEFALL || CONFIG_WSEN_ISDS_2536030320001_DELTA */ + +#ifdef CONFIG_WSEN_ISDS_2536030320001_FREEFALL + if (data->freefall_handler && wake_up_event.freeFallState) { + data->freefall_handler(dev, data->freefall_trigger); + } +#endif /* CONFIG_WSEN_ISDS_2536030320001_FREEFALL */ + +#ifdef CONFIG_WSEN_ISDS_2536030320001_DELTA + if (data->delta_handler && wake_up_event.wakeUpState) { + data->delta_handler(dev, data->delta_trigger); + } +#endif /* CONFIG_WSEN_ISDS_2536030320001_DELTA */ + + /* Re-enable interrupt handling */ + isds_2536030320001_setup_interrupt(dev, &cfg->events_interrupt_gpio, true); +} + +/* + * Is called when interrupt on INT0. + * Triggers asynchronous handling of interrupt in isds_2536030320001_process_interrupt(). + */ +static void isds_2536030320001_interrupt_0_gpio_callback(const struct device *dev, + struct gpio_callback *cb, uint32_t pins) +{ + struct isds_2536030320001_data *data = + CONTAINER_OF(cb, struct isds_2536030320001_data, events_interrupt_cb); + + ARG_UNUSED(pins); + + isds_2536030320001_handle_interrupt_0(data->dev); +} + +#endif /* CONFIG_WSEN_ISDS_2536030320001_EVENTS */ + +#ifdef CONFIG_WSEN_ISDS_2536030320001_TRIGGER_OWN_THREAD +static void isds_2536030320001_drdy_thread(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct isds_2536030320001_data *data = p1; + + while (true) { + k_sem_take(&data->drdy_sem, K_FOREVER); + isds_2536030320001_process_interrupt_1(data->dev); + } +} +#ifdef CONFIG_WSEN_ISDS_2536030320001_EVENTS +static void isds_2536030320001_events_thread(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct isds_2536030320001_data *data = p1; + + while (true) { + k_sem_take(&data->events_sem, K_FOREVER); + isds_2536030320001_process_interrupt_0(data->dev); + } +} +#endif /* CONFIG_WSEN_ISDS_2536030320001_EVENTS */ +#endif /* CONFIG_WSEN_ISDS_2536030320001_TRIGGER_OWN_THREAD */ + +#ifdef CONFIG_WSEN_ISDS_2536030320001_TRIGGER_GLOBAL_THREAD +static void isds_2536030320001_drdy_work_cb(struct k_work *work) +{ + struct isds_2536030320001_data *isds_2536030320001 = + CONTAINER_OF(work, struct isds_2536030320001_data, drdy_work); + + isds_2536030320001_process_interrupt_1(isds_2536030320001->dev); +} + +#ifdef CONFIG_WSEN_ISDS_2536030320001_EVENTS +static void isds_2536030320001_events_work_cb(struct k_work *work) +{ + struct isds_2536030320001_data *isds_2536030320001 = + CONTAINER_OF(work, struct isds_2536030320001_data, events_work); + + isds_2536030320001_process_interrupt_0(isds_2536030320001->dev); +} +#endif /* CONFIG_WSEN_ISDS_2536030320001_EVENTS */ +#endif /* CONFIG_WSEN_ISDS_2536030320001_TRIGGER_GLOBAL_THREAD */ + +/* (Un)register trigger handler and enable/disable the corresponding sensor interrupt */ +int isds_2536030320001_trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + struct isds_2536030320001_data *data = dev->data; + const struct isds_2536030320001_config *cfg = dev->config; + + ISDS_state_t state = (handler != NULL) ? ISDS_enable : ISDS_disable; + + switch (trig->type) { + case SENSOR_TRIG_DATA_READY: { + int16_t x, y, z; + + switch (trig->chan) { + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: { + data->accel_data_ready_handler = handler; + data->accel_data_ready_trigger = trig; + isds_2536030320001_setup_interrupt(dev, &cfg->drdy_interrupt_gpio, + data->accel_data_ready_handler || + data->gyro_data_ready_handler || + data->temp_data_ready_handler); + if (state) { + /* Dummy read: re-trigger interrupt */ + ISDS_getRawAccelerations(&data->sensor_interface, &x, &y, &z); + } + if (ISDS_enableAccDataReadyINT1(&data->sensor_interface, state) != + WE_SUCCESS) { + return -EIO; + } + break; + } + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + case SENSOR_CHAN_GYRO_XYZ: { + data->gyro_data_ready_handler = handler; + data->gyro_data_ready_trigger = trig; + isds_2536030320001_setup_interrupt(dev, &cfg->drdy_interrupt_gpio, + data->accel_data_ready_handler || + data->gyro_data_ready_handler || + data->temp_data_ready_handler); + if (state) { + /* Dummy read: re-trigger interrupt */ + ISDS_getRawAngularRates(&data->sensor_interface, &x, &y, &z); + } + if (ISDS_enableGyroDataReadyINT1(&data->sensor_interface, state) != + WE_SUCCESS) { + return -EIO; + } + break; + } + case SENSOR_CHAN_AMBIENT_TEMP: { + data->temp_data_ready_handler = handler; + data->temp_data_ready_trigger = trig; + isds_2536030320001_setup_interrupt(dev, &cfg->drdy_interrupt_gpio, + data->accel_data_ready_handler || + data->gyro_data_ready_handler || + data->temp_data_ready_handler); + if (state) { + /* Dummy read: re-trigger interrupt */ + ISDS_getRawTemperature(&data->sensor_interface, &x); + } + if (ISDS_enableTemperatureDataReadyINT1(&data->sensor_interface, state) != + WE_SUCCESS) { + return -EIO; + } + break; + } + default: + goto error; + } + return 0; + } +#ifdef CONFIG_WSEN_ISDS_2536030320001_TAP + case SENSOR_TRIG_TAP: + if (trig->chan != SENSOR_CHAN_ALL) { + break; + } + data->single_tap_handler = handler; + data->single_tap_trigger = trig; + isds_2536030320001_setup_interrupt( + dev, &cfg->events_interrupt_gpio, + data->single_tap_handler || data->double_tap_handler || + data->freefall_handler || data->delta_handler); + if (ISDS_enableSingleTapINT0(&data->sensor_interface, state) != WE_SUCCESS) { + return -EIO; + } + return 0; + case SENSOR_TRIG_DOUBLE_TAP: + if (trig->chan != SENSOR_CHAN_ALL) { + break; + } + data->double_tap_handler = handler; + data->double_tap_trigger = trig; + isds_2536030320001_setup_interrupt( + dev, &cfg->events_interrupt_gpio, + data->single_tap_handler || data->double_tap_handler || + data->freefall_handler || data->delta_handler); + if (ISDS_enableDoubleTapINT0(&data->sensor_interface, state) != WE_SUCCESS) { + return -EIO; + } + return 0; +#endif /* CONFIG_WSEN_ISDS_2536030320001_TAP */ + +#ifdef CONFIG_WSEN_ISDS_2536030320001_FREEFALL + case SENSOR_TRIG_FREEFALL: + if (trig->chan != SENSOR_CHAN_ALL) { + break; + } + data->freefall_handler = handler; + data->freefall_trigger = trig; + isds_2536030320001_setup_interrupt( + dev, &cfg->events_interrupt_gpio, + data->single_tap_handler || data->double_tap_handler || + data->freefall_handler || data->delta_handler); + if (ISDS_enableFreeFallINT0(&data->sensor_interface, state) != WE_SUCCESS) { + return -EIO; + } + return 0; +#endif /* CONFIG_WSEN_ISDS_2536030320001_FREEFALL */ + +#ifdef CONFIG_WSEN_ISDS_2536030320001_DELTA + case SENSOR_TRIG_DELTA: + if (trig->chan != SENSOR_CHAN_ALL) { + break; + } + data->delta_handler = handler; + data->delta_trigger = trig; + isds_2536030320001_setup_interrupt( + dev, &cfg->events_interrupt_gpio, + data->single_tap_handler || data->double_tap_handler || + data->freefall_handler || data->delta_handler); + if (ISDS_enableWakeUpINT0(&data->sensor_interface, state) != WE_SUCCESS) { + return -EIO; + } + return 0; +#endif /* CONFIG_WSEN_ISDS_2536030320001_DELTA */ + default: + break; + } + +error: + LOG_ERR("Unsupported sensor trigger"); + return -ENOTSUP; +} + +int isds_2536030320001_init_interrupt(const struct device *dev) +{ + struct isds_2536030320001_data *data = dev->data; + const struct isds_2536030320001_config *cfg = dev->config; + + data->dev = dev; + + if (cfg->drdy_interrupt_gpio.port == NULL) { + LOG_ERR("drdy-interrupt-gpios is not defined in the device tree."); + return -EINVAL; + } + + if (!gpio_is_ready_dt(&cfg->drdy_interrupt_gpio)) { + LOG_ERR("Device %s is not ready", cfg->drdy_interrupt_gpio.port->name); + return -ENODEV; + } + + /* Setup interrupt gpio */ + if (gpio_pin_configure_dt(&cfg->drdy_interrupt_gpio, GPIO_INPUT) < 0) { + LOG_ERR("Failed to configure %s.%02u", cfg->drdy_interrupt_gpio.port->name, + cfg->drdy_interrupt_gpio.pin); + return -EIO; + } + + gpio_init_callback(&data->drdy_interrupt_cb, isds_2536030320001_interrupt_1_gpio_callback, + BIT(cfg->drdy_interrupt_gpio.pin)); + + if (gpio_add_callback(cfg->drdy_interrupt_gpio.port, &data->drdy_interrupt_cb) < 0) { + LOG_ERR("Failed to set gpio callback"); + return -EIO; + } + +#if defined(CONFIG_WSEN_ISDS_2536030320001_EVENTS) + + if (cfg->events_interrupt_gpio.port == NULL) { + LOG_DBG("events-interrupt-gpios is not defined in the device tree."); + return -EINVAL; + } + + if (!gpio_is_ready_dt(&cfg->events_interrupt_gpio)) { + LOG_ERR("Device %s is not ready", cfg->events_interrupt_gpio.port->name); + return -ENODEV; + } + + /* Setup interrupt gpio */ + if (gpio_pin_configure_dt(&cfg->events_interrupt_gpio, GPIO_INPUT) < 0) { + LOG_ERR("Failed to configure %s.%02u", cfg->events_interrupt_gpio.port->name, + cfg->events_interrupt_gpio.pin); + return -EIO; + } + + gpio_init_callback(&data->events_interrupt_cb, isds_2536030320001_interrupt_0_gpio_callback, + BIT(cfg->events_interrupt_gpio.pin)); + + if (gpio_add_callback(cfg->events_interrupt_gpio.port, &data->events_interrupt_cb) < 0) { + LOG_ERR("Failed to set gpio callback"); + return -EIO; + } + +#endif + +#if defined(CONFIG_WSEN_ISDS_2536030320001_TRIGGER_OWN_THREAD) + k_sem_init(&data->drdy_sem, 0, K_SEM_MAX_LIMIT); + + k_thread_create(&data->drdy_thread, data->drdy_thread_stack, + CONFIG_WSEN_ISDS_2536030320001_THREAD_STACK_SIZE, + isds_2536030320001_drdy_thread, data, NULL, NULL, + K_PRIO_COOP(CONFIG_WSEN_ISDS_2536030320001_THREAD_PRIORITY), 0, K_NO_WAIT); +#if defined(CONFIG_WSEN_ISDS_2536030320001_EVENTS) + k_sem_init(&data->events_sem, 0, K_SEM_MAX_LIMIT); + + k_thread_create(&data->events_thread, data->events_thread_stack, + CONFIG_WSEN_ISDS_2536030320001_THREAD_STACK_SIZE, + isds_2536030320001_events_thread, data, NULL, NULL, + K_PRIO_COOP(CONFIG_WSEN_ISDS_2536030320001_THREAD_PRIORITY), 0, K_NO_WAIT); +#endif +#elif defined(CONFIG_WSEN_ISDS_2536030320001_TRIGGER_GLOBAL_THREAD) + data->drdy_work.handler = isds_2536030320001_drdy_work_cb; +#if defined(CONFIG_WSEN_ISDS_2536030320001_EVENTS) + data->events_work.handler = isds_2536030320001_events_work_cb; +#endif +#endif + + /* Enable interrupt on INT_0/INT_1 in pulsed mode */ + if (ISDS_enableLatchedInterrupt(&data->sensor_interface, ISDS_disable) != WE_SUCCESS) { + LOG_ERR("Failed to disable latched mode"); + return -EIO; + } + + /* Enable data-ready interrupt on INT_0/INT_1 in pulsed mode */ + if (ISDS_enableDataReadyPulsed(&data->sensor_interface, ISDS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable data-ready pulsed mode"); + return -EIO; + } + + if (ISDS_enableInterrupts(&data->sensor_interface, ISDS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable interrupts"); + return -EIO; + } + +#ifdef CONFIG_WSEN_ISDS_2536030320001_TAP + if (cfg->accel_odr < ISDS_accOdr416Hz || cfg->accel_odr >= ISDS_accOdr1Hz6) { + LOG_WRN("The tap recognition feature requires a minimum output data rate " + "of 416 Hz"); + } + + if (ISDS_enableDoubleTapEvent(&data->sensor_interface, + (cfg->tap_mode == 1) ? ISDS_enable : ISDS_disable) != + WE_SUCCESS) { + LOG_ERR("Failed to enable/disable double tap event"); + return -EIO; + } + + if (ISDS_setTapThreshold(&data->sensor_interface, cfg->tap_threshold) != WE_SUCCESS) { + LOG_ERR("Failed to set tap threshold"); + return -EIO; + } + + if (cfg->tap_axis_enable[0] != 0) { + if (ISDS_enableTapX(&data->sensor_interface, ISDS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable tap recognition in X direction"); + return -EIO; + } + } + + if (cfg->tap_axis_enable[1] != 0) { + if (ISDS_enableTapY(&data->sensor_interface, ISDS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable tap recognition in Y direction"); + return -EIO; + } + } + + if (cfg->tap_axis_enable[2] != 0) { + if (ISDS_enableTapZ(&data->sensor_interface, ISDS_enable) != WE_SUCCESS) { + LOG_ERR("Failed to enable tap recognition in Z direction"); + return -EIO; + } + } + + if (ISDS_setTapShockTime(&data->sensor_interface, cfg->tap_shock) != WE_SUCCESS) { + LOG_ERR("Failed to set tap shock duration"); + return -EIO; + } + + if (ISDS_setTapLatencyTime(&data->sensor_interface, cfg->tap_latency) != WE_SUCCESS) { + LOG_ERR("Failed to set tap latency"); + return -EIO; + } + + if (ISDS_setTapQuietTime(&data->sensor_interface, cfg->tap_quiet) != WE_SUCCESS) { + LOG_ERR("Failed to set tap quiet time"); + return -EIO; + } +#endif /* CONFIG_WSEN_ISDS_2536030320001_TAP */ + +#ifdef CONFIG_WSEN_ISDS_2536030320001_FREEFALL + if (ISDS_setFreeFallDuration(&data->sensor_interface, cfg->freefall_duration) != + WE_SUCCESS) { + LOG_ERR("Failed to set free-fall duration"); + return -EIO; + } + + if (ISDS_setFreeFallThreshold(&data->sensor_interface, cfg->freefall_threshold) != + WE_SUCCESS) { + LOG_ERR("Failed to set free-fall threshold"); + return -EIO; + } +#endif /* CONFIG_WSEN_ISDS_2536030320001_FREEFALL */ + +#ifdef CONFIG_WSEN_ISDS_2536030320001_DELTA + if (ISDS_setWakeUpDuration(&data->sensor_interface, cfg->delta_duration) != WE_SUCCESS) { + LOG_ERR("Failed to set wake-up duration"); + return -EIO; + } + + if (ISDS_setWakeUpThreshold(&data->sensor_interface, cfg->delta_threshold) != WE_SUCCESS) { + LOG_ERR("Failed to set wake-up threshold"); + return -EIO; + } +#endif /* CONFIG_WSEN_ISDS_2536030320001_DELTA */ + + return 0; +} diff --git a/dts/bindings/sensor/we,wsen-isds-2536030320001/we,wsen-isds-2536030320001-common.yaml b/dts/bindings/sensor/we,wsen-isds-2536030320001/we,wsen-isds-2536030320001-common.yaml new file mode 100644 index 000000000000..f35577ef62c1 --- /dev/null +++ b/dts/bindings/sensor/we,wsen-isds-2536030320001/we,wsen-isds-2536030320001-common.yaml @@ -0,0 +1,194 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +properties: + events-interrupt-gpios: + type: phandle-array + description: | + Events Interrupt pin (Tap, Freefall, .. etc) (INT0 Pin). + Interrupts are active high by default. + + drdy-interrupt-gpios: + type: phandle-array + description: | + DRDY Interrupt pin (INT1 Pin). + Interrupts are active high by default. + + accel-odr: + type: string + required: true + enum: + - "0" # Accelerometer turned off + - "12.5" + - "26" + - "52" + - "104" + - "208" + - "416" + - "833" + - "1660" + - "3330" + - "6660" + - "1.6" + description: Accelerometer output data rate in Hz + + accel-range: + type: int + default: 2 + enum: + - 2 # 2g + - 16 # 16g + - 4 # 4g + - 8 # 8g + description: Accelerometer range (full scale) in g. Defaults to 2, which is + the configuration at power-up. + + gyro-odr: + type: string + required: true + enum: + - "0" # Gyroscope turned off + - "12.5" + - "26" + - "52" + - "104" + - "208" + - "416" + - "833" + - "1660" + - "3330" + - "6660" + description: Gyroscope output data rate in Hz + + gyro-range: + type: int + default: 250 + enum: + - 250 + - 125 + - 500 + - 1000 + - 2000 + description: Gyroscope range (full scale) in degrees per second. Defaults to 250, + which is the configuration at power-up. + + tap-mode: + type: int + default: 0 + enum: + - 0 # Only single tap + - 1 # Single and double tap + description: Tap mode (only single tap or single and double tap). + Defaults to 0, which is the configuration at power-up. + + tap-threshold: + type: int + default: 0 + description: | + Tap X/Y/Z axis threshold (unsigned 5-bit, ranging from 0x00 to 0x1F). + Defaults to zero, which is the configuration at power-up. + + Threshold for tap recognition on the X/Y/Z axes depending on selected + measurement range (full scale). + + Example: + + tap-threshold = <6> + + For FS=2g, this sets the threshold to 6 \* 2g/32 = 375mg. + + tap-axis-enable: + type: array + default: [1, 1, 1] + description: | + Enable/disable tap recognition on X/Y/Z axis. + + Defaults to "<1>, <1>, <1>", i.e. tap recognition enabled for all three axes. + Setting elements of this array to zero disables tap recognition for the + corresponding axes. + + tap-shock: + type: int + default: 0x0 + description: | + Maximum duration of over-threshold event when detecting taps (unsigned + 2-bit, ranging from 0x0 to 0x3). Defaults to zero, which is the + configuration at power-up. + + A value of 0 corresponds to 4 \* 1/ODR and 1 LSB = 8 \* 1/ODR. + + tap-latency: + type: int + default: 0x0 + description: | + Maximum duration time gap for double-tap recognition (unsigned 4-bit, + ranging from 0x0 to 0xF). Defaults to zero, which is the + configuration at power-up. + + A value of 0 corresponds to 16 \* 1/ODR and 1 LSB = 32 \* 1/ODR. + + tap-quiet: + type: int + default: 0x0 + description: | + Expected quiet time for double-tap recognition (unsigned 2-bit, ranging + from 0x0 to 0x3). This defines the time after the first detected tap in + which there must not be any over-threshold event. Defaults to zero, which + is the configuration at power-up. + + A value of 0 corresponds to 2 \* 1/ODR and 1 LSB = 4 \* 1/ODR. + + freefall-duration: + type: int + default: 0x0 + description: | + Minimum duration of free-fall event (unsigned 6-bit, ranging from 0x0 + to 0x3F). Defaults to 0, which is the configuration at power-up. + + 1 LSB = 1 \* 1/ODR. + + freefall-threshold: + type: int + default: 0x0 + enum: + - 0 # 156 mg + - 1 # 219 mg + - 2 # 250 mg + - 3 # 312 mg + - 4 # 344 mg + - 5 # 406 mg + - 6 # 469 mg + - 7 # 500 mg + description: | + Free-fall threshold (amplitude of the "free-fall zone" around zero-g + level where the accelerations of all axes are small enough to generate + the free-fall interrupt). Defaults to 0, which is the configuration + at power-up. + + delta-duration: + type: int + default: 0x0 + enum: + - 0 + - 1 + - 2 + - 3 + description: | + Wake-up duration, i.e. minimum duration of wake-up event to be + recognized (unsigned 2-bit, ranging from 0x0 to 0x3). + Defaults to 0, which is the configuration at power-up. + + 1 LSB = 1 \* 1/ODR + + delta-threshold: + type: int + default: 0x0 + description: | + Wake-up threshold (unsigned 6-bit, ranging from 0x0 to 0x3F). + The threshold value is applicable to both positive and negative + acceleration data. A wake-up event is recognized, if at least + one of the acceleration axis values exceeds the threshold value. + + Defaults to 0, which is the configuration at power-up. + + 1 LSB = 1/64 of measurement range (full scale). diff --git a/dts/bindings/sensor/we,wsen-isds-2536030320001/we,wsen-isds-2536030320001-i2c.yaml b/dts/bindings/sensor/we,wsen-isds-2536030320001/we,wsen-isds-2536030320001-i2c.yaml new file mode 100644 index 000000000000..922904599111 --- /dev/null +++ b/dts/bindings/sensor/we,wsen-isds-2536030320001/we,wsen-isds-2536030320001-i2c.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +description: | + Würth Elektronik WSEN-ISDS-2536030320001 acceleration and gyroscope sensor with + integrated temperature sensor (I2C bus) + +compatible: "we,wsen-isds-2536030320001" + +include: ["i2c-device.yaml", "we,wsen-isds-2536030320001-common.yaml"] diff --git a/dts/bindings/sensor/we,wsen-isds-2536030320001/we,wsen-isds-2536030320001-spi.yaml b/dts/bindings/sensor/we,wsen-isds-2536030320001/we,wsen-isds-2536030320001-spi.yaml new file mode 100644 index 000000000000..7287bd9d4b52 --- /dev/null +++ b/dts/bindings/sensor/we,wsen-isds-2536030320001/we,wsen-isds-2536030320001-spi.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +description: | + Würth Elektronik WSEN-ISDS-2536030320001 acceleration and gyroscope sensor with + integrated temperature sensor (SPI bus) + +compatible: "we,wsen-isds-2536030320001" + +include: ["spi-device.yaml", "we,wsen-isds-2536030320001-common.yaml"] diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index 8cf2b6a8216a..d1484c37271e 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -1105,3 +1105,18 @@ test_i2c_wsen_hids_2525020210002: wsen_hids_2525020210002@94 { reg = <0x94>; precision = "High"; }; + +test_i2c_wsen_isds_2536030320001: wsen_isds_2536030320001@95 { + compatible = "we,wsen-isds-2536030320001"; + reg = <0x95>; + accel-odr = "416"; + gyro-odr = "416"; + tap-threshold = < 9 >; + tap-latency = < 5 >; + tap-shock = < 2 >; + tap-quiet = < 1 >; + tap-mode = < 1 >; + tap-axis-enable = < 0 0 1 >; + events-interrupt-gpios = <&test_gpio 0 0>; + drdy-interrupt-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 c4b53ea2a6e7..8b1002348fb6 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_global.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_global.conf @@ -64,6 +64,7 @@ CONFIG_TSL2540_TRIGGER_GLOBAL_THREAD=y CONFIG_TSL2591_TRIGGER_GLOBAL_THREAD=y CONFIG_VCNL4040_TRIGGER_GLOBAL_THREAD=y CONFIG_WSEN_HIDS_2525020210001_TRIGGER_GLOBAL_THREAD=y +CONFIG_WSEN_ISDS_2536030320001_TRIGGER_GLOBAL_THREAD=y CONFIG_WSEN_ITDS_2533020201601_TRIGGER_GLOBAL_THREAD=y CONFIG_WSEN_PADS_2511020213301_TRIGGER_GLOBAL_THREAD=y CONFIG_WSEN_TIDS_2521020222501_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 a51eda8b88eb..f7a76f93fad3 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_none.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_none.conf @@ -64,6 +64,7 @@ CONFIG_TSL2540_TRIGGER_NONE=y CONFIG_TSL2591_TRIGGER_NONE=y CONFIG_VCNL4040_TRIGGER_NONE=y CONFIG_WSEN_HIDS_2525020210001_TRIGGER_NONE=y +CONFIG_WSEN_ISDS_2536030320001_TRIGGER_NONE=y CONFIG_WSEN_ITDS_2533020201601_TRIGGER_NONE=y CONFIG_WSEN_PADS_2511020213301_TRIGGER_NONE=y CONFIG_WSEN_TIDS_2521020222501_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 b618c6da3d0d..c8da76e0777e 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_own.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_own.conf @@ -61,6 +61,7 @@ CONFIG_TSL2540_TRIGGER_OWN_THREAD=y CONFIG_TSL2591_TRIGGER_OWN_THREAD=y CONFIG_VCNL4040_TRIGGER_OWN_THREAD=y CONFIG_WSEN_HIDS_2525020210001_TRIGGER_OWN_THREAD=y +CONFIG_WSEN_ISDS_2536030320001_TRIGGER_OWN_THREAD=y CONFIG_WSEN_ITDS_2533020201601_TRIGGER_OWN_THREAD=y CONFIG_WSEN_PADS_2511020213301_TRIGGER_OWN_THREAD=y CONFIG_WSEN_TIDS_2521020222501_TRIGGER_OWN_THREAD=y From 4c5ff0027ae7a277851fe4262426532d3aaa4fa3 Mon Sep 17 00:00:00 2001 From: Wajdi ELMuhtadi Date: Mon, 5 Feb 2024 09:55:01 +0100 Subject: [PATCH 14/14] doc: releases: update notes for wurth drivers update update release notes and migration guide for wurth elektronik sensor drivers update. Signed-off-by: Wajdi ELMuhtadi --- doc/releases/migration-guide-4.0.rst | 77 ++++++++++++++++++++++++++++ doc/releases/release-notes-4.0.rst | 17 ++++++ 2 files changed, 94 insertions(+) diff --git a/doc/releases/migration-guide-4.0.rst b/doc/releases/migration-guide-4.0.rst index 9395e39eac98..98b858796c58 100644 --- a/doc/releases/migration-guide-4.0.rst +++ b/doc/releases/migration-guide-4.0.rst @@ -91,6 +91,83 @@ LED Strip Sensors ======= +* The :dtcompatible:`we,wsen-itds` driver has been renamed to + :dtcompatible:`we,wsen-itds-2533020201601`. + The Device Tree can be configured as follows: + + .. code-block:: devicetree + + &i2c0 { + itds:itds-2533020201601@19 { + compatible = "we,wsen-itds-2533020201601"; + reg = <0x19>; + odr = "400"; + op-mode = "high-perf"; + power-mode = "normal"; + events-interrupt-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; + drdy-interrupt-gpios = < &gpio1 2 GPIO_ACTIVE_HIGH >; + }; + }; + +* The :dtcompatible:`we,wsen-hids` driver has been renamed to + :dtcompatible:`we,wsen-hids-2525020210001`. + The Device Tree can be configured as follows: + + .. code-block:: devicetree + + &i2c0 { + hids:hids-2525020210001@5F { + compatible = "we,wsen-hids-2525020210001"; + reg = < 0x5F >; + odr = "1"; + drdy-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; + }; + }; + + * The :dtcompatible:`we,wsen-pads` driver has been renamed to + :dtcompatible:`we,wsen-pads-2511020213301`. + The Device Tree can be configured as follows: + + .. code-block:: devicetree + + &i2c0 { + pads:pads-2511020213301@5d { + compatible = "we,wsen-pads-2511020213301"; + reg = <0x5d>; + odr = < 10 >; + interrupt-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; + }; + }; + + * The :dtcompatible:`we,wsen-pdus` driver has been renamed to + :dtcompatible:`we,wsen-pdus-25131308XXXXX`. + The Device Tree can be configured as follows: + + .. code-block:: devicetree + + &i2c0 { + pdus:pdus-25131308XXXXX@78 { + compatible = "we,wsen-pdus-25131308XXXXX"; + reg = < 0x78 >; + sensor-type = < 4 >; + }; + }; + + * The :dtcompatible:`we,wsen-tids` driver has been renamed to + :dtcompatible:`we,wsen-tids-2521020222501`. + The Device Tree can be configured as follows: + + .. code-block:: devicetree + + &i2c0 { + tids:tids-2521020222501@3F { + compatible = "we,wsen-tids-2521020222501"; + reg = < 0x3F >; + odr = < 25 >; + interrupt-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>; + }; + }; + Serial ====== diff --git a/doc/releases/release-notes-4.0.rst b/doc/releases/release-notes-4.0.rst index 25ba180d581b..bd3178c393d9 100644 --- a/doc/releases/release-notes-4.0.rst +++ b/doc/releases/release-notes-4.0.rst @@ -166,6 +166,23 @@ Drivers and Sensors * Sensors + * WE + + * Replaced outdated :dtcompatible:`we,wsen-itds` accelerometer driver + and renamed it to :dtcompatible:`we,wsen-itds-2533020201601`. + * Replaced outdated :dtcompatible:`we,wsen-hids` humidity sensor driver + and renamed it to :dtcompatible:`we,wsen-hids-2525020210001`. + * Added Würth Elektronik HIDS-2525020210002 + :dtcompatible:`we,wsen-hids-2525020210002` humidity sensor driver. + * Replaced outdated :dtcompatible:`we,wsen-pads` absolute pressure sensor driver + and renamed it to :dtcompatible:`we,wsen-pads-2511020213301`. + * Replaced outdated :dtcompatible:`we,wsen-pdus` differential pressure sensor driver + and renamed it to :dtcompatible:`we,wsen-pdus-25131308XXXXX`. + * Added Würth Elektronik ISDS-2536030320001 + :dtcompatible:`we,wsen-isds-2536030320001` 6-axis IMU sensor driver. + * Replaced outdated :dtcompatible:`we,wsen-tids` temperature sensor driver + and renamed it to :dtcompatible:`we,wsen-tids-2521020222501`. + * Serial * LiteX: Renamed the ``compatible`` from ``litex,uart0`` to :dtcompatible:`litex,uart`.