From 871d132577729b69bf296f9f04735597a6a2f6bd Mon Sep 17 00:00:00 2001 From: Armando Visconti Date: Thu, 5 Sep 2019 15:19:40 +0200 Subject: [PATCH] driver/sensor: add IIS3DHHC accelerometer sensor Add support to STM IIS3DHHC the ultra-low noise, high-stability three-axis linear accelerometer. Signed-off-by: Armando Visconti --- drivers/sensor/CMakeLists.txt | 1 + drivers/sensor/Kconfig | 2 + drivers/sensor/iis3dhhc/CMakeLists.txt | 11 + drivers/sensor/iis3dhhc/Kconfig | 72 +++++ drivers/sensor/iis3dhhc/iis3dhhc.c | 257 ++++++++++++++++++ drivers/sensor/iis3dhhc/iis3dhhc.h | 80 ++++++ drivers/sensor/iis3dhhc/iis3dhhc_spi.c | 126 +++++++++ drivers/sensor/iis3dhhc/iis3dhhc_trigger.c | 172 ++++++++++++ dts/bindings/sensor/st,iis3dhhc-spi.yaml | 18 ++ tests/drivers/build_all/dts_fixup.h | 12 + tests/drivers/build_all/sensors_i_z.conf | 1 + .../build_all/sensors_trigger_i_z.conf | 2 + 12 files changed, 754 insertions(+) create mode 100644 drivers/sensor/iis3dhhc/CMakeLists.txt create mode 100644 drivers/sensor/iis3dhhc/Kconfig create mode 100644 drivers/sensor/iis3dhhc/iis3dhhc.c create mode 100644 drivers/sensor/iis3dhhc/iis3dhhc.h create mode 100644 drivers/sensor/iis3dhhc/iis3dhhc_spi.c create mode 100644 drivers/sensor/iis3dhhc/iis3dhhc_trigger.c create mode 100644 dts/bindings/sensor/st,iis3dhhc-spi.yaml diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index 61333fe6121..a3c4df804c6 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -24,6 +24,7 @@ add_subdirectory_ifdef(CONFIG_TI_HDC ti_hdc) add_subdirectory_ifdef(CONFIG_HMC5883L hmc5883l) add_subdirectory_ifdef(CONFIG_HP206C hp206c) add_subdirectory_ifdef(CONFIG_HTS221 hts221) +add_subdirectory_ifdef(CONFIG_IIS3DHHC iis3dhhc) add_subdirectory_ifdef(CONFIG_ISL29035 isl29035) add_subdirectory_ifdef(CONFIG_LIS2DH lis2dh) add_subdirectory_ifdef(CONFIG_LIS2DS12 lis2ds12) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 0bf9a127ba3..6dbcd905c5c 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -73,6 +73,8 @@ source "drivers/sensor/hp206c/Kconfig" source "drivers/sensor/hts221/Kconfig" +source "drivers/sensor/iis3dhhc/Kconfig" + source "drivers/sensor/isl29035/Kconfig" source "drivers/sensor/lis2dh/Kconfig" diff --git a/drivers/sensor/iis3dhhc/CMakeLists.txt b/drivers/sensor/iis3dhhc/CMakeLists.txt new file mode 100644 index 00000000000..1ef89503b0d --- /dev/null +++ b/drivers/sensor/iis3dhhc/CMakeLists.txt @@ -0,0 +1,11 @@ +# ST Microelectronics IIS3DHHC accelerometer sensor +# +# Copyright (c) 2019 STMicroelectronics +# +# SPDX-License-Identifier: Apache-2.0 +# +zephyr_library() + +zephyr_library_sources_ifdef(CONFIG_IIS3DHHC iis3dhhc.c) +zephyr_library_sources_ifdef(CONFIG_IIS3DHHC iis3dhhc_spi.c) +zephyr_library_sources_ifdef(CONFIG_IIS3DHHC_TRIGGER iis3dhhc_trigger.c) diff --git a/drivers/sensor/iis3dhhc/Kconfig b/drivers/sensor/iis3dhhc/Kconfig new file mode 100644 index 00000000000..54931d2e72b --- /dev/null +++ b/drivers/sensor/iis3dhhc/Kconfig @@ -0,0 +1,72 @@ +# ST Microelectronics IIS3DHHC accelerometer sensor +# +# Copyright (c) 2019 STMicroelectronics +# +# SPDX-License-Identifier: Apache-2.0 +# + +menuconfig IIS3DHHC + bool "IIS3DHHC accelerometer sensor" + depends on SPI + select HAS_STMEMSC + select USE_STDC_IIS3DHHC + help + Enable driver for IIS3DHHC SPI-based accelerometer sensor. + +if IIS3DHHC + +choice IIS3DHHC_TRIGGER_MODE + prompt "Trigger mode" + default IIS3DHHC_TRIGGER_GLOBAL_THREAD + help + Specify the type of triggering to be used by the driver. + +config IIS3DHHC_TRIGGER_NONE + bool "No trigger" + +config IIS3DHHC_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + depends on GPIO + select IIS3DHHC_TRIGGER + +config IIS3DHHC_TRIGGER_OWN_THREAD + bool "Use own thread" + depends on GPIO + select IIS3DHHC_TRIGGER + +endchoice # IIS3DHHC_TRIGGER_MODE + +config IIS3DHHC_TRIGGER + bool + +config IIS3DHHC_THREAD_PRIORITY + int "Thread priority" + depends on IIS3DHHC_TRIGGER_OWN_THREAD + default 10 + help + Priority of thread used by the driver to handle interrupts. + +config IIS3DHHC_THREAD_STACK_SIZE + int "Thread stack size" + depends on IIS3DHHC_TRIGGER_OWN_THREAD + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + +menu "Attributes" + +config IIS3DHHC_NORM_MODE + bool "Enable Sensor at 1KHz" + default y + +config IIS3DHHC_DRDY_INT1 + bool "Data ready interrupt to INT1 pin" + depends on IIS3DHHC_TRIGGER + default y + help + Say Y to route data ready interrupt to INT1 pin. Say N to route to + INT2 pin. + +endmenu + +endif # IIS3DHHC diff --git a/drivers/sensor/iis3dhhc/iis3dhhc.c b/drivers/sensor/iis3dhhc/iis3dhhc.c new file mode 100644 index 00000000000..bec30006ac2 --- /dev/null +++ b/drivers/sensor/iis3dhhc/iis3dhhc.c @@ -0,0 +1,257 @@ +/* ST Microelectronics IIS3DHHC accelerometer senor + * + * Copyright (c) 2019 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/iis3dhhc.pdf + */ + +#include +#include +#include +#include +#include +#include + +#include "iis3dhhc.h" + +#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL +LOG_MODULE_REGISTER(IIS3DHHC); + +static int iis3dhhc_sample_fetch(struct device *dev, + enum sensor_channel chan) +{ + struct iis3dhhc_data *data = dev->driver_data; + axis3bit16_t raw_accel; + + __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL); + + iis3dhhc_acceleration_raw_get(data->ctx, raw_accel.u8bit); + data->acc[0] = sys_le16_to_cpu(raw_accel.i16bit[0]); + data->acc[1] = sys_le16_to_cpu(raw_accel.i16bit[1]); + data->acc[2] = sys_le16_to_cpu(raw_accel.i16bit[2]); + + return 0; +} + +#define IIS3DHHC_FROM_LSB_TO_ums2(lsb) \ + ((IIS3DHHC_FROM_LSB_TO_mg((s64_t)lsb) * SENSOR_G) / 1000LL) + +static inline void iis3dhhc_convert(struct sensor_value *val, + s16_t raw_val) +{ + s64_t micro_ms2; + + /* Convert to m/s^2 */ + micro_ms2 = IIS3DHHC_FROM_LSB_TO_ums2((s64_t)raw_val); + val->val1 = micro_ms2 / 1000000LL; + val->val2 = micro_ms2 % 1000000LL; +} + +static inline void iis3dhhc_channel_get_acc(struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + int i; + u8_t ofs_start, ofs_stop; + struct iis3dhhc_data *iis3dhhc = dev->driver_data; + struct sensor_value *pval = val; + + 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++) { + iis3dhhc_convert(pval++, iis3dhhc->acc[i]); + } +} + +static int iis3dhhc_channel_get(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: + iis3dhhc_channel_get_acc(dev, chan, val); + return 0; + default: + LOG_DBG("Channel not supported"); + break; + } + + return -ENOTSUP; +} + +static int iis3dhhc_odr_set(struct device *dev, + const struct sensor_value *val) +{ + struct iis3dhhc_data *data = dev->driver_data; + iis3dhhc_norm_mod_en_t en; + + switch (val->val1) { + case 0: + en = IIS3DHHC_POWER_DOWN; + break; + case 1000: + en = IIS3DHHC_1kHz1; + break; + default: + return -EIO; + } + + if (iis3dhhc_data_rate_set(data->ctx, en)) { + LOG_DBG("failed to set sampling rate"); + return -EIO; + } + + return 0; +} + +static int iis3dhhc_attr_set(struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, + const struct sensor_value *val) +{ + if (chan != SENSOR_CHAN_ALL) { + LOG_WRN("attr_set() not supported on this channel."); + return -ENOTSUP; + } + + switch (attr) { + case SENSOR_ATTR_SAMPLING_FREQUENCY: + return iis3dhhc_odr_set(dev, val); + default: + LOG_DBG("operation not supported."); + return -ENOTSUP; + } + + return 0; +} + +static const struct sensor_driver_api iis3dhhc_api_funcs = { + .attr_set = iis3dhhc_attr_set, + .sample_fetch = iis3dhhc_sample_fetch, + .channel_get = iis3dhhc_channel_get, +#if CONFIG_IIS3DHHC_TRIGGER + .trigger_set = iis3dhhc_trigger_set, +#endif +}; + +static int iis3dhhc_init_chip(struct device *dev) +{ + struct iis3dhhc_data *data = dev->driver_data; + u8_t chip_id, rst; + + if (iis3dhhc_device_id_get(data->ctx, &chip_id) < 0) { + LOG_DBG("Failed reading chip id"); + return -EIO; + } + + if (chip_id != IIS3DHHC_ID) { + LOG_DBG("Invalid chip id 0x%x", chip_id); + return -EIO; + } + + /* + * Restore default configuration + */ + iis3dhhc_reset_set(data->ctx, PROPERTY_ENABLE); + do { + iis3dhhc_reset_get(data->ctx, &rst); + } while (rst); + + /* Enable Block Data Update */ + iis3dhhc_block_data_update_set(data->ctx, PROPERTY_ENABLE); + + /* Set Output Data Rate */ +#ifdef CONFIG_IIS3DHHC_NORM_MODE + iis3dhhc_data_rate_set(data->ctx, 1); +#else + iis3dhhc_data_rate_set(data->ctx, 0); +#endif + + /* Enable temperature compensation */ + iis3dhhc_offset_temp_comp_set(data->ctx, PROPERTY_ENABLE); + + return 0; +} + +static int iis3dhhc_init(struct device *dev) +{ + const struct iis3dhhc_config * const config = dev->config->config_info; + struct iis3dhhc_data *data = dev->driver_data; + + data->bus = device_get_binding(config->master_dev_name); + if (!data->bus) { + LOG_DBG("bus master not found: %s", config->master_dev_name); + return -EINVAL; + } + + config->bus_init(dev); + + if (iis3dhhc_init_chip(dev) < 0) { + LOG_DBG("Failed to initialize chip"); + return -EIO; + } + +#ifdef CONFIG_IIS3DHHC_TRIGGER + if (iis3dhhc_init_interrupt(dev) < 0) { + LOG_ERR("Failed to initialize interrupt."); + return -EIO; + } +#endif + + return 0; +} + +static struct iis3dhhc_data iis3dhhc_data; + +static const struct iis3dhhc_config iis3dhhc_config = { + .master_dev_name = DT_INST_0_ST_IIS3DHHC_BUS_NAME, +#ifdef CONFIG_IIS3DHHC_TRIGGER +#ifdef CONFIG_IIS3DHHC_DRDY_INT1 + .int_port = DT_INST_0_ST_IIS3DHHC_IRQ_GPIOS_CONTROLLER_0, + .int_pin = DT_INST_0_ST_IIS3DHHC_IRQ_GPIOS_PIN_0, +#else + .int_port = DT_INST_0_ST_IIS3DHHC_IRQ_GPIOS_CONTROLLER_1, + .int_pin = DT_INST_0_ST_IIS3DHHC_IRQ_GPIOS_PIN_1, +#endif /* CONFIG_IIS3DHHC_DRDY_INT1 */ +#endif /* CONFIG_IIS3DHHC_TRIGGER */ +#if defined(DT_ST_IIS3DHHC_BUS_SPI) + .bus_init = iis3dhhc_spi_init, + .spi_conf.frequency = DT_INST_0_ST_IIS3DHHC_SPI_MAX_FREQUENCY, + .spi_conf.operation = (SPI_OP_MODE_MASTER | SPI_MODE_CPOL | + SPI_MODE_CPHA | SPI_WORD_SET(8) | + SPI_LINES_SINGLE), + .spi_conf.slave = DT_INST_0_ST_IIS3DHHC_BASE_ADDRESS, +#if defined(DT_INST_0_ST_IIS3DHHC_CS_GPIO_CONTROLLER) + .gpio_cs_port = DT_INST_0_ST_IIS3DHHC_CS_GPIOS_CONTROLLER, + .cs_gpio = DT_INST_0_ST_IIS3DHHC_CS_GPIOS_PIN, + + .spi_conf.cs = &iis3dhhc_data.cs_ctrl, +#else + .spi_conf.cs = NULL, +#endif +#else +#error "BUS MACRO NOT DEFINED IN DTS" +#endif +}; + +DEVICE_AND_API_INIT(iis3dhhc, DT_INST_0_ST_IIS3DHHC_LABEL, iis3dhhc_init, + &iis3dhhc_data, &iis3dhhc_config, POST_KERNEL, + CONFIG_SENSOR_INIT_PRIORITY, &iis3dhhc_api_funcs); diff --git a/drivers/sensor/iis3dhhc/iis3dhhc.h b/drivers/sensor/iis3dhhc/iis3dhhc.h new file mode 100644 index 00000000000..2acc67423d6 --- /dev/null +++ b/drivers/sensor/iis3dhhc/iis3dhhc.h @@ -0,0 +1,80 @@ +/* ST Microelectronics IIS3DHHC accelerometer sensor + * + * Copyright (c) 2019 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/iis3dhhc.pdf + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_IIS3DHHC_IIS3DHHC_H_ +#define ZEPHYR_DRIVERS_SENSOR_IIS3DHHC_IIS3DHHC_H_ + +#include +#include +#include +#include +#include +#include +#include "iis3dhhc_reg.h" + +struct iis3dhhc_config { + char *master_dev_name; + int (*bus_init)(struct device *dev); +#ifdef CONFIG_IIS3DHHC_TRIGGER + const char *int_port; + u8_t int_pin; +#endif +#ifdef DT_ST_IIS3DHHC_BUS_SPI + struct spi_config spi_conf; +#if defined(DT_INST_0_ST_IIS3DHHC_CS_GPIO_CONTROLLER) + const char *gpio_cs_port; + u8_t cs_gpio; +#endif +#endif +}; + +struct iis3dhhc_data { + struct device *bus; + s16_t acc[3]; + + iis3dhhc_ctx_t *ctx; + +#ifdef DT_ST_IIS3DHHC_BUS_SPI + iis3dhhc_ctx_t ctx_spi; +#endif + +#ifdef CONFIG_IIS3DHHC_TRIGGER + struct device *gpio; + u32_t pin; + struct gpio_callback gpio_cb; + + sensor_trigger_handler_t handler_drdy; + +#if defined(CONFIG_IIS3DHHC_TRIGGER_OWN_THREAD) + K_THREAD_STACK_MEMBER(thread_stack, CONFIG_IIS3DHHC_THREAD_STACK_SIZE); + struct k_thread thread; + struct k_sem gpio_sem; +#elif defined(CONFIG_IIS3DHHC_TRIGGER_GLOBAL_THREAD) + struct k_work work; + struct device *dev; +#endif + +#endif /* CONFIG_IIS3DHHC_TRIGGER */ +#if defined(DT_INST_0_ST_IIS3DHHC_CS_GPIO_CONTROLLER) + struct spi_cs_control cs_ctrl; +#endif +}; + +int iis3dhhc_spi_init(struct device *dev); + +#ifdef CONFIG_IIS3DHHC_TRIGGER +int iis3dhhc_trigger_set(struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); + +int iis3dhhc_init_interrupt(struct device *dev); +#endif + +#endif /* ZEPHYR_DRIVERS_SENSOR_IIS3DHHC_IIS3DHHC_H_ */ diff --git a/drivers/sensor/iis3dhhc/iis3dhhc_spi.c b/drivers/sensor/iis3dhhc/iis3dhhc_spi.c new file mode 100644 index 00000000000..5068ff7bc41 --- /dev/null +++ b/drivers/sensor/iis3dhhc/iis3dhhc_spi.c @@ -0,0 +1,126 @@ +/* ST Microelectronics IIS3DHHC accelerometer sensor + * + * Copyright (c) 2019 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/iis3dhhc.pdf + */ + +#include +#include "iis3dhhc.h" +#include + +#ifdef DT_ST_IIS3DHHC_BUS_SPI + +#define IIS3DHHC_SPI_READ (1 << 7) + +#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL +LOG_MODULE_DECLARE(IIS3DHHC); + +static struct spi_config iis3dhhc_spi_conf = { + .frequency = DT_INST_0_ST_IIS3DHHC_SPI_MAX_FREQUENCY, + .operation = (SPI_OP_MODE_MASTER | SPI_MODE_CPOL | + SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_LINES_SINGLE), + .slave = DT_INST_0_ST_IIS3DHHC_BASE_ADDRESS, + .cs = NULL, +}; + +static int iis3dhhc_spi_read(struct iis3dhhc_data *ctx, u8_t reg, + u8_t *data, u16_t len) +{ + struct spi_config *spi_cfg = &iis3dhhc_spi_conf; + u8_t buffer_tx[2] = { reg | IIS3DHHC_SPI_READ, 0 }; + const struct spi_buf tx_buf = { + .buf = buffer_tx, + .len = 2, + }; + const struct spi_buf_set tx = { + .buffers = &tx_buf, + .count = 1 + }; + const struct spi_buf rx_buf[2] = { + { + .buf = NULL, + .len = 1, + }, + { + .buf = data, + .len = len, + } + }; + const struct spi_buf_set rx = { + .buffers = rx_buf, + .count = 2 + }; + + if (spi_transceive(ctx->bus, spi_cfg, &tx, &rx)) { + return -EIO; + } + + return 0; +} + +static int iis3dhhc_spi_write(struct iis3dhhc_data *ctx, u8_t reg, + u8_t *data, u16_t len) +{ + struct spi_config *spi_cfg = &iis3dhhc_spi_conf; + u8_t buffer_tx[1] = { reg & ~IIS3DHHC_SPI_READ }; + const struct spi_buf tx_buf[2] = { + { + .buf = buffer_tx, + .len = 1, + }, + { + .buf = data, + .len = len, + } + }; + const struct spi_buf_set tx = { + .buffers = tx_buf, + .count = 2 + }; + + + if (spi_write(ctx->bus, spi_cfg, &tx)) { + return -EIO; + } + + return 0; +} + +iis3dhhc_ctx_t iis3dhhc_spi_ctx = { + .read_reg = (iis3dhhc_read_ptr) iis3dhhc_spi_read, + .write_reg = (iis3dhhc_write_ptr) iis3dhhc_spi_write, +}; + +int iis3dhhc_spi_init(struct device *dev) +{ + struct iis3dhhc_data *data = dev->driver_data; + + data->ctx = &iis3dhhc_spi_ctx; + data->ctx->handle = data; + +#if defined(DT_INST_0_ST_IIS3DHHC_CS_GPIOS_CONTROLLER) + /* handle SPI CS thru GPIO if it is the case */ + data->cs_ctrl.gpio_dev = device_get_binding( + DT_INST_0_ST_IIS3DHHC_CS_GPIOS_CONTROLLER); + if (!data->cs_ctrl.gpio_dev) { + LOG_ERR("Unable to get GPIO SPI CS device"); + return -ENODEV; + } + + data->cs_ctrl.gpio_pin = DT_INST_0_ST_IIS3DHHC_CS_GPIOS_PIN; + data->cs_ctrl.delay = 0U; + + iis3dhhc_spi_conf.cs = &data->cs_ctrl; + + LOG_DBG("SPI GPIO CS configured on %s:%u", + DT_INST_0_ST_IIS3DHHC_CS_GPIOS_CONTROLLER, + DT_INST_0_ST_IIS3DHHC_CS_GPIOS_PIN); +#endif + + return 0; +} +#endif /* DT_ST_IIS3DHHC_BUS_SPI */ diff --git a/drivers/sensor/iis3dhhc/iis3dhhc_trigger.c b/drivers/sensor/iis3dhhc/iis3dhhc_trigger.c new file mode 100644 index 00000000000..e96050592fe --- /dev/null +++ b/drivers/sensor/iis3dhhc/iis3dhhc_trigger.c @@ -0,0 +1,172 @@ +/* ST Microelectronics IIS3DHHC accelerometer sensor + * + * Copyright (c) 2019 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/iis3dhhc.pdf + */ + +#include +#include +#include +#include + +#include "iis3dhhc.h" + +#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL +LOG_MODULE_DECLARE(IIS3DHHC); + +/** + * iis3dhhc_enable_int - enable selected int pin to generate interrupt + */ +static int iis3dhhc_enable_int(struct device *dev, int enable) +{ + struct iis3dhhc_data *iis3dhhc = dev->driver_data; + + /* set interrupt */ +#ifdef CONFIG_IIS3DHHC_DRDY_INT1 + return iis3dhhc_drdy_on_int1_set(iis3dhhc->ctx, enable); +#else + return iis3dhhc_drdy_on_int2_set(iis3dhhc->ctx, enable); +#endif +} + +/** + * iis3dhhc_trigger_set - link external trigger to event data ready + */ +int iis3dhhc_trigger_set(struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + struct iis3dhhc_data *iis3dhhc = dev->driver_data; + axis3bit16_t raw; + + if (trig->chan == SENSOR_CHAN_ACCEL_XYZ) { + iis3dhhc->handler_drdy = handler; + if (handler) { + /* dummy read: re-trigger interrupt */ + iis3dhhc_acceleration_raw_get(iis3dhhc->ctx, raw.u8bit); + return iis3dhhc_enable_int(dev, PROPERTY_ENABLE); + } else { + return iis3dhhc_enable_int(dev, PROPERTY_DISABLE); + } + } + + return -ENOTSUP; +} + +/** + * iis3dhhc_handle_interrupt - handle the drdy event + * read data and call handler if registered any + */ +static void iis3dhhc_handle_interrupt(void *arg) +{ + struct device *dev = arg; + struct iis3dhhc_data *iis3dhhc = dev->driver_data; + struct sensor_trigger drdy_trigger = { + .type = SENSOR_TRIG_DATA_READY, + }; + const struct iis3dhhc_config *cfg = dev->config->config_info; + + if (iis3dhhc->handler_drdy != NULL) { + iis3dhhc->handler_drdy(dev, &drdy_trigger); + } + + gpio_pin_enable_callback(iis3dhhc->gpio, cfg->int_pin); +} + +static void iis3dhhc_gpio_callback(struct device *dev, + struct gpio_callback *cb, u32_t pins) +{ + struct iis3dhhc_data *iis3dhhc = + CONTAINER_OF(cb, struct iis3dhhc_data, gpio_cb); + const struct iis3dhhc_config *cfg = dev->config->config_info; + + ARG_UNUSED(pins); + + gpio_pin_disable_callback(dev, cfg->int_pin); + +#if defined(CONFIG_IIS3DHHC_TRIGGER_OWN_THREAD) + k_sem_give(&iis3dhhc->gpio_sem); +#elif defined(CONFIG_IIS3DHHC_TRIGGER_GLOBAL_THREAD) + k_work_submit(&iis3dhhc->work); +#endif /* CONFIG_IIS3DHHC_TRIGGER_OWN_THREAD */ +} + +#ifdef CONFIG_IIS3DHHC_TRIGGER_OWN_THREAD +static void iis3dhhc_thread(int dev_ptr, int unused) +{ + struct device *dev = INT_TO_POINTER(dev_ptr); + struct iis3dhhc_data *iis3dhhc = dev->driver_data; + + ARG_UNUSED(unused); + + while (1) { + k_sem_take(&iis3dhhc->gpio_sem, K_FOREVER); + iis3dhhc_handle_interrupt(dev); + } +} +#endif /* CONFIG_IIS3DHHC_TRIGGER_OWN_THREAD */ + +#ifdef CONFIG_IIS3DHHC_TRIGGER_GLOBAL_THREAD +static void iis3dhhc_work_cb(struct k_work *work) +{ + struct iis3dhhc_data *iis3dhhc = + CONTAINER_OF(work, struct iis3dhhc_data, work); + + iis3dhhc_handle_interrupt(iis3dhhc->dev); +} +#endif /* CONFIG_IIS3DHHC_TRIGGER_GLOBAL_THREAD */ + +int iis3dhhc_init_interrupt(struct device *dev) +{ + struct iis3dhhc_data *iis3dhhc = dev->driver_data; + const struct iis3dhhc_config *cfg = dev->config->config_info; + int ret; + + /* setup data ready gpio interrupt (INT1 or INT2) */ + iis3dhhc->gpio = device_get_binding(cfg->int_port); + if (iis3dhhc->gpio == NULL) { + LOG_DBG("Cannot get pointer to %s device", cfg->int_port); + return -EINVAL; + } + +#if defined(CONFIG_IIS3DHHC_TRIGGER_OWN_THREAD) + k_sem_init(&iis3dhhc->gpio_sem, 0, UINT_MAX); + + k_thread_create(&iis3dhhc->thread, iis3dhhc->thread_stack, + CONFIG_IIS3DHHC_THREAD_STACK_SIZE, + (k_thread_entry_t)iis3dhhc_thread, dev, + 0, NULL, K_PRIO_COOP(CONFIG_IIS3DHHC_THREAD_PRIORITY), + 0, 0); +#elif defined(CONFIG_IIS3DHHC_TRIGGER_GLOBAL_THREAD) + iis3dhhc->work.handler = iis3dhhc_work_cb; + iis3dhhc->dev = dev; +#endif /* CONFIG_IIS3DHHC_TRIGGER_OWN_THREAD */ + + ret = gpio_pin_configure(iis3dhhc->gpio, cfg->int_pin, + GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | + GPIO_INT_ACTIVE_HIGH | GPIO_INT_DEBOUNCE); + if (ret < 0) { + LOG_DBG("Could not configure gpio"); + return ret; + } + + gpio_init_callback(&iis3dhhc->gpio_cb, + iis3dhhc_gpio_callback, + BIT(cfg->int_pin)); + + if (gpio_add_callback(iis3dhhc->gpio, &iis3dhhc->gpio_cb) < 0) { + LOG_DBG("Could not set gpio callback"); + return -EIO; + } + + /* enable interrupt on int1/int2 in pulse mode */ + if (iis3dhhc_drdy_notification_mode_set(iis3dhhc->ctx, IIS3DHHC_PULSED)) { + return -EIO; + } + + return gpio_pin_enable_callback(iis3dhhc->gpio, cfg->int_pin); +} diff --git a/dts/bindings/sensor/st,iis3dhhc-spi.yaml b/dts/bindings/sensor/st,iis3dhhc-spi.yaml new file mode 100644 index 00000000000..c5f6b5c6960 --- /dev/null +++ b/dts/bindings/sensor/st,iis3dhhc-spi.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2019 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +title: STMicroelectronics MEMS sensors IIS3DHHC SPI + +description: > + This binding gives a base representation of IIS3DHHC 3-axis accelerometer + accessed through SPI bus + +compatible: "st,iis3dhhc" + +include: spi-device.yaml + +properties: + irq-gpios: + type: phandle-array + required: false + description: DRDY pin diff --git a/tests/drivers/build_all/dts_fixup.h b/tests/drivers/build_all/dts_fixup.h index 3c769fe326e..575d2279624 100644 --- a/tests/drivers/build_all/dts_fixup.h +++ b/tests/drivers/build_all/dts_fixup.h @@ -266,6 +266,18 @@ #define DT_INST_0_BOSCH_BMI160_SPI_MAX_FREQUENCY 6400000 #endif +#ifndef DT_INST_0_ST_IIS3DHHC_LABEL +#define DT_INST_0_ST_IIS3DHHC_LABEL "" +#define DT_INST_0_ST_IIS3DHHC_BASE_ADDRESS 0 +#define DT_INST_0_ST_IIS3DHHC_BUS_NAME "" +#define DT_INST_0_ST_IIS3DHHC_IRQ_GPIOS_CONTROLLER_0 "" +#define DT_INST_0_ST_IIS3DHHC_IRQ_GPIOS_PIN_0 0 +#define DT_INST_0_ST_IIS3DHHC_IRQ_GPIOS_CONTROLLER_1 "" +#define DT_INST_0_ST_IIS3DHHC_IRQ_GPIOS_PIN_1 0 +#define DT_INST_0_ST_IIS3DHHC_SPI_MAX_FREQUENCY 6400000 +#define DT_ST_IIS3DHHC_BUS_SPI 1 +#endif + #ifndef DT_INST_0_ST_LIS2DH_LABEL #define DT_INST_0_ST_LIS2DH_LABEL "" #define DT_INST_0_ST_LIS2DH_BASE_ADDRESS 0 diff --git a/tests/drivers/build_all/sensors_i_z.conf b/tests/drivers/build_all/sensors_i_z.conf index 581e74641f5..a37cbae0e05 100644 --- a/tests/drivers/build_all/sensors_i_z.conf +++ b/tests/drivers/build_all/sensors_i_z.conf @@ -6,6 +6,7 @@ CONFIG_SENSOR=y CONFIG_SPI=y CONFIG_LOG=y CONFIG_SENSOR_LOG_LEVEL_DBG=y +CONFIG_IIS3DHHC=y CONFIG_ISL29035=y CONFIG_LIS2DH=y CONFIG_LIS2DS12=y diff --git a/tests/drivers/build_all/sensors_trigger_i_z.conf b/tests/drivers/build_all/sensors_trigger_i_z.conf index 211afdcc6d5..6b62220fe3c 100644 --- a/tests/drivers/build_all/sensors_trigger_i_z.conf +++ b/tests/drivers/build_all/sensors_trigger_i_z.conf @@ -5,6 +5,8 @@ CONFIG_ADC=y CONFIG_GPIO=y CONFIG_SPI=y CONFIG_SENSOR=y +CONFIG_IIS3DHHC=y +CONFIG_IIS3DHHC_TRIGGER_OWN_THREAD=y CONFIG_ISL29035=y CONFIG_ISL29035_TRIGGER_OWN_THREAD=y CONFIG_LIS2DH=y