brintos

brintos / linux-shallow public Read only

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