1350 lines
33 KiB
C
1350 lines
33 KiB
C
/*
|
|
* 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 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 = 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 = 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 = 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 = 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 = 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 = 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 = -ENOTSUP;
|
|
|
|
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_DISABLE);
|
|
}
|
|
|
|
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)
|
|
{
|
|
const struct bosch_bmi323_config *config = (const struct bosch_bmi323_config *)dev->config;
|
|
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;
|
|
}
|
|
|
|
ret = gpio_pin_interrupt_configure_dt(&config->int_gpio, GPIO_INT_EDGE_TO_ACTIVE);
|
|
if (ret < 0) {
|
|
LOG_WRN("Failed to configure int");
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
#ifdef CONFIG_PM_DEVICE
|
|
static int bosch_bmi323_pm_suspend(const struct device *dev)
|
|
{
|
|
const struct bosch_bmi323_config *config = (const struct bosch_bmi323_config *)dev->config;
|
|
int ret;
|
|
|
|
ret = gpio_pin_interrupt_configure_dt(&config->int_gpio, GPIO_INT_DISABLE);
|
|
if (ret < 0) {
|
|
LOG_WRN("Failed to disable int");
|
|
}
|
|
|
|
/* 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)
|