File Index
Files and directories
Sign in
FILE

inv_icm42600_gyro.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.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
 14#include <linux/iio/buffer.h>
 15#include <linux/iio/common/inv_sensors_timestamp.h>
 16#include <linux/iio/iio.h>
 17#include <linux/iio/kfifo_buf.h>
 18
 19#include "inv_icm42600.h"
 20#include "inv_icm42600_temp.h"
 21#include "inv_icm42600_buffer.h"
 22
 23#define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info)		\
 24	{								\
 25		.type = IIO_ANGL_VEL,					\
 26		.modified = 1,						\
 27		.channel2 = _modifier,					\
 28		.info_mask_separate =					\
 29			BIT(IIO_CHAN_INFO_RAW) |			\
 30			BIT(IIO_CHAN_INFO_CALIBBIAS),			\
 31		.info_mask_shared_by_type =				\
 32			BIT(IIO_CHAN_INFO_SCALE),			\
 33		.info_mask_shared_by_type_available =			\
 34			BIT(IIO_CHAN_INFO_SCALE) |			\
 35			BIT(IIO_CHAN_INFO_CALIBBIAS),			\
 36		.info_mask_shared_by_all =				\
 37			BIT(IIO_CHAN_INFO_SAMP_FREQ),			\
 38		.info_mask_shared_by_all_available =			\
 39			BIT(IIO_CHAN_INFO_SAMP_FREQ),			\
 40		.scan_index = _index,					\
 41		.scan_type = {						\
 42			.sign = 's',					\
 43			.realbits = 16,					\
 44			.storagebits = 16,				\
 45			.endianness = IIO_BE,				\
 46		},							\
 47		.ext_info = _ext_info,					\
 48	}
 49
 50enum inv_icm42600_gyro_scan {
 51	INV_ICM42600_GYRO_SCAN_X,
 52	INV_ICM42600_GYRO_SCAN_Y,
 53	INV_ICM42600_GYRO_SCAN_Z,
 54	INV_ICM42600_GYRO_SCAN_TEMP,
 55	INV_ICM42600_GYRO_SCAN_TIMESTAMP,
 56};
 57
 58static const struct iio_chan_spec_ext_info inv_icm42600_gyro_ext_infos[] = {
 59	IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42600_get_mount_matrix),
 60	{ }
 61};
 62
 63static const struct iio_chan_spec inv_icm42600_gyro_channels[] = {
 64	INV_ICM42600_GYRO_CHAN(IIO_MOD_X, INV_ICM42600_GYRO_SCAN_X,
 65			       inv_icm42600_gyro_ext_infos),
 66	INV_ICM42600_GYRO_CHAN(IIO_MOD_Y, INV_ICM42600_GYRO_SCAN_Y,
 67			       inv_icm42600_gyro_ext_infos),
 68	INV_ICM42600_GYRO_CHAN(IIO_MOD_Z, INV_ICM42600_GYRO_SCAN_Z,
 69			       inv_icm42600_gyro_ext_infos),
 70	INV_ICM42600_TEMP_CHAN(INV_ICM42600_GYRO_SCAN_TEMP),
 71	IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42600_GYRO_SCAN_TIMESTAMP),
 72};
 73
 74/*
 75 * IIO buffer data: size must be a power of 2 and timestamp aligned
 76 * 16 bytes: 6 bytes angular velocity, 2 bytes temperature, 8 bytes timestamp
 77 */
 78struct inv_icm42600_gyro_buffer {
 79	struct inv_icm42600_fifo_sensor_data gyro;
 80	s16 temp;
 81	aligned_s64 timestamp;
 82};
 83
 84#define INV_ICM42600_SCAN_MASK_GYRO_3AXIS				\
 85	(BIT(INV_ICM42600_GYRO_SCAN_X) |				\
 86	BIT(INV_ICM42600_GYRO_SCAN_Y) |					\
 87	BIT(INV_ICM42600_GYRO_SCAN_Z))
 88
 89#define INV_ICM42600_SCAN_MASK_TEMP	BIT(INV_ICM42600_GYRO_SCAN_TEMP)
 90
 91static const unsigned long inv_icm42600_gyro_scan_masks[] = {
 92	/* 3-axis gyro + temperature */
 93	INV_ICM42600_SCAN_MASK_GYRO_3AXIS | INV_ICM42600_SCAN_MASK_TEMP,
 94	0,
 95};
 96
 97/* enable gyroscope sensor and FIFO write */
 98static int inv_icm42600_gyro_update_scan_mode(struct iio_dev *indio_dev,
 99					      const unsigned long *scan_mask)
