Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

iio: imu: inv_icm42600: add WoM support

Add WoM as accel roc rising x|y|z event.

Signed-off-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
Link: https://patch.msgid.link/20250630-losd-3-inv-icm42600-add-wom-support-v6-2-5bb0c84800d9@tdk.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Jean-Baptiste Maneyrol and committed by
Jonathan Cameron
50cfaa9a 0c122c28

+427 -5
+47 -1
drivers/iio/imu/inv_icm42600/inv_icm42600.h
··· 135 135 bool temp; 136 136 }; 137 137 138 + struct inv_icm42600_apex { 139 + unsigned int on; 140 + struct { 141 + u64 value; 142 + bool enable; 143 + } wom; 144 + }; 145 + 138 146 /** 139 147 * struct inv_icm42600_state - driver state variables 140 148 * @lock: lock for serializing multiple registers access. ··· 157 149 * @indio_gyro: gyroscope IIO device. 158 150 * @indio_accel: accelerometer IIO device. 159 151 * @timestamp: interrupt timestamps. 152 + * @apex: APEX (Advanced Pedometer and Event detection) management 160 153 * @fifo: FIFO management structure. 161 154 * @buffer: data transfer buffer aligned for DMA. 162 155 */ ··· 177 168 s64 gyro; 178 169 s64 accel; 179 170 } timestamp; 171 + struct inv_icm42600_apex apex; 180 172 struct inv_icm42600_fifo fifo; 181 - u8 buffer[2] __aligned(IIO_DMA_MINALIGN); 173 + u8 buffer[3] __aligned(IIO_DMA_MINALIGN); 182 174 }; 183 175 184 176 ··· 263 253 #define INV_ICM42600_REG_FIFO_COUNT 0x002E 264 254 #define INV_ICM42600_REG_FIFO_DATA 0x0030 265 255 256 + #define INV_ICM42600_REG_INT_STATUS2 0x0037 257 + #define INV_ICM42600_INT_STATUS2_SMD_INT BIT(3) 258 + #define INV_ICM42600_INT_STATUS2_WOM_INT GENMASK(2, 0) 259 + 260 + #define INV_ICM42600_REG_INT_STATUS3 0x0038 261 + #define INV_ICM42600_INT_STATUS3_STEP_DET_INT BIT(5) 262 + #define INV_ICM42600_INT_STATUS3_STEP_CNT_OVF_INT BIT(4) 263 + #define INV_ICM42600_INT_STATUS3_TILT_DET_INT BIT(3) 264 + #define INV_ICM42600_INT_STATUS3_WAKE_INT BIT(2) 265 + #define INV_ICM42600_INT_STATUS3_SLEEP_INT BIT(1) 266 + #define INV_ICM42600_INT_STATUS3_TAP_DET_INT BIT(0) 267 + 266 268 #define INV_ICM42600_REG_SIGNAL_PATH_RESET 0x004B 267 269 #define INV_ICM42600_SIGNAL_PATH_RESET_DMP_INIT_EN BIT(6) 268 270 #define INV_ICM42600_SIGNAL_PATH_RESET_DMP_MEM_RESET BIT(5) ··· 331 309 #define INV_ICM42600_TMST_CONFIG_TMST_FSYNC_EN BIT(1) 332 310 #define INV_ICM42600_TMST_CONFIG_TMST_EN BIT(0) 333 311 312 + #define INV_ICM42600_REG_SMD_CONFIG 0x0057 313 + #define INV_ICM42600_SMD_CONFIG_WOM_INT_MODE BIT(3) 314 + #define INV_ICM42600_SMD_CONFIG_WOM_MODE BIT(2) 315 + #define INV_ICM42600_SMD_CONFIG_SMD_MODE_OFF 0x00 316 + #define INV_ICM42600_SMD_CONFIG_SMD_MODE_WOM 0x01 317 + #define INV_ICM42600_SMD_CONFIG_SMD_MODE_SHORT 0x02 318 + #define INV_ICM42600_SMD_CONFIG_SMD_MODE_LONG 0x03 319 + 334 320 #define INV_ICM42600_REG_FIFO_CONFIG1 0x005F 335 321 #define INV_ICM42600_FIFO_CONFIG1_RESUME_PARTIAL_RD BIT(6) 336 322 #define INV_ICM42600_FIFO_CONFIG1_WM_GT_TH BIT(5) ··· 367 337 #define INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN BIT(2) 368 338 #define INV_ICM42600_INT_SOURCE0_FIFO_FULL_INT1_EN BIT(1) 369 339 #define INV_ICM42600_INT_SOURCE0_UI_AGC_RDY_INT1_EN BIT(0) 340 + 341 + #define INV_ICM42600_REG_INT_SOURCE1 0x0066 342 + #define INV_ICM42600_INT_SOURCE1_I3C_ERROR_INT1_EN BIT(6) 343 + #define INV_ICM42600_INT_SOURCE1_SMD_INT1_EN BIT(3) 344 + #define INV_ICM42600_INT_SOURCE1_WOM_INT1_EN GENMASK(2, 0) 370 345 371 346 #define INV_ICM42600_REG_WHOAMI 0x0075 372 347 #define INV_ICM42600_WHOAMI_ICM42600 0x40 ··· 408 373 #define INV_ICM42600_INTF_CONFIG6_I3C_SDR_EN BIT(0) 409 374 410 375 /* User bank 4 (MSB 0x40) */ 376 + #define INV_ICM42600_REG_ACCEL_WOM_X_THR 0x404A 377 + #define INV_ICM42600_REG_ACCEL_WOM_Y_THR 0x404B 378 + #define INV_ICM42600_REG_ACCEL_WOM_Z_THR 0x404C 379 + 411 380 #define INV_ICM42600_REG_INT_SOURCE8 0x404F 412 381 #define INV_ICM42600_INT_SOURCE8_FSYNC_IBI_EN BIT(5) 413 382 #define INV_ICM42600_INT_SOURCE8_PLL_RDY_IBI_EN BIT(4) ··· 462 423 int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable, 463 424 unsigned int *sleep_ms); 464 425 426 + int inv_icm42600_enable_wom(struct inv_icm42600_state *st); 427 + int inv_icm42600_disable_wom(struct inv_icm42600_state *st); 428 + 465 429 int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg, 466 430 unsigned int writeval, unsigned int *readval); 467 431 ··· 478 436 struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st); 479 437 480 438 int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev); 439 + 440 + void inv_icm42600_accel_handle_events(struct iio_dev *indio_dev, 441 + unsigned int status2, unsigned int status3, 442 + s64 timestamp); 481 443 482 444 #endif
+321 -3
drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
··· 10 10 #include <linux/regmap.h> 11 11 #include <linux/delay.h> 12 12 #include <linux/math64.h> 13 + #include <linux/minmax.h> 14 + #include <linux/units.h> 13 15 14 16 #include <linux/iio/buffer.h> 15 17 #include <linux/iio/common/inv_sensors_timestamp.h> 18 + #include <linux/iio/events.h> 16 19 #include <linux/iio/iio.h> 17 20 #include <linux/iio/kfifo_buf.h> 18 21 ··· 48 45 .endianness = IIO_BE, \ 49 46 }, \ 50 47 .ext_info = _ext_info, \ 48 + } 49 + 50 + #define INV_ICM42600_ACCEL_EVENT_CHAN(_modifier, _events, _events_nb) \ 51 + { \ 52 + .type = IIO_ACCEL, \ 53 + .modified = 1, \ 54 + .channel2 = _modifier, \ 55 + .event_spec = _events, \ 56 + .num_event_specs = _events_nb, \ 57 + .scan_index = -1, \ 51 58 } 52 59 53 60 enum inv_icm42600_accel_scan { ··· 95 82 if (idx >= ARRAY_SIZE(inv_icm42600_accel_power_mode_values)) 96 83 return -EINVAL; 97 84 98 - if (iio_buffer_enabled(indio_dev)) 99 - return -EBUSY; 100 - 101 85 power_mode = inv_icm42600_accel_power_mode_values[idx]; 102 86 filter = inv_icm42600_accel_filter_values[idx]; 103 87 104 88 guard(mutex)(&st->lock); 89 + 90 + /* cannot change if accel sensor is on */ 91 + if (st->conf.accel.mode != INV_ICM42600_SENSOR_MODE_OFF) 92 + return -EBUSY; 105 93 106 94 /* prevent change if power mode is not supported by the ODR */ 107 95 switch (power_mode) { ··· 174 160 { } 175 161 }; 176 162 163 + /* WoM event: rising ROC */ 164 + static const struct iio_event_spec inv_icm42600_wom_events[] = { 165 + { 166 + .type = IIO_EV_TYPE_ROC, 167 + .dir = IIO_EV_DIR_RISING, 168 + .mask_separate = BIT(IIO_EV_INFO_ENABLE) | 169 + BIT(IIO_EV_INFO_VALUE), 170 + }, 171 + }; 172 + 177 173 static const struct iio_chan_spec inv_icm42600_accel_channels[] = { 178 174 INV_ICM42600_ACCEL_CHAN(IIO_MOD_X, INV_ICM42600_ACCEL_SCAN_X, 179 175 inv_icm42600_accel_ext_infos), ··· 193 169 inv_icm42600_accel_ext_infos), 194 170 INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP), 195 171 IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42600_ACCEL_SCAN_TIMESTAMP), 172 + INV_ICM42600_ACCEL_EVENT_CHAN(IIO_MOD_X_OR_Y_OR_Z, inv_icm42600_wom_events, 173 + ARRAY_SIZE(inv_icm42600_wom_events)), 196 174 }; 197 175 198 176 /* ··· 318 292 pm_runtime_mark_last_busy(dev); 319 293 pm_runtime_put_autosuspend(dev); 320 294 return ret; 295 + } 296 + 297 + static unsigned int inv_icm42600_accel_convert_roc_to_wom(u64 roc, 298 + int accel_hz, int accel_uhz) 299 + { 300 + /* 1000/256mg per LSB converted in µm/s² */ 301 + const unsigned int convert = (9807U * (MICRO / MILLI)) / 256U; 302 + u64 value; 303 + u64 freq_uhz; 304 + 305 + /* return 0 only if roc is 0 */ 306 + if (roc == 0) 307 + return 0; 308 + 309 + freq_uhz = (u64)accel_hz * MICRO + (u64)accel_uhz; 310 + value = div64_u64(roc * MICRO, freq_uhz * (u64)convert); 311 + 312 + /* limit value to 8 bits and prevent 0 */ 313 + return clamp(value, 1, 255); 314 + } 315 + 316 + static u64 inv_icm42600_accel_convert_wom_to_roc(unsigned int threshold, 317 + int accel_hz, int accel_uhz) 318 + { 319 + /* 1000/256mg per LSB converted in µm/s² */ 320 + const unsigned int convert = (9807U * (MICRO / MILLI)) / 256U; 321 + u64 value; 322 + u64 freq_uhz; 323 + 324 + value = threshold * convert; 325 + freq_uhz = (u64)accel_hz * MICRO + (u64)accel_uhz; 326 + 327 + /* compute the differential by multiplying by the frequency */ 328 + return div_u64(value * freq_uhz, MICRO); 329 + } 330 + 331 + static int inv_icm42600_accel_set_wom_threshold(struct inv_icm42600_state *st, 332 + u64 value, 333 + int accel_hz, int accel_uhz) 334 + { 335 + unsigned int threshold; 336 + int ret; 337 + 338 + /* convert roc to wom threshold and convert back to handle clipping */ 339 + threshold = inv_icm42600_accel_convert_roc_to_wom(value, accel_hz, accel_uhz); 340 + value = inv_icm42600_accel_convert_wom_to_roc(threshold, accel_hz, accel_uhz); 341 + 342 + dev_dbg(regmap_get_device(st->map), "wom_threshold: 0x%x\n", threshold); 343 + 344 + /* set accel WoM threshold for the 3 axes */ 345 + st->buffer[0] = threshold; 346 + st->buffer[1] = threshold; 347 + st->buffer[2] = threshold; 348 + ret = regmap_bulk_write(st->map, INV_ICM42600_REG_ACCEL_WOM_X_THR, st->buffer, 3); 349 + if (ret) 350 + return ret; 351 + 352 + st->apex.wom.value = value; 353 + 354 + return 0; 355 + } 356 + 357 + static int _inv_icm42600_accel_enable_wom(struct iio_dev *indio_dev) 358 + { 359 + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); 360 + struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev); 361 + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; 362 + unsigned int sleep_ms = 0; 363 + int ret; 364 + 365 + scoped_guard(mutex, &st->lock) { 366 + /* turn on accel sensor */ 367 + conf.mode = accel_st->power_mode; 368 + conf.filter = accel_st->filter; 369 + ret = inv_icm42600_set_accel_conf(st, &conf, &sleep_ms); 370 + if (ret) 371 + return ret; 372 + } 373 + 374 + if (sleep_ms) 375 + msleep(sleep_ms); 376 + 377 + scoped_guard(mutex, &st->lock) { 378 + ret = inv_icm42600_enable_wom(st); 379 + if (ret) 380 + return ret; 381 + st->apex.on++; 382 + st->apex.wom.enable = true; 383 + } 384 + 385 + return 0; 386 + } 387 + 388 + static int inv_icm42600_accel_enable_wom(struct iio_dev *indio_dev) 389 + { 390 + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); 391 + struct device *pdev = regmap_get_device(st->map); 392 + int ret; 393 + 394 + ret = pm_runtime_resume_and_get(pdev); 395 + if (ret) 396 + return ret; 397 + 398 + ret = _inv_icm42600_accel_enable_wom(indio_dev); 399 + if (ret) { 400 + pm_runtime_mark_last_busy(pdev); 401 + pm_runtime_put_autosuspend(pdev); 402 + return ret; 403 + } 404 + 405 + return 0; 406 + } 407 + 408 + static int _inv_icm42600_accel_disable_wom(struct iio_dev *indio_dev) 409 + { 410 + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); 411 + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; 412 + unsigned int sleep_ms = 0; 413 + int ret; 414 + 415 + scoped_guard(mutex, &st->lock) { 416 + /* 417 + * Consider that turning off WoM is always working to avoid 418 + * blocking the chip in on mode and prevent going back to sleep. 419 + * If there is an error, the chip will anyway go back to sleep 420 + * and the feature will not work anymore. 421 + */ 422 + st->apex.wom.enable = false; 423 + st->apex.on--; 424 + ret = inv_icm42600_disable_wom(st); 425 + if (ret) 426 + return ret; 427 + /* turn off accel sensor if not used */ 428 + if (!st->apex.on && !iio_buffer_enabled(indio_dev)) { 429 + conf.mode = INV_ICM42600_SENSOR_MODE_OFF; 430 + ret = inv_icm42600_set_accel_conf(st, &conf, &sleep_ms); 431 + if (ret) 432 + return ret; 433 + } 434 + } 435 + 436 + if (sleep_ms) 437 + msleep(sleep_ms); 438 + 439 + return 0; 440 + } 441 + 442 + static int inv_icm42600_accel_disable_wom(struct iio_dev *indio_dev) 443 + { 444 + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); 445 + struct device *pdev = regmap_get_device(st->map); 446 + int ret; 447 + 448 + ret = _inv_icm42600_accel_disable_wom(indio_dev); 449 + 450 + pm_runtime_mark_last_busy(pdev); 451 + pm_runtime_put_autosuspend(pdev); 452 + 453 + return ret; 454 + } 455 + 456 + void inv_icm42600_accel_handle_events(struct iio_dev *indio_dev, 457 + unsigned int status2, unsigned int status3, 458 + s64 timestamp) 459 + { 460 + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); 461 + u64 ev_code; 462 + 463 + /* handle WoM event */ 464 + if (st->apex.wom.enable && (status2 & INV_ICM42600_INT_STATUS2_WOM_INT)) { 465 + ev_code = IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z, 466 + IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING); 467 + iio_push_event(indio_dev, ev_code, timestamp); 468 + } 321 469 } 322 470 323 471 /* IIO format int + nano */ ··· 664 464 goto out_unlock; 665 465 666 466 ret = inv_icm42600_set_accel_conf(st, &conf, NULL); 467 + if (ret) 468 + goto out_unlock; 469 + /* update wom threshold since roc is dependent on sampling frequency */ 470 + ret = inv_icm42600_accel_set_wom_threshold(st, st->apex.wom.value, val, val2); 667 471 if (ret) 668 472 goto out_unlock; 669 473 inv_icm42600_buffer_update_fifo_period(st); ··· 1023 819 return ret; 1024 820 } 1025 821 822 + static int inv_icm42600_accel_read_event_config(struct iio_dev *indio_dev, 823 + const struct iio_chan_spec *chan, 824 + enum iio_event_type type, 825 + enum iio_event_direction dir) 826 + { 827 + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); 828 + 829 + /* handle only WoM (roc rising) event */ 830 + if (type != IIO_EV_TYPE_ROC || dir != IIO_EV_DIR_RISING) 831 + return -EINVAL; 832 + 833 + guard(mutex)(&st->lock); 834 + 835 + return st->apex.wom.enable ? 1 : 0; 836 + } 837 + 838 + static int inv_icm42600_accel_write_event_config(struct iio_dev *indio_dev, 839 + const struct iio_chan_spec *chan, 840 + enum iio_event_type type, 841 + enum iio_event_direction dir, 842 + bool state) 843 + { 844 + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); 845 + 846 + /* handle only WoM (roc rising) event */ 847 + if (type != IIO_EV_TYPE_ROC || dir != IIO_EV_DIR_RISING) 848 + return -EINVAL; 849 + 850 + scoped_guard(mutex, &st->lock) { 851 + if (st->apex.wom.enable == state) 852 + return 0; 853 + } 854 + 855 + if (state) 856 + return inv_icm42600_accel_enable_wom(indio_dev); 857 + 858 + return inv_icm42600_accel_disable_wom(indio_dev); 859 + } 860 + 861 + static int inv_icm42600_accel_read_event_value(struct iio_dev *indio_dev, 862 + const struct iio_chan_spec *chan, 863 + enum iio_event_type type, 864 + enum iio_event_direction dir, 865 + enum iio_event_info info, 866 + int *val, int *val2) 867 + { 868 + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); 869 + u32 rem; 870 + 871 + /* handle only WoM (roc rising) event value */ 872 + if (type != IIO_EV_TYPE_ROC || dir != IIO_EV_DIR_RISING) 873 + return -EINVAL; 874 + 875 + guard(mutex)(&st->lock); 876 + 877 + /* return value in micro */ 878 + *val = div_u64_rem(st->apex.wom.value, MICRO, &rem); 879 + *val2 = rem; 880 + return IIO_VAL_INT_PLUS_MICRO; 881 + } 882 + 883 + static int _inv_icm42600_accel_wom_value(struct inv_icm42600_state *st, 884 + int val, int val2) 885 + { 886 + u64 value; 887 + unsigned int accel_hz, accel_uhz; 888 + int ret; 889 + 890 + guard(mutex)(&st->lock); 891 + 892 + ret = inv_icm42600_accel_read_odr(st, &accel_hz, &accel_uhz); 893 + if (ret < 0) 894 + return ret; 895 + 896 + value = (u64)val * MICRO + (u64)val2; 897 + 898 + return inv_icm42600_accel_set_wom_threshold(st, value, 899 + accel_hz, accel_uhz); 900 + } 901 + 902 + static int inv_icm42600_accel_write_event_value(struct iio_dev *indio_dev, 903 + const struct iio_chan_spec *chan, 904 + enum iio_event_type type, 905 + enum iio_event_direction dir, 906 + enum iio_event_info info, 907 + int val, int val2) 908 + { 909 + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); 910 + struct device *dev = regmap_get_device(st->map); 911 + int ret; 912 + 913 + /* handle only WoM (roc rising) event value */ 914 + if (type != IIO_EV_TYPE_ROC || dir != IIO_EV_DIR_RISING) 915 + return -EINVAL; 916 + 917 + if (val < 0 || val2 < 0) 918 + return -EINVAL; 919 + 920 + ret = pm_runtime_resume_and_get(dev); 921 + if (ret) 922 + return ret; 923 + 924 + ret = _inv_icm42600_accel_wom_value(st, val, val2); 925 + 926 + pm_runtime_mark_last_busy(dev); 927 + pm_runtime_put_autosuspend(dev); 928 + 929 + return ret; 930 + } 931 + 1026 932 static const struct iio_info inv_icm42600_accel_info = { 1027 933 .read_raw = inv_icm42600_accel_read_raw, 1028 934 .read_avail = inv_icm42600_accel_read_avail, ··· 1142 828 .update_scan_mode = inv_icm42600_accel_update_scan_mode, 1143 829 .hwfifo_set_watermark = inv_icm42600_accel_hwfifo_set_watermark, 1144 830 .hwfifo_flush_to_buffer = inv_icm42600_accel_hwfifo_flush, 831 + .read_event_config = inv_icm42600_accel_read_event_config, 832 + .write_event_config = inv_icm42600_accel_write_event_config, 833 + .read_event_value = inv_icm42600_accel_read_event_value, 834 + .write_event_value = inv_icm42600_accel_write_event_value, 1145 835 }; 1146 836 1147 837 struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st)
+1 -1
drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c
··· 422 422 conf.mode = INV_ICM42600_SENSOR_MODE_OFF; 423 423 if (sensor == INV_ICM42600_SENSOR_GYRO) 424 424 ret = inv_icm42600_set_gyro_conf(st, &conf, &sleep_sensor); 425 - else 425 + else if (!st->apex.on) 426 426 ret = inv_icm42600_set_accel_conf(st, &conf, &sleep_sensor); 427 427 if (ret) 428 428 goto out_unlock;
+58
drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
··· 404 404 sleep_ms); 405 405 } 406 406 407 + int 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 + 423 + int 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 + 407 438 int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg, 408 439 unsigned int writeval, unsigned int *readval) 409 440 { ··· 578 547 int ret; 579 548 580 549 mutex_lock(&st->lock); 550 + 551 + if (st->apex.on) { 552 + unsigned int status2, status3; 553 + 554 + /* read INT_STATUS2 and INT_STATUS3 in 1 operation */ 555 + ret = regmap_bulk_read(st->map, INV_ICM42600_REG_INT_STATUS2, st->buffer, 2); 556 + if (ret) 557 + goto out_unlock; 558 + status2 = st->buffer[0]; 559 + status3 = st->buffer[1]; 560 + inv_icm42600_accel_handle_events(st->indio_accel, status2, status3, 561 + st->timestamp.accel); 562 + } 581 563 582 564 ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, &status); 583 565 if (ret) ··· 863 819 goto out_unlock; 864 820 } 865 821 822 + /* disable APEX features */ 823 + if (st->apex.wom.enable) { 824 + ret = inv_icm42600_disable_wom(st); 825 + if (ret) 826 + goto out_unlock; 827 + } 828 + 866 829 ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF, 867 830 INV_ICM42600_SENSOR_MODE_OFF, false, 868 831 NULL); ··· 910 859 st->suspended.temp, NULL); 911 860 if (ret) 912 861 goto out_unlock; 862 + 863 + /* restore APEX features */ 864 + if (st->apex.wom.enable) { 865 + ret = inv_icm42600_enable_wom(st); 866 + if (ret) 867 + goto out_unlock; 868 + } 913 869 914 870 /* restore FIFO data streaming */ 915 871 if (st->fifo.on) {