1686 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * IIO driver for Bosch BNO055 IMU4 *5 * Copyright (C) 2021-2022 Istituto Italiano di Tecnologia6 * Electronic Design Laboratory7 * Written by Andrea Merello <andrea.merello@iit.it>8 *9 * Portions of this driver are taken from the BNO055 driver patch10 * from Vlad Dogaru which is Copyright (c) 2016, Intel Corporation.11 *12 * This driver is also based on BMI160 driver, which is:13 * Copyright (c) 2016, Intel Corporation.14 * Copyright (c) 2019, Martin Kelly.15 */16 17#include <linux/bitfield.h>18#include <linux/bitmap.h>19#include <linux/clk.h>20#include <linux/debugfs.h>21#include <linux/device.h>22#include <linux/firmware.h>23#include <linux/gpio/consumer.h>24#include <linux/module.h>25#include <linux/mutex.h>26#include <linux/regmap.h>27#include <linux/util_macros.h>28 29#include <linux/iio/buffer.h>30#include <linux/iio/iio.h>31#include <linux/iio/sysfs.h>32#include <linux/iio/trigger_consumer.h>33#include <linux/iio/triggered_buffer.h>34 35#include "bno055.h"36 37#define BNO055_FW_UID_FMT "bno055-caldata-%*phN.dat"38#define BNO055_FW_GENERIC_NAME "bno055-caldata.dat"39 40/* common registers */41#define BNO055_PAGESEL_REG 0x742 43/* page 0 registers */44#define BNO055_CHIP_ID_REG 0x045#define BNO055_CHIP_ID_MAGIC 0xA046#define BNO055_SW_REV_LSB_REG 0x447#define BNO055_SW_REV_MSB_REG 0x548#define BNO055_ACC_DATA_X_LSB_REG 0x849#define BNO055_ACC_DATA_Y_LSB_REG 0xA50#define BNO055_ACC_DATA_Z_LSB_REG 0xC51#define BNO055_MAG_DATA_X_LSB_REG 0xE52#define BNO055_MAG_DATA_Y_LSB_REG 0x1053#define BNO055_MAG_DATA_Z_LSB_REG 0x1254#define BNO055_GYR_DATA_X_LSB_REG 0x1455#define BNO055_GYR_DATA_Y_LSB_REG 0x1656#define BNO055_GYR_DATA_Z_LSB_REG 0x1857#define BNO055_EUL_DATA_X_LSB_REG 0x1A58#define BNO055_EUL_DATA_Y_LSB_REG 0x1C59#define BNO055_EUL_DATA_Z_LSB_REG 0x1E60#define BNO055_QUAT_DATA_W_LSB_REG 0x2061#define BNO055_LIA_DATA_X_LSB_REG 0x2862#define BNO055_LIA_DATA_Y_LSB_REG 0x2A63#define BNO055_LIA_DATA_Z_LSB_REG 0x2C64#define BNO055_GRAVITY_DATA_X_LSB_REG 0x2E65#define BNO055_GRAVITY_DATA_Y_LSB_REG 0x3066#define BNO055_GRAVITY_DATA_Z_LSB_REG 0x3267#define BNO055_SCAN_CH_COUNT ((BNO055_GRAVITY_DATA_Z_LSB_REG - BNO055_ACC_DATA_X_LSB_REG) / 2)68#define BNO055_TEMP_REG 0x3469#define BNO055_CALIB_STAT_REG 0x3570#define BNO055_CALIB_STAT_MAGN_SHIFT 071#define BNO055_CALIB_STAT_ACCEL_SHIFT 272#define BNO055_CALIB_STAT_GYRO_SHIFT 473#define BNO055_CALIB_STAT_SYS_SHIFT 674#define BNO055_SYS_ERR_REG 0x3A75#define BNO055_POWER_MODE_REG 0x3E76#define BNO055_POWER_MODE_NORMAL 077#define BNO055_SYS_TRIGGER_REG 0x3F78#define BNO055_SYS_TRIGGER_RST_SYS BIT(5)79#define BNO055_SYS_TRIGGER_CLK_SEL BIT(7)80#define BNO055_OPR_MODE_REG 0x3D81#define BNO055_OPR_MODE_CONFIG 0x082#define BNO055_OPR_MODE_AMG 0x783#define BNO055_OPR_MODE_FUSION_FMC_OFF 0xB84#define BNO055_OPR_MODE_FUSION 0xC85#define BNO055_UNIT_SEL_REG 0x3B86/* Android orientation mode means: pitch value decreases turning clockwise */87#define BNO055_UNIT_SEL_ANDROID BIT(7)88#define BNO055_UNIT_SEL_GYR_RPS BIT(1)89#define BNO055_CALDATA_START 0x5590#define BNO055_CALDATA_END 0x6A91#define BNO055_CALDATA_LEN 2292 93/*94 * The difference in address between the register that contains the95 * value and the register that contains the offset. This applies for96 * accel, gyro and magn channels.97 */98#define BNO055_REG_OFFSET_ADDR 0x4D99 100/* page 1 registers */101#define BNO055_PG1(x) ((x) | 0x80)102#define BNO055_ACC_CONFIG_REG BNO055_PG1(0x8)103#define BNO055_ACC_CONFIG_LPF_MASK GENMASK(4, 2)104#define BNO055_ACC_CONFIG_RANGE_MASK GENMASK(1, 0)105#define BNO055_MAG_CONFIG_REG BNO055_PG1(0x9)106#define BNO055_MAG_CONFIG_HIGHACCURACY 0x18107#define BNO055_MAG_CONFIG_ODR_MASK GENMASK(2, 0)108#define BNO055_GYR_CONFIG_REG BNO055_PG1(0xA)109#define BNO055_GYR_CONFIG_RANGE_MASK GENMASK(2, 0)110#define BNO055_GYR_CONFIG_LPF_MASK GENMASK(5, 3)111#define BNO055_GYR_AM_SET_REG BNO055_PG1(0x1F)112#define BNO055_UID_LOWER_REG BNO055_PG1(0x50)113#define BNO055_UID_HIGHER_REG BNO055_PG1(0x5F)114#define BNO055_UID_LEN 16115 116struct bno055_sysfs_attr {117 int *vals;118 int len;119 int *fusion_vals;120 int *hw_xlate;121 int type;122};123 124static int bno055_acc_lpf_vals[] = {125 7, 810000, 15, 630000, 31, 250000, 62, 500000,126 125, 0, 250, 0, 500, 0, 1000, 0,127};128 129static struct bno055_sysfs_attr bno055_acc_lpf = {130 .vals = bno055_acc_lpf_vals,131 .len = ARRAY_SIZE(bno055_acc_lpf_vals),132 .fusion_vals = (int[]){62, 500000},133 .type = IIO_VAL_INT_PLUS_MICRO,134};135 136static int bno055_acc_range_vals[] = {137 /* G: 2, 4, 8, 16 */138 1962, 3924, 7848, 15696139};140 141static struct bno055_sysfs_attr bno055_acc_range = {142 .vals = bno055_acc_range_vals,143 .len = ARRAY_SIZE(bno055_acc_range_vals),144 .fusion_vals = (int[]){3924}, /* 4G */145 .type = IIO_VAL_INT,146};147 148/*149 * Theoretically the IMU should return data in a given (i.e. fixed) unit150 * regardless of the range setting. This happens for the accelerometer, but not151 * for the gyroscope; the gyroscope range setting affects the scale.152 * This is probably due to this[0] bug.153 * For this reason we map the internal range setting onto the standard IIO scale154 * attribute for gyro.155 * Since the bug[0] may be fixed in future, we check for the IMU FW version and156 * eventually warn the user.157 * Currently we just don't care about "range" attributes for gyro.158 *159 * [0] https://community.bosch-sensortec.com/t5/MEMS-sensors-forum/BNO055-Wrong-sensitivity-resolution-in-datasheet/td-p/10266160 */161 162/*163 * dps = hwval * (dps_range/2^15)164 * rps = hwval * (rps_range/2^15)165 * = hwval * (dps_range/(2^15 * k))166 * where k is rad-to-deg factor167 */168static int bno055_gyr_scale_vals[] = {169 125, 1877467, 250, 1877467, 500, 1877467,170 1000, 1877467, 2000, 1877467,171};172 173static struct bno055_sysfs_attr bno055_gyr_scale = {174 .vals = bno055_gyr_scale_vals,175 .len = ARRAY_SIZE(bno055_gyr_scale_vals),176 .fusion_vals = (int[]){1, 900},177 .hw_xlate = (int[]){4, 3, 2, 1, 0},178 .type = IIO_VAL_FRACTIONAL,179};180 181static int bno055_gyr_lpf_vals[] = {12, 23, 32, 47, 64, 116, 230, 523};182static struct bno055_sysfs_attr bno055_gyr_lpf = {183 .vals = bno055_gyr_lpf_vals,184 .len = ARRAY_SIZE(bno055_gyr_lpf_vals),185 .fusion_vals = (int[]){32},186 .hw_xlate = (int[]){5, 4, 7, 3, 6, 2, 1, 0},187 .type = IIO_VAL_INT,188};189 190static int bno055_mag_odr_vals[] = {2, 6, 8, 10, 15, 20, 25, 30};191static struct bno055_sysfs_attr bno055_mag_odr = {192 .vals = bno055_mag_odr_vals,193 .len = ARRAY_SIZE(bno055_mag_odr_vals),194 .fusion_vals = (int[]){20},195 .type = IIO_VAL_INT,196};197 198struct bno055_priv {199 struct regmap *regmap;200 struct device *dev;201 struct clk *clk;202 int operation_mode;203 int xfer_burst_break_thr;204 struct mutex lock;205 u8 uid[BNO055_UID_LEN];206 struct gpio_desc *reset_gpio;207 bool sw_reset;208 struct {209 __le16 chans[BNO055_SCAN_CH_COUNT];210 s64 timestamp __aligned(8);211 } buf;212 struct dentry *debugfs;213};214 215static bool bno055_regmap_volatile(struct device *dev, unsigned int reg)216{217 /* data and status registers */218 if (reg >= BNO055_ACC_DATA_X_LSB_REG && reg <= BNO055_SYS_ERR_REG)219 return true;220 221 /* when in fusion mode, config is updated by chip */222 if (reg == BNO055_MAG_CONFIG_REG ||223 reg == BNO055_ACC_CONFIG_REG ||224 reg == BNO055_GYR_CONFIG_REG)225 return true;226 227 /* calibration data may be updated by the IMU */228 if (reg >= BNO055_CALDATA_START && reg <= BNO055_CALDATA_END)229 return true;230 231 return false;232}233 234static bool bno055_regmap_readable(struct device *dev, unsigned int reg)235{236 /* unnamed PG0 reserved areas */237 if ((reg < BNO055_PG1(0) && reg > BNO055_CALDATA_END) ||238 reg == 0x3C)239 return false;240 241 /* unnamed PG1 reserved areas */242 if (reg > BNO055_PG1(BNO055_UID_HIGHER_REG) ||243 (reg < BNO055_PG1(BNO055_UID_LOWER_REG) && reg > BNO055_PG1(BNO055_GYR_AM_SET_REG)) ||244 reg == BNO055_PG1(0xE) ||245 (reg < BNO055_PG1(BNO055_PAGESEL_REG) && reg >= BNO055_PG1(0x0)))246 return false;247 return true;248}249 250static bool bno055_regmap_writeable(struct device *dev, unsigned int reg)251{252 /*253 * Unreadable registers are indeed reserved; there are no WO regs254 * (except for a single bit in SYS_TRIGGER register)255 */256 if (!bno055_regmap_readable(dev, reg))257 return false;258 259 /* data and status registers */260 if (reg >= BNO055_ACC_DATA_X_LSB_REG && reg <= BNO055_SYS_ERR_REG)261 return false;262 263 /* ID areas */264 if (reg < BNO055_PAGESEL_REG ||265 (reg <= BNO055_UID_HIGHER_REG && reg >= BNO055_UID_LOWER_REG))266 return false;267 268 return true;269}270 271static const struct regmap_range_cfg bno055_regmap_ranges[] = {272 {273 .range_min = 0,274 .range_max = 0x7f * 2,275 .selector_reg = BNO055_PAGESEL_REG,276 .selector_mask = GENMASK(7, 0),277 .selector_shift = 0,278 .window_start = 0,279 .window_len = 0x80,280 },281};282 283const struct regmap_config bno055_regmap_config = {284 .name = "bno055",285 .reg_bits = 8,286 .val_bits = 8,287 .ranges = bno055_regmap_ranges,288 .num_ranges = 1,289 .volatile_reg = bno055_regmap_volatile,290 .max_register = 0x80 * 2,291 .writeable_reg = bno055_regmap_writeable,292 .readable_reg = bno055_regmap_readable,293 .cache_type = REGCACHE_RBTREE,294};295EXPORT_SYMBOL_NS_GPL(bno055_regmap_config, IIO_BNO055);296 297/* must be called in configuration mode */298static int bno055_calibration_load(struct bno055_priv *priv, const u8 *data, int len)299{300 if (len != BNO055_CALDATA_LEN) {301 dev_dbg(priv->dev, "Invalid calibration file size %d (expected %d)",302 len, BNO055_CALDATA_LEN);303 return -EINVAL;304 }305 306 dev_dbg(priv->dev, "loading cal data: %*ph", BNO055_CALDATA_LEN, data);307 return regmap_bulk_write(priv->regmap, BNO055_CALDATA_START,308 data, BNO055_CALDATA_LEN);309}310 311static int bno055_operation_mode_do_set(struct bno055_priv *priv,312 int operation_mode)313{314 int ret;315 316 ret = regmap_write(priv->regmap, BNO055_OPR_MODE_REG,317 operation_mode);318 if (ret)319 return ret;320 321 /* Following datasheet specifications: sensor takes 7mS up to 19 mS to switch mode */322 msleep(20);323 324 return 0;325}326 327static int bno055_system_reset(struct bno055_priv *priv)328{329 int ret;330 331 if (priv->reset_gpio) {332 gpiod_set_value_cansleep(priv->reset_gpio, 0);333 usleep_range(5000, 10000);334 gpiod_set_value_cansleep(priv->reset_gpio, 1);335 } else if (priv->sw_reset) {336 ret = regmap_write(priv->regmap, BNO055_SYS_TRIGGER_REG,337 BNO055_SYS_TRIGGER_RST_SYS);338 if (ret)339 return ret;340 } else {341 return 0;342 }343 344 regcache_drop_region(priv->regmap, 0x0, 0xff);345 usleep_range(650000, 700000);346 347 return 0;348}349 350static int bno055_init(struct bno055_priv *priv, const u8 *caldata, int len)351{352 int ret;353 354 ret = bno055_operation_mode_do_set(priv, BNO055_OPR_MODE_CONFIG);355 if (ret)356 return ret;357 358 ret = regmap_write(priv->regmap, BNO055_POWER_MODE_REG,359 BNO055_POWER_MODE_NORMAL);360 if (ret)361 return ret;362 363 ret = regmap_write(priv->regmap, BNO055_SYS_TRIGGER_REG,364 priv->clk ? BNO055_SYS_TRIGGER_CLK_SEL : 0);365 if (ret)366 return ret;367 368 /* use standard SI units */369 ret = regmap_write(priv->regmap, BNO055_UNIT_SEL_REG,370 BNO055_UNIT_SEL_ANDROID | BNO055_UNIT_SEL_GYR_RPS);371 if (ret)372 return ret;373 374 if (caldata) {375 ret = bno055_calibration_load(priv, caldata, len);376 if (ret)377 dev_warn(priv->dev, "failed to load calibration data with error %d\n",378 ret);379 }380 381 return 0;382}383 384static ssize_t bno055_operation_mode_set(struct bno055_priv *priv,385 int operation_mode)386{387 u8 caldata[BNO055_CALDATA_LEN];388 int ret;389 390 mutex_lock(&priv->lock);391 392 ret = bno055_operation_mode_do_set(priv, BNO055_OPR_MODE_CONFIG);393 if (ret)394 goto exit_unlock;395 396 if (operation_mode == BNO055_OPR_MODE_FUSION ||397 operation_mode == BNO055_OPR_MODE_FUSION_FMC_OFF) {398 /* for entering fusion mode, reset the chip to clear the algo state */399 ret = regmap_bulk_read(priv->regmap, BNO055_CALDATA_START, caldata,400 BNO055_CALDATA_LEN);401 if (ret)402 goto exit_unlock;403 404 ret = bno055_system_reset(priv);405 if (ret)406 goto exit_unlock;407 408 ret = bno055_init(priv, caldata, BNO055_CALDATA_LEN);409 if (ret)410 goto exit_unlock;411 }412 413 ret = bno055_operation_mode_do_set(priv, operation_mode);414 if (ret)415 goto exit_unlock;416 417 priv->operation_mode = operation_mode;418 419exit_unlock:420 mutex_unlock(&priv->lock);421 return ret;422}423 424static void bno055_uninit(void *arg)425{426 struct bno055_priv *priv = arg;427 428 /* stop the IMU */429 bno055_operation_mode_do_set(priv, BNO055_OPR_MODE_CONFIG);430}431 432#define BNO055_CHANNEL(_type, _axis, _index, _address, _sep, _sh, _avail) { \433 .address = _address, \434 .type = _type, \435 .modified = 1, \436 .channel2 = IIO_MOD_##_axis, \437 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | (_sep), \438 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | (_sh), \439 .info_mask_shared_by_type_available = _avail, \440 .scan_index = _index, \441 .scan_type = { \442 .sign = 's', \443 .realbits = 16, \444 .storagebits = 16, \445 .endianness = IIO_LE, \446 .repeat = IIO_MOD_##_axis == IIO_MOD_QUATERNION ? 4 : 0, \447 }, \448}449 450/* scan indexes follow DATA register order */451enum bno055_scan_axis {452 BNO055_SCAN_ACCEL_X,453 BNO055_SCAN_ACCEL_Y,454 BNO055_SCAN_ACCEL_Z,455 BNO055_SCAN_MAGN_X,456 BNO055_SCAN_MAGN_Y,457 BNO055_SCAN_MAGN_Z,458 BNO055_SCAN_GYRO_X,459 BNO055_SCAN_GYRO_Y,460 BNO055_SCAN_GYRO_Z,461 BNO055_SCAN_YAW,462 BNO055_SCAN_ROLL,463 BNO055_SCAN_PITCH,464 BNO055_SCAN_QUATERNION,465 BNO055_SCAN_LIA_X,466 BNO055_SCAN_LIA_Y,467 BNO055_SCAN_LIA_Z,468 BNO055_SCAN_GRAVITY_X,469 BNO055_SCAN_GRAVITY_Y,470 BNO055_SCAN_GRAVITY_Z,471 BNO055_SCAN_TIMESTAMP,472 _BNO055_SCAN_MAX473};474 475static const struct iio_chan_spec bno055_channels[] = {476 /* accelerometer */477 BNO055_CHANNEL(IIO_ACCEL, X, BNO055_SCAN_ACCEL_X,478 BNO055_ACC_DATA_X_LSB_REG, BIT(IIO_CHAN_INFO_OFFSET),479 BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),480 BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY)),481 BNO055_CHANNEL(IIO_ACCEL, Y, BNO055_SCAN_ACCEL_Y,482 BNO055_ACC_DATA_Y_LSB_REG, BIT(IIO_CHAN_INFO_OFFSET),483 BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),484 BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY)),485 BNO055_CHANNEL(IIO_ACCEL, Z, BNO055_SCAN_ACCEL_Z,486 BNO055_ACC_DATA_Z_LSB_REG, BIT(IIO_CHAN_INFO_OFFSET),487 BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),488 BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY)),489 /* gyroscope */490 BNO055_CHANNEL(IIO_ANGL_VEL, X, BNO055_SCAN_GYRO_X,491 BNO055_GYR_DATA_X_LSB_REG, BIT(IIO_CHAN_INFO_OFFSET),492 BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),493 BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) |494 BIT(IIO_CHAN_INFO_SCALE)),495 BNO055_CHANNEL(IIO_ANGL_VEL, Y, BNO055_SCAN_GYRO_Y,496 BNO055_GYR_DATA_Y_LSB_REG, BIT(IIO_CHAN_INFO_OFFSET),497 BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),498 BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) |499 BIT(IIO_CHAN_INFO_SCALE)),500 BNO055_CHANNEL(IIO_ANGL_VEL, Z, BNO055_SCAN_GYRO_Z,501 BNO055_GYR_DATA_Z_LSB_REG, BIT(IIO_CHAN_INFO_OFFSET),502 BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),503 BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) |504 BIT(IIO_CHAN_INFO_SCALE)),505 /* magnetometer */506 BNO055_CHANNEL(IIO_MAGN, X, BNO055_SCAN_MAGN_X,507 BNO055_MAG_DATA_X_LSB_REG, BIT(IIO_CHAN_INFO_OFFSET),508 BIT(IIO_CHAN_INFO_SAMP_FREQ), BIT(IIO_CHAN_INFO_SAMP_FREQ)),509 BNO055_CHANNEL(IIO_MAGN, Y, BNO055_SCAN_MAGN_Y,510 BNO055_MAG_DATA_Y_LSB_REG, BIT(IIO_CHAN_INFO_OFFSET),511 BIT(IIO_CHAN_INFO_SAMP_FREQ), BIT(IIO_CHAN_INFO_SAMP_FREQ)),512 BNO055_CHANNEL(IIO_MAGN, Z, BNO055_SCAN_MAGN_Z,513 BNO055_MAG_DATA_Z_LSB_REG, BIT(IIO_CHAN_INFO_OFFSET),514 BIT(IIO_CHAN_INFO_SAMP_FREQ), BIT(IIO_CHAN_INFO_SAMP_FREQ)),515 /* euler angle */516 BNO055_CHANNEL(IIO_ROT, YAW, BNO055_SCAN_YAW,517 BNO055_EUL_DATA_X_LSB_REG, 0, 0, 0),518 BNO055_CHANNEL(IIO_ROT, ROLL, BNO055_SCAN_ROLL,519 BNO055_EUL_DATA_Y_LSB_REG, 0, 0, 0),520 BNO055_CHANNEL(IIO_ROT, PITCH, BNO055_SCAN_PITCH,521 BNO055_EUL_DATA_Z_LSB_REG, 0, 0, 0),522 /* quaternion */523 BNO055_CHANNEL(IIO_ROT, QUATERNION, BNO055_SCAN_QUATERNION,524 BNO055_QUAT_DATA_W_LSB_REG, 0, 0, 0),525 526 /* linear acceleration */527 BNO055_CHANNEL(IIO_ACCEL, LINEAR_X, BNO055_SCAN_LIA_X,528 BNO055_LIA_DATA_X_LSB_REG, 0, 0, 0),529 BNO055_CHANNEL(IIO_ACCEL, LINEAR_Y, BNO055_SCAN_LIA_Y,530 BNO055_LIA_DATA_Y_LSB_REG, 0, 0, 0),531 BNO055_CHANNEL(IIO_ACCEL, LINEAR_Z, BNO055_SCAN_LIA_Z,532 BNO055_LIA_DATA_Z_LSB_REG, 0, 0, 0),533 534 /* gravity vector */535 BNO055_CHANNEL(IIO_GRAVITY, X, BNO055_SCAN_GRAVITY_X,536 BNO055_GRAVITY_DATA_X_LSB_REG, 0, 0, 0),537 BNO055_CHANNEL(IIO_GRAVITY, Y, BNO055_SCAN_GRAVITY_Y,538 BNO055_GRAVITY_DATA_Y_LSB_REG, 0, 0, 0),539 BNO055_CHANNEL(IIO_GRAVITY, Z, BNO055_SCAN_GRAVITY_Z,540 BNO055_GRAVITY_DATA_Z_LSB_REG, 0, 0, 0),541 542 {543 .type = IIO_TEMP,544 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),545 .scan_index = -1,546 },547 IIO_CHAN_SOFT_TIMESTAMP(BNO055_SCAN_TIMESTAMP),548};549 550static int bno055_get_regmask(struct bno055_priv *priv, int *val, int *val2,551 int reg, int mask, struct bno055_sysfs_attr *attr)552{553 const int shift = __ffs(mask);554 int hwval, idx;555 int ret;556 int i;557 558 ret = regmap_read(priv->regmap, reg, &hwval);559 if (ret)560 return ret;561 562 idx = (hwval & mask) >> shift;563 if (attr->hw_xlate)564 for (i = 0; i < attr->len; i++)565 if (attr->hw_xlate[i] == idx) {566 idx = i;567 break;568 }569 if (attr->type == IIO_VAL_INT) {570 *val = attr->vals[idx];571 } else { /* IIO_VAL_INT_PLUS_MICRO or IIO_VAL_FRACTIONAL */572 *val = attr->vals[idx * 2];573 *val2 = attr->vals[idx * 2 + 1];574 }575 576 return attr->type;577}578 579static int bno055_set_regmask(struct bno055_priv *priv, int val, int val2,580 int reg, int mask, struct bno055_sysfs_attr *attr)581{582 const int shift = __ffs(mask);583 int best_delta;584 int req_val;585 int tbl_val;586 bool first;587 int delta;588 int hwval;589 int ret;590 int len;591 int i;592 593 /*594 * The closest value the HW supports is only one in fusion mode,595 * and it is autoselected, so don't do anything, just return OK,596 * as the closest possible value has been (virtually) selected597 */598 if (priv->operation_mode != BNO055_OPR_MODE_AMG)599 return 0;600 601 len = attr->len;602 603 /*604 * We always get a request in INT_PLUS_MICRO, but we605 * take care of the micro part only when we really have606 * non-integer tables. This prevents 32-bit overflow with607 * larger integers contained in integer tables.608 */609 req_val = val;610 if (attr->type != IIO_VAL_INT) {611 len /= 2;612 req_val = min(val, 2147) * 1000000 + val2;613 }614 615 first = true;616 for (i = 0; i < len; i++) {617 switch (attr->type) {618 case IIO_VAL_INT:619 tbl_val = attr->vals[i];620 break;621 case IIO_VAL_INT_PLUS_MICRO:622 WARN_ON(attr->vals[i * 2] > 2147);623 tbl_val = attr->vals[i * 2] * 1000000 +624 attr->vals[i * 2 + 1];625 break;626 case IIO_VAL_FRACTIONAL:627 WARN_ON(attr->vals[i * 2] > 4294);628 tbl_val = attr->vals[i * 2] * 1000000 /629 attr->vals[i * 2 + 1];630 break;631 default:632 return -EINVAL;633 }634 delta = abs(tbl_val - req_val);635 if (first || delta < best_delta) {636 best_delta = delta;637 hwval = i;638 first = false;639 }640 }641 642 if (attr->hw_xlate)643 hwval = attr->hw_xlate[hwval];644 645 ret = bno055_operation_mode_do_set(priv, BNO055_OPR_MODE_CONFIG);646 if (ret)647 return ret;648 649 ret = regmap_update_bits(priv->regmap, reg, mask, hwval << shift);650 if (ret)651 return ret;652 653 return bno055_operation_mode_do_set(priv, BNO055_OPR_MODE_AMG);654}655 656static int bno055_read_simple_chan(struct iio_dev *indio_dev,657 struct iio_chan_spec const *chan,658 int *val, int *val2, long mask)659{660 struct bno055_priv *priv = iio_priv(indio_dev);661 __le16 raw_val;662 int ret;663 664 switch (mask) {665 case IIO_CHAN_INFO_RAW:666 ret = regmap_bulk_read(priv->regmap, chan->address,667 &raw_val, sizeof(raw_val));668 if (ret < 0)669 return ret;670 *val = sign_extend32(le16_to_cpu(raw_val), 15);671 return IIO_VAL_INT;672 case IIO_CHAN_INFO_OFFSET:673 if (priv->operation_mode != BNO055_OPR_MODE_AMG) {674 *val = 0;675 } else {676 ret = regmap_bulk_read(priv->regmap,677 chan->address +678 BNO055_REG_OFFSET_ADDR,679 &raw_val, sizeof(raw_val));680 if (ret < 0)681 return ret;682 /*683 * IMU reports sensor offsets; IIO wants correction684 * offsets, thus we need the 'minus' here.685 */686 *val = -sign_extend32(le16_to_cpu(raw_val), 15);687 }688 return IIO_VAL_INT;689 case IIO_CHAN_INFO_SCALE:690 *val = 1;691 switch (chan->type) {692 case IIO_GRAVITY:693 /* Table 3-35: 1 m/s^2 = 100 LSB */694 case IIO_ACCEL:695 /* Table 3-17: 1 m/s^2 = 100 LSB */696 *val2 = 100;697 break;698 case IIO_MAGN:699 /*700 * Table 3-19: 1 uT = 16 LSB. But we need701 * Gauss: 1G = 0.1 uT.702 */703 *val2 = 160;704 break;705 case IIO_ANGL_VEL:706 /*707 * Table 3-22: 1 Rps = 900 LSB708 * .. but this is not exactly true. See comment at the709 * beginning of this file.710 */711 if (priv->operation_mode != BNO055_OPR_MODE_AMG) {712 *val = bno055_gyr_scale.fusion_vals[0];713 *val2 = bno055_gyr_scale.fusion_vals[1];714 return IIO_VAL_FRACTIONAL;715 }716 717 return bno055_get_regmask(priv, val, val2,718 BNO055_GYR_CONFIG_REG,719 BNO055_GYR_CONFIG_RANGE_MASK,720 &bno055_gyr_scale);721 break;722 case IIO_ROT:723 /* Table 3-28: 1 degree = 16 LSB */724 *val2 = 16;725 break;726 default:727 return -EINVAL;728 }729 return IIO_VAL_FRACTIONAL;730 731 case IIO_CHAN_INFO_SAMP_FREQ:732 if (chan->type != IIO_MAGN)733 return -EINVAL;734 735 return bno055_get_regmask(priv, val, val2,736 BNO055_MAG_CONFIG_REG,737 BNO055_MAG_CONFIG_ODR_MASK,738 &bno055_mag_odr);739 740 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:741 switch (chan->type) {742 case IIO_ANGL_VEL:743 return bno055_get_regmask(priv, val, val2,744 BNO055_GYR_CONFIG_REG,745 BNO055_GYR_CONFIG_LPF_MASK,746 &bno055_gyr_lpf);747 case IIO_ACCEL:748 return bno055_get_regmask(priv, val, val2,749 BNO055_ACC_CONFIG_REG,750 BNO055_ACC_CONFIG_LPF_MASK,751 &bno055_acc_lpf);752 default:753 return -EINVAL;754 }755 756 default:757 return -EINVAL;758 }759}760 761static int bno055_sysfs_attr_avail(struct bno055_priv *priv, struct bno055_sysfs_attr *attr,762 const int **vals, int *length)763{764 if (priv->operation_mode != BNO055_OPR_MODE_AMG) {765 /* locked when fusion enabled */766 *vals = attr->fusion_vals;767 if (attr->type == IIO_VAL_INT)768 *length = 1;769 else770 *length = 2; /* IIO_VAL_INT_PLUS_MICRO or IIO_VAL_FRACTIONAL*/771 } else {772 *vals = attr->vals;773 *length = attr->len;774 }775 776 return attr->type;777}778 779static int bno055_read_avail(struct iio_dev *indio_dev,780 struct iio_chan_spec const *chan,781 const int **vals, int *type, int *length,782 long mask)783{784 struct bno055_priv *priv = iio_priv(indio_dev);785 786 switch (mask) {787 case IIO_CHAN_INFO_SCALE:788 switch (chan->type) {789 case IIO_ANGL_VEL:790 *type = bno055_sysfs_attr_avail(priv, &bno055_gyr_scale,791 vals, length);792 return IIO_AVAIL_LIST;793 default:794 return -EINVAL;795 }796 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:797 switch (chan->type) {798 case IIO_ANGL_VEL:799 *type = bno055_sysfs_attr_avail(priv, &bno055_gyr_lpf,800 vals, length);801 return IIO_AVAIL_LIST;802 case IIO_ACCEL:803 *type = bno055_sysfs_attr_avail(priv, &bno055_acc_lpf,804 vals, length);805 return IIO_AVAIL_LIST;806 default:807 return -EINVAL;808 }809 810 break;811 case IIO_CHAN_INFO_SAMP_FREQ:812 switch (chan->type) {813 case IIO_MAGN:814 *type = bno055_sysfs_attr_avail(priv, &bno055_mag_odr,815 vals, length);816 return IIO_AVAIL_LIST;817 default:818 return -EINVAL;819 }820 default:821 return -EINVAL;822 }823}824 825static int bno055_read_temp_chan(struct iio_dev *indio_dev, int *val)826{827 struct bno055_priv *priv = iio_priv(indio_dev);828 unsigned int raw_val;829 int ret;830 831 ret = regmap_read(priv->regmap, BNO055_TEMP_REG, &raw_val);832 if (ret < 0)833 return ret;834 835 /*836 * Tables 3-36 and 3-37: one byte of priv, signed, 1 LSB = 1C.837 * ABI wants milliC.838 */839 *val = raw_val * 1000;840 841 return IIO_VAL_INT;842}843 844static int bno055_read_quaternion(struct iio_dev *indio_dev,845 struct iio_chan_spec const *chan,846 int size, int *vals, int *val_len,847 long mask)848{849 struct bno055_priv *priv = iio_priv(indio_dev);850 __le16 raw_vals[4];851 int i, ret;852 853 switch (mask) {854 case IIO_CHAN_INFO_RAW:855 if (size < 4)856 return -EINVAL;857 ret = regmap_bulk_read(priv->regmap,858 BNO055_QUAT_DATA_W_LSB_REG,859 raw_vals, sizeof(raw_vals));860 if (ret < 0)861 return ret;862 for (i = 0; i < 4; i++)863 vals[i] = sign_extend32(le16_to_cpu(raw_vals[i]), 15);864 *val_len = 4;865 return IIO_VAL_INT_MULTIPLE;866 case IIO_CHAN_INFO_SCALE:867 /* Table 3-31: 1 quaternion = 2^14 LSB */868 if (size < 2)869 return -EINVAL;870 vals[0] = 1;871 vals[1] = 14;872 return IIO_VAL_FRACTIONAL_LOG2;873 default:874 return -EINVAL;875 }876}877 878static bool bno055_is_chan_readable(struct iio_dev *indio_dev,879 struct iio_chan_spec const *chan)880{881 struct bno055_priv *priv = iio_priv(indio_dev);882 883 if (priv->operation_mode != BNO055_OPR_MODE_AMG)884 return true;885 886 switch (chan->type) {887 case IIO_GRAVITY:888 case IIO_ROT:889 return false;890 case IIO_ACCEL:891 if (chan->channel2 == IIO_MOD_LINEAR_X ||892 chan->channel2 == IIO_MOD_LINEAR_Y ||893 chan->channel2 == IIO_MOD_LINEAR_Z)894 return false;895 return true;896 default:897 return true;898 }899}900 901static int _bno055_read_raw_multi(struct iio_dev *indio_dev,902 struct iio_chan_spec const *chan,903 int size, int *vals, int *val_len,904 long mask)905{906 if (!bno055_is_chan_readable(indio_dev, chan))907 return -EBUSY;908 909 switch (chan->type) {910 case IIO_MAGN:911 case IIO_ACCEL:912 case IIO_ANGL_VEL:913 case IIO_GRAVITY:914 if (size < 2)915 return -EINVAL;916 *val_len = 2;917 return bno055_read_simple_chan(indio_dev, chan,918 &vals[0], &vals[1],919 mask);920 case IIO_TEMP:921 *val_len = 1;922 return bno055_read_temp_chan(indio_dev, &vals[0]);923 case IIO_ROT:924 /*925 * Rotation is exposed as either a quaternion or three926 * Euler angles.927 */928 if (chan->channel2 == IIO_MOD_QUATERNION)929 return bno055_read_quaternion(indio_dev, chan,930 size, vals,931 val_len, mask);932 if (size < 2)933 return -EINVAL;934 *val_len = 2;935 return bno055_read_simple_chan(indio_dev, chan,936 &vals[0], &vals[1],937 mask);938 default:939 return -EINVAL;940 }941}942 943static int bno055_read_raw_multi(struct iio_dev *indio_dev,944 struct iio_chan_spec const *chan,945 int size, int *vals, int *val_len,946 long mask)947{948 struct bno055_priv *priv = iio_priv(indio_dev);949 int ret;950 951 mutex_lock(&priv->lock);952 ret = _bno055_read_raw_multi(indio_dev, chan, size,953 vals, val_len, mask);954 mutex_unlock(&priv->lock);955 return ret;956}957 958static int _bno055_write_raw(struct iio_dev *iio_dev,959 struct iio_chan_spec const *chan,960 int val, int val2, long mask)961{962 struct bno055_priv *priv = iio_priv(iio_dev);963 964 switch (chan->type) {965 case IIO_MAGN:966 switch (mask) {967 case IIO_CHAN_INFO_SAMP_FREQ:968 return bno055_set_regmask(priv, val, val2,969 BNO055_MAG_CONFIG_REG,970 BNO055_MAG_CONFIG_ODR_MASK,971 &bno055_mag_odr);972 default:973 return -EINVAL;974 }975 case IIO_ACCEL:976 switch (mask) {977 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:978 return bno055_set_regmask(priv, val, val2,979 BNO055_ACC_CONFIG_REG,980 BNO055_ACC_CONFIG_LPF_MASK,981 &bno055_acc_lpf);982 983 default:984 return -EINVAL;985 }986 case IIO_ANGL_VEL:987 switch (mask) {988 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:989 return bno055_set_regmask(priv, val, val2,990 BNO055_GYR_CONFIG_REG,991 BNO055_GYR_CONFIG_LPF_MASK,992 &bno055_gyr_lpf);993 case IIO_CHAN_INFO_SCALE:994 return bno055_set_regmask(priv, val, val2,995 BNO055_GYR_CONFIG_REG,996 BNO055_GYR_CONFIG_RANGE_MASK,997 &bno055_gyr_scale);998 default:999 return -EINVAL;1000 }1001 default:1002 return -EINVAL;1003 }1004}1005 1006static int bno055_write_raw(struct iio_dev *iio_dev,1007 struct iio_chan_spec const *chan,1008 int val, int val2, long mask)1009{1010 struct bno055_priv *priv = iio_priv(iio_dev);1011 int ret;1012 1013 mutex_lock(&priv->lock);1014 ret = _bno055_write_raw(iio_dev, chan, val, val2, mask);1015 mutex_unlock(&priv->lock);1016 1017 return ret;1018}1019 1020static ssize_t in_accel_range_raw_available_show(struct device *dev,1021 struct device_attribute *attr,1022 char *buf)1023{1024 struct bno055_priv *priv = iio_priv(dev_to_iio_dev(dev));1025 int len = 0;1026 int i;1027 1028 if (priv->operation_mode != BNO055_OPR_MODE_AMG)1029 return sysfs_emit(buf, "%d\n", bno055_acc_range.fusion_vals[0]);1030 1031 for (i = 0; i < bno055_acc_range.len; i++)1032 len += sysfs_emit_at(buf, len, "%d ", bno055_acc_range.vals[i]);1033 buf[len - 1] = '\n';1034 1035 return len;1036}1037 1038static ssize_t fusion_enable_show(struct device *dev,1039 struct device_attribute *attr,1040 char *buf)1041{1042 struct bno055_priv *priv = iio_priv(dev_to_iio_dev(dev));1043 1044 return sysfs_emit(buf, "%d\n",1045 priv->operation_mode != BNO055_OPR_MODE_AMG);1046}1047 1048static ssize_t fusion_enable_store(struct device *dev,1049 struct device_attribute *attr,1050 const char *buf, size_t len)1051{1052 struct iio_dev *indio_dev = dev_to_iio_dev(dev);1053 struct bno055_priv *priv = iio_priv(indio_dev);1054 bool en;1055 int ret;1056 1057 if (indio_dev->active_scan_mask &&1058 !bitmap_empty(indio_dev->active_scan_mask, _BNO055_SCAN_MAX))1059 return -EBUSY;1060 1061 ret = kstrtobool(buf, &en);1062 if (ret)1063 return -EINVAL;1064 1065 if (!en)1066 return bno055_operation_mode_set(priv, BNO055_OPR_MODE_AMG) ?: len;1067 1068 /*1069 * Coming from AMG means the FMC was off, just switch to fusion but1070 * don't change anything that doesn't belong to us (i.e let FMC stay off).1071 * Coming from any other fusion mode means we don't need to do anything.1072 */1073 if (priv->operation_mode == BNO055_OPR_MODE_AMG)1074 return bno055_operation_mode_set(priv, BNO055_OPR_MODE_FUSION_FMC_OFF) ?: len;1075 1076 return len;1077}1078 1079static ssize_t in_magn_calibration_fast_enable_show(struct device *dev,1080 struct device_attribute *attr,1081 char *buf)1082{1083 struct bno055_priv *priv = iio_priv(dev_to_iio_dev(dev));1084 1085 return sysfs_emit(buf, "%d\n",1086 priv->operation_mode == BNO055_OPR_MODE_FUSION);1087}1088 1089static ssize_t in_magn_calibration_fast_enable_store(struct device *dev,1090 struct device_attribute *attr,1091 const char *buf, size_t len)1092{1093 struct iio_dev *indio_dev = dev_to_iio_dev(dev);1094 struct bno055_priv *priv = iio_priv(indio_dev);1095 int ret;1096 1097 if (indio_dev->active_scan_mask &&1098 !bitmap_empty(indio_dev->active_scan_mask, _BNO055_SCAN_MAX))1099 return -EBUSY;1100 1101 if (sysfs_streq(buf, "0")) {1102 if (priv->operation_mode == BNO055_OPR_MODE_FUSION) {1103 ret = bno055_operation_mode_set(priv, BNO055_OPR_MODE_FUSION_FMC_OFF);1104 if (ret)1105 return ret;1106 }1107 } else {1108 if (priv->operation_mode == BNO055_OPR_MODE_AMG)1109 return -EINVAL;1110 1111 if (priv->operation_mode != BNO055_OPR_MODE_FUSION) {1112 ret = bno055_operation_mode_set(priv, BNO055_OPR_MODE_FUSION);1113 if (ret)1114 return ret;1115 }1116 }1117 1118 return len;1119}1120 1121static ssize_t in_accel_range_raw_show(struct device *dev,1122 struct device_attribute *attr,1123 char *buf)1124{1125 struct bno055_priv *priv = iio_priv(dev_to_iio_dev(dev));1126 int val;1127 int ret;1128 1129 ret = bno055_get_regmask(priv, &val, NULL,1130 BNO055_ACC_CONFIG_REG,1131 BNO055_ACC_CONFIG_RANGE_MASK,1132 &bno055_acc_range);1133 if (ret < 0)1134 return ret;1135 1136 return sysfs_emit(buf, "%d\n", val);1137}1138 1139static ssize_t in_accel_range_raw_store(struct device *dev,1140 struct device_attribute *attr,1141 const char *buf, size_t len)1142{1143 struct bno055_priv *priv = iio_priv(dev_to_iio_dev(dev));1144 unsigned long val;1145 int ret;1146 1147 ret = kstrtoul(buf, 10, &val);1148 if (ret)1149 return ret;1150 1151 mutex_lock(&priv->lock);1152 ret = bno055_set_regmask(priv, val, 0,1153 BNO055_ACC_CONFIG_REG,1154 BNO055_ACC_CONFIG_RANGE_MASK,1155 &bno055_acc_range);1156 mutex_unlock(&priv->lock);1157 1158 return ret ?: len;1159}1160 1161static ssize_t bno055_get_calib_status(struct device *dev, char *buf, int which)1162{1163 struct bno055_priv *priv = iio_priv(dev_to_iio_dev(dev));1164 int calib;1165 int ret;1166 int val;1167 1168 if (priv->operation_mode == BNO055_OPR_MODE_AMG ||1169 (priv->operation_mode == BNO055_OPR_MODE_FUSION_FMC_OFF &&1170 which == BNO055_CALIB_STAT_MAGN_SHIFT)) {1171 calib = 0;1172 } else {1173 mutex_lock(&priv->lock);1174 ret = regmap_read(priv->regmap, BNO055_CALIB_STAT_REG, &val);1175 mutex_unlock(&priv->lock);1176 1177 if (ret)1178 return -EIO;1179 1180 calib = ((val >> which) & GENMASK(1, 0)) + 1;1181 }1182 1183 return sysfs_emit(buf, "%d\n", calib);1184}1185 1186static ssize_t serialnumber_show(struct device *dev,1187 struct device_attribute *attr,1188 char *buf)1189{1190 struct bno055_priv *priv = iio_priv(dev_to_iio_dev(dev));1191 1192 return sysfs_emit(buf, "%*ph\n", BNO055_UID_LEN, priv->uid);1193}1194 1195static ssize_t calibration_data_read(struct file *filp, struct kobject *kobj,1196 struct bin_attribute *bin_attr, char *buf,1197 loff_t pos, size_t count)1198{1199 struct bno055_priv *priv = iio_priv(dev_to_iio_dev(kobj_to_dev(kobj)));1200 u8 data[BNO055_CALDATA_LEN];1201 int ret;1202 1203 /*1204 * Calibration data is volatile; reading it in chunks will possibly1205 * results in inconsistent data. We require the user to read the whole1206 * blob in a single chunk1207 */1208 if (count < BNO055_CALDATA_LEN || pos)1209 return -EINVAL;1210 1211 mutex_lock(&priv->lock);1212 ret = bno055_operation_mode_do_set(priv, BNO055_OPR_MODE_CONFIG);1213 if (ret)1214 goto exit_unlock;1215 1216 ret = regmap_bulk_read(priv->regmap, BNO055_CALDATA_START, data,1217 BNO055_CALDATA_LEN);1218 if (ret)1219 goto exit_unlock;1220 1221 ret = bno055_operation_mode_do_set(priv, priv->operation_mode);1222 if (ret)1223 goto exit_unlock;1224 1225 memcpy(buf, data, BNO055_CALDATA_LEN);1226 1227 ret = BNO055_CALDATA_LEN;1228exit_unlock:1229 mutex_unlock(&priv->lock);1230 return ret;1231}1232 1233static ssize_t sys_calibration_auto_status_show(struct device *dev,1234 struct device_attribute *a,1235 char *buf)1236{1237 return bno055_get_calib_status(dev, buf, BNO055_CALIB_STAT_SYS_SHIFT);1238}1239 1240static ssize_t in_accel_calibration_auto_status_show(struct device *dev,1241 struct device_attribute *a,1242 char *buf)1243{1244 return bno055_get_calib_status(dev, buf, BNO055_CALIB_STAT_ACCEL_SHIFT);1245}1246 1247static ssize_t in_gyro_calibration_auto_status_show(struct device *dev,1248 struct device_attribute *a,1249 char *buf)1250{1251 return bno055_get_calib_status(dev, buf, BNO055_CALIB_STAT_GYRO_SHIFT);1252}1253 1254static ssize_t in_magn_calibration_auto_status_show(struct device *dev,1255 struct device_attribute *a,1256 char *buf)1257{1258 return bno055_get_calib_status(dev, buf, BNO055_CALIB_STAT_MAGN_SHIFT);1259}1260 1261static int bno055_debugfs_reg_access(struct iio_dev *iio_dev, unsigned int reg,1262 unsigned int writeval, unsigned int *readval)1263{1264 struct bno055_priv *priv = iio_priv(iio_dev);1265 1266 if (readval)1267 return regmap_read(priv->regmap, reg, readval);1268 else1269 return regmap_write(priv->regmap, reg, writeval);1270}1271 1272static ssize_t bno055_show_fw_version(struct file *file, char __user *userbuf,1273 size_t count, loff_t *ppos)1274{1275 struct bno055_priv *priv = file->private_data;1276 int rev, ver;1277 char *buf;1278 int ret;1279 1280 ret = regmap_read(priv->regmap, BNO055_SW_REV_LSB_REG, &rev);1281 if (ret)1282 return ret;1283 1284 ret = regmap_read(priv->regmap, BNO055_SW_REV_MSB_REG, &ver);1285 if (ret)1286 return ret;1287 1288 buf = kasprintf(GFP_KERNEL, "ver: 0x%x, rev: 0x%x\n", ver, rev);1289 if (!buf)1290 return -ENOMEM;1291 1292 ret = simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));1293 kfree(buf);1294 1295 return ret;1296}1297 1298static const struct file_operations bno055_fw_version_ops = {1299 .open = simple_open,1300 .read = bno055_show_fw_version,1301 .llseek = default_llseek,1302 .owner = THIS_MODULE,1303};1304 1305static void bno055_debugfs_remove(void *_priv)1306{1307 struct bno055_priv *priv = _priv;1308 1309 debugfs_remove(priv->debugfs);1310 priv->debugfs = NULL;1311}1312 1313static void bno055_debugfs_init(struct iio_dev *iio_dev)1314{1315 struct bno055_priv *priv = iio_priv(iio_dev);1316 1317 priv->debugfs = debugfs_create_file("firmware_version", 0400,1318 iio_get_debugfs_dentry(iio_dev),1319 priv, &bno055_fw_version_ops);1320 if (!IS_ERR(priv->debugfs))1321 devm_add_action_or_reset(priv->dev, bno055_debugfs_remove,1322 priv);1323 if (IS_ERR_OR_NULL(priv->debugfs))1324 dev_warn(priv->dev, "failed to setup debugfs");1325}1326 1327static IIO_DEVICE_ATTR_RW(fusion_enable, 0);1328static IIO_DEVICE_ATTR_RW(in_magn_calibration_fast_enable, 0);1329static IIO_DEVICE_ATTR_RW(in_accel_range_raw, 0);1330 1331static IIO_DEVICE_ATTR_RO(in_accel_range_raw_available, 0);1332static IIO_DEVICE_ATTR_RO(sys_calibration_auto_status, 0);1333static IIO_DEVICE_ATTR_RO(in_accel_calibration_auto_status, 0);1334static IIO_DEVICE_ATTR_RO(in_gyro_calibration_auto_status, 0);1335static IIO_DEVICE_ATTR_RO(in_magn_calibration_auto_status, 0);1336static IIO_DEVICE_ATTR_RO(serialnumber, 0);1337 1338static struct attribute *bno055_attrs[] = {1339 &iio_dev_attr_in_accel_range_raw_available.dev_attr.attr,1340 &iio_dev_attr_in_accel_range_raw.dev_attr.attr,1341 &iio_dev_attr_fusion_enable.dev_attr.attr,1342 &iio_dev_attr_in_magn_calibration_fast_enable.dev_attr.attr,1343 &iio_dev_attr_sys_calibration_auto_status.dev_attr.attr,1344 &iio_dev_attr_in_accel_calibration_auto_status.dev_attr.attr,1345 &iio_dev_attr_in_gyro_calibration_auto_status.dev_attr.attr,1346 &iio_dev_attr_in_magn_calibration_auto_status.dev_attr.attr,1347 &iio_dev_attr_serialnumber.dev_attr.attr,1348 NULL1349};1350 1351static BIN_ATTR_RO(calibration_data, BNO055_CALDATA_LEN);1352 1353static struct bin_attribute *bno055_bin_attrs[] = {1354 &bin_attr_calibration_data,1355 NULL1356};1357 1358static const struct attribute_group bno055_attrs_group = {1359 .attrs = bno055_attrs,1360 .bin_attrs = bno055_bin_attrs,1361};1362 1363static const struct iio_info bno055_info = {1364 .read_raw_multi = bno055_read_raw_multi,1365 .read_avail = bno055_read_avail,1366 .write_raw = bno055_write_raw,1367 .attrs = &bno055_attrs_group,1368 .debugfs_reg_access = bno055_debugfs_reg_access,1369};1370 1371/*1372 * Reads len samples from the HW, stores them in buf starting from buf_idx,1373 * and applies mask to cull (skip) unneeded samples.1374 * Updates buf_idx incrementing with the number of stored samples.1375 * Samples from HW are transferred into buf, then in-place copy on buf is1376 * performed in order to cull samples that need to be skipped.1377 * This avoids copies of the first samples until we hit the 1st sample to skip,1378 * and also avoids having an extra bounce buffer.1379 * buf must be able to contain len elements in spite of how many samples we are1380 * going to cull.1381 */1382static int bno055_scan_xfer(struct bno055_priv *priv,1383 int start_ch, int len, unsigned long mask,1384 __le16 *buf, int *buf_idx)1385{1386 const int base = BNO055_ACC_DATA_X_LSB_REG;1387 bool quat_in_read = false;1388 int buf_base = *buf_idx;1389 __le16 *dst, *src;1390 int offs_fixup = 0;1391 int xfer_len = len;1392 int ret;1393 int i, n;1394 1395 if (!mask)1396 return 0;1397 1398 /*1399 * All channels are made up 1 16-bit sample, except for quaternion that1400 * is made up 4 16-bit values.1401 * For us the quaternion CH is just like 4 regular CHs.1402 * If our read starts past the quaternion make sure to adjust the1403 * starting offset; if the quaternion is contained in our scan then make1404 * sure to adjust the read len.1405 */1406 if (start_ch > BNO055_SCAN_QUATERNION) {1407 start_ch += 3;1408 } else if ((start_ch <= BNO055_SCAN_QUATERNION) &&1409 ((start_ch + len) > BNO055_SCAN_QUATERNION)) {1410 quat_in_read = true;1411 xfer_len += 3;1412 }1413 1414 ret = regmap_bulk_read(priv->regmap,1415 base + start_ch * sizeof(__le16),1416 buf + buf_base,1417 xfer_len * sizeof(__le16));1418 if (ret)1419 return ret;1420 1421 for_each_set_bit(i, &mask, len) {1422 if (quat_in_read && ((start_ch + i) > BNO055_SCAN_QUATERNION))1423 offs_fixup = 3;1424 1425 dst = buf + *buf_idx;1426 src = buf + buf_base + offs_fixup + i;1427 1428 n = (start_ch + i == BNO055_SCAN_QUATERNION) ? 4 : 1;1429 1430 if (dst != src)1431 memcpy(dst, src, n * sizeof(__le16));1432 1433 *buf_idx += n;1434 }1435 return 0;1436}1437 1438static irqreturn_t bno055_trigger_handler(int irq, void *p)1439{1440 struct iio_poll_func *pf = p;1441 struct iio_dev *iio_dev = pf->indio_dev;1442 struct bno055_priv *priv = iio_priv(iio_dev);1443 int xfer_start, start, end, prev_end;1444 unsigned long mask;1445 int quat_extra_len;1446 bool first = true;1447 int buf_idx = 0;1448 bool thr_hit;1449 int ret;1450 1451 mutex_lock(&priv->lock);1452 1453 /*1454 * Walk the bitmap and eventually perform several transfers.1455 * Bitmap ones-fields that are separated by gaps <= xfer_burst_break_thr1456 * will be included in same transfer.1457 * Every time the bitmap contains a gap wider than xfer_burst_break_thr1458 * then we split the transfer, skipping the gap.1459 */1460 for_each_set_bitrange(start, end, iio_dev->active_scan_mask,1461 iio_get_masklength(iio_dev)) {1462 /*1463 * First transfer will start from the beginning of the first1464 * ones-field in the bitmap1465 */1466 if (first) {1467 xfer_start = start;1468 } else {1469 /*1470 * We found the next ones-field; check whether to1471 * include it in * the current transfer or not (i.e.1472 * let's perform the current * transfer and prepare for1473 * another one).1474 */1475 1476 /*1477 * In case the zeros-gap contains the quaternion bit,1478 * then its length is actually 4 words instead of 11479 * (i.e. +3 wrt other channels).1480 */1481 quat_extra_len = ((start > BNO055_SCAN_QUATERNION) &&1482 (prev_end <= BNO055_SCAN_QUATERNION)) ? 3 : 0;1483 1484 /* If the gap is wider than xfer_burst_break_thr then.. */1485 thr_hit = (start - prev_end + quat_extra_len) >1486 priv->xfer_burst_break_thr;1487 1488 /*1489 * .. transfer all the data up to the gap. Then set the1490 * next transfer start index at right after the gap1491 * (i.e. at the start of this ones-field).1492 */1493 if (thr_hit) {1494 mask = *iio_dev->active_scan_mask >> xfer_start;1495 ret = bno055_scan_xfer(priv, xfer_start,1496 prev_end - xfer_start,1497 mask, priv->buf.chans, &buf_idx);1498 if (ret)1499 goto done;1500 xfer_start = start;1501 }1502 }1503 first = false;1504 prev_end = end;1505 }1506 1507 /*1508 * We finished walking the bitmap; no more gaps to check for. Just1509 * perform the current transfer.1510 */1511 mask = *iio_dev->active_scan_mask >> xfer_start;1512 ret = bno055_scan_xfer(priv, xfer_start,1513 prev_end - xfer_start,1514 mask, priv->buf.chans, &buf_idx);1515 1516 if (!ret)1517 iio_push_to_buffers_with_timestamp(iio_dev,1518 &priv->buf, pf->timestamp);1519done:1520 mutex_unlock(&priv->lock);1521 iio_trigger_notify_done(iio_dev->trig);1522 return IRQ_HANDLED;1523}1524 1525static int bno055_buffer_preenable(struct iio_dev *indio_dev)1526{1527 struct bno055_priv *priv = iio_priv(indio_dev);1528 const unsigned long fusion_mask =1529 BIT(BNO055_SCAN_YAW) |1530 BIT(BNO055_SCAN_ROLL) |1531 BIT(BNO055_SCAN_PITCH) |1532 BIT(BNO055_SCAN_QUATERNION) |1533 BIT(BNO055_SCAN_LIA_X) |1534 BIT(BNO055_SCAN_LIA_Y) |1535 BIT(BNO055_SCAN_LIA_Z) |1536 BIT(BNO055_SCAN_GRAVITY_X) |1537 BIT(BNO055_SCAN_GRAVITY_Y) |1538 BIT(BNO055_SCAN_GRAVITY_Z);1539 1540 if (priv->operation_mode == BNO055_OPR_MODE_AMG &&1541 bitmap_intersects(indio_dev->active_scan_mask, &fusion_mask,1542 _BNO055_SCAN_MAX))1543 return -EBUSY;1544 return 0;1545}1546 1547static const struct iio_buffer_setup_ops bno055_buffer_setup_ops = {1548 .preenable = bno055_buffer_preenable,1549};1550 1551int bno055_probe(struct device *dev, struct regmap *regmap,1552 int xfer_burst_break_thr, bool sw_reset)1553{1554 const struct firmware *caldata = NULL;1555 struct bno055_priv *priv;1556 struct iio_dev *iio_dev;1557 char *fw_name_buf;1558 unsigned int val;1559 int rev, ver;1560 int ret;1561 1562 iio_dev = devm_iio_device_alloc(dev, sizeof(*priv));1563 if (!iio_dev)1564 return -ENOMEM;1565 1566 iio_dev->name = "bno055";1567 priv = iio_priv(iio_dev);1568 mutex_init(&priv->lock);1569 priv->regmap = regmap;1570 priv->dev = dev;1571 priv->xfer_burst_break_thr = xfer_burst_break_thr;1572 priv->sw_reset = sw_reset;1573 1574 priv->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);1575 if (IS_ERR(priv->reset_gpio))1576 return dev_err_probe(dev, PTR_ERR(priv->reset_gpio), "Failed to get reset GPIO\n");1577 1578 priv->clk = devm_clk_get_optional_enabled(dev, "clk");1579 if (IS_ERR(priv->clk))1580 return dev_err_probe(dev, PTR_ERR(priv->clk), "Failed to get CLK\n");1581 1582 if (priv->reset_gpio) {1583 usleep_range(5000, 10000);1584 gpiod_set_value_cansleep(priv->reset_gpio, 1);1585 usleep_range(650000, 750000);1586 } else if (!sw_reset) {1587 dev_warn(dev, "No usable reset method; IMU may be unreliable\n");1588 }1589 1590 ret = regmap_read(priv->regmap, BNO055_CHIP_ID_REG, &val);1591 if (ret)1592 return ret;1593 1594 if (val != BNO055_CHIP_ID_MAGIC)1595 dev_warn(dev, "Unrecognized chip ID 0x%x\n", val);1596 1597 /*1598 * In case we haven't a HW reset pin, we can still reset the chip via1599 * register write. This is probably nonsense in case we can't even1600 * communicate with the chip or the chip isn't the one we expect (i.e.1601 * we don't write to unknown chips), so we perform SW reset only after1602 * chip magic ID check1603 */1604 if (!priv->reset_gpio) {1605 ret = bno055_system_reset(priv);1606 if (ret)1607 return ret;1608 }1609 1610 ret = regmap_read(priv->regmap, BNO055_SW_REV_LSB_REG, &rev);1611 if (ret)1612 return ret;1613 1614 ret = regmap_read(priv->regmap, BNO055_SW_REV_MSB_REG, &ver);1615 if (ret)1616 return ret;1617 1618 /*1619 * The stock FW version contains a bug (see comment at the beginning of1620 * this file) that causes the anglvel scale to be changed depending on1621 * the chip range setting. We workaround this, but we don't know what1622 * other FW versions might do.1623 */1624 if (ver != 0x3 || rev != 0x11)1625 dev_warn(dev, "Untested firmware version. Anglvel scale may not work as expected\n");1626 1627 ret = regmap_bulk_read(priv->regmap, BNO055_UID_LOWER_REG,1628 priv->uid, BNO055_UID_LEN);1629 if (ret)1630 return ret;1631 1632 /* Sensor calibration data */1633 fw_name_buf = kasprintf(GFP_KERNEL, BNO055_FW_UID_FMT,1634 BNO055_UID_LEN, priv->uid);1635 if (!fw_name_buf)1636 return -ENOMEM;1637 1638 ret = request_firmware(&caldata, fw_name_buf, dev);1639 kfree(fw_name_buf);1640 if (ret)1641 ret = request_firmware(&caldata, BNO055_FW_GENERIC_NAME, dev);1642 if (ret) {1643 dev_notice(dev, "Calibration file load failed. See instruction in kernel Documentation/iio/bno055.rst\n");1644 ret = bno055_init(priv, NULL, 0);1645 } else {1646 ret = bno055_init(priv, caldata->data, caldata->size);1647 release_firmware(caldata);1648 }1649 if (ret)1650 return ret;1651 1652 priv->operation_mode = BNO055_OPR_MODE_FUSION;1653 ret = bno055_operation_mode_do_set(priv, priv->operation_mode);1654 if (ret)1655 return ret;1656 1657 ret = devm_add_action_or_reset(dev, bno055_uninit, priv);1658 if (ret)1659 return ret;1660 1661 iio_dev->channels = bno055_channels;1662 iio_dev->num_channels = ARRAY_SIZE(bno055_channels);1663 iio_dev->info = &bno055_info;1664 iio_dev->modes = INDIO_DIRECT_MODE;1665 1666 ret = devm_iio_triggered_buffer_setup(dev, iio_dev,1667 iio_pollfunc_store_time,1668 bno055_trigger_handler,1669 &bno055_buffer_setup_ops);1670 if (ret)1671 return ret;1672 1673 ret = devm_iio_device_register(dev, iio_dev);1674 if (ret)1675 return ret;1676 1677 bno055_debugfs_init(iio_dev);1678 1679 return 0;1680}1681EXPORT_SYMBOL_NS_GPL(bno055_probe, IIO_BNO055);1682 1683MODULE_AUTHOR("Andrea Merello <andrea.merello@iit.it>");1684MODULE_DESCRIPTION("Bosch BNO055 driver");1685MODULE_LICENSE("GPL");1686