File Index
Files and directories
Sign in
FILE

inv_icm42600_accel.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 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/mutex.h>
   9#include <linux/pm_runtime.h>
  10#include <linux/regmap.h>
  11#include <linux/delay.h>
  12#include <linux/math64.h>
  13#include <linux/minmax.h>
  14#include <linux/units.h>
  15
  16#include <linux/iio/buffer.h>
  17#include <linux/iio/common/inv_sensors_timestamp.h>
  18#include <linux/iio/events.h>
  19#include <linux/iio/iio.h>
  20#include <linux/iio/kfifo_buf.h>
  21
  22#include "inv_icm42600.h"
  23#include "inv_icm42600_temp.h"
  24#include "inv_icm42600_buffer.h"
  25
  26#define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)		\
  27	{								\
  28		.type = IIO_ACCEL,					\
  29		.modified = 1,						\
  30		.channel2 = _modifier,					\
  31		.info_mask_separate =					\
  32			BIT(IIO_CHAN_INFO_RAW) |			\
  33			BIT(IIO_CHAN_INFO_CALIBBIAS),			\
  34		.info_mask_shared_by_type =				\
  35			BIT(IIO_CHAN_INFO_SCALE),			\
  36		.info_mask_shared_by_type_available =			\
  37			BIT(IIO_CHAN_INFO_SCALE) |			\
  38			BIT(IIO_CHAN_INFO_CALIBBIAS),			\
  39		.info_mask_shared_by_all =				\
  40			BIT(IIO_CHAN_INFO_SAMP_FREQ),			\
  41		.info_mask_shared_by_all_available =			\
  42			BIT(IIO_CHAN_INFO_SAMP_FREQ),			\
  43		.scan_index = _index,					\
  44		.scan_type = {						\
  45			.sign = 's',					\
  46			.realbits = 16,					\
  47			.storagebits = 16,				\
  48			.endianness = IIO_BE,				\
  49		},							\
  50		.ext_info = _ext_info,					\
  51	}
  52
  53#define INV_ICM42600_ACCEL_EVENT_CHAN(_modifier, _events, _events_nb)	\
  54	{								\
  55		.type = IIO_ACCEL,					\
  56		.modified = 1,						\
  57		.channel2 = _modifier,					\
  58		.event_spec = _events,					\
  59		.num_event_specs = _events_nb,				\
  60		.scan_index = -1,					\
  61	}
  62
  63enum inv_icm42600_accel_scan {
  64	INV_ICM42600_ACCEL_SCAN_X,
  65	INV_ICM42600_ACCEL_SCAN_Y,
  66	INV_ICM42600_ACCEL_SCAN_Z,
  67	INV_ICM42600_ACCEL_SCAN_TEMP,
  68	INV_ICM42600_ACCEL_SCAN_TIMESTAMP,
  69};
  70
  71static const char * const inv_icm42600_accel_power_mode_items[] = {
  72	"low-noise",
  73	"low-power",
  74};
  75static const int inv_icm42600_accel_power_mode_values[] = {
  76	INV_ICM42600_SENSOR_MODE_LOW_NOISE,
  77	INV_ICM42600_SENSOR_MODE_LOW_POWER,
  78};
  79static const int inv_icm42600_accel_filter_values[] = {
  80	INV_ICM42600_FILTER_BW_ODR_DIV_2,
  81	INV_ICM42600_FILTER_AVG_16X,
  82};
  83
  84static int inv_icm42600_accel_power_mode_set(struct iio_dev *indio_dev,
  85					     const struct iio_chan_spec *chan,
  86					     unsigned int idx)
  87{
  88	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
  89	struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev);
  90	int power_mode, filter;
  91
  92	if (chan->type != IIO_ACCEL)
  93		return -EINVAL;
  94
  95	if (idx >= ARRAY_SIZE(inv_icm42600_accel_power_mode_values))
  96		return -EINVAL;
  97
  98	power_mode = inv_icm42600_accel_power_mode_values[idx];
  99	filter = inv_icm42600_accel_filter_values[idx];
 100
 101	guard(mutex)(&st->lock);
 102
 103	/* cannot change if accel sensor is on */
 104	if (st->conf.accel.mode != INV_ICM42600_SENSOR_MODE_OFF)
 105		return -EBUSY;
 106
 107	/* prevent change if power mode is not supported by the ODR */
 108	switch (power_mode) {
 109	case INV_ICM42600_SENSOR_MODE_LOW_NOISE:
 110		if (st->conf.accel.odr >= INV_ICM42600_ODR_6_25HZ_LP &&
 111		    st->conf.accel.odr <= INV_ICM42600_ODR_1_5625HZ_LP)
 112			return -EPERM;
 113		break;
 114	case INV_ICM42600_SENSOR_MODE_LOW_POWER:
 115	default:
 116		if (st->conf.accel.odr <= INV_ICM42600_ODR_1KHZ_LN)
 117			return -EPERM;
 118		break;
 119	}
 120
 121	accel_st->power_mode = power_mode;
 122	accel_st->filter = filter;
 123
 124	return 0;
 125}
 126
 127static int inv_icm42600_accel_power_mode_get(struct iio_dev *indio_dev,
 128					     const struct iio_chan_spec *chan)
 129{
 130	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
 131	struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev);
 132	unsigned int idx;
 133	int power_mode;
 134
 135	if (chan->type != IIO_ACCEL)
 136		return -EINVAL;
 137
 138	guard(mutex)(&st->lock);
 139
 140	/* if sensor is on, returns actual power mode and not configured one */
 141	switch (st->conf.accel.mode) {
 142	case INV_ICM42600_SENSOR_MODE_LOW_POWER:
 143	case INV_ICM42600_SENSOR_MODE_LOW_NOISE:
 144		power_mode = st->conf.accel.mode;
 145		break;
 146	default:
 147		power_mode = accel_st->power_mode;
 148		break;
 149	}
 150
 151	for (idx = 0; idx < ARRAY_SIZE(inv_icm42600_accel_power_mode_values); ++idx) {
 152		if (power_mode == inv_icm42600_accel_power_mode_values[idx])
 153			break;
 154	}
 155	if (idx >= ARRAY_SIZE(inv_icm42600_accel_power_mode_values))
 156		return -EINVAL;
 157
 158	return idx;
 159}
 160
 161static const struct iio_enum inv_icm42600_accel_power_mode_enum = {
 162	.items = inv_icm42600_accel_power_mode_items,
 163	.num_items = ARRAY_SIZE(inv_icm42600_accel_power_mode_items),
 164	.set = inv_icm42600_accel_power_mode_set,
 165	.get = inv_icm42600_accel_power_mode_get,
 166};
 167
 168static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = {
 169	IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42600_get_mount_matrix),
 170	IIO_ENUM_AVAILABLE("power_mode", IIO_SHARED_BY_TYPE,
 171			   &inv_icm42600_accel_power_mode_enum),
 172	IIO_ENUM("power_mode", IIO_SHARED_BY_TYPE,
 173		 &inv_icm42600_accel_power_mode_enum),
 174	{ }
 175};
 176
 177/* WoM event: rising ROC */
 178static const struct iio_event_spec inv_icm42600_wom_events[] = {
 179	{
 180		.type = IIO_EV_TYPE_ROC,
 181		.dir = IIO_EV_DIR_RISING,
 182		.mask_separate = BIT(IIO_EV_INFO_ENABLE) |
 183				 BIT(IIO_EV_INFO_VALUE),
 184	},
 185};
 186
 187static const struct iio_chan_spec inv_icm42600_accel_channels[] = {
 188	INV_ICM42600_ACCEL_CHAN(IIO_MOD_X, INV_ICM42600_ACCEL_SCAN_X,
 189				inv_icm42600_accel_ext_infos),
 190	INV_ICM42600_ACCEL_CHAN(IIO_MOD_Y, INV_ICM42600_ACCEL_SCAN_Y,
 191				inv_icm42600_accel_ext_infos),
 192	INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z,
 193				inv_icm42600_accel_ext_infos),
 194	INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP),
 195	IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42600_ACCEL_SCAN_TIMESTAMP),
 196	INV_ICM42600_ACCEL_EVENT_CHAN(IIO_MOD_X_OR_Y_OR_Z, inv_icm42600_wom_events,
 197				      ARRAY_SIZE(inv_icm42600_wom_events)),
 198};
 199
 200/*
 201 * IIO buffer data: size must be a power of 2 and timestamp aligned
 202 * 16 bytes: 6 bytes acceleration, 2 bytes temperature, 8 bytes timestamp
 203 */
 204struct inv_icm42600_accel_buffer {
 205	struct inv_icm42600_fifo_sensor_data accel;
 206	s16 temp;
 207	aligned_s64 timestamp;
 208};
 209
 210#define INV_ICM42600_SCAN_MASK_ACCEL_3AXIS				\
 211	(BIT(INV_ICM42600_ACCEL_SCAN_X) |				\
 212	BIT(INV_ICM42600_ACCEL_SCAN_Y) |				\
 213	BIT(INV_ICM42600_ACCEL_SCAN_Z))
 214
 215#define INV_ICM42600_SCAN_MASK_TEMP	BIT(INV_ICM42600_ACCEL_SCAN_TEMP)
 216
 217static const unsigned long inv_icm42600_accel_scan_masks[] = {
 218	/* 3-axis accel + temperature */
 219	INV_ICM42600_SCAN_MASK_ACCEL_3AXIS | INV_ICM42600_SCAN_MASK_TEMP,
 220	0,
 221};
 222
 223/* enable accelerometer sensor and FIFO write */
 224static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev,
 225					       const unsigned long *scan_mask)
 226{
 227	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
 228	struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev);
 229	struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
 230	unsigned int fifo_en = 0;
 231	unsigned int sleep_temp = 0;
 232	unsigned int sleep_accel = 0;
 233	unsigned int sleep;
 234	int ret;
 235
 236	mutex_lock(&st->lock);
 237
 238	if (*scan_mask & INV_ICM42600_SCAN_MASK_TEMP) {
 239		/* enable temp sensor */
 240		ret = inv_icm42600_set_temp_conf(st, true, &sleep_temp);
 241		if (ret)
 242			goto out_unlock;
 243		fifo_en |= INV_ICM42600_SENSOR_TEMP;
 244	}
 245
 246	if (*scan_mask & INV_ICM42600_SCAN_MASK_ACCEL_3AXIS) {
 247		/* enable accel sensor */
 248		conf.mode = accel_st->power_mode;
 249		conf.filter = accel_st->filter;
 250		ret = inv_icm42600_set_accel_conf(st, &conf, &sleep_accel);
 251		if (ret)
 252			goto out_unlock;
 253		fifo_en |= INV_ICM42600_SENSOR_ACCEL;
 254	}
 255
 256	/* update data FIFO write */
 257	ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en);
 258
 259out_unlock:
 260	mutex_unlock(&st->lock);
 261	/* sleep maximum required time */
 262	sleep = max(sleep_accel, sleep_temp);
 263	if (sleep)
 264		msleep(sleep);
 265	return ret;
 266}
 267
 268static int inv_icm42600_accel_read_sensor(struct iio_dev *indio_dev,
 269					  struct iio_chan_spec const *chan,
 270					  s16 *val)
 271{
 272	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
 273	struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev);
 274	struct device *dev = regmap_get_device(st->map);
 275	struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
 276	unsigned int reg;
 277	__be16 *data;
 278	int ret;
 279
 280	if (chan->type != IIO_ACCEL)
 281		return -EINVAL;
 282
 283	switch (chan->channel2) {
 284	case IIO_MOD_X:
 285		reg = INV_ICM42600_REG_ACCEL_DATA_X;
 286		break;
 287	case IIO_MOD_Y:
 288		reg = INV_ICM42600_REG_ACCEL_DATA_Y;
 289		break;
 290	case IIO_MOD_Z:
 291		reg = INV_ICM42600_REG_ACCEL_DATA_Z;
 292		break;
 293	default:
 294		return -EINVAL;
 295	}
 296
 297	pm_runtime_get_sync(dev);
 298	mutex_lock(&st->lock);
 299
 300	/* enable accel sensor */
 301	conf.mode = accel_st->power_mode;
 302	conf.filter = accel_st->filter;
 303	ret = inv_icm42600_set_accel_conf(st, &conf, NULL);
 304	if (ret)
 305		goto exit;
 306
 307	/* read accel register data */
 308	data = (__be16 *)&st->buffer[0];
 309	ret = regmap_bulk_read(st->map, reg, data, sizeof(*data));
 310	if (ret)
 311		goto exit;
 312
 313	*val = (s16)be16_to_cpup(data);
 314	if (*val == INV_ICM42600_DATA_INVALID)
 315		ret = -EINVAL;
 316exit:
 317	mutex_unlock(&st->lock);
 318	pm_runtime_put_autosuspend(dev);
 319	return ret;
 320}
 321
 322static unsigned int inv_icm42600_accel_convert_roc_to_wom(u64 roc,
 323							  int accel_hz, int accel_uhz)
 324{
 325	/* 1000/256mg per LSB converted in µm/s² */
 326	const unsigned int convert = (9807U * (MICRO / MILLI)) / 256U;
 327	u64 value;
 328	u64 freq_uhz;
 329
 330	/* return 0 only if roc is 0 */
 331	if (roc == 0)
 332		return 0;
 333
 334	freq_uhz = (u64)accel_hz * MICRO + (u64)accel_uhz;
 335	value = div64_u64(roc * MICRO, freq_uhz * (u64)convert);
 336
 337	/* limit value to 8 bits and prevent 0 */
 338	return clamp(value, 1, 255);
 339}
 340
 341static u64 inv_icm42600_accel_convert_wom_to_roc(unsigned int threshold,
 342						 int accel_hz, int accel_uhz)
 343{
 344	/* 1000/256mg per LSB converted in µm/s² */
 345	const unsigned int convert = (9807U * (MICRO / MILLI)) / 256U;
 346	u64 value;
 347	u64 freq_uhz;
 348
 349	value = threshold * convert;
 350	freq_uhz = (u64)accel_hz * MICRO + (u64)accel_uhz;
 351
 352	/* compute the differential by multiplying by the frequency */
 353	return div_u64(value * freq_uhz, MICRO);
 354}
 355
 356static int inv_icm42600_accel_set_wom_threshold(struct inv_icm42600_state *st,
 357						u64 value,
 358						int accel_hz, int accel_uhz)
 359{
 360	unsigned int threshold;
 361	int ret;
 362
 363	/* convert roc to wom threshold and convert back to handle clipping */
 364	threshold = inv_icm42600_accel_convert_roc_to_wom(value, accel_hz, accel_uhz);
 365	value = inv_icm42600_accel_convert_wom_to_roc(threshold, accel_hz, accel_uhz);
 366
 367	dev_dbg(regmap_get_device(st->map), "wom_threshold: 0x%x\n", threshold);
 368
 369	/* set accel WoM threshold for the 3 axes */
 370	st->buffer[0] = threshold;
 371	st->buffer[1] = threshold;
 372	st->buffer[2] = threshold;
 373	ret = regmap_bulk_write(st->map, INV_ICM42600_REG_ACCEL_WOM_X_THR, st->buffer, 3);
 374	if (ret)
 375		return ret;
 376
 377	st->apex.wom.value = value;
 378
 379	return 0;
 380}
 381
 382static int _inv_icm42600_accel_enable_wom(struct iio_dev *indio_dev)
 383{
 384	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
 385	struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev);
 386	struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
 387	unsigned int sleep_ms = 0;
 388	int ret;
 389
 390	scoped_guard(mutex, &st->lock) {
 391		/* turn on accel sensor */
 392		conf.mode = accel_st->power_mode;
 393		conf.filter = accel_st->filter;
 394		ret = inv_icm42600_set_accel_conf(st, &conf, &sleep_ms);
 395		if (ret)
 396			return ret;
 397	}
 398
 399	if (sleep_ms)
 400		msleep(sleep_ms);
 401
 402	scoped_guard(mutex, &st->lock) {
 403		ret = inv_icm42600_enable_wom(st);
 404		if (ret)
 405			return ret;
 406		st->apex.on++;
 407		st->apex.wom.enable = true;
 408	}
 409
 410	return 0;
 411}
 412
 413static int inv_icm42600_accel_enable_wom(struct iio_dev *indio_dev)
 414{
 415	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
 416	struct device *pdev = regmap_get_device(st->map);
 417	int ret;
 418
 419	ret = pm_runtime_resume_and_get(pdev);
 420	if (ret)
 421		return ret;
 422
 423	ret = _inv_icm42600_accel_enable_wom(indio_dev);
 424	if (ret) {
 425		pm_runtime_mark_last_busy(pdev);
 426		pm_runtime_put_autosuspend(pdev);
 427		return ret;
 428	}
 429
 430	return 0;
 431}
 432
 433static int _inv_icm42600_accel_disable_wom(struct iio_dev *indio_dev)
 434{
 435	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
 436	struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
 437	unsigned int sleep_ms = 0;
 438	int ret;
 439
 440	scoped_guard(mutex, &st->lock) {
 441		/*
 442		 * Consider that turning off WoM is always working to avoid
 443		 * blocking the chip in on mode and prevent going back to sleep.
 444		 * If there is an error, the chip will anyway go back to sleep
 445		 * and the feature will not work anymore.
 446		 */
 447		st->apex.wom.enable = false;
 448		st->apex.on--;
 449		ret = inv_icm42600_disable_wom(st);
 450		if (ret)
 451			return ret;
 452		/* turn off accel sensor if not used */
 453		if (!st->apex.on && !iio_buffer_enabled(indio_dev)) {
 454			conf.mode = INV_ICM42600_SENSOR_MODE_OFF;
 455			ret = inv_icm42600_set_accel_conf(st, &conf, &sleep_ms);
 456			if (ret)
 457				return ret;
 458		}
 459	}
 460
 461	if (sleep_ms)
 462		msleep(sleep_ms);
 463
 464	return 0;
 465}
 466
 467static int inv_icm42600_accel_disable_wom(struct iio_dev *indio_dev)
 468{
 469	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
 470	struct device *pdev = regmap_get_device(st->map);
 471	int ret;
 472
 473	ret = _inv_icm42600_accel_disable_wom(indio_dev);
 474
 475	pm_runtime_mark_last_busy(pdev);
 476	pm_runtime_put_autosuspend(pdev);
 477
 478	return ret;
 479}
 480
 481void inv_icm42600_accel_handle_events(struct iio_dev *indio_dev,
 482				      unsigned int status2, unsigned int status3,
 483				      s64 timestamp)
 484{
 485	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
 486	u64 ev_code;
 487
 488	/* handle WoM event */
 489	if (st->apex.wom.enable && (status2 & INV_ICM42600_INT_STATUS2_WOM_INT)) {
 490		ev_code = IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z,
 491					     IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING);
 492		iio_push_event(indio_dev, ev_code, timestamp);
 493	}
 494}
 495
 496/* IIO format int + nano */
 497static const int inv_icm42600_accel_scale[] = {
 498	/* +/- 16G => 0.004788403 m/s-2 */
 499	[2 * INV_ICM42600_ACCEL_FS_16G] = 0,
 500	[2 * INV_ICM42600_ACCEL_FS_16G + 1] = 4788403,
 501	/* +/- 8G => 0.002394202 m/s-2 */
 502	[2 * INV_ICM42600_ACCEL_FS_8G] = 0,
 503	[2 * INV_ICM42600_ACCEL_FS_8G + 1] = 2394202,
 504	/* +/- 4G => 0.001197101 m/s-2 */
 505	[2 * INV_ICM42600_ACCEL_FS_4G] = 0,
 506	[2 * INV_ICM42600_ACCEL_FS_4G + 1] = 1197101,
 507	/* +/- 2G => 0.000598550 m/s-2 */
 508	[2 * INV_ICM42600_ACCEL_FS_2G] = 0,
 509	[2 * INV_ICM42600_ACCEL_FS_2G + 1] = 598550,
 510};
 511static const int inv_icm42686_accel_scale[] = {
 512	/* +/- 32G => 0.009576807 m/s-2 */
 513	[2 * INV_ICM42686_ACCEL_FS_32G] = 0,
 514	[2 * INV_ICM42686_ACCEL_FS_32G + 1] = 9576807,
 515	/* +/- 16G => 0.004788403 m/s-2 */
 516	[2 * INV_ICM42686_ACCEL_FS_16G] = 0,
 517	[2 * INV_ICM42686_ACCEL_FS_16G + 1] = 4788403,
 518	/* +/- 8G => 0.002394202 m/s-2 */
 519	[2 * INV_ICM42686_ACCEL_FS_8G] = 0,
 520	[2 * INV_ICM42686_ACCEL_FS_8G + 1] = 2394202,
 521	/* +/- 4G => 0.001197101 m/s-2 */
 522	[2 * INV_ICM42686_ACCEL_FS_4G] = 0,
 523	[2 * INV_ICM42686_ACCEL_FS_4G + 1] = 1197101,
 524	/* +/- 2G => 0.000598550 m/s-2 */
 525	[2 * INV_ICM42686_ACCEL_FS_2G] = 0,
 526	[2 * INV_ICM42686_ACCEL_FS_2G + 1] = 598550,
 527};
 528
 529static int inv_icm42600_accel_read_scale(struct iio_dev *indio_dev,
 530					 int *val, int *val2)
 531{
 532	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
 533	struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev);
 534	unsigned int idx;
 535
 536	idx = st->conf.accel.fs;
 537
 538	*val = accel_st->scales[2 * idx];
 539	*val2 = accel_st->scales[2 * idx + 1];
 540	return IIO_VAL_INT_PLUS_NANO;
 541}
 542
 543static int inv_icm42600_accel_write_scale(struct iio_dev *indio_dev,
 544					  int val, int val2)
 545{
 546	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
 547	struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev);
 548	struct device *dev = regmap_get_device(st->map);
 549	unsigned int idx;
 550	struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
 551	int ret;
 552
 553	for (idx = 0; idx < accel_st->scales_len; idx += 2) {
 554		if (val == accel_st->scales[idx] &&
 555		    val2 == accel_st->scales[idx + 1])
 556			break;
 557	}
 558	if (idx >= accel_st->scales_len)
 559		return -EINVAL;
 560
 561	conf.fs = idx / 2;
 562
 563	pm_runtime_get_sync(dev);
 564
 565	scoped_guard(mutex, &st->lock)
 566		ret = inv_icm42600_set_accel_conf(st, &conf, NULL);
 567
 568	pm_runtime_put_autosuspend(dev);
 569
 570	return ret;
 571}
 572
 573/* IIO format int + micro */
 574static const int inv_icm42600_accel_odr[] = {
 575	/* 1.5625Hz */
 576	1, 562500,
 577	/* 3.125Hz */
 578	3, 125000,
 579	/* 6.25Hz */
 580	6, 250000,
 581	/* 12.5Hz */
 582	12, 500000,
 583	/* 25Hz */
 584	25, 0,
 585	/* 50Hz */
 586	50, 0,
 587	/* 100Hz */
 588	100, 0,
 589	/* 200Hz */
 590	200, 0,
 591	/* 1kHz */
 592	1000, 0,
 593	/* 2kHz */
 594	2000, 0,
 595	/* 4kHz */
 596	4000, 0,
 597};
 598
 599static const int inv_icm42600_accel_odr_conv[] = {
 600	INV_ICM42600_ODR_1_5625HZ_LP,
 601	INV_ICM42600_ODR_3_125HZ_LP,
 602	INV_ICM42600_ODR_6_25HZ_LP,
 603	INV_ICM42600_ODR_12_5HZ,
 604	INV_ICM42600_ODR_25HZ,
 605	INV_ICM42600_ODR_50HZ,
 606	INV_ICM42600_ODR_100HZ,
 607	INV_ICM42600_ODR_200HZ,
 608	INV_ICM42600_ODR_1KHZ_LN,
 609	INV_ICM42600_ODR_2KHZ_LN,
 610	INV_ICM42600_ODR_4KHZ_LN,
 611};
 612
 613static int inv_icm42600_accel_read_odr(struct inv_icm42600_state *st,
 614				       int *val, int *val2)
 615{
 616	unsigned int odr;
 617	unsigned int i;
 618
 619	odr = st->conf.accel.odr;
 620
 621	for (i = 0; i < ARRAY_SIZE(inv_icm42600_accel_odr_conv); ++i) {
 622		if (inv_icm42600_accel_odr_conv[i] == odr)
 623			break;
 624	}
 625	if (i >= ARRAY_SIZE(inv_icm42600_accel_odr_conv))
 626		return -EINVAL;
 627
 628	*val = inv_icm42600_accel_odr[2 * i];
 629	*val2 = inv_icm42600_accel_odr[2 * i + 1];
 630
 631	return IIO_VAL_INT_PLUS_MICRO;
 632}
 633
 634static int inv_icm42600_accel_write_odr(struct iio_dev *indio_dev,
 635					int val, int val2)
 636{
 637	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
 638	struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev);
 639	struct inv_sensors_timestamp *ts = &accel_st->ts;
 640	struct device *dev = regmap_get_device(st->map);
 641	unsigned int idx;
 642	struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
 643	int ret;
 644
 645	for (idx = 0; idx < ARRAY_SIZE(inv_icm42600_accel_odr); idx += 2) {
 646		if (val == inv_icm42600_accel_odr[idx] &&
 647		    val2 == inv_icm42600_accel_odr[idx + 1])
 648			break;
 649	}
 650	if (idx >= ARRAY_SIZE(inv_icm42600_accel_odr))
 651		return -EINVAL;
 652
 653	conf.odr = inv_icm42600_accel_odr_conv[idx / 2];
 654	if (conf.odr == st->conf.accel.odr)
 655		return 0;
 656
 657	pm_runtime_get_sync(dev);
 658	mutex_lock(&st->lock);
 659
 660	ret = inv_sensors_timestamp_update_odr(ts, inv_icm42600_odr_to_period(conf.odr),
 661					       iio_buffer_enabled(indio_dev));
 662	if (ret)
 663		goto out_unlock;
 664
 665	ret = inv_icm42600_set_accel_conf(st, &conf, NULL);
 666	if (ret)
 667		goto out_unlock;
 668	/* update wom threshold since roc is dependent on sampling frequency */
 669	ret = inv_icm42600_accel_set_wom_threshold(st, st->apex.wom.value, val, val2);
 670	if (ret)
 671		goto out_unlock;
 672	inv_icm42600_buffer_update_fifo_period(st);
 673	inv_icm42600_buffer_update_watermark(st);
 674
 675out_unlock:
 676	mutex_unlock(&st->lock);
 677	pm_runtime_put_autosuspend(dev);
 678
 679	return ret;
 680}
 681
 682/*
 683 * Calibration bias values, IIO range format int + micro.
 684 * Value is limited to +/-1g coded on 12 bits signed. Step is 0.5mg.
 685 */
 686static int inv_icm42600_accel_calibbias[] = {
 687	-10, 42010,		/* min: -10.042010 m/s² */
 688	0, 4903,		/* step: 0.004903 m/s² */
 689	10, 37106,		/* max: 10.037106 m/s² */
 690};
 691
 692static int inv_icm42600_accel_read_offset(struct inv_icm42600_state *st,
 693					  struct iio_chan_spec const *chan,
 694					  int *val, int *val2)
 695{
 696	struct device *dev = regmap_get_device(st->map);
 697	s64 val64;
 698	s32 bias;
 699	unsigned int reg;
 700	s16 offset;
 701	u8 data[2];
 702	int ret;
 703
 704	if (chan->type != IIO_ACCEL)
 705		return -EINVAL;
 706
 707	switch (chan->channel2) {
 708	case IIO_MOD_X:
 709		reg = INV_ICM42600_REG_OFFSET_USER4;
 710		break;
 711	case IIO_MOD_Y:
 712		reg = INV_ICM42600_REG_OFFSET_USER6;
 713		break;
 714	case IIO_MOD_Z:
 715		reg = INV_ICM42600_REG_OFFSET_USER7;
 716		break;
 717	default:
 718		return -EINVAL;
 719	}
 720
 721	pm_runtime_get_sync(dev);
 722	mutex_lock(&st->lock);
 723
 724	ret = regmap_bulk_read(st->map, reg, st->buffer, sizeof(data));
 725	memcpy(data, st->buffer, sizeof(data));
 726
 727	mutex_unlock(&st->lock);
 728	pm_runtime_put_autosuspend(dev);
 729	if (ret)
 730		return ret;
 731
 732	/* 12 bits signed value */
 733	switch (chan->channel2) {
 734	case IIO_MOD_X:
 735		offset = sign_extend32(((data[0] & 0xF0) << 4) | data[1], 11);
 736		break;
 737	case IIO_MOD_Y:
 738		offset = sign_extend32(((data[1] & 0x0F) << 8) | data[0], 11);
 739		break;
 740	case IIO_MOD_Z:
 741		offset = sign_extend32(((data[0] & 0xF0) << 4) | data[1], 11);
 742		break;
 743	default:
 744		return -EINVAL;
 745	}
 746
 747	/*
 748	 * convert raw offset to g then to m/s²
 749	 * 12 bits signed raw step 0.5mg to g: 5 / 10000
 750	 * g to m/s²: 9.806650
 751	 * result in micro (1000000)
 752	 * (offset * 5 * 9.806650 * 1000000) / 10000
 753	 */
 754	val64 = (s64)offset * 5LL * 9806650LL;
 755	/* for rounding, add + or - divisor (10000) divided by 2 */
 756	if (val64 >= 0)
 757		val64 += 10000LL / 2LL;
 758	else
 759		val64 -= 10000LL / 2LL;
 760	bias = div_s64(val64, 10000L);
 761	*val = bias / 1000000L;
 762	*val2 = bias % 1000000L;
 763
 764	return IIO_VAL_INT_PLUS_MICRO;
 765}
 766
 767static int inv_icm42600_accel_write_offset(struct inv_icm42600_state *st,
 768					   struct iio_chan_spec const *chan,
 769					   int val, int val2)
 770{
 771	struct device *dev = regmap_get_device(st->map);
 772	s64 val64;
 773	s32 min, max;
 774	unsigned int reg, regval;
 775	s16 offset;
 776	int ret;
 777
 778	if (chan->type != IIO_ACCEL)
 779		return -EINVAL;
 780
 781	switch (chan->channel2) {
 782	case IIO_MOD_X:
 783		reg = INV_ICM42600_REG_OFFSET_USER4;
 784		break;
 785	case IIO_MOD_Y:
 786		reg = INV_ICM42600_REG_OFFSET_USER6;
 787		break;
 788	case IIO_MOD_Z:
 789		reg = INV_ICM42600_REG_OFFSET_USER7;
 790		break;
 791	default:
 792		return -EINVAL;
 793	}
 794
 795	/* inv_icm42600_accel_calibbias: min - step - max in micro */
 796	min = inv_icm42600_accel_calibbias[0] * 1000000L +
 797	      inv_icm42600_accel_calibbias[1];
 798	max = inv_icm42600_accel_calibbias[4] * 1000000L +
 799	      inv_icm42600_accel_calibbias[5];
 800	val64 = (s64)val * 1000000LL + (s64)val2;
 801	if (val64 < min || val64 > max)
 802		return -EINVAL;
 803
 804	/*
 805	 * convert m/s² to g then to raw value
 806	 * m/s² to g: 1 / 9.806650
 807	 * g to raw 12 bits signed, step 0.5mg: 10000 / 5
 808	 * val in micro (1000000)
 809	 * val * 10000 / (9.806650 * 1000000 * 5)
 810	 */
 811	val64 = val64 * 10000LL;
 812	/* for rounding, add + or - divisor (9806650 * 5) divided by 2 */
 813	if (val64 >= 0)
 814		val64 += 9806650 * 5 / 2;
 815	else
 816		val64 -= 9806650 * 5 / 2;
 817	offset = div_s64(val64, 9806650 * 5);
 818
 819	/* clamp value limited to 12 bits signed */
 820	if (offset < -2048)
 821		offset = -2048;
 822	else if (offset > 2047)
 823		offset = 2047;
 824
 825	pm_runtime_get_sync(dev);
 826	mutex_lock(&st->lock);
 827
 828	switch (chan->channel2) {
 829	case IIO_MOD_X:
 830		/* OFFSET_USER4 register is shared */
 831		ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER4,
 832				  &regval);
 833		if (ret)
 834			goto out_unlock;
 835		st->buffer[0] = ((offset & 0xF00) >> 4) | (regval & 0x0F);
 836		st->buffer[1] = offset & 0xFF;
 837		break;
 838	case IIO_MOD_Y:
 839		/* OFFSET_USER7 register is shared */
 840		ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER7,
 841				  &regval);
 842		if (ret)
 843			goto out_unlock;
 844		st->buffer[0] = offset & 0xFF;
 845		st->buffer[1] = ((offset & 0xF00) >> 8) | (regval & 0xF0);
 846		break;
 847	case IIO_MOD_Z:
 848		/* OFFSET_USER7 register is shared */
 849		ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER7,
 850				  &regval);
 851		if (ret)
 852			goto out_unlock;
 853		st->buffer[0] = ((offset & 0xF00) >> 4) | (regval & 0x0F);
 854		st->buffer[1] = offset & 0xFF;
 855		break;
 856	default:
 857		ret = -EINVAL;
 858		goto out_unlock;
 859	}
 860
 861	ret = regmap_bulk_write(st->map, reg, st->buffer, 2);
 862
 863out_unlock:
 864	mutex_unlock(&st->lock);
 865	pm_runtime_put_autosuspend(dev);
 866	return ret;
 867}
 868
 869static int inv_icm42600_accel_read_raw(struct iio_dev *indio_dev,
 870				       struct iio_chan_spec const *chan,
 871				       int *val, int *val2, long mask)
 872{
 873	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
 874	s16 data;
 875	int ret;
 876
 877	switch (chan->type) {
 878	case IIO_ACCEL:
 879		break;
 880	case IIO_TEMP:
 881		return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, mask);
 882	default:
 883		return -EINVAL;
 884	}
 885
 886	switch (mask) {
 887	case IIO_CHAN_INFO_RAW:
 888		if (!iio_device_claim_direct(indio_dev))
 889			return -EBUSY;
 890		ret = inv_icm42600_accel_read_sensor(indio_dev, chan, &data);
 891		iio_device_release_direct(indio_dev);
 892		if (ret)
 893			return ret;
 894		*val = data;
 895		return IIO_VAL_INT;
 896	case IIO_CHAN_INFO_SCALE:
 897		return inv_icm42600_accel_read_scale(indio_dev, val, val2);
 898	case IIO_CHAN_INFO_SAMP_FREQ:
 899		return inv_icm42600_accel_read_odr(st, val, val2);
 900	case IIO_CHAN_INFO_CALIBBIAS:
 901		return inv_icm42600_accel_read_offset(st, chan, val, val2);
 902	default:
 903		return -EINVAL;
 904	}
 905}
 906
 907static int inv_icm42600_accel_read_avail(struct iio_dev *indio_dev,
 908					 struct iio_chan_spec const *chan,
 909					 const int **vals,
 910					 int *type, int *length, long mask)
 911{
 912	struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev);
 913
 914	if (chan->type != IIO_ACCEL)
 915		return -EINVAL;
 916
 917	switch (mask) {
 918	case IIO_CHAN_INFO_SCALE:
 919		*vals = accel_st->scales;
 920		*type = IIO_VAL_INT_PLUS_NANO;
 921		*length = accel_st->scales_len;
 922		return IIO_AVAIL_LIST;
 923	case IIO_CHAN_INFO_SAMP_FREQ:
 924		*vals = inv_icm42600_accel_odr;
 925		*type = IIO_VAL_INT_PLUS_MICRO;
 926		*length = ARRAY_SIZE(inv_icm42600_accel_odr);
 927		return IIO_AVAIL_LIST;
 928	case IIO_CHAN_INFO_CALIBBIAS:
 929		*vals = inv_icm42600_accel_calibbias;
 930		*type = IIO_VAL_INT_PLUS_MICRO;
 931		return IIO_AVAIL_RANGE;
 932	default:
 933		return -EINVAL;
 934	}
 935}
 936
 937static int inv_icm42600_accel_write_raw(struct iio_dev *indio_dev,
 938					struct iio_chan_spec const *chan,
 939					int val, int val2, long mask)
 940{
 941	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
 942	int ret;
 943
 944	if (chan->type != IIO_ACCEL)
 945		return -EINVAL;
 946
 947	switch (mask) {
 948	case IIO_CHAN_INFO_SCALE:
 949		if (!iio_device_claim_direct(indio_dev))
 950			return -EBUSY;
 951		ret = inv_icm42600_accel_write_scale(indio_dev, val, val2);
 952		iio_device_release_direct(indio_dev);
 953		return ret;
 954	case IIO_CHAN_INFO_SAMP_FREQ:
 955		return inv_icm42600_accel_write_odr(indio_dev, val, val2);
 956	case IIO_CHAN_INFO_CALIBBIAS:
 957		if (!iio_device_claim_direct(indio_dev))
 958			return -EBUSY;
 959		ret = inv_icm42600_accel_write_offset(st, chan, val, val2);
 960		iio_device_release_direct(indio_dev);
 961		return ret;
 962	default:
 963		return -EINVAL;
 964	}
 965}
 966
 967static int inv_icm42600_accel_write_raw_get_fmt(struct iio_dev *indio_dev,
 968						struct iio_chan_spec const *chan,
 969						long mask)
 970{
 971	if (chan->type != IIO_ACCEL)
 972		return -EINVAL;
 973
 974	switch (mask) {
 975	case IIO_CHAN_INFO_SCALE:
 976		return IIO_VAL_INT_PLUS_NANO;
 977	case IIO_CHAN_INFO_SAMP_FREQ:
 978		return IIO_VAL_INT_PLUS_MICRO;
 979	case IIO_CHAN_INFO_CALIBBIAS:
 980		return IIO_VAL_INT_PLUS_MICRO;
 981	default:
 982		return -EINVAL;
 983	}
 984}
 985
 986static int inv_icm42600_accel_hwfifo_set_watermark(struct iio_dev *indio_dev,
 987						   unsigned int val)
 988{
 989	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
 990
 991	guard(mutex)(&st->lock);
 992
 993	st->fifo.watermark.accel = val;
 994	return inv_icm42600_buffer_update_watermark(st);
 995}
 996
 997static int inv_icm42600_accel_hwfifo_flush(struct iio_dev *indio_dev,
 998					   unsigned int count)
 999{
1000	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
1001	int ret;
1002
1003	if (count == 0)
1004		return 0;
1005
1006	guard(mutex)(&st->lock);
1007
1008	ret = inv_icm42600_buffer_hwfifo_flush(st, count);
1009	if (ret)
1010		return ret;
1011
1012	return st->fifo.nb.accel;
1013}
1014
1015static int inv_icm42600_accel_read_event_config(struct iio_dev *indio_dev,
1016						const struct iio_chan_spec *chan,
1017						enum iio_event_type type,
1018						enum iio_event_direction dir)
1019{
1020	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
1021
1022	/* handle only WoM (roc rising) event */
1023	if (type != IIO_EV_TYPE_ROC || dir != IIO_EV_DIR_RISING)
1024		return -EINVAL;
1025
1026	guard(mutex)(&st->lock);
1027
1028	return st->apex.wom.enable ? 1 : 0;
1029}
1030
1031static int inv_icm42600_accel_write_event_config(struct iio_dev *indio_dev,
1032						 const struct iio_chan_spec *chan,
1033						 enum iio_event_type type,
1034						 enum iio_event_direction dir,
1035						 bool state)
1036{
1037	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
1038
1039	/* handle only WoM (roc rising) event */
1040	if (type != IIO_EV_TYPE_ROC || dir != IIO_EV_DIR_RISING)
1041		return -EINVAL;
1042
1043	scoped_guard(mutex, &st->lock) {
1044		if (st->apex.wom.enable == state)
1045			return 0;
1046	}
1047
1048	if (state)
1049		return inv_icm42600_accel_enable_wom(indio_dev);
1050
1051	return inv_icm42600_accel_disable_wom(indio_dev);
1052}
1053
1054static int inv_icm42600_accel_read_event_value(struct iio_dev *indio_dev,
1055					       const struct iio_chan_spec *chan,
1056					       enum iio_event_type type,
1057					       enum iio_event_direction dir,
1058					       enum iio_event_info info,
1059					       int *val, int *val2)
1060{
1061	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
1062	u32 rem;
1063
1064	/* handle only WoM (roc rising) event value */
1065	if (type != IIO_EV_TYPE_ROC || dir != IIO_EV_DIR_RISING)
1066		return -EINVAL;
1067
1068	guard(mutex)(&st->lock);
1069
1070	/* return value in micro */
1071	*val = div_u64_rem(st->apex.wom.value, MICRO, &rem);
1072	*val2 = rem;
1073	return IIO_VAL_INT_PLUS_MICRO;
1074}
1075
1076static int _inv_icm42600_accel_wom_value(struct inv_icm42600_state *st,
1077					 int val, int val2)
1078{
1079	u64 value;
1080	unsigned int accel_hz, accel_uhz;
1081	int ret;
1082
1083	guard(mutex)(&st->lock);
1084
1085	ret = inv_icm42600_accel_read_odr(st, &accel_hz, &accel_uhz);
1086	if (ret < 0)
1087		return ret;
1088
1089	value = (u64)val * MICRO + (u64)val2;
1090
1091	return inv_icm42600_accel_set_wom_threshold(st, value,
1092						    accel_hz, accel_uhz);
1093}
1094
1095static int inv_icm42600_accel_write_event_value(struct iio_dev *indio_dev,
1096						const struct iio_chan_spec *chan,
1097						enum iio_event_type type,
1098						enum iio_event_direction dir,
1099						enum iio_event_info info,
1100						int val, int val2)
1101{
1102	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
1103	struct device *dev = regmap_get_device(st->map);
1104	int ret;
1105
1106	/* handle only WoM (roc rising) event value */
1107	if (type != IIO_EV_TYPE_ROC || dir != IIO_EV_DIR_RISING)
1108		return -EINVAL;
1109
1110	if (val < 0 || val2 < 0)
1111		return -EINVAL;
1112
1113	ret = pm_runtime_resume_and_get(dev);
1114	if (ret)
1115		return ret;
1116
1117	ret = _inv_icm42600_accel_wom_value(st, val, val2);
1118
1119	pm_runtime_mark_last_busy(dev);
1120	pm_runtime_put_autosuspend(dev);
1121
1122	return ret;
1123}
1124
1125static const struct iio_info inv_icm42600_accel_info = {
1126	.read_raw = inv_icm42600_accel_read_raw,
1127	.read_avail = inv_icm42600_accel_read_avail,
1128	.write_raw = inv_icm42600_accel_write_raw,
1129	.write_raw_get_fmt = inv_icm42600_accel_write_raw_get_fmt,
1130	.debugfs_reg_access = inv_icm42600_debugfs_reg,
1131	.update_scan_mode = inv_icm42600_accel_update_scan_mode,
1132	.hwfifo_set_watermark = inv_icm42600_accel_hwfifo_set_watermark,
1133	.hwfifo_flush_to_buffer = inv_icm42600_accel_hwfifo_flush,
1134	.read_event_config = inv_icm42600_accel_read_event_config,
1135	.write_event_config = inv_icm42600_accel_write_event_config,
1136	.read_event_value = inv_icm42600_accel_read_event_value,
1137	.write_event_value = inv_icm42600_accel_write_event_value,
1138};
1139
1140struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st)
1141{
1142	struct device *dev = regmap_get_device(st->map);
1143	const char *name;
1144	struct inv_icm42600_sensor_state *accel_st;
1145	struct inv_sensors_timestamp_chip ts_chip;
1146	struct iio_dev *indio_dev;
1147	int ret;
1148
1149	name = devm_kasprintf(dev, GFP_KERNEL, "%s-accel", st->name);
1150	if (!name)
1151		return ERR_PTR(-ENOMEM);
1152
1153	indio_dev = devm_iio_device_alloc(dev, sizeof(*accel_st));
1154	if (!indio_dev)
1155		return ERR_PTR(-ENOMEM);
1156	accel_st = iio_priv(indio_dev);
1157
1158	switch (st->chip) {
1159	case INV_CHIP_ICM42686:
1160		accel_st->scales = inv_icm42686_accel_scale;
1161		accel_st->scales_len = ARRAY_SIZE(inv_icm42686_accel_scale);
1162		break;
1163	default:
1164		accel_st->scales = inv_icm42600_accel_scale;
1165		accel_st->scales_len = ARRAY_SIZE(inv_icm42600_accel_scale);
1166		break;
1167	}
1168	/* low-power by default at init */
1169	accel_st->power_mode = INV_ICM42600_SENSOR_MODE_LOW_POWER;
1170	accel_st->filter = INV_ICM42600_FILTER_AVG_16X;
1171
1172	/*
1173	 * clock period is 32kHz (31250ns)
1174	 * jitter is +/- 2% (20 per mille)
1175	 */
1176	ts_chip.clock_period = 31250;
1177	ts_chip.jitter = 20;
1178	ts_chip.init_period = inv_icm42600_odr_to_period(st->conf.accel.odr);
1179	inv_sensors_timestamp_init(&accel_st->ts, &ts_chip);
1180
1181	iio_device_set_drvdata(indio_dev, st);
1182	indio_dev->name = name;
1183	indio_dev->info = &inv_icm42600_accel_info;
1184	indio_dev->modes = INDIO_DIRECT_MODE;
1185	indio_dev->channels = inv_icm42600_accel_channels;
1186	indio_dev->num_channels = ARRAY_SIZE(inv_icm42600_accel_channels);
1187	indio_dev->available_scan_masks = inv_icm42600_accel_scan_masks;
1188
1189	ret = devm_iio_kfifo_buffer_setup(dev, indio_dev,
1190					  &inv_icm42600_buffer_ops);
1191	if (ret)
1192		return ERR_PTR(ret);
1193
1194	ret = devm_iio_device_register(dev, indio_dev);
1195	if (ret)
1196		return ERR_PTR(ret);
1197
1198	/* accel events are wakeup capable */
1199	ret = devm_device_init_wakeup(&indio_dev->dev);
1200	if (ret)
1201		return ERR_PTR(ret);
1202
1203	return indio_dev;
1204}
1205
1206int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev)
1207{
1208	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
1209	struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev);
1210	struct inv_sensors_timestamp *ts = &accel_st->ts;
1211	ssize_t i, size;
1212	unsigned int no;
1213	const void *accel, *gyro, *timestamp;
1214	const int8_t *temp;
1215	unsigned int odr;
1216	int64_t ts_val;
1217	/* buffer is copied to userspace, zeroing it to avoid any data leak */
1218	struct inv_icm42600_accel_buffer buffer = { };
1219
1220	/* parse all fifo packets */
1221	for (i = 0, no = 0; i < st->fifo.count; i += size, ++no) {
1222		size = inv_icm42600_fifo_decode_packet(&st->fifo.data[i],
1223				&accel, &gyro, &temp, &timestamp, &odr);
1224		/* quit if error or FIFO is empty */
1225		if (size <= 0)
1226			return size;
1227
1228		/* skip packet if no accel data or data is invalid */
1229		if (accel == NULL || !inv_icm42600_fifo_is_data_valid(accel))
1230			continue;
1231
1232		/* update odr */
1233		if (odr & INV_ICM42600_SENSOR_ACCEL)
1234			inv_sensors_timestamp_apply_odr(ts, st->fifo.period,
1235							st->fifo.nb.total, no);
1236
1237		memcpy(&buffer.accel, accel, sizeof(buffer.accel));
1238		/* convert 8 bits FIFO temperature in high resolution format */
1239		buffer.temp = temp ? (*temp * 64) : 0;
1240		ts_val = inv_sensors_timestamp_pop(ts);
1241		iio_push_to_buffers_with_timestamp(indio_dev, &buffer, ts_val);
1242	}
1243
1244	return 0;
1245}
~/ Read-only file preview.