100{
101	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
102	struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
103	unsigned int fifo_en = 0;
104	unsigned int sleep_gyro = 0;
105	unsigned int sleep_temp = 0;
106	unsigned int sleep;
107	int ret;
108
109	mutex_lock(&st->lock);
110
111	if (*scan_mask & INV_ICM42600_SCAN_MASK_TEMP) {
112		/* enable temp sensor */
113		ret = inv_icm42600_set_temp_conf(st, true, &sleep_temp);
114		if (ret)
115			goto out_unlock;
116		fifo_en |= INV_ICM42600_SENSOR_TEMP;
117	}
118
119	if (*scan_mask & INV_ICM42600_SCAN_MASK_GYRO_3AXIS) {
120		/* enable gyro sensor */
121		conf.mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE;
122		ret = inv_icm42600_set_gyro_conf(st, &conf, &sleep_gyro);
123		if (ret)
124			goto out_unlock;
125		fifo_en |= INV_ICM42600_SENSOR_GYRO;
126	}
127
128	/* update data FIFO write */
129	ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en);
130
131out_unlock:
132	mutex_unlock(&st->lock);
133	/* sleep maximum required time */
134	sleep = max(sleep_gyro, sleep_temp);
135	if (sleep)
136		msleep(sleep);
137	return ret;
138}
139
140static int inv_icm42600_gyro_read_sensor(struct inv_icm42600_state *st,
141					 struct iio_chan_spec const *chan,
142					 s16 *val)
143{
144	struct device *dev = regmap_get_device(st->map);
145	struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
146	unsigned int reg;
147	__be16 *data;
148	int ret;
149
150	if (chan->type != IIO_ANGL_VEL)
151		return -EINVAL;
152
153	switch (chan->channel2) {
154	case IIO_MOD_X:
155		reg = INV_ICM42600_REG_GYRO_DATA_X;
156		break;
157	case IIO_MOD_Y:
158		reg = INV_ICM42600_REG_GYRO_DATA_Y;
159		break;
160	case IIO_MOD_Z:
161		reg = INV_ICM42600_REG_GYRO_DATA_Z;
162		break;
163	default:
164		return -EINVAL;
165	}
166
167	pm_runtime_get_sync(dev);
168	mutex_lock(&st->lock);
169
170	/* enable gyro sensor */
171	conf.mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE;
172	ret = inv_icm42600_set_gyro_conf(st, &conf, NULL);
173	if (ret)
174		goto exit;
175
176	/* read gyro register data */
177	data = (__be16 *)&st->buffer[0];
178	ret = regmap_bulk_read(st->map, reg, data, sizeof(*data));
179	if (ret)
180		goto exit;
181
182	*val = (s16)be16_to_cpup(data);
183	if (*val == INV_ICM42600_DATA_INVALID)
184		ret = -EINVAL;
185exit:
186	mutex_unlock(&st->lock);
187	pm_runtime_put_autosuspend(dev);
188	return ret;
189}
190
191/* IIO format int + nano */
192static const int inv_icm42600_gyro_scale[] = {
193	/* +/- 2000dps => 0.001065264 rad/s */
194	[2 * INV_ICM42600_GYRO_FS_2000DPS] = 0,
195	[2 * INV_ICM42600_GYRO_FS_2000DPS + 1] = 1065264,
196	/* +/- 1000dps => 0.000532632 rad/s */
197	[2 * INV_ICM42600_GYRO_FS_1000DPS] = 0,
198	[2 * INV_ICM42600_GYRO_FS_1000DPS + 1] = 532632,
199	/* +/- 500dps => 0.000266316 rad/s */
200	[2 * INV_ICM42600_GYRO_FS_500DPS] = 0,
201	[2 * INV_ICM42600_GYRO_FS_500DPS + 1] = 266316,
202	/* +/- 250dps => 0.000133158 rad/s */
203	[2 * INV_ICM42600_GYRO_FS_250DPS] = 0,
204	[2 * INV_ICM42600_GYRO_FS_250DPS + 1] = 133158,
205	/* +/- 125dps => 0.000066579 rad/s */
206	[2 * INV_ICM42600_GYRO_FS_125DPS] = 0,
207	[2 * INV_ICM42600_GYRO_FS_125DPS + 1] = 66579,
208	/* +/- 62.5dps => 0.000033290 rad/s */
209	[2 * INV_ICM42600_GYRO_FS_62_5DPS] = 0,
210	[2 * INV_ICM42600_GYRO_FS_62_5DPS + 1] = 33290,
211	/* +/- 31.25dps => 0.000016645 rad/s */
212	[2 * INV_ICM42600_GYRO_FS_31_25DPS] = 0,
213	[2 * INV_ICM42600_GYRO_FS_31_25DPS + 1] = 16645,
214	/* +/- 15.625dps => 0.000008322 rad/s */
215	[2 * INV_ICM42600_GYRO_FS_15_625DPS] = 0,
216	[2 * INV_ICM42600_GYRO_FS_15_625DPS + 1] = 8322,
217};
218static const int inv_icm42686_gyro_scale[] = {
219	/* +/- 4000dps => 0.002130529 rad/s */
220	[2 * INV_ICM42686_GYRO_FS_4000DPS] = 0,
221	[2 * INV_ICM42686_GYRO_FS_4000DPS + 1] = 2130529,
222	/* +/- 2000dps => 0.001065264 rad/s */
223	[2 * INV_ICM42686_GYRO_FS_2000DPS] = 0,
224	[2 * INV_ICM42686_GYRO_FS_2000DPS + 1] = 1065264,
225	/* +/- 1000dps => 0.000532632 rad/s */
226	[2 * INV_ICM42686_GYRO_FS_1000DPS] = 0,
227	[2 * INV_ICM42686_GYRO_FS_1000DPS + 1] = 532632,
228	/* +/- 500dps => 0.000266316 rad/s */
229	[2 * INV_ICM42686_GYRO_FS_500DPS] = 0,
230	[2 * INV_ICM42686_GYRO_FS_500DPS + 1] = 266316,
231	/* +/- 250dps => 0.000133158 rad/s */
232	[2 * INV_ICM42686_GYRO_FS_250DPS] = 0,
233	[2 * INV_ICM42686_GYRO_FS_250DPS + 1] = 133158,
234	/* +/- 125dps => 0.000066579 rad/s */
235	[2 * INV_ICM42686_GYRO_FS_125DPS] = 0,
236	[2 * INV_ICM42686_GYRO_FS_125DPS + 1] = 66579,
237	/* +/- 62.5dps => 0.000033290 rad/s */
238	[2 * INV_ICM42686_GYRO_FS_62_5DPS] = 0,
239	[2 * INV_ICM42686_GYRO_FS_62_5DPS + 1] = 33290,
240	/* +/- 31.25dps => 0.000016645 rad/s */
241	[2 * INV_ICM42686_GYRO_FS_31_25DPS] = 0,
242	[2 * INV_ICM42686_GYRO_FS_31_25DPS + 1] = 16645,
243};
244
245static int inv_icm42600_gyro_read_scale(struct iio_dev *indio_dev,
246					int *val, int *val2)
247{
248	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
249	struct inv_icm42600_sensor_state *gyro_st = iio_priv(indio_dev);
250	unsigned int idx;
251
252	idx = st->conf.gyro.fs;
253
254	*val = gyro_st->scales[2 * idx];
255	*val2 = gyro_st->scales[2 * idx + 1];
256	return IIO_VAL_INT_PLUS_NANO;
257}
258
259static int inv_icm42600_gyro_write_scale(struct iio_dev *indio_dev,
260					 int val, int val2)
261{
262	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
263	struct inv_icm42600_sensor_state *gyro_st = iio_priv(indio_dev);
264	struct device *dev = regmap_get_device(st->map);
265	unsigned int idx;
266	struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
267	int ret;
268
269	for (idx = 0; idx < gyro_st->scales_len; idx += 2) {
270		if (val == gyro_st->scales[idx] &&
271		    val2 == gyro_st->scales[idx + 1])
272			break;
273	}
274	if (idx >= gyro_st->scales_len)
275		return -EINVAL;
276
277	conf.fs = idx / 2;
278
279	pm_runtime_get_sync(dev);
280
281	scoped_guard(mutex, &st->lock)
282		ret = inv_icm42600_set_gyro_conf(st, &conf, NULL);
283
284	pm_runtime_put_autosuspend(dev);
285
286	return ret;
287}
288
289/* IIO format int + micro */
290static const int inv_icm42600_gyro_odr[] = {
291	/* 12.5Hz */
292	12, 500000,
293	/* 25Hz */
294	25, 0,
295	/* 50Hz */
296	50, 0,
297	/* 100Hz */
298	100, 0,
299	/* 200Hz */
300	200, 0,
301	/* 1kHz */
302	1000, 0,
303	/* 2kHz */
304	2000, 0,
305	/* 4kHz */
306	4000, 0,
307};
308
309static const int inv_icm42600_gyro_odr_conv[] = {
310	INV_ICM42600_ODR_12_5HZ,
311	INV_ICM42600_ODR_25HZ,
312	INV_ICM42600_ODR_50HZ,
313	INV_ICM42600_ODR_100HZ,
314	INV_ICM42600_ODR_200HZ,
315	INV_ICM42600_ODR_1KHZ_LN,
316	INV_ICM42600_ODR_2KHZ_LN,
317	INV_ICM42600_ODR_4KHZ_LN,
318};
319
320static int inv_icm42600_gyro_read_odr(struct inv_icm42600_state *st,
321				      int *val, int *val2)
322{
323	unsigned int odr;
324	unsigned int i;
325
326	odr = st->conf.gyro.odr;
327
328	for (i = 0; i < ARRAY_SIZE(inv_icm42600_gyro_odr_conv); ++i) {
329		if (inv_icm42600_gyro_odr_conv[i] == odr)
330			break;
331	}
332	if (i >= ARRAY_SIZE(inv_icm42600_gyro_odr_conv))
333		return -EINVAL;
334
335	*val = inv_icm42600_gyro_odr[2 * i];
336	*val2 = inv_icm42600_gyro_odr[2 * i + 1];
337
338	return IIO_VAL_INT_PLUS_MICRO;
339}
340
341static int inv_icm42600_gyro_write_odr(struct iio_dev *indio_dev,
342				       int val, int val2)
343{
344	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
345	struct inv_icm42600_sensor_state *gyro_st = iio_priv(indio_dev);
346	struct inv_sensors_timestamp *ts = &gyro_st->ts;
347	struct device *dev = regmap_get_device(st->map);
348	unsigned int idx;
349	struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
350	int ret;
351
352	for (idx = 0; idx < ARRAY_SIZE(inv_icm42600_gyro_odr); idx += 2) {
353		if (val == inv_icm42600_gyro_odr[idx] &&
354		    val2 == inv_icm42600_gyro_odr[idx + 1])
355			break;
356	}
357	if (idx >= ARRAY_SIZE(inv_icm42600_gyro_odr))
358		return -EINVAL;
359
360	conf.odr = inv_icm42600_gyro_odr_conv[idx / 2];
361	if (conf.odr == st->conf.gyro.odr)
362		return 0;
363
364	pm_runtime_get_sync(dev);
365	mutex_lock(&st->lock);
366
367	ret = inv_sensors_timestamp_update_odr(ts, inv_icm42600_odr_to_period(conf.odr),
368					       iio_buffer_enabled(indio_dev));
369	if (ret)
370		goto out_unlock;
371
372	ret = inv_icm42600_set_gyro_conf(st, &conf, NULL);
373	if (ret)
374		goto out_unlock;
375	inv_icm42600_buffer_update_fifo_period(st);
376	inv_icm42600_buffer_update_watermark(st);
377
378out_unlock:
379	mutex_unlock(&st->lock);
380	pm_runtime_put_autosuspend(dev);
381
382	return ret;
383}
384
385/*
386 * Calibration bias values, IIO range format int + nano.
387 * Value is limited to +/-64dps coded on 12 bits signed. Step is 1/32 dps.
388 */
389static int inv_icm42600_gyro_calibbias[] = {
390	-1, 117010721,		/* min: -1.117010721 rad/s */
391	0, 545415,		/* step: 0.000545415 rad/s */
392	1, 116465306,		/* max: 1.116465306 rad/s */
393};
394
395static int inv_icm42600_gyro_read_offset(struct inv_icm42600_state *st,
396					 struct iio_chan_spec const *chan,
397					 int *val, int *val2)
398{
399	struct device *dev = regmap_get_device(st->map);
400	s64 val64;
401	s32 bias;
402	unsigned int reg;
403	s16 offset;
404	u8 data[2];
405	int ret;
406
407	if (chan->type != IIO_ANGL_VEL)
408		return -EINVAL;
409
410	switch (chan->channel2) {
411	case IIO_MOD_X:
412		reg = INV_ICM42600_REG_OFFSET_USER0;
413		break;
414	case IIO_MOD_Y:
415		reg = INV_ICM42600_REG_OFFSET_USER1;
416		break;
417	case IIO_MOD_Z:
418		reg = INV_ICM42600_REG_OFFSET_USER3;
419		break;
420	default:
421		return -EINVAL;
422	}
423
424	pm_runtime_get_sync(dev);
425	mutex_lock(&st->lock);
426
427	ret = regmap_bulk_read(st->map, reg, st->buffer, sizeof(data));
428	memcpy(data, st->buffer, sizeof(data));
429
430	mutex_unlock(&st->lock);
431	pm_runtime_put_autosuspend(dev);
432	if (ret)
433		return ret;
434
435	/* 12 bits signed value */
436	switch (chan->channel2) {
437	case IIO_MOD_X:
438		offset = sign_extend32(((data[1] & 0x0F) << 8) | data[0], 11);
439		break;
440	case IIO_MOD_Y:
441		offset = sign_extend32(((data[0] & 0xF0) << 4) | data[1], 11);
442		break;
443	case IIO_MOD_Z:
444		offset = sign_extend32(((data[1] & 0x0F) << 8) | data[0], 11);
445		break;
446	default:
447		return -EINVAL;
448	}
449
450	/*
451	 * convert raw offset to dps then to rad/s
452	 * 12 bits signed raw max 64 to dps: 64 / 2048
453	 * dps to rad: Pi / 180
454	 * result in nano (1000000000)
455	 * (offset * 64 * Pi * 1000000000) / (2048 * 180)
456	 */
457	val64 = (s64)offset * 64LL * 3141592653LL;
458	/* for rounding, add + or - divisor (2048 * 180) divided by 2 */
459	if (val64 >= 0)
460		val64 += 2048 * 180 / 2;
461	else
462		val64 -= 2048 * 180 / 2;
463	bias = div_s64(val64, 2048 * 180);
464	*val = bias / 1000000000L;
465	*val2 = bias % 1000000000L;
466
467	return IIO_VAL_INT_PLUS_NANO;
468}
469
470static int inv_icm42600_gyro_write_offset(struct inv_icm42600_state *st,
471					  struct iio_chan_spec const *chan,
472					  int val, int val2)
473{
474	struct device *dev = regmap_get_device(st->map);
475	s64 val64, min, max;
476	unsigned int reg, regval;
477	s16 offset;
478	int ret;
479
480	if (chan->type != IIO_ANGL_VEL)
481		return -EINVAL;
482
483	switch (chan->channel2) {
484	case IIO_MOD_X:
485		reg = INV_ICM42600_REG_OFFSET_USER0;
486		break;
487	case IIO_MOD_Y:
488		reg = INV_ICM42600_REG_OFFSET_USER1;
489		break;
490	case IIO_MOD_Z:
491		reg = INV_ICM42600_REG_OFFSET_USER3;
492		break;
493	default:
494		return -EINVAL;
495	}
496
497	/* inv_icm42600_gyro_calibbias: min - step - max in nano */
498	min = (s64)inv_icm42600_gyro_calibbias[0] * 1000000000LL +
499	      (s64)inv_icm42600_gyro_calibbias[1];
500	max = (s64)inv_icm42600_gyro_calibbias[4] * 1000000000LL +
501	      (s64)inv_icm42600_gyro_calibbias[5];
502	val64 = (s64)val * 1000000000LL + (s64)val2;
503	if (val64 < min || val64 > max)
504		return -EINVAL;
505
506	/*
507	 * convert rad/s to dps then to raw value
508	 * rad to dps: 180 / Pi
509	 * dps to raw 12 bits signed, max 64: 2048 / 64
510	 * val in nano (1000000000)
511	 * val * 180 * 2048 / (Pi * 1000000000 * 64)
512	 */
513	val64 = val64 * 180LL * 2048LL;
514	/* for rounding, add + or - divisor (3141592653 * 64) divided by 2 */
515	if (val64 >= 0)
516		val64 += 3141592653LL * 64LL / 2LL;
517	else
518		val64 -= 3141592653LL * 64LL / 2LL;
519	offset = div64_s64(val64, 3141592653LL * 64LL);
520
521	/* clamp value limited to 12 bits signed */
522	if (offset < -2048)
523		offset = -2048;
524	else if (offset > 2047)
525		offset = 2047;
526
527	pm_runtime_get_sync(dev);
528	mutex_lock(&st->lock);
529
530	switch (chan->channel2) {
531	case IIO_MOD_X:
532		/* OFFSET_USER1 register is shared */
533		ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER1,
534				  &regval);
535		if (ret)
536			goto out_unlock;
537		st->buffer[0] = offset & 0xFF;
538		st->buffer[1] = (regval & 0xF0) | ((offset & 0xF00) >> 8);
539		break;
540	case IIO_MOD_Y:
541		/* OFFSET_USER1 register is shared */
542		ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER1,
543				  &regval);
544		if (ret)
545			goto out_unlock;
546		st->buffer[0] = ((offset & 0xF00) >> 4) | (regval & 0x0F);
547		st->buffer[1] = offset & 0xFF;
548		break;
549	case IIO_MOD_Z:
550		/* OFFSET_USER4 register is shared */
551		ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER4,
552				  &regval);
553		if (ret)
554			goto out_unlock;
555		st->buffer[0] = offset & 0xFF;
556		st->buffer[1] = (regval & 0xF0) | ((offset & 0xF00) >> 8);
557		break;
558	default:
559		ret = -EINVAL;
560		goto out_unlock;
561	}
562
563	ret = regmap_bulk_write(st->map, reg, st->buffer, 2);
564
565out_unlock:
566	mutex_unlock(&st->lock);
567	pm_runtime_put_autosuspend(dev);
568	return ret;
569}
570
571static int inv_icm42600_gyro_read_raw(struct iio_dev *indio_dev,
572				      struct iio_chan_spec const *chan,
573				      int *val, int *val2, long mask)
574{
575	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
576	s16 data;
577	int ret;
578
579	switch (chan->type) {
580	case IIO_ANGL_VEL:
581		break;
582	case IIO_TEMP:
583		return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, mask);
584	default:
585		return -EINVAL;
586	}
587
588	switch (mask) {
589	case IIO_CHAN_INFO_RAW:
590		if (!iio_device_claim_direct(indio_dev))
591			return -EBUSY;
592		ret = inv_icm42600_gyro_read_sensor(st, chan, &data);
593		iio_device_release_direct(indio_dev);
594		if (ret)
595			return ret;
596		*val = data;
597		return IIO_VAL_INT;
598	case IIO_CHAN_INFO_SCALE:
599		return inv_icm42600_gyro_read_scale(indio_dev, val, val2);
600	case IIO_CHAN_INFO_SAMP_FREQ:
601		return inv_icm42600_gyro_read_odr(st, val, val2);
602	case IIO_CHAN_INFO_CALIBBIAS:
603		return inv_icm42600_gyro_read_offset(st, chan, val, val2);
604	default:
605		return -EINVAL;
606	}
607}
608
609static int inv_icm42600_gyro_read_avail(struct iio_dev *indio_dev,
610					struct iio_chan_spec const *chan,
611					const int **vals,
612					int *type, int *length, long mask)
613{
614	struct inv_icm42600_sensor_state *gyro_st = iio_priv(indio_dev);
615
616	if (chan->type != IIO_ANGL_VEL)
617		return -EINVAL;
618
619	switch (mask) {
620	case IIO_CHAN_INFO_SCALE:
621		*vals = gyro_st->scales;
622		*type = IIO_VAL_INT_PLUS_NANO;
623		*length = gyro_st->scales_len;
624		return IIO_AVAIL_LIST;
625	case IIO_CHAN_INFO_SAMP_FREQ:
626		*vals = inv_icm42600_gyro_odr;
627		*type = IIO_VAL_INT_PLUS_MICRO;
628		*length = ARRAY_SIZE(inv_icm42600_gyro_odr);
629		return IIO_AVAIL_LIST;
630	case IIO_CHAN_INFO_CALIBBIAS:
631		*vals = inv_icm42600_gyro_calibbias;
632		*type = IIO_VAL_INT_PLUS_NANO;
633		return IIO_AVAIL_RANGE;
634	default:
635		return -EINVAL;
636	}
637}
638
639static int inv_icm42600_gyro_write_raw(struct iio_dev *indio_dev,
640				       struct iio_chan_spec const *chan,
641				       int val, int val2, long mask)
642{
643	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
644	int ret;
645
646	if (chan->type != IIO_ANGL_VEL)
647		return -EINVAL;
648
649	switch (mask) {
650	case IIO_CHAN_INFO_SCALE:
651		if (!iio_device_claim_direct(indio_dev))
652			return -EBUSY;
653		ret = inv_icm42600_gyro_write_scale(indio_dev, val, val2);
654		iio_device_release_direct(indio_dev);
655		return ret;
656	case IIO_CHAN_INFO_SAMP_FREQ:
657		return inv_icm42600_gyro_write_odr(indio_dev, val, val2);
658	case IIO_CHAN_INFO_CALIBBIAS:
659		if (!iio_device_claim_direct(indio_dev))
660			return -EBUSY;
661		ret = inv_icm42600_gyro_write_offset(st, chan, val, val2);
662		iio_device_release_direct(indio_dev);
663		return ret;
664	default:
665		return -EINVAL;
666	}
667}
668
669static int inv_icm42600_gyro_write_raw_get_fmt(struct iio_dev *indio_dev,
670					       struct iio_chan_spec const *chan,
671					       long mask)
672{
673	if (chan->type != IIO_ANGL_VEL)
674		return -EINVAL;
675
676	switch (mask) {
677	case IIO_CHAN_INFO_SCALE:
678		return IIO_VAL_INT_PLUS_NANO;
679	case IIO_CHAN_INFO_SAMP_FREQ:
680		return IIO_VAL_INT_PLUS_MICRO;
681	case IIO_CHAN_INFO_CALIBBIAS:
682		return IIO_VAL_INT_PLUS_NANO;
683	default:
684		return -EINVAL;
685	}
686}
687
688static int inv_icm42600_gyro_hwfifo_set_watermark(struct iio_dev *indio_dev,
689						  unsigned int val)
690{
691	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
692
693	guard(mutex)(&st->lock);
694
695	st->fifo.watermark.gyro = val;
696	return inv_icm42600_buffer_update_watermark(st);
697}
698
699static int inv_icm42600_gyro_hwfifo_flush(struct iio_dev *indio_dev,
700					  unsigned int count)
701{
702	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
703	int ret;
704
705	if (count == 0)
706		return 0;
707
708	guard(mutex)(&st->lock);
709
710	ret = inv_icm42600_buffer_hwfifo_flush(st, count);
711	if (ret)
712		return ret;
713
714	return st->fifo.nb.gyro;
715}
716
717static const struct iio_info inv_icm42600_gyro_info = {
718	.read_raw = inv_icm42600_gyro_read_raw,
719	.read_avail = inv_icm42600_gyro_read_avail,
720	.write_raw = inv_icm42600_gyro_write_raw,
721	.write_raw_get_fmt = inv_icm42600_gyro_write_raw_get_fmt,
722	.debugfs_reg_access = inv_icm42600_debugfs_reg,
723	.update_scan_mode = inv_icm42600_gyro_update_scan_mode,
724	.hwfifo_set_watermark = inv_icm42600_gyro_hwfifo_set_watermark,
725	.hwfifo_flush_to_buffer = inv_icm42600_gyro_hwfifo_flush,
726};
727
728struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st)
729{
730	struct device *dev = regmap_get_device(st->map);
731	const char *name;
732	struct inv_icm42600_sensor_state *gyro_st;
733	struct inv_sensors_timestamp_chip ts_chip;
734	struct iio_dev *indio_dev;
735	int ret;
736
737	name = devm_kasprintf(dev, GFP_KERNEL, "%s-gyro", st->name);
738	if (!name)
739		return ERR_PTR(-ENOMEM);
740
741	indio_dev = devm_iio_device_alloc(dev, sizeof(*gyro_st));
742	if (!indio_dev)
743		return ERR_PTR(-ENOMEM);
744	gyro_st = iio_priv(indio_dev);
745
746	switch (st->chip) {
747	case INV_CHIP_ICM42686:
748		gyro_st->scales = inv_icm42686_gyro_scale;
749		gyro_st->scales_len = ARRAY_SIZE(inv_icm42686_gyro_scale);
750		break;
751	default:
752		gyro_st->scales = inv_icm42600_gyro_scale;
753		gyro_st->scales_len = ARRAY_SIZE(inv_icm42600_gyro_scale);
754		break;
755	}
756
757	/*
758	 * clock period is 32kHz (31250ns)
759	 * jitter is +/- 2% (20 per mille)
760	 */
761	ts_chip.clock_period = 31250;
762	ts_chip.jitter = 20;
763	ts_chip.init_period = inv_icm42600_odr_to_period(st->conf.accel.odr);
764	inv_sensors_timestamp_init(&gyro_st->ts, &ts_chip);
765
766	iio_device_set_drvdata(indio_dev, st);
767	indio_dev->name = name;
768	indio_dev->info = &inv_icm42600_gyro_info;
769	indio_dev->modes = INDIO_DIRECT_MODE;
770	indio_dev->channels = inv_icm42600_gyro_channels;
771	indio_dev->num_channels = ARRAY_SIZE(inv_icm42600_gyro_channels);
772	indio_dev->available_scan_masks = inv_icm42600_gyro_scan_masks;
773	indio_dev->setup_ops = &inv_icm42600_buffer_ops;
774
775	ret = devm_iio_kfifo_buffer_setup(dev, indio_dev,
776					  &inv_icm42600_buffer_ops);
777	if (ret)
778		return ERR_PTR(ret);
779
780	ret = devm_iio_device_register(dev, indio_dev);
781	if (ret)
782		return ERR_PTR(ret);
783
784	return indio_dev;
785}
786
787int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev)
788{
789	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
790	struct inv_icm42600_sensor_state *gyro_st = iio_priv(indio_dev);
791	struct inv_sensors_timestamp *ts = &gyro_st->ts;
792	ssize_t i, size;
793	unsigned int no;
794	const void *accel, *gyro, *timestamp;
795	const s8 *temp;
796	unsigned int odr;
797	s64 ts_val;
798	/* buffer is copied to userspace, zeroing it to avoid any data leak */
799	struct inv_icm42600_gyro_buffer buffer = { };
800
801	/* parse all fifo packets */
802	for (i = 0, no = 0; i < st->fifo.count; i += size, ++no) {
803		size = inv_icm42600_fifo_decode_packet(&st->fifo.data[i],
804				&accel, &gyro, &temp, &timestamp, &odr);
805		/* quit if error or FIFO is empty */
806		if (size <= 0)
807			return size;
808
809		/* skip packet if no gyro data or data is invalid */
810		if (gyro == NULL || !inv_icm42600_fifo_is_data_valid(gyro))
811			continue;
812
813		/* update odr */
814		if (odr & INV_ICM42600_SENSOR_GYRO)
815			inv_sensors_timestamp_apply_odr(ts, st->fifo.period,
816							st->fifo.nb.total, no);
817
818		memcpy(&buffer.gyro, gyro, sizeof(buffer.gyro));
819		/* convert 8 bits FIFO temperature in high resolution format */
820		buffer.temp = temp ? (*temp * 64) : 0;
821		ts_val = inv_sensors_timestamp_pop(ts);
822		iio_push_to_buffers_with_timestamp(indio_dev, &buffer, ts_val);
823	}
824
825	return 0;
826}
~/ Read-only file preview.