FILE
inv_icm42600_core.c
File preview with syntax highlighting.
linux-6.19.14/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (C) 2020 Invensense, Inc. 4 */ 5 6#include <linux/kernel.h> 7#include <linux/device.h> 8#include <linux/module.h> 9#include <linux/slab.h> 10#include <linux/delay.h> 11#include <linux/mutex.h> 12#include <linux/interrupt.h> 13#include <linux/irq.h> 14#include <linux/regulator/consumer.h> 15#include <linux/pm_runtime.h> 16#include <linux/property.h> 17#include <linux/regmap.h> 18 19#include <linux/iio/iio.h> 20 21#include "inv_icm42600.h" 22#include "inv_icm42600_buffer.h" 23 24static const struct regmap_range_cfg inv_icm42600_regmap_ranges[] = { 25 { 26 .name = "user banks", 27 .range_min = 0x0000, 28 .range_max = 0x4FFF, 29 .selector_reg = INV_ICM42600_REG_BANK_SEL, 30 .selector_mask = INV_ICM42600_BANK_SEL_MASK, 31 .selector_shift = 0, 32 .window_start = 0, 33 .window_len = 0x1000, 34 }, 35}; 36 37static const struct regmap_range inv_icm42600_regmap_volatile_yes_ranges[] = { 38 /* Sensor data registers */ 39 regmap_reg_range(0x001D, 0x002A), 40 /* INT status, FIFO, APEX data */ 41 regmap_reg_range(0x002D, 0x0038), 42 /* Signal path reset */ 43 regmap_reg_range(0x004B, 0x004B), 44 /* FIFO lost packets */ 45 regmap_reg_range(0x006C, 0x006D), 46 /* Timestamp value */ 47 regmap_reg_range(0x1062, 0x1064), 48}; 49 50static const struct regmap_range inv_icm42600_regmap_volatile_no_ranges[] = { 51 regmap_reg_range(0x0000, 0x001C), 52 regmap_reg_range(0x006E, 0x1061), 53 regmap_reg_range(0x1065, 0x4FFF), 54}; 55 56static const struct regmap_access_table inv_icm42600_regmap_volatile_accesses[] = { 57 { 58 .yes_ranges = inv_icm42600_regmap_volatile_yes_ranges, 59 .n_yes_ranges = ARRAY_SIZE(inv_icm42600_regmap_volatile_yes_ranges), 60 .no_ranges = inv_icm42600_regmap_volatile_no_ranges, 61 .n_no_ranges = ARRAY_SIZE(inv_icm42600_regmap_volatile_no_ranges), 62 }, 63}; 64 65static const struct regmap_range inv_icm42600_regmap_rd_noinc_no_ranges[] = { 66 regmap_reg_range(0x0000, INV_ICM42600_REG_FIFO_DATA - 1), 67 regmap_reg_range(INV_ICM42600_REG_FIFO_DATA + 1, 0x4FFF), 68}; 69 70static const struct regmap_access_table inv_icm42600_regmap_rd_noinc_accesses[] = { 71 { 72 .no_ranges = inv_icm42600_regmap_rd_noinc_no_ranges, 73 .n_no_ranges = ARRAY_SIZE(inv_icm42600_regmap_rd_noinc_no_ranges), 74 }, 75}; 76 77const struct regmap_config inv_icm42600_regmap_config = { 78 .name = "inv_icm42600", 79 .reg_bits = 8, 80 .val_bits = 8, 81 .max_register = 0x4FFF, 82 .ranges = inv_icm42600_regmap_ranges, 83 .num_ranges = ARRAY_SIZE(inv_icm42600_regmap_ranges), 84 .volatile_table = inv_icm42600_regmap_volatile_accesses, 85 .rd_noinc_table = inv_icm42600_regmap_rd_noinc_accesses, 86 .cache_type = REGCACHE_MAPLE, 87}; 88EXPORT_SYMBOL_NS_GPL(inv_icm42600_regmap_config, "IIO_ICM42600"); 89 90/* define specific regmap for SPI not supporting burst write */ 91const struct regmap_config inv_icm42600_spi_regmap_config = { 92 .name = "inv_icm42600", 93 .reg_bits = 8, 94 .val_bits = 8, 95 .max_register = 0x4FFF, 96 .ranges = inv_icm42600_regmap_ranges, 97 .num_ranges = ARRAY_SIZE(inv_icm42600_regmap_ranges), 98 .volatile_table = inv_icm42600_regmap_volatile_accesses, 99 .rd_noinc_table = inv_icm42600_regmap_rd_noinc_accesses, 100 .cache_type = REGCACHE_MAPLE, 101 .use_single_write = true, 102}; 103EXPORT_SYMBOL_NS_GPL(inv_icm42600_spi_regmap_config, "IIO_ICM42600"); 104 105struct inv_icm42600_hw { 106 u8 whoami; 107 const char *name; 108 const struct inv_icm42600_conf *conf; 109}; 110 111/* chip initial default configuration */ 112static const struct inv_icm42600_conf inv_icm42600_default_conf = { 113 .gyro = { 114 .mode = INV_ICM42600_SENSOR_MODE_OFF, 115 .fs = INV_ICM42600_GYRO_FS_2000DPS, 116 .odr = INV_ICM42600_ODR_50HZ, 117 .filter = INV_ICM42600_FILTER_BW_ODR_DIV_2, 118 }, 119 .accel = { 120 .mode = INV_ICM42600_SENSOR_MODE_OFF, 121 .fs = INV_ICM42600_ACCEL_FS_16G, 122 .odr = INV_ICM42600_ODR_50HZ, 123 .filter = INV_ICM42600_FILTER_BW_ODR_DIV_2, 124 }, 125 .temp_en = false, 126}; 127 128static const struct inv_icm42600_conf inv_icm42686_default_conf = { 129 .gyro = { 130 .mode = INV_ICM42600_SENSOR_MODE_OFF, 131 .fs = INV_ICM42686_GYRO_FS_4000DPS, 132 .odr = INV_ICM42600_ODR_50HZ, 133 .filter = INV_ICM42600_FILTER_BW_ODR_DIV_2, 134 }, 135 .accel = { 136 .mode = INV_ICM42600_SENSOR_MODE_OFF, 137 .fs = INV_ICM42686_ACCEL_FS_32G, 138 .odr = INV_ICM42600_ODR_50HZ, 139 .filter = INV_ICM42600_FILTER_BW_ODR_DIV_2, 140 }, 141 .temp_en = false, 142}; 143 144static const struct inv_icm42600_hw inv_icm42600_hw[INV_CHIP_NB] = { 145 [INV_CHIP_ICM42600] = { 146 .whoami = INV_ICM42600_WHOAMI_ICM42600, 147 .name = "icm42600", 148 .conf = &inv_icm42600_default_conf, 149 }, 150 [INV_CHIP_ICM42602] = { 151 .whoami = INV_ICM42600_WHOAMI_ICM42602, 152 .name = "icm42602", 153 .conf = &inv_icm42600_default_conf, 154 }, 155 [INV_CHIP_ICM42605] = { 156 .whoami = INV_ICM42600_WHOAMI_ICM42605, 157 .name = "icm42605", 158 .conf = &inv_icm42600_default_conf, 159 }, 160 [INV_CHIP_ICM42686] = { 161 .whoami = INV_ICM42600_WHOAMI_ICM42686, 162 .name = "icm42686", 163 .conf = &inv_icm42686_default_conf, 164 }, 165 [INV_CHIP_ICM42622] = { 166 .whoami = INV_ICM42600_WHOAMI_ICM42622, 167 .name = "icm42622", 168 .conf = &inv_icm42600_default_conf, 169 }, 170 [INV_CHIP_ICM42688] = { 171 .whoami = INV_ICM42600_WHOAMI_ICM42688, 172 .name = "icm42688", 173 .conf = &inv_icm42600_default_conf, 174 }, 175 [INV_CHIP_ICM42631] = { 176 .whoami = INV_ICM42600_WHOAMI_ICM42631, 177 .name = "icm42631", 178 .conf = &inv_icm42600_default_conf, 179 }, 180}; 181 182const struct iio_mount_matrix * 183inv_icm42600_get_mount_matrix(const struct iio_dev *indio_dev, 184 const struct iio_chan_spec *chan) 185{ 186 const struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); 187 188 return &st->orientation; 189} 190 191u32 inv_icm42600_odr_to_period(enum inv_icm42600_odr odr) 192{ 193 static u32 odr_periods[INV_ICM42600_ODR_NB] = { 194 /* reserved values */ 195 0, 0, 0, 196 /* 8kHz */ 197 125000, 198 /* 4kHz */ 199 250000, 200 /* 2kHz */ 201 500000, 202 /* 1kHz */ 203 1000000, 204 /* 200Hz */ 205 5000000, 206 /* 100Hz */ 207 10000000, 208 /* 50Hz */ 209 20000000, 210 /* 25Hz */ 211 40000000, 212 /* 12.5Hz */ 213 80000000, 214 /* 6.25Hz */ 215 160000000, 216 /* 3.125Hz */ 217 320000000, 218 /* 1.5625Hz */ 219 640000000, 220 /* 500Hz */ 221 2000000, 222 }; 223 224 return odr_periods[odr]; 225} 226 227static int inv_icm42600_set_pwr_mgmt0(struct inv_icm42600_state *st, 228 enum inv_icm42600_sensor_mode gyro, 229 enum inv_icm42600_sensor_mode accel, 230 bool temp, unsigned int *sleep_ms) 231{ 232 enum inv_icm42600_sensor_mode oldgyro = st->conf.gyro.mode; 233 enum inv_icm42600_sensor_mode oldaccel = st->conf.accel.mode; 234 bool oldtemp = st->conf.temp_en; 235 unsigned int sleepval; 236 unsigned int val; 237 int ret; 238 239 /* if nothing changed, exit */ 240 if (gyro == oldgyro && accel == oldaccel && temp == oldtemp) 241 return 0; 242 243 val = INV_ICM42600_PWR_MGMT0_GYRO(gyro) | 244 INV_ICM42600_PWR_MGMT0_ACCEL(accel); 245 if (!temp) 246 val |= INV_ICM42600_PWR_MGMT0_TEMP_DIS; 247 ret = regmap_write(st->map, INV_ICM42600_REG_PWR_MGMT0, val); 248 if (ret) 249 return ret; 250 251 st->conf.gyro.mode = gyro; 252 st->conf.accel.mode = accel; 253 st->conf.temp_en = temp; 254 255 /* compute required wait time for sensors to stabilize */ 256 sleepval = 0; 257 /* temperature stabilization time */ 258 if (temp && !oldtemp) { 259 if (sleepval < INV_ICM42600_TEMP_STARTUP_TIME_MS) 260 sleepval = INV_ICM42600_TEMP_STARTUP_TIME_MS; 261 } 262 /* accel startup time */ 263 if (accel != oldaccel && oldaccel == INV_ICM42600_SENSOR_MODE_OFF) { 264 /* block any register write for at least 200 µs */ 265 usleep_range(200, 300); 266 if (sleepval < INV_ICM42600_ACCEL_STARTUP_TIME_MS) 267 sleepval = INV_ICM42600_ACCEL_STARTUP_TIME_MS; 268 } 269 if (gyro != oldgyro) { 270 /* gyro startup time */ 271 if (oldgyro == INV_ICM42600_SENSOR_MODE_OFF) { 272 /* block any register write for at least 200 µs */ 273 usleep_range(200, 300); 274 if (sleepval < INV_ICM42600_GYRO_STARTUP_TIME_MS) 275 sleepval = INV_ICM42600_GYRO_STARTUP_TIME_MS; 276 /* gyro stop time */ 277 } else if (gyro == INV_ICM42600_SENSOR_MODE_OFF) { 278 if (sleepval < INV_ICM42600_GYRO_STOP_TIME_MS) 279 sleepval = INV_ICM42600_GYRO_STOP_TIME_MS; 280 } 281 } 282 283 /* deferred sleep value if sleep pointer is provided or direct sleep */ 284 if (sleep_ms) 285 *sleep_ms = sleepval; 286 else if (sleepval) 287 msleep(sleepval); 288 289 return 0; 290} 291 292int inv_icm42600_set_accel_conf(struct inv_icm42600_state *st, 293 struct inv_icm42600_sensor_conf *conf, 294 unsigned int *sleep_ms) 295{ 296 struct inv_icm42600_sensor_conf *oldconf = &st->conf.accel; 297 unsigned int val; 298 int ret; 299 300 /* Sanitize missing values with current values */ 301 if (conf->mode < 0) 302 conf->mode = oldconf->mode; 303 if (conf->fs < 0) 304 conf->fs = oldconf->fs; 305 if (conf->odr < 0) 306 conf->odr = oldconf->odr; 307 if (conf->filter < 0) 308 conf->filter = oldconf->filter; 309 310 /* force power mode against ODR when sensor is on */ 311 switch (conf->mode) { 312 case INV_ICM42600_SENSOR_MODE_LOW_POWER: 313 case INV_ICM42600_SENSOR_MODE_LOW_NOISE: 314 if (conf->odr <= INV_ICM42600_ODR_1KHZ_LN) { 315 conf->mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE; 316 conf->filter = INV_ICM42600_FILTER_BW_ODR_DIV_2; 317 } else if (conf->odr >= INV_ICM42600_ODR_6_25HZ_LP && 318 conf->odr <= INV_ICM42600_ODR_1_5625HZ_LP) { 319 conf->mode = INV_ICM42600_SENSOR_MODE_LOW_POWER; 320 conf->filter = INV_ICM42600_FILTER_AVG_16X; 321 } 322 break; 323 default: 324 break; 325 } 326 327 /* set ACCEL_CONFIG0 register (accel fullscale & odr) */ 328 if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) { 329 val = INV_ICM42600_ACCEL_CONFIG0_FS(conf->fs) | 330 INV_ICM42600_ACCEL_CONFIG0_ODR(conf->odr); 331 ret = regmap_write(st->map, INV_ICM42600_REG_ACCEL_CONFIG0, val); 332 if (ret) 333 return ret; 334 oldconf->fs = conf->fs; 335 oldconf->odr = conf->odr; 336 } 337 338 /* set GYRO_ACCEL_CONFIG0 register (accel filter) */ 339 if (conf->filter != oldconf->filter) { 340 val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(conf->filter) | 341 INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(st->conf.gyro.filter); 342 ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val); 343 if (ret) 344 return ret; 345 oldconf->filter = conf->filter; 346 } 347 348 /* set PWR_MGMT0 register (accel sensor mode) */ 349 return inv_icm42600_set_pwr_mgmt0(st, st->conf.gyro.mode, conf->mode, 350 st->conf.temp_en, sleep_ms); 351} 352 353int inv_icm42600_set_gyro_conf(struct inv_icm42600_state *st, 354 struct inv_icm42600_sensor_conf *conf, 355 unsigned int *sleep_ms) 356{ 357 struct inv_icm42600_sensor_conf *oldconf = &st->conf.gyro; 358 unsigned int val; 359 int ret; 360 361 /* sanitize missing values with current values */ 362 if (conf->mode < 0) 363 conf->mode = oldconf->mode; 364 if (conf->fs < 0) 365 conf->fs = oldconf->fs; 366 if (conf->odr < 0) 367 conf->odr = oldconf->odr; 368 if (conf->filter < 0) 369 conf->filter = oldconf->filter; 370 371 /* set GYRO_CONFIG0 register (gyro fullscale & odr) */ 372 if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) { 373 val = INV_ICM42600_GYRO_CONFIG0_FS(conf->fs) | 374 INV_ICM42600_GYRO_CONFIG0_ODR(conf->odr); 375 ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_CONFIG0, val); 376 if (ret) 377 return ret; 378 oldconf->fs = conf->fs; 379 oldconf->odr = conf->odr; 380 } 381 382 /* set GYRO_ACCEL_CONFIG0 register (gyro filter) */ 383 if (conf->filter != oldconf->filter) { 384 val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(st->conf.accel.filter) | 385 INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(conf->filter); 386 ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val); 387 if (ret) 388 return ret; 389 oldconf->filter = conf->filter; 390 } 391 392 /* set PWR_MGMT0 register (gyro sensor mode) */ 393 return inv_icm42600_set_pwr_mgmt0(st, conf->mode, st->conf.accel.mode, 394 st->conf.temp_en, sleep_ms); 395 396 return 0; 397} 398 399int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable, 400 unsigned int *sleep_ms) 401{ 402 return inv_icm42600_set_pwr_mgmt0(st, st->conf.gyro.mode, 403 st->conf.accel.mode, enable, 404 sleep_ms); 405} 406 407int inv_icm42600_enable_wom(struct inv_icm42600_state *st) 408{ 409 int ret; 410 411 /* enable WoM hardware */ 412 ret = regmap_write(st->map, INV_ICM42600_REG_SMD_CONFIG, 413 INV_ICM42600_SMD_CONFIG_SMD_MODE_WOM | 414 INV_ICM42600_SMD_CONFIG_WOM_MODE); 415 if (ret) 416 return ret; 417 418 /* enable WoM interrupt */ 419 return regmap_set_bits(st->map, INV_ICM42600_REG_INT_SOURCE1, 420 INV_ICM42600_INT_SOURCE1_WOM_INT1_EN); 421} 422 423int inv_icm42600_disable_wom(struct inv_icm42600_state *st) 424{ 425 int ret; 426 427 /* disable WoM interrupt */ 428 ret = regmap_clear_bits(st->map, INV_ICM42600_REG_INT_SOURCE1, 429 INV_ICM42600_INT_SOURCE1_WOM_INT1_EN); 430 if (ret) 431 return ret; 432 433 /* disable WoM hardware */ 434 return regmap_write(st->map, INV_ICM42600_REG_SMD_CONFIG, 435 INV_ICM42600_SMD_CONFIG_SMD_MODE_OFF); 436} 437 438int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg, 439 unsigned int writeval, unsigned int *readval) 440{ 441 struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); 442 443 guard(mutex)(&st->lock); 444 445 if (readval) 446 return regmap_read(st->map, reg, readval); 447 448 return regmap_write(st->map, reg, writeval); 449} 450 451static int inv_icm42600_set_conf(struct inv_icm42600_state *st, 452 const struct inv_icm42600_conf *conf) 453{ 454 unsigned int val; 455 int ret; 456 457 /* set PWR_MGMT0 register (gyro & accel sensor mode, temp enabled) */ 458 val = INV_ICM42600_PWR_MGMT0_GYRO(conf->gyro.mode) | 459 INV_ICM42600_PWR_MGMT0_ACCEL(conf->accel.mode); 460 if (!conf->temp_en) 461 val |= INV_ICM42600_PWR_MGMT0_TEMP_DIS; 462 ret = regmap_write(st->map, INV_ICM42600_REG_PWR_MGMT0, val); 463 if (ret) 464 return ret; 465 466 /* set GYRO_CONFIG0 register (gyro fullscale & odr) */ 467 val = INV_ICM42600_GYRO_CONFIG0_FS(conf->gyro.fs) | 468 INV_ICM42600_GYRO_CONFIG0_ODR(conf->gyro.odr); 469 ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_CONFIG0, val); 470 if (ret) 471 return ret; 472 473 /* set ACCEL_CONFIG0 register (accel fullscale & odr) */ 474 val = INV_ICM42600_ACCEL_CONFIG0_FS(conf->accel.fs) | 475 INV_ICM42600_ACCEL_CONFIG0_ODR(conf->accel.odr); 476 ret = regmap_write(st->map, INV_ICM42600_REG_ACCEL_CONFIG0, val); 477 if (ret) 478 return ret; 479 480 /* set GYRO_ACCEL_CONFIG0 register (gyro & accel filters) */ 481 val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(conf->accel.filter) | 482 INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(conf->gyro.filter); 483 ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val); 484 if (ret) 485 return ret; 486 487 /* update internal conf */ 488 st->conf = *conf; 489 490 return 0; 491} 492 493/** 494 * inv_icm42600_setup() - check and setup chip 495 * @st: driver internal state 496 * @bus_setup: callback for setting up bus specific registers 497 * 498 * Returns 0 on success, a negative error code otherwise. 499 */ 500static int inv_icm42600_setup(struct inv_icm42600_state *st, 501 inv_icm42600_bus_setup bus_setup) 502{ 503 const struct inv_icm42600_hw *hw = &inv_icm42600_hw[st->chip]; 504 const struct device *dev = regmap_get_device(st->map); 505 unsigned int val; 506 int ret; 507 508 /* check chip self-identification value */ 509 ret = regmap_read(st->map, INV_ICM42600_REG_WHOAMI, &val); 510 if (ret) 511 return ret; 512 if (val != hw->whoami) { 513 dev_err(dev, "invalid whoami %#02x expected %#02x (%s)\n", 514 val, hw->whoami, hw->name); 515 return -ENODEV; 516 } 517 st->name = hw->name; 518 519 /* reset to make sure previous state are not there */ 520 ret = regmap_write(st->map, INV_ICM42600_REG_DEVICE_CONFIG, 521 INV_ICM42600_DEVICE_CONFIG_SOFT_RESET); 522 if (ret) 523 return ret; 524 msleep(INV_ICM42600_RESET_TIME_MS); 525 526 ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, &val); 527 if (ret) 528 return ret; 529 if (!(val & INV_ICM42600_INT_STATUS_RESET_DONE)) { 530 dev_err(dev, "reset error, reset done bit not set\n"); 531 return -ENODEV; 532 } 533 534 /* set chip bus configuration */ 535 ret = bus_setup(st); 536 if (ret) 537 return ret; 538 539 /* sensor data in big-endian (default) */ 540 ret = regmap_set_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0, 541 INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN); 542 if (ret) 543 return ret; 544 545 /* 546 * Use RC clock for accel low-power to fix glitches when switching 547 * gyro on/off while accel low-power is on. 548 */ 549 ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG1, 550 INV_ICM42600_INTF_CONFIG1_ACCEL_LP_CLK_RC, 551 INV_ICM42600_INTF_CONFIG1_ACCEL_LP_CLK_RC); 552 if (ret) 553 return ret; 554 555 return inv_icm42600_set_conf(st, hw->conf); 556} 557 558static irqreturn_t inv_icm42600_irq_timestamp(int irq, void *_data) 559{ 560 struct inv_icm42600_state *st = _data; 561 562 st->timestamp.gyro = iio_get_time_ns(st->indio_gyro); 563 st->timestamp.accel = iio_get_time_ns(st->indio_accel); 564 565 return IRQ_WAKE_THREAD; 566} 567 568static irqreturn_t inv_icm42600_irq_handler(int irq, void *_data) 569{ 570 struct inv_icm42600_state *st = _data; 571 struct device *dev = regmap_get_device(st->map); 572 unsigned int status; 573 int ret; 574 575 mutex_lock(&st->lock); 576 577 if (st->apex.on) { 578 unsigned int status2, status3; 579 580 /* read INT_STATUS2 and INT_STATUS3 in 1 operation */ 581 ret = regmap_bulk_read(st->map, INV_ICM42600_REG_INT_STATUS2, st->buffer, 2); 582 if (ret) 583 goto out_unlock; 584 status2 = st->buffer[0]; 585 status3 = st->buffer[1]; 586 inv_icm42600_accel_handle_events(st->indio_accel, status2, status3, 587 st->timestamp.accel); 588 } 589 590 ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, &status); 591 if (ret) 592 goto out_unlock; 593 594 /* FIFO full */ 595 if (status & INV_ICM42600_INT_STATUS_FIFO_FULL) 596 dev_warn(dev, "FIFO full data lost!\n"); 597 598 /* FIFO threshold reached */ 599 if (status & INV_ICM42600_INT_STATUS_FIFO_THS) { 600 ret = inv_icm42600_buffer_fifo_read(st, 0); 601 if (ret) { 602 dev_err(dev, "FIFO read error %d\n", ret); 603 goto out_unlock; 604 } 605 ret = inv_icm42600_buffer_fifo_parse(st); 606 if (ret) 607 dev_err(dev, "FIFO parsing error %d\n", ret); 608 } 609 610out_unlock: 611 mutex_unlock(&st->lock); 612 return IRQ_HANDLED; 613} 614 615/** 616 * inv_icm42600_irq_init() - initialize int pin and interrupt handler 617 * @st: driver internal state 618 * @irq: irq number 619 * @irq_type: irq trigger type 620 * @open_drain: true if irq is open drain, false for push-pull 621 * 622 * Returns 0 on success, a negative error code otherwise. 623 */ 624static int inv_icm42600_irq_init(struct inv_icm42600_state *st, int irq, 625 int irq_type, bool open_drain) 626{ 627 struct device *dev = regmap_get_device(st->map); 628 unsigned int val; 629 int ret; 630 631 /* configure INT1 interrupt: default is active low on edge */ 632 switch (irq_type) { 633 case IRQF_TRIGGER_RISING: 634 case IRQF_TRIGGER_HIGH: 635 val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_HIGH; 636 break; 637 default: 638 val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW; 639 break; 640 } 641 642 switch (irq_type) { 643 case IRQF_TRIGGER_LOW: 644 case IRQF_TRIGGER_HIGH: 645 val |= INV_ICM42600_INT_CONFIG_INT1_LATCHED; 646 break; 647 default: 648 break; 649 } 650 651 if (!open_drain) 652 val |= INV_ICM42600_INT_CONFIG_INT1_PUSH_PULL; 653 654 ret = regmap_write(st->map, INV_ICM42600_REG_INT_CONFIG, val); 655 if (ret) 656 return ret; 657 658 /* Deassert async reset for proper INT pin operation (cf datasheet) */ 659 ret = regmap_clear_bits(st->map, INV_ICM42600_REG_INT_CONFIG1, 660 INV_ICM42600_INT_CONFIG1_ASYNC_RESET); 661 if (ret) 662 return ret; 663 664 irq_type |= IRQF_ONESHOT; 665 return devm_request_threaded_irq(dev, irq, inv_icm42600_irq_timestamp, 666 inv_icm42600_irq_handler, irq_type, 667 "inv_icm42600", st); 668} 669 670static int inv_icm42600_timestamp_setup(struct inv_icm42600_state *st) 671{ 672 unsigned int val; 673 674 /* enable timestamp register */ 675 val = INV_ICM42600_TMST_CONFIG_TMST_TO_REGS_EN | 676 INV_ICM42600_TMST_CONFIG_TMST_EN; 677 return regmap_update_bits(st->map, INV_ICM42600_REG_TMST_CONFIG, 678 INV_ICM42600_TMST_CONFIG_MASK, val); 679} 680 681static int inv_icm42600_enable_regulator_vddio(struct inv_icm42600_state *st) 682{ 683 int ret; 684 685 ret = regulator_enable(st->vddio_supply); 686 if (ret) 687 return ret; 688 689 /* wait a little for supply ramp */ 690 usleep_range(3000, 4000); 691 692 return 0; 693} 694 695static void inv_icm42600_disable_vddio_reg(void *_data) 696{ 697 struct inv_icm42600_state *st = _data; 698 struct device *dev = regmap_get_device(st->map); 699 700 if (pm_runtime_status_suspended(dev)) 701 return; 702 703 regulator_disable(st->vddio_supply); 704} 705 706int inv_icm42600_core_probe(struct regmap *regmap, int chip, 707 inv_icm42600_bus_setup bus_setup) 708{ 709 struct device *dev = regmap_get_device(regmap); 710 struct fwnode_handle *fwnode = dev_fwnode(dev); 711 struct inv_icm42600_state *st; 712 int irq, irq_type; 713 bool open_drain; 714 int ret; 715 716 if (chip <= INV_CHIP_INVALID || chip >= INV_CHIP_NB) { 717 dev_err(dev, "invalid chip = %d\n", chip); 718 return -ENODEV; 719 } 720 721 /* get INT1 only supported interrupt or fallback to first interrupt */ 722 irq = fwnode_irq_get_byname(fwnode, "INT1"); 723 if (irq < 0 && irq != -EPROBE_DEFER) { 724 dev_info(dev, "no INT1 interrupt defined, fallback to first interrupt\n"); 725 irq = fwnode_irq_get(fwnode, 0); 726 } 727 if (irq < 0) 728 return dev_err_probe(dev, irq, "error missing INT1 interrupt\n"); 729 730 irq_type = irq_get_trigger_type(irq); 731 if (!irq_type) 732 irq_type = IRQF_TRIGGER_FALLING; 733 734 open_drain = device_property_read_bool(dev, "drive-open-drain"); 735 736 st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL); 737 if (!st) 738 return -ENOMEM; 739 740 dev_set_drvdata(dev, st); 741 mutex_init(&st->lock); 742 st->chip = chip; 743 st->map = regmap; 744 st->irq = irq; 745 746 ret = iio_read_mount_matrix(dev, &st->orientation); 747 if (ret) { 748 dev_err(dev, "failed to retrieve mounting matrix %d\n", ret); 749 return ret; 750 } 751 752 ret = devm_regulator_get_enable(dev, "vdd"); 753 if (ret) 754 return dev_err_probe(dev, ret, 755 "Failed to get vdd regulator\n"); 756 757 msleep(INV_ICM42600_POWER_UP_TIME_MS); 758 759 st->vddio_supply = devm_regulator_get(dev, "vddio"); 760 if (IS_ERR(st->vddio_supply)) 761 return PTR_ERR(st->vddio_supply); 762 763 ret = inv_icm42600_enable_regulator_vddio(st); 764 if (ret) 765 return ret; 766 767 ret = devm_add_action_or_reset(dev, inv_icm42600_disable_vddio_reg, st); 768 if (ret) 769 return ret; 770 771 /* setup chip registers */ 772 ret = inv_icm42600_setup(st, bus_setup); 773 if (ret) 774 return ret; 775 776 ret = inv_icm42600_timestamp_setup(st); 777 if (ret) 778 return ret; 779 780 ret = inv_icm42600_buffer_init(st); 781 if (ret) 782 return ret; 783 784 st->indio_gyro = inv_icm42600_gyro_init(st); 785 if (IS_ERR(st->indio_gyro)) 786 return PTR_ERR(st->indio_gyro); 787 788 st->indio_accel = inv_icm42600_accel_init(st); 789 if (IS_ERR(st->indio_accel)) 790 return PTR_ERR(st->indio_accel); 791 792 ret = inv_icm42600_irq_init(st, irq, irq_type, open_drain); 793 if (ret) 794 return ret; 795 796 /* setup runtime power management */ 797 ret = devm_pm_runtime_set_active_enabled(dev); 798 if (ret) 799 return ret; 800 801 pm_runtime_set_autosuspend_delay(dev, INV_ICM42600_SUSPEND_DELAY_MS); 802 pm_runtime_use_autosuspend(dev); 803 804 return ret; 805} 806EXPORT_SYMBOL_NS_GPL(inv_icm42600_core_probe, "IIO_ICM42600"); 807 808/* 809 * Suspend saves sensors state and turns everything off. 810 * Check first if runtime suspend has not already done the job. 811 */ 812static int inv_icm42600_suspend(struct device *dev) 813{ 814 struct inv_icm42600_state *st = dev_get_drvdata(dev); 815 struct device *accel_dev; 816 bool wakeup; 817 int accel_conf; 818 int ret; 819 820 guard(mutex)(&st->lock); 821 822 st->suspended.gyro = st->conf.gyro.mode; 823 st->suspended.accel = st->conf.accel.mode; 824 st->suspended.temp = st->conf.temp_en; 825 if (pm_runtime_suspended(dev)) 826 return 0; 827 828 /* disable FIFO data streaming */ 829 if (st->fifo.on) { 830 ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG, 831 INV_ICM42600_FIFO_CONFIG_BYPASS); 832 if (ret) 833 return ret; 834 } 835 836 /* keep chip on and wake-up capable if APEX and wakeup on */ 837 accel_dev = &st->indio_accel->dev; 838 wakeup = st->apex.on && device_may_wakeup(accel_dev); 839 if (wakeup) { 840 /* keep accel on and setup irq for wakeup */ 841 accel_conf = st->conf.accel.mode; 842 enable_irq_wake(st->irq); 843 disable_irq(st->irq); 844 } else { 845 /* disable APEX features and accel if wakeup disabled */ 846 if (st->apex.wom.enable) { 847 ret = inv_icm42600_disable_wom(st); 848 if (ret) 849 return ret; 850 } 851 accel_conf = INV_ICM42600_SENSOR_MODE_OFF; 852 } 853 854 ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF, 855 accel_conf, false, NULL); 856 if (ret) 857 return ret; 858 859 /* disable vddio regulator if chip is sleeping */ 860 if (!wakeup) 861 regulator_disable(st->vddio_supply); 862 863 return 0; 864} 865 866/* 867 * System resume gets the system back on and restores the sensors state. 868 * Manually put runtime power management in system active state. 869 */ 870static int inv_icm42600_resume(struct device *dev) 871{ 872 struct inv_icm42600_state *st = dev_get_drvdata(dev); 873 struct inv_icm42600_sensor_state *gyro_st = iio_priv(st->indio_gyro); 874 struct inv_icm42600_sensor_state *accel_st = iio_priv(st->indio_accel); 875 struct device *accel_dev; 876 bool wakeup; 877 int ret; 878 879 guard(mutex)(&st->lock); 880 881 if (pm_runtime_suspended(dev)) 882 return 0; 883 884 /* check wakeup capability */ 885 accel_dev = &st->indio_accel->dev; 886 wakeup = st->apex.on && device_may_wakeup(accel_dev); 887 /* restore irq state or vddio if cut off */ 888 if (wakeup) { 889 enable_irq(st->irq); 890 disable_irq_wake(st->irq); 891 } else { 892 ret = inv_icm42600_enable_regulator_vddio(st); 893 if (ret) 894 return ret; 895 } 896 897 /* restore sensors state */ 898 ret = inv_icm42600_set_pwr_mgmt0(st, st->suspended.gyro, 899 st->suspended.accel, 900 st->suspended.temp, NULL); 901 if (ret) 902 return ret; 903 904 /* restore APEX features if disabled */ 905 if (!wakeup && st->apex.wom.enable) { 906 ret = inv_icm42600_enable_wom(st); 907 if (ret) 908 return ret; 909 } 910 911 /* restore FIFO data streaming */ 912 if (st->fifo.on) { 913 inv_sensors_timestamp_reset(&gyro_st->ts); 914 inv_sensors_timestamp_reset(&accel_st->ts); 915 ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG, 916 INV_ICM42600_FIFO_CONFIG_STREAM); 917 } 918 919 return 0; 920} 921 922/* Runtime suspend will turn off sensors that are enabled by iio devices. */ 923static int inv_icm42600_runtime_suspend(struct device *dev) 924{ 925 struct inv_icm42600_state *st = dev_get_drvdata(dev); 926 int ret; 927 928 guard(mutex)(&st->lock); 929 930 /* disable all sensors */ 931 ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF, 932 INV_ICM42600_SENSOR_MODE_OFF, false, 933 NULL); 934 if (ret) 935 return ret; 936 937 regulator_disable(st->vddio_supply); 938 939 return 0; 940} 941 942/* Sensors are enabled by iio devices, no need to turn them back on here. */ 943static int inv_icm42600_runtime_resume(struct device *dev) 944{ 945 struct inv_icm42600_state *st = dev_get_drvdata(dev); 946 947 guard(mutex)(&st->lock); 948 949 return inv_icm42600_enable_regulator_vddio(st); 950} 951 952EXPORT_NS_GPL_DEV_PM_OPS(inv_icm42600_pm_ops, IIO_ICM42600) = { 953 SYSTEM_SLEEP_PM_OPS(inv_icm42600_suspend, inv_icm42600_resume) 954 RUNTIME_PM_OPS(inv_icm42600_runtime_suspend, 955 inv_icm42600_runtime_resume, NULL) 956}; 957 958MODULE_AUTHOR("InvenSense, Inc."); 959MODULE_DESCRIPTION("InvenSense ICM-426xx device driver"); 960MODULE_LICENSE("GPL"); 961MODULE_IMPORT_NS("IIO_INV_SENSORS_TIMESTAMP");
~/
Read-only file preview.