drivers/iio/chemical/sen0322.c

Source file repositories/reference/linux-study-clean/drivers/iio/chemical/sen0322.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/chemical/sen0322.c
Extension
.c
Size
3589 bytes
Lines
162
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 sen0322 {
	struct regmap	*regmap;
};

static int sen0322_read_data(struct sen0322 *sen0322)
{
	u8 data[3] = { };
	int ret;

	ret = regmap_bulk_read(sen0322->regmap, SEN0322_REG_DATA, data,
			       sizeof(data));
	if (ret < 0)
		return ret;

	/*
	 * The actual value in the registers is:
	 *	val = data[0] + data[1] / 10 + data[2] / 100
	 * but it is multiplied by 100 here to avoid floating-point math
	 * and the scale is divided by 100 to compensate this.
	 */
	return data[0] * 100 + data[1] * 10 + data[2];
}

static int sen0322_read_scale(struct sen0322 *sen0322, int *num, int *den)
{
	u32 val;
	int ret;

	ret = regmap_read(sen0322->regmap, SEN0322_REG_COEFF, &val);
	if (ret < 0)
		return ret;

	if (val) {
		*num = val;
		*den = 100000;	/* Coeff is scaled by 1000 at calibration. */
	} else { /* The device is not calibrated, using the factory-defaults. */
		*num = 209;	/* Oxygen content in the atmosphere is 20.9%. */
		*den = 120000;	/* Output of the sensor at 20.9% is 120 uA. */
	}

	dev_dbg(regmap_get_device(sen0322->regmap), "scale: %d/%d\n",
		*num, *den);

	return 0;
}

static int sen0322_read_raw(struct iio_dev *iio_dev,
			    const struct iio_chan_spec *chan,
			    int *val, int *val2, long mask)
{
	struct sen0322 *sen0322 = iio_priv(iio_dev);
	int ret;

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

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		ret = sen0322_read_data(sen0322);
		if (ret < 0)
			return ret;

		*val = ret;
		return IIO_VAL_INT;

	case IIO_CHAN_INFO_SCALE:
		ret = sen0322_read_scale(sen0322, val, val2);
		if (ret < 0)
			return ret;

		return IIO_VAL_FRACTIONAL;

	default:
		return -EINVAL;
	}
}

static const struct iio_info sen0322_info = {
	.read_raw = sen0322_read_raw,
};

static const struct regmap_config sen0322_regmap_conf = {
	.reg_bits = 8,
	.val_bits = 8,
};

static const struct iio_chan_spec sen0322_channel = {
	.type = IIO_CONCENTRATION,
	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
			      BIT(IIO_CHAN_INFO_SCALE),

Annotation

Implementation Notes