bmi088-accel-core.c (14518B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * 3-axis accelerometer driver supporting following Bosch-Sensortec chips: 4 * - BMI088 5 * 6 * Copyright (c) 2018-2021, Topic Embedded Products 7 */ 8 9#include <linux/delay.h> 10#include <linux/iio/iio.h> 11#include <linux/iio/sysfs.h> 12#include <linux/interrupt.h> 13#include <linux/module.h> 14#include <linux/pm.h> 15#include <linux/pm_runtime.h> 16#include <linux/regmap.h> 17#include <linux/slab.h> 18#include <asm/unaligned.h> 19 20#include "bmi088-accel.h" 21 22#define BMI088_ACCEL_REG_CHIP_ID 0x00 23#define BMI088_ACCEL_REG_ERROR 0x02 24 25#define BMI088_ACCEL_REG_INT_STATUS 0x1D 26#define BMI088_ACCEL_INT_STATUS_BIT_DRDY BIT(7) 27 28#define BMI088_ACCEL_REG_RESET 0x7E 29#define BMI088_ACCEL_RESET_VAL 0xB6 30 31#define BMI088_ACCEL_REG_PWR_CTRL 0x7D 32#define BMI088_ACCEL_REG_PWR_CONF 0x7C 33 34#define BMI088_ACCEL_REG_INT_MAP_DATA 0x58 35#define BMI088_ACCEL_INT_MAP_DATA_BIT_INT1_DRDY BIT(2) 36#define BMI088_ACCEL_INT_MAP_DATA_BIT_INT2_FWM BIT(5) 37 38#define BMI088_ACCEL_REG_INT1_IO_CONF 0x53 39#define BMI088_ACCEL_INT1_IO_CONF_BIT_ENABLE_OUT BIT(3) 40#define BMI088_ACCEL_INT1_IO_CONF_BIT_LVL BIT(1) 41 42#define BMI088_ACCEL_REG_INT2_IO_CONF 0x54 43#define BMI088_ACCEL_INT2_IO_CONF_BIT_ENABLE_OUT BIT(3) 44#define BMI088_ACCEL_INT2_IO_CONF_BIT_LVL BIT(1) 45 46#define BMI088_ACCEL_REG_ACC_CONF 0x40 47#define BMI088_ACCEL_MODE_ODR_MASK 0x0f 48 49#define BMI088_ACCEL_REG_ACC_RANGE 0x41 50#define BMI088_ACCEL_RANGE_3G 0x00 51#define BMI088_ACCEL_RANGE_6G 0x01 52#define BMI088_ACCEL_RANGE_12G 0x02 53#define BMI088_ACCEL_RANGE_24G 0x03 54 55#define BMI088_ACCEL_REG_TEMP 0x22 56#define BMI088_ACCEL_REG_TEMP_SHIFT 5 57#define BMI088_ACCEL_TEMP_UNIT 125 58#define BMI088_ACCEL_TEMP_OFFSET 23000 59 60#define BMI088_ACCEL_REG_XOUT_L 0x12 61#define BMI088_ACCEL_AXIS_TO_REG(axis) \ 62 (BMI088_ACCEL_REG_XOUT_L + (axis * 2)) 63 64#define BMI088_ACCEL_MAX_STARTUP_TIME_US 1000 65#define BMI088_AUTO_SUSPEND_DELAY_MS 2000 66 67#define BMI088_ACCEL_REG_FIFO_STATUS 0x0E 68#define BMI088_ACCEL_REG_FIFO_CONFIG0 0x48 69#define BMI088_ACCEL_REG_FIFO_CONFIG1 0x49 70#define BMI088_ACCEL_REG_FIFO_DATA 0x3F 71#define BMI088_ACCEL_FIFO_LENGTH 100 72 73#define BMI088_ACCEL_FIFO_MODE_FIFO 0x40 74#define BMI088_ACCEL_FIFO_MODE_STREAM 0x80 75 76enum bmi088_accel_axis { 77 AXIS_X, 78 AXIS_Y, 79 AXIS_Z, 80}; 81 82static const int bmi088_sample_freqs[] = { 83 12, 500000, 84 25, 0, 85 50, 0, 86 100, 0, 87 200, 0, 88 400, 0, 89 800, 0, 90 1600, 0, 91}; 92 93/* Available OSR (over sampling rate) sets the 3dB cut-off frequency */ 94enum bmi088_osr_modes { 95 BMI088_ACCEL_MODE_OSR_NORMAL = 0xA, 96 BMI088_ACCEL_MODE_OSR_2 = 0x9, 97 BMI088_ACCEL_MODE_OSR_4 = 0x8, 98}; 99 100/* Available ODR (output data rates) in Hz */ 101enum bmi088_odr_modes { 102 BMI088_ACCEL_MODE_ODR_12_5 = 0x5, 103 BMI088_ACCEL_MODE_ODR_25 = 0x6, 104 BMI088_ACCEL_MODE_ODR_50 = 0x7, 105 BMI088_ACCEL_MODE_ODR_100 = 0x8, 106 BMI088_ACCEL_MODE_ODR_200 = 0x9, 107 BMI088_ACCEL_MODE_ODR_400 = 0xa, 108 BMI088_ACCEL_MODE_ODR_800 = 0xb, 109 BMI088_ACCEL_MODE_ODR_1600 = 0xc, 110}; 111 112struct bmi088_scale_info { 113 int scale; 114 u8 reg_range; 115}; 116 117struct bmi088_accel_chip_info { 118 const char *name; 119 u8 chip_id; 120 const struct iio_chan_spec *channels; 121 int num_channels; 122}; 123 124struct bmi088_accel_data { 125 struct regmap *regmap; 126 const struct bmi088_accel_chip_info *chip_info; 127 u8 buffer[2] ____cacheline_aligned; /* shared DMA safe buffer */ 128}; 129 130static const struct regmap_range bmi088_volatile_ranges[] = { 131 /* All registers below 0x40 are volatile, except the CHIP ID. */ 132 regmap_reg_range(BMI088_ACCEL_REG_ERROR, 0x3f), 133 /* Mark the RESET as volatile too, it is self-clearing */ 134 regmap_reg_range(BMI088_ACCEL_REG_RESET, BMI088_ACCEL_REG_RESET), 135}; 136 137static const struct regmap_access_table bmi088_volatile_table = { 138 .yes_ranges = bmi088_volatile_ranges, 139 .n_yes_ranges = ARRAY_SIZE(bmi088_volatile_ranges), 140}; 141 142const struct regmap_config bmi088_regmap_conf = { 143 .reg_bits = 8, 144 .val_bits = 8, 145 .max_register = 0x7E, 146 .volatile_table = &bmi088_volatile_table, 147 .cache_type = REGCACHE_RBTREE, 148}; 149EXPORT_SYMBOL_NS_GPL(bmi088_regmap_conf, IIO_BMI088); 150 151static int bmi088_accel_power_up(struct bmi088_accel_data *data) 152{ 153 int ret; 154 155 /* Enable accelerometer and temperature sensor */ 156 ret = regmap_write(data->regmap, BMI088_ACCEL_REG_PWR_CTRL, 0x4); 157 if (ret) 158 return ret; 159 160 /* Datasheet recommends to wait at least 5ms before communication */ 161 usleep_range(5000, 6000); 162 163 /* Disable suspend mode */ 164 ret = regmap_write(data->regmap, BMI088_ACCEL_REG_PWR_CONF, 0x0); 165 if (ret) 166 return ret; 167 168 /* Recommended at least 1ms before further communication */ 169 usleep_range(1000, 1200); 170 171 return 0; 172} 173 174static int bmi088_accel_power_down(struct bmi088_accel_data *data) 175{ 176 int ret; 177 178 /* Enable suspend mode */ 179 ret = regmap_write(data->regmap, BMI088_ACCEL_REG_PWR_CONF, 0x3); 180 if (ret) 181 return ret; 182 183 /* Recommended at least 1ms before further communication */ 184 usleep_range(1000, 1200); 185 186 /* Disable accelerometer and temperature sensor */ 187 ret = regmap_write(data->regmap, BMI088_ACCEL_REG_PWR_CTRL, 0x0); 188 if (ret) 189 return ret; 190 191 /* Datasheet recommends to wait at least 5ms before communication */ 192 usleep_range(5000, 6000); 193 194 return 0; 195} 196 197static int bmi088_accel_get_sample_freq(struct bmi088_accel_data *data, 198 int *val, int *val2) 199{ 200 unsigned int value; 201 int ret; 202 203 ret = regmap_read(data->regmap, BMI088_ACCEL_REG_ACC_CONF, 204 &value); 205 if (ret) 206 return ret; 207 208 value &= BMI088_ACCEL_MODE_ODR_MASK; 209 value -= BMI088_ACCEL_MODE_ODR_12_5; 210 value <<= 1; 211 212 if (value >= ARRAY_SIZE(bmi088_sample_freqs) - 1) 213 return -EINVAL; 214 215 *val = bmi088_sample_freqs[value]; 216 *val2 = bmi088_sample_freqs[value + 1]; 217 218 return IIO_VAL_INT_PLUS_MICRO; 219} 220 221static int bmi088_accel_set_sample_freq(struct bmi088_accel_data *data, int val) 222{ 223 unsigned int regval; 224 int index = 0; 225 226 while (index < ARRAY_SIZE(bmi088_sample_freqs) && 227 bmi088_sample_freqs[index] != val) 228 index += 2; 229 230 if (index >= ARRAY_SIZE(bmi088_sample_freqs)) 231 return -EINVAL; 232 233 regval = (index >> 1) + BMI088_ACCEL_MODE_ODR_12_5; 234 235 return regmap_update_bits(data->regmap, BMI088_ACCEL_REG_ACC_CONF, 236 BMI088_ACCEL_MODE_ODR_MASK, regval); 237} 238 239static int bmi088_accel_get_temp(struct bmi088_accel_data *data, int *val) 240{ 241 int ret; 242 s16 temp; 243 244 ret = regmap_bulk_read(data->regmap, BMI088_ACCEL_REG_TEMP, 245 &data->buffer, sizeof(__be16)); 246 if (ret) 247 return ret; 248 249 /* data->buffer is cacheline aligned */ 250 temp = be16_to_cpu(*(__be16 *)data->buffer); 251 252 *val = temp >> BMI088_ACCEL_REG_TEMP_SHIFT; 253 254 return IIO_VAL_INT; 255} 256 257static int bmi088_accel_get_axis(struct bmi088_accel_data *data, 258 struct iio_chan_spec const *chan, 259 int *val) 260{ 261 int ret; 262 s16 raw_val; 263 264 ret = regmap_bulk_read(data->regmap, 265 BMI088_ACCEL_AXIS_TO_REG(chan->scan_index), 266 data->buffer, sizeof(__le16)); 267 if (ret) 268 return ret; 269 270 raw_val = le16_to_cpu(*(__le16 *)data->buffer); 271 *val = raw_val; 272 273 return IIO_VAL_INT; 274} 275 276static int bmi088_accel_read_raw(struct iio_dev *indio_dev, 277 struct iio_chan_spec const *chan, 278 int *val, int *val2, long mask) 279{ 280 struct bmi088_accel_data *data = iio_priv(indio_dev); 281 struct device *dev = regmap_get_device(data->regmap); 282 int ret; 283 284 switch (mask) { 285 case IIO_CHAN_INFO_RAW: 286 switch (chan->type) { 287 case IIO_TEMP: 288 ret = pm_runtime_resume_and_get(dev); 289 if (ret) 290 return ret; 291 292 ret = bmi088_accel_get_temp(data, val); 293 goto out_read_raw_pm_put; 294 case IIO_ACCEL: 295 ret = pm_runtime_resume_and_get(dev); 296 if (ret) 297 return ret; 298 299 ret = iio_device_claim_direct_mode(indio_dev); 300 if (ret) 301 goto out_read_raw_pm_put; 302 303 ret = bmi088_accel_get_axis(data, chan, val); 304 iio_device_release_direct_mode(indio_dev); 305 if (!ret) 306 ret = IIO_VAL_INT; 307 308 goto out_read_raw_pm_put; 309 default: 310 return -EINVAL; 311 } 312 case IIO_CHAN_INFO_OFFSET: 313 switch (chan->type) { 314 case IIO_TEMP: 315 /* Offset applies before scale */ 316 *val = BMI088_ACCEL_TEMP_OFFSET/BMI088_ACCEL_TEMP_UNIT; 317 return IIO_VAL_INT; 318 default: 319 return -EINVAL; 320 } 321 case IIO_CHAN_INFO_SCALE: 322 switch (chan->type) { 323 case IIO_TEMP: 324 /* 0.125 degrees per LSB */ 325 *val = BMI088_ACCEL_TEMP_UNIT; 326 return IIO_VAL_INT; 327 case IIO_ACCEL: 328 ret = pm_runtime_resume_and_get(dev); 329 if (ret) 330 return ret; 331 332 ret = regmap_read(data->regmap, 333 BMI088_ACCEL_REG_ACC_RANGE, val); 334 if (ret) 335 goto out_read_raw_pm_put; 336 337 *val2 = 15 - (*val & 0x3); 338 *val = 3 * 980; 339 ret = IIO_VAL_FRACTIONAL_LOG2; 340 341 goto out_read_raw_pm_put; 342 default: 343 return -EINVAL; 344 } 345 case IIO_CHAN_INFO_SAMP_FREQ: 346 ret = pm_runtime_resume_and_get(dev); 347 if (ret) 348 return ret; 349 350 ret = bmi088_accel_get_sample_freq(data, val, val2); 351 goto out_read_raw_pm_put; 352 default: 353 break; 354 } 355 356 return -EINVAL; 357 358out_read_raw_pm_put: 359 pm_runtime_mark_last_busy(dev); 360 pm_runtime_put_autosuspend(dev); 361 362 return ret; 363} 364 365static int bmi088_accel_read_avail(struct iio_dev *indio_dev, 366 struct iio_chan_spec const *chan, 367 const int **vals, int *type, int *length, 368 long mask) 369{ 370 switch (mask) { 371 case IIO_CHAN_INFO_SAMP_FREQ: 372 *type = IIO_VAL_INT_PLUS_MICRO; 373 *vals = bmi088_sample_freqs; 374 *length = ARRAY_SIZE(bmi088_sample_freqs); 375 return IIO_AVAIL_LIST; 376 default: 377 return -EINVAL; 378 } 379} 380 381static int bmi088_accel_write_raw(struct iio_dev *indio_dev, 382 struct iio_chan_spec const *chan, 383 int val, int val2, long mask) 384{ 385 struct bmi088_accel_data *data = iio_priv(indio_dev); 386 struct device *dev = regmap_get_device(data->regmap); 387 int ret; 388 389 switch (mask) { 390 case IIO_CHAN_INFO_SAMP_FREQ: 391 ret = pm_runtime_resume_and_get(dev); 392 if (ret) 393 return ret; 394 395 ret = bmi088_accel_set_sample_freq(data, val); 396 pm_runtime_mark_last_busy(dev); 397 pm_runtime_put_autosuspend(dev); 398 return ret; 399 default: 400 return -EINVAL; 401 } 402} 403 404#define BMI088_ACCEL_CHANNEL(_axis) { \ 405 .type = IIO_ACCEL, \ 406 .modified = 1, \ 407 .channel2 = IIO_MOD_##_axis, \ 408 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 409 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 410 BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 411 .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 412 .scan_index = AXIS_##_axis, \ 413} 414 415static const struct iio_chan_spec bmi088_accel_channels[] = { 416 { 417 .type = IIO_TEMP, 418 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 419 BIT(IIO_CHAN_INFO_SCALE) | 420 BIT(IIO_CHAN_INFO_OFFSET), 421 .scan_index = -1, 422 }, 423 BMI088_ACCEL_CHANNEL(X), 424 BMI088_ACCEL_CHANNEL(Y), 425 BMI088_ACCEL_CHANNEL(Z), 426 IIO_CHAN_SOFT_TIMESTAMP(3), 427}; 428 429static const struct bmi088_accel_chip_info bmi088_accel_chip_info_tbl[] = { 430 [0] = { 431 .name = "bmi088a", 432 .chip_id = 0x1E, 433 .channels = bmi088_accel_channels, 434 .num_channels = ARRAY_SIZE(bmi088_accel_channels), 435 }, 436}; 437 438static const struct iio_info bmi088_accel_info = { 439 .read_raw = bmi088_accel_read_raw, 440 .write_raw = bmi088_accel_write_raw, 441 .read_avail = bmi088_accel_read_avail, 442}; 443 444static const unsigned long bmi088_accel_scan_masks[] = { 445 BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z), 446 0 447}; 448 449static int bmi088_accel_chip_init(struct bmi088_accel_data *data) 450{ 451 struct device *dev = regmap_get_device(data->regmap); 452 int ret, i; 453 unsigned int val; 454 455 /* Do a dummy read to enable SPI interface, won't harm I2C */ 456 regmap_read(data->regmap, BMI088_ACCEL_REG_INT_STATUS, &val); 457 458 /* 459 * Reset chip to get it in a known good state. A delay of 1ms after 460 * reset is required according to the data sheet 461 */ 462 ret = regmap_write(data->regmap, BMI088_ACCEL_REG_RESET, 463 BMI088_ACCEL_RESET_VAL); 464 if (ret) 465 return ret; 466 467 usleep_range(1000, 2000); 468 469 /* Do a dummy read again after a reset to enable the SPI interface */ 470 regmap_read(data->regmap, BMI088_ACCEL_REG_INT_STATUS, &val); 471 472 /* Read chip ID */ 473 ret = regmap_read(data->regmap, BMI088_ACCEL_REG_CHIP_ID, &val); 474 if (ret) { 475 dev_err(dev, "Error: Reading chip id\n"); 476 return ret; 477 } 478 479 /* Validate chip ID */ 480 for (i = 0; i < ARRAY_SIZE(bmi088_accel_chip_info_tbl); i++) { 481 if (bmi088_accel_chip_info_tbl[i].chip_id == val) { 482 data->chip_info = &bmi088_accel_chip_info_tbl[i]; 483 break; 484 } 485 } 486 if (i == ARRAY_SIZE(bmi088_accel_chip_info_tbl)) { 487 dev_err(dev, "Invalid chip %x\n", val); 488 return -ENODEV; 489 } 490 491 return 0; 492} 493 494int bmi088_accel_core_probe(struct device *dev, struct regmap *regmap, 495 int irq, const char *name, bool block_supported) 496{ 497 struct bmi088_accel_data *data; 498 struct iio_dev *indio_dev; 499 int ret; 500 501 indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 502 if (!indio_dev) 503 return -ENOMEM; 504 505 data = iio_priv(indio_dev); 506 dev_set_drvdata(dev, indio_dev); 507 508 data->regmap = regmap; 509 510 ret = bmi088_accel_chip_init(data); 511 if (ret) 512 return ret; 513 514 indio_dev->channels = data->chip_info->channels; 515 indio_dev->num_channels = data->chip_info->num_channels; 516 indio_dev->name = name ? name : data->chip_info->name; 517 indio_dev->available_scan_masks = bmi088_accel_scan_masks; 518 indio_dev->modes = INDIO_DIRECT_MODE; 519 indio_dev->info = &bmi088_accel_info; 520 521 /* Enable runtime PM */ 522 pm_runtime_get_noresume(dev); 523 pm_runtime_set_suspended(dev); 524 pm_runtime_enable(dev); 525 /* We need ~6ms to startup, so set the delay to 6 seconds */ 526 pm_runtime_set_autosuspend_delay(dev, 6000); 527 pm_runtime_use_autosuspend(dev); 528 pm_runtime_put(dev); 529 530 ret = iio_device_register(indio_dev); 531 if (ret) 532 dev_err(dev, "Unable to register iio device\n"); 533 534 return ret; 535} 536EXPORT_SYMBOL_NS_GPL(bmi088_accel_core_probe, IIO_BMI088); 537 538 539void bmi088_accel_core_remove(struct device *dev) 540{ 541 struct iio_dev *indio_dev = dev_get_drvdata(dev); 542 struct bmi088_accel_data *data = iio_priv(indio_dev); 543 544 iio_device_unregister(indio_dev); 545 546 pm_runtime_disable(dev); 547 pm_runtime_set_suspended(dev); 548 bmi088_accel_power_down(data); 549} 550EXPORT_SYMBOL_NS_GPL(bmi088_accel_core_remove, IIO_BMI088); 551 552static int __maybe_unused bmi088_accel_runtime_suspend(struct device *dev) 553{ 554 struct iio_dev *indio_dev = dev_get_drvdata(dev); 555 struct bmi088_accel_data *data = iio_priv(indio_dev); 556 557 return bmi088_accel_power_down(data); 558} 559 560static int __maybe_unused bmi088_accel_runtime_resume(struct device *dev) 561{ 562 struct iio_dev *indio_dev = dev_get_drvdata(dev); 563 struct bmi088_accel_data *data = iio_priv(indio_dev); 564 565 return bmi088_accel_power_up(data); 566} 567 568const struct dev_pm_ops bmi088_accel_pm_ops = { 569 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 570 pm_runtime_force_resume) 571 SET_RUNTIME_PM_OPS(bmi088_accel_runtime_suspend, 572 bmi088_accel_runtime_resume, NULL) 573}; 574EXPORT_SYMBOL_NS_GPL(bmi088_accel_pm_ops, IIO_BMI088); 575 576MODULE_AUTHOR("Niek van Agt <niek.van.agt@topicproducts.com>"); 577MODULE_LICENSE("GPL v2"); 578MODULE_DESCRIPTION("BMI088 accelerometer driver (core)");