From 2779dd9d9bfd85ff9215c331bdada9880261a980 Mon Sep 17 00:00:00 2001 From: Weiwei Guo Date: Wed, 17 May 2023 18:11:30 +0800 Subject: [PATCH] drivers: sensor: bmm150: Add trigger support for bmm150 magnetometer sensor Add bmm150 magetometer sensor data ready trigger support. Signed-off-by: Weiwei Guo --- drivers/sensor/bmm150/CMakeLists.txt | 1 + drivers/sensor/bmm150/Kconfig | 39 ++++ drivers/sensor/bmm150/bmm150.c | 19 ++ drivers/sensor/bmm150/bmm150.h | 33 +++- drivers/sensor/bmm150/bmm150_trigger.c | 175 ++++++++++++++++++ dts/bindings/sensor/bosch,bmm150.yaml | 7 + tests/drivers/build_all/sensor/i2c.dtsi | 1 + .../sensor/sensors_trigger_global.conf | 1 + .../sensor/sensors_trigger_none.conf | 1 + .../build_all/sensor/sensors_trigger_own.conf | 1 + tests/drivers/build_all/sensor/spi.dtsi | 1 + 11 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 drivers/sensor/bmm150/bmm150_trigger.c diff --git a/drivers/sensor/bmm150/CMakeLists.txt b/drivers/sensor/bmm150/CMakeLists.txt index 7b3ad8d04cbbd6..d41b954038c68d 100644 --- a/drivers/sensor/bmm150/CMakeLists.txt +++ b/drivers/sensor/bmm150/CMakeLists.txt @@ -2,3 +2,4 @@ zephyr_library() zephyr_library_sources(bmm150.c bmm150_i2c.c bmm150_spi.c) +zephyr_library_sources_ifdef(CONFIG_BMM150_TRIGGER bmm150_trigger.c) diff --git a/drivers/sensor/bmm150/Kconfig b/drivers/sensor/bmm150/Kconfig index 54cf97456d3577..93f652eb2b37f5 100644 --- a/drivers/sensor/bmm150/Kconfig +++ b/drivers/sensor/bmm150/Kconfig @@ -33,6 +33,31 @@ config BMM150_PRESET_HIGH_ACCURACY endchoice +choice BMM150_TRIGGER_MODE + prompt "Trigger mode" + default BMM150_TRIGGER_NONE + help + Specify the type of triggering to be used by the driver. + +config BMM150_TRIGGER_NONE + bool "No trigger" + +config BMM150_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + select BMM150_TRIGGER + +config BMM150_TRIGGER_OWN_THREAD + bool "Use own thread" + select BMM150_TRIGGER + +config BMM150_TRIGGER_DIRECT + bool "Use IRQ handler" + select BMM150_TRIGGER +endchoice + +config BMM150_TRIGGER + bool + config BMM150_SAMPLING_RATE_RUNTIME bool "Dynamic sampling rate" help @@ -48,4 +73,18 @@ config BMM150_SAMPLING_REP_Z help Enable alteration of Z oversampling at runtime. +config BMM150_THREAD_PRIORITY + int "Own thread priority" + depends on BMM150_TRIGGER_OWN_THREAD + default 10 + help + Priority of the thread used by the driver to handle interrupts. + +config BMM150_THREAD_STACK_SIZE + int "Own thread stack size" + depends on BMM150_TRIGGER_OWN_THREAD + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + endif # BMM150 diff --git a/drivers/sensor/bmm150/bmm150.c b/drivers/sensor/bmm150/bmm150.c index 6c480190a67a79..62393ca02aee8c 100644 --- a/drivers/sensor/bmm150/bmm150.c +++ b/drivers/sensor/bmm150/bmm150.c @@ -495,6 +495,10 @@ static const struct sensor_driver_api bmm150_api_funcs = { #endif .sample_fetch = bmm150_sample_fetch, .channel_get = bmm150_channel_get, + +#ifdef CONFIG_BMM150_TRIGGER + .trigger_set = bmm150_trigger_set, +#endif }; static int bmm150_full_por(const struct device *dev) @@ -668,6 +672,13 @@ static int bmm150_init(const struct device *dev) return -EIO; } +#ifdef CONFIG_BMM150_TRIGGER + if (bmm150_trigger_mode_init(dev) < 0) { + LOG_ERR("Cannot set up trigger mode."); + return -EINVAL; + } +#endif + return 0; } @@ -686,6 +697,13 @@ static int bmm150_init(const struct device *dev) (BMM150_CONFIG_I2C(inst)), \ (BMM150_CONFIG_SPI(inst))) +#if defined(CONFIG_BMM150_TRIGGER) +#define BMM150_INT_CFG(inst) \ + .drdy_int = GPIO_DT_SPEC_INST_GET(inst, drdy_gpios), +#else +#define BMM150_INT_CFG(inst) +#endif + /* * Main instantiation macro, which selects the correct bus-specific * instantiation macros for the instance. @@ -694,6 +712,7 @@ static int bmm150_init(const struct device *dev) static struct bmm150_data bmm150_data_##inst; \ static const struct bmm150_config bmm150_config_##inst = { \ BMM150_BUS_CFG(inst) \ + BMM150_INT_CFG(inst) \ }; \ \ PM_DEVICE_DT_INST_DEFINE(inst, pm_action); \ diff --git a/drivers/sensor/bmm150/bmm150.h b/drivers/sensor/bmm150/bmm150.h index d00497354a48ca..47fb3f736cd667 100644 --- a/drivers/sensor/bmm150/bmm150.h +++ b/drivers/sensor/bmm150/bmm150.h @@ -157,13 +157,38 @@ struct bmm150_trim_regs { struct bmm150_config { union bmm150_bus bus; const struct bmm150_bus_io *bus_io; + +#ifdef CONFIG_BMM150_TRIGGER + struct gpio_dt_spec drdy_int; +#endif }; struct bmm150_data { - struct k_sem sem; struct bmm150_trim_regs tregs; int rep_xy, rep_z, odr, max_odr; int sample_x, sample_y, sample_z; + +#if defined(CONFIG_BMM150_TRIGGER) + struct gpio_callback gpio_cb; +#endif + +#ifdef CONFIG_BMM150_TRIGGER_OWN_THREAD + struct k_sem sem; +#endif + +#ifdef CONFIG_BMM150_TRIGGER_GLOBAL_THREAD + struct k_work work; +#endif + +#if defined(CONFIG_BMM150_TRIGGER_GLOBAL_THREAD) || \ + defined(CONFIG_BMM150_TRIGGER_DIRECT) + const struct device *dev; +#endif + +#ifdef CONFIG_BMM150_TRIGGER + const struct sensor_trigger *drdy_trigger; + sensor_trigger_handler_t drdy_handler; +#endif /* CONFIG_BMM150_TRIGGER */ }; enum bmm150_axis { @@ -198,6 +223,12 @@ enum bmm150_presets { /* Start-Up Time - from suspend to sleep (Max) */ #define BMM150_START_UP_TIME K_MSEC(3) +int bmm150_trigger_mode_init(const struct device *dev); + +int bmm150_trigger_set(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); + int bmm150_reg_update_byte(const struct device *dev, uint8_t reg, uint8_t mask, uint8_t value); diff --git a/drivers/sensor/bmm150/bmm150_trigger.c b/drivers/sensor/bmm150/bmm150_trigger.c new file mode 100644 index 00000000000000..edfd5d89b682c7 --- /dev/null +++ b/drivers/sensor/bmm150/bmm150_trigger.c @@ -0,0 +1,175 @@ +/* Bosch BMM150 pressure sensor + * + * Copyright (c) 2020 Facebook, Inc. and its affiliates + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmm150-ds001.pdf + */ + +#include +#include +#include + +#include "bmm150.h" + +LOG_MODULE_DECLARE(BMM150, CONFIG_SENSOR_LOG_LEVEL); + +static void bmm150_handle_interrupts(const void *arg) +{ + const struct device *dev = (const struct device *)arg; + struct bmm150_data *data = dev->data; + + if (data->drdy_handler) { + data->drdy_handler(dev, data->drdy_trigger); + } +} + +#ifdef CONFIG_BMM150_TRIGGER_OWN_THREAD +static K_THREAD_STACK_DEFINE(bmm150_thread_stack, + CONFIG_BMM150_THREAD_STACK_SIZE); +static struct k_thread bmm150_thread; + +static void bmm150_thread_main(void *arg1, void *unused1, void *unused2) +{ + ARG_UNUSED(unused1); + ARG_UNUSED(unused2); + const struct device *dev = (const struct device *)arg1; + struct bmm150_data *data = dev->data; + + while (1) { + k_sem_take(&data->sem, K_FOREVER); + bmm150_handle_interrupts(dev); + } +} +#endif + +#ifdef CONFIG_BMM150_TRIGGER_GLOBAL_THREAD +static void bmm150_work_handler(struct k_work *work) +{ + struct bmm150_data *data = CONTAINER_OF(work, + struct bmm150_data, + work); + + bmm150_handle_interrupts(data->dev); +} +#endif + +static void bmm150_gpio_callback(const struct device *port, + struct gpio_callback *cb, + uint32_t pin) +{ + struct bmm150_data *data = CONTAINER_OF(cb, + struct bmm150_data, + gpio_cb); + + ARG_UNUSED(port); + ARG_UNUSED(pin); + +#if defined(CONFIG_BMM150_TRIGGER_OWN_THREAD) + k_sem_give(&data->sem); +#elif defined(CONFIG_BMM150_TRIGGER_GLOBAL_THREAD) + k_work_submit(&data->work); +#elif defined(CONFIG_BMM150_TRIGGER_DIRECT) + bmm150_handle_interrupts(data->dev); +#endif +} + +int bmm150_trigger_set( + const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + uint16_t values[BMM150_AXIS_XYZR_MAX]; + struct bmm150_data *data = dev->data; + const struct bmm150_config *cfg = dev->config; + +#ifdef CONFIG_PM_DEVICE + enum pm_device_state state; + + (void)pm_device_state_get(dev, &state); + if (state != PM_DEVICE_STATE_ACTIVE) { + return -EBUSY; + } +#endif + + if (trig->type != SENSOR_TRIG_DATA_READY) { + return -ENOTSUP; + } + + data->drdy_trigger = trig; + data->drdy_handler = handler; + + if (bmm150_reg_update_byte(dev, + BMM150_REG_INT_DRDY, + BMM150_MASK_DRDY_EN, + (handler != NULL) << BMM150_SHIFT_DRDY_EN) < 0) { + LOG_ERR("Failed to enable DRDY interrupt"); + return -EIO; + } + + /* Clean data registers */ + if (cfg->bus_io->read(&cfg->bus, BMM150_REG_X_L, (uint8_t *)values, sizeof(values)) < 0) { + LOG_ERR("failed to read sample"); + return -EIO; + } + + return 0; +} + +int bmm150_trigger_mode_init(const struct device *dev) +{ + struct bmm150_data *data = dev->data; + const struct bmm150_config *cfg = dev->config; + int ret; + + if (!device_is_ready(cfg->drdy_int.port)) { + LOG_ERR("INT device is not ready"); + return -ENODEV; + } + +#if defined(CONFIG_BMM150_TRIGGER_OWN_THREAD) + k_sem_init(&data->sem, 0, 1); + k_thread_create( + &bmm150_thread, + bmm150_thread_stack, + CONFIG_BMM150_THREAD_STACK_SIZE, + bmm150_thread_main, + (void *)dev, + NULL, + NULL, + K_PRIO_COOP(CONFIG_BMM150_THREAD_PRIORITY), + 0, + K_NO_WAIT); +#elif defined(CONFIG_BMM150_TRIGGER_GLOBAL_THREAD) + k_work_init(&data->work, bmm150_work_handler); +#endif + +#if defined(CONFIG_BMM150_TRIGGER_GLOBAL_THREAD) || \ + defined(CONFIG_BMM150_TRIGGER_DIRECT) + data->dev = dev; +#endif + + ret = gpio_pin_configure_dt(&cfg->drdy_int, GPIO_INPUT); + if (ret < 0) { + return ret; + } + + gpio_init_callback(&data->gpio_cb, + bmm150_gpio_callback, + BIT(cfg->drdy_int.pin)); + + ret = gpio_add_callback(cfg->drdy_int.port, &data->gpio_cb); + if (ret < 0) { + return ret; + } + + ret = gpio_pin_interrupt_configure_dt(&cfg->drdy_int, + GPIO_INT_EDGE_TO_ACTIVE); + if (ret < 0) { + return ret; + } + + return 0; +} diff --git a/dts/bindings/sensor/bosch,bmm150.yaml b/dts/bindings/sensor/bosch,bmm150.yaml index 579999968b5d50..9b546b8117125e 100644 --- a/dts/bindings/sensor/bosch,bmm150.yaml +++ b/dts/bindings/sensor/bosch,bmm150.yaml @@ -4,3 +4,10 @@ # Common fields for BMM150 include: sensor-device.yaml + +properties: + drdy-gpios: + type: phandle-array + description: | + This property specifies the connection for data ready pin. + The polarity default is active high when sensor data is ready. diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index c0f687ee05df6d..d654b93ff15140 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -88,6 +88,7 @@ test_i2c_bmg160: bmg160@c { test_i2c_bmm150: bmm150@d { compatible = "bosch,bmm150"; reg = <0xd>; + drdy-gpios = <&test_gpio 0 0>; }; test_i2c_hmc5883l: hmc5883l@e { diff --git a/tests/drivers/build_all/sensor/sensors_trigger_global.conf b/tests/drivers/build_all/sensor/sensors_trigger_global.conf index dc8321f1a7dd4a..cf4fce093e4bb4 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_global.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_global.conf @@ -10,6 +10,7 @@ CONFIG_BMI08X_ACCEL_TRIGGER_GLOBAL_THREAD=y CONFIG_BMI08X_GYRO_TRIGGER_GLOBAL_THREAD=y CONFIG_BMI160_TRIGGER_GLOBAL_THREAD=y CONFIG_BMI270_TRIGGER_GLOBAL_THREAD=y +CONFIG_BMM150_TRIGGER_GLOBAL_THREAD=y CONFIG_BMP388_TRIGGER_GLOBAL_THREAD=y CONFIG_BQ274XX_TRIGGER_GLOBAL_THREAD=y CONFIG_CCS811_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 e53189629ba869..f89a07de1c46ab 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_none.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_none.conf @@ -10,6 +10,7 @@ CONFIG_BMI08X_ACCEL_TRIGGER_NONE=y CONFIG_BMI08X_GYRO_TRIGGER_NONE=y CONFIG_BMI160_TRIGGER_NONE=y CONFIG_BMI270_TRIGGER_NONE=y +CONFIG_BMM150_TRIGGER_NONE=y CONFIG_BMP388_TRIGGER_NONE=y CONFIG_BQ274XX_TRIGGER_NONE=y CONFIG_CCS811_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 4f7e3bbdbfadd8..3447061c16f4e3 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_own.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_own.conf @@ -9,6 +9,7 @@ CONFIG_BMI08X_ACCEL_TRIGGER_OWN_THREAD=y CONFIG_BMI08X_GYRO_TRIGGER_OWN_THREAD=y CONFIG_BMI160_TRIGGER_OWN_THREAD=y CONFIG_BMI270_TRIGGER_OWN_THREAD=y +CONFIG_BMM150_TRIGGER_OWN_THREAD=y CONFIG_BMP388_TRIGGER_OWN_THREAD=y CONFIG_BQ274XX_TRIGGER_OWN_THREAD=y CONFIG_CCS811_TRIGGER_OWN_THREAD=y diff --git a/tests/drivers/build_all/sensor/spi.dtsi b/tests/drivers/build_all/sensor/spi.dtsi index b352cd193fda08..246ecd50dd7b74 100644 --- a/tests/drivers/build_all/sensor/spi.dtsi +++ b/tests/drivers/build_all/sensor/spi.dtsi @@ -225,6 +225,7 @@ test_spi_bmm150: bmm150@1d { compatible = "bosch,bmm150"; reg = <0x1d>; spi-max-frequency = <0>; + drdy-gpios = <&test_gpio 0 0>; }; test_spi_hts221: hts221@1e {