linux/drivers/iio/imu/bno055/bno055.c

// SPDX-License-Identifier: GPL-2.0
/*
 * IIO driver for Bosch BNO055 IMU
 *
 * Copyright (C) 2021-2022 Istituto Italiano di Tecnologia
 * Electronic Design Laboratory
 * Written by Andrea Merello <[email protected]>
 *
 * Portions of this driver are taken from the BNO055 driver patch
 * from Vlad Dogaru which is Copyright (c) 2016, Intel Corporation.
 *
 * This driver is also based on BMI160 driver, which is:
 *	Copyright (c) 2016, Intel Corporation.
 *	Copyright (c) 2019, Martin Kelly.
 */

#include <linux/bitfield.h>
#include <linux/bitmap.h>
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
#include <linux/util_macros.h>

#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>

#include "bno055.h"

#define BNO055_FW_UID_FMT
#define BNO055_FW_GENERIC_NAME

/* common registers */
#define BNO055_PAGESEL_REG

/* page 0 registers */
#define BNO055_CHIP_ID_REG
#define BNO055_CHIP_ID_MAGIC
#define BNO055_SW_REV_LSB_REG
#define BNO055_SW_REV_MSB_REG
#define BNO055_ACC_DATA_X_LSB_REG
#define BNO055_ACC_DATA_Y_LSB_REG
#define BNO055_ACC_DATA_Z_LSB_REG
#define BNO055_MAG_DATA_X_LSB_REG
#define BNO055_MAG_DATA_Y_LSB_REG
#define BNO055_MAG_DATA_Z_LSB_REG
#define BNO055_GYR_DATA_X_LSB_REG
#define BNO055_GYR_DATA_Y_LSB_REG
#define BNO055_GYR_DATA_Z_LSB_REG
#define BNO055_EUL_DATA_X_LSB_REG
#define BNO055_EUL_DATA_Y_LSB_REG
#define BNO055_EUL_DATA_Z_LSB_REG
#define BNO055_QUAT_DATA_W_LSB_REG
#define BNO055_LIA_DATA_X_LSB_REG
#define BNO055_LIA_DATA_Y_LSB_REG
#define BNO055_LIA_DATA_Z_LSB_REG
#define BNO055_GRAVITY_DATA_X_LSB_REG
#define BNO055_GRAVITY_DATA_Y_LSB_REG
#define BNO055_GRAVITY_DATA_Z_LSB_REG
#define BNO055_SCAN_CH_COUNT
#define BNO055_TEMP_REG
#define BNO055_CALIB_STAT_REG
#define BNO055_CALIB_STAT_MAGN_SHIFT
#define BNO055_CALIB_STAT_ACCEL_SHIFT
#define BNO055_CALIB_STAT_GYRO_SHIFT
#define BNO055_CALIB_STAT_SYS_SHIFT
#define BNO055_SYS_ERR_REG
#define BNO055_POWER_MODE_REG
#define BNO055_POWER_MODE_NORMAL
#define BNO055_SYS_TRIGGER_REG
#define BNO055_SYS_TRIGGER_RST_SYS
#define BNO055_SYS_TRIGGER_CLK_SEL
#define BNO055_OPR_MODE_REG
#define BNO055_OPR_MODE_CONFIG
#define BNO055_OPR_MODE_AMG
#define BNO055_OPR_MODE_FUSION_FMC_OFF
#define BNO055_OPR_MODE_FUSION
#define BNO055_UNIT_SEL_REG
/* Android orientation mode means: pitch value decreases turning clockwise */
#define BNO055_UNIT_SEL_ANDROID
#define BNO055_UNIT_SEL_GYR_RPS
#define BNO055_CALDATA_START
#define BNO055_CALDATA_END
#define BNO055_CALDATA_LEN

/*
 * The difference in address between the register that contains the
 * value and the register that contains the offset.  This applies for
 * accel, gyro and magn channels.
 */
#define BNO055_REG_OFFSET_ADDR

/* page 1 registers */
#define BNO055_PG1(x)
#define BNO055_ACC_CONFIG_REG
#define BNO055_ACC_CONFIG_LPF_MASK
#define BNO055_ACC_CONFIG_RANGE_MASK
#define BNO055_MAG_CONFIG_REG
#define BNO055_MAG_CONFIG_HIGHACCURACY
#define BNO055_MAG_CONFIG_ODR_MASK
#define BNO055_GYR_CONFIG_REG
#define BNO055_GYR_CONFIG_RANGE_MASK
#define BNO055_GYR_CONFIG_LPF_MASK
#define BNO055_GYR_AM_SET_REG
#define BNO055_UID_LOWER_REG
#define BNO055_UID_HIGHER_REG
#define BNO055_UID_LEN

