| /* |
| * Copyright (c) 2023 Trackunit Corporation |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include "bmi323.h" |
| #include "bmi323_spi.h" |
| |
| #include <zephyr/kernel.h> |
| #include <zephyr/device.h> |
| #include <zephyr/drivers/gpio.h> |
| #include <zephyr/drivers/sensor.h> |
| #include <zephyr/pm/device.h> |
| #include <zephyr/pm/device_runtime.h> |
| |
| #include <zephyr/logging/log.h> |
| LOG_MODULE_REGISTER(bosch_bmi323); |
| |
| #define DT_DRV_COMPAT bosch_bmi323 |
| |
| /* Value taken from BMI323 Datasheet section 5.8.1 */ |
| #define IMU_BOSCH_FEATURE_ENGINE_STARTUP_CONFIG (0x012C) |
| |
| #define IMU_BOSCH_DIE_TEMP_OFFSET_MICRO_DEG_CELCIUS (23000000LL) |
| #define IMU_BOSCH_DIE_TEMP_MICRO_DEG_CELCIUS_LSB (1953L) |
| |
| typedef void (*bosch_bmi323_gpio_callback_ptr)(const struct device *dev, struct gpio_callback *cb, |
| uint32_t pins); |
| |
| struct bosch_bmi323_config { |
| const struct bosch_bmi323_bus *bus; |
| const struct gpio_dt_spec int_gpio; |
| |
| const bosch_bmi323_gpio_callback_ptr int_gpio_callback; |
| }; |
| |
| struct bosch_bmi323_data { |
| struct k_mutex lock; |
| |
| struct sensor_value acc_samples[3]; |
| struct sensor_value gyro_samples[3]; |
| struct sensor_value temperature; |
| |
| bool acc_samples_valid; |
| bool gyro_samples_valid; |
| bool temperature_valid; |
| |
| uint32_t acc_full_scale; |
| uint32_t gyro_full_scale; |
| |
| struct gpio_callback gpio_callback; |
| const struct sensor_trigger *trigger; |
| sensor_trigger_handler_t trigger_handler; |
| struct k_work callback_work; |
| const struct device *dev; |
| }; |
| |
| static int bosch_bmi323_bus_init(const struct device *dev) |
| { |
| const struct bosch_bmi323_config *config = (const struct bosch_bmi323_config *)dev->config; |
| |
| const struct bosch_bmi323_bus *bus = config->bus; |
| |
| return bus->api->init(bus->context); |
| } |
| |
| static int bosch_bmi323_bus_read_words(const struct device *dev, uint8_t offset, uint16_t *words, |
| uint16_t words_count) |
| { |
| const struct bosch_bmi323_config *config = (const struct bosch_bmi323_config *)dev->config; |
| |
| const struct bosch_bmi323_bus *bus = config->bus; |
| |
| return bus->api->read_words(bus->context, offset, words, words_count); |
| } |
| |
| static int bosch_bmi323_bus_write_words(const struct device *dev, uint8_t offset, uint16_t *words, |
| uint16_t words_count) |
| { |
| const struct bosch_bmi323_config *config = (const struct bosch_bmi323_config *)dev->config; |
| |
| const struct bosch_bmi323_bus *bus = config->bus; |
| |
| return bus->api->write_words(bus->context, offset, words, words_count); |
| } |
| |
| static int32_t bosch_bmi323_lsb_from_fullscale(int64_t fullscale) |
| { |
| return (fullscale * 1000) / INT16_MAX; |
| } |
| |
| /* lsb is the value of one 1/1000000 LSB */ |
| static int64_t bosch_bmi323_value_to_micro(int16_t value, int32_t lsb) |
| { |
| return ((int64_t)value) * lsb; |
| } |
| |
| /* lsb is the value of one 1/1000000 LSB */ |
| static void bosch_bmi323_value_to_sensor_value(struct sensor_value *result, int16_t value, |
| int32_t lsb) |
| { |
| int64_t ll_value = (int64_t)value * lsb; |
| int32_t int_part = (int32_t)(ll_value / 1000000); |
| int32_t frac_part = (int32_t)(ll_value % 1000000); |
| |
| result->val1 = int_part; |
| result->val2 = frac_part; |
| } |
| |
| static int64_t bosch_bmi323_sensor_value_to_milli(const struct sensor_value *val) |
| { |
| return ((int64_t)val->val1 * 1000) + val->val2 / 1000; |
| } |
| |
| static void bosch_bmi323_sensor_value_from_micro(struct sensor_value *result, int64_t micro) |
| { |
| int32_t int_part = (int32_t)(micro / 1000000); |
| int32_t frac_part = (int32_t)(micro % 1000000); |
| |
| result->val1 = int_part; |
| result->val2 = frac_part; |
| } |
| |
| static bool bosch_bmi323_value_is_valid(int16_t value) |
| { |
| return ((uint16_t)value == 0x8000) ? false : true; |
| } |
| |
| static int bosch_bmi323_validate_chip_id(const struct device *dev) |
| { |
| uint16_t sensor_id; |
| int ret; |
| |
| ret = bosch_bmi323_bus_read_words(dev, 0, &sensor_id, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| if ((sensor_id & 0xFF) != 0x43) { |
| return -ENODEV; |
| } |
| |
| return 0; |
| } |
| |
| static int bosch_bmi323_soft_reset(const struct device *dev) |
| { |
| uint16_t cmd; |
| int ret; |
| |
| cmd = IMU_BOSCH_BMI323_REG_VALUE(CMD, CMD, SOFT_RESET); |
| |
| ret = bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_CMD, &cmd, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| k_usleep(1500); |
| |
| return 0; |
| } |
| |
| static int bosch_bmi323_enable_feature_engine(const struct device *dev) |
| { |
| uint16_t buf; |
| int ret; |
| |
| buf = IMU_BOSCH_FEATURE_ENGINE_STARTUP_CONFIG; |
| |
| ret = bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_FEATURE_IO2, &buf, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| buf = IMU_BOSCH_BMI323_REG_VALUE(FEATURE_IO_STATUS, STATUS, SET); |
| |
| ret = bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_FEATURE_IO_STATUS, &buf, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| buf = IMU_BOSCH_BMI323_REG_VALUE(FEATURE_CTRL, ENABLE, EN); |
| |
| return bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_FEATURE_CTRL, &buf, 1); |
| } |
| |
| static int bosch_bmi323_driver_api_set_acc_odr(const struct device *dev, |
| const struct sensor_value *val) |
| { |
| int ret; |
| uint16_t acc_conf; |
| int64_t odr = bosch_bmi323_sensor_value_to_milli(val); |
| |
| ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_ACC_CONF, &acc_conf, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| acc_conf &= ~IMU_BOSCH_BMI323_REG_MASK(ACC_CONF, ODR); |
| |
| if (odr <= 782) { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, ODR, HZ0P78125); |
| } else if (odr <= 1563) { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, ODR, HZ1P5625); |
| } else if (odr <= 3125) { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, ODR, HZ3P125); |
| } else if (odr <= 6250) { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, ODR, HZ6P25); |
| } else if (odr <= 12500) { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, ODR, HZ12P5); |
| } else if (odr <= 25000) { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, ODR, HZ25); |
| } else if (odr <= 50000) { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, ODR, HZ50); |
| } else if (odr <= 100000) { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, ODR, HZ100); |
| } else if (odr <= 200000) { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, ODR, HZ200); |
| } else if (odr <= 400000) { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, ODR, HZ400); |
| } else if (odr <= 800000) { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, ODR, HZ800); |
| } else if (odr <= 1600000) { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, ODR, HZ1600); |
| } else if (odr <= 3200000) { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, ODR, HZ3200); |
| } else { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, ODR, HZ6400); |
| } |
| |
| return bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_ACC_CONF, &acc_conf, 1); |
| } |
| |
| static int bosch_bmi323_driver_api_set_acc_full_scale(const struct device *dev, |
| const struct sensor_value *val) |
| { |
| struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data; |
| int ret; |
| uint16_t acc_conf; |
| int64_t fullscale = bosch_bmi323_sensor_value_to_milli(val); |
| |
| ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_ACC_CONF, &acc_conf, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| acc_conf &= ~IMU_BOSCH_BMI323_REG_MASK(ACC_CONF, RANGE); |
| |
| if (fullscale <= 2000) { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, RANGE, G2); |
| } else if (fullscale <= 4000) { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, RANGE, G4); |
| } else if (fullscale <= 8000) { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, RANGE, G8); |
| } else { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, RANGE, G16); |
| } |
| |
| data->acc_full_scale = 0; |
| |
| return bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_ACC_CONF, &acc_conf, 1); |
| } |
| |
| static int bosch_bmi323_driver_api_set_acc_feature_mask(const struct device *dev, |
| const struct sensor_value *val) |
| { |
| int ret; |
| uint16_t acc_conf; |
| |
| ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_ACC_CONF, &acc_conf, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| acc_conf &= ~IMU_BOSCH_BMI323_REG_MASK(ACC_CONF, MODE); |
| |
| if (val->val1) { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, MODE, HPWR); |
| } else { |
| acc_conf |= IMU_BOSCH_BMI323_REG_VALUE(ACC_CONF, MODE, DIS); |
| } |
| |
| return bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_ACC_CONF, &acc_conf, 1); |
| } |
| |
| static int bosch_bmi323_driver_api_set_gyro_odr(const struct device *dev, |
| const struct sensor_value *val) |
| { |
| int ret; |
| uint16_t gyro_conf; |
| int64_t odr = bosch_bmi323_sensor_value_to_milli(val); |
| |
| ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_GYRO_CONF, &gyro_conf, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| gyro_conf &= ~IMU_BOSCH_BMI323_REG_MASK(GYRO_CONF, ODR); |
| |
| if (odr <= 782) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, ODR, HZ0P78125); |
| } else if (odr <= 1563) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, ODR, HZ1P5625); |
| } else if (odr <= 3125) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, ODR, HZ3P125); |
| } else if (odr <= 6250) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, ODR, HZ6P25); |
| } else if (odr <= 12500) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, ODR, HZ12P5); |
| } else if (odr <= 25000) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, ODR, HZ25); |
| } else if (odr <= 50000) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, ODR, HZ50); |
| } else if (odr <= 100000) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, ODR, HZ100); |
| } else if (odr <= 200000) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, ODR, HZ200); |
| } else if (odr <= 400000) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, ODR, HZ400); |
| } else if (odr <= 800000) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, ODR, HZ800); |
| } else if (odr <= 1600000) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, ODR, HZ1600); |
| } else if (odr <= 3200000) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, ODR, HZ3200); |
| } else { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, ODR, HZ6400); |
| } |
| |
| return bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_GYRO_CONF, &gyro_conf, 1); |
| } |
| |
| static int bosch_bmi323_driver_api_set_gyro_full_scale(const struct device *dev, |
| const struct sensor_value *val) |
| { |
| struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data; |
| int ret; |
| uint16_t gyro_conf; |
| int32_t fullscale = bosch_bmi323_sensor_value_to_milli(val); |
| |
| ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_GYRO_CONF, &gyro_conf, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| gyro_conf &= ~IMU_BOSCH_BMI323_REG_MASK(GYRO_CONF, RANGE); |
| |
| if (fullscale <= 125000) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, RANGE, DPS125); |
| } else if (fullscale <= 250000) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, RANGE, DPS250); |
| } else if (fullscale <= 500000) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, RANGE, DPS500); |
| } else if (fullscale <= 1000000) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, RANGE, DPS1000); |
| } else { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, RANGE, DPS2000); |
| } |
| |
| data->gyro_full_scale = 0; |
| |
| return bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_GYRO_CONF, &gyro_conf, 1); |
| } |
| |
| static int bosch_bmi323_driver_api_set_gyro_feature_mask(const struct device *dev, |
| const struct sensor_value *val) |
| { |
| int ret; |
| uint16_t gyro_conf; |
| |
| ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_GYRO_CONF, &gyro_conf, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| gyro_conf &= ~IMU_BOSCH_BMI323_REG_MASK(GYRO_CONF, MODE); |
| |
| if (val->val1) { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, MODE, HPWR); |
| } else { |
| gyro_conf |= IMU_BOSCH_BMI323_REG_VALUE(GYRO_CONF, MODE, DIS); |
| } |
| |
| return bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_GYRO_CONF, &gyro_conf, 1); |
| } |
| |
| static int bosch_bmi323_driver_api_attr_set(const struct device *dev, enum sensor_channel chan, |
| enum sensor_attribute attr, |
| const struct sensor_value *val) |
| { |
| struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data; |
| int ret; |
| |
| k_mutex_lock(&data->lock, K_FOREVER); |
| |
| switch (chan) { |
| case SENSOR_CHAN_ACCEL_XYZ: |
| switch (attr) { |
| case SENSOR_ATTR_SAMPLING_FREQUENCY: |
| ret = bosch_bmi323_driver_api_set_acc_odr(dev, val); |
| |
| break; |
| |
| case SENSOR_ATTR_FULL_SCALE: |
| ret = bosch_bmi323_driver_api_set_acc_full_scale(dev, val); |
| |
| break; |
| |
| case SENSOR_ATTR_FEATURE_MASK: |
| ret = bosch_bmi323_driver_api_set_acc_feature_mask(dev, val); |
| |
| break; |
| |
| default: |
| ret = -ENODEV; |
| |
| break; |
| } |
| |
| break; |
| |
| case SENSOR_CHAN_GYRO_XYZ: |
| switch (attr) { |
| case SENSOR_ATTR_SAMPLING_FREQUENCY: |
| ret = bosch_bmi323_driver_api_set_gyro_odr(dev, val); |
| |
| break; |
| |
| case SENSOR_ATTR_FULL_SCALE: |
| ret = bosch_bmi323_driver_api_set_gyro_full_scale(dev, val); |
| |
| break; |
| |
| case SENSOR_ATTR_FEATURE_MASK: |
| ret = bosch_bmi323_driver_api_set_gyro_feature_mask(dev, val); |
| |
| break; |
| |
| default: |
| ret = -ENODEV; |
| |
| break; |
| } |
| |
| break; |
| |
| default: |
| ret = -ENODEV; |
| |
| break; |
| } |
| |
| k_mutex_unlock(&data->lock); |
| |
| return ret; |
| } |
| |
| static int bosch_bmi323_driver_api_get_acc_odr(const struct device *dev, struct sensor_value *val) |
| { |
| uint16_t acc_conf; |
| int ret; |
| |
| ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_ACC_CONF, &acc_conf, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| switch (IMU_BOSCH_BMI323_REG_VALUE_GET_FIELD(acc_conf, ACC_CONF, ODR)) { |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_ODR_VAL_HZ0P78125: |
| val->val1 = 0; |
| val->val2 = 781250; |
| break; |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_ODR_VAL_HZ1P5625: |
| val->val1 = 1; |
| val->val2 = 562500; |
| break; |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_ODR_VAL_HZ3P125: |
| val->val1 = 3; |
| val->val2 = 125000; |
| break; |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_ODR_VAL_HZ6P25: |
| val->val1 = 6; |
| val->val2 = 250000; |
| break; |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_ODR_VAL_HZ12P5: |
| val->val1 = 12; |
| val->val2 = 500000; |
| break; |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_ODR_VAL_HZ25: |
| val->val1 = 25; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_ODR_VAL_HZ50: |
| val->val1 = 50; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_ODR_VAL_HZ100: |
| val->val1 = 100; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_ODR_VAL_HZ200: |
| val->val1 = 200; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_ODR_VAL_HZ400: |
| val->val1 = 400; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_ODR_VAL_HZ800: |
| val->val1 = 800; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_ODR_VAL_HZ1600: |
| val->val1 = 1600; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_ODR_VAL_HZ3200: |
| val->val1 = 3200; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_ODR_VAL_HZ6400: |
| val->val1 = 6400; |
| val->val2 = 0; |
| break; |
| default: |
| return -EINVAL; |
| } |
| |
| return 0; |
| } |
| |
| static int bosch_bmi323_driver_api_get_acc_full_scale(const struct device *dev, |
| struct sensor_value *val) |
| { |
| uint16_t acc_conf; |
| int ret; |
| |
| ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_ACC_CONF, &acc_conf, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| switch (IMU_BOSCH_BMI323_REG_VALUE_GET_FIELD(acc_conf, ACC_CONF, RANGE)) { |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_RANGE_VAL_G2: |
| val->val1 = 2; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_RANGE_VAL_G4: |
| val->val1 = 4; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_RANGE_VAL_G8: |
| val->val1 = 8; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_ACC_CONF_RANGE_VAL_G16: |
| val->val1 = 16; |
| val->val2 = 0; |
| break; |
| default: |
| return -EINVAL; |
| } |
| |
| return 0; |
| } |
| |
| static int bosch_bmi323_driver_api_get_acc_feature_mask(const struct device *dev, |
| struct sensor_value *val) |
| { |
| uint16_t acc_conf; |
| int ret; |
| |
| ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_ACC_CONF, &acc_conf, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| if (IMU_BOSCH_BMI323_REG_VALUE_GET_FIELD(acc_conf, ACC_CONF, MODE)) { |
| val->val1 = 1; |
| val->val2 = 0; |
| } else { |
| val->val1 = 0; |
| val->val2 = 0; |
| } |
| |
| return 0; |
| } |
| |
| static int bosch_bmi323_driver_api_get_gyro_odr(const struct device *dev, struct sensor_value *val) |
| { |
| uint16_t gyro_conf; |
| int ret; |
| |
| ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_GYRO_CONF, &gyro_conf, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| switch (IMU_BOSCH_BMI323_REG_VALUE_GET_FIELD(gyro_conf, GYRO_CONF, ODR)) { |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_ODR_VAL_HZ0P78125: |
| val->val1 = 0; |
| val->val2 = 781250; |
| break; |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_ODR_VAL_HZ1P5625: |
| val->val1 = 1; |
| val->val2 = 562500; |
| break; |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_ODR_VAL_HZ3P125: |
| val->val1 = 3; |
| val->val2 = 125000; |
| break; |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_ODR_VAL_HZ6P25: |
| val->val1 = 6; |
| val->val2 = 250000; |
| break; |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_ODR_VAL_HZ12P5: |
| val->val1 = 12; |
| val->val2 = 500000; |
| break; |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_ODR_VAL_HZ25: |
| val->val1 = 25; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_ODR_VAL_HZ50: |
| val->val1 = 50; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_ODR_VAL_HZ100: |
| val->val1 = 100; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_ODR_VAL_HZ200: |
| val->val1 = 200; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_ODR_VAL_HZ400: |
| val->val1 = 400; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_ODR_VAL_HZ800: |
| val->val1 = 800; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_ODR_VAL_HZ1600: |
| val->val1 = 1600; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_ODR_VAL_HZ3200: |
| val->val1 = 3200; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_ODR_VAL_HZ6400: |
| val->val1 = 6400; |
| val->val2 = 0; |
| break; |
| default: |
| return -EINVAL; |
| } |
| |
| return 0; |
| } |
| |
| static int bosch_bmi323_driver_api_get_gyro_full_scale(const struct device *dev, |
| struct sensor_value *val) |
| { |
| uint16_t gyro_conf; |
| int ret; |
| |
| ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_GYRO_CONF, &gyro_conf, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| switch (IMU_BOSCH_BMI323_REG_VALUE_GET_FIELD(gyro_conf, GYRO_CONF, RANGE)) { |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_RANGE_VAL_DPS125: |
| val->val1 = 125; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_RANGE_VAL_DPS250: |
| val->val1 = 250; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_RANGE_VAL_DPS500: |
| val->val1 = 500; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_RANGE_VAL_DPS1000: |
| val->val1 = 1000; |
| val->val2 = 0; |
| break; |
| case IMU_BOSCH_BMI323_REG_GYRO_CONF_RANGE_VAL_DPS2000: |
| val->val1 = 2000; |
| val->val2 = 0; |
| break; |
| default: |
| return -EINVAL; |
| } |
| |
| return 0; |
| } |
| |
| static int bosch_bmi323_driver_api_get_gyro_feature_mask(const struct device *dev, |
| struct sensor_value *val) |
| { |
| uint16_t gyro_conf; |
| int ret; |
| |
| ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_GYRO_CONF, &gyro_conf, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| if (IMU_BOSCH_BMI323_REG_VALUE_GET_FIELD(gyro_conf, GYRO_CONF, MODE)) { |
| val->val1 = 1; |
| val->val2 = 0; |
| } else { |
| val->val1 = 0; |
| val->val2 = 0; |
| } |
| |
| return 0; |
| } |
| |
| static int bosch_bmi323_driver_api_attr_get(const struct device *dev, enum sensor_channel chan, |
| enum sensor_attribute attr, struct sensor_value *val) |
| { |
| struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data; |
| int ret; |
| |
| k_mutex_lock(&data->lock, K_FOREVER); |
| |
| switch (chan) { |
| case SENSOR_CHAN_ACCEL_XYZ: |
| switch (attr) { |
| case SENSOR_ATTR_SAMPLING_FREQUENCY: |
| ret = bosch_bmi323_driver_api_get_acc_odr(dev, val); |
| |
| break; |
| |
| case SENSOR_ATTR_FULL_SCALE: |
| ret = bosch_bmi323_driver_api_get_acc_full_scale(dev, val); |
| |
| break; |
| |
| case SENSOR_ATTR_FEATURE_MASK: |
| ret = bosch_bmi323_driver_api_get_acc_feature_mask(dev, val); |
| |
| break; |
| |
| default: |
| ret = -ENODEV; |
| |
| break; |
| } |
| |
| break; |
| |
| case SENSOR_CHAN_GYRO_XYZ: |
| switch (attr) { |
| case SENSOR_ATTR_SAMPLING_FREQUENCY: |
| ret = bosch_bmi323_driver_api_get_gyro_odr(dev, val); |
| |
| break; |
| |
| case SENSOR_ATTR_FULL_SCALE: |
| ret = bosch_bmi323_driver_api_get_gyro_full_scale(dev, val); |
| |
| break; |
| |
| case SENSOR_ATTR_FEATURE_MASK: |
| ret = bosch_bmi323_driver_api_get_gyro_feature_mask(dev, val); |
| |
| break; |
| |
| default: |
| ret = -ENODEV; |
| |
| break; |
| } |
| |
| break; |
| |
| default: |
| ret = -ENODEV; |
| break; |
| } |
| |
| k_mutex_unlock(&data->lock); |
| |
| return ret; |
| } |
| |
| static int bosch_bmi323_driver_api_trigger_set_acc_drdy(const struct device *dev) |
| { |
| uint16_t buf[2]; |
| |
| buf[0] = 0; |
| buf[1] = IMU_BOSCH_BMI323_REG_VALUE(INT_MAP2, ACC_DRDY_INT, INT1); |
| |
| return bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_INT_MAP1, buf, 2); |
| } |
| |
| static int bosch_bmi323_driver_api_trigger_set_acc_motion(const struct device *dev) |
| { |
| uint16_t buf[2]; |
| int ret; |
| |
| buf[0] = IMU_BOSCH_BMI323_REG_VALUE(INT_MAP1, MOTION_OUT, INT1); |
| buf[1] = 0; |
| |
| ret = bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_INT_MAP1, buf, 2); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| buf[0] = 0; |
| |
| ret = bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_FEATURE_IO0, buf, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| buf[0] = IMU_BOSCH_BMI323_REG_VALUE(FEATURE_IO0, MOTION_X_EN, EN) | |
| IMU_BOSCH_BMI323_REG_VALUE(FEATURE_IO0, MOTION_Y_EN, EN) | |
| IMU_BOSCH_BMI323_REG_VALUE(FEATURE_IO0, MOTION_Z_EN, EN); |
| |
| ret = bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_FEATURE_IO0, buf, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| buf[0] = 1; |
| |
| return bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_FEATURE_IO_STATUS, buf, 1); |
| } |
| |
| static int bosch_bmi323_driver_api_trigger_set(const struct device *dev, |
| const struct sensor_trigger *trig, |
| sensor_trigger_handler_t handler) |
| { |
| struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data; |
| int ret = -ENODEV; |
| |
| k_mutex_lock(&data->lock, K_FOREVER); |
| |
| data->trigger = trig; |
| data->trigger_handler = handler; |
| |
| switch (trig->chan) { |
| case SENSOR_CHAN_ACCEL_XYZ: |
| switch (trig->type) { |
| case SENSOR_TRIG_DATA_READY: |
| ret = bosch_bmi323_driver_api_trigger_set_acc_drdy(dev); |
| |
| break; |
| |
| case SENSOR_TRIG_MOTION: |
| ret = bosch_bmi323_driver_api_trigger_set_acc_motion(dev); |
| |
| break; |
| |
| default: |
| break; |
| } |
| |
| break; |
| |
| default: |
| break; |
| } |
| |
| k_mutex_unlock(&data->lock); |
| |
| return ret; |
| } |
| |
| static int bosch_bmi323_driver_api_fetch_acc_samples(const struct device *dev) |
| { |
| struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data; |
| struct sensor_value full_scale; |
| int16_t *buf = (int16_t *)data->acc_samples; |
| int ret; |
| int32_t lsb; |
| |
| if (data->acc_full_scale == 0) { |
| ret = bosch_bmi323_driver_api_get_acc_full_scale(dev, &full_scale); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| data->acc_full_scale = bosch_bmi323_sensor_value_to_milli(&full_scale); |
| } |
| |
| ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_ACC_DATA_X, (uint16_t *)buf, 3); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| if ((bosch_bmi323_value_is_valid(buf[0]) == false) || |
| (bosch_bmi323_value_is_valid(buf[1]) == false) || |
| (bosch_bmi323_value_is_valid(buf[2]) == false)) { |
| return -ENODATA; |
| } |
| |
| lsb = bosch_bmi323_lsb_from_fullscale(data->acc_full_scale); |
| |
| /* Reuse vector backwards to avoid overwriting the raw values */ |
| bosch_bmi323_value_to_sensor_value(&data->acc_samples[2], buf[2], lsb); |
| bosch_bmi323_value_to_sensor_value(&data->acc_samples[1], buf[1], lsb); |
| bosch_bmi323_value_to_sensor_value(&data->acc_samples[0], buf[0], lsb); |
| |
| data->acc_samples_valid = true; |
| |
| return 0; |
| } |
| |
| static int bosch_bmi323_driver_api_fetch_gyro_samples(const struct device *dev) |
| { |
| struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data; |
| struct sensor_value full_scale; |
| int16_t *buf = (int16_t *)data->gyro_samples; |
| int ret; |
| int32_t lsb; |
| |
| if (data->gyro_full_scale == 0) { |
| ret = bosch_bmi323_driver_api_get_gyro_full_scale(dev, &full_scale); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| data->gyro_full_scale = bosch_bmi323_sensor_value_to_milli(&full_scale); |
| } |
| |
| ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_GYRO_DATA_X, (uint16_t *)buf, |
| 3); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| if ((bosch_bmi323_value_is_valid(buf[0]) == false) || |
| (bosch_bmi323_value_is_valid(buf[1]) == false) || |
| (bosch_bmi323_value_is_valid(buf[2]) == false)) { |
| return -ENODATA; |
| } |
| |
| lsb = bosch_bmi323_lsb_from_fullscale(data->gyro_full_scale); |
| |
| /* Reuse vector backwards to avoid overwriting the raw values */ |
| bosch_bmi323_value_to_sensor_value(&data->gyro_samples[2], buf[2], lsb); |
| bosch_bmi323_value_to_sensor_value(&data->gyro_samples[1], buf[1], lsb); |
| bosch_bmi323_value_to_sensor_value(&data->gyro_samples[0], buf[0], lsb); |
| |
| data->gyro_samples_valid = true; |
| |
| return 0; |
| } |
| |
| static int bosch_bmi323_driver_api_fetch_temperature(const struct device *dev) |
| { |
| struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data; |
| int16_t buf; |
| int64_t micro; |
| int ret; |
| |
| ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_TEMP_DATA, &buf, 1); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| if (bosch_bmi323_value_is_valid(buf) == false) { |
| return -ENODATA; |
| } |
| |
| micro = bosch_bmi323_value_to_micro(buf, IMU_BOSCH_DIE_TEMP_MICRO_DEG_CELCIUS_LSB); |
| |
| micro += IMU_BOSCH_DIE_TEMP_OFFSET_MICRO_DEG_CELCIUS; |
| |
| bosch_bmi323_sensor_value_from_micro(&data->temperature, micro); |
| |
| data->temperature_valid = true; |
| |
| return 0; |
| } |
| |
| static int bosch_bmi323_driver_api_sample_fetch(const struct device *dev, enum sensor_channel chan) |
| { |
| struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data; |
| int ret; |
| |
| k_mutex_lock(&data->lock, K_FOREVER); |
| |
| switch (chan) { |
| case SENSOR_CHAN_ACCEL_XYZ: |
| ret = bosch_bmi323_driver_api_fetch_acc_samples(dev); |
| |
| break; |
| |
| case SENSOR_CHAN_GYRO_XYZ: |
| ret = bosch_bmi323_driver_api_fetch_gyro_samples(dev); |
| |
| break; |
| |
| case SENSOR_CHAN_DIE_TEMP: |
| ret = bosch_bmi323_driver_api_fetch_temperature(dev); |
| |
| break; |
| |
| case SENSOR_CHAN_ALL: |
| ret = bosch_bmi323_driver_api_fetch_acc_samples(dev); |
| |
| if (ret < 0) { |
| break; |
| } |
| |
| ret = bosch_bmi323_driver_api_fetch_gyro_samples(dev); |
| |
| if (ret < 0) { |
| break; |
| } |
| |
| ret = bosch_bmi323_driver_api_fetch_temperature(dev); |
| |
| break; |
| |
| default: |
| ret = -ENODEV; |
| |
| break; |
| } |
| |
| k_mutex_unlock(&data->lock); |
| |
| return ret; |
| } |
| |
| static int bosch_bmi323_driver_api_channel_get(const struct device *dev, enum sensor_channel chan, |
| struct sensor_value *val) |
| { |
| struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data; |
| int ret = 0; |
| |
| k_mutex_lock(&data->lock, K_FOREVER); |
| |
| switch (chan) { |
| case SENSOR_CHAN_ACCEL_XYZ: |
| if (data->acc_samples_valid == false) { |
| ret = -ENODATA; |
| |
| break; |
| } |
| |
| memcpy(val, data->acc_samples, sizeof(data->acc_samples)); |
| |
| break; |
| |
| case SENSOR_CHAN_GYRO_XYZ: |
| if (data->gyro_samples_valid == false) { |
| ret = -ENODATA; |
| |
| break; |
| } |
| |
| memcpy(val, data->gyro_samples, sizeof(data->gyro_samples)); |
| |
| break; |
| |
| case SENSOR_CHAN_DIE_TEMP: |
| if (data->temperature_valid == false) { |
| ret = -ENODATA; |
| |
| break; |
| } |
| |
| (*val) = data->temperature; |
| |
| break; |
| |
| default: |
| ret = -ENODEV; |
| |
| break; |
| } |
| |
| k_mutex_unlock(&data->lock); |
| |
| return ret; |
| } |
| |
| static const struct sensor_driver_api bosch_bmi323_api = { |
| .attr_set = bosch_bmi323_driver_api_attr_set, |
| .attr_get = bosch_bmi323_driver_api_attr_get, |
| .trigger_set = bosch_bmi323_driver_api_trigger_set, |
| .sample_fetch = bosch_bmi323_driver_api_sample_fetch, |
| .channel_get = bosch_bmi323_driver_api_channel_get, |
| }; |
| |
| static void bosch_bmi323_irq_callback(const struct device *dev) |
| { |
| struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data; |
| |
| k_work_submit(&data->callback_work); |
| } |
| |
| static int bosch_bmi323_init_irq(const struct device *dev) |
| { |
| struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data; |
| struct bosch_bmi323_config *config = (struct bosch_bmi323_config *)dev->config; |
| int ret; |
| |
| ret = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| gpio_init_callback(&data->gpio_callback, config->int_gpio_callback, |
| BIT(config->int_gpio.pin)); |
| |
| ret = gpio_add_callback(config->int_gpio.port, &data->gpio_callback); |
| |
| if (ret < 0) { |
| return ret; |
| } |
| |
| return gpio_pin_interrupt_configure_dt(&config->int_gpio, GPIO_INT_EDGE_TO_ACTIVE); |
| } |
| |
| static int bosch_bmi323_init_int1(const struct device *dev) |
| { |
| uint16_t buf; |
| |
| buf = IMU_BOSCH_BMI323_REG_VALUE(IO_INT_CTRL, INT1_LVL, ACT_HIGH) | |
| IMU_BOSCH_BMI323_REG_VALUE(IO_INT_CTRL, INT1_OD, PUSH_PULL) | |
| IMU_BOSCH_BMI323_REG_VALUE(IO_INT_CTRL, INT1_OUTPUT_EN, EN); |
| |
| return bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_IO_INT_CTRL, &buf, 1); |
| } |
| |
| static void bosch_bmi323_irq_callback_handler(struct k_work *item) |
| { |
| struct bosch_bmi323_data *data = |
| CONTAINER_OF(item, struct bosch_bmi323_data, callback_work); |
| |
| k_mutex_lock(&data->lock, K_FOREVER); |
| |
| if (data->trigger_handler != NULL) { |
| data->trigger_handler(data->dev, data->trigger); |
| } |
| |
| k_mutex_unlock(&data->lock); |
| } |
| |
| static int bosch_bmi323_pm_resume(const struct device *dev) |
| { |
| int ret; |
| |
| ret = bosch_bmi323_bus_init(dev); |
| |
| if (ret < 0) { |
| LOG_WRN("Failed to init bus"); |
| |
| return ret; |
| } |
| |
| ret = bosch_bmi323_validate_chip_id(dev); |
| |
| if (ret < 0) { |
| LOG_WRN("Failed to validate chip id"); |
| |
| return ret; |
| } |
| |
| ret = bosch_bmi323_soft_reset(dev); |
| |
| if (ret < 0) { |
| LOG_WRN("Failed to soft reset chip"); |
| |
| return ret; |
| } |
| |
| ret = bosch_bmi323_bus_init(dev); |
| |
| if (ret < 0) { |
| LOG_WRN("Failed to re-init bus"); |
| |
| return ret; |
| } |
| |
| ret = bosch_bmi323_enable_feature_engine(dev); |
| |
| if (ret < 0) { |
| LOG_WRN("Failed to enable feature engine"); |
| |
| return ret; |
| } |
| |
| ret = bosch_bmi323_init_int1(dev); |
| |
| if (ret < 0) { |
| LOG_WRN("Failed to enable INT1"); |
| } |
| |
| return ret; |
| } |
| |
| #ifdef CONFIG_PM_DEVICE |
| static int bosch_bmi323_pm_suspend(const struct device *dev) |
| { |
| /* Soft reset device to put it into suspend */ |
| return bosch_bmi323_soft_reset(dev); |
| } |
| #endif /* CONFIG_PM_DEVICE */ |
| |
| #ifdef CONFIG_PM_DEVICE |
| static int bosch_bmi323_pm_action(const struct device *dev, enum pm_device_action action) |
| { |
| struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data; |
| int ret; |
| |
| k_mutex_lock(&data->lock, K_FOREVER); |
| |
| switch (action) { |
| case PM_DEVICE_ACTION_RESUME: |
| ret = bosch_bmi323_pm_resume(dev); |
| |
| break; |
| |
| case PM_DEVICE_ACTION_SUSPEND: |
| ret = bosch_bmi323_pm_suspend(dev); |
| |
| break; |
| |
| default: |
| ret = -ENOTSUP; |
| |
| break; |
| } |
| |
| k_mutex_unlock(&data->lock); |
| |
| return ret; |
| } |
| #endif /* CONFIG_PM_DEVICE */ |
| |
| static int bosch_bmi323_init(const struct device *dev) |
| { |
| struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data; |
| int ret; |
| |
| k_mutex_init(&data->lock); |
| |
| k_work_init(&data->callback_work, bosch_bmi323_irq_callback_handler); |
| |
| data->dev = dev; |
| |
| ret = bosch_bmi323_init_irq(dev); |
| |
| if (ret < 0) { |
| LOG_WRN("Failed to init irq"); |
| |
| return ret; |
| } |
| |
| #ifndef CONFIG_PM_DEVICE_RUNTIME |
| ret = bosch_bmi323_pm_resume(dev); |
| |
| if (ret < 0) { |
| LOG_WRN("Failed to initialize device"); |
| } |
| #else |
| pm_device_init_suspended(dev); |
| |
| ret = pm_device_runtime_enable(dev); |
| |
| if (ret < 0) { |
| LOG_WRN("Failed to enable device pm runtime"); |
| } |
| #endif /* CONFIG_PM_DEVICE_RUNTIME */ |
| |
| return ret; |
| } |
| |
| /* |
| * Currently only support for the SPI bus is implemented. This shall be updated to |
| * select the appropriate bus once I2C is implemented. |
| */ |
| #define BMI323_DEVICE_BUS(inst) \ |
| BUILD_ASSERT(DT_INST_ON_BUS(inst, spi), "Unimplemented bus"); \ |
| BMI323_DEVICE_SPI_BUS(inst) |
| |
| #define BMI323_DEVICE(inst) \ |
| static struct bosch_bmi323_data bosch_bmi323_data_##inst; \ |
| \ |
| BMI323_DEVICE_BUS(inst); \ |
| \ |
| static void bosch_bmi323_irq_callback##inst(const struct device *dev, \ |
| struct gpio_callback *cb, uint32_t pins) \ |
| { \ |
| bosch_bmi323_irq_callback(DEVICE_DT_INST_GET(inst)); \ |
| } \ |
| \ |
| static const struct bosch_bmi323_config bosch_bmi323_config_##inst = { \ |
| .bus = &bosch_bmi323_bus_api##inst, \ |
| .int_gpio = GPIO_DT_SPEC_INST_GET(inst, int_gpios), \ |
| .int_gpio_callback = bosch_bmi323_irq_callback##inst, \ |
| }; \ |
| \ |
| PM_DEVICE_DT_INST_DEFINE(inst, bosch_bmi323_pm_action); \ |
| \ |
| SENSOR_DEVICE_DT_INST_DEFINE(inst, bosch_bmi323_init, PM_DEVICE_DT_INST_GET(inst), \ |
| &bosch_bmi323_data_##inst, &bosch_bmi323_config_##inst, \ |
| POST_KERNEL, 99, &bosch_bmi323_api); |
| |
| DT_INST_FOREACH_STATUS_OKAY(BMI323_DEVICE) |