drivers/iio/magnetometer/si7210.c

Source file repositories/reference/linux-study-clean/drivers/iio/magnetometer/si7210.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/magnetometer/si7210.c
Extension
.c
Size
10957 bytes
Lines
440
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 si7210_data {
	struct regmap *regmap;
	struct i2c_client *client;
	struct mutex fetch_lock; /* lock for a single measurement fetch */
	unsigned int vdd_uV;
	s8 temp_offset;
	s8 temp_gain;
	s8 scale_20_a[A_REGS_COUNT];
	s8 scale_200_a[A_REGS_COUNT];
	u8 curr_scale;
};

static const struct iio_chan_spec si7210_channels[] = {
	{
		.type = IIO_MAGN,
		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
			BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET),
	}, {
		.type = IIO_TEMP,
		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
	},
};

static int si7210_fetch_measurement(struct si7210_data *data,
				    struct iio_chan_spec const *chan,
				    u16 *buf)
{
	u8 dspsigsel = chan->type == IIO_MAGN ? 0 : 1;
	int ret;
	__be16 result;

	guard(mutex)(&data->fetch_lock);

	ret = regmap_update_bits(data->regmap, SI7210_REG_DSPSIGSEL,
				 SI7210_MASK_DSPSIGSEL, dspsigsel);
	if (ret)
		return ret;

	ret = regmap_update_bits(data->regmap, SI7210_REG_POWER_CTRL,
				 SI7210_MASK_ONEBURST | SI7210_MASK_STOP,
				 SI7210_MASK_ONEBURST & ~SI7210_MASK_STOP);
	if (ret)
		return ret;

	/*
	 * Read the contents of the
	 * registers containing the result: DSPSIGM, DSPSIGL
	 */
	ret = regmap_bulk_read(data->regmap, SI7210_REG_DSPSIGM,
			       &result, sizeof(result));
	if (ret)
		return ret;

	*buf = be16_to_cpu(result);

	return 0;
}

static int si7210_read_raw(struct iio_dev *indio_dev,
			   struct iio_chan_spec const *chan,
			   int *val, int *val2, long mask)
{
	struct si7210_data *data = iio_priv(indio_dev);
	long long temp;
	u16 dspsig;
	int ret;

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		ret = si7210_fetch_measurement(data, chan, &dspsig);
		if (ret)
			return ret;

		*val = dspsig & GENMASK(14, 0);
		return IIO_VAL_INT;
	case IIO_CHAN_INFO_SCALE:
		*val = 0;
		if (data->curr_scale == 20)
			*val2 = 12500;
		else /* data->curr_scale == 200 */
			*val2 = 125000;
		return IIO_VAL_INT_PLUS_MICRO;
	case IIO_CHAN_INFO_OFFSET:
		*val = -16384;
		return IIO_VAL_INT;
	case IIO_CHAN_INFO_PROCESSED:
		ret = si7210_fetch_measurement(data, chan, &dspsig);
		if (ret)
			return ret;

Annotation

Implementation Notes