struct bno055_sysfs_attr {};

static int bno055_acc_lpf_vals[] =;

static struct bno055_sysfs_attr bno055_acc_lpf =;

static int bno055_acc_range_vals[] =;

static struct bno055_sysfs_attr bno055_acc_range =;

/*
 * Theoretically the IMU should return data in a given (i.e. fixed) unit
 * regardless of the range setting. This happens for the accelerometer, but not
 * for the gyroscope; the gyroscope range setting affects the scale.
 * This is probably due to this[0] bug.
 * For this reason we map the internal range setting onto the standard IIO scale
 * attribute for gyro.
 * Since the bug[0] may be fixed in future, we check for the IMU FW version and
 * eventually warn the user.
 * Currently we just don't care about "range" attributes for gyro.
 *
 * [0]  https://community.bosch-sensortec.com/t5/MEMS-sensors-forum/BNO055-Wrong-sensitivity-resolution-in-datasheet/td-p/10266
 */

/*
 * dps = hwval * (dps_range/2^15)
 * rps = hwval * (rps_range/2^15)
 *     = hwval * (dps_range/(2^15 * k))
 * where k is rad-to-deg factor
 */
static int bno055_gyr_scale_vals[] =;

static struct bno055_sysfs_attr bno055_gyr_scale =;

static int bno055_gyr_lpf_vals[] =;
static struct bno055_sysfs_attr bno055_gyr_lpf =;

static int bno055_mag_odr_vals[] =;
static struct bno055_sysfs_attr bno055_mag_odr =;

struct bno055_priv {};

static bool bno055_regmap_volatile(struct device *dev, unsigned int reg)
{}

static bool bno055_regmap_readable(struct device *dev, unsigned int reg)
{}

static bool bno055_regmap_writeable(struct device *dev, unsigned int reg)
{}

static const struct regmap_range_cfg bno055_regmap_ranges[] =;

const struct regmap_config bno055_regmap_config =;
EXPORT_SYMBOL_NS_GPL();

/* must be called in configuration mode */
static int bno055_calibration_load(struct bno055_priv *priv, const u8 *data, int len)
{}

static int bno055_operation_mode_do_set(struct bno055_priv *priv,
					int operation_mode)
{}

static int bno055_system_reset(struct bno055_priv *priv)
{}

static int bno055_init(struct bno055_priv *priv, const u8 *caldata, int len)
{}

static ssize_t bno055_operation_mode_set(struct bno055_priv *priv,
					 int operation_mode)
{}

static void bno055_uninit(void *arg)
{}

#define BNO055_CHANNEL(_type, _axis, _index, _address, _sep, _sh, _avail)

/* scan indexes follow DATA register order */
enum bno055_scan_axis {};

static const struct iio_chan_spec bno055_channels[] =;

static int bno055_get_regmask(struct bno055_priv *priv, int *val, int *val2,
			      int reg, int mask, struct bno055_sysfs_attr *attr)
{}

static int bno055_set_regmask(struct bno055_priv *priv, int val, int val2,
			      int reg, int mask, struct bno055_sysfs_attr *attr)
{}

static int bno055_read_simple_chan(struct iio_dev *indio_dev,
				   struct iio_chan_spec const *chan,
				   int *val, int *val2, long mask)
{}

static int bno055_sysfs_attr_avail(struct bno055_priv *priv, struct bno055_sysfs_attr *attr,
				   const int **vals, int *length)
{}

static int bno055_read_avail(struct iio_dev *indio_dev,
			     struct iio_chan_spec const *chan,
			     const int **vals, int *type, int *length,
			     long mask)
{}

static int bno055_read_temp_chan(struct iio_dev *indio_dev, int *val)
{}

static int bno055_read_quaternion(struct iio_dev *indio_dev,
				  struct iio_chan_spec const *chan,
				  int size, int *vals, int *val_len,
				  long mask)
{}

static bool bno055_is_chan_readable(struct iio_dev *indio_dev,
				    struct iio_chan_spec const *chan)
{}

static int _bno055_read_raw_multi(struct iio_dev *indio_dev,
				  struct iio_chan_spec const *chan,
				  int size, int *vals, int *val_len,
				  long mask)
{}

static int bno055_read_raw_multi(struct iio_dev *indio_dev,
				 struct iio_chan_spec const *chan,
				 int size, int *vals, int *val_len,
				 long mask)
{}

static int _bno055_write_raw(struct iio_dev *iio_dev,
			     struct iio_chan_spec const *chan,
			     int val, int val2, long mask)
{}

