From e13205b2565720d548fa08b774365168547d3a41 Mon Sep 17 00:00:00 2001 From: Armando Visconti Date: Wed, 12 Feb 2020 15:31:46 +0100 Subject: [PATCH] drivers/sensor: add support to IIS2DLPC accelerometer sensor The IIS2DLPC is a 3D digital accelerometer ultra-low power sensor for industrial applications, which can be interfaced through either I2C or SPI bus. https://www.st.com/resource/en/datasheet/iis2dlpc.pdf This driver is based on stmemsc i/f v1.02 Signed-off-by: Armando Visconti --- drivers/sensor/CMakeLists.txt | 1 + drivers/sensor/Kconfig | 2 + drivers/sensor/iis2dlpc/CMakeLists.txt | 12 + drivers/sensor/iis2dlpc/Kconfig | 227 ++++++++++ drivers/sensor/iis2dlpc/iis2dlpc.c | 406 ++++++++++++++++++ drivers/sensor/iis2dlpc/iis2dlpc.h | 149 +++++++ drivers/sensor/iis2dlpc/iis2dlpc_i2c.c | 51 +++ drivers/sensor/iis2dlpc/iis2dlpc_spi.c | 126 ++++++ drivers/sensor/iis2dlpc/iis2dlpc_trigger.c | 284 ++++++++++++ dts/bindings/sensor/st,iis2dlpc-i2c.yaml | 19 + dts/bindings/sensor/st,iis2dlpc-spi.yaml | 19 + tests/drivers/build_all/dts_fixup.h | 21 + tests/drivers/build_all/sensors_stmemsc.conf | 1 + .../build_all/sensors_stmemsc_trigger.conf | 2 + 14 files changed, 1320 insertions(+) create mode 100644 drivers/sensor/iis2dlpc/CMakeLists.txt create mode 100644 drivers/sensor/iis2dlpc/Kconfig create mode 100644 drivers/sensor/iis2dlpc/iis2dlpc.c create mode 100644 drivers/sensor/iis2dlpc/iis2dlpc.h create mode 100644 drivers/sensor/iis2dlpc/iis2dlpc_i2c.c create mode 100644 drivers/sensor/iis2dlpc/iis2dlpc_spi.c create mode 100644 drivers/sensor/iis2dlpc/iis2dlpc_trigger.c create mode 100644 dts/bindings/sensor/st,iis2dlpc-i2c.yaml create mode 100644 dts/bindings/sensor/st,iis2dlpc-spi.yaml diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index e25ea66e6a7..ddbdba27c6d 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -25,6 +25,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_IIS2DLPC iis2dlpc) add_subdirectory_ifdef(CONFIG_IIS3DHHC iis3dhhc) add_subdirectory_ifdef(CONFIG_ISL29035 isl29035) add_subdirectory_ifdef(CONFIG_LIS2DH lis2dh) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 41ab58d3c73..ae1b17e683e 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -79,6 +79,8 @@ source "drivers/sensor/hp206c/Kconfig" source "drivers/sensor/hts221/Kconfig" +source "drivers/sensor/iis2dlpc/Kconfig" + source "drivers/sensor/iis3dhhc/Kconfig" source "drivers/sensor/isl29035/Kconfig" diff --git a/drivers/sensor/iis2dlpc/CMakeLists.txt b/drivers/sensor/iis2dlpc/CMakeLists.txt new file mode 100644 index 00000000000..d5341abed18 --- /dev/null +++ b/drivers/sensor/iis2dlpc/CMakeLists.txt @@ -0,0 +1,12 @@ +# ST Microelectronics IIS2DLPC 3-axis accelerometer driver +# +# Copyright (c) 2020 STMicroelectronics +# +# SPDX-License-Identifier: Apache-2.0 +# +zephyr_library() + +zephyr_library_sources_ifdef(CONFIG_IIS2DLPC iis2dlpc) +zephyr_library_sources_ifdef(CONFIG_IIS2DLPC iis2dlpc_i2c.c) +zephyr_library_sources_ifdef(CONFIG_IIS2DLPC iis2dlpc_spi.c) +zephyr_library_sources_ifdef(CONFIG_IIS2DLPC_TRIGGER iis2dlpc_trigger.c) diff --git a/drivers/sensor/iis2dlpc/Kconfig b/drivers/sensor/iis2dlpc/Kconfig new file mode 100644 index 00000000000..388f5d30184 --- /dev/null +++ b/drivers/sensor/iis2dlpc/Kconfig @@ -0,0 +1,227 @@ +# ST Microelectronics IIS2DLPC 3-axis accelerometer driver + +# Copyright (c) 2020 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +menuconfig IIS2DLPC + bool "IIS2DLPC I2C/SPI accelerometer sensor driver" + depends on (I2C && HAS_DTS_I2C) || SPI + select HAS_STMEMSC + select USE_STDC_IIS2DLPC + help + Enable driver for IIS2DLPC accelerometer sensor driver + +if IIS2DLPC + +choice IIS2DLPC_TRIGGER_MODE + prompt "Trigger mode" + help + Specify the type of triggering to be used by the driver. + +config IIS2DLPC_TRIGGER_NONE + bool "No trigger" + +config IIS2DLPC_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + depends on GPIO + select IIS2DLPC_TRIGGER + +config IIS2DLPC_TRIGGER_OWN_THREAD + bool "Use own thread" + depends on GPIO + select IIS2DLPC_TRIGGER + +endchoice + +config IIS2DLPC_TRIGGER + bool + +if IIS2DLPC_TRIGGER + +config IIS2DLPC_THREAD_PRIORITY + int "Thread priority" + depends on IIS2DLPC_TRIGGER_OWN_THREAD + default 10 + help + Priority of thread used by the driver to handle interrupts. + +config IIS2DLPC_THREAD_STACK_SIZE + int "Thread stack size" + depends on IIS2DLPC_TRIGGER_OWN_THREAD + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + +choice + prompt "Sensor INT pin number" + default IIS2DLPC_INT_PIN_1 + help + The number of IIS2DLPC int pin used to generate interrupt to cpu. + Supported values are int1 or int2 + +config IIS2DLPC_INT_PIN_1 + bool "int1" + +config IIS2DLPC_INT_PIN_2 + bool "int2" +endchoice + +menuconfig IIS2DLPC_PULSE + bool "Pulse detection" + help + Enable pulse (single/double tap) detection + +if IIS2DLPC_PULSE + +choice + prompt "Pulse interrupt source" + default IIS2DLPC_ONLY_SINGLE + +config IIS2DLPC_ONLY_SINGLE + bool "single" + +config IIS2DLPC_SINGLE_DOUBLE + bool "single/double" + +endchoice + +config IIS2DLPC_PULSE_THSX + hex "Pulse X-axis threshold" + range 0 0x1F + default 0x0E + help + Threshold to start the pulse-event detection procedure on the X-axis. + Threshold values for each axis are unsigned 5-bit corresponding + to an 2g acceleration full-scale range. + +config IIS2DLPC_PULSE_THSY + hex "Pulse Y-axis threshold" + range 0 0x1F + default 0x0E + help + Threshold to start the pulse-event detection procedure on the Y-axis. + Threshold values for each axis are unsigned 5-bit corresponding + to an 2g acceleration full-scale range. + +config IIS2DLPC_PULSE_THSZ + hex "Pulse Z-axis threshold" + range 0 0x1F + default 0x0E + help + Threshold to start the pulse-event detection procedure on the Z-axis. + Threshold values for each axis are unsigned 5-bit corresponding + to an 2g acceleration full-scale range. + +config IIS2DLPC_PULSE_X + bool "Enable X axis for pulse" + default y + +config IIS2DLPC_PULSE_Y + bool "Enable Y axis for pulse" + default y + +config IIS2DLPC_PULSE_Z + bool "Enable Z axis for pulse" + default y + +config IIS2DLPC_PULSE_SHOCK + hex "Shock value" + range 0 0x03 + default 0x00 + help + Maximum duration of over-threshold event: this register represents + the maximum time of an over-threshold signal detection to be + recognized as a tap event. Where 0 equals 4*1/ODR and 1LSB = 8*1/ODR. + +config IIS2DLPC_PULSE_LTNCY + hex "Latency value" + range 0 0x0F + default 0x05 + help + When double-tap recognition is enabled, this register expresses + the maximum time between two successive detected taps to + determine a double-tap event. Where 0 equals 16*1/ODR and + 1LSB = 32*1/ODR. + +config IIS2DLPC_PULSE_QUIET + hex "Quiet value" + range 0 0x03 + default 0x00 + help + Expected quiet time after a tap detection: this register represents + the time after the first detected tap in which there must not be + any overthreshold event. Where 0 equals 2*1/ODR and 1LSB = 4*1/ODR. + +endif # IIS2DLPC_PULSE + +endif # IIS2DLPC_TRIGGER + +choice + prompt "Accelerometer Full-scale range setting" + default IIS2DLPC_ACCEL_RANGE_RUNTIME + +config IIS2DLPC_ACCEL_RANGE_RUNTIME + bool "Set at runtime (Default 2G)" + +config IIS2DLPC_ACCEL_RANGE_2G + bool "2G" + +config IIS2DLPC_ACCEL_RANGE_4G + bool "4G" + +config IIS2DLPC_ACCEL_RANGE_8G + bool "8G" + +config IIS2DLPC_ACCEL_RANGE_16G + bool "16G" +endchoice + +choice + prompt "Accelerometer sampling frequency (ODR)" + default IIS2DLPC_ODR_RUNTIME + +config IIS2DLPC_ODR_RUNTIME + bool "Set at runtime (Default 100 Hz)" + +config IIS2DLPC_ODR_1_6 + bool "1.6 Hz" + +config IIS2DLPC_ODR_12_5 + bool "12.5 Hz" + +config IIS2DLPC_ODR_25 + bool "25 Hz" + +config IIS2DLPC_ODR_50 + bool "50 Hz" + +config IIS2DLPC_ODR_100 + bool "100 Hz" + +config IIS2DLPC_ODR_200 + bool "200 Hz" + +config IIS2DLPC_ODR_400 + bool "400 Hz" + +config IIS2DLPC_ODR_800 + bool "800 Hz" + +config IIS2DLPC_ODR_1600 + bool "1600 Hz" + +endchoice + +config IIS2DLPC_POWER_MODE + int "Sensor Power Modes" + range 0 4 + default 0 + help + Specify the sensor power mode + 0: Low Power M1 + 1: Low Power M2 + 2: Low Power M3 + 3: Low Power M4 + 4: High Performance + +endif # IIS2DLPC diff --git a/drivers/sensor/iis2dlpc/iis2dlpc.c b/drivers/sensor/iis2dlpc/iis2dlpc.c new file mode 100644 index 00000000000..9a382f67c34 --- /dev/null +++ b/drivers/sensor/iis2dlpc/iis2dlpc.c @@ -0,0 +1,406 @@ +/* ST Microelectronics IIS2DLPC 3-axis accelerometer driver + * + * Copyright (c) 2020 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/iis2dlpc.pdf + */ + +#include +#include +#include +#include +#include + +#if defined(DT_ST_IIS2DLPC_BUS_SPI) +#include +#elif defined(DT_ST_IIS2DLPC_BUS_I2C) +#include +#endif + +#include "iis2dlpc.h" + +LOG_MODULE_REGISTER(IIS2DLPC, CONFIG_SENSOR_LOG_LEVEL); + +/** + * iis2dlpc_set_range - set full scale range for acc + * @dev: Pointer to instance of struct device (I2C or SPI) + * @range: Full scale range (2, 4, 8 and 16 G) + */ +static int iis2dlpc_set_range(struct device *dev, u16_t range) +{ + int err; + struct iis2dlpc_data *iis2dlpc = dev->driver_data; + const struct iis2dlpc_device_config *cfg = dev->config->config_info; + u8_t shift_gain = 0U; + u8_t fs = IIS2DLPC_FS_TO_REG(range); + + err = iis2dlpc_full_scale_set(iis2dlpc->ctx, fs); + + if (cfg->pm == IIS2DLPC_CONT_LOW_PWR_12bit) { + shift_gain = IIS2DLPC_SHFT_GAIN_NOLP1; + } + + if (!err) { + /* save internally gain for optimization */ + iis2dlpc->gain = + IIS2DLPC_FS_TO_GAIN(IIS2DLPC_FS_TO_REG(range), + shift_gain); + } + + return err; +} + +/** + * iis2dlpc_set_odr - set new sampling frequency + * @dev: Pointer to instance of struct device (I2C or SPI) + * @odr: Output data rate + */ +static int iis2dlpc_set_odr(struct device *dev, u16_t odr) +{ + struct iis2dlpc_data *iis2dlpc = dev->driver_data; + u8_t val; + + /* check if power off */ + if (odr == 0U) { + return iis2dlpc_data_rate_set(iis2dlpc->ctx, + IIS2DLPC_XL_ODR_OFF); + } + + val = IIS2DLPC_ODR_TO_REG(odr); + if (val > IIS2DLPC_XL_ODR_1k6Hz) { + LOG_ERR("ODR too high"); + return -ENOTSUP; + } + + return iis2dlpc_data_rate_set(iis2dlpc->ctx, val); +} + +static inline void iis2dlpc_convert(struct sensor_value *val, int raw_val, + float gain) +{ + s64_t dval; + + /* Gain is in ug/LSB */ + /* Convert to m/s^2 */ + dval = ((s64_t)raw_val * gain * SENSOR_G) / 1000000LL; + val->val1 = dval / 1000000LL; + val->val2 = dval % 1000000LL; +} + +static inline void iis2dlpc_channel_get_acc(struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + int i; + u8_t ofs_start, ofs_stop; + struct iis2dlpc_data *iis2dlpc = 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++) { + iis2dlpc_convert(pval++, iis2dlpc->acc[i], iis2dlpc->gain); + } +} + +static int iis2dlpc_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: + iis2dlpc_channel_get_acc(dev, chan, val); + return 0; + default: + LOG_DBG("Channel not supported"); + break; + } + + return -ENOTSUP; +} + +static int iis2dlpc_config(struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, + const struct sensor_value *val) +{ + switch (attr) { + case SENSOR_ATTR_FULL_SCALE: + return iis2dlpc_set_range(dev, sensor_ms2_to_g(val)); + case SENSOR_ATTR_SAMPLING_FREQUENCY: + return iis2dlpc_set_odr(dev, val->val1); + default: + LOG_DBG("Acc attribute not supported"); + break; + } + + return -ENOTSUP; +} + +static int iis2dlpc_attr_set(struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, + const 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: + return iis2dlpc_config(dev, chan, attr, val); + default: + LOG_DBG("Attr not supported on %d channel", chan); + break; + } + + return -ENOTSUP; +} + +static int iis2dlpc_sample_fetch(struct device *dev, enum sensor_channel chan) +{ + struct iis2dlpc_data *iis2dlpc = dev->driver_data; + const struct iis2dlpc_device_config *cfg = dev->config->config_info; + u8_t shift; + union axis3bit16_t buf; + + /* fetch raw data sample */ + if (iis2dlpc_acceleration_raw_get(iis2dlpc->ctx, buf.u8bit) < 0) { + LOG_DBG("Failed to fetch raw data sample"); + return -EIO; + } + + /* adjust to resolution */ + if (cfg->pm == IIS2DLPC_CONT_LOW_PWR_12bit) { + shift = IIS2DLPC_SHIFT_PM1; + } else { + shift = IIS2DLPC_SHIFT_PMOTHER; + } + + iis2dlpc->acc[0] = sys_le16_to_cpu(buf.i16bit[0]) >> shift; + iis2dlpc->acc[1] = sys_le16_to_cpu(buf.i16bit[1]) >> shift; + iis2dlpc->acc[2] = sys_le16_to_cpu(buf.i16bit[2]) >> shift; + + return 0; +} + +static const struct sensor_driver_api iis2dlpc_driver_api = { + .attr_set = iis2dlpc_attr_set, +#if CONFIG_IIS2DLPC_TRIGGER + .trigger_set = iis2dlpc_trigger_set, +#endif /* CONFIG_IIS2DLPC_TRIGGER */ + .sample_fetch = iis2dlpc_sample_fetch, + .channel_get = iis2dlpc_channel_get, +}; + +static int iis2dlpc_init_interface(struct device *dev) +{ + struct iis2dlpc_data *iis2dlpc = dev->driver_data; + const struct iis2dlpc_device_config *cfg = dev->config->config_info; + + iis2dlpc->bus = device_get_binding(cfg->bus_name); + if (!iis2dlpc->bus) { + LOG_DBG("master bus not found: %s", cfg->bus_name); + return -EINVAL; + } + +#if defined(DT_ST_IIS2DLPC_BUS_SPI) + iis2dlpc_spi_init(dev); +#elif defined(DT_ST_IIS2DLPC_BUS_I2C) + iis2dlpc_i2c_init(dev); +#else +#error "BUS MACRO NOT DEFINED IN DTS" +#endif + + return 0; +} + +static int iis2dlpc_set_power_mode(struct iis2dlpc_data *iis2dlpc, + iis2dlpc_mode_t pm) +{ + u8_t regval = IIS2DLPC_CONT_LOW_PWR_12bit; + + switch (pm) { + case IIS2DLPC_CONT_LOW_PWR_2: + case IIS2DLPC_CONT_LOW_PWR_3: + case IIS2DLPC_CONT_LOW_PWR_4: + case IIS2DLPC_HIGH_PERFORMANCE: + regval = pm; + break; + default: + LOG_DBG("Apply default Power Mode"); + break; + } + + return iis2dlpc_write_reg(iis2dlpc->ctx, IIS2DLPC_CTRL1, ®val, 1); +} + +static int iis2dlpc_init(struct device *dev) +{ + struct iis2dlpc_data *iis2dlpc = dev->driver_data; + const struct iis2dlpc_device_config *cfg = dev->config->config_info; + u8_t wai; + + if (iis2dlpc_init_interface(dev)) { + return -EINVAL; + } + + /* check chip ID */ + if (iis2dlpc_device_id_get(iis2dlpc->ctx, &wai) < 0) { + return -EIO; + } + + if (wai != IIS2DLPC_ID) { + LOG_ERR("Invalid chip ID"); + return -EINVAL; + } + + /* reset device */ + if (iis2dlpc_reset_set(iis2dlpc->ctx, PROPERTY_ENABLE) < 0) { + return -EIO; + } + + k_busy_wait(100); + + if (iis2dlpc_block_data_update_set(iis2dlpc->ctx, + PROPERTY_ENABLE) < 0) { + return -EIO; + } + + /* set power mode */ + if (iis2dlpc_set_power_mode(iis2dlpc, CONFIG_IIS2DLPC_POWER_MODE)) { + return -EIO; + } + + /* set default odr and full scale for acc */ + if (iis2dlpc_data_rate_set(iis2dlpc->ctx, IIS2DLPC_DEFAULT_ODR) < 0) { + return -EIO; + } + + if (iis2dlpc_full_scale_set(iis2dlpc->ctx, IIS2DLPC_ACC_FS) < 0) { + return -EIO; + } + + iis2dlpc->gain = + IIS2DLPC_FS_TO_GAIN(IIS2DLPC_ACC_FS, + cfg->pm == IIS2DLPC_CONT_LOW_PWR_12bit ? + IIS2DLPC_SHFT_GAIN_NOLP1 : 0); + +#ifdef CONFIG_IIS2DLPC_TRIGGER + if (iis2dlpc_init_interrupt(dev) < 0) { + LOG_ERR("Failed to initialize interrupts"); + return -EIO; + } + +#ifdef CONFIG_IIS2DLPC_PULSE + if (iis2dlpc_tap_mode_set(iis2dlpc->ctx, cfg->pulse_trigger) < 0) { + LOG_ERR("Failed to select pulse trigger mode"); + return -EIO; + } + + if (iis2dlpc_tap_threshold_x_set(iis2dlpc->ctx, + cfg->pulse_ths[0]) < 0) { + LOG_ERR("Failed to set tap X axis threshold"); + return -EIO; + } + + if (iis2dlpc_tap_threshold_y_set(iis2dlpc->ctx, + cfg->pulse_ths[1]) < 0) { + LOG_ERR("Failed to set tap Y axis threshold"); + return -EIO; + } + + if (iis2dlpc_tap_threshold_z_set(iis2dlpc->ctx, + cfg->pulse_ths[2]) < 0) { + LOG_ERR("Failed to set tap Z axis threshold"); + return -EIO; + } + + if (iis2dlpc_tap_detection_on_x_set(iis2dlpc->ctx, + CONFIG_IIS2DLPC_PULSE_X) < 0) { + LOG_ERR("Failed to set tap detection on X axis"); + return -EIO; + } + + if (iis2dlpc_tap_detection_on_y_set(iis2dlpc->ctx, + CONFIG_IIS2DLPC_PULSE_Y) < 0) { + LOG_ERR("Failed to set tap detection on Y axis"); + return -EIO; + } + + if (iis2dlpc_tap_detection_on_z_set(iis2dlpc->ctx, + CONFIG_IIS2DLPC_PULSE_Z) < 0) { + LOG_ERR("Failed to set tap detection on Z axis"); + return -EIO; + } + + if (iis2dlpc_tap_shock_set(iis2dlpc->ctx, cfg->pulse_shock) < 0) { + LOG_ERR("Failed to set tap shock duration"); + return -EIO; + } + + if (iis2dlpc_tap_dur_set(iis2dlpc->ctx, cfg->pulse_ltncy) < 0) { + LOG_ERR("Failed to set tap latency"); + return -EIO; + } + + if (iis2dlpc_tap_quiet_set(iis2dlpc->ctx, cfg->pulse_quiet) < 0) { + LOG_ERR("Failed to set tap quiet time"); + return -EIO; + } +#endif /* CONFIG_IIS2DLPC_PULSE */ +#endif /* CONFIG_IIS2DLPC_TRIGGER */ + + return 0; +} + +const struct iis2dlpc_device_config iis2dlpc_cfg = { + .bus_name = DT_INST_0_ST_IIS2DLPC_BUS_NAME, + .pm = CONFIG_IIS2DLPC_POWER_MODE, +#ifdef CONFIG_IIS2DLPC_TRIGGER + .int_gpio_port = DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_CONTROLLER, + .int_gpio_pin = DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_PIN, + .int_gpio_flags = DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_FLAGS, +#if defined(CONFIG_IIS2DLPC_INT_PIN_1) + .int_pin = 1, +#elif defined(CONFIG_IIS2DLPC_INT_PIN_2) + .int_pin = 2, +#endif /* CONFIG_IIS2DLPC_INT_PIN_* */ + +#ifdef CONFIG_IIS2DLPC_PULSE +#if defined(CONFIG_IIS2DLPC_ONLY_SINGLE) + .pulse_trigger = IIS2DLPC_ONLY_SINGLE, +#elif defined(CONFIG_IIS2DLPC_SINGLE_DOUBLE) + .pulse_trigger = IIS2DLPC_BOTH_SINGLE_DOUBLE, +#endif + .pulse_ths[0] = CONFIG_IIS2DLPC_PULSE_THSX, + .pulse_ths[1] = CONFIG_IIS2DLPC_PULSE_THSY, + .pulse_ths[2] = CONFIG_IIS2DLPC_PULSE_THSZ, + .pulse_shock = CONFIG_IIS2DLPC_PULSE_SHOCK, + .pulse_ltncy = CONFIG_IIS2DLPC_PULSE_LTNCY, + .pulse_quiet = CONFIG_IIS2DLPC_PULSE_QUIET, +#endif /* CONFIG_IIS2DLPC_PULSE */ +#endif /* CONFIG_IIS2DLPC_TRIGGER */ +}; + +struct iis2dlpc_data iis2dlpc_data; + +DEVICE_AND_API_INIT(iis2dlpc, DT_INST_0_ST_IIS2DLPC_LABEL, iis2dlpc_init, + &iis2dlpc_data, &iis2dlpc_cfg, POST_KERNEL, + CONFIG_SENSOR_INIT_PRIORITY, &iis2dlpc_driver_api); diff --git a/drivers/sensor/iis2dlpc/iis2dlpc.h b/drivers/sensor/iis2dlpc/iis2dlpc.h new file mode 100644 index 00000000000..459654f4f80 --- /dev/null +++ b/drivers/sensor/iis2dlpc/iis2dlpc.h @@ -0,0 +1,149 @@ +/* ST Microelectronics IIS2DLPC 3-axis accelerometer driver + * + * Copyright (c) 2020 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/iis2dlpc.pdf + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_IIS2DLPC_IIS2DLPC_H_ +#define ZEPHYR_DRIVERS_SENSOR_IIS2DLPC_IIS2DLPC_H_ + +#include +#include +#include +#include +#include "iis2dlpc_reg.h" + +union axis3bit16_t { + s16_t i16bit[3]; + u8_t u8bit[6]; +}; + +#if defined(CONFIG_IIS2DLPC_ODR_1_6) + #define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_1Hz6_LP_ONLY +#elif defined(CONFIG_IIS2DLPC_ODR_12_5) + #define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_12Hz5 +#elif defined(CONFIG_IIS2DLPC_ODR_25) + #define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_25Hz +#elif defined(CONFIG_IIS2DLPC_ODR_50) + #define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_50Hz +#elif defined(CONFIG_IIS2DLPC_ODR_100) || \ + defined(CONFIG_IIS2DLPC_ODR_RUNTIME) + #define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_100Hz +#elif defined(CONFIG_IIS2DLPC_ODR_200) + #define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_200Hz +#elif defined(CONFIG_IIS2DLPC_ODR_400) + #define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_400Hz +#elif defined(CONFIG_IIS2DLPC_ODR_800) + #define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_800Hz +#elif defined(CONFIG_IIS2DLPC_ODR_1600) + #define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_1k6Hz +#endif + +/* Return ODR reg value based on data rate set */ +#define IIS2DLPC_ODR_TO_REG(_odr) \ + ((_odr <= 1) ? IIS2DLPC_XL_ODR_1Hz6_LP_ONLY : \ + (_odr <= 12) ? IIS2DLPC_XL_ODR_12Hz5 : \ + ((31 - __builtin_clz(_odr / 25))) + 3) + +/* FS reg value from Full Scale */ +#define IIS2DLPC_FS_TO_REG(_fs) (30 - __builtin_clz(_fs)) + +#if defined(CONFIG_IIS2DLPC_ACCEL_RANGE_RUNTIME) || \ + defined(CONFIG_IIS2DLPC_ACCEL_RANGE_2G) + #define IIS2DLPC_ACC_FS IIS2DLPC_2g +#elif defined(CONFIG_IIS2DLPC_ACCEL_RANGE_4G) + #define IIS2DLPC_ACC_FS IIS2DLPC_4g +#elif defined(CONFIG_IIS2DLPC_ACCEL_RANGE_8G) + #define IIS2DLPC_ACC_FS IIS2DLPC_8g +#elif defined(CONFIG_IIS2DLPC_ACCEL_RANGE_16G) + #define IIS2DLPC_ACC_FS IIS2DLPC_16g +#endif + +/* Acc Gain value in ug/LSB in High Perf mode */ +#define IIS2DLPC_FS_2G_GAIN 244 +#define IIS2DLPC_FS_4G_GAIN 488 +#define IIS2DLPC_FS_8G_GAIN 976 +#define IIS2DLPC_FS_16G_GAIN 1952 + +#define IIS2DLPC_SHFT_GAIN_NOLP1 2 +#define IIS2DLPC_ACCEL_GAIN_DEFAULT_VAL IIS2DLPC_FS_2G_GAIN +#define IIS2DLPC_FS_TO_GAIN(_fs, _lp1) \ + (IIS2DLPC_FS_2G_GAIN << ((_fs) + (_lp1))) + +/* shift value for power mode */ +#define IIS2DLPC_SHIFT_PM1 4 +#define IIS2DLPC_SHIFT_PMOTHER 2 + +/** + * struct iis2dlpc_device_config - iis2dlpc hw configuration + * @bus_name: Pointer to bus master identifier. + * @pm: Power mode (lis2dh_powermode). + * @int_gpio_port: Pointer to GPIO PORT identifier. + * @int_gpio_pin: GPIO pin number connecter to sensor int pin. + * @int_pin: Sensor int pin (int1/int2). + */ +struct iis2dlpc_device_config { + const char *bus_name; + iis2dlpc_mode_t pm; +#ifdef CONFIG_IIS2DLPC_TRIGGER + const char *int_gpio_port; + u8_t int_gpio_pin; + u8_t int_gpio_flags; + u8_t int_pin; +#ifdef CONFIG_IIS2DLPC_PULSE + u8_t pulse_trigger; + u8_t pulse_ths[3]; + u8_t pulse_shock; + u8_t pulse_ltncy; + u8_t pulse_quiet; +#endif /* CONFIG_IIS2DLPC_PULSE */ +#endif /* CONFIG_IIS2DLPC_TRIGGER */ +}; + +/* sensor data */ +struct iis2dlpc_data { + struct device *bus; + s16_t acc[3]; + + /* save sensitivity */ + u16_t gain; + + stmdev_ctx_t *ctx; +#ifdef CONFIG_IIS2DLPC_TRIGGER + struct device *gpio; + u8_t gpio_pin; + struct gpio_callback gpio_cb; + sensor_trigger_handler_t drdy_handler; +#ifdef CONFIG_IIS2DLPC_PULSE + sensor_trigger_handler_t tap_handler; + sensor_trigger_handler_t double_tap_handler; +#endif /* CONFIG_IIS2DLPC_PULSE */ +#if defined(CONFIG_IIS2DLPC_TRIGGER_OWN_THREAD) + K_THREAD_STACK_MEMBER(thread_stack, CONFIG_IIS2DLPC_THREAD_STACK_SIZE); + struct k_thread thread; + struct k_sem gpio_sem; +#elif defined(CONFIG_IIS2DLPC_TRIGGER_GLOBAL_THREAD) + struct k_work work; + struct device *dev; +#endif /* CONFIG_IIS2DLPC_TRIGGER_GLOBAL_THREAD */ +#endif /* CONFIG_IIS2DLPC_TRIGGER */ +#if defined(DT_INST_0_ST_IIS2DLPC_CS_GPIOS_CONTROLLER) + struct spi_cs_control cs_ctrl; +#endif +}; + +int iis2dlpc_i2c_init(struct device *dev); +int iis2dlpc_spi_init(struct device *dev); + +#ifdef CONFIG_IIS2DLPC_TRIGGER +int iis2dlpc_init_interrupt(struct device *dev); +int iis2dlpc_trigger_set(struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); +#endif /* CONFIG_IIS2DLPC_TRIGGER */ + +#endif /* ZEPHYR_DRIVERS_SENSOR_IIS2DLPC_IIS2DLPC_H_ */ diff --git a/drivers/sensor/iis2dlpc/iis2dlpc_i2c.c b/drivers/sensor/iis2dlpc/iis2dlpc_i2c.c new file mode 100644 index 00000000000..8cc1ddb2c0f --- /dev/null +++ b/drivers/sensor/iis2dlpc/iis2dlpc_i2c.c @@ -0,0 +1,51 @@ +/* ST Microelectronics IIS2DLPC 3-axis accelerometer driver + * + * Copyright (c) 2020 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/iis2dlpc.pdf + */ + +#include +#include +#include + +#include "iis2dlpc.h" + +#ifdef DT_ST_IIS2DLPC_BUS_I2C + +static u16_t iis2dlpc_i2c_slave_addr = DT_INST_0_ST_IIS2DLPC_BASE_ADDRESS; + +LOG_MODULE_DECLARE(IIS2DLPC, CONFIG_SENSOR_LOG_LEVEL); + +static int iis2dlpc_i2c_read(struct iis2dlpc_data *data, u8_t reg_addr, + u8_t *value, u16_t len) +{ + return i2c_burst_read(data->bus, iis2dlpc_i2c_slave_addr, + reg_addr, value, len); +} + +static int iis2dlpc_i2c_write(struct iis2dlpc_data *data, u8_t reg_addr, + u8_t *value, u16_t len) +{ + return i2c_burst_write(data->bus, iis2dlpc_i2c_slave_addr, + reg_addr, value, len); +} + +stmdev_ctx_t iis2dlpc_i2c_ctx = { + .read_reg = (stmdev_read_ptr) iis2dlpc_i2c_read, + .write_reg = (stmdev_write_ptr) iis2dlpc_i2c_write, +}; + +int iis2dlpc_i2c_init(struct device *dev) +{ + struct iis2dlpc_data *data = dev->driver_data; + + data->ctx = &iis2dlpc_i2c_ctx; + data->ctx->handle = data; + + return 0; +} +#endif /* DT_ST_IIS2DLPC_BUS_I2C */ diff --git a/drivers/sensor/iis2dlpc/iis2dlpc_spi.c b/drivers/sensor/iis2dlpc/iis2dlpc_spi.c new file mode 100644 index 00000000000..007f4766788 --- /dev/null +++ b/drivers/sensor/iis2dlpc/iis2dlpc_spi.c @@ -0,0 +1,126 @@ +/* ST Microelectronics IIS2DLPC 3-axis accelerometer driver + * + * Copyright (c) 2020 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/iis2dlpc.pdf + */ + + +#include +#include "iis2dlpc.h" +#include + +#ifdef DT_ST_IIS2DLPC_BUS_SPI + +#define IIS2DLPC_SPI_READ (1 << 7) + +LOG_MODULE_DECLARE(IIS2DLPC, CONFIG_SENSOR_LOG_LEVEL); + +static struct spi_config iis2dlpc_spi_conf = { + .frequency = DT_INST_0_ST_IIS2DLPC_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_IIS2DLPC_BASE_ADDRESS, + .cs = NULL, +}; + +static int iis2dlpc_spi_read(struct iis2dlpc_data *ctx, u8_t reg, + u8_t *data, u16_t len) +{ + struct spi_config *spi_cfg = &iis2dlpc_spi_conf; + u8_t buffer_tx[2] = { reg | IIS2DLPC_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 iis2dlpc_spi_write(struct iis2dlpc_data *ctx, u8_t reg, + u8_t *data, u16_t len) +{ + struct spi_config *spi_cfg = &iis2dlpc_spi_conf; + u8_t buffer_tx[1] = { reg & ~IIS2DLPC_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; +} + +stmdev_ctx_t iis2dlpc_spi_ctx = { + .read_reg = (stmdev_read_ptr) iis2dlpc_spi_read, + .write_reg = (stmdev_write_ptr) iis2dlpc_spi_write, +}; + +int iis2dlpc_spi_init(struct device *dev) +{ + struct iis2dlpc_data *data = dev->driver_data; + + data->ctx = &iis2dlpc_spi_ctx; + data->ctx->handle = data; + +#if defined(DT_INST_0_ST_IIS2DLPC_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_IIS2DLPC_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_IIS2DLPC_CS_GPIOS_PIN; + data->cs_ctrl.delay = 0U; + + iis2dlpc_spi_conf.cs = &data->cs_ctrl; + + LOG_DBG("SPI GPIO CS configured on %s:%u", + DT_INST_0_ST_IIS2DLPC_CS_GPIOS_CONTROLLER, + DT_INST_0_ST_IIS2DLPC_CS_GPIOS_PIN); +#endif + + return 0; +} +#endif /* DT_ST_IIS2DLPC_BUS_SPI */ diff --git a/drivers/sensor/iis2dlpc/iis2dlpc_trigger.c b/drivers/sensor/iis2dlpc/iis2dlpc_trigger.c new file mode 100644 index 00000000000..a39ed63b647 --- /dev/null +++ b/drivers/sensor/iis2dlpc/iis2dlpc_trigger.c @@ -0,0 +1,284 @@ +/* ST Microelectronics IIS2DLPC 3-axis accelerometer driver + * + * Copyright (c) 2020 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.st.com/resource/en/datasheet/iis2dlpc.pdf + */ + +#include +#include +#include +#include + +#include "iis2dlpc.h" + +LOG_MODULE_DECLARE(IIS2DLPC, CONFIG_SENSOR_LOG_LEVEL); + +/** + * iis2dlpc_enable_int - enable selected int pin to generate interrupt + */ +static int iis2dlpc_enable_int(struct device *dev, + enum sensor_trigger_type type, int enable) +{ + const struct iis2dlpc_device_config *cfg = dev->config->config_info; + struct iis2dlpc_data *iis2dlpc = dev->driver_data; + iis2dlpc_reg_t int_route; + + if (cfg->int_pin == 1U) { + /* set interrupt for pin INT1 */ + iis2dlpc_pin_int1_route_get(iis2dlpc->ctx, + &int_route.ctrl4_int1_pad_ctrl); + + switch (type) { + case SENSOR_TRIG_DATA_READY: + int_route.ctrl4_int1_pad_ctrl.int1_drdy = enable; + break; +#ifdef CONFIG_IIS2DLPC_PULSE + case SENSOR_TRIG_TAP: + int_route.ctrl4_int1_pad_ctrl.int1_single_tap = enable; + break; + case SENSOR_TRIG_DOUBLE_TAP: + int_route.ctrl4_int1_pad_ctrl.int1_tap = enable; + break; +#endif /* CONFIG_IIS2DLPC_PULSE */ + default: + LOG_ERR("Unsupported trigger interrupt route"); + return -ENOTSUP; + } + + return iis2dlpc_pin_int1_route_set(iis2dlpc->ctx, + &int_route.ctrl4_int1_pad_ctrl); + } else { + /* set interrupt for pin INT2 */ + iis2dlpc_pin_int2_route_get(iis2dlpc->ctx, + &int_route.ctrl5_int2_pad_ctrl); + + switch (type) { + case SENSOR_TRIG_DATA_READY: + int_route.ctrl5_int2_pad_ctrl.int2_drdy = enable; + break; + default: + LOG_ERR("Unsupported trigger interrupt route"); + return -ENOTSUP; + } + + return iis2dlpc_pin_int2_route_set(iis2dlpc->ctx, + &int_route.ctrl5_int2_pad_ctrl); + } +} + +/** + * iis2dlpc_trigger_set - link external trigger to event data ready + */ +int iis2dlpc_trigger_set(struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + struct iis2dlpc_data *iis2dlpc = dev->driver_data; + union axis3bit16_t raw; + int state = (handler != NULL) ? PROPERTY_ENABLE : PROPERTY_DISABLE; + + switch (trig->type) { + case SENSOR_TRIG_DATA_READY: + iis2dlpc->drdy_handler = handler; + if (state) { + /* dummy read: re-trigger interrupt */ + iis2dlpc_acceleration_raw_get(iis2dlpc->ctx, raw.u8bit); + } + return iis2dlpc_enable_int(dev, SENSOR_TRIG_DATA_READY, state); +#ifdef CONFIG_IIS2DLPC_PULSE + case SENSOR_TRIG_TAP: + iis2dlpc->tap_handler = handler; + return iis2dlpc_enable_int(dev, SENSOR_TRIG_TAP, state); + case SENSOR_TRIG_DOUBLE_TAP: + iis2dlpc->double_tap_handler = handler; + return iis2dlpc_enable_int(dev, SENSOR_TRIG_DOUBLE_TAP, state); +#endif /* CONFIG_IIS2DLPC_PULSE */ + default: + LOG_ERR("Unsupported sensor trigger"); + return -ENOTSUP; + } +} + +static int iis2dlpc_handle_drdy_int(struct device *dev) +{ + struct iis2dlpc_data *data = dev->driver_data; + + struct sensor_trigger drdy_trig = { + .type = SENSOR_TRIG_DATA_READY, + .chan = SENSOR_CHAN_ALL, + }; + + if (data->drdy_handler) { + data->drdy_handler(dev, &drdy_trig); + } + + return 0; +} + +#ifdef CONFIG_IIS2DLPC_PULSE +static int iis2dlpc_handle_single_tap_int(struct device *dev) +{ + struct iis2dlpc_data *data = dev->driver_data; + sensor_trigger_handler_t handler = data->tap_handler; + + struct sensor_trigger pulse_trig = { + .type = SENSOR_TRIG_TAP, + .chan = SENSOR_CHAN_ALL, + }; + + if (handler) { + handler(dev, &pulse_trig); + } + + return 0; +} + +static int iis2dlpc_handle_double_tap_int(struct device *dev) +{ + struct iis2dlpc_data *data = dev->driver_data; + sensor_trigger_handler_t handler = data->double_tap_handler; + + struct sensor_trigger pulse_trig = { + .type = SENSOR_TRIG_DOUBLE_TAP, + .chan = SENSOR_CHAN_ALL, + }; + + if (handler) { + handler(dev, &pulse_trig); + } + + return 0; +} +#endif /* CONFIG_IIS2DLPC_PULSE */ + +/** + * iis2dlpc_handle_interrupt - handle the drdy event + * read data and call handler if registered any + */ +static void iis2dlpc_handle_interrupt(void *arg) +{ + struct device *dev = (struct device *)arg; + struct iis2dlpc_data *iis2dlpc = dev->driver_data; + const struct iis2dlpc_device_config *cfg = dev->config->config_info; + iis2dlpc_all_sources_t sources; + + iis2dlpc_all_sources_get(iis2dlpc->ctx, &sources); + + if (sources.status_dup.drdy) { + iis2dlpc_handle_drdy_int(dev); + } +#ifdef CONFIG_IIS2DLPC_PULSE + if (sources.status_dup.single_tap) { + iis2dlpc_handle_single_tap_int(dev); + } + if (sources.status_dup.double_tap) { + iis2dlpc_handle_double_tap_int(dev); + } +#endif /* CONFIG_IIS2DLPC_PULSE */ + + gpio_pin_interrupt_configure(iis2dlpc->gpio, cfg->int_gpio_pin, + GPIO_INT_EDGE_TO_ACTIVE); +} + +static void iis2dlpc_gpio_callback(struct device *dev, + struct gpio_callback *cb, u32_t pins) +{ + struct iis2dlpc_data *iis2dlpc = + CONTAINER_OF(cb, struct iis2dlpc_data, gpio_cb); + + if ((pins & BIT(iis2dlpc->gpio_pin)) == 0U) { + return; + } + + gpio_pin_interrupt_configure(dev, iis2dlpc->gpio_pin, + GPIO_INT_DISABLE); + +#if defined(CONFIG_IIS2DLPC_TRIGGER_OWN_THREAD) + k_sem_give(&iis2dlpc->gpio_sem); +#elif defined(CONFIG_IIS2DLPC_TRIGGER_GLOBAL_THREAD) + k_work_submit(&iis2dlpc->work); +#endif /* CONFIG_IIS2DLPC_TRIGGER_OWN_THREAD */ +} + +#ifdef CONFIG_IIS2DLPC_TRIGGER_OWN_THREAD +static void iis2dlpc_thread(int dev_ptr, int unused) +{ + struct device *dev = INT_TO_POINTER(dev_ptr); + struct iis2dlpc_data *iis2dlpc = dev->driver_data; + + ARG_UNUSED(unused); + + while (1) { + k_sem_take(&iis2dlpc->gpio_sem, K_FOREVER); + iis2dlpc_handle_interrupt(dev); + } +} +#endif /* CONFIG_IIS2DLPC_TRIGGER_OWN_THREAD */ + +#ifdef CONFIG_IIS2DLPC_TRIGGER_GLOBAL_THREAD +static void iis2dlpc_work_cb(struct k_work *work) +{ + struct iis2dlpc_data *iis2dlpc = + CONTAINER_OF(work, struct iis2dlpc_data, work); + + iis2dlpc_handle_interrupt(iis2dlpc->dev); +} +#endif /* CONFIG_IIS2DLPC_TRIGGER_GLOBAL_THREAD */ + +int iis2dlpc_init_interrupt(struct device *dev) +{ + struct iis2dlpc_data *iis2dlpc = dev->driver_data; + const struct iis2dlpc_device_config *cfg = dev->config->config_info; + int ret; + + /* setup data ready gpio interrupt (INT1 or INT2) */ + iis2dlpc->gpio = device_get_binding(cfg->int_gpio_port); + if (iis2dlpc->gpio == NULL) { + LOG_DBG("Cannot get pointer to %s device", + cfg->int_gpio_port); + return -EINVAL; + } + +#if defined(CONFIG_IIS2DLPC_TRIGGER_OWN_THREAD) + k_sem_init(&iis2dlpc->gpio_sem, 0, UINT_MAX); + + k_thread_create(&iis2dlpc->thread, iis2dlpc->thread_stack, + CONFIG_IIS2DLPC_THREAD_STACK_SIZE, + (k_thread_entry_t)iis2dlpc_thread, dev, + 0, NULL, K_PRIO_COOP(CONFIG_IIS2DLPC_THREAD_PRIORITY), + 0, K_NO_WAIT); +#elif defined(CONFIG_IIS2DLPC_TRIGGER_GLOBAL_THREAD) + iis2dlpc->work.handler = iis2dlpc_work_cb; + iis2dlpc->dev = dev; +#endif /* CONFIG_IIS2DLPC_TRIGGER_OWN_THREAD */ + + iis2dlpc->gpio_pin = cfg->int_gpio_pin; + + ret = gpio_pin_configure(iis2dlpc->gpio, cfg->int_gpio_pin, + GPIO_INPUT | cfg->int_gpio_flags); + if (ret < 0) { + LOG_DBG("Could not configure gpio"); + return ret; + } + + gpio_init_callback(&iis2dlpc->gpio_cb, + iis2dlpc_gpio_callback, + BIT(cfg->int_gpio_pin)); + + if (gpio_add_callback(iis2dlpc->gpio, &iis2dlpc->gpio_cb) < 0) { + LOG_DBG("Could not set gpio callback"); + return -EIO; + } + + /* enable interrupt on int1/int2 in pulse mode */ + if (iis2dlpc_int_notification_set(iis2dlpc->ctx, IIS2DLPC_INT_PULSED)) { + return -EIO; + } + + return gpio_pin_interrupt_configure(iis2dlpc->gpio, cfg->int_gpio_pin, + GPIO_INT_EDGE_TO_ACTIVE); +} diff --git a/dts/bindings/sensor/st,iis2dlpc-i2c.yaml b/dts/bindings/sensor/st,iis2dlpc-i2c.yaml new file mode 100644 index 00000000000..b1fb0acd138 --- /dev/null +++ b/dts/bindings/sensor/st,iis2dlpc-i2c.yaml @@ -0,0 +1,19 @@ +# Copyright (c) 2018 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STMicroelectronics IIS2DLPC accelerometer accessed through I2C bus + +compatible: "st,iis2dlpc" + +include: i2c-device.yaml + +properties: + drdy-gpios: + type: phandle-array + required: false + description: DRDY pin + + This pin defaults to active high when produced by the sensor. + The property value should ensure the flags properly describe + the signal that is presented to the driver. diff --git a/dts/bindings/sensor/st,iis2dlpc-spi.yaml b/dts/bindings/sensor/st,iis2dlpc-spi.yaml new file mode 100644 index 00000000000..24834dfb2f8 --- /dev/null +++ b/dts/bindings/sensor/st,iis2dlpc-spi.yaml @@ -0,0 +1,19 @@ +# Copyright (c) 2019 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STMicroelectronics IIS2DLPC accelerometer accessed through SPI bus + +compatible: "st,iis2dlpc" + +include: spi-device.yaml + +properties: + drdy-gpios: + type: phandle-array + required: false + description: DRDY pin + + This pin defaults to active high when produced by the sensor. + The property value should ensure the flags properly describe + the signal that is presented to the driver. diff --git a/tests/drivers/build_all/dts_fixup.h b/tests/drivers/build_all/dts_fixup.h index 59a1deab5e1..8963295d11e 100644 --- a/tests/drivers/build_all/dts_fixup.h +++ b/tests/drivers/build_all/dts_fixup.h @@ -119,6 +119,16 @@ #define DT_INST_0_ST_HTS221_DRDY_GPIOS_CONTROLLER "" #endif +#ifndef DT_INST_0_ST_IIS2DLPC_LABEL +#define DT_INST_0_ST_IIS2DLPC_LABEL "" +#define DT_INST_0_ST_IIS2DLPC_BUS_NAME "" +#define DT_INST_0_ST_IIS2DLPC_BASE_ADDRESS 0 +#define DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_FLAGS 0 +#define DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_PIN 0 +#define DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_CONTROLLER "" +#define DT_ST_IIS2DLPC_BUS_I2C 1 +#endif + #ifndef DT_INST_0_ST_LIS3MDL_MAGN_LABEL #define DT_INST_0_ST_LIS3MDL_MAGN_LABEL "" #define DT_INST_0_ST_LIS3MDL_MAGN_BUS_NAME "" @@ -485,6 +495,17 @@ #define DT_INST_0_BOSCH_BMI160_SPI_MAX_FREQUENCY 6400000 #endif +#ifndef DT_INST_0_ST_IIS2DLPC_LABEL +#define DT_INST_0_ST_IIS2DLPC_LABEL "" +#define DT_INST_0_ST_IIS2DLPC_BUS_NAME "" +#define DT_INST_0_ST_IIS2DLPC_SPI_MAX_FREQUENCY 100000 +#define DT_INST_0_ST_IIS2DLPC_BASE_ADDRESS 1 +#define DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_CONTROLLER "" +#define DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_FLAGS 0 +#define DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_PIN 0 +#define DT_ST_IIS2DLPC_BUS_SPI 1 +#endif + #ifndef DT_INST_0_ST_IIS3DHHC_LABEL #define DT_INST_0_ST_IIS3DHHC_LABEL "" #define DT_INST_0_ST_IIS3DHHC_BASE_ADDRESS 0 diff --git a/tests/drivers/build_all/sensors_stmemsc.conf b/tests/drivers/build_all/sensors_stmemsc.conf index ad8294bd5e5..cea8b6cb008 100644 --- a/tests/drivers/build_all/sensors_stmemsc.conf +++ b/tests/drivers/build_all/sensors_stmemsc.conf @@ -5,5 +5,6 @@ CONFIG_ADC=y CONFIG_GPIO=y CONFIG_SPI=y CONFIG_SENSOR=y +CONFIG_IIS2DLPC=y CONFIG_LIS2DW12=y CONFIG_STTS751=y diff --git a/tests/drivers/build_all/sensors_stmemsc_trigger.conf b/tests/drivers/build_all/sensors_stmemsc_trigger.conf index 677282358eb..99b257a3cb2 100644 --- a/tests/drivers/build_all/sensors_stmemsc_trigger.conf +++ b/tests/drivers/build_all/sensors_stmemsc_trigger.conf @@ -5,6 +5,8 @@ CONFIG_ADC=y CONFIG_GPIO=y CONFIG_SPI=y CONFIG_SENSOR=y +CONFIG_IIS2DLPC=y +CONFIG_IIS2DLPC_TRIGGER_OWN_THREAD=y CONFIG_LIS2DW12=y CONFIG_LIS2DW12_TRIGGER_OWN_THREAD=y CONFIG_STTS751=y