drivers/iio/imu/inv_icm45600/inv_icm45600_accel.c

Source file repositories/reference/linux-study-clean/drivers/iio/imu/inv_icm45600/inv_icm45600_accel.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/imu/inv_icm45600/inv_icm45600_accel.c
Extension
.c
Size
20981 bytes
Lines
783
Domain
Driver Families
Bucket
drivers/iio
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct inv_icm45600_accel_buffer {
	struct inv_icm45600_fifo_sensor_data accel;
	s16 temp;
	aligned_s64 timestamp;
};

static const unsigned long inv_icm45600_accel_scan_masks[] = {
	/* 3-axis accel + temperature */
	BIT(INV_ICM45600_ACCEL_SCAN_X) |
	BIT(INV_ICM45600_ACCEL_SCAN_Y) |
	BIT(INV_ICM45600_ACCEL_SCAN_Z) |
	BIT(INV_ICM45600_ACCEL_SCAN_TEMP),
	0
};

/* enable accelerometer sensor and FIFO write */
static int inv_icm45600_accel_update_scan_mode(struct iio_dev *indio_dev,
					       const unsigned long *scan_mask)
{
	struct inv_icm45600_state *st = iio_device_get_drvdata(indio_dev);
	struct inv_icm45600_sensor_state *accel_st = iio_priv(indio_dev);
	struct inv_icm45600_sensor_conf conf = INV_ICM45600_SENSOR_CONF_KEEP_VALUES;
	unsigned int fifo_en = 0;
	unsigned int sleep = 0;
	int ret;

	scoped_guard(mutex, &st->lock) {
		if (*scan_mask & BIT(INV_ICM45600_ACCEL_SCAN_TEMP))
			fifo_en |= INV_ICM45600_SENSOR_TEMP;

		if (*scan_mask & (BIT(INV_ICM45600_ACCEL_SCAN_X) |
				 BIT(INV_ICM45600_ACCEL_SCAN_Y) |
				 BIT(INV_ICM45600_ACCEL_SCAN_Z))) {
			/* enable accel sensor */
			conf.mode = accel_st->power_mode;
			ret = inv_icm45600_set_accel_conf(st, &conf, &sleep);
			if (ret)
				return ret;
			fifo_en |= INV_ICM45600_SENSOR_ACCEL;
		}

		/* Update data FIFO write. */
		ret = inv_icm45600_buffer_set_fifo_en(st, fifo_en | st->fifo.en);
	}

	/* Sleep required time. */
	if (sleep)
		msleep(sleep);

	return ret;
}

static int _inv_icm45600_accel_read_sensor(struct inv_icm45600_state *st,
					   struct inv_icm45600_sensor_state *accel_st,
					   unsigned int reg, int *val)
{
	struct inv_icm45600_sensor_conf conf = INV_ICM45600_SENSOR_CONF_KEEP_VALUES;
	int ret;

	/* enable accel sensor */
	conf.mode = accel_st->power_mode;
	ret = inv_icm45600_set_accel_conf(st, &conf, NULL);
	if (ret)
		return ret;

	/* read accel register data */
	ret = regmap_bulk_read(st->map, reg, &st->buffer.u16, sizeof(st->buffer.u16));
	if (ret)
		return ret;

	*val = sign_extend32(le16_to_cpup(&st->buffer.u16), 15);
	if (*val == INV_ICM45600_DATA_INVALID)
		return -ENODATA;

	return 0;
}

static int inv_icm45600_accel_read_sensor(struct iio_dev *indio_dev,
					  struct iio_chan_spec const *chan,
					  int *val)
{
	struct inv_icm45600_state *st = iio_device_get_drvdata(indio_dev);
	struct inv_icm45600_sensor_state *accel_st = iio_priv(indio_dev);
	struct device *dev = regmap_get_device(st->map);
	unsigned int reg;
	int ret;

	if (chan->type != IIO_ACCEL)
		return -EINVAL;

Annotation

Implementation Notes