static int bno055_write_raw(struct iio_dev *iio_dev,
			    struct iio_chan_spec const *chan,
			    int val, int val2, long mask)
{}

static ssize_t in_accel_range_raw_available_show(struct device *dev,
						 struct device_attribute *attr,
						 char *buf)
{}

static ssize_t fusion_enable_show(struct device *dev,
				  struct device_attribute *attr,
				  char *buf)
{}

static ssize_t fusion_enable_store(struct device *dev,
				   struct device_attribute *attr,
				   const char *buf, size_t len)
{}

static ssize_t in_magn_calibration_fast_enable_show(struct device *dev,
						    struct device_attribute *attr,
						    char *buf)
{}

static ssize_t in_magn_calibration_fast_enable_store(struct device *dev,
						     struct device_attribute *attr,
						     const char *buf, size_t len)
{}

static ssize_t in_accel_range_raw_show(struct device *dev,
				       struct device_attribute *attr,
				       char *buf)
{}

static ssize_t in_accel_range_raw_store(struct device *dev,
					struct device_attribute *attr,
					const char *buf, size_t len)
{}

static ssize_t bno055_get_calib_status(struct device *dev, char *buf, int which)
{}

static ssize_t serialnumber_show(struct device *dev,
				 struct device_attribute *attr,
				 char *buf)
{}

static ssize_t calibration_data_read(struct file *filp, struct kobject *kobj,
				     struct bin_attribute *bin_attr, char *buf,
				     loff_t pos, size_t count)
{}

static ssize_t sys_calibration_auto_status_show(struct device *dev,
						struct device_attribute *a,
						char *buf)
{}

static ssize_t in_accel_calibration_auto_status_show(struct device *dev,
						     struct device_attribute *a,
						     char *buf)
{}

static ssize_t in_gyro_calibration_auto_status_show(struct device *dev,
						    struct device_attribute *a,
						    char *buf)
{}

static ssize_t in_magn_calibration_auto_status_show(struct device *dev,
						    struct device_attribute *a,
						    char *buf)
{}

static int bno055_debugfs_reg_access(struct iio_dev *iio_dev, unsigned int reg,
				     unsigned int writeval, unsigned int *readval)
{}

static ssize_t bno055_show_fw_version(struct file *file, char __user *userbuf,
				      size_t count, loff_t *ppos)
{}

static const struct file_operations bno055_fw_version_ops =;

static void bno055_debugfs_remove(void *_priv)
{}

static void bno055_debugfs_init(struct iio_dev *iio_dev)
{}

static IIO_DEVICE_ATTR_RW(fusion_enable, 0);
static IIO_DEVICE_ATTR_RW(in_magn_calibration_fast_enable, 0);
static IIO_DEVICE_ATTR_RW(in_accel_range_raw, 0);

static IIO_DEVICE_ATTR_RO(in_accel_range_raw_available, 0);
static IIO_DEVICE_ATTR_RO(sys_calibration_auto_status, 0);
static IIO_DEVICE_ATTR_RO(in_accel_calibration_auto_status, 0);
static IIO_DEVICE_ATTR_RO(in_gyro_calibration_auto_status, 0);
static IIO_DEVICE_ATTR_RO(in_magn_calibration_auto_status, 0);
static IIO_DEVICE_ATTR_RO(serialnumber, 0);

static struct attribute *bno055_attrs[] =;

static BIN_ATTR_RO(calibration_data, BNO055_CALDATA_LEN);

static struct bin_attribute *bno055_bin_attrs[] =;

static const struct attribute_group bno055_attrs_group =;

static const struct iio_info bno055_info =;

/*
 * Reads len samples from the HW, stores them in buf starting from buf_idx,
 * and applies mask to cull (skip) unneeded samples.
 * Updates buf_idx incrementing with the number of stored samples.
 * Samples from HW are transferred into buf, then in-place copy on buf is
 * performed in order to cull samples that need to be skipped.
 * This avoids copies of the first samples until we hit the 1st sample to skip,
 * and also avoids having an extra bounce buffer.
 * buf must be able to contain len elements in spite of how many samples we are
 * going to cull.
 */
static int bno055_scan_xfer(struct bno055_priv *priv,
			    int start_ch, int len, unsigned long mask,
			    __le16 *buf, int *buf_idx)
{}

static irqreturn_t bno055_trigger_handler(int irq, void *p)
{}

static int bno055_buffer_preenable(struct iio_dev *indio_dev)
{}

static const struct iio_buffer_setup_ops bno055_buffer_setup_ops =;

int bno055_probe(struct device *dev, struct regmap *regmap,
		 int xfer_burst_break_thr, bool sw_reset)
{}
EXPORT_SYMBOL_NS_GPL